Compare commits
3 Commits
d0f35e1af6
...
2319347f03
| Author | SHA1 | Date | |
|---|---|---|---|
|
2319347f03
|
|||
|
a64e973269
|
|||
|
918d0efa1e
|
347
.eslintrc.json
347
.eslintrc.json
@ -1,171 +1,178 @@
|
|||||||
{
|
{
|
||||||
"env":{
|
"env": {
|
||||||
"es2021":true,
|
"es2021": true,
|
||||||
"node":true
|
"node": true
|
||||||
},
|
},
|
||||||
"extends":[
|
"extends": [
|
||||||
"eslint:recommended",
|
"eslint:recommended",
|
||||||
"plugin:@typescript-eslint/eslint-recommended",
|
"plugin:@typescript-eslint/eslint-recommended",
|
||||||
"plugin:@typescript-eslint/recommended",
|
"plugin:@typescript-eslint/recommended",
|
||||||
"plugin:promise/recommended",
|
"plugin:promise/recommended",
|
||||||
"plugin:import/recommended",
|
"plugin:import/recommended",
|
||||||
"plugin:import/typescript"
|
"plugin:import/typescript"
|
||||||
],
|
],
|
||||||
"parser":"@typescript-eslint/parser",
|
"parser": "@typescript-eslint/parser",
|
||||||
"parserOptions":{
|
"parserOptions": {
|
||||||
"project":"./tsconfig.json",
|
"project": "./tsconfig.json",
|
||||||
"ecmaVersion":"latest",
|
"ecmaVersion": "latest",
|
||||||
"sourceType":"module"
|
"sourceType": "module"
|
||||||
},
|
},
|
||||||
"plugins":[
|
"plugins": ["@typescript-eslint", "unused-imports", "promise"],
|
||||||
"@typescript-eslint",
|
"rules": {
|
||||||
"unused-imports",
|
"no-console": ["error"],
|
||||||
"promise"
|
"semi": "off",
|
||||||
],
|
"@typescript-eslint/semi": ["error", "always"],
|
||||||
"rules":{
|
"quotes": ["error", "double"],
|
||||||
"no-console":[
|
"no-multiple-empty-lines": [
|
||||||
"error"
|
"error",
|
||||||
],
|
{
|
||||||
"semi":"off",
|
"max": 1,
|
||||||
"@typescript-eslint/semi":[
|
"maxEOF": 1
|
||||||
"error",
|
}
|
||||||
"always"
|
],
|
||||||
],
|
"spaced-comment": ["error", "always"],
|
||||||
"quotes":[
|
"padding-line-between-statements": [
|
||||||
"error",
|
"error",
|
||||||
"double"
|
{
|
||||||
],
|
"blankLine": "always",
|
||||||
"no-multiple-empty-lines":[
|
"prev": "import",
|
||||||
"error",
|
"next": "*"
|
||||||
{
|
},
|
||||||
"max":1,
|
{
|
||||||
"maxEOF":1
|
"blankLine": "never",
|
||||||
}
|
"prev": "import",
|
||||||
],
|
"next": "import"
|
||||||
"spaced-comment":[
|
},
|
||||||
"error",
|
{
|
||||||
"always"
|
"blankLine": "always",
|
||||||
],
|
"prev": "class",
|
||||||
"padding-line-between-statements":[
|
"next": "*"
|
||||||
"error",
|
}
|
||||||
{
|
],
|
||||||
"blankLine":"always",
|
"lines-between-class-members": "off",
|
||||||
"prev":"import",
|
"@typescript-eslint/lines-between-class-members": [
|
||||||
"next":"*"
|
"error",
|
||||||
},
|
"always",
|
||||||
{
|
{
|
||||||
"blankLine":"never",
|
"exceptAfterSingleLine": true
|
||||||
"prev":"import",
|
}
|
||||||
"next":"import"
|
],
|
||||||
},
|
"@typescript-eslint/await-thenable": "error",
|
||||||
{
|
"@typescript-eslint/no-for-in-array": "error",
|
||||||
"blankLine":"always",
|
"@typescript-eslint/no-misused-promises": "error",
|
||||||
"prev":"class",
|
"@typescript-eslint/explicit-function-return-type": "error",
|
||||||
"next":"*"
|
"@typescript-eslint/no-unnecessary-type-assertion": "error",
|
||||||
}
|
"@typescript-eslint/prefer-includes": "error",
|
||||||
],
|
"@typescript-eslint/prefer-regexp-exec": "error",
|
||||||
"lines-between-class-members":"off",
|
"@typescript-eslint/prefer-string-starts-ends-with": "error",
|
||||||
"@typescript-eslint/lines-between-class-members":[
|
"@typescript-eslint/explicit-member-accessibility": "error",
|
||||||
"error",
|
"require-await": "off",
|
||||||
"always",
|
"@typescript-eslint/require-await": "error",
|
||||||
{
|
"@typescript-eslint/unbound-method": "error",
|
||||||
"exceptAfterSingleLine":true
|
"no-var": "error",
|
||||||
}
|
"prefer-const": "error",
|
||||||
],
|
"prefer-rest-params": "error",
|
||||||
"@typescript-eslint/await-thenable":"error",
|
"prefer-spread": "error",
|
||||||
"@typescript-eslint/no-for-in-array":"error",
|
"no-use-before-define": "off",
|
||||||
"@typescript-eslint/no-misused-promises":"error",
|
"@typescript-eslint/no-use-before-define": "error",
|
||||||
"@typescript-eslint/explicit-function-return-type":"error",
|
"no-useless-constructor": "off",
|
||||||
"@typescript-eslint/no-unnecessary-type-assertion":"error",
|
"@typescript-eslint/no-useless-constructor": "error",
|
||||||
"@typescript-eslint/prefer-includes":"error",
|
"@typescript-eslint/no-var-requires": "error",
|
||||||
"@typescript-eslint/prefer-regexp-exec":"error",
|
"@typescript-eslint/no-misused-new": "error",
|
||||||
"@typescript-eslint/prefer-string-starts-ends-with":"error",
|
"@typescript-eslint/no-non-null-asserted-optional-chain": "error",
|
||||||
"@typescript-eslint/explicit-member-accessibility":"error",
|
"@typescript-eslint/no-non-null-assertion": "error",
|
||||||
"require-await":"off",
|
"@typescript-eslint/no-parameter-properties": "error",
|
||||||
"@typescript-eslint/require-await":"error",
|
"@typescript-eslint/no-require-imports": "error",
|
||||||
"@typescript-eslint/unbound-method":"error",
|
"@typescript-eslint/no-this-alias": "error",
|
||||||
"no-var":"error",
|
"@typescript-eslint/no-throw-literal": "error",
|
||||||
"prefer-const":"error",
|
"@typescript-eslint/no-unsafe-call": "error",
|
||||||
"prefer-rest-params":"error",
|
"@typescript-eslint/no-unsafe-member-access": "error",
|
||||||
"prefer-spread":"error",
|
"@typescript-eslint/no-unsafe-return": "error",
|
||||||
"no-use-before-define":"off",
|
"no-unused-expressions": "off",
|
||||||
"@typescript-eslint/no-use-before-define":"error",
|
"@typescript-eslint/no-unused-expressions": "error",
|
||||||
"no-useless-constructor":"off",
|
"no-extra-semi": "off",
|
||||||
"@typescript-eslint/no-useless-constructor":"error",
|
"@typescript-eslint/no-extra-semi": "error",
|
||||||
"@typescript-eslint/no-var-requires":"error",
|
"@typescript-eslint/no-extraneous-class": "error",
|
||||||
"@typescript-eslint/no-misused-new":"error",
|
"@typescript-eslint/no-floating-promises": "error",
|
||||||
"@typescript-eslint/no-non-null-asserted-optional-chain":"error",
|
"@typescript-eslint/no-implied-eval": "error",
|
||||||
"@typescript-eslint/no-non-null-assertion":"error",
|
"comma-spacing": "off",
|
||||||
"@typescript-eslint/no-parameter-properties":"error",
|
"@typescript-eslint/comma-spacing": "error",
|
||||||
"@typescript-eslint/no-require-imports":"error",
|
"func-call-spacing": "off",
|
||||||
"@typescript-eslint/no-this-alias":"error",
|
"@typescript-eslint/func-call-spacing": "error",
|
||||||
"@typescript-eslint/no-throw-literal":"error",
|
"space-before-function-paren": "off",
|
||||||
"@typescript-eslint/no-unsafe-call":"error",
|
"@typescript-eslint/space-before-function-paren": "error",
|
||||||
"@typescript-eslint/no-unsafe-member-access":"error",
|
"@typescript-eslint/type-annotation-spacing": "error",
|
||||||
"@typescript-eslint/no-unsafe-return":"error",
|
"no-magic-numbers": "off",
|
||||||
"no-unused-expressions":"off",
|
"@typescript-eslint/no-magic-numbers": [
|
||||||
"@typescript-eslint/no-unused-expressions":"error",
|
"error",
|
||||||
"no-extra-semi":"off",
|
{
|
||||||
"@typescript-eslint/no-extra-semi":"error",
|
"ignoreArrayIndexes": true,
|
||||||
"@typescript-eslint/no-extraneous-class":"error",
|
"ignore": [-1, 1, 0, 2, 3]
|
||||||
"@typescript-eslint/no-floating-promises":"error",
|
}
|
||||||
"@typescript-eslint/no-implied-eval":"error",
|
],
|
||||||
"comma-spacing":"off",
|
"@typescript-eslint/no-unnecessary-boolean-literal-compare": "warn",
|
||||||
"@typescript-eslint/comma-spacing":"error",
|
"@typescript-eslint/no-unnecessary-condition": "warn",
|
||||||
"func-call-spacing":"off",
|
"@typescript-eslint/no-unnecessary-qualifier": "warn",
|
||||||
"@typescript-eslint/func-call-spacing":"error",
|
"@typescript-eslint/no-unnecessary-type-arguments": "warn",
|
||||||
"space-before-function-paren":"off",
|
"@typescript-eslint/member-ordering": [
|
||||||
"@typescript-eslint/space-before-function-paren":"error",
|
"error",
|
||||||
"@typescript-eslint/type-annotation-spacing":"error",
|
{
|
||||||
"no-magic-numbers":"off",
|
"default": {
|
||||||
"@typescript-eslint/no-magic-numbers":[
|
"memberTypes": [
|
||||||
"error",
|
"public-static-field",
|
||||||
{
|
"public-field",
|
||||||
"ignoreArrayIndexes":true,
|
"protected-static-field",
|
||||||
"ignore":[
|
"protected-field",
|
||||||
-1,
|
"private-static-field",
|
||||||
1,
|
"private-field",
|
||||||
0,
|
"public-constructor",
|
||||||
2,
|
"protected-constructor",
|
||||||
3
|
"private-constructor",
|
||||||
]
|
["public-get", "public-set"],
|
||||||
}
|
["protected-get", "protected-set"],
|
||||||
],
|
["private-get", "private-set"],
|
||||||
"@typescript-eslint/no-unnecessary-boolean-literal-compare":"warn",
|
"signature",
|
||||||
"@typescript-eslint/no-unnecessary-condition":"warn",
|
"public-static-method",
|
||||||
"@typescript-eslint/no-unnecessary-qualifier":"warn",
|
"public-method",
|
||||||
"@typescript-eslint/no-unnecessary-type-arguments":"warn",
|
"protected-static-method",
|
||||||
"@typescript-eslint/member-ordering":"warn",
|
"protected-method",
|
||||||
"@typescript-eslint/strict-boolean-expressions":"off",
|
"private-static-method",
|
||||||
"@typescript-eslint/prefer-as-const":"warn",
|
"private-method"
|
||||||
"@typescript-eslint/prefer-for-of":"warn",
|
],
|
||||||
"@typescript-eslint/prefer-function-type":"warn",
|
"order": "alphabetically"
|
||||||
"@typescript-eslint/prefer-namespace-keyword":"warn",
|
}
|
||||||
"@typescript-eslint/prefer-nullish-coalescing":"warn",
|
}
|
||||||
"@typescript-eslint/prefer-optional-chain":"warn",
|
],
|
||||||
"@typescript-eslint/prefer-readonly":"warn",
|
"@typescript-eslint/strict-boolean-expressions": "off",
|
||||||
"@typescript-eslint/prefer-readonly-parameter-types":"off",
|
"@typescript-eslint/prefer-as-const": "warn",
|
||||||
"@typescript-eslint/no-explicit-any":1,
|
"@typescript-eslint/prefer-for-of": "warn",
|
||||||
"@typescript-eslint/no-inferrable-types":[
|
"@typescript-eslint/prefer-function-type": "warn",
|
||||||
"warn",
|
"@typescript-eslint/prefer-namespace-keyword": "warn",
|
||||||
{
|
"@typescript-eslint/prefer-nullish-coalescing": "warn",
|
||||||
"ignoreParameters":true
|
"@typescript-eslint/prefer-optional-chain": "warn",
|
||||||
}
|
"@typescript-eslint/prefer-readonly": "warn",
|
||||||
],
|
"@typescript-eslint/prefer-readonly-parameter-types": "off",
|
||||||
"no-unused-vars":"off",
|
"@typescript-eslint/no-explicit-any": 1,
|
||||||
"unused-imports/no-unused-vars": "off",
|
"@typescript-eslint/no-inferrable-types": [
|
||||||
"unused-imports/no-unused-imports":"error",
|
"warn",
|
||||||
"@typescript-eslint/no-unused-vars":[
|
{
|
||||||
"warn",
|
"ignoreParameters": true
|
||||||
{
|
}
|
||||||
"vars":"all",
|
],
|
||||||
"varsIgnorePattern":"^_",
|
"no-unused-vars": "off",
|
||||||
"args":"after-used",
|
"unused-imports/no-unused-vars": "off",
|
||||||
"argsIgnorePattern":"^_"
|
"unused-imports/no-unused-imports": "error",
|
||||||
}
|
"@typescript-eslint/no-unused-vars": [
|
||||||
],
|
"warn",
|
||||||
"indent": "off",
|
{
|
||||||
"@typescript-eslint/indent": ["error", 2],
|
"vars": "all",
|
||||||
"import/no-unresolved": ["off"]
|
"varsIgnorePattern": "^_",
|
||||||
}
|
"args": "after-used",
|
||||||
}
|
"argsIgnorePattern": "^_"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"indent": "off",
|
||||||
|
"@typescript-eslint/indent": ["error", 2],
|
||||||
|
"import/no-unresolved": [2, { "ignore": ["^#.+$"] }]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
47
.vscode/launch.json
vendored
47
.vscode/launch.json
vendored
@ -1,20 +1,29 @@
|
|||||||
{
|
{
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"configurations": [{
|
"configurations": [
|
||||||
"name": "Node Inspector",
|
{
|
||||||
"type": "node",
|
"name": "Node Inspector",
|
||||||
"request": "launch",
|
"type": "node",
|
||||||
"args": ["${workspaceRoot}/src/server.ts"],
|
"request": "launch",
|
||||||
"runtimeArgs": ["--loader", "./src/myloader.mjs", "--experimental-top-level-await", "--experimental-specifier-resolution=node", "--experimental-specifier-resolution=node"],
|
"args": ["${workspaceRoot}/src/app.ts", "start", "-p", "1234"],
|
||||||
"cwd": "${workspaceRoot}",
|
"runtimeArgs": [
|
||||||
"protocol": "inspector",
|
"--no-warnings",
|
||||||
"sourceMaps": true,
|
"--loader",
|
||||||
"trace": "all",
|
"./src/myloader.mjs",
|
||||||
"outputCapture": "std",
|
"--experimental-modules",
|
||||||
"internalConsoleOptions": "openOnSessionStart",
|
"--es-module-specifier-resolution=node"
|
||||||
"env": {
|
],
|
||||||
"TS_NODE_IGNORE": "false",
|
"cwd": "${workspaceRoot}",
|
||||||
"NODE_ENV": "development"
|
"protocol": "inspector",
|
||||||
}
|
"sourceMaps": true,
|
||||||
}]
|
"trace": "all",
|
||||||
}
|
"outputCapture": "std",
|
||||||
|
"internalConsoleOptions": "openOnSessionStart",
|
||||||
|
"env": {
|
||||||
|
"TS_NODE_IGNORE": "false",
|
||||||
|
"NODE_ENV": "development",
|
||||||
|
"TS_NODE_COMPILER": "ttypescript"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
69
.vscode/settings.json
vendored
69
.vscode/settings.json
vendored
@ -1,25 +1,46 @@
|
|||||||
{
|
{
|
||||||
"editor.codeActionsOnSave": {
|
"editor.codeActionsOnSave": {
|
||||||
"source.fixAll.eslint": true
|
"source.fixAll.eslint": true
|
||||||
},
|
},
|
||||||
"eslint.validate": ["javascript", "typescript"],
|
"eslint.validate": ["javascript", "typescript"],
|
||||||
"editor.formatOnSave": true,
|
"editor.formatOnSave": true,
|
||||||
"[javascript]": {
|
"[javascript]": {
|
||||||
"editor.formatOnSave": false
|
"editor.formatOnSave": false
|
||||||
},
|
},
|
||||||
"[typescript]": {
|
"[typescript]": {
|
||||||
"editor.formatOnSave": false
|
"editor.formatOnSave": false
|
||||||
},
|
},
|
||||||
"[markdown]": {
|
"[markdown]": {
|
||||||
"editor.formatOnSave": false
|
"editor.formatOnSave": true
|
||||||
},
|
},
|
||||||
"search.exclude": {
|
"search.exclude": {
|
||||||
"**/node_modules": true,
|
"**/node_modules": true,
|
||||||
"**/bower_components": true,
|
"**/bower_components": true,
|
||||||
"**/dist": true,
|
"**/dist": true,
|
||||||
"**/coverage": true
|
"**/coverage": true
|
||||||
},
|
},
|
||||||
"typescript.referencesCodeLens.enabled": true,
|
"typescript.referencesCodeLens.enabled": true,
|
||||||
"appService.zipIgnorePattern": [".vscode{,/**}"],
|
"appService.zipIgnorePattern": [".vscode{,/**}"],
|
||||||
"appService.deploySubpath": ""
|
"appService.deploySubpath": "",
|
||||||
}
|
"workbench.colorCustomizations": {
|
||||||
|
"activityBar.activeBackground": "#2f7c47",
|
||||||
|
"activityBar.activeBorder": "#422c74",
|
||||||
|
"activityBar.background": "#2f7c47",
|
||||||
|
"activityBar.foreground": "#e7e7e7",
|
||||||
|
"activityBar.inactiveForeground": "#e7e7e799",
|
||||||
|
"activityBarBadge.background": "#422c74",
|
||||||
|
"activityBarBadge.foreground": "#e7e7e7",
|
||||||
|
"sash.hoverBorder": "#2f7c47",
|
||||||
|
"statusBar.background": "#215732",
|
||||||
|
"statusBar.foreground": "#e7e7e7",
|
||||||
|
"statusBarItem.hoverBackground": "#2f7c47",
|
||||||
|
"statusBarItem.remoteBackground": "#215732",
|
||||||
|
"statusBarItem.remoteForeground": "#e7e7e7",
|
||||||
|
"titleBar.activeBackground": "#215732",
|
||||||
|
"titleBar.activeForeground": "#e7e7e7",
|
||||||
|
"titleBar.inactiveBackground": "#21573299",
|
||||||
|
"titleBar.inactiveForeground": "#e7e7e799"
|
||||||
|
},
|
||||||
|
"peacock.color": "#215732",
|
||||||
|
"docwriter.hotkey.windows": "Alt + ."
|
||||||
|
}
|
||||||
|
|||||||
33
package.json
33
package.json
@ -5,11 +5,13 @@
|
|||||||
"main": "server.ts",
|
"main": "server.ts",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node --no-warnings --loader ./src/myloader.mjs --experimental-modules --es-module-specifier-resolution=node ./dist/server.js",
|
"start": "node ./dist/app.js",
|
||||||
"dev": "node --no-warnings --loader ./src/myloader.mjs --experimental-modules --es-module-specifier-resolution=node ./src/server.ts",
|
"dev": "cross-env TS_NODE_COMPILER=ttypescript node --no-warnings --loader ./src/myloader.mjs --experimental-modules --es-module-specifier-resolution=node ./src/app.ts",
|
||||||
"build": "tsc -p tsconfig.json",
|
"build": "ttsc -p tsconfig.json && tsc-alias -p tsconfig.json",
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
"lint": "eslint --fix --ext ts src/"
|
"lint": "eslint --fix --ext ts src/",
|
||||||
|
"upgrade": "yarn upgrade --latest",
|
||||||
|
"xxx": "node --loader ts-node/esm ./src/test.ts"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@ -23,26 +25,43 @@
|
|||||||
"author": "Joshua Schnabel",
|
"author": "Joshua Schnabel",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@automapper/classes": "^8.3.0",
|
||||||
|
"@automapper/core": "^8.3.0",
|
||||||
"@gquittet/graceful-server": "^2.5.2",
|
"@gquittet/graceful-server": "^2.5.2",
|
||||||
|
"@nestjs/common": "^8.4.3",
|
||||||
|
"@nestjs/core": "^8.4.3",
|
||||||
|
"@nestjs/passport": "^8.2.1",
|
||||||
|
"@nestjs/platform-fastify": "^8.4.3",
|
||||||
|
"args-command-parser": "^1.2.4",
|
||||||
|
"cli-color": "^2.0.1",
|
||||||
"fastify": "^3.25.3",
|
"fastify": "^3.25.3",
|
||||||
"fastify-plugin": "^3.0.0",
|
"fastify-plugin": "^3.0.0",
|
||||||
"fastify-sensible": "^3.1.2",
|
"fastify-sensible": "^3.1.2",
|
||||||
|
"passport": "^0.5.2",
|
||||||
|
"passport-http": "^0.3.0",
|
||||||
|
"reflect-metadata": "^0.1.13",
|
||||||
|
"rxjs": "^7.5.5",
|
||||||
"winston": "^3.4.0"
|
"winston": "^3.4.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tsconfig/node16": "^1.0.2",
|
"@tsconfig/node16": "^1.0.2",
|
||||||
|
"@types/cli-color": "^2.0.2",
|
||||||
"@types/node": "^17.0.9",
|
"@types/node": "^17.0.9",
|
||||||
|
"@types/passport": "^1.0.7",
|
||||||
|
"@types/passport-http": "^0.3.9",
|
||||||
"@types/triple-beam": "^1.3.2",
|
"@types/triple-beam": "^1.3.2",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.10.0",
|
"@typescript-eslint/eslint-plugin": "^5.10.0",
|
||||||
"@typescript-eslint/parser": "^5.10.0",
|
"@typescript-eslint/parser": "^5.10.0",
|
||||||
|
"builder-pattern": "^1.3.0",
|
||||||
|
"cross-env": "^7.0.3",
|
||||||
"eslint": "^8.7.0",
|
"eslint": "^8.7.0",
|
||||||
|
"eslint-import-resolver-alias": "^1.1.2",
|
||||||
"eslint-plugin-import": "^2.25.4",
|
"eslint-plugin-import": "^2.25.4",
|
||||||
"eslint-plugin-promise": "^6.0.0",
|
"eslint-plugin-promise": "^6.0.0",
|
||||||
"eslint-plugin-unused-imports": "^2.0.0",
|
"eslint-plugin-unused-imports": "^2.0.0",
|
||||||
"ts-node": "^10.4.0",
|
"ts-node": "^10.4.0",
|
||||||
|
"tsc-alias": "^1.6.6",
|
||||||
|
"ttypescript": "^1.5.13",
|
||||||
"typescript": "^4.5.4"
|
"typescript": "^4.5.4"
|
||||||
},
|
|
||||||
"_moduleAliases": {
|
|
||||||
"@logger/*": "./dist/logger/*"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +0,0 @@
|
|||||||
class InfrastructureAutoLoadable {
|
|
||||||
public load (): void {console.log("TEST");}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default new InfrastructureAutoLoadable();
|
|
||||||
10
src/app.module.ts
Normal file
10
src/app.module.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { FrameworkModule } from "#framework/framework.module";
|
||||||
|
import { Module } from "@nestjs/common";
|
||||||
|
import { PersistenceModule } from "./application/persistance.module";
|
||||||
|
import { RestModule } from "./application/rest.module";
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [RestModule, FrameworkModule, PersistenceModule]
|
||||||
|
})
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
|
||||||
|
export class AppModule {}
|
||||||
76
src/app.ts
Normal file
76
src/app.ts
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-magic-numbers */
|
||||||
|
/* eslint-disable no-console */
|
||||||
|
import clc from "cli-color";
|
||||||
|
import App, { AppCommand } from "#app";
|
||||||
|
import ConfigurationDefinition, { DefinitionType } from "#configuration/configurationDefinition";
|
||||||
|
import definitionValidators from "#configuration/configurationValidatior";
|
||||||
|
import Server from "#framework/server/server";
|
||||||
|
import getlogger, { defaultLogger } from "#logger";
|
||||||
|
|
||||||
|
const app: App = new (class extends App {
|
||||||
|
public options (setDefinitions: (...definitions: ConfigurationDefinition[]) => void): void {
|
||||||
|
setDefinitions(new ConfigurationDefinition()
|
||||||
|
.withName("port")
|
||||||
|
.withType(DefinitionType.Number)
|
||||||
|
.withArgName("port", "p")
|
||||||
|
.withEnvName("port")
|
||||||
|
.withDescription("Port of the server.")
|
||||||
|
.isRequired()
|
||||||
|
.relevantToCommands("start")
|
||||||
|
.withValidator(definitionValidators.validatePort()),
|
||||||
|
new ConfigurationDefinition()
|
||||||
|
.withName("host")
|
||||||
|
.withType(DefinitionType.String)
|
||||||
|
.withArgName("host", "h")
|
||||||
|
.withEnvName("host")
|
||||||
|
.withDefault("127.0.0.1")
|
||||||
|
.withDescription("Host name under which the server should listen for requests.")
|
||||||
|
.relevantToCommands("start")
|
||||||
|
.withValidator(definitionValidators.validateHost()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public commmands (setCommands: (...commands: AppCommand[]) => void): void {
|
||||||
|
setCommands(new (class implements AppCommand {
|
||||||
|
public getName (): string {
|
||||||
|
return "start";
|
||||||
|
}
|
||||||
|
|
||||||
|
public getDescriptions (): string {
|
||||||
|
return "Start the server.";
|
||||||
|
}
|
||||||
|
|
||||||
|
public run (): void {
|
||||||
|
const server = new Server();
|
||||||
|
const logger = getlogger("server");
|
||||||
|
server.setup().then(() => {
|
||||||
|
return server.start();
|
||||||
|
}).catch((err) => logger.error(err));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public printBanner (): void {
|
||||||
|
const crot = clc.xterm(9);
|
||||||
|
const cyellow = clc.xterm(11);
|
||||||
|
const cwhite = clc.xterm(15);
|
||||||
|
const cpurple = clc.xterm(13);
|
||||||
|
console.log(crot(" ") + cwhite("_ _ _ _ _ _ ") + cpurple(" ____ _ "));
|
||||||
|
console.log(crot(" \\ \\ ") + cwhite(" / \\ _ __ | |_| |__ (_) | | ") + cpurple("| __ ) __ _ ___| | ___ _ _ __ "));
|
||||||
|
console.log(crot(" |__/ _ .-. ") + cwhite(" / _ \\ | '_ \\| __| '_ \\| | | | ") + cpurple("| _ \\ / _` |/ __| |/ / | | | '_ \\ "));
|
||||||
|
console.log(crot("(") + cyellow("o_o") + crot(")(_`>( ) ") + cwhite(" / ___ \\| | | | |_| | | | | | |") + cpurple(" | |_) | (_| | (__| <| |_| | |_) |"));
|
||||||
|
console.log(crot(" { }//||\\\\`-' ") + cwhite(" /_/ \\_\\_| |_|\\__|_| |_|_|_|_| ") + cpurple("|____/ \\__,_|\\___|_|\\_\\\\__,_| .__/ "));
|
||||||
|
console.log(cpurple(" |_| "));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
app.execute();
|
||||||
|
} catch (error: unknown) {
|
||||||
|
if (error instanceof Error) {
|
||||||
|
defaultLogger.error(error.message);
|
||||||
|
} else {
|
||||||
|
defaultLogger.error("ssss" + error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
65
src/application/domain/repo/repo.entity.ts
Normal file
65
src/application/domain/repo/repo.entity.ts
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import { Aggregate, Identifier, IdentifierGenerator } from "#ddd";
|
||||||
|
import { randomUUID } from "crypto";
|
||||||
|
import { UserAssignment } from "./userAssignment.entity";
|
||||||
|
|
||||||
|
export class RepoId extends Identifier<string> {
|
||||||
|
private readonly _value: string;
|
||||||
|
|
||||||
|
public constructor (value: string) {
|
||||||
|
super();
|
||||||
|
this._value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get value (): string {
|
||||||
|
return this._value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default class Repo extends Aggregate<RepoId>{
|
||||||
|
|
||||||
|
private readonly _id?: RepoId;
|
||||||
|
private readonly _name: string;
|
||||||
|
|
||||||
|
private readonly _userAssignment: UserAssignment[] = [];
|
||||||
|
|
||||||
|
public constructor (id: RepoId| undefined, name: string, userAssignment: UserAssignment[]) {
|
||||||
|
super();
|
||||||
|
this._id = id;
|
||||||
|
this._name = name;
|
||||||
|
this._userAssignment = userAssignment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get id (): RepoId | undefined {
|
||||||
|
return this._id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get name (): string {
|
||||||
|
return this._name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get path (): string {
|
||||||
|
return "/" + this._name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get userAssignment (): UserAssignment[] {
|
||||||
|
return this._userAssignment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public addUserAssignment (userAssignment: UserAssignment): void {
|
||||||
|
this._userAssignment.push(userAssignment);
|
||||||
|
}
|
||||||
|
|
||||||
|
public removeUserAssignment (userAssignment: UserAssignment): void {
|
||||||
|
this._userAssignment.filter(item => item !== userAssignment);
|
||||||
|
}
|
||||||
|
|
||||||
|
// public static builder (): IBuilder<Repo> {
|
||||||
|
// return <IBuilder<Repo>> <unknown>Builder(Repo);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
export class RepoIdGenerator implements IdentifierGenerator<RepoId> {
|
||||||
|
public generate (): RepoId {
|
||||||
|
return new RepoId(randomUUID());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
6
src/application/domain/repo/repo.repo.ts
Normal file
6
src/application/domain/repo/repo.repo.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import {Repository} from "#ddd";
|
||||||
|
import Repo, { RepoId } from "./repo.entity";
|
||||||
|
|
||||||
|
export const RepoRepository = "RepoRepository";
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||||
|
export default interface RepoRepository extends Repository<RepoId, Repo> {}
|
||||||
30
src/application/domain/repo/userAssignment.entity.ts
Normal file
30
src/application/domain/repo/userAssignment.entity.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import { ValueObject } from "#ddd";
|
||||||
|
import { UserId } from "../user/user.entity";
|
||||||
|
// import { Builder, IBuilder } from "builder-pattern";
|
||||||
|
|
||||||
|
enum UserRight {
|
||||||
|
Read = "read",
|
||||||
|
AppendOnly = "append",
|
||||||
|
Write = "write"
|
||||||
|
}
|
||||||
|
|
||||||
|
export class UserAssignment extends ValueObject {
|
||||||
|
private readonly _right: UserRight;
|
||||||
|
|
||||||
|
private readonly _userId: UserId;
|
||||||
|
|
||||||
|
private constructor (userId: UserId, right: UserRight) {
|
||||||
|
super();
|
||||||
|
this._userId = userId;
|
||||||
|
this._right = right;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get id (): UserId {
|
||||||
|
return this._userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get right (): UserRight {
|
||||||
|
return this._right;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
42
src/application/domain/user/user.entity.ts
Normal file
42
src/application/domain/user/user.entity.ts
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import { Identifier, Aggregate} from "#ddd";
|
||||||
|
|
||||||
|
export default class User extends Aggregate<UserId>{
|
||||||
|
private readonly _id: UserId | undefined;
|
||||||
|
|
||||||
|
private readonly _name: string;
|
||||||
|
|
||||||
|
private readonly _password: string;
|
||||||
|
|
||||||
|
public constructor (id: UserId | undefined, name: string, password: string) {
|
||||||
|
super();
|
||||||
|
this._id = id;
|
||||||
|
this._name = name;
|
||||||
|
this._password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get id (): UserId | undefined {
|
||||||
|
return this._id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get name (): string {
|
||||||
|
return this._name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get password (): string {
|
||||||
|
return this._password;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
export class UserId extends Identifier<string> {
|
||||||
|
private readonly _value: string;
|
||||||
|
|
||||||
|
public constructor (value: string) {
|
||||||
|
super();
|
||||||
|
this._value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get value (): string {
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
5
src/application/domain/user/user.repo.ts
Normal file
5
src/application/domain/user/user.repo.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import User, { UserId } from "./user.entity";
|
||||||
|
import {Repository} from "#ddd";
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||||
|
export default interface UserRepository extends Repository<UserId, User> {}
|
||||||
@ -0,0 +1,46 @@
|
|||||||
|
import Repo, { RepoId } from "#domain/repo/repo.entity";
|
||||||
|
import RepoRepository from "#domain/repo/repo.repo";
|
||||||
|
import { Injectable } from "@nestjs/common";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export default class RepoFilePersistence implements RepoRepository {
|
||||||
|
|
||||||
|
private readonly values: Map<RepoId, Repo> = new Map();
|
||||||
|
|
||||||
|
public constructor () {
|
||||||
|
const x = new RepoId("xxxx");
|
||||||
|
const y = Repo.instantiate(x, "/xxx");
|
||||||
|
this.values.set(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public deleteAggregate (aggregate: Repo): void {
|
||||||
|
if(aggregate.id)
|
||||||
|
this.values.delete(aggregate.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public deleteAggregateById (id: RepoId): void{
|
||||||
|
this.values.delete(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getAggregate (identitiy: RepoId): Repo {
|
||||||
|
const v: Repo | undefined = this.values.get(identitiy);
|
||||||
|
if(v !== undefined)
|
||||||
|
return v;
|
||||||
|
throw new Error();
|
||||||
|
}
|
||||||
|
|
||||||
|
public getAggregates (): Repo[] {
|
||||||
|
return Array.from(this.values.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
public storeAggregate (aggregate: Repo): Repo {
|
||||||
|
let id = aggregate.id;
|
||||||
|
if(id) {
|
||||||
|
id = new RepoId("");
|
||||||
|
aggregate = Repo.instantiate(id, aggregate.path);
|
||||||
|
}
|
||||||
|
this.values.set(id as RepoId, aggregate);
|
||||||
|
return aggregate;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
import { constructUsing, createMap, forMember, mapFrom } from "@automapper/core";
|
||||||
|
import Repo, { RepoId } from "#domain/repo/repo.entity";
|
||||||
|
import { mapper } from "#framework/mapper/mapper";
|
||||||
|
|
||||||
|
export class RepoDto {
|
||||||
|
public id!: string;
|
||||||
|
public path!: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
createMap(mapper, Repo, RepoDto, forMember(
|
||||||
|
(destination: RepoDto) => destination.id, mapFrom(s => s.id?.value)
|
||||||
|
));
|
||||||
|
|
||||||
|
createMap(mapper, RepoDto, Repo,
|
||||||
|
constructUsing((sourceObject, _destinationIdentifier): Repo => {
|
||||||
|
return new Repo(new RepoId(sourceObject.id), sourceObject.path);
|
||||||
|
})
|
||||||
|
);
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
|
||||||
|
import Repo from "#domain/repo/repo.entity";
|
||||||
|
import Repository, { RepoRepository } from "#domain/repo/repo.repo";
|
||||||
|
import { mapper } from "#framework/mapper/mapper";
|
||||||
|
import { Body, Controller, Get, Inject, Post, UseGuards } from "@nestjs/common";
|
||||||
|
import { AuthGuard } from "@nestjs/passport";
|
||||||
|
import { RepoDto } from "./dtos/repo.dto";
|
||||||
|
|
||||||
|
@Controller("api/management")
|
||||||
|
export class ManagementController {
|
||||||
|
@Inject(RepoRepository)
|
||||||
|
private readonly repos!: Repository;
|
||||||
|
|
||||||
|
@Post()
|
||||||
|
@UseGuards(AuthGuard("basic"))
|
||||||
|
public create (@Body() repo: RepoDto): RepoDto {
|
||||||
|
console.log(repo);
|
||||||
|
console.log(mapper.map(repo, RepoDto, Repo));
|
||||||
|
return new RepoDto();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get()
|
||||||
|
@UseGuards(AuthGuard("basic"))
|
||||||
|
public findAll (): RepoDto[] {
|
||||||
|
console.log(this.repos.getAggregates());
|
||||||
|
console.log(mapper.mapArray<Repo, RepoDto>(this.repos.getAggregates(), Repo, RepoDto));
|
||||||
|
return mapper.mapArray<Repo, RepoDto>(this.repos.getAggregates(), Repo, RepoDto);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
import { Controller, Get } from "@nestjs/common";
|
||||||
|
|
||||||
|
@Controller("repo")
|
||||||
|
export class RepoController {
|
||||||
|
|
||||||
|
@Get()
|
||||||
|
public findAll (): string {
|
||||||
|
return "This action returns all cats";
|
||||||
|
}
|
||||||
|
}
|
||||||
16
src/application/persistance.module.ts
Normal file
16
src/application/persistance.module.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-extraneous-class */
|
||||||
|
|
||||||
|
import {RepoRepository} from "#domain/repo/repo.repo";
|
||||||
|
import { Module } from "@nestjs/common";
|
||||||
|
import RepoFilePersistence from "./infrastructure/persistence/file/repo.persistence";
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
providers: [
|
||||||
|
{
|
||||||
|
useClass: RepoFilePersistence,
|
||||||
|
provide: RepoRepository
|
||||||
|
}
|
||||||
|
],
|
||||||
|
exports: [RepoRepository]
|
||||||
|
})
|
||||||
|
export class PersistenceModule {}
|
||||||
12
src/application/rest.module.ts
Normal file
12
src/application/rest.module.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-extraneous-class */
|
||||||
|
|
||||||
|
import { Module } from "@nestjs/common";
|
||||||
|
import { ManagementController } from "./infrastructure/presentation/rest/management.controller";
|
||||||
|
import { RepoController } from "./infrastructure/presentation/rest/repo.controller";
|
||||||
|
import { PersistenceModule } from "./persistance.module";
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
controllers: [ManagementController, RepoController],
|
||||||
|
imports: [PersistenceModule]
|
||||||
|
})
|
||||||
|
export class RestModule {}
|
||||||
77
src/framework/app/app.ts
Normal file
77
src/framework/app/app.ts
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
|
||||||
|
/* eslint-disable @typescript-eslint/no-magic-numbers */
|
||||||
|
/* eslint-disable no-console */
|
||||||
|
import configuration, {initConfiguration} from "#configuration";
|
||||||
|
import ConfigurationDefinition from "#configuration/configurationDefinition";
|
||||||
|
import getLogger from "#logger";
|
||||||
|
import { Logger } from "winston";
|
||||||
|
import AppHelp from "./appHelp";
|
||||||
|
|
||||||
|
export abstract class AppCommand {
|
||||||
|
public abstract getDescriptions (): string;
|
||||||
|
public abstract run (): void;
|
||||||
|
|
||||||
|
public abstract getName (): string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default abstract class App {
|
||||||
|
|
||||||
|
private readonly commands: Map<string, AppCommand> = new Map();
|
||||||
|
private readonly appHelp: AppHelp;
|
||||||
|
private readonly logger: Logger;
|
||||||
|
|
||||||
|
public constructor () {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
||||||
|
const that = this;
|
||||||
|
this.appHelp = new AppHelp();
|
||||||
|
this.logger = getLogger("app");
|
||||||
|
this.addCommmand(new (class implements AppCommand {
|
||||||
|
public getName (): string {
|
||||||
|
return "help";
|
||||||
|
}
|
||||||
|
|
||||||
|
public getDescriptions (): string {
|
||||||
|
return "Show help for this application.";
|
||||||
|
}
|
||||||
|
|
||||||
|
public run (): void {
|
||||||
|
that.appHelp.printHelp(that.commands);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* It executes the commands and options.
|
||||||
|
*/
|
||||||
|
public execute (): void {
|
||||||
|
this.commmands((...definitions): void => {
|
||||||
|
for (const definition of definitions) {
|
||||||
|
this.addCommmand(definition);
|
||||||
|
}
|
||||||
|
console.log();
|
||||||
|
});
|
||||||
|
this.options((...defs): void => {
|
||||||
|
initConfiguration("XXX", ...defs);
|
||||||
|
});
|
||||||
|
this.printBanner();
|
||||||
|
configuration().validate();
|
||||||
|
const name = configuration().getCommand();
|
||||||
|
const command = this.commands.get(name);
|
||||||
|
this.logger.info("Starting App with command '" + name + "'");
|
||||||
|
if(command) {
|
||||||
|
command.run();
|
||||||
|
} else {
|
||||||
|
throw new Error(name + " is not implemented");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private addCommmand (command: AppCommand): void {
|
||||||
|
this.commands.set(command.getName(), command);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract options (setDefinitions: (...definitions: ConfigurationDefinition[]) => void): void;
|
||||||
|
|
||||||
|
public abstract commmands (setCommands: (...commands: AppCommand[]) => void): void;
|
||||||
|
public abstract printBanner (): void;
|
||||||
|
|
||||||
|
}
|
||||||
110
src/framework/app/appHelp.ts
Normal file
110
src/framework/app/appHelp.ts
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-magic-numbers */
|
||||||
|
/* eslint-disable no-console */
|
||||||
|
|
||||||
|
import configuration from "#configuration";
|
||||||
|
import clc from "cli-color";
|
||||||
|
import ConfigurationDefinition from "#configuration/configurationDefinition";
|
||||||
|
import { AppCommand } from "#app";
|
||||||
|
|
||||||
|
/* The `AppHelp` class is responsible for printing out the help message */
|
||||||
|
export default class AppHelp {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints the help message
|
||||||
|
* @param commands - A map of all the commands that the program can run.
|
||||||
|
*/
|
||||||
|
public printHelp (commands: Map<string, AppCommand>): void {
|
||||||
|
const programm = process.argv.slice(0, 2).join(" ");
|
||||||
|
const underline = clc.underline;
|
||||||
|
console.log(underline("Usage")+"\n");
|
||||||
|
console.log("\t"+ programm + " [COMMAND] [OPTIONS]"+"\n");
|
||||||
|
console.log(underline("Commands")+"\n");
|
||||||
|
this.printCommands(commands);
|
||||||
|
console.log();
|
||||||
|
console.log(underline("Options"));
|
||||||
|
console.log();
|
||||||
|
this.printOptions((def) => def.getCommands().length >= 1);
|
||||||
|
console.log();
|
||||||
|
console.log(underline("Rules & Behavior"));
|
||||||
|
console.log();
|
||||||
|
this.printOptions((def) => def.getCommands().length == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints all commands and their descriptions
|
||||||
|
* @param commands - Map<string, AppCommand>
|
||||||
|
*/
|
||||||
|
private printCommands (commands: Map<string, AppCommand>): void {
|
||||||
|
commands.forEach((v, k, _m) => {
|
||||||
|
console.log("\t" + k + " - " + v.getDescriptions());
|
||||||
|
const paramaters: string[] = [];
|
||||||
|
// Find parameters for current command
|
||||||
|
for (const def of this.getConfigurationDefinitions()) {
|
||||||
|
if (def.getCommands().includes(k)) {
|
||||||
|
paramaters.push(this.generateParameters(def));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log("\t↳ " + k + " " + paramaters.join(" "));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints out all the options that are available to the user
|
||||||
|
* @param condition - Select witch options are printed.
|
||||||
|
*/
|
||||||
|
private printOptions (condition: (a: ConfigurationDefinition) => boolean): void {
|
||||||
|
let maxLength = 0;
|
||||||
|
/* Find longest String */
|
||||||
|
for (const def of this.getConfigurationDefinitions()) {
|
||||||
|
if (condition(def)) {
|
||||||
|
const option = " -" + def.getArgName().sort((a, b) => a.length - b.length).join(" -");
|
||||||
|
maxLength = Math.max(maxLength, option.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const def of this.getConfigurationDefinitions()) {
|
||||||
|
if (condition(def)) {
|
||||||
|
const option = " -" + def.getArgName().sort((a, b) => a.length - b.length).join(" -");
|
||||||
|
console.log("\t↳ " + (option.padEnd(maxLength, " ")) + " - " + def.getDescription());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate the parameters for the command line help
|
||||||
|
* @param {ConfigurationDefinition} def - ConfigurationDefinition
|
||||||
|
* @returns The `generateParameters` function returns a string that represents the parameters that are
|
||||||
|
* being passed to the `CommandLine` object.
|
||||||
|
*/
|
||||||
|
private generateParameters (def: ConfigurationDefinition): string {
|
||||||
|
const args: string[] = [];
|
||||||
|
for (const argParam of def.getArgName()) {
|
||||||
|
if (argParam.length === 1)
|
||||||
|
args.push("-" + argParam + " <" + def.getName() + ">");
|
||||||
|
else
|
||||||
|
args.push("--" + argParam + " <" + def.getName() + ">");
|
||||||
|
}
|
||||||
|
let paramater = args.join(" | ");
|
||||||
|
if (def.getArgName().length > 1)
|
||||||
|
paramater = "(" + paramater + ")";
|
||||||
|
if (!def.getRequired())
|
||||||
|
paramater = "[" + paramater + "]";
|
||||||
|
return paramater;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the configuration definitions from the configuration object
|
||||||
|
* @returns The configuration definitions are being returned.
|
||||||
|
*/
|
||||||
|
private getConfigurationDefinitions (): ConfigurationDefinition[] {
|
||||||
|
return configuration().getDefinitions().sort((a, b) => {
|
||||||
|
if (a.getRequired() && !b.getRequired())
|
||||||
|
return -1;
|
||||||
|
else if (!a.getRequired() && b.getRequired())
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
else
|
||||||
|
return a.getName() < b.getName() ? -1 : 1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
23
src/framework/auth/auth-basic.strategy.ts
Normal file
23
src/framework/auth/auth-basic.strategy.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
|
||||||
|
import { BasicStrategy as Strategy } from "passport-http";
|
||||||
|
import { Injectable, UnauthorizedException } from "@nestjs/common";
|
||||||
|
import { PassportStrategy } from "@nestjs/passport";
|
||||||
|
import { FastifyRequest } from "fastify";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class BasicStrategy extends PassportStrategy(Strategy) {
|
||||||
|
public constructor () {
|
||||||
|
super({
|
||||||
|
passReqToCallback: true,
|
||||||
|
realm: "XXXXX"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/require-await
|
||||||
|
public async validate (req: FastifyRequest, username: string, password: string): Promise<boolean> {
|
||||||
|
if (username === "test" && password === "abc") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
throw new UnauthorizedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
116
src/framework/configuration/ConfigurationDefinition.ts
Normal file
116
src/framework/configuration/ConfigurationDefinition.ts
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
import { DefinitionValidator } from "./configurationValidatior";
|
||||||
|
|
||||||
|
export enum DefinitionType {
|
||||||
|
String = "string",
|
||||||
|
Boolean = "boolean",
|
||||||
|
File = "file",
|
||||||
|
Number = "number"
|
||||||
|
}
|
||||||
|
|
||||||
|
class ConfigurationDefinition implements ConfigurationDefinition {
|
||||||
|
private name!: string;
|
||||||
|
private envName!: string;
|
||||||
|
private argName!: string[];
|
||||||
|
private validator!: DefinitionValidator;
|
||||||
|
private description!: string;
|
||||||
|
private type!: DefinitionType;
|
||||||
|
private multiple = false;
|
||||||
|
private required = false;
|
||||||
|
private commands: string[] = [];
|
||||||
|
private defaultValue: string | undefined = undefined;
|
||||||
|
|
||||||
|
public getName (): string {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getEnvName (): string {
|
||||||
|
return this.envName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getArgName (): string[] {
|
||||||
|
return this.argName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getValidator (): DefinitionValidator {
|
||||||
|
return this.validator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getDescription (): string {
|
||||||
|
return this.description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getType (): DefinitionType {
|
||||||
|
return this.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getRequired (): boolean {
|
||||||
|
return this.required;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getMultiple (): boolean {
|
||||||
|
return this.multiple;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getCommands (): string[] {
|
||||||
|
return this.commands;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getDefaultValue (): string[] | undefined {
|
||||||
|
if(this.defaultValue) {
|
||||||
|
return [this.defaultValue];
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
public withName (name: string): ConfigurationDefinition {
|
||||||
|
this.name = name;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public withEnvName (envName: string): ConfigurationDefinition {
|
||||||
|
this.envName = envName;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public withArgName (...argName: string[]): ConfigurationDefinition {
|
||||||
|
this.argName = argName;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public withValidator (validator: DefinitionValidator): ConfigurationDefinition {
|
||||||
|
this.validator = validator;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public withDescription (description: string): ConfigurationDefinition {
|
||||||
|
this.description = description;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public withDefault (defaultValue: string): ConfigurationDefinition {
|
||||||
|
this.defaultValue = defaultValue;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public withType (type: DefinitionType): ConfigurationDefinition {
|
||||||
|
this.type = type;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public relevantToCommands (...commands: string[]): ConfigurationDefinition {
|
||||||
|
this.commands = commands;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public isRequired (): ConfigurationDefinition {
|
||||||
|
this.required = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public isMultiple (): ConfigurationDefinition {
|
||||||
|
this.multiple = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ConfigurationDefinition;
|
||||||
190
src/framework/configuration/configuration.ts
Normal file
190
src/framework/configuration/configuration.ts
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
import ConfigurationDefinition, {DefinitionType} from "./configurationDefinition";
|
||||||
|
import {parser, ArgCollection} from "args-command-parser";
|
||||||
|
|
||||||
|
class Configuration {
|
||||||
|
|
||||||
|
private readonly definitions: Map<string, ConfigurationDefinition> = new Map();
|
||||||
|
private readonly values: Map<string, string[] | undefined> = new Map();
|
||||||
|
private readonly defaultCommand: string;
|
||||||
|
private readonly envPrefix: string;
|
||||||
|
private readonly arguments: ArgCollection;
|
||||||
|
public constructor (defaultCommand: string, envPrefix: string, ...definitions: ConfigurationDefinition[]) {
|
||||||
|
this.arguments = parser();
|
||||||
|
for (const definition of definitions) {
|
||||||
|
this.definitions.set(definition.getName(), definition);
|
||||||
|
this.values.set(definition.getName(), this.getInternalValue(definition));
|
||||||
|
}
|
||||||
|
this.defaultCommand = defaultCommand;
|
||||||
|
this.envPrefix = envPrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public validate (): void {
|
||||||
|
this.definitions.forEach((v, _k, _m) => {
|
||||||
|
const def = v;
|
||||||
|
const values = this.values.get(def.getName()) ?? [];
|
||||||
|
if(!def.getMultiple() && values.length > 1)
|
||||||
|
throw new Error("No more than one value may be assigned to parameter '" + def.getName() + "'.");
|
||||||
|
if(def.getRequired() && (def.getCommands().length === 0 || def.getCommands().includes(this.getCommand())) && values.length === 0)
|
||||||
|
throw new Error("Parameter '" + def.getName() + "' is required.");
|
||||||
|
for (const value of values) {
|
||||||
|
if(!def.getValidator().validate(value))
|
||||||
|
throw new Error("Parameter '" + def.getName() + "' does not meet the requirements: " + def.getValidator().description());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public getDefinitions (): ConfigurationDefinition[] {
|
||||||
|
return Array.from(this.definitions.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the command from the arguments
|
||||||
|
* @returns The command that was passed in the arguments.
|
||||||
|
*/
|
||||||
|
public getCommand (): string {
|
||||||
|
if(this.arguments.data.commands.length >= 1)
|
||||||
|
return this.arguments.data.commands[0];
|
||||||
|
else
|
||||||
|
return this.defaultCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of a parameter
|
||||||
|
* @param {string} name - The name of the parameter.
|
||||||
|
* @returns The value of the parameter.
|
||||||
|
*/
|
||||||
|
public getValue (name: string): string | string[] | boolean | boolean[] | number | number[] | undefined {
|
||||||
|
const def = this.definitions.get(name);
|
||||||
|
const value = this.values.get(name) ?? [];
|
||||||
|
switch ( def?.getType() ) {
|
||||||
|
case DefinitionType.Boolean: {
|
||||||
|
const result = this.toBoolean(value);
|
||||||
|
if(def.getMultiple()) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return result[0];
|
||||||
|
}
|
||||||
|
case DefinitionType.Number: {
|
||||||
|
const result: number[] = this.toInteger(value);
|
||||||
|
if(def.getMultiple()) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return result[0];
|
||||||
|
}
|
||||||
|
case DefinitionType.String: {
|
||||||
|
if(def.getMultiple()) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return value[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of a boolean parameter
|
||||||
|
* @param {string} name - The name of the parameter.
|
||||||
|
* @returns The value of the parameter.
|
||||||
|
*/
|
||||||
|
public getBooleanValue (name: string): boolean | boolean[] | undefined {
|
||||||
|
const def = this.definitions.get(name);
|
||||||
|
if(def?.getType() == DefinitionType.Boolean) {
|
||||||
|
const value = this.values.get(name) ?? [];
|
||||||
|
const result: boolean[] = this.toBoolean(value);
|
||||||
|
if(def.getMultiple()) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return result[0];
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getNumberValue (name: string): number | number[] | undefined {
|
||||||
|
const def = this.definitions.get(name);
|
||||||
|
if(def?.getType() == DefinitionType.Number) {
|
||||||
|
const value = this.values.get(name) ?? [];
|
||||||
|
const result: number[] = this.toInteger(value);
|
||||||
|
if(def.getMultiple()) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return result[0];
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getStringValue (name: string): string | string[] | undefined {
|
||||||
|
const def = this.definitions.get(name);
|
||||||
|
if(def?.getType() == DefinitionType.String) {
|
||||||
|
const value = this.values.get(name) ?? [];
|
||||||
|
if(def.getMultiple()) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return value[0];
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Convert a string array to a boolean array
|
||||||
|
* @param {string[]} value - The value of the parameter.
|
||||||
|
* @returns The `toBoolean` function returns an array of booleans.
|
||||||
|
*/
|
||||||
|
|
||||||
|
private toBoolean (value: string[]): boolean[] {
|
||||||
|
const result: boolean[] = [];
|
||||||
|
for (const v of value) {
|
||||||
|
result.push(v === "true" || v === "1" || v === "y");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* It takes an array of strings and returns an array of numbers.
|
||||||
|
* @param {string[]} value - The value of the parameter.
|
||||||
|
* @returns The `toInteger` function returns an array of numbers.
|
||||||
|
*/
|
||||||
|
private toInteger (value: string[]): number[] {
|
||||||
|
const result: number[] = [];
|
||||||
|
for (const v of value) {
|
||||||
|
const f = parseFloat(v); const i = parseInt(v);
|
||||||
|
result.push((f == i) ? i : f);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private getInternalValue (def: ConfigurationDefinition): string[] | undefined {
|
||||||
|
let value = this.getArgValue(def);
|
||||||
|
value = (value === undefined)?this.getEnvValue(def):value;
|
||||||
|
value = (value === undefined)?def.getDefaultValue():value;
|
||||||
|
if(value !== undefined) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
private getEnvValue (def: ConfigurationDefinition): string[] | undefined {
|
||||||
|
const value = process.env[this.envPrefix + "_" + def.getEnvName().toUpperCase()];
|
||||||
|
if(value !== undefined)
|
||||||
|
return [value];
|
||||||
|
else
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
private getArgValue (def: ConfigurationDefinition): string[] | undefined{
|
||||||
|
for (const arg of def.getArgName()) {
|
||||||
|
if(arg.length >= 2 && this.arguments.hasLongSwitch(arg)) {
|
||||||
|
return this.arguments.getLongSwitch(arg).values;
|
||||||
|
} else if (this.arguments.hasShortSwitch(arg)) {
|
||||||
|
return this.arguments.getShortSwitch(arg).values;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let configInstance: Configuration;
|
||||||
|
|
||||||
|
export function initConfiguration (envPrefix: string, ...definitions: ConfigurationDefinition[]): void {
|
||||||
|
configInstance = new Configuration("help", envPrefix, ...definitions);
|
||||||
|
}
|
||||||
|
export default function config (): Configuration {
|
||||||
|
return configInstance;
|
||||||
|
}
|
||||||
56
src/framework/configuration/configurationValidatior.ts
Normal file
56
src/framework/configuration/configurationValidatior.ts
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
export abstract class DefinitionValidator {
|
||||||
|
public abstract validate (value: string): boolean;
|
||||||
|
public abstract description (): string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const definitionValidators = {
|
||||||
|
validateBoolean (): DefinitionValidator {
|
||||||
|
return new (class implements DefinitionValidator {
|
||||||
|
public description (): string {
|
||||||
|
return "Parameter must be a boolean value.";
|
||||||
|
}
|
||||||
|
|
||||||
|
public validate (value: string): boolean {
|
||||||
|
return (value === "true" || value === "1" || value === "y" || value === "false" || value === "0" || value === "n");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
validateNumber (): DefinitionValidator {
|
||||||
|
return new (class implements DefinitionValidator {
|
||||||
|
public description (): string {
|
||||||
|
return "Parameter must be a numeric value.";
|
||||||
|
}
|
||||||
|
|
||||||
|
public validate (value: string): boolean {
|
||||||
|
return /^[+-]?([0-9]*[.])?[0-9]+$/.exec(value) !== null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
validatePort (): DefinitionValidator {
|
||||||
|
return new (class implements DefinitionValidator {
|
||||||
|
public description (): string {
|
||||||
|
return "Parameter must be valid port (1-65535).";
|
||||||
|
}
|
||||||
|
|
||||||
|
public validate (value: string): boolean {
|
||||||
|
const maxPort = 65535;
|
||||||
|
return (/^[0-9]*$/.exec(value) !== null) && parseInt(value) >= 1 && parseInt(value) <= maxPort;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
validateHost (): DefinitionValidator {
|
||||||
|
return new (class implements DefinitionValidator {
|
||||||
|
public description (): string {
|
||||||
|
return "Hostname musst be a IP-Adress or a valid Hostname.";
|
||||||
|
}
|
||||||
|
|
||||||
|
public validate (value: string): boolean {
|
||||||
|
const regexIPv6 = /(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))/gi;
|
||||||
|
const regexIPv4 = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
|
||||||
|
const regexHost = /^(([a-zA-Z0-9]*)|([a-zA-Z0-9]*\.)*([a-zA-Z]+))$/;
|
||||||
|
return (regexHost.exec(value) !== null) || (regexIPv4.exec(value) !== null) || (regexIPv6.exec(value) !== null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
export default definitionValidators;
|
||||||
41
src/framework/ddd/ddd.types.ts
Normal file
41
src/framework/ddd/ddd.types.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
export abstract class Entity<I extends Identifier<unknown>> {
|
||||||
|
public abstract get id (): I | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
|
||||||
|
export abstract class ValueObject {}
|
||||||
|
|
||||||
|
export abstract class Identifier<Type> {
|
||||||
|
public abstract get value (): Type;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export abstract class IdentifierGenerator<I extends Identifier<unknown>> {
|
||||||
|
|
||||||
|
public abstract generate (): I;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export abstract class Aggregate<I extends Identifier<unknown>> extends Entity<I> {}
|
||||||
|
|
||||||
|
export interface ReadRepository<I extends Identifier<unknown>, A extends Aggregate<I>> {
|
||||||
|
|
||||||
|
getAggregate(identitiy: I): A;
|
||||||
|
getAggregates(): Array<A>;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface WriteRepository<I extends Identifier<unknown>, A extends Aggregate<I>> {
|
||||||
|
|
||||||
|
storeAggregate(aggregate: A): A;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DeleteRepository<I extends Identifier<unknown>, A extends Aggregate<I>> {
|
||||||
|
|
||||||
|
deleteAggregate(aggregate: A): void;
|
||||||
|
deleteAggregateById(identitiy: I): void;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Repository<I extends Identifier<unknown>, A extends Aggregate<I>> extends ReadRepository<I, A>, WriteRepository<I, A>, DeleteRepository<I, A>{}
|
||||||
10
src/framework/framework.module.ts
Normal file
10
src/framework/framework.module.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { Module } from "@nestjs/common";
|
||||||
|
import { BasicStrategy } from "./auth/auth-basic.strategy";
|
||||||
|
import { PassportModule } from "@nestjs/passport";
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [PassportModule],
|
||||||
|
providers: [BasicStrategy],
|
||||||
|
})
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
|
||||||
|
export class FrameworkModule {}
|
||||||
@ -70,24 +70,36 @@ export const plugin: FastifyPluginAsync<FastifyRequestLoggerOptions> = async (fa
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const ifExists = (prefix: string, value: string): string => {
|
||||||
|
if(value.length >= 1) {
|
||||||
|
if(prefix.length >= 1) {
|
||||||
|
return prefix + " " + value;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
};
|
||||||
|
|
||||||
fastify.addHook("onRequest", async (request) => {
|
fastify.addHook("onRequest", async (request) => {
|
||||||
if (isIgnoredRequest(request)) {
|
if (isIgnoredRequest(request)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const id = request.id;
|
const id = request.id;
|
||||||
const method = request.method;
|
const method = request.method;
|
||||||
const referrer = (request.headers["Referer"] ?? (request.headers["referer"]) ?? request.headers["Refferer"]) ?? request.headers["refferer"];
|
const referrer = (request.headers["Referer"] ?? (request.headers["referer"]) ?? request.headers["Refferer"]) ?? request.headers["refferer"] ?? "none";
|
||||||
const remoteAddr = request.ip;
|
const remoteAddr = request.ip;
|
||||||
const remoteUser = "???";
|
const remoteUser = "???";
|
||||||
const url = request.url;
|
const url = request.url;
|
||||||
const httpVersion = request.raw.httpVersion;
|
const httpVersion = request.raw.httpVersion;
|
||||||
const userAgent = request.headers["User-Agents"];
|
const userAgent = request.headers["User-Agents"];
|
||||||
const contentLength = request.headers["content-length"];
|
const contentLength = request.headers["content-length"] ?? "";
|
||||||
|
|
||||||
request.log.info(`${chalk.bold.yellow("→")} ${chalk.yellow(method)} ${chalk.green(url)} HTTP/${httpVersion} - ${chalk.blue(remoteAddr)} ${remoteUser} - ${referrer} - ${contentLength} bytes [${id}]`);
|
console.log(JSON.stringify(request.headers));
|
||||||
request.log.trace(`${chalk.bold.yellow("→")} ${chalk.yellow(method)} ${chalk.green(url)} ${userAgent} [${id}]`);
|
|
||||||
|
request.log.info(`${chalk.bold.yellow("→")} ${chalk.yellow(method)} ${chalk.green(url)} HTTP/${httpVersion} - ${chalk.blue(remoteAddr)} ${ifExists("", remoteUser)} - ${referrer} ${ifExists("-", contentLength+" bytes")} [${chalk.greenBright(id)}]`);
|
||||||
|
request.log.trace(`${chalk.bold.yellow("→")} ${chalk.yellow(method)} ${chalk.green(url)} ${userAgent} [${chalk.greenBright(id)}]`);
|
||||||
request.log.info(
|
request.log.info(
|
||||||
`${chalk.bold.yellow("←")}${chalk.yellow(request.method)}:${chalk.green(
|
`${chalk.bold.yellow("← ")}${chalk.yellow(request.method)}:${chalk.green(
|
||||||
request.url
|
request.url
|
||||||
)} request from ip ${chalk.blue(request.ip)}${
|
)} request from ip ${chalk.blue(request.ip)}${
|
||||||
contentLength ? ` with a ${chalk.yellow(contentLength)}-length body` : ""
|
contentLength ? ` with a ${chalk.yellow(contentLength)}-length body` : ""
|
||||||
|
|||||||
@ -5,7 +5,7 @@ const { combine, timestamp, label, printf, errors, splat } = format;
|
|||||||
|
|
||||||
// Custom logging format
|
// Custom logging format
|
||||||
const customFormat = printf(({ level, message, label, timestamp, stack }) => {
|
const customFormat = printf(({ level, message, label, timestamp, stack }) => {
|
||||||
return `${level}\t ${timestamp} · ${label || "-"}: ${message} ${stack || ""}`;
|
return `${level}\t ${timestamp} · ${label || "-"} \t· ${message} ${stack || ""}`;
|
||||||
});
|
});
|
||||||
|
|
||||||
const myCustomLevels = {
|
const myCustomLevels = {
|
||||||
|
|||||||
28
src/framework/logger/nestLogger.ts
Normal file
28
src/framework/logger/nestLogger.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
|
||||||
|
import { LoggerService } from "@nestjs/common";
|
||||||
|
import getlogger from "./logger";
|
||||||
|
|
||||||
|
const logger = getlogger("nest");
|
||||||
|
export default class NestLogger implements LoggerService {
|
||||||
|
|
||||||
|
public log (message: any, ...optionalParams: any[]): void {
|
||||||
|
logger.info(message, optionalParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
public error (message: any, ...optionalParams: any[]): void {
|
||||||
|
logger.error(message, optionalParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
public warn (message: any, ...optionalParams: any[]): void {
|
||||||
|
logger.warning(message, optionalParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
public debug (message: any, ...optionalParams: any[]): void {
|
||||||
|
logger.debug(message, optionalParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
public verbose (message: any, ...optionalParams: any[]): void {
|
||||||
|
logger.verbose(message, optionalParams);
|
||||||
|
}
|
||||||
|
}
|
||||||
7
src/framework/mapper/mapper.ts
Normal file
7
src/framework/mapper/mapper.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { CamelCaseNamingConvention, createMapper } from "@automapper/core";
|
||||||
|
import { classes } from "@automapper/classes";
|
||||||
|
|
||||||
|
export const mapper = createMapper({
|
||||||
|
strategyInitializer: classes(),
|
||||||
|
namingConventions: new CamelCaseNamingConvention()
|
||||||
|
});
|
||||||
67
src/framework/server/server.ts
Normal file
67
src/framework/server/server.ts
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import fastifySensible from "fastify-sensible";
|
||||||
|
import GracefulServer from "@gquittet/graceful-server";
|
||||||
|
import getlogger from "#logger";
|
||||||
|
import {fastifyLogger, fastifyRequestLogger} from "#logger/fastifyLogger";
|
||||||
|
import { Logger } from "winston";
|
||||||
|
import IGracefulServer from "@gquittet/graceful-server/lib/types/interface/gracefulServer";
|
||||||
|
import configuration from "#configuration";
|
||||||
|
import { NestFactory } from "@nestjs/core";
|
||||||
|
import { FastifyAdapter, NestFastifyApplication } from "@nestjs/platform-fastify";
|
||||||
|
import { AppModule } from "../../app.module";
|
||||||
|
import NestLogger from "#framework/logger/nestLogger";
|
||||||
|
|
||||||
|
export default class Server {
|
||||||
|
private readonly logger: Logger;
|
||||||
|
private gracefulServer: IGracefulServer | undefined;
|
||||||
|
private nest: NestFastifyApplication | undefined;
|
||||||
|
public constructor () {
|
||||||
|
this.logger = getlogger("fastify");
|
||||||
|
}
|
||||||
|
|
||||||
|
public async start (): Promise<void> {
|
||||||
|
const start = async (): Promise<void> => {
|
||||||
|
try {
|
||||||
|
const port = <number>configuration().getNumberValue("port");
|
||||||
|
const host = <string>configuration().getStringValue("host");
|
||||||
|
this.logger.info("Start server on port " + host + ":" + port);
|
||||||
|
await this.nest?.listen(port, host);
|
||||||
|
this.gracefulServer?.setReady();
|
||||||
|
} catch (err) {
|
||||||
|
this.logger.error(err);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
await start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async setup (): Promise<void> {
|
||||||
|
this.nest = await NestFactory.create<NestFastifyApplication>(
|
||||||
|
AppModule,
|
||||||
|
new FastifyAdapter({
|
||||||
|
logger: fastifyLogger,
|
||||||
|
disableRequestLogging: true
|
||||||
|
}), {
|
||||||
|
logger: new NestLogger(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
await this.nest.register(fastifySensible);
|
||||||
|
await this.nest.register(fastifyRequestLogger);
|
||||||
|
|
||||||
|
this.gracefulServer = GracefulServer(this.nest.getHttpServer());
|
||||||
|
|
||||||
|
this.gracefulServer.on(GracefulServer.READY, () => {
|
||||||
|
this.logger.info("Server is ready");
|
||||||
|
});
|
||||||
|
|
||||||
|
this.gracefulServer.on(GracefulServer.SHUTTING_DOWN, () => {
|
||||||
|
this.logger.info("Server is shutting down");
|
||||||
|
});
|
||||||
|
|
||||||
|
this.gracefulServer.on(GracefulServer.SHUTDOWN, () => {
|
||||||
|
this.logger.info("Server is down");
|
||||||
|
process.exit();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -1,45 +0,0 @@
|
|||||||
import Fastify from "fastify";
|
|
||||||
import fastifySensible from "fastify-sensible";
|
|
||||||
import GracefulServer from "@gquittet/graceful-server";
|
|
||||||
import getlogger from "@logger";
|
|
||||||
import {fastifyLogger, fastifyRequestLogger} from "@logger/fastifyLogger";
|
|
||||||
|
|
||||||
const fastify = Fastify({
|
|
||||||
logger: fastifyLogger,
|
|
||||||
disableRequestLogging: true
|
|
||||||
});
|
|
||||||
await fastify.register(fastifyRequestLogger, {logBody: true});
|
|
||||||
await fastify.register(fastifySensible);
|
|
||||||
|
|
||||||
const gracefulServer = GracefulServer(fastify.server);
|
|
||||||
|
|
||||||
gracefulServer.on(GracefulServer.READY, () => {
|
|
||||||
getlogger("server").info("Server is ready");
|
|
||||||
});
|
|
||||||
|
|
||||||
gracefulServer.on(GracefulServer.SHUTTING_DOWN, () => {
|
|
||||||
getlogger("server").info("Server is shutting down");
|
|
||||||
});
|
|
||||||
|
|
||||||
gracefulServer.on(GracefulServer.SHUTDOWN, (error: {message: string}) => {
|
|
||||||
getlogger("server").info("Server is down because of", error.message);
|
|
||||||
process.exit();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Declare a route
|
|
||||||
fastify.get("/", function (request, reply) {
|
|
||||||
void reply.send({ hello: "world" });
|
|
||||||
});
|
|
||||||
|
|
||||||
// Run the server!
|
|
||||||
const start = async (): Promise<void> => {
|
|
||||||
try {
|
|
||||||
const port = 3000;
|
|
||||||
await fastify.listen(port);
|
|
||||||
gracefulServer.setReady();
|
|
||||||
} catch (err) {
|
|
||||||
fastify.log.error(err);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
await start();
|
|
||||||
@ -1,19 +1,36 @@
|
|||||||
{
|
{
|
||||||
"extends": "@tsconfig/node16/tsconfig.json",
|
"extends": "@tsconfig/node16/tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"typeRoots": ["./node_modules/@types"],
|
"typeRoots": ["./node_modules/@types"],
|
||||||
"target": "ESNext",
|
"target": "ESNext",
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"outDir": "./dist/",
|
"outDir": "./dist/",
|
||||||
"baseUrl": "./src/",
|
"baseUrl": "./src/",
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"emitDecoratorMetadata": true,
|
||||||
"paths": {
|
"paths": {
|
||||||
"@abc/*": ["abc/*"],
|
"#ddd": ["framework/ddd/ddd.types"],
|
||||||
"@logger": ["framework/logger/logger"],
|
"#framework/*": ["framework/*"],
|
||||||
"@logger/*": ["framework/logger/*"]
|
"#logger": ["framework/logger/logger"],
|
||||||
}
|
"#logger/*": ["framework/logger/*"],
|
||||||
|
"#configuration": ["framework/configuration/configuration"],
|
||||||
|
"#configuration/*": ["framework/configuration/*"],
|
||||||
|
"#app": ["framework/app/app"],
|
||||||
|
"#domain/*": ["application/domain/*"]
|
||||||
|
},
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"transform": "@automapper/classes/transformer-plugin",
|
||||||
|
"modelFileNameSuffix": [".types.js", ".entity.ts", ".dto.ts"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"tsc-alias": {
|
||||||
|
"verbose": true,
|
||||||
|
"resolveFullPaths": true
|
||||||
},
|
},
|
||||||
"include": ["src/**/*.ts"],
|
"include": ["src/**/*.ts"],
|
||||||
"exclude": ["node_modules"]
|
"exclude": ["node_modules"]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user