From 47bf370919c85e7275ecd99f63dfe6ab8aab0e5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Bitard?= <bitard.michael@gmail.com> Date: Wed, 12 Apr 2023 17:50:16 +0200 Subject: [PATCH] chore(api): utilise pg-typed pour remplacer knex et objection (#512) --- package-lock.json | 468 +++++++++++++++++- packages/api/.prettierignore | 3 +- packages/api/config.json | 18 + packages/api/package.json | 20 +- .../src/api/rest/statistiques/dgtm.queries.ts | 21 + .../rest/statistiques/dgtm.queries.types.ts | 19 + .../api/src/api/rest/statistiques/dgtm.ts | 27 +- ...es-etapes-areas-update.test.integration.ts | 1 + .../processes/titres-etapes-areas-update.ts | 1 + .../titres-etapes-heritage-contenu-update.ts | 1 + ...021121056_delete-titres-administrations.ts | 1 + .../20221229082906_migre-sdomzones.ts | 1 + packages/api/src/pg-database.ts | 10 + packages/api/src/tools/geojson.ts | 1 + packages/api/src/tools/territoires-update.ts | 1 + packages/api/tests/db-manager.ts | 1 + 16 files changed, 578 insertions(+), 16 deletions(-) create mode 100644 packages/api/config.json create mode 100644 packages/api/src/api/rest/statistiques/dgtm.queries.ts create mode 100644 packages/api/src/api/rest/statistiques/dgtm.queries.types.ts create mode 100644 packages/api/src/pg-database.ts diff --git a/package-lock.json b/package-lock.json index 300d3a7ee..8ab5c8052 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3686,6 +3686,132 @@ "@octokit/openapi-types": "^16.0.0" } }, + "node_modules/@pgtyped/parser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@pgtyped/parser/-/parser-2.1.0.tgz", + "integrity": "sha512-HIHbQ8iQCPvr4JM/UcXkYlB1zFH2abFoZ9ID8S66pEwm2WUjQlwK1r+/4DRnqXFmwi+qkRPcg4KfAs5iN11eMw==", + "dev": true, + "dependencies": { + "antlr4ts": "0.5.0-alpha.4", + "chalk": "^4.1.0", + "debug": "^4.1.1" + }, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/@pgtyped/parser/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@pgtyped/parser/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@pgtyped/parser/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@pgtyped/parser/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@pgtyped/runtime": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@pgtyped/runtime/-/runtime-2.1.0.tgz", + "integrity": "sha512-PHND3jE4VnPL23OFqAc6e2Z2V09RKp6RWh2kVfz6KsBIzj7saao2HkAVxzJNED4WNGw66OyXVPdZwOP0NY9CbA==", + "dev": true, + "dependencies": { + "@pgtyped/parser": "^2.1.0", + "chalk": "^4.1.0", + "debug": "^4.1.1" + }, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/@pgtyped/runtime/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@pgtyped/runtime/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@pgtyped/runtime/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@pgtyped/runtime/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, "node_modules/@pnpm/config.env-replace": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.0.0.tgz", @@ -8125,6 +8251,12 @@ "integrity": "sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==", "dev": true }, + "node_modules/antlr4ts": { + "version": "0.5.0-alpha.4", + "resolved": "https://registry.npmjs.org/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz", + "integrity": "sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==", + "dev": true + }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -8472,6 +8604,15 @@ "node": ">=8" } }, + "node_modules/astring": { + "version": "1.8.4", + "resolved": "https://registry.npmjs.org/astring/-/astring-1.8.4.tgz", + "integrity": "sha512-97a+l2LBU3Op3bBQEff79i/E4jMD2ZLFD8rHx9B6mXyB2uQwhJQYfiDqUwtfjF4QA1F2qs//N6Cw8LetMbQjcw==", + "dev": true, + "bin": { + "astring": "bin/astring" + } + }, "node_modules/async-each": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.6.tgz", @@ -13710,6 +13851,25 @@ "eslint": "^7.0.0 || ^8.0.0" } }, + "node_modules/eslint-plugin-sql": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-sql/-/eslint-plugin-sql-2.3.2.tgz", + "integrity": "sha512-cyR9MdqEIkLvBI6DOEQCfAhKcLGkjhzUF+6qYvEesSdxq7IveFQQhgYjH3fSaGAde1U5Q20WjpWdpZ6awYjXzA==", + "dev": true, + "dependencies": { + "astring": "^1.8.3", + "debug": "^4.3.4", + "lodash": "^4.17.21", + "pg-formatter": "^1.3.0", + "sql-parse": "^0.1.5" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "eslint": ">=8.1.0" + } + }, "node_modules/eslint-plugin-tsdoc": { "version": "0.2.17", "resolved": "https://registry.npmjs.org/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.2.17.tgz", @@ -24020,6 +24180,92 @@ "integrity": "sha512-QfXcpxyN9vT+kvexQpTeNyiwCxs4LPXLAV/C0EeLTJPCF61swhGdDlnHcuDgxJudgKGfQYiCkegg0GsSKSvvEg==", "dev": true }, + "node_modules/pg-formatter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/pg-formatter/-/pg-formatter-1.3.0.tgz", + "integrity": "sha512-y1kNdgD+QWzhmYCm91z/k7VGyx6BekQg6ww/krFEEhw1IIB4zEk2xaB0pmueTcc59YFetpiHIKECgHEuw6gyvg==", + "dev": true, + "dependencies": { + "shell-quote": "^1.7.2", + "yargs": "^17.2.1" + }, + "bin": { + "pg-formatter": "dist/bin/index.js" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/pg-formatter/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/pg-formatter/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/pg-formatter/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/pg-formatter/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pg-formatter/node_modules/yargs": { + "version": "17.7.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", + "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/pg-formatter/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, "node_modules/pg-int8": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", @@ -27630,6 +27876,15 @@ "node": ">=8" } }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/shpjs": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/shpjs/-/shpjs-4.0.4.tgz", @@ -28181,6 +28436,15 @@ "node": ">= 6" } }, + "node_modules/sql-parse": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/sql-parse/-/sql-parse-0.1.5.tgz", + "integrity": "sha512-e2ExBX6iDHoCDC1zN2NvZV49UMhKVLvvwrDjzSVHFS3TKHKtIpl2nMDQkdlbTjDVvf2bxRYBq9iXAAMZvZpGVA==", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, "node_modules/ssf": { "version": "0.11.2", "resolved": "https://registry.npmjs.org/ssf/-/ssf-0.11.2.tgz", @@ -32910,6 +33174,7 @@ "xstate": "^4.37.0" }, "devDependencies": { + "@pgtyped/runtime": "^2.1.0", "@types/carbone": "^3.2.1", "@types/cookie-parser": "^1.4.3", "@types/stream-json": "^1.7.3", @@ -32924,6 +33189,7 @@ "eslint-plugin-import": "^2.27.5", "eslint-plugin-n": "^15.6.1", "eslint-plugin-promise": "^6.1.1", + "eslint-plugin-sql": "^2.3.2", "eslint-plugin-tsdoc": "^0.2.1", "pg-escape": "^0.2.0", "prettier-eslint": "^15.0.1", @@ -35483,6 +35749,100 @@ "@octokit/openapi-types": "^16.0.0" } }, + "@pgtyped/parser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@pgtyped/parser/-/parser-2.1.0.tgz", + "integrity": "sha512-HIHbQ8iQCPvr4JM/UcXkYlB1zFH2abFoZ9ID8S66pEwm2WUjQlwK1r+/4DRnqXFmwi+qkRPcg4KfAs5iN11eMw==", + "dev": true, + "requires": { + "antlr4ts": "0.5.0-alpha.4", + "chalk": "^4.1.0", + "debug": "^4.1.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + } + } + }, + "@pgtyped/runtime": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@pgtyped/runtime/-/runtime-2.1.0.tgz", + "integrity": "sha512-PHND3jE4VnPL23OFqAc6e2Z2V09RKp6RWh2kVfz6KsBIzj7saao2HkAVxzJNED4WNGw66OyXVPdZwOP0NY9CbA==", + "dev": true, + "requires": { + "@pgtyped/parser": "^2.1.0", + "chalk": "^4.1.0", + "debug": "^4.1.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + } + } + }, "@pnpm/config.env-replace": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.0.0.tgz", @@ -39011,6 +39371,12 @@ "integrity": "sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==", "dev": true }, + "antlr4ts": { + "version": "0.5.0-alpha.4", + "resolved": "https://registry.npmjs.org/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz", + "integrity": "sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==", + "dev": true + }, "anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -39284,6 +39650,12 @@ "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", "dev": true }, + "astring": { + "version": "1.8.4", + "resolved": "https://registry.npmjs.org/astring/-/astring-1.8.4.tgz", + "integrity": "sha512-97a+l2LBU3Op3bBQEff79i/E4jMD2ZLFD8rHx9B6mXyB2uQwhJQYfiDqUwtfjF4QA1F2qs//N6Cw8LetMbQjcw==", + "dev": true + }, "async-each": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.6.tgz", @@ -40309,6 +40681,7 @@ "requires": { "@graphql-tools/graphql-file-loader": "^7.5.16", "@graphql-tools/load": "^7.8.13", + "@pgtyped/runtime": "^2.1.0", "@sentry/node": "^7.43.0", "@sentry/types": "^7.43.0", "@sindresorhus/slugify": "^1.1.2", @@ -40353,6 +40726,7 @@ "eslint-plugin-import": "^2.27.5", "eslint-plugin-n": "^15.6.1", "eslint-plugin-promise": "^6.1.1", + "eslint-plugin-sql": "^2.3.2", "eslint-plugin-tsdoc": "^0.2.1", "express": "^4.18.2", "express-graphql": "^0.12.0", @@ -40365,7 +40739,7 @@ "graphql-type-json": "^0.3.2", "graphql-upload": "^13.0.0", "html-to-text": "^9.0.4", - "jsondiffpatch": "*", + "jsondiffpatch": "^0.4.1", "jsonwebtoken": "^9.0.0", "jszip": "^3.10.1", "knex": "^2.4.2", @@ -43583,6 +43957,19 @@ "dev": true, "requires": {} }, + "eslint-plugin-sql": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-sql/-/eslint-plugin-sql-2.3.2.tgz", + "integrity": "sha512-cyR9MdqEIkLvBI6DOEQCfAhKcLGkjhzUF+6qYvEesSdxq7IveFQQhgYjH3fSaGAde1U5Q20WjpWdpZ6awYjXzA==", + "dev": true, + "requires": { + "astring": "^1.8.3", + "debug": "^4.3.4", + "lodash": "^4.17.21", + "pg-formatter": "^1.3.0", + "sql-parse": "^0.1.5" + } + }, "eslint-plugin-tsdoc": { "version": "0.2.17", "resolved": "https://registry.npmjs.org/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.2.17.tgz", @@ -51161,6 +51548,73 @@ "integrity": "sha512-QfXcpxyN9vT+kvexQpTeNyiwCxs4LPXLAV/C0EeLTJPCF61swhGdDlnHcuDgxJudgKGfQYiCkegg0GsSKSvvEg==", "dev": true }, + "pg-formatter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/pg-formatter/-/pg-formatter-1.3.0.tgz", + "integrity": "sha512-y1kNdgD+QWzhmYCm91z/k7VGyx6BekQg6ww/krFEEhw1IIB4zEk2xaB0pmueTcc59YFetpiHIKECgHEuw6gyvg==", + "dev": true, + "requires": { + "shell-quote": "^1.7.2", + "yargs": "^17.2.1" + }, + "dependencies": { + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "yargs": { + "version": "17.7.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", + "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", + "dev": true, + "requires": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + } + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true + } + } + }, "pg-int8": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", @@ -53843,6 +54297,12 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, + "shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "dev": true + }, "shpjs": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/shpjs/-/shpjs-4.0.4.tgz", @@ -54303,6 +54763,12 @@ } } }, + "sql-parse": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/sql-parse/-/sql-parse-0.1.5.tgz", + "integrity": "sha512-e2ExBX6iDHoCDC1zN2NvZV49UMhKVLvvwrDjzSVHFS3TKHKtIpl2nMDQkdlbTjDVvf2bxRYBq9iXAAMZvZpGVA==", + "dev": true + }, "ssf": { "version": "0.11.2", "resolved": "https://registry.npmjs.org/ssf/-/ssf-0.11.2.tgz", diff --git a/packages/api/.prettierignore b/packages/api/.prettierignore index 2431a55cf..ec601c276 100644 --- a/packages/api/.prettierignore +++ b/packages/api/.prettierignore @@ -8,4 +8,5 @@ node_modules sources CHANGELOG.md oct.cas.json -titre-phases-find.cas.json \ No newline at end of file +titre-phases-find.cas.json +**/*.queries.types.ts \ No newline at end of file diff --git a/packages/api/config.json b/packages/api/config.json new file mode 100644 index 000000000..5fb69e8d0 --- /dev/null +++ b/packages/api/config.json @@ -0,0 +1,18 @@ +{ + "transforms": [ + { + "mode": "ts", + "include": "**/*.queries.ts", + "emitTemplate": "{{dir}}/{{name}}.types.ts" + } + ], + "srcDir": "./src/", + "failOnError": false, + "camelCaseColumnNames": false, + "db": { + "host": "localhost", + "user": "postgres", + "dbName": "camino", + "password": "password" + } +} diff --git a/packages/api/package.json b/packages/api/package.json index 5e17482f6..f82c05111 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -17,6 +17,7 @@ "db:recreate": "dropdb --host=localhost --username=postgres camino && createdb --host=localhost --username=postgres camino", "db:migrate": "node --loader ts-node/esm/transpile-only ./src/knex/migrate.ts", "db:add-migration": "NODE_OPTIONS='--loader ts-node/esm/transpile-only' knex migrate:make", + "db:watch": "npx --package=@pgtyped/cli pgtyped -w -c config.json", "dev": "node --watch --loader ts-node/esm/transpile-only --inspect ./src/index.ts", "daily-debug": "node --inspect-brk=3000 --loader ts-node/esm/transpile-only ./src/scripts/daily.ts", "dev:backups-archive": "tar -zcvf backups/`date +%Y%m%d_%H%M%S`-camino.tar.gz backups/files/* backups/camino.sql", @@ -99,6 +100,7 @@ "xstate": "^4.37.0" }, "devDependencies": { + "@pgtyped/runtime": "^2.1.0", "@types/carbone": "^3.2.1", "@types/cookie-parser": "^1.4.3", "@types/stream-json": "^1.7.3", @@ -113,6 +115,7 @@ "eslint-plugin-import": "^2.27.5", "eslint-plugin-n": "^15.6.1", "eslint-plugin-promise": "^6.1.1", + "eslint-plugin-sql": "^2.3.2", "eslint-plugin-tsdoc": "^0.2.1", "pg-escape": "^0.2.0", "prettier-eslint": "^15.0.1", @@ -139,9 +142,24 @@ "node": true }, "plugins": [ - "@typescript-eslint" + "@typescript-eslint", + "sql" ], "rules": { + "sql/format": [ + 2, + { + "ignoreExpressions": false, + "ignoreInline": true, + "ignoreTagless": true + } + ], + "sql/no-unsafe-query": [ + 2, + { + "allowLiteral": false + } + ], "newline-before-return": 1, "no-use-before-define": 0, "no-redeclare": 0, diff --git a/packages/api/src/api/rest/statistiques/dgtm.queries.ts b/packages/api/src/api/rest/statistiques/dgtm.queries.ts new file mode 100644 index 000000000..06ab4defc --- /dev/null +++ b/packages/api/src/api/rest/statistiques/dgtm.queries.ts @@ -0,0 +1,21 @@ +import { sql } from '@pgtyped/runtime' +import { SubstanceFiscaleId } from 'camino-common/src/static/substancesFiscales' +import { Redefine } from '../../../pg-database.js' +import { IGetProductionOrQuery } from './dgtm.queries.types.js' + +// On peut récupérer le nombre de producteurs d’or que à partir de l’année 2018. L’année à laquelle nous avons commencé à récolter les productions dans Camino +export const getProductionOr = sql<Redefine<IGetProductionOrQuery, { substance: SubstanceFiscaleId }>>` +select distinct + ta.annee, + count(distinct tt.entreprise_id) +from + titres_activites ta + left join titres t on ta.titre_id = t.id + left join titres_titulaires tt on tt.titre_etape_id = t.props_titre_etapes_ids ->> 'titulaires' +where + ta.type_id in ('gra', 'grx') + and (ta.contenu -> 'substancesFiscales' -> $ substance)::int > 0 + and ta.annee > 2017 +group by + ta.annee +` diff --git a/packages/api/src/api/rest/statistiques/dgtm.queries.types.ts b/packages/api/src/api/rest/statistiques/dgtm.queries.types.ts new file mode 100644 index 000000000..4715e1fc1 --- /dev/null +++ b/packages/api/src/api/rest/statistiques/dgtm.queries.types.ts @@ -0,0 +1,19 @@ +/** Types generated for queries found in "src/api/rest/statistiques/dgtm.queries.ts" */ + +/** 'GetProductionOr' parameters type */ +export interface IGetProductionOrParams { + substance?: string | null | void; +} + +/** 'GetProductionOr' return type */ +export interface IGetProductionOrResult { + annee: number; + count: string | null; +} + +/** 'GetProductionOr' query type */ +export interface IGetProductionOrQuery { + params: IGetProductionOrParams; + result: IGetProductionOrResult; +} + diff --git a/packages/api/src/api/rest/statistiques/dgtm.ts b/packages/api/src/api/rest/statistiques/dgtm.ts index 99dc1e928..bf9a5bb38 100644 --- a/packages/api/src/api/rest/statistiques/dgtm.ts +++ b/packages/api/src/api/rest/statistiques/dgtm.ts @@ -2,12 +2,13 @@ import { AdministrationId } from 'camino-common/src/static/administrations.js' import { TitreTypeId } from 'camino-common/src/static/titresTypes.js' import { getTitreTypeIdsByAdministration } from 'camino-common/src/static/administrationsTitresTypes.js' import { StatistiquesDGTM, TitreTypeIdDelai, titreTypeIdDelais } from 'camino-common/src/statistiques.js' -import { CaminoAnnee, CaminoDate, getAnnee, daysBetween } from 'camino-common/src/date.js' +import { CaminoAnnee, CaminoDate, getAnnee, daysBetween, toCaminoAnnee } from 'camino-common/src/date.js' import { knex } from '../../../knex.js' import { SDOMZoneId, SDOMZoneIds } from 'camino-common/src/static/sdom.js' import { ETAPES_TYPES, EtapeTypeId } from 'camino-common/src/static/etapesTypes.js' -import { SUBSTANCES_FISCALES_IDS } from 'camino-common/src/static/substancesFiscales.js' import { EtapeStatutId } from 'camino-common/src/static/etapesStatuts.js' +import { getProductionOr } from './dgtm.queries.js' +import { pool } from '../../../pg-database.js' const anneeDepartStats = 2015 @@ -215,18 +216,18 @@ export const getDGTMStatsInside = async (administrationId: AdministrationId): Pr } }) - // On peut récupérer le nombre de producteurs d’or que à partir de l’année 2018. L’année à laquelle nous avons commencé à récolter les productions dans Camino - const producteursOr: { rows: { annee: CaminoAnnee; count: string }[] } = await knex.raw(`select distinct ta.annee, count ( distinct tt.entreprise_id) - from titres_activites ta - left join titres t on ta.titre_id = t.id - left join titres_titulaires tt on tt.titre_etape_id = t.props_titre_etapes_ids->>'titulaires' - where ta.type_id in ('gra', 'grx') and (ta.contenu -> 'substancesFiscales' -> '${SUBSTANCES_FISCALES_IDS.or}')::int > 0 - and ta.annee > 2017 - group by ta.annee;`) + const producteursOr = await getProductionOr.run( + { + substance: 'auru', + }, + pool + ) - if (producteursOr && producteursOr.rows?.length) { - result.producteursOr = producteursOr.rows.reduce<Record<CaminoAnnee, number>>((acc, r) => { - acc[r.annee] = parseInt(r.count, 10) + if (producteursOr && producteursOr?.length) { + result.producteursOr = producteursOr.reduce<Record<CaminoAnnee, number>>((acc, r) => { + if (r.annee && r.count) { + acc[toCaminoAnnee(r.annee)] = parseInt(r.count, 10) + } return acc }, {}) diff --git a/packages/api/src/business/processes/titres-etapes-areas-update.test.integration.ts b/packages/api/src/business/processes/titres-etapes-areas-update.test.integration.ts index ec2012a3c..151311696 100644 --- a/packages/api/src/business/processes/titres-etapes-areas-update.test.integration.ts +++ b/packages/api/src/business/processes/titres-etapes-areas-update.test.integration.ts @@ -1,3 +1,4 @@ +/* eslint-disable sql/no-unsafe-query */ import { dbManager } from '../../../tests/db-manager.js' import { Knex } from 'knex' import Titres from '../../database/models/titres.js' diff --git a/packages/api/src/business/processes/titres-etapes-areas-update.ts b/packages/api/src/business/processes/titres-etapes-areas-update.ts index 7f2845f89..c7bcc5769 100644 --- a/packages/api/src/business/processes/titres-etapes-areas-update.ts +++ b/packages/api/src/business/processes/titres-etapes-areas-update.ts @@ -1,3 +1,4 @@ +/* eslint-disable sql/no-unsafe-query */ import { geojsonFeatureMultiPolygon, geojsonIntersectsCommunes, geojsonIntersectsSecteursMaritime, geojsonIntersectsForets, geojsonIntersectsSDOM } from '../../tools/geojson.js' import { titresEtapesGet } from '../../database/queries/titres-etapes.js' import TitresCommunes from '../../database/models/titres-communes.js' diff --git a/packages/api/src/business/processes/titres-etapes-heritage-contenu-update.ts b/packages/api/src/business/processes/titres-etapes-heritage-contenu-update.ts index 2a13ac06a..96dbc8393 100644 --- a/packages/api/src/business/processes/titres-etapes-heritage-contenu-update.ts +++ b/packages/api/src/business/processes/titres-etapes-heritage-contenu-update.ts @@ -1,3 +1,4 @@ +/* eslint-disable sql/no-unsafe-query */ import { DemarcheId, IContenu, IHeritageContenu, ITitreEtape } from '../../types.js' import { titreEtapeUpdate } from '../../database/queries/titres-etapes.js' diff --git a/packages/api/src/knex/migrations-schema/20221021121056_delete-titres-administrations.ts b/packages/api/src/knex/migrations-schema/20221021121056_delete-titres-administrations.ts index c9dfa4767..343964d27 100644 --- a/packages/api/src/knex/migrations-schema/20221021121056_delete-titres-administrations.ts +++ b/packages/api/src/knex/migrations-schema/20221021121056_delete-titres-administrations.ts @@ -1,3 +1,4 @@ +/* eslint-disable sql/no-unsafe-query */ import { Knex } from 'knex' export const up = async (knex: Knex) => { await knex.schema.alterTable('titres_etapes', function (table) { diff --git a/packages/api/src/knex/migrations-schema/20221229082906_migre-sdomzones.ts b/packages/api/src/knex/migrations-schema/20221229082906_migre-sdomzones.ts index 5546587a4..c6a64f7dc 100644 --- a/packages/api/src/knex/migrations-schema/20221229082906_migre-sdomzones.ts +++ b/packages/api/src/knex/migrations-schema/20221229082906_migre-sdomzones.ts @@ -1,3 +1,4 @@ +/* eslint-disable sql/no-unsafe-query */ import { Knex } from 'knex' export const up = async (knex: Knex) => { await knex.schema.alterTable('titres_etapes', function (table) { diff --git a/packages/api/src/pg-database.ts b/packages/api/src/pg-database.ts new file mode 100644 index 000000000..b61d900c8 --- /dev/null +++ b/packages/api/src/pg-database.ts @@ -0,0 +1,10 @@ +import pg from 'pg' + +export const pool = new pg.Pool({ + host: process.env.PGHOST, + user: process.env.PGUSER, + password: process.env.PGPASSWORD, + database: process.env.PGDATABASE, +}) + +export type Redefine<T, V> = T extends { params: infer A } ? (keyof A extends keyof V ? Omit<T, 'params'> & { params: V } : false) : false diff --git a/packages/api/src/tools/geojson.ts b/packages/api/src/tools/geojson.ts index d4183d856..3a69fff50 100644 --- a/packages/api/src/tools/geojson.ts +++ b/packages/api/src/tools/geojson.ts @@ -1,3 +1,4 @@ +/* eslint-disable sql/no-unsafe-query */ import rewind from 'geojson-rewind' import center from '@turf/center' diff --git a/packages/api/src/tools/territoires-update.ts b/packages/api/src/tools/territoires-update.ts index c222a73a0..bea36001c 100644 --- a/packages/api/src/tools/territoires-update.ts +++ b/packages/api/src/tools/territoires-update.ts @@ -1,3 +1,4 @@ +/* eslint-disable sql/no-unsafe-query */ import '../init.js' import { knex } from '../knex.js' import fetch from 'node-fetch' diff --git a/packages/api/tests/db-manager.ts b/packages/api/tests/db-manager.ts index 5780ecbc3..5f2c4214e 100644 --- a/packages/api/tests/db-manager.ts +++ b/packages/api/tests/db-manager.ts @@ -1,3 +1,4 @@ +/* eslint-disable sql/no-unsafe-query */ import { join } from 'path' import { idGenerate } from '../src/database/models/_format/id-create.js' -- GitLab