From 5db6de193aaeaf7a88b7e4ce675ca76cda7a50c3 Mon Sep 17 00:00:00 2001 From: AnthonyLzq Date: Mon, 31 Jul 2023 16:42:59 -0500 Subject: [PATCH] feat: second step to replace sequelize with prisma, the api is now working --- example/fastify-prisma/package.json | 16 +- example/fastify-prisma/pnpm-lock.yaml | 116 ++--- .../migration.sql | 0 example/fastify-prisma/src/network/server.ts | 2 +- example/fastify-prisma/src/schemas/user.ts | 2 +- lib/src/functions/api/database.js | 18 +- lib/src/functions/api/fastify.js | 466 +++++++++--------- package.json | 1 + 8 files changed, 305 insertions(+), 316 deletions(-) rename example/fastify-prisma/prisma/migrations/{20230731010230_init => 20230731213639_init}/migration.sql (100%) diff --git a/example/fastify-prisma/package.json b/example/fastify-prisma/package.json index 31628dd..48849c2 100644 --- a/example/fastify-prisma/package.json +++ b/example/fastify-prisma/package.json @@ -4,9 +4,11 @@ "main": "src/index.ts", "description": "This is a test using fastify with prisma", "scripts": { + "build:dev": "webpack --mode development", + "build": "webpack --mode production", "lint": "eslint src/* --ext .ts --fix", "service": "nodemon", - "start": "ts-node src/index.ts", + "start": "node dist/index.js", "release": "standard-version", "test:ci": "jest --ci -i", "test:local": "NODE_ENV=local jest --ci -i" @@ -19,8 +21,8 @@ "@types/http-errors": "^2.0.1", "@types/jest": "^29.5.3", "@types/node": "^20.4.5", - "@typescript-eslint/eslint-plugin": "^6.2.0", - "@typescript-eslint/parser": "^6.2.0", + "@typescript-eslint/eslint-plugin": "^6.2.1", + "@typescript-eslint/parser": "^6.2.1", "axios": "^1.4.0", "dotenv": "^16.3.1", "eslint": "^8.46.0", @@ -41,7 +43,11 @@ "ts-loader": "^9.4.4", "ts-node": "^10.9.1", "tsconfig-paths": "^4.2.0", - "typescript": "^5.1.6" + "tsconfig-paths-webpack-plugin": "^4.1.0", + "typescript": "^5.1.6", + "webpack": "^5.88.2", + "webpack-cli": "^5.1.4", + "webpack-node-externals": "^3.0.0" }, "nodemonConfig": { "watch": [ @@ -52,7 +58,7 @@ "ignore": [ "src/**/*.test.ts" ], - "exec": "DEBUG=App:* npx ts-node -r dotenv/config ./src/index" + "exec": "npx ts-node -r dotenv/config ./src/index" }, "dependencies": { "@fastify/cors": "^7", diff --git a/example/fastify-prisma/pnpm-lock.yaml b/example/fastify-prisma/pnpm-lock.yaml index bd40a50..1a7545d 100644 --- a/example/fastify-prisma/pnpm-lock.yaml +++ b/example/fastify-prisma/pnpm-lock.yaml @@ -56,11 +56,11 @@ devDependencies: specifier: ^20.4.5 version: 20.4.5 '@typescript-eslint/eslint-plugin': - specifier: ^6.2.0 - version: 6.2.0(@typescript-eslint/parser@6.2.0)(eslint@8.46.0)(typescript@5.1.6) + specifier: ^6.2.1 + version: 6.2.1(@typescript-eslint/parser@6.2.1)(eslint@8.46.0)(typescript@5.1.6) '@typescript-eslint/parser': - specifier: ^6.2.0 - version: 6.2.0(eslint@8.46.0)(typescript@5.1.6) + specifier: ^6.2.1 + version: 6.2.1(eslint@8.46.0)(typescript@5.1.6) axios: specifier: ^1.4.0 version: 1.4.0(debug@4.3.4) @@ -78,10 +78,10 @@ devDependencies: version: 17.1.0(eslint-plugin-import@2.28.0)(eslint-plugin-n@16.0.1)(eslint-plugin-promise@6.1.1)(eslint@8.46.0) eslint-plugin-import: specifier: ^2.28.0 - version: 2.28.0(@typescript-eslint/parser@6.2.0)(eslint@8.46.0) + version: 2.28.0(@typescript-eslint/parser@6.2.1)(eslint@8.46.0) eslint-plugin-jest: specifier: ^27.2.3 - version: 27.2.3(@typescript-eslint/eslint-plugin@6.2.0)(eslint@8.46.0)(jest@29.6.2)(typescript@5.1.6) + version: 27.2.3(@typescript-eslint/eslint-plugin@6.2.1)(eslint@8.46.0)(jest@29.6.2)(typescript@5.1.6) eslint-plugin-node: specifier: ^11.1.0 version: 11.1.0(eslint@8.46.0) @@ -1103,8 +1103,8 @@ packages: '@types/yargs-parser': 21.0.0 dev: true - /@typescript-eslint/eslint-plugin@6.2.0(@typescript-eslint/parser@6.2.0)(eslint@8.46.0)(typescript@5.1.6): - resolution: {integrity: sha512-rClGrMuyS/3j0ETa1Ui7s6GkLhfZGKZL3ZrChLeAiACBE/tRc1wq8SNZESUuluxhLj9FkUefRs2l6bCIArWBiQ==} + /@typescript-eslint/eslint-plugin@6.2.1(@typescript-eslint/parser@6.2.1)(eslint@8.46.0)(typescript@5.1.6): + resolution: {integrity: sha512-iZVM/ALid9kO0+I81pnp1xmYiFyqibAHzrqX4q5YvvVEyJqY+e6rfTXSCsc2jUxGNqJqTfFSSij/NFkZBiBzLw==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha @@ -1115,11 +1115,11 @@ packages: optional: true dependencies: '@eslint-community/regexpp': 4.6.2 - '@typescript-eslint/parser': 6.2.0(eslint@8.46.0)(typescript@5.1.6) - '@typescript-eslint/scope-manager': 6.2.0 - '@typescript-eslint/type-utils': 6.2.0(eslint@8.46.0)(typescript@5.1.6) - '@typescript-eslint/utils': 6.2.0(eslint@8.46.0)(typescript@5.1.6) - '@typescript-eslint/visitor-keys': 6.2.0 + '@typescript-eslint/parser': 6.2.1(eslint@8.46.0)(typescript@5.1.6) + '@typescript-eslint/scope-manager': 6.2.1 + '@typescript-eslint/type-utils': 6.2.1(eslint@8.46.0)(typescript@5.1.6) + '@typescript-eslint/utils': 6.2.1(eslint@8.46.0)(typescript@5.1.6) + '@typescript-eslint/visitor-keys': 6.2.1 debug: 4.3.4 eslint: 8.46.0 graphemer: 1.4.0 @@ -1133,8 +1133,8 @@ packages: - supports-color dev: true - /@typescript-eslint/parser@6.2.0(eslint@8.46.0)(typescript@5.1.6): - resolution: {integrity: sha512-igVYOqtiK/UsvKAmmloQAruAdUHihsOCvplJpplPZ+3h4aDkC/UKZZNKgB6h93ayuYLuEymU3h8nF1xMRbh37g==} + /@typescript-eslint/parser@6.2.1(eslint@8.46.0)(typescript@5.1.6): + resolution: {integrity: sha512-Ld+uL1kYFU8e6btqBFpsHkwQ35rw30IWpdQxgOqOh4NfxSDH6uCkah1ks8R/RgQqI5hHPXMaLy9fbFseIe+dIg==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 @@ -1143,10 +1143,10 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/scope-manager': 6.2.0 - '@typescript-eslint/types': 6.2.0 - '@typescript-eslint/typescript-estree': 6.2.0(typescript@5.1.6) - '@typescript-eslint/visitor-keys': 6.2.0 + '@typescript-eslint/scope-manager': 6.2.1 + '@typescript-eslint/types': 6.2.1 + '@typescript-eslint/typescript-estree': 6.2.1(typescript@5.1.6) + '@typescript-eslint/visitor-keys': 6.2.1 debug: 4.3.4 eslint: 8.46.0 typescript: 5.1.6 @@ -1162,16 +1162,16 @@ packages: '@typescript-eslint/visitor-keys': 5.62.0 dev: true - /@typescript-eslint/scope-manager@6.2.0: - resolution: {integrity: sha512-1ZMNVgm5nnHURU8ZSJ3snsHzpFeNK84rdZjluEVBGNu7jDymfqceB3kdIZ6A4xCfEFFhRIB6rF8q/JIqJd2R0Q==} + /@typescript-eslint/scope-manager@6.2.1: + resolution: {integrity: sha512-UCqBF9WFqv64xNsIEPfBtenbfodPXsJ3nPAr55mGPkQIkiQvgoWNo+astj9ZUfJfVKiYgAZDMnM6dIpsxUMp3Q==} engines: {node: ^16.0.0 || >=18.0.0} dependencies: - '@typescript-eslint/types': 6.2.0 - '@typescript-eslint/visitor-keys': 6.2.0 + '@typescript-eslint/types': 6.2.1 + '@typescript-eslint/visitor-keys': 6.2.1 dev: true - /@typescript-eslint/type-utils@6.2.0(eslint@8.46.0)(typescript@5.1.6): - resolution: {integrity: sha512-DnGZuNU2JN3AYwddYIqrVkYW0uUQdv0AY+kz2M25euVNlujcN2u+rJgfJsBFlUEzBB6OQkUqSZPyuTLf2bP5mw==} + /@typescript-eslint/type-utils@6.2.1(eslint@8.46.0)(typescript@5.1.6): + resolution: {integrity: sha512-fTfCgomBMIgu2Dh2Or3gMYgoNAnQm3RLtRp+jP7A8fY+LJ2+9PNpi5p6QB5C4RSP+U3cjI0vDlI3mspAkpPVbQ==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 @@ -1180,8 +1180,8 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/typescript-estree': 6.2.0(typescript@5.1.6) - '@typescript-eslint/utils': 6.2.0(eslint@8.46.0)(typescript@5.1.6) + '@typescript-eslint/typescript-estree': 6.2.1(typescript@5.1.6) + '@typescript-eslint/utils': 6.2.1(eslint@8.46.0)(typescript@5.1.6) debug: 4.3.4 eslint: 8.46.0 ts-api-utils: 1.0.1(typescript@5.1.6) @@ -1195,8 +1195,8 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /@typescript-eslint/types@6.2.0: - resolution: {integrity: sha512-1nRRaDlp/XYJQLvkQJG5F3uBTno5SHPT7XVcJ5n1/k2WfNI28nJsvLakxwZRNY5spuatEKO7d5nZWsQpkqXwBA==} + /@typescript-eslint/types@6.2.1: + resolution: {integrity: sha512-528bGcoelrpw+sETlyM91k51Arl2ajbNT9L4JwoXE2dvRe1yd8Q64E4OL7vHYw31mlnVsf+BeeLyAZUEQtqahQ==} engines: {node: ^16.0.0 || >=18.0.0} dev: true @@ -1221,8 +1221,8 @@ packages: - supports-color dev: true - /@typescript-eslint/typescript-estree@6.2.0(typescript@5.1.6): - resolution: {integrity: sha512-Mts6+3HQMSM+LZCglsc2yMIny37IhUgp1Qe8yJUYVyO6rHP7/vN0vajKu3JvHCBIy8TSiKddJ/Zwu80jhnGj1w==} + /@typescript-eslint/typescript-estree@6.2.1(typescript@5.1.6): + resolution: {integrity: sha512-G+UJeQx9AKBHRQBpmvr8T/3K5bJa485eu+4tQBxFq0KoT22+jJyzo1B50JDT9QdC1DEmWQfdKsa8ybiNWYsi0Q==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: typescript: '*' @@ -1230,8 +1230,8 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/types': 6.2.0 - '@typescript-eslint/visitor-keys': 6.2.0 + '@typescript-eslint/types': 6.2.1 + '@typescript-eslint/visitor-keys': 6.2.1 debug: 4.3.4 globby: 11.1.0 is-glob: 4.0.3 @@ -1262,8 +1262,8 @@ packages: - typescript dev: true - /@typescript-eslint/utils@6.2.0(eslint@8.46.0)(typescript@5.1.6): - resolution: {integrity: sha512-RCFrC1lXiX1qEZN8LmLrxYRhOkElEsPKTVSNout8DMzf8PeWoQG7Rxz2SadpJa3VSh5oYKGwt7j7X/VRg+Y3OQ==} + /@typescript-eslint/utils@6.2.1(eslint@8.46.0)(typescript@5.1.6): + resolution: {integrity: sha512-eBIXQeupYmxVB6S7x+B9SdBeB6qIdXKjgQBge2J+Ouv8h9Cxm5dHf/gfAZA6dkMaag+03HdbVInuXMmqFB/lKQ==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 @@ -1271,9 +1271,9 @@ packages: '@eslint-community/eslint-utils': 4.4.0(eslint@8.46.0) '@types/json-schema': 7.0.12 '@types/semver': 7.5.0 - '@typescript-eslint/scope-manager': 6.2.0 - '@typescript-eslint/types': 6.2.0 - '@typescript-eslint/typescript-estree': 6.2.0(typescript@5.1.6) + '@typescript-eslint/scope-manager': 6.2.1 + '@typescript-eslint/types': 6.2.1 + '@typescript-eslint/typescript-estree': 6.2.1(typescript@5.1.6) eslint: 8.46.0 semver: 7.5.4 transitivePeerDependencies: @@ -1289,11 +1289,11 @@ packages: eslint-visitor-keys: 3.4.2 dev: true - /@typescript-eslint/visitor-keys@6.2.0: - resolution: {integrity: sha512-QbaYUQVKKo9bgCzpjz45llCfwakyoxHetIy8CAvYCtd16Zu1KrpzNHofwF8kGkpPOxZB2o6kz+0nqH8ZkIzuoQ==} + /@typescript-eslint/visitor-keys@6.2.1: + resolution: {integrity: sha512-iTN6w3k2JEZ7cyVdZJTVJx2Lv7t6zFA8DCrJEHD2mwfc16AEvvBWVhbFh34XyG2NORCd0viIgQY1+u7kPI0WpA==} engines: {node: ^16.0.0 || >=18.0.0} dependencies: - '@typescript-eslint/types': 6.2.0 + '@typescript-eslint/types': 6.2.1 eslint-visitor-keys: 3.4.2 dev: true @@ -1813,8 +1813,8 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true dependencies: - caniuse-lite: 1.0.30001517 - electron-to-chromium: 1.4.477 + caniuse-lite: 1.0.30001518 + electron-to-chromium: 1.4.478 node-releases: 2.0.13 update-browserslist-db: 1.0.11(browserslist@4.21.10) dev: true @@ -1892,8 +1892,8 @@ packages: engines: {node: '>=10'} dev: true - /caniuse-lite@1.0.30001517: - resolution: {integrity: sha512-Vdhm5S11DaFVLlyiKu4hiUTkpZu+y1KA/rZZqVQfOD5YdDT/eQKlkt7NaE0WGOFgX32diqt9MiP9CAiFeRklaA==} + /caniuse-lite@1.0.30001518: + resolution: {integrity: sha512-rup09/e3I0BKjncL+FesTayKtPrdwKhUufQFd3riFw1hHg8JmIFoInYfB102cFcY/pPgGmdyl/iy+jgiDi2vdA==} dev: true /chalk@2.4.2: @@ -2304,8 +2304,8 @@ packages: engines: {node: '>=0.10.0'} dev: true - /dedent@1.5.0: - resolution: {integrity: sha512-3sSQTYoWKGcRHmHl6Y6opLpRJH55bxeGQ0Y1LCI5pZzUXvokVkj0FC4bi7uEwazxA9FQZ0Nv067Zt5kSUvXxEA==} + /dedent@1.5.1: + resolution: {integrity: sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==} peerDependencies: babel-plugin-macros: ^3.1.0 peerDependenciesMeta: @@ -2436,8 +2436,8 @@ packages: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} dev: false - /electron-to-chromium@1.4.477: - resolution: {integrity: sha512-shUVy6Eawp33dFBFIoYbIwLHrX0IZ857AlH9ug2o4rvbWmpaCUdBpQ5Zw39HRrfzAFm4APJE9V+E2A/WB0YqJw==} + /electron-to-chromium@1.4.478: + resolution: {integrity: sha512-qjTA8djMXd+ruoODDFGnRCRBpID+AAfYWCyGtYTNhsuwxI19s8q19gbjKTwRS5z/LyVf5wICaIiPQGLekmbJbA==} dev: true /emittery@0.13.1: @@ -2601,7 +2601,7 @@ packages: eslint-plugin-promise: ^6.0.0 dependencies: eslint: 8.46.0 - eslint-plugin-import: 2.28.0(@typescript-eslint/parser@6.2.0)(eslint@8.46.0) + eslint-plugin-import: 2.28.0(@typescript-eslint/parser@6.2.1)(eslint@8.46.0) eslint-plugin-n: 16.0.1(eslint@8.46.0) eslint-plugin-promise: 6.1.1(eslint@8.46.0) dev: true @@ -2616,7 +2616,7 @@ packages: - supports-color dev: true - /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.2.0)(eslint-import-resolver-node@0.3.7)(eslint@8.46.0): + /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.2.1)(eslint-import-resolver-node@0.3.7)(eslint@8.46.0): resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} engines: {node: '>=4'} peerDependencies: @@ -2637,7 +2637,7 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - '@typescript-eslint/parser': 6.2.0(eslint@8.46.0)(typescript@5.1.6) + '@typescript-eslint/parser': 6.2.1(eslint@8.46.0)(typescript@5.1.6) debug: 3.2.7(supports-color@5.5.0) eslint: 8.46.0 eslint-import-resolver-node: 0.3.7 @@ -2667,7 +2667,7 @@ packages: regexpp: 3.2.0 dev: true - /eslint-plugin-import@2.28.0(@typescript-eslint/parser@6.2.0)(eslint@8.46.0): + /eslint-plugin-import@2.28.0(@typescript-eslint/parser@6.2.1)(eslint@8.46.0): resolution: {integrity: sha512-B8s/n+ZluN7sxj9eUf7/pRFERX0r5bnFA2dCaLHy2ZeaQEAz0k+ZZkFWRFHJAqxfxQDx6KLv9LeIki7cFdwW+Q==} engines: {node: '>=4'} peerDependencies: @@ -2677,7 +2677,7 @@ packages: '@typescript-eslint/parser': optional: true dependencies: - '@typescript-eslint/parser': 6.2.0(eslint@8.46.0)(typescript@5.1.6) + '@typescript-eslint/parser': 6.2.1(eslint@8.46.0)(typescript@5.1.6) array-includes: 3.1.6 array.prototype.findlastindex: 1.2.2 array.prototype.flat: 1.3.1 @@ -2686,7 +2686,7 @@ packages: doctrine: 2.1.0 eslint: 8.46.0 eslint-import-resolver-node: 0.3.7 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.2.0)(eslint-import-resolver-node@0.3.7)(eslint@8.46.0) + eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.2.1)(eslint-import-resolver-node@0.3.7)(eslint@8.46.0) has: 1.0.3 is-core-module: 2.12.1 is-glob: 4.0.3 @@ -2703,7 +2703,7 @@ packages: - supports-color dev: true - /eslint-plugin-jest@27.2.3(@typescript-eslint/eslint-plugin@6.2.0)(eslint@8.46.0)(jest@29.6.2)(typescript@5.1.6): + /eslint-plugin-jest@27.2.3(@typescript-eslint/eslint-plugin@6.2.1)(eslint@8.46.0)(jest@29.6.2)(typescript@5.1.6): resolution: {integrity: sha512-sRLlSCpICzWuje66Gl9zvdF6mwD5X86I4u55hJyFBsxYOsBCmT5+kSUjf+fkFWVMMgpzNEupjW8WzUqi83hJAQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} peerDependencies: @@ -2716,7 +2716,7 @@ packages: jest: optional: true dependencies: - '@typescript-eslint/eslint-plugin': 6.2.0(@typescript-eslint/parser@6.2.0)(eslint@8.46.0)(typescript@5.1.6) + '@typescript-eslint/eslint-plugin': 6.2.1(@typescript-eslint/parser@6.2.1)(eslint@8.46.0)(typescript@5.1.6) '@typescript-eslint/utils': 5.62.0(eslint@8.46.0)(typescript@5.1.6) eslint: 8.46.0 jest: 29.6.2(@types/node@20.4.5)(ts-node@10.9.1) @@ -3847,7 +3847,7 @@ packages: '@types/node': 20.4.5 chalk: 4.1.2 co: 4.6.0 - dedent: 1.5.0 + dedent: 1.5.1 is-generator-fn: 2.1.0 jest-each: 29.6.2 jest-matcher-utils: 29.6.2 diff --git a/example/fastify-prisma/prisma/migrations/20230731010230_init/migration.sql b/example/fastify-prisma/prisma/migrations/20230731213639_init/migration.sql similarity index 100% rename from example/fastify-prisma/prisma/migrations/20230731010230_init/migration.sql rename to example/fastify-prisma/prisma/migrations/20230731213639_init/migration.sql diff --git a/example/fastify-prisma/src/network/server.ts b/example/fastify-prisma/src/network/server.ts index a91ec9c..306af5f 100644 --- a/example/fastify-prisma/src/network/server.ts +++ b/example/fastify-prisma/src/network/server.ts @@ -57,7 +57,7 @@ class Server implements Log { try { await this.#connection?.disconnect() await this.#app.close() - d(`HTTP server stopped.`) + d('HTTP server stopped.') } catch (e) { this.log({ method: this.stop.name, diff --git a/example/fastify-prisma/src/schemas/user.ts b/example/fastify-prisma/src/schemas/user.ts index 1bb2092..7c4264a 100644 --- a/example/fastify-prisma/src/schemas/user.ts +++ b/example/fastify-prisma/src/schemas/user.ts @@ -1,6 +1,6 @@ import { Static, Type } from '@sinclair/typebox' -import { id } from './id' +import { id } from '.' const user = Type.Object({ lastName: Type.String(), diff --git a/lib/src/functions/api/database.js b/lib/src/functions/api/database.js index 8b6ba81..1ce6c42 100644 --- a/lib/src/functions/api/database.js +++ b/lib/src/functions/api/database.js @@ -300,7 +300,7 @@ export { store, remove, get, update } */ const sql = async ({ projectName, db }) => { const createFoldersCommands = `mkdir ${projectName}/prisma \ -${projectName}/src/database/postgres ${projectName}/src/database/postgres/models \ +${projectName}/src/database/postgres \ ${projectName}/src/database/postgres/queries` if (platform() === 'win32') @@ -336,6 +336,11 @@ model User { file: `${projectName}/src/database/index.ts` }, [db]: { + index: { + content: `export * from './connection' +export * from './queries'\n`, + file: `${projectName}/src/database/${db}/index.ts` + }, connection: { content: `import { PrismaClient } from '@prisma/client' import { Debugger } from 'debug' @@ -376,15 +381,9 @@ const dbConnection = ( } } -export { dbConnection } -`, +export { dbConnection }\n`, file: `${projectName}/src/database/${db}/connection.ts` }, - index: { - content: `export * from './connection' -export * from './queries'\n`, - file: `${projectName}/src/database/${db}/index.ts` - }, queries: { index: { content: "export * from './user'\n", @@ -492,8 +491,7 @@ const update = async (id: Id, user: UserSchema) => { } } -export { store, removeById, getById, update } -`, +export { store, removeById, getById, update }\n`, file: `${projectName}/src/database/${db}/queries/user.ts` } } diff --git a/lib/src/functions/api/fastify.js b/lib/src/functions/api/fastify.js index 196ef20..d4c721a 100644 --- a/lib/src/functions/api/fastify.js +++ b/lib/src/functions/api/fastify.js @@ -267,26 +267,22 @@ const server = new Server() export { server as Server } ` : `import fastify, { FastifyInstance } from 'fastify' +import debug from 'debug' import { dbConnection } from 'database' +import { Log } from 'utils' import { applyRoutes } from './router' import { validatorCompiler } from './utils' +const d = debug('App:Network:Server') const PORT = process.env.PORT ?? 1996 -const ENVIRONMENTS_WITHOUT_PRETTY_PRINT = ['production', 'ci'] -class Server { +class Server implements Log { #app: FastifyInstance #connection: Awaited> | undefined constructor() { - this.#app = fastify({ - logger: { - prettyPrint: !ENVIRONMENTS_WITHOUT_PRETTY_PRINT.includes( - process.env.NODE_ENV as string - ) - } - }) + this.#app = fastify() this.#config() } @@ -307,7 +303,7 @@ class Server { } async #dbConnection() { - this.#connection = await dbConnection(this.#app.log) + this.#connection = dbConnection(d) } public async start(): Promise { @@ -315,8 +311,13 @@ class Server { await this.#dbConnection() await this.#connection?.connect() await this.#app.listen(PORT) + d(\`HTTP server listening on port \${PORT}.\`) } catch (e) { - console.error(e) + this.log({ + method: this.start.name, + value: 'error', + content: e + }) } } @@ -324,10 +325,31 @@ class Server { try { await this.#connection?.disconnect() await this.#app.close() + d('HTTP server stopped.') } catch (e) { - console.error(e) + this.log({ + method: this.stop.name, + value: 'error', + content: e + }) } } + + public log({ + method, + value, + content + }: { + method: string + value: string + content: unknown + }) { + d( + \`Server invoked -> \${ + this.constructor.name + } ~ \${method} ~ value: \${value} ~ content: \${JSON.stringify(content)}\` + ) + } } const server = new Server() @@ -407,7 +429,6 @@ ${graphQL ? '' : "export * from './user'\n"}`, ...(!graphQL && { user: { content: `import { FastifyInstance } from 'fastify' -import { Type } from '@sinclair/typebox' import { response } from 'network/response' import { @@ -443,10 +464,8 @@ const User = (app: FastifyInstance, prefix = '/api'): void => { args: { lastName, name } } } = request - const us = new UserService({ - user: { lastName, name } - }) - const user = await us.process({ type: 'store' }) + const us = new UserService() + const user = await us.store({ lastName, name }) response({ error: false, @@ -456,62 +475,6 @@ const User = (app: FastifyInstance, prefix = '/api'): void => { }) } ) - .get( - \`\${prefix}/users\`, - { - schema: { - response: { - 200: { - error: { - type: 'boolean' - }, - message: Type.Array(userDto) - } - }, - tags: ['user'] - } - }, - async (request, reply) => { - const us = new UserService() - const users = await us.process({ type: 'getAll' }) - - response({ - error: false, - message: users, - reply, - status: 200 - }) - } - ) - .delete( - \`\${prefix}/users\`, - { - schema: { - response: { - 200: { - error: { - type: 'boolean' - }, - message: { - type: 'string' - } - } - }, - tags: ['user'] - } - }, - async (request, reply) => { - const us = new UserService() - const result = await us.process({ type: 'deleteAll' }) - - response({ - error: false, - message: result, - reply, - status: 200 - }) - } - ) .get<{ Params: IdSchema }>( \`\${prefix}/user/:id\`, { @@ -532,8 +495,8 @@ const User = (app: FastifyInstance, prefix = '/api'): void => { const { params: { id } } = request - const us = new UserService({ id }) - const user = await us.process({ type: 'getOne' }) + const us = new UserService() + const user = await us.getById(id) response({ error: false, @@ -567,10 +530,8 @@ const User = (app: FastifyInstance, prefix = '/api'): void => { }, params: { id } } = request - const us = new UserService({ - userWithId: { name, lastName, id } - }) - const user = await us.process({ type: 'update' }) + const us = new UserService() + const user = await us.update(id, { name, lastName }) response({ error: false, @@ -602,8 +563,8 @@ const User = (app: FastifyInstance, prefix = '/api'): void => { const { params: { id } } = request - const us = new UserService({ id }) - const result = await us.process({ type: 'delete' }) + const us = new UserService() + const result = await us.deleteById(id) response({ error: false, @@ -615,8 +576,7 @@ const User = (app: FastifyInstance, prefix = '/api'): void => { ) } -export { User } -`, +export { User }\n`, file: `${projectName}/src/network/routes/user.ts` } }) @@ -1227,23 +1187,7 @@ const ajv = addFormats(new Ajv(), ['email']) export { id, ID, idSchema, IDSchema, ajv } export * from './user' ` - : `import { Static, Type } from '@sinclair/typebox' - -const id = ${ - dbIsSQL - ? `Type.Number()` - : `Type.String({ pattern: '^[a-zA-Z0-9]{24,}$' })` - } - -type Id = Static - -const idSchema = Type.Object({ id }) - -type IdSchema = Static - -export { id, Id, idSchema, IdSchema } -export * from './user' -`, + : `export * from './id'\nexport * from './user'\n`, file: `${projectName}/src/schemas/index.ts` }, user: { @@ -1290,13 +1234,33 @@ export { } `, file: `${projectName}/src/schemas/user.ts` - } + }, + ...(!graphQL && { + id: { + content: `import { Static, Type } from '@sinclair/typebox' + +const id = Type.Number() + +type Id = Static + +const idSchema = Type.Object({ id }) + +type IdSchema = Static + +export { id, Id, idSchema, IdSchema }\n`, + file: `${projectName}/src/schemas/id.ts` + } + }) } - await Promise.all([ + const processes = [ writeFile(schemas.index.file, schemas.index.content), writeFile(schemas.user.file, schemas.user.content) - ]) + ] + + if (!graphQL) processes.push(writeFile(schemas.id.file, schemas.id.content)) + + await Promise.all(processes) } /** @@ -1315,205 +1279,212 @@ ${projectName}/src/services/utils/messages` const services = { index: { - content: "export * from './user'\n", + content: "export * from './User'\n", file: `${projectName}/src/services/index.ts` }, - user: { - content: `import httpErrors from 'http-errors' + base: { + content: `import { Debugger } from 'debug' +import httpErrors, { + HttpErrorConstructor, + NamedConstructors +} from 'http-errors' -import { store, remove, get, update } from 'database' -import { User, UserDTO, UserWithId } from 'schemas' -import { EFU, MFU, GE, errorHandling } from './utils' +import { GE } from './utils' +import { Log } from 'utils' -type Process = { - type: 'store' | 'getAll' | 'deleteAll' | 'getOne' | 'update' | 'delete' -} +type FilterNumberKeys = { + [K in keyof T]: T[K] extends HttpErrorConstructor + ? N extends number + ? K + : never + : never +}[keyof T] -type Arguments = { - id?: ${dbIsSQL ? 'number' : 'string'} - user?: User - userWithId?: UserWithId -} +type ErrorCodes = FilterNumberKeys -class UserService { - #args: Arguments +class BaseHttpService implements Log { + #debug: Debugger - constructor(args: Arguments = {}) { - this.#args = args + constructor(debug: Debugger) { + this.#debug = debug } - public process({ type }: Process): Promise { - switch (type) { - case 'store': - return this.#store() - case 'getAll': - return this.#getAll() - case 'deleteAll': - return this.#deleteAll() - case 'getOne': - return this.#getOne() - case 'update': - return this.#update() - case 'delete': - return this.#delete() - default: - throw new httpErrors.InternalServerError(GE.INTERNAL_SERVER_ERROR) - } + log({ + method, + value, + content + }: { + method: string + value: string + content: unknown + }) { + this.#debug( + \`Service invoked -> \${ + this.constructor.name + } ~ \${method} ~ value: \${value} ~ content: \${JSON.stringify(content)}\` + ) } - async #store(): Promise { - try { - if (!this.#args.user) - throw new httpErrors.UnprocessableEntity(GE.INTERNAL_SERVER_ERROR) + errorHandling( + error: unknown, + { + message, + code + }: + | { + message?: string + code?: never + } + | { + message?: never + code: ErrorCodes + } = { + message: GE.INTERNAL_SERVER_ERROR + } + ): never { + this.log({ + method: this.errorHandling.name, + value: 'error', + content: error + }) - const result = await store(this.#args.user) + if (code) + throw new httpErrors[code]( + message ?? (error as { message: string }).message + ) - return result - } catch (e) { - return errorHandling(e, GE.INTERNAL_SERVER_ERROR) - } + throw new httpErrors.InternalServerError( + message ?? (error as { message: string }).message + ) } +} - async #getAll(): Promise { - try { - const users = (await get()) as UserDTO[] +export { BaseHttpService }\n`, + file: `${projectName}/src/services/BaseHttp.ts` + }, + user: { + content: `import debug from 'debug' - return users - } catch (e) { - return errorHandling(e, GE.INTERNAL_SERVER_ERROR) - } +import { getById, removeById, store, update } from 'database' +import { Id, User as UserSchema } from 'schemas' +import { BaseHttpService } from './BaseHttp' +import { EFU, MFU, GE } from './utils' + +class UserService extends BaseHttpService { + constructor() { + super(debug('App:Services:User')) } - async #deleteAll(): Promise { + async store(userDto: UserSchema) { try { - const usersDeleted = (await remove()) as number - - ${ - dbIsSQL - ? 'if (usersDeleted !== 0) return MFU.ALL_USERS_DELETED' - : `if (usersDeleted >= 1) return MFU.ALL_USERS_DELETED - - if (usersDeleted === 0) - throw new httpErrors.Conflict(EFU.NOTHING_TO_DELETE)` - } + const result = await store(userDto) + super.log({ method: this.store.name, value: 'result', content: result }) - throw new httpErrors.InternalServerError(GE.INTERNAL_SERVER_ERROR) + return result } catch (e) { - return errorHandling(e, GE.INTERNAL_SERVER_ERROR) + return super.errorHandling(e) } } - async #getOne(): Promise { + async getById(id: Id) { try { - if (!this.#args.id) - throw new httpErrors.UnprocessableEntity(GE.INTERNAL_SERVER_ERROR) + const user = getById(id) + super.log({ method: this.getById.name, value: 'result', content: user }) - const { id } = this.#args - const user = (await get(id)) as UserDTO | null - - if (!user) throw new httpErrors.NotFound(EFU.NOT_FOUND) + if (!user) + return super.errorHandling(new Error(EFU.NOT_FOUND), { code: '404' }) return user } catch (e) { - return errorHandling(e, GE.INTERNAL_SERVER_ERROR) + return super.errorHandling(e) } } - async #update(): Promise { + async update(id: Id, user: UserSchema) { try { - if (!this.#args.userWithId || !this.#args.userWithId.id) - throw new httpErrors.UnprocessableEntity(GE.INTERNAL_SERVER_ERROR) - - const updatedUser = await update(this.#args.userWithId) + const updatedUser = await update(id, user) + super.log({ + method: this.update.name, + value: 'result', + content: updatedUser + }) - if (!updatedUser) throw new httpErrors.NotFound(EFU.NOT_FOUND) + if (!updatedUser) + return super.errorHandling(new Error(EFU.NOT_FOUND), { code: '404' }) return updatedUser } catch (e) { - return errorHandling(e, GE.INTERNAL_SERVER_ERROR) + return super.errorHandling(e, { message: GE.INTERNAL_SERVER_ERROR }) } } - async #delete(): Promise { + async deleteById(id: Id) { try { - if (!this.#args.id) - throw new httpErrors.UnprocessableEntity(GE.INTERNAL_SERVER_ERROR) - - const { id } = this.#args - const deletedUser = await remove(id) + const deletedUser = await removeById(id) + super.log({ + method: this.deleteById.name, + value: 'result', + content: deletedUser + }) - if (!deletedUser) throw new httpErrors.NotFound(EFU.NOT_FOUND) + if (!deletedUser) + return super.errorHandling(new Error(EFU.NOT_FOUND), { code: '404' }) return MFU.USER_DELETED } catch (e) { - return errorHandling(e, GE.INTERNAL_SERVER_ERROR) + return super.errorHandling(e) } } } -export { UserService } -`, - file: `${projectName}/src/services/user.ts` +export { UserService }\n`, + file: `${projectName}/src/services/User.ts` }, utils: { index: { - content: `import httpErrors from 'http-errors' - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -const errorHandling = (e: any, message?: string): never => { - console.error(e) - - if (e instanceof httpErrors.HttpError) throw e - - throw new httpErrors.InternalServerError(message ?? e.message) -} - -export { errorHandling } -export * from './messages' -`, + content: `export * from './messages'\n`, file: `${projectName}/src/services/utils/index.ts` - } - }, - 'utils/messages': { - index: { - content: `enum GenericErrors { - INTERNAL_SERVER_ERROR = 'Something went wrong' -} - -export { GenericErrors as GE } -export * from './user' -`, - file: `${projectName}/src/services/utils/messages/index.ts` }, - user: { - content: `enum ErrorForUser { - NOT_FOUND = 'The requested user does not exists', - NOTHING_TO_DELETE = 'There is no user to be deleted' -} - -enum MessageForUser { - ALL_USERS_DELETED = 'All the users were deleted successfully', - USER_DELETED = 'The requested user was successfully deleted' -} + messages: { + index: { + content: `const GenericErrors = { + INTERNAL_SERVER_ERROR: 'Something went wrong' +} as const -export { ErrorForUser as EFU, MessageForUser as MFU } -`, - file: `${projectName}/src/services/utils/messages/user.ts` +export { GenericErrors as GE } +export * from './user'\n`, + file: `${projectName}/src/services/utils/messages/index.ts` + }, + user: { + content: `const ErrorForUser = { + NOT_FOUND: 'The requested user does not exists', + NOTHING_TO_DELETE: 'There is no user to be deleted' +} as const + +const MessageForUser = { + ALL_USERS_DELETED: 'All the users were deleted successfully', + USER_DELETED: 'The requested user was successfully deleted' +} as const + +export { ErrorForUser as EFU, MessageForUser as MFU }\n`, + file: `${projectName}/src/services/utils/messages/user.ts` + } } } } await Promise.all([ writeFile(services.index.file, services.index.content), + writeFile(services.base.file, services.base.content), writeFile(services.user.file, services.user.content), writeFile(services.utils.index.file, services.utils.index.content), writeFile( - services['utils/messages'].index.file, - services['utils/messages'].index.content + services.utils.messages.index.file, + services.utils.messages.index.content ), writeFile( - services['utils/messages'].user.file, - services['utils/messages'].user.content + services.utils.messages.user.file, + services.utils.messages.user.content ) ]) } @@ -1531,13 +1502,27 @@ const utils = async ({ projectName }) => { const utils = { index: { - content: `export * from './logger`, + content: `export * from './Logger'\n`, file: `${projectName}/src/utils/index.ts` }, logger: { content: `import { Debugger } from 'debug' -class Logger { +export interface Log { + log({ + origin, + method, + value, + content + }: { + origin?: string + method: string + value: string + content: unknown + }): void +} + +class Logger implements Log { #debug: Debugger constructor(debug: Debugger) { @@ -1563,9 +1548,8 @@ class Logger { } } -export { Logger } -`, - file: `${projectName}/src/utils/logger.ts` +export { Logger }\n`, + file: `${projectName}/src/utils/Logger.ts` } } diff --git a/package.json b/package.json index 5319504..3c7a10e 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "build:and:test:only": "npm run build && npm run test:only", "test": "npm run test:without:restore && git restore .", "test:local": "npm run test:without:restore && git restore .", + "test:integration": "jest --testPathPattern=test/integration", "test:without:restore": "npm run build && npm run test:express:local && npm run test:fastify:local && npm run test:express:graphql:local && npm run test:fastify:graphql:local && npm run test:express:graphql:sequelize:local && test:fastify:graphql:sequelize:local && npm run test:express:sequelize:local && test:fastify:sequelize:local", "test:ci:mongo": "npm run build:mongo && npm run test:express:ci && npm run test:fastify:ci && npm run test:express:graphql:ci && npm run test:fastify:graphql:ci", "test:ci:postgresql": "npm run build:postgresql && npm run test:express:sequelize:ci && npm run test:fastify:sequelize:ci",