fix: modernize nullresolve runtime
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
name: Docker (tags)
|
name: Docker (non-tag pushes)
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
@@ -6,44 +6,12 @@ on:
|
|||||||
- '**'
|
- '**'
|
||||||
|
|
||||||
env:
|
env:
|
||||||
IMAGE: code.foss.global/hosttoday/ht-docker-node:npmci
|
IMAGE: code.foss.global/host.today/ht-docker-node:szci
|
||||||
NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@/${{gitea.repository}}.git
|
NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@gitea.lossless.digital/${{gitea.repository}}.git
|
||||||
NPMCI_TOKEN_NPM: ${{secrets.NPMCI_TOKEN_NPM}}
|
|
||||||
NPMCI_TOKEN_NPM2: ${{secrets.NPMCI_TOKEN_NPM2}}
|
|
||||||
NPMCI_GIT_GITHUBTOKEN: ${{secrets.NPMCI_GIT_GITHUBTOKEN}}
|
|
||||||
NPMCI_LOGIN_DOCKER_GITEA: ${{ github.server_url }}|${{ gitea.repository_owner }}|${{ secrets.GITEA_TOKEN }}
|
|
||||||
NPMCI_LOGIN_DOCKER_DOCKERREGISTRY: ${{ secrets.NPMCI_LOGIN_DOCKER_DOCKERREGISTRY }}
|
NPMCI_LOGIN_DOCKER_DOCKERREGISTRY: ${{ secrets.NPMCI_LOGIN_DOCKER_DOCKERREGISTRY }}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
security:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
container:
|
|
||||||
image: ${{ env.IMAGE }}
|
|
||||||
continue-on-error: true
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Install pnpm and npmci
|
|
||||||
run: |
|
|
||||||
pnpm install -g pnpm
|
|
||||||
pnpm install -g @ship.zone/npmci
|
|
||||||
npmci npm prepare
|
|
||||||
|
|
||||||
- name: Audit production dependencies
|
|
||||||
run: |
|
|
||||||
npmci command npm config set registry https://registry.npmjs.org
|
|
||||||
npmci command pnpm audit --audit-level=high --prod
|
|
||||||
continue-on-error: true
|
|
||||||
|
|
||||||
- name: Audit development dependencies
|
|
||||||
run: |
|
|
||||||
npmci command npm config set registry https://registry.npmjs.org
|
|
||||||
npmci command pnpm audit --audit-level=high --dev
|
|
||||||
continue-on-error: true
|
|
||||||
|
|
||||||
test:
|
test:
|
||||||
needs: security
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
image: ${{ env.IMAGE }}
|
image: ${{ env.IMAGE }}
|
||||||
@@ -54,18 +22,14 @@ jobs:
|
|||||||
- name: Prepare
|
- name: Prepare
|
||||||
run: |
|
run: |
|
||||||
pnpm install -g pnpm
|
pnpm install -g pnpm
|
||||||
pnpm install -g @ship.zone/npmci
|
pnpm install -g @git.zone/tsdocker@latest
|
||||||
npmci npm prepare
|
pnpm install
|
||||||
|
|
||||||
- name: Test stable
|
- name: Test
|
||||||
run: |
|
run: pnpm test
|
||||||
npmci node install stable
|
|
||||||
npmci npm install
|
|
||||||
npmci npm test
|
|
||||||
|
|
||||||
- name: Test build
|
- name: Build image
|
||||||
run: |
|
run: tsdocker build
|
||||||
npmci npm prepare
|
|
||||||
npmci node install stable
|
- name: Test image
|
||||||
npmci npm install
|
run: tsdocker test
|
||||||
npmci command npm run build
|
|
||||||
|
|||||||
@@ -6,75 +6,15 @@ on:
|
|||||||
- '*'
|
- '*'
|
||||||
|
|
||||||
env:
|
env:
|
||||||
IMAGE: code.foss.global/hosttoday/ht-docker-node:npmci
|
IMAGE: code.foss.global/host.today/ht-docker-node:szci
|
||||||
NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@/${{gitea.repository}}.git
|
NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@gitea.lossless.digital/${{gitea.repository}}.git
|
||||||
NPMCI_TOKEN_NPM: ${{secrets.NPMCI_TOKEN_NPM}}
|
|
||||||
NPMCI_TOKEN_NPM2: ${{secrets.NPMCI_TOKEN_NPM2}}
|
|
||||||
NPMCI_GIT_GITHUBTOKEN: ${{secrets.NPMCI_GIT_GITHUBTOKEN}}
|
|
||||||
NPMCI_LOGIN_DOCKER_GITEA: ${{ github.server_url }}|${{ gitea.repository_owner }}|${{ secrets.GITEA_TOKEN }}
|
|
||||||
NPMCI_LOGIN_DOCKER_DOCKERREGISTRY: ${{ secrets.NPMCI_LOGIN_DOCKER_DOCKERREGISTRY }}
|
NPMCI_LOGIN_DOCKER_DOCKERREGISTRY: ${{ secrets.NPMCI_LOGIN_DOCKER_DOCKERREGISTRY }}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
security:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
container:
|
|
||||||
image: ${{ env.IMAGE }}
|
|
||||||
continue-on-error: true
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Prepare
|
|
||||||
run: |
|
|
||||||
pnpm install -g pnpm
|
|
||||||
pnpm install -g @ship.zone/npmci
|
|
||||||
npmci npm prepare
|
|
||||||
|
|
||||||
- name: Audit production dependencies
|
|
||||||
run: |
|
|
||||||
npmci command npm config set registry https://registry.npmjs.org
|
|
||||||
npmci command pnpm audit --audit-level=high --prod
|
|
||||||
continue-on-error: true
|
|
||||||
|
|
||||||
- name: Audit development dependencies
|
|
||||||
run: |
|
|
||||||
npmci command npm config set registry https://registry.npmjs.org
|
|
||||||
npmci command pnpm audit --audit-level=high --dev
|
|
||||||
continue-on-error: true
|
|
||||||
|
|
||||||
test:
|
|
||||||
needs: security
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
container:
|
|
||||||
image: ${{ env.IMAGE }}
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Prepare
|
|
||||||
run: |
|
|
||||||
pnpm install -g pnpm
|
|
||||||
pnpm install -g @ship.zone/npmci
|
|
||||||
npmci npm prepare
|
|
||||||
|
|
||||||
- name: Test stable
|
|
||||||
run: |
|
|
||||||
npmci node install stable
|
|
||||||
npmci npm install
|
|
||||||
npmci npm test
|
|
||||||
|
|
||||||
- name: Test build
|
|
||||||
run: |
|
|
||||||
npmci node install stable
|
|
||||||
npmci npm install
|
|
||||||
npmci command npm run build
|
|
||||||
|
|
||||||
release:
|
release:
|
||||||
needs: test
|
|
||||||
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
image: code.foss.global/hosttoday/ht-docker-dbase:npmci
|
image: code.foss.global/host.today/ht-docker-dbase:szci
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
@@ -82,25 +22,20 @@ jobs:
|
|||||||
- name: Prepare
|
- name: Prepare
|
||||||
run: |
|
run: |
|
||||||
pnpm install -g pnpm
|
pnpm install -g pnpm
|
||||||
pnpm install -g @ship.zone/npmci
|
pnpm install -g @git.zone/tsdocker@latest
|
||||||
|
pnpm install
|
||||||
|
|
||||||
- name: Release
|
- name: Login to registries
|
||||||
run: |
|
run: tsdocker login
|
||||||
npmci docker login
|
|
||||||
npmci docker build
|
|
||||||
npmci docker test
|
|
||||||
# npmci docker push
|
|
||||||
npmci docker push
|
|
||||||
|
|
||||||
metadata:
|
- name: List images
|
||||||
needs: test
|
run: tsdocker list
|
||||||
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
container:
|
|
||||||
image: ${{ env.IMAGE }}
|
|
||||||
|
|
||||||
steps:
|
- name: Build images
|
||||||
- uses: actions/checkout@v3
|
run: tsdocker build
|
||||||
|
|
||||||
- name: Trigger
|
- name: Test images
|
||||||
run: npmci trigger
|
run: tsdocker test
|
||||||
|
|
||||||
|
- name: Push to code.foss.global
|
||||||
|
run: tsdocker push code.foss.global
|
||||||
|
|||||||
@@ -1,23 +1,20 @@
|
|||||||
{
|
{
|
||||||
"npmci": {
|
"@git.zone/tsdocker": {
|
||||||
"npmGlobalTools": [],
|
"registries": ["code.foss.global"],
|
||||||
"dockerRegistryRepoMap": {
|
"registryRepoMap": {
|
||||||
"registry.gitlab.com": "losslessone/services/servezone/nullresolve"
|
"code.foss.global": "serve.zone/nullresolve"
|
||||||
},
|
},
|
||||||
"dockerBuildargEnvMap": {
|
"platforms": ["linux/amd64", "linux/arm64"]
|
||||||
"NPMCI_TOKEN_NPM2": "NPMCI_TOKEN_NPM2"
|
|
||||||
},
|
|
||||||
"npmRegistryUrl": "verdaccio.lossless.one"
|
|
||||||
},
|
},
|
||||||
"gitzone": {
|
"@git.zone/cli": {
|
||||||
"projectType": "service",
|
"projectType": "service",
|
||||||
"module": {
|
"module": {
|
||||||
"githost": "gitlab.com",
|
"githost": "code.foss.global",
|
||||||
"gitscope": "losslessone/services/servezone",
|
"gitscope": "serve.zone",
|
||||||
"gitrepo": "nullresolve",
|
"gitrepo": "nullresolve",
|
||||||
"description": "The nullresolve project is a private service designed to handle requests that would otherwise remain unserved, providing appropriate feedback mechanisms within the servzone architecture.",
|
"description": "The nullresolve project is a private service designed to handle requests that would otherwise remain unserved, providing appropriate feedback mechanisms within the servzone architecture.",
|
||||||
"npmPackagename": "@losslessone_private/nullresolve",
|
"npmPackagename": "@losslessone_private/nullresolve",
|
||||||
"license": "MIT",
|
"license": "UNLICENSED",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"nullresolve",
|
"nullresolve",
|
||||||
"service",
|
"service",
|
||||||
+20
-33
@@ -1,46 +1,33 @@
|
|||||||
# gitzone dockerfile_service
|
# gitzone dockerfile_service
|
||||||
## STAGE 1 // BUILD
|
## STAGE 1 // BUILD
|
||||||
FROM code.foss.global/host.today/ht-docker-node:npmci as node1
|
FROM code.foss.global/host.today/ht-docker-node:lts AS build
|
||||||
COPY ./ /app
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
ARG NPMCI_TOKEN_NPM2
|
|
||||||
ENV NPMCI_TOKEN_NPM2 $NPMCI_TOKEN_NPM2
|
COPY package.json pnpm-lock.yaml ./
|
||||||
RUN npmci npm prepare
|
|
||||||
RUN pnpm config set store-dir .pnpm-store
|
RUN pnpm config set store-dir .pnpm-store
|
||||||
RUN rm -rf node_modules && pnpm install
|
RUN pnpm install --frozen-lockfile
|
||||||
|
|
||||||
|
COPY . ./
|
||||||
RUN pnpm run build
|
RUN pnpm run build
|
||||||
|
|
||||||
# gitzone dockerfile_service
|
|
||||||
## STAGE 2 // install production
|
|
||||||
FROM code.foss.global/host.today/ht-docker-node:npmci as node2
|
|
||||||
WORKDIR /app
|
|
||||||
COPY --from=node1 /app /app
|
|
||||||
RUN rm -rf .pnpm-store
|
RUN rm -rf .pnpm-store
|
||||||
ARG NPMCI_TOKEN_NPM2
|
RUN pnpm prune --prod
|
||||||
ENV NPMCI_TOKEN_NPM2 $NPMCI_TOKEN_NPM2
|
|
||||||
RUN npmci npm prepare
|
|
||||||
RUN pnpm config set store-dir .pnpm-store
|
|
||||||
RUN rm -rf node_modules/ && pnpm install --prod
|
|
||||||
|
|
||||||
|
## STAGE 2 // PRODUCTION
|
||||||
|
FROM code.foss.global/host.today/ht-docker-node:lts AS production
|
||||||
|
|
||||||
## STAGE 3 // rebuild dependencies for alpine
|
|
||||||
FROM code.foss.global/host.today/ht-docker-node:alpinenpmci as node3
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY --from=node2 /app /app
|
|
||||||
ARG NPMCI_TOKEN_NPM2
|
|
||||||
ENV NPMCI_TOKEN_NPM2 $NPMCI_TOKEN_NPM2
|
|
||||||
RUN npmci npm prepare
|
|
||||||
RUN pnpm config set store-dir .pnpm-store
|
|
||||||
RUN pnpm rebuild -r
|
|
||||||
|
|
||||||
## STAGE 4 // the final production image with all dependencies in place
|
ENV NODE_ENV=production
|
||||||
FROM code.foss.global/host.today/ht-docker-node:alpine as node4
|
|
||||||
WORKDIR /app
|
|
||||||
COPY --from=node3 /app /app
|
|
||||||
|
|
||||||
### Healthchecks
|
COPY --from=build /app/package.json ./package.json
|
||||||
RUN pnpm install -g @servezone/healthy
|
COPY --from=build /app/node_modules ./node_modules
|
||||||
HEALTHCHECK --interval=30s --timeout=30s --start-period=30s --retries=3 CMD [ "healthy" ]
|
COPY --from=build /app/cli.js ./cli.js
|
||||||
|
COPY --from=build /app/dist_ts ./dist_ts
|
||||||
|
|
||||||
|
LABEL org.opencontainers.image.title="nullresolve" \
|
||||||
|
org.opencontainers.image.description="serve.zone fallback response service" \
|
||||||
|
org.opencontainers.image.source="https://code.foss.global/serve.zone/nullresolve"
|
||||||
|
|
||||||
EXPOSE 80
|
EXPOSE 80
|
||||||
CMD ["npm", "start"]
|
CMD ["node", "cli.js"]
|
||||||
|
|||||||
+16
-15
@@ -10,21 +10,22 @@
|
|||||||
"start": "(node cli.js)",
|
"start": "(node cli.js)",
|
||||||
"startTs": "(node cli.ts.js)",
|
"startTs": "(node cli.ts.js)",
|
||||||
"build": "(tsbuild --web --allowimplicitany)",
|
"build": "(tsbuild --web --allowimplicitany)",
|
||||||
"watch": "(tswatch service)"
|
"watch": "(tswatch service)",
|
||||||
|
"build:docker": "tsdocker build --verbose",
|
||||||
|
"release:docker": "tsdocker push --verbose"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@git.zone/tsbuild": "^2.1.63",
|
"@git.zone/tsbuild": "^4.4.0",
|
||||||
"@git.zone/tstest": "^1.0.71",
|
"@git.zone/tsdocker": "^2.2.4",
|
||||||
"@git.zone/tswatch": "^2.0.37",
|
"@git.zone/tsrun": "^2.0.2",
|
||||||
"@push.rocks/tapbundle": "^5.0.3",
|
"@git.zone/tstest": "^3.6.3",
|
||||||
"@types/node": "^22.10.2"
|
"@git.zone/tswatch": "^3.3.2",
|
||||||
|
"@types/node": "^25.6.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@api.global/typedserver": "^3.0.53",
|
"@api.global/typedserver": "^8.4.6",
|
||||||
"@git.zone/tsrun": "^1.2.37",
|
"@push.rocks/projectinfo": "^5.1.0",
|
||||||
"@push.rocks/projectinfo": "^5.0.1",
|
"@push.rocks/smartpath": "^6.0.0",
|
||||||
"@push.rocks/smartlog": "^3.0.7",
|
|
||||||
"@push.rocks/smartpath": "^5.0.5",
|
|
||||||
"@push.rocks/smartstatus": "^1.1.1"
|
"@push.rocks/smartstatus": "^1.1.1"
|
||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
@@ -37,7 +38,7 @@
|
|||||||
"dist_ts_web/**/*",
|
"dist_ts_web/**/*",
|
||||||
"assets/**/*",
|
"assets/**/*",
|
||||||
"cli.js",
|
"cli.js",
|
||||||
"npmextra.json",
|
".smartconfig.json",
|
||||||
"readme.md"
|
"readme.md"
|
||||||
],
|
],
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
@@ -45,12 +46,12 @@
|
|||||||
],
|
],
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://gitlab.com/losslessone/services/servezone/nullresolve.git"
|
"url": "git+https://code.foss.global/serve.zone/nullresolve.git"
|
||||||
},
|
},
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://gitlab.com/losslessone/services/servezone/nullresolve/issues"
|
"url": "https://code.foss.global/serve.zone/nullresolve/issues"
|
||||||
},
|
},
|
||||||
"homepage": "https://gitlab.com/losslessone/services/servezone/nullresolve#readme",
|
"homepage": "https://code.foss.global/serve.zone/nullresolve#readme",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"nullresolve",
|
"nullresolve",
|
||||||
"service",
|
"service",
|
||||||
|
|||||||
Generated
+4168
-4209
File diff suppressed because it is too large
Load Diff
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
import { tap, expect } from '@push.rocks/tapbundle';
|
import { tap, expect } from '@git.zone/tstest/tapbundle';
|
||||||
|
|
||||||
import * as nullresolve from '../ts/index.js';
|
import * as nullresolve from '../ts/index.js';
|
||||||
|
|
||||||
@@ -11,4 +11,4 @@ tap.test('should create, start and stop an instance of nullresolve', async () =>
|
|||||||
await nullresolveInstance.stop();
|
await nullresolveInstance.stop();
|
||||||
});
|
});
|
||||||
|
|
||||||
tap.start();
|
export default tap.start();
|
||||||
|
|||||||
Executable
+28
@@ -0,0 +1,28 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
node --input-type=module <<'NODE'
|
||||||
|
import fs from 'node:fs';
|
||||||
|
|
||||||
|
const readJson = (path) => JSON.parse(fs.readFileSync(path, 'utf8'));
|
||||||
|
|
||||||
|
const checks = {
|
||||||
|
packageVersion: readJson('/app/package.json').version,
|
||||||
|
typedserverVersion: readJson('/app/node_modules/@api.global/typedserver/package.json').version,
|
||||||
|
hasCli: fs.existsSync('/app/cli.js'),
|
||||||
|
};
|
||||||
|
|
||||||
|
await import('/app/dist_ts/index.js');
|
||||||
|
|
||||||
|
if (checks.packageVersion !== '1.0.31') {
|
||||||
|
throw new Error(`Unexpected nullresolve package version ${checks.packageVersion}`);
|
||||||
|
}
|
||||||
|
if (checks.typedserverVersion !== '8.4.6') {
|
||||||
|
throw new Error(`Unexpected typedserver version ${checks.typedserverVersion}`);
|
||||||
|
}
|
||||||
|
if (!checks.hasCli) {
|
||||||
|
throw new Error('Missing cli.js');
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(JSON.stringify(checks));
|
||||||
|
NODE
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
/**
|
|
||||||
* autocreated commitinfo by @push.rocks/commitinfo
|
|
||||||
*/
|
|
||||||
export const commitinfo = {
|
|
||||||
name: '@losslessone_private/nullresolve',
|
|
||||||
version: '1.0.31',
|
|
||||||
description: 'The nullresolve project is a private service designed to handle requests that would otherwise remain unserved, providing appropriate feedback mechanisms within the servzone architecture.'
|
|
||||||
}
|
|
||||||
+1
-2
@@ -1,8 +1,7 @@
|
|||||||
import './nullresolve.logging.js';
|
|
||||||
import { NullResolve } from './nullresolve.classes.nullresolve.js';
|
import { NullResolve } from './nullresolve.classes.nullresolve.js';
|
||||||
export { NullResolve };
|
export { NullResolve };
|
||||||
|
|
||||||
let mainNullResolve: NullResolve;
|
let mainNullResolve: NullResolve | null;
|
||||||
|
|
||||||
export const runCli = async () => {
|
export const runCli = async () => {
|
||||||
mainNullResolve = new NullResolve();
|
mainNullResolve = new NullResolve();
|
||||||
|
|||||||
@@ -1,147 +1,162 @@
|
|||||||
import * as plugins from './nullresolve.plugins.js';
|
import * as plugins from './nullresolve.plugins.js';
|
||||||
import { projectinfo } from './nullresolve.projectinfo.js';
|
import * as paths from './nullresolve.paths.js';
|
||||||
import { configObject } from './nullresolve.config.js';
|
import { configObject } from './nullresolve.config.js';
|
||||||
|
import type { IHtmlInfoOptions } from '@api.global/typedserver/infohtml';
|
||||||
|
|
||||||
|
export interface INullResolveOptions {
|
||||||
|
port?: number;
|
||||||
|
serviceDomain?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
type TResolvedNullResolveOptions = INullResolveOptions & {
|
||||||
|
serviceDomain: string;
|
||||||
|
};
|
||||||
|
|
||||||
export class NullResolve {
|
export class NullResolve {
|
||||||
public serviceServer: plugins.typedserver.utilityservers.UtilityServiceServer;
|
public serviceServer: plugins.typedserver.utilityservers.UtilityServiceServer | null = null;
|
||||||
|
private options: TResolvedNullResolveOptions;
|
||||||
|
|
||||||
constructor() {
|
constructor(optionsArg: INullResolveOptions = {}) {
|
||||||
this.serviceServer = new plugins.typedserver.utilityservers.UtilityServiceServer({
|
this.options = {
|
||||||
serviceDomain: 'nullresolve.lossless.one',
|
serviceDomain: 'nullresolve.lossless.one',
|
||||||
serviceName: 'nullresolve',
|
...optionsArg,
|
||||||
serviceVersion: projectinfo.npm.version,
|
};
|
||||||
addCustomRoutes: async (serverArg) => {
|
}
|
||||||
serverArg.addRoute(
|
|
||||||
'/status/:code',
|
|
||||||
new plugins.typedserver.servertools.Handler('GET', async (req, res) => {
|
|
||||||
let infoHtmlOptions: plugins.typedserverInfoHtml.IHtmlInfoOptions;
|
|
||||||
|
|
||||||
switch (req.params.code) {
|
private async createInfoHtmlResponse(
|
||||||
case 'ipblock':
|
infoHtmlOptionsArg: IHtmlInfoOptions,
|
||||||
infoHtmlOptions = {
|
) {
|
||||||
title: 'Lossless Network: Blocked IP',
|
const { InfoHtml } = await import('@api.global/typedserver/infohtml');
|
||||||
heading: 'Blocked IP',
|
const infoHtmlInstance = await InfoHtml.fromOptions(infoHtmlOptionsArg);
|
||||||
text: 'Your IP (::CLIENT_IP::) is not allowed to access this ressource.',
|
return new Response(infoHtmlInstance.htmlString, {
|
||||||
sentryDsn: configObject.sentryDsn,
|
status: 200,
|
||||||
sentryMessage: 'ipblock',
|
headers: {
|
||||||
redirectTo: 'https://lossless.com',
|
'content-type': 'text/html; charset=utf-8',
|
||||||
};
|
|
||||||
break;
|
|
||||||
case 'firewall':
|
|
||||||
infoHtmlOptions = {
|
|
||||||
title: 'Lossless Network: Firewall',
|
|
||||||
heading: 'Firewall',
|
|
||||||
text: 'Your request has been blocked by our firewall since it showed possibly harmful behaviour.',
|
|
||||||
sentryDsn: configObject.sentryDsn,
|
|
||||||
sentryMessage: 'firewall',
|
|
||||||
redirectTo: 'https://lossless.com',
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
case '500class':
|
|
||||||
infoHtmlOptions = {
|
|
||||||
title: 'Lossless Network: 5xx',
|
|
||||||
heading: '5xx',
|
|
||||||
text: '::CLOUDFLARE_ERROR_500S_BOX::',
|
|
||||||
sentryDsn: configObject.sentryDsn,
|
|
||||||
sentryMessage: '5xx error',
|
|
||||||
redirectTo: 'https://lossless.com',
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
case '1000class':
|
|
||||||
infoHtmlOptions = {
|
|
||||||
title: 'Lossless Network: DNS Resolution failed',
|
|
||||||
heading: '1xxx',
|
|
||||||
text: '::CLOUDFLARE_ERROR_1000S_BOX::',
|
|
||||||
sentryDsn: configObject.sentryDsn,
|
|
||||||
sentryMessage: '1000 class error',
|
|
||||||
redirectTo: 'https://lossless.com',
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
case 'alwaysonline':
|
|
||||||
infoHtmlOptions = {
|
|
||||||
title: 'Lossless Network: No Cache',
|
|
||||||
heading: 'No Cache',
|
|
||||||
text: '::ALWAYS_ONLINE_NO_COPY_BOX::',
|
|
||||||
sentryDsn: configObject.sentryDsn,
|
|
||||||
sentryMessage: 'alwaysonline triggered. Potentially offline!',
|
|
||||||
redirectTo: 'https://lossless.com',
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
case 'waf':
|
|
||||||
infoHtmlOptions = {
|
|
||||||
title: 'Lossless Network: Firewall Challenge',
|
|
||||||
heading: 'Firewall Challenge',
|
|
||||||
text: '::CAPTCHA_BOX::',
|
|
||||||
redirectTo: 'https://lossless.com',
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
case 'country':
|
|
||||||
infoHtmlOptions = {
|
|
||||||
title: 'Lossless Network: Country Challenge',
|
|
||||||
heading: 'Country Challenge',
|
|
||||||
text: '::CAPTCHA_BOX::',
|
|
||||||
redirectTo: 'https://lossless.com',
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
case 'attack':
|
|
||||||
infoHtmlOptions = {
|
|
||||||
title: 'Lossless Network: Advanced User Challenge',
|
|
||||||
heading: 'Advanced User Challenge',
|
|
||||||
text: '::IM_UNDER_ATTACK_BOX::',
|
|
||||||
redirectTo: 'https://lossless.com',
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
const statusInstance = plugins.smartstatus.HttpStatus.getHttpStatusByString(
|
|
||||||
req.params.code,
|
|
||||||
);
|
|
||||||
infoHtmlOptions = {
|
|
||||||
title: `Lossless Network: ${statusInstance.code.toString()}`,
|
|
||||||
heading: statusInstance.code.toString(),
|
|
||||||
text: statusInstance.text,
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
const infoHtmlInstance =
|
|
||||||
await plugins.typedserverInfoHtml.InfoHtml.fromOptions(infoHtmlOptions);
|
|
||||||
res.status(200);
|
|
||||||
res.send(infoHtmlInstance.htmlString);
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
serverArg.addRoute(
|
|
||||||
'/custom',
|
|
||||||
new plugins.typedserver.servertools.Handler('GET', async (req, res) => {
|
|
||||||
console.log(req.query);
|
|
||||||
const options: any = {
|
|
||||||
title: 'Lossless Network',
|
|
||||||
heading: 'Error!',
|
|
||||||
text: 'Please wait...',
|
|
||||||
redirectTo: 'https://lossless.com',
|
|
||||||
...req.query,
|
|
||||||
};
|
|
||||||
const infoHtmlInstance = await plugins.typedserverInfoHtml.InfoHtml.fromOptions({
|
|
||||||
title: decodeURI(options.title),
|
|
||||||
heading: decodeURI(options.heading),
|
|
||||||
text: decodeURI(options.text),
|
|
||||||
redirectTo: decodeURI(options.redirectTo),
|
|
||||||
sentryDsn: configObject.sentryDsn,
|
|
||||||
sentryMessage: `nullresolve custom: ${decodeURI(options.title)}`,
|
|
||||||
});
|
|
||||||
res.status(200);
|
|
||||||
res.send(infoHtmlInstance.htmlString);
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getStatusInfoOptions(statusCodeArg: string): IHtmlInfoOptions {
|
||||||
|
switch (statusCodeArg) {
|
||||||
|
case 'ipblock':
|
||||||
|
return {
|
||||||
|
title: 'Lossless Network: Blocked IP',
|
||||||
|
heading: 'Blocked IP',
|
||||||
|
text: 'Your IP (::CLIENT_IP::) is not allowed to access this resource.',
|
||||||
|
sentryDsn: configObject.sentryDsn,
|
||||||
|
sentryMessage: 'ipblock',
|
||||||
|
redirectTo: 'https://lossless.com',
|
||||||
|
};
|
||||||
|
case 'firewall':
|
||||||
|
return {
|
||||||
|
title: 'Lossless Network: Firewall',
|
||||||
|
heading: 'Firewall',
|
||||||
|
text: 'Your request has been blocked by our firewall since it showed possibly harmful behaviour.',
|
||||||
|
sentryDsn: configObject.sentryDsn,
|
||||||
|
sentryMessage: 'firewall',
|
||||||
|
redirectTo: 'https://lossless.com',
|
||||||
|
};
|
||||||
|
case '500class':
|
||||||
|
return {
|
||||||
|
title: 'Lossless Network: 5xx',
|
||||||
|
heading: '5xx',
|
||||||
|
text: '::CLOUDFLARE_ERROR_500S_BOX::',
|
||||||
|
sentryDsn: configObject.sentryDsn,
|
||||||
|
sentryMessage: '5xx error',
|
||||||
|
redirectTo: 'https://lossless.com',
|
||||||
|
};
|
||||||
|
case '1000class':
|
||||||
|
return {
|
||||||
|
title: 'Lossless Network: DNS Resolution failed',
|
||||||
|
heading: '1xxx',
|
||||||
|
text: '::CLOUDFLARE_ERROR_1000S_BOX::',
|
||||||
|
sentryDsn: configObject.sentryDsn,
|
||||||
|
sentryMessage: '1000 class error',
|
||||||
|
redirectTo: 'https://lossless.com',
|
||||||
|
};
|
||||||
|
case 'alwaysonline':
|
||||||
|
return {
|
||||||
|
title: 'Lossless Network: No Cache',
|
||||||
|
heading: 'No Cache',
|
||||||
|
text: '::ALWAYS_ONLINE_NO_COPY_BOX::',
|
||||||
|
sentryDsn: configObject.sentryDsn,
|
||||||
|
sentryMessage: 'alwaysonline triggered. Potentially offline!',
|
||||||
|
redirectTo: 'https://lossless.com',
|
||||||
|
};
|
||||||
|
case 'waf':
|
||||||
|
return {
|
||||||
|
title: 'Lossless Network: Firewall Challenge',
|
||||||
|
heading: 'Firewall Challenge',
|
||||||
|
text: '::CAPTCHA_BOX::',
|
||||||
|
redirectTo: 'https://lossless.com',
|
||||||
|
};
|
||||||
|
case 'country':
|
||||||
|
return {
|
||||||
|
title: 'Lossless Network: Country Challenge',
|
||||||
|
heading: 'Country Challenge',
|
||||||
|
text: '::CAPTCHA_BOX::',
|
||||||
|
redirectTo: 'https://lossless.com',
|
||||||
|
};
|
||||||
|
case 'attack':
|
||||||
|
return {
|
||||||
|
title: 'Lossless Network: Advanced User Challenge',
|
||||||
|
heading: 'Advanced User Challenge',
|
||||||
|
text: '::IM_UNDER_ATTACK_BOX::',
|
||||||
|
redirectTo: 'https://lossless.com',
|
||||||
|
};
|
||||||
|
default: {
|
||||||
|
const statusInstance = plugins.smartstatus.HttpStatus.getHttpStatusByString(statusCodeArg);
|
||||||
|
return {
|
||||||
|
title: `Lossless Network: ${statusInstance.code.toString()}`,
|
||||||
|
heading: statusInstance.code.toString(),
|
||||||
|
text: statusInstance.text,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async addCustomRoutes(typedServerArg: plugins.typedserver.TypedServer) {
|
||||||
|
typedServerArg.addRoute('/status/:code', 'GET', async (ctxArg) => {
|
||||||
|
return this.createInfoHtmlResponse(this.getStatusInfoOptions(ctxArg.params.code));
|
||||||
|
});
|
||||||
|
|
||||||
|
typedServerArg.addRoute('/custom', 'GET', async (ctxArg) => {
|
||||||
|
const options = {
|
||||||
|
title: ctxArg.query.title || 'Lossless Network',
|
||||||
|
heading: ctxArg.query.heading || 'Error!',
|
||||||
|
text: ctxArg.query.text || 'Please wait...',
|
||||||
|
redirectTo: ctxArg.query.redirectTo || 'https://lossless.com',
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.createInfoHtmlResponse({
|
||||||
|
...options,
|
||||||
|
sentryDsn: configObject.sentryDsn,
|
||||||
|
sentryMessage: `nullresolve custom: ${options.title}`,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public async start() {
|
public async start() {
|
||||||
|
if (this.serviceServer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const projectinfo = await plugins.projectinfo.ProjectInfo.create(paths.packageDir);
|
||||||
|
this.serviceServer = new plugins.typedserver.utilityservers.UtilityServiceServer({
|
||||||
|
serviceDomain: this.options.serviceDomain,
|
||||||
|
serviceName: 'nullresolve',
|
||||||
|
serviceVersion: projectinfo.npm.version,
|
||||||
|
port: this.options.port,
|
||||||
|
addCustomRoutes: async (typedServerArg) => this.addCustomRoutes(typedServerArg),
|
||||||
|
});
|
||||||
await this.serviceServer.start();
|
await this.serviceServer.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async stop() {
|
public async stop() {
|
||||||
|
if (!this.serviceServer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
await this.serviceServer.stop();
|
await this.serviceServer.stop();
|
||||||
|
this.serviceServer = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
import * as plugins from './nullresolve.plugins.js';
|
|
||||||
import * as paths from './nullresolve.paths.js';
|
|
||||||
|
|
||||||
const projectInfoNpm = new plugins.projectinfo.ProjectinfoNpm(paths.packageDir);
|
|
||||||
|
|
||||||
import { commitinfo } from './00_commitinfo_data.js';
|
|
||||||
|
|
||||||
export const logger = plugins.smartlog.Smartlog.createForCommitinfo(commitinfo);
|
|
||||||
@@ -5,14 +5,12 @@ export { path };
|
|||||||
|
|
||||||
// @api.global scope
|
// @api.global scope
|
||||||
import * as typedserver from '@api.global/typedserver';
|
import * as typedserver from '@api.global/typedserver';
|
||||||
import * as typedserverInfoHtml from '@api.global/typedserver/infohtml';
|
|
||||||
|
|
||||||
export { typedserver, typedserverInfoHtml };
|
export { typedserver };
|
||||||
|
|
||||||
// @push.rocks scope
|
// @push.rocks scope
|
||||||
import * as projectinfo from '@push.rocks/projectinfo';
|
import * as projectinfo from '@push.rocks/projectinfo';
|
||||||
import * as smartlog from '@push.rocks/smartlog';
|
|
||||||
import * as smartpath from '@push.rocks/smartpath';
|
import * as smartpath from '@push.rocks/smartpath';
|
||||||
import * as smartstatus from '@push.rocks/smartstatus';
|
import * as smartstatus from '@push.rocks/smartstatus';
|
||||||
|
|
||||||
export { projectinfo, smartlog, smartpath, smartstatus };
|
export { projectinfo, smartpath, smartstatus };
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
import * as plugins from './nullresolve.plugins.js';
|
|
||||||
import * as paths from './nullresolve.paths.js';
|
|
||||||
|
|
||||||
export const projectinfo = new plugins.projectinfo.ProjectInfo(paths.packageDir);
|
|
||||||
Reference in New Issue
Block a user