This commit is contained in:
Philipp Kunz 2024-12-26 00:29:13 +01:00
commit d7c8972072
25 changed files with 10342 additions and 0 deletions

1
.dockerignore Normal file
View File

@ -0,0 +1 @@
node_modules/

View File

@ -0,0 +1,71 @@
name: Docker (tags)
on:
push:
tags-ignore:
- '**'
env:
IMAGE: code.foss.global/hosttoday/ht-docker-node:npmci
NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@/${{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 }}
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:
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 npm prepare
npmci node install stable
npmci npm install
npmci command npm run build

View File

@ -0,0 +1,106 @@
name: Docker (tags)
on:
push:
tags:
- '*'
env:
IMAGE: code.foss.global/hosttoday/ht-docker-node:npmci
NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@/${{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 }}
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:
needs: test
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
container:
image: code.foss.global/hosttoday/ht-docker-dbase:npmci
steps:
- uses: actions/checkout@v3
- name: Prepare
run: |
pnpm install -g pnpm
pnpm install -g @ship.zone/npmci
- name: Release
run: |
npmci docker login
npmci docker build
npmci docker test
# npmci docker push
npmci docker push
metadata:
needs: test
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
container:
image: ${{ env.IMAGE }}
steps:
- uses: actions/checkout@v3
- name: Trigger
run: npmci trigger

19
.gitignore vendored Normal file
View File

@ -0,0 +1,19 @@
.nogit/
# artifacts
coverage/
public/
# installs
node_modules/
# caches
.yarn/
.cache/
.rpt2_cache
# builds
dist/
dist_*/
#------# custom

11
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,11 @@
{
"version": "0.2.0",
"configurations": [
{
"command": "npm test",
"name": "Run npm test",
"request": "launch",
"type": "node-terminal"
}
]
}

26
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,26 @@
{
"json.schemas": [
{
"fileMatch": ["/npmextra.json"],
"schema": {
"type": "object",
"properties": {
"npmci": {
"type": "object",
"description": "settings for npmci"
},
"gitzone": {
"type": "object",
"description": "settings for gitzone",
"properties": {
"projectType": {
"type": "string",
"enum": ["website", "element", "service", "npm", "wcc"]
}
}
}
}
}
}
]
}

46
Dockerfile Normal file
View File

@ -0,0 +1,46 @@
# gitzone dockerfile_service
## STAGE 1 // BUILD
FROM code.foss.global/host.today/ht-docker-node:npmci as node1
COPY ./ /app
WORKDIR /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 rm -rf node_modules && pnpm install
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
ARG NPMCI_TOKEN_NPM2
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 3 // rebuild dependencies for alpine
FROM code.foss.global/host.today/ht-docker-node:alpinenpmci as node3
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
FROM code.foss.global/host.today/ht-docker-node:alpine as node4
WORKDIR /app
COPY --from=node3 /app /app
### Healthchecks
RUN pnpm install -g @servezone/healthy
HEALTHCHECK --interval=30s --timeout=30s --start-period=30s --retries=3 CMD [ "healthy" ]
EXPOSE 80
CMD ["npm", "start"]

4
cli.child.ts Normal file
View File

@ -0,0 +1,4 @@
#!/usr/bin/env node
process.env.CLI_CALL = 'true';
import * as cliTool from './ts/index.js';
cliTool.runCli();

4
cli.js Normal file
View File

@ -0,0 +1,4 @@
#!/usr/bin/env node
process.env.CLI_CALL = 'true';
const cliTool = await import('./dist_ts/index.js');
cliTool.runCli();

5
cli.ts.js Normal file
View File

@ -0,0 +1,5 @@
#!/usr/bin/env node
process.env.CLI_CALL = 'true';
import * as tsrun from '@git.zone/tsrun';
tsrun.runPath('./cli.child.js', import.meta.url);

23
npmextra.json Normal file
View File

@ -0,0 +1,23 @@
{
"npmci": {
"npmGlobalTools": [],
"dockerRegistryRepoMap": {
"registry.gitlab.com": "losslessone/services/servezone/nullresolve"
},
"dockerBuildargEnvMap": {
"NPMCI_TOKEN_NPM2": "NPMCI_TOKEN_NPM2"
},
"npmRegistryUrl": "verdaccio.lossless.one"
},
"gitzone": {
"projectType": "service",
"module": {
"githost": "gitlab.com",
"gitscope": "losslessone/services/servezone",
"gitrepo": "nullresolve",
"description": "servezone service. the null service takes care of handling requests and giving feedback for those that would otherwise not be served.",
"npmPackagename": "@losslessone_private/nullresolve",
"license": "MIT"
}
}
}

54
package.json Normal file
View File

@ -0,0 +1,54 @@
{
"name": "@losslessone_private/nullresolve",
"version": "1.0.29",
"description": "servezone service. the null service takes care of handling requests and giving feedback for those that would otherwise not be served.",
"type": "module",
"author": "Lossless GmbH",
"license": "UNLICENSED",
"scripts": {
"test": "(tstest test/)",
"start": "(node cli.js)",
"startTs": "(node cli.ts.js)",
"build": "(tsbuild --web --allowimplicitany)",
"watch": "(tswatch service)"
},
"devDependencies": {
"@git.zone/tsbuild": "^2.1.63",
"@git.zone/tstest": "^1.0.71",
"@git.zone/tswatch": "^2.0.37",
"@push.rocks/tapbundle": "^5.0.3",
"@types/node": "^22.10.2"
},
"dependencies": {
"@api.global/typedserver": "^3.0.53",
"@git.zone/tsrun": "^1.2.37",
"@push.rocks/projectinfo": "^5.0.1",
"@push.rocks/smartlog": "^3.0.7",
"@push.rocks/smartpath": "^5.0.5",
"@push.rocks/smartstatus": "^1.1.1"
},
"private": true,
"files": [
"ts/**/*",
"ts_web/**/*",
"dist/**/*",
"dist_*/**/*",
"dist_ts/**/*",
"dist_ts_web/**/*",
"assets/**/*",
"cli.js",
"npmextra.json",
"readme.md"
],
"browserslist": [
"last 1 chrome versions"
],
"repository": {
"type": "git",
"url": "git+https://gitlab.com/losslessone/services/servezone/nullresolve.git"
},
"bugs": {
"url": "https://gitlab.com/losslessone/services/servezone/nullresolve/issues"
},
"homepage": "https://gitlab.com/losslessone/services/servezone/nullresolve#readme"
}

9686
pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

3
readme.hints.md Normal file
View File

@ -0,0 +1,3 @@
# Project Readme Hints
This is the initial readme hints file.

43
readme.md Normal file
View File

@ -0,0 +1,43 @@
# @losslessone/services/servezone/nullresolve
servezone service. the null service takes care of handling requests and giving feedback for those that would otherwise not be served.
## Availabililty and Links
- [npmjs.org (npm package)](https://www.npmjs.com/package/@losslessone_private/nullresolve)
- [gitlab.com (source)](https://gitlab.com/losslessone/services/servezone/nullresolve)
- [github.com (source mirror)](https://github.com/losslessone/services/servezone/nullresolve)
- [docs (typedoc)](https://losslessone/services/servezone.gitlab.io/nullresolve/)
## Status for master
| Status Category | Status Badge |
| ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| GitLab Pipelines | [![pipeline status](https://gitlab.com/losslessone/services/servezone/nullresolve/badges/master/pipeline.svg)](https://lossless.cloud) |
| GitLab Pipline Test Coverage | [![coverage report](https://gitlab.com/losslessone/services/servezone/nullresolve/badges/master/coverage.svg)](https://lossless.cloud) |
| npm | [![npm downloads per month](https://badgen.net/npm/dy/@losslessone_private/nullresolve)](https://lossless.cloud) |
| Snyk | [![Known Vulnerabilities](https://badgen.net/snyk/losslessone/services/servezone/nullresolve)](https://lossless.cloud) |
| TypeScript Support | [![TypeScript](https://badgen.net/badge/TypeScript/>=%203.x/blue?icon=typescript)](https://lossless.cloud) |
| node Support | [![node](https://img.shields.io/badge/node->=%2010.x.x-blue.svg)](https://nodejs.org/dist/latest-v10.x/docs/api/) |
| Code Style | [![Code Style](https://badgen.net/badge/style/prettier/purple)](https://lossless.cloud) |
| PackagePhobia (total standalone install weight) | [![PackagePhobia](https://badgen.net/packagephobia/install/@losslessone_private/nullresolve)](https://lossless.cloud) |
| PackagePhobia (package size on registry) | [![PackagePhobia](https://badgen.net/packagephobia/publish/@losslessone_private/nullresolve)](https://lossless.cloud) |
| BundlePhobia (total size when bundled) | [![BundlePhobia](https://badgen.net/bundlephobia/minzip/@losslessone_private/nullresolve)](https://lossless.cloud) |
| Platform support | [![Supports Windows 10](https://badgen.net/badge/supports%20Windows%2010/yes/green?icon=windows)](https://lossless.cloud) [![Supports Mac OS X](https://badgen.net/badge/supports%20Mac%20OS%20X/yes/green?icon=apple)](https://lossless.cloud) |
## Usage
## Contribution
We are always happy for code contributions. If you are not the code contributing type that is ok. Still, maintaining Open Source repositories takes considerable time and thought. If you like the quality of what we do and our modules are useful to you we would appreciate a little monthly contribution: You can [contribute one time](https://lossless.link/contribute-onetime) or [contribute monthly](https://lossless.link/contribute). :)
## Contribution
We are always happy for code contributions. If you are not the code contributing type that is ok. Still, maintaining Open Source repositories takes considerable time and thought. If you like the quality of what we do and our modules are useful to you we would appreciate a little monthly contribution: You can [contribute one time](https://lossless.link/contribute-onetime) or [contribute monthly](https://lossless.link/contribute). :)
For further information read the linked docs at the top of this readme.
> MIT licensed | **©** [Lossless GmbH](https://lossless.gmbh)
> | By using this npm module you agree to our [privacy policy](https://lossless.gmbH/privacy)
[![repo-footer](https://lossless.gitlab.io/publicrelations/repofooter.svg)](https://maintainedby.lossless.com)

14
test/test.node.ts Normal file
View File

@ -0,0 +1,14 @@
import { tap, expect } from '@push.rocks/tapbundle';
import * as nullresolve from '../ts/index.js';
let nullresolveInstance: nullresolve.NullResolve;
tap.test('should create, start and stop an instance of nullresolve', async () => {
nullresolveInstance = new nullresolve.NullResolve();
expect(nullresolveInstance).toBeInstanceOf(nullresolve.NullResolve);
await nullresolveInstance.start();
await nullresolveInstance.stop();
});
tap.start();

9
ts/00_commitinfo_data.ts Normal file
View File

@ -0,0 +1,9 @@
/**
* autocreated commitinfo by @push.rocks/commitinfo
*/
export const commitinfo = {
name: '@losslessone_private/nullresolve',
version: '1.0.29',
description:
'servezone service. the null service takes care of handling requests and giving feedback for those that would otherwise not be served.',
};

17
ts/index.ts Normal file
View File

@ -0,0 +1,17 @@
import './nullresolve.logging.js';
import { NullResolve } from './nullresolve.classes.nullresolve.js';
export { NullResolve };
let mainNullResolve: NullResolve;
export const runCli = async () => {
mainNullResolve = new NullResolve();
await mainNullResolve.start();
};
export const stop = async () => {
if (mainNullResolve) {
await mainNullResolve.stop();
mainNullResolve = null;
}
};

View File

@ -0,0 +1,147 @@
import * as plugins from './nullresolve.plugins.js';
import { projectinfo } from './nullresolve.projectinfo.js';
import { configObject } from './nullresolve.config.js';
export class NullResolve {
public serviceServer: plugins.typedserver.utilityservers.UtilityServiceServer;
constructor() {
this.serviceServer = new plugins.typedserver.utilityservers.UtilityServiceServer({
serviceDomain: 'nullresolve.lossless.one',
serviceName: 'nullresolve',
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) {
case 'ipblock':
infoHtmlOptions = {
title: 'Lossless Network: Blocked IP',
heading: 'Blocked IP',
text: 'Your IP (::CLIENT_IP::) is not allowed to access this ressource.',
sentryDsn: configObject.sentryDsn,
sentryMessage: 'ipblock',
redirectTo: 'https://lossless.com',
};
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);
}),
);
},
});
}
public async start() {
await this.serviceServer.start();
}
public async stop() {
await this.serviceServer.stop();
}
}

3
ts/nullresolve.config.ts Normal file
View File

@ -0,0 +1,3 @@
export const configObject = {
sentryDsn: 'https://85d4a993eac74dd389c56c1f842b2dff@sentry.io/1486007',
};

View File

@ -0,0 +1,8 @@
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);

6
ts/nullresolve.paths.ts Normal file
View File

@ -0,0 +1,6 @@
import * as plugins from './nullresolve.plugins.js';
export const packageDir = plugins.path.join(
plugins.smartpath.get.dirnameFromImportMetaUrl(import.meta.url),
'../',
);

18
ts/nullresolve.plugins.ts Normal file
View File

@ -0,0 +1,18 @@
// native
import * as path from 'path';
export { path };
// @api.global scope
import * as typedserver from '@api.global/typedserver';
import * as typedserverInfoHtml from '@api.global/typedserver/infohtml';
export { typedserver, typedserverInfoHtml };
// @push.rocks scope
import * as projectinfo from '@push.rocks/projectinfo';
import * as smartlog from '@push.rocks/smartlog';
import * as smartpath from '@push.rocks/smartpath';
import * as smartstatus from '@push.rocks/smartstatus';
export { projectinfo, smartlog, smartpath, smartstatus };

View File

@ -0,0 +1,4 @@
import * as plugins from './nullresolve.plugins.js';
import * as paths from './nullresolve.paths.js';
export const projectinfo = new plugins.projectinfo.ProjectInfo(paths.packageDir);

14
tsconfig.json Normal file
View File

@ -0,0 +1,14 @@
{
"compilerOptions": {
"experimentalDecorators": true,
"useDefineForClassFields": false,
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"esModuleInterop": true,
"verbatimModuleSyntax": true
},
"exclude": [
"dist_*/**/*.d.ts"
]
}