diff --git a/biome.json b/biome.json index 28d45b6..14d1258 100644 --- a/biome.json +++ b/biome.json @@ -1,7 +1,14 @@ { "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", - "vcs": { "enabled": false, "clientKind": "git", "useIgnoreFile": false }, - "files": { "ignoreUnknown": false, "ignore": ["dist"] }, + "vcs": { + "enabled": false, + "clientKind": "git", + "useIgnoreFile": false + }, + "files": { + "ignoreUnknown": false, + "ignore": ["dist"] + }, "formatter": { "enabled": true, "useEditorconfig": true, @@ -9,11 +16,13 @@ "indentStyle": "space", "indentWidth": 2, "lineEnding": "lf", - "lineWidth": 80, + "lineWidth": 240, "attributePosition": "auto", "bracketSpacing": true }, - "organizeImports": { "enabled": true }, + "organizeImports": { + "enabled": true + }, "linter": { "enabled": true, "rules": { diff --git a/epess-database b/epess-database index 63a9ad3..e4383ee 160000 --- a/epess-database +++ b/epess-database @@ -1 +1 @@ -Subproject commit 63a9ad306dddef4e6d9f4b205e24b71257cc035d +Subproject commit e4383ee3b11a271a650856ac4c5bdb05f1776a9b diff --git a/package-lock.json b/package-lock.json index a8fc8f3..7698b0a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -42,6 +42,7 @@ "@prisma/client": "^5.21.1", "@smatch-corp/nestjs-pothos": "^0.3.0", "@smatch-corp/nestjs-pothos-apollo-driver": "^0.1.0", + "@turbodocx/html-to-docx": "^1.10.0", "apollo-server-express": "^3.13.0", "axios": "^1.7.7", "bcryptjs": "^2.4.3", @@ -4123,7 +4124,6 @@ "version": "0.3.6", "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", @@ -5097,6 +5097,93 @@ "license": "MIT", "optional": true }, + "node_modules/@oozcitak/dom": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/@oozcitak/dom/-/dom-1.15.6.tgz", + "integrity": "sha512-k4uEIa6DI3FCrFJMGq/05U/59WnS9DjME0kaPqBRCJAqBTkmopbYV1Xs4qFKbDJ/9wOg8W97p+1E0heng/LH7g==", + "license": "MIT", + "dependencies": { + "@oozcitak/infra": "1.0.5", + "@oozcitak/url": "1.0.0", + "@oozcitak/util": "8.3.4" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/@oozcitak/infra": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@oozcitak/infra/-/infra-1.0.5.tgz", + "integrity": "sha512-o+zZH7M6l5e3FaAWy3ojaPIVN5eusaYPrKm6MZQt0DKNdgXa2wDYExjpP0t/zx+GoQgQKzLu7cfD8rHCLt8JrQ==", + "license": "MIT", + "dependencies": { + "@oozcitak/util": "8.0.0" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/@oozcitak/infra/node_modules/@oozcitak/util": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-8.0.0.tgz", + "integrity": "sha512-+9Hq6yuoq/3TRV/n/xcpydGBq2qN2/DEDMqNTG7rm95K6ZE2/YY/sPyx62+1n8QsE9O26e5M1URlXsk+AnN9Jw==", + "license": "MIT", + "engines": { + "node": ">=6.0" + } + }, + "node_modules/@oozcitak/url": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@oozcitak/url/-/url-1.0.0.tgz", + "integrity": "sha512-LGrMeSxeLzsdaitxq3ZmBRVOrlRRQIgNNci6L0VRnOKlJFuRIkNm4B+BObXPCJA6JT5bEJtrrwjn30jueHJYZQ==", + "license": "MIT", + "dependencies": { + "@oozcitak/infra": "1.0.3", + "@oozcitak/util": "1.0.2" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/@oozcitak/url/node_modules/@oozcitak/infra": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@oozcitak/infra/-/infra-1.0.3.tgz", + "integrity": "sha512-9O2wxXGnRzy76O1XUxESxDGsXT5kzETJPvYbreO4mv6bqe1+YSuux2cZTagjJ/T4UfEwFJz5ixanOqB0QgYAag==", + "license": "MIT", + "dependencies": { + "@oozcitak/util": "1.0.1" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/@oozcitak/url/node_modules/@oozcitak/infra/node_modules/@oozcitak/util": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-1.0.1.tgz", + "integrity": "sha512-dFwFqcKrQnJ2SapOmRD1nQWEZUtbtIy9Y6TyJquzsalWNJsKIPxmTI0KG6Ypyl8j7v89L2wixH9fQDNrF78hKg==", + "license": "MIT", + "engines": { + "node": ">=6.0" + } + }, + "node_modules/@oozcitak/url/node_modules/@oozcitak/util": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-1.0.2.tgz", + "integrity": "sha512-4n8B1cWlJleSOSba5gxsMcN4tO8KkkcvXhNWW+ADqvq9Xj+Lrl9uCa90GRpjekqQJyt84aUX015DG81LFpZYXA==", + "license": "MIT", + "engines": { + "node": ">=6.0" + } + }, + "node_modules/@oozcitak/util": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-8.3.4.tgz", + "integrity": "sha512-6gH/bLQJSJEg7OEpkH4wGQdA8KXHRbzL1YkGyUO12YNAgV3jxKy4K9kvfXj4+9T0OLug5k58cnPCKSSIKzp7pg==", + "license": "MIT", + "engines": { + "node": ">=8.0" + } + }, "node_modules/@payos/node": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/@payos/node/-/node-1.0.10.tgz", @@ -5514,6 +5601,28 @@ "dev": true, "license": "MIT" }, + "node_modules/@turbodocx/html-to-docx": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@turbodocx/html-to-docx/-/html-to-docx-1.10.0.tgz", + "integrity": "sha512-zVA/Z8kCSh4KgKmVpy3a9+DdL5Fhjbdih/OYywWSfDzG7h80mcVJRj6jN5iJWDSk/du9dtZvZ8CUNegPPf8fpg==", + "license": "MIT", + "dependencies": { + "@oozcitak/dom": "1.15.6", + "@oozcitak/util": "8.3.4", + "color-name": "^1.1.4", + "html-entities": "^2.3.3", + "html-minifier-terser": "^7.2.0", + "html-to-vdom": "^0.7.0", + "image-size": "^1.0.0", + "image-to-base64": "^2.2.0", + "jszip": "^3.7.1", + "lodash": "^4.17.21", + "mime-types": "^2.1.35", + "nanoid": "^3.1.25", + "virtual-dom": "^2.1.1", + "xmlbuilder2": "2.1.2" + } + }, "node_modules/@types/accepts": { "version": "1.3.7", "resolved": "https://registry.npmjs.org/@types/accepts/-/accepts-1.3.7.tgz", @@ -6544,7 +6653,6 @@ "version": "8.14.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", - "dev": true, "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -7690,6 +7798,12 @@ "integrity": "sha512-8CVjaLJGuSKMVTxJ2DpBl5XnlNDiT4cQFeuCJJrvJmts9YrTZDizTX7PjC2s6W4x+MBGZeEY6dGMrF04/6Hgqg==", "license": "MIT" }, + "node_modules/browser-split": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/browser-split/-/browser-split-0.0.1.tgz", + "integrity": "sha512-JhvgRb2ihQhsljNda3BI8/UcRHVzrVwo3Q+P8vDtSiyobXuFpuZ9mq+MbRGMnC22CjW3RrfXdg6j6ITX8M+7Ow==", + "license": "MIT" + }, "node_modules/browserslist": { "version": "4.24.2", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", @@ -7912,6 +8026,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/camelize": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz", + "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/caniuse-lite": { "version": "1.0.30001676", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001676.tgz", @@ -9046,6 +9169,11 @@ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, + "node_modules/dom-walk": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", + "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==" + }, "node_modules/domelementtype": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", @@ -9293,6 +9421,24 @@ "node": ">=10.13.0" } }, + "node_modules/ent": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.1.tgz", + "integrity": "sha512-QHuXVeZx9d+tIQAz/XztU0ZwZf2Agg9CcXcgE1rurqvdBeDBrpSwjl8/6XUqMg7tw2Y7uAdKb2sRv+bSEFqQ5A==", + "license": "MIT", + "dependencies": { + "punycode": "^1.4.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ent/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "license": "MIT" + }, "node_modules/entities": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", @@ -9309,6 +9455,16 @@ "resolved": "", "link": true }, + "node_modules/error": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/error/-/error-4.4.0.tgz", + "integrity": "sha512-SNDKualLUtT4StGFP7xNfuFybL2f6iJujFtrWuvJqGbVQGaN+adE23veqzPz1hjUjTunLi2EnJ+0SJxtbJreKw==", + "dependencies": { + "camelize": "^1.0.0", + "string-template": "~0.2.0", + "xtend": "~4.0.0" + } + }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -9645,6 +9801,14 @@ "node": ">= 0.6" } }, + "node_modules/ev-store": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ev-store/-/ev-store-7.0.0.tgz", + "integrity": "sha512-otazchNRnGzp2YarBJ+GXKVGvhxVATB1zmaStxJBYet0Dyq7A9VhH8IUEB/gRcL6Ch52lfpgPTRJ2m49epyMsQ==", + "dependencies": { + "individual": "^3.0.0" + } + }, "node_modules/event-target-shim": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", @@ -10500,6 +10664,16 @@ "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "license": "BSD-2-Clause" }, + "node_modules/global": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", + "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==", + "license": "MIT", + "dependencies": { + "min-document": "^2.19.0", + "process": "^0.11.10" + } + }, "node_modules/globals": { "version": "15.11.0", "resolved": "https://registry.npmjs.org/globals/-/globals-15.11.0.tgz", @@ -10996,6 +11170,22 @@ "node": ">=18" } }, + "node_modules/html-entities": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", + "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ], + "license": "MIT" + }, "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", @@ -11025,6 +11215,57 @@ "node": ">=6" } }, + "node_modules/html-minifier-terser": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-7.2.0.tgz", + "integrity": "sha512-tXgn3QfqPIpGl9o+K5tpcj3/MN4SfLtsx2GWwBC3SSd0tXQGyF3gsSqad8loJgKZGM3ZxbYDd5yhiBIdWpmvLA==", + "license": "MIT", + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "~5.3.2", + "commander": "^10.0.0", + "entities": "^4.4.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.15.1" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": "^14.13.1 || >=16.0.0" + } + }, + "node_modules/html-minifier-terser/node_modules/clean-css": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", + "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", + "license": "MIT", + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 10.0" + } + }, + "node_modules/html-minifier-terser/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/html-minifier-terser/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/html-minifier/node_modules/camel-case": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", @@ -11094,6 +11335,92 @@ "node": ">=14" } }, + "node_modules/html-to-vdom": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/html-to-vdom/-/html-to-vdom-0.7.0.tgz", + "integrity": "sha512-k+d2qNkbx0JO00KezQsNcn6k2I/xSBP4yXYFLvXbcasTTDh+RDLUJS3puxqyNnpdyXWRHFGoKU7cRmby8/APcQ==", + "license": "ISC", + "dependencies": { + "ent": "^2.0.0", + "htmlparser2": "^3.8.2" + } + }, + "node_modules/html-to-vdom/node_modules/dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "license": "MIT", + "dependencies": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + } + }, + "node_modules/html-to-vdom/node_modules/dom-serializer/node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/html-to-vdom/node_modules/dom-serializer/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "license": "BSD-2-Clause", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/html-to-vdom/node_modules/domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "license": "BSD-2-Clause" + }, + "node_modules/html-to-vdom/node_modules/domhandler": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "1" + } + }, + "node_modules/html-to-vdom/node_modules/domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "node_modules/html-to-vdom/node_modules/entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", + "license": "BSD-2-Clause" + }, + "node_modules/html-to-vdom/node_modules/htmlparser2": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", + "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", + "license": "MIT", + "dependencies": { + "domelementtype": "^1.3.1", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "inherits": "^2.0.1", + "readable-stream": "^3.1.1" + } + }, "node_modules/htmlparser2": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", @@ -11218,6 +11545,36 @@ "node": ">= 4" } }, + "node_modules/image-size": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.1.1.tgz", + "integrity": "sha512-541xKlUw6jr/6gGuk92F+mYM5zaFAc5ahphvkqvNe2bQ6gVBkd6bfrmVJ2t4KDAfikAYZyIqTnktX3i6/aQDrQ==", + "license": "MIT", + "dependencies": { + "queue": "6.0.2" + }, + "bin": { + "image-size": "bin/image-size.js" + }, + "engines": { + "node": ">=16.x" + } + }, + "node_modules/image-to-base64": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/image-to-base64/-/image-to-base64-2.2.0.tgz", + "integrity": "sha512-Z+aMwm/91UOQqHhrz7Upre2ytKhWejZlWV/JxUTD1sT7GWWKFDJUEV5scVQKnkzSgPHFuQBUEWcanO+ma0PSVw==", + "license": "MIT", + "dependencies": { + "node-fetch": "^2.6.0" + } + }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "license": "MIT" + }, "node_modules/immutable": { "version": "3.7.6", "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.7.6.tgz", @@ -11306,6 +11663,11 @@ "node": ">=8" } }, + "node_modules/individual": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/individual/-/individual-3.0.0.tgz", + "integrity": "sha512-rUY5vtT748NMRbEMrTNiFfy29BgGZwGXUi2NFUVMWQrogSLzlJvQV9eeMWi+g1aVaQ53tpyLAQtd5x/JH0Nh1g==" + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -11599,6 +11961,15 @@ "node": ">=0.12.0" } }, + "node_modules/is-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz", + "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-path-inside": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", @@ -12895,6 +13266,48 @@ "promise": "^7.0.1" } }, + "node_modules/jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "license": "(MIT OR GPL-3.0-or-later)", + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, + "node_modules/jszip/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/jszip/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/jszip/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/juice": { "version": "10.0.1", "resolved": "https://registry.npmjs.org/juice/-/juice-10.0.1.tgz", @@ -13067,6 +13480,15 @@ "license": "MIT", "optional": true }, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "license": "MIT", + "dependencies": { + "immediate": "~3.0.5" + } + }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -13765,6 +14187,14 @@ "node": ">=6" } }, + "node_modules/min-document": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", + "integrity": "sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ==", + "dependencies": { + "dom-walk": "^0.1.0" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -14384,6 +14814,24 @@ "dev": true, "license": "ISC" }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -14420,6 +14868,12 @@ "@nestjs/core": ">7.0.0" } }, + "node_modules/next-tick": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-0.2.2.tgz", + "integrity": "sha512-f7h4svPtl+QidoBv4taKXUjJ70G2asaZ8G28nS0OkqaalX8dwwrtWtyxEDPK62AC00ur/+/E0pUwBwY5EPn15Q==", + "license": "MIT" + }, "node_modules/nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", @@ -14898,6 +15352,12 @@ "devOptional": true, "license": "BlueOak-1.0.0" }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "license": "(MIT AND Zlib)" + }, "node_modules/param-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", @@ -15384,6 +15844,15 @@ "fsevents": "2.3.3" } }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -15665,6 +16134,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/queue": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", + "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", + "license": "MIT", + "dependencies": { + "inherits": "~2.0.3" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -15890,7 +16368,6 @@ "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", "license": "MIT", - "optional": true, "engines": { "node": ">= 0.10" } @@ -16630,7 +17107,6 @@ "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", @@ -16641,7 +17117,6 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -16778,6 +17253,11 @@ "node": ">=10" } }, + "node_modules/string-template": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", + "integrity": "sha512-Yptehjogou2xm4UJbxJ4CxgZx12HBfeystp0y3x7s4Dj32ltVVG1Gg8YhKjHZkHicuKpZX/ffilA8505VbUbpw==" + }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -17104,7 +17584,6 @@ "version": "5.36.0", "resolved": "https://registry.npmjs.org/terser/-/terser-5.36.0.tgz", "integrity": "sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "@jridgewell/source-map": "^0.3.3", @@ -17189,7 +17668,6 @@ "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true, "license": "MIT" }, "node_modules/test-exclude": { @@ -17978,6 +18456,22 @@ "node": ">= 0.8" } }, + "node_modules/virtual-dom": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/virtual-dom/-/virtual-dom-2.1.1.tgz", + "integrity": "sha512-wb6Qc9Lbqug0kRqo/iuApfBpJJAq14Sk1faAnSmtqXiwahg7PVTvWMs9L02Z8nNIMqbwsxzBAA90bbtRLbw0zg==", + "license": "MIT", + "dependencies": { + "browser-split": "0.0.1", + "error": "^4.3.0", + "ev-store": "^7.0.0", + "global": "^4.3.0", + "is-object": "^1.0.1", + "next-tick": "^0.2.2", + "x-is-array": "0.1.0", + "x-is-string": "0.1.0" + } + }, "node_modules/void-elements": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", @@ -18476,6 +18970,16 @@ } } }, + "node_modules/x-is-array": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/x-is-array/-/x-is-array-0.1.0.tgz", + "integrity": "sha512-goHPif61oNrr0jJgsXRfc8oqtYzvfiMJpTqwE7Z4y9uH+T3UozkGqQ4d2nX9mB9khvA8U2o/UbPOFjgC7hLWIA==" + }, + "node_modules/x-is-string": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz", + "integrity": "sha512-GojqklwG8gpzOVEVki5KudKNoq7MbbjYZCbyWzEz7tyPA7eleiE0+ePwOWQQRb5fm86rD3S8Tc0tSFf3AOv50w==" + }, "node_modules/xml-name-validator": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", @@ -18507,6 +19011,52 @@ "node": ">=4.0" } }, + "node_modules/xmlbuilder2": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xmlbuilder2/-/xmlbuilder2-2.1.2.tgz", + "integrity": "sha512-PI710tmtVlQ5VmwzbRTuhmVhKnj9pM8Si+iOZCV2g2SNo3gCrpzR2Ka9wNzZtqfD+mnP+xkrqoNy0sjKZqP4Dg==", + "license": "MIT", + "dependencies": { + "@oozcitak/dom": "1.15.5", + "@oozcitak/infra": "1.0.5", + "@oozcitak/util": "8.3.3" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/xmlbuilder2/node_modules/@oozcitak/dom": { + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/@oozcitak/dom/-/dom-1.15.5.tgz", + "integrity": "sha512-L6v3Mwb0TaYBYgeYlIeBaHnc+2ZEaDSbFiRm5KmqZQSoBlbPlf+l6aIH/sD5GUf2MYwULw00LT7+dOnEuAEC0A==", + "license": "MIT", + "dependencies": { + "@oozcitak/infra": "1.0.5", + "@oozcitak/url": "1.0.0", + "@oozcitak/util": "8.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/xmlbuilder2/node_modules/@oozcitak/dom/node_modules/@oozcitak/util": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-8.0.0.tgz", + "integrity": "sha512-+9Hq6yuoq/3TRV/n/xcpydGBq2qN2/DEDMqNTG7rm95K6ZE2/YY/sPyx62+1n8QsE9O26e5M1URlXsk+AnN9Jw==", + "license": "MIT", + "engines": { + "node": ">=6.0" + } + }, + "node_modules/xmlbuilder2/node_modules/@oozcitak/util": { + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-8.3.3.tgz", + "integrity": "sha512-Ufpab7G5PfnEhQyy5kDg9C8ltWJjsVT1P/IYqacjstaqydG4Q21HAT2HUZQYBrC/a1ZLKCz87pfydlDvv8y97w==", + "license": "MIT", + "engines": { + "node": ">=6.0" + } + }, "node_modules/xmlchars": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", diff --git a/package.json b/package.json index 17e09c5..f88243a 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,7 @@ "@prisma/client": "^5.21.1", "@smatch-corp/nestjs-pothos": "^0.3.0", "@smatch-corp/nestjs-pothos-apollo-driver": "^0.1.0", + "@turbodocx/html-to-docx": "^1.10.0", "apollo-server-express": "^3.13.0", "axios": "^1.7.7", "bcryptjs": "^2.4.3", diff --git a/src/CenterMentor/centermentor.schema.ts b/src/CenterMentor/centermentor.schema.ts index 4dcffe7..2d5c9cf 100644 --- a/src/CenterMentor/centermentor.schema.ts +++ b/src/CenterMentor/centermentor.schema.ts @@ -155,7 +155,7 @@ export class CenterMentorSchema extends PothosSchema { } // build signature const token = this.jwtUtils.signTokenRS256( - JSON.stringify({ centerId: center.id, email: args.email }), + { centerId: center.id, email: args.email }, '1d', ) // build invite url @@ -185,7 +185,7 @@ export class CenterMentorSchema extends PothosSchema { return this.prisma.$transaction(async () => { // sign token const token = this.jwtUtils.signTokenRS256( - JSON.stringify({ centerId: args.centerId, email: args.email }), + { centerId: args.centerId, email: args.email }, '1d', ) // build invite url diff --git a/src/Document/document.schema.ts b/src/Document/document.schema.ts index 0663368..d9e0ece 100644 --- a/src/Document/document.schema.ts +++ b/src/Document/document.schema.ts @@ -11,11 +11,13 @@ import { DocumentEvent } from './document.event' import { Document } from '@prisma/client' import { DocumentDelta } from './document.type' import Delta from 'quill-delta' +import { MinioService } from 'src/Minio/minio.service' @Injectable() export class DocumentSchema extends PothosSchema { constructor( @Inject(SchemaBuilderToken) private readonly builder: Builder, private readonly prisma: PrismaService, + private readonly minio: MinioService, ) { super() } @@ -46,6 +48,7 @@ export class DocumentSchema extends PothosSchema { delta: t.field({ type: 'Delta', }), + senderId: t.string(), }), }) } @@ -88,6 +91,30 @@ export class DocumentSchema extends PothosSchema { }) }, }), + newDocument: t.field({ + type: this.document(), + args: {}, + resolve: async (query, _args, ctx, _info) => { + if (ctx.isSubscription) throw new Error('Not allowed') + const userId = ctx.http?.me?.id + if (!userId) throw new Error('User not found') + const fileUrl = await this.minio.getFileUrl( + 'document', + 'document', + 'document', + ) + if (!fileUrl) throw new Error('File not found') + const document = await this.prisma.document.create({ + ...query, + data: { + name: 'Untitled', + fileUrl, + ownerId: userId, + }, + }) + return document + }, + }), })) this.builder.mutationFields((t) => ({ @@ -99,10 +126,16 @@ export class DocumentSchema extends PothosSchema { required: true, }), }, - resolve: async (query, _root, args) => { + resolve: async (query, _root, args, ctx: SchemaContext) => { + if (ctx.isSubscription) throw new Error('Not allowed') + const userId = ctx.http?.me?.id + if (!userId) throw new Error('User not found') return await this.prisma.document.create({ ...query, - data: args.data, + data: { + ...args.data, + // ownerId: userId, + }, }) }, }), @@ -120,6 +153,7 @@ export class DocumentSchema extends PothosSchema { documentId: args.documentId, pageIndex: args.pageIndex, delta, + senderId: ctx.http?.me?.id, } ctx.http.pubSub.publish( `${DocumentEvent.CHANGED}.${args.documentId}`, @@ -142,10 +176,12 @@ export class DocumentSchema extends PothosSchema { const { http: { pubSub }, } = ctx - pubSub.publish( - `${DocumentEvent.CHANGED}.${args.data.documentId}`, - args.data, - ) + const senderId = ctx.http?.me?.id + if (!senderId) throw new Error('User not found') + pubSub.publish(`${DocumentEvent.CHANGED}.${args.data.documentId}`, { + ...args.data, + senderId, + }) return args.data }, }), @@ -172,7 +208,11 @@ export class DocumentSchema extends PothosSchema { `${DocumentEvent.SAVED}.${args.documentId}`, ]) as unknown as AsyncIterable }, - resolve: async (payload: DocumentDelta) => payload, + resolve: async (payload: DocumentDelta, _args, ctx: SchemaContext) => { + if (!ctx.isSubscription) throw new Error('Not allowed') + if (payload.senderId === ctx.websocket?.me?.id) return + return payload + }, }), })) } diff --git a/src/Document/document.service.ts b/src/Document/document.service.ts index 25b2ab3..0d6762e 100644 --- a/src/Document/document.service.ts +++ b/src/Document/document.service.ts @@ -31,7 +31,7 @@ export class DocumentService { const { default: Quill } = await import('quill') this.quill = Quill } - + // TODO: maybe never do :) async handleOnChange(delta: DocumentDelta) {} async handleOnSave() {} diff --git a/src/Document/document.type.ts b/src/Document/document.type.ts index 813ec69..9638b67 100644 --- a/src/Document/document.type.ts +++ b/src/Document/document.type.ts @@ -3,4 +3,5 @@ import Delta from 'quill-delta' export type DocumentDelta = Delta & { pageIndex: number documentId: string + senderId?: string } diff --git a/src/Graphql/graphql.builder.ts b/src/Graphql/graphql.builder.ts index 47a0764..7ddd25e 100644 --- a/src/Graphql/graphql.builder.ts +++ b/src/Graphql/graphql.builder.ts @@ -34,6 +34,7 @@ export type SchemaContext = websocket: { req: Request pubSub: PubSub + sessionId: string me: User generator: PrismaCrudGenerator } @@ -159,8 +160,8 @@ export class Builder extends SchemaBuilder { }, }) this.scalarType('Delta', { - serialize: (value) => value.toString(), - parseValue: (value: unknown) => value as unknown as Delta, + serialize: (value) => JSON.stringify(value), + parseValue: (value: unknown) => JSON.parse(value as string) as Delta, parseLiteral: (ast: ValueNode) => ast as unknown as Delta, }) diff --git a/src/Graphql/graphql.module.ts b/src/Graphql/graphql.module.ts index 0112351..70cc6bf 100644 --- a/src/Graphql/graphql.module.ts +++ b/src/Graphql/graphql.module.ts @@ -41,6 +41,7 @@ import { WorkshopSubscriptionModule } from '../WorkshopSubscription/workshopsubs import { initContextCache } from '@pothos/core' import { PubSub } from 'graphql-subscriptions' import { DocumentModule } from 'src/Document/document.module' +import { Context } from 'graphql-ws' @Global() @Module({ @@ -90,25 +91,43 @@ import { DocumentModule } from 'src/Document/document.module' debug: process.env.NODE_ENV === 'development' || false, playground: process.env.NODE_ENV === 'development' || false, introspection: process.env.NODE_ENV === 'development' || false, + installSubscriptionHandlers: true, subscriptions: { - 'graphql-ws': true, + 'graphql-ws': { + onConnect: (ctx: Context>) => { + if (!ctx.connectionParams) { + throw new Error('No connectionParams provided') + } + if (!ctx.extra) { + throw new Error('No extra provided') + } + // @ts-expect-error: TODO + ctx.extra.request.headers['x-session-id'] = ctx.connectionParams['x-session-id'] + }, + }, }, context: async ({ req, subscriptions, extra, - // biome-ignore lint/suspicious/noExplicitAny: - }: { req?: Request; subscriptions?: any; extra?: any }) => { + }: { + req?: Request + subscriptions?: Record + extra?: Record + }) => { initContextCache() if (subscriptions) { + // @ts-expect-error: TODO + if (!extra?.request?.headers['x-session-id']) { + throw new Error('No sessionId provided') + } return { isSubscription: true, websocket: { - req: extra.request, + req: extra?.request, pubSub: pubsub, - me: await graphqlService.acquireContext( - extra.request.headers['x-session-id'], - ), + // @ts-expect-error: TODO + me: await graphqlService.acquireContextFromSessionId(extra.request.headers['x-session-id']), }, } } @@ -118,10 +137,7 @@ import { DocumentModule } from 'src/Document/document.module' req, me: req ? await graphqlService.acquireContext(req) : null, pubSub: pubsub, - invalidateCache: () => - graphqlService.invalidateCache( - req?.headers['x-session-id'] as string, - ), + invalidateCache: () => graphqlService.invalidateCache(req?.headers['x-session-id'] as string), }, } }, @@ -132,8 +148,7 @@ import { DocumentModule } from 'src/Document/document.module' RedisService, { provide: GraphqlService, - useFactory: (prisma: PrismaService, redis: RedisService) => - new GraphqlService(prisma, redis), + useFactory: (prisma: PrismaService, redis: RedisService) => new GraphqlService(prisma, redis), inject: [PrismaService, 'REDIS_CLIENT'], }, { @@ -151,12 +166,6 @@ import { DocumentModule } from 'src/Document/document.module' useFactory: () => new PubSub(), }, ], - exports: [ - Builder, - PrismaCrudGenerator, - GraphqlService, - RedisService, - 'PUB_SUB', - ], + exports: [Builder, PrismaCrudGenerator, GraphqlService, RedisService, 'PUB_SUB'], }) export class GraphqlModule {} diff --git a/src/Graphql/graphql.service.ts b/src/Graphql/graphql.service.ts index 01edcea..78bccac 100644 --- a/src/Graphql/graphql.service.ts +++ b/src/Graphql/graphql.service.ts @@ -18,6 +18,12 @@ export class GraphqlService { @Inject('REDIS_CLIENT') private readonly redis: RedisService, ) {} + async acquireContextFromSessionId(sessionId: string) { + return this.acquireContext({ + headers: { 'x-session-id': sessionId }, + } as unknown as Request) + } + async acquireContext(req: Request) { // get x-session-id from headers let sessionId: string diff --git a/src/User/user.schema.ts b/src/User/user.schema.ts index db5ce8d..4dbd043 100644 --- a/src/User/user.schema.ts +++ b/src/User/user.schema.ts @@ -433,7 +433,6 @@ export class UserSchema extends PothosSchema { const { websocket: { pubSub }, } = ctx - Logger.log(ctx.websocket.me?.id, 'Me ID') return pubSub.asyncIterator([ `${PubSubEvent.NEW_MESSAGE}.${ctx.websocket.me?.id}`, ]) as unknown as AsyncIterable diff --git a/src/common/utils/jwt.utils.ts b/src/common/utils/jwt.utils.ts index 81959ea..3932433 100644 --- a/src/common/utils/jwt.utils.ts +++ b/src/common/utils/jwt.utils.ts @@ -4,10 +4,10 @@ import { Injectable } from '@nestjs/common' @Injectable() export class JwtUtils { - signToken(payload: string, expiresIn: string) { + signToken(payload: object, expiresIn: string) { return sign(payload, process.env.JWT_SECRET!, { expiresIn }) } - signTokenRS256(payload: string, expiresIn: string) { + signTokenRS256(payload: object, expiresIn: string) { const privateKey = process.env.JWT_RS256_PRIVATE_KEY if (!privateKey) { throw new Error('JWT_RS256_PRIVATE_KEY is not defined') diff --git a/src/main.ts b/src/main.ts index 078fbf5..47e6fda 100644 --- a/src/main.ts +++ b/src/main.ts @@ -7,54 +7,32 @@ import { clerkMiddleware } from '@clerk/express' import graphqlUploadExpress from 'graphql-upload/graphqlUploadExpress.js' import path from 'node:path' import { readFileSync } from 'node:fs' +import { json } from 'express' async function bootstrap() { const app = await NestFactory.create(AppModule) - // load private key and public key - const privateKey = readFileSync( - path.join(__dirname, 'KeyStore', 'private_key.pem'), - 'utf8', - ) - const publicKey = readFileSync( - path.join(__dirname, 'KeyStore', 'public_key.pem'), - 'utf8', - ) + const privateKey = readFileSync(path.join(__dirname, 'KeyStore', 'private_key.pem'), 'utf8') + const publicKey = readFileSync(path.join(__dirname, 'KeyStore', 'public_key.pem'), 'utf8') // set private key and public key to env process.env.JWT_RS256_PRIVATE_KEY = privateKey process.env.JWT_RS256_PUBLIC_KEY = publicKey - Logger.log( - `Private key: ${privateKey.slice(0, 10).replace(/\n/g, '')}...`, - 'Bootstrap', - ) - Logger.log( - `Public key: ${publicKey.slice(0, 10).replace(/\n/g, '')}...`, - 'Bootstrap', - ) + Logger.log(`Private key: ${privateKey.slice(0, 10).replace(/\n/g, '')}...`, 'Bootstrap') + Logger.log(`Public key: ${publicKey.slice(0, 10).replace(/\n/g, '')}...`, 'Bootstrap') const corsOrigin = (process.env.CORS_ORIGIN ?? '').split(',') // split by comma to array app.enableCors({ origin: corsOrigin, methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'], - allowedHeaders: [ - 'Content-Type', - '*', - 'x-apollo-operation-name', - 'x-session-id', - ], + allowedHeaders: ['Content-Type', '*', 'x-apollo-operation-name', 'x-session-id'], credentials: true, }) // set base path for api app.setGlobalPrefix(process.env.API_PATH ?? '/v1') - const config = new DocumentBuilder() - .setTitle('EPESS API') - .setDescription('API documentation for EPESS application') - .setVersion('0.0.1') - .addBearerAuth() - .build() + const config = new DocumentBuilder().setTitle('EPESS API').setDescription('API documentation for EPESS application').setVersion('0.0.1').addBearerAuth().build() const document = SwaggerModule.createDocument(app, config) SwaggerModule.setup(process.env.SWAGGER_PATH ?? 'v1', app, document) @@ -63,8 +41,7 @@ async function bootstrap() { get: { tags: ['GraphQL'], summary: 'GraphQL Playground', - description: - 'Access the GraphQL Playground to interact with the GraphQL API.', + description: 'Access the GraphQL Playground to interact with the GraphQL API.', responses: { '200': { description: 'GraphQL Playground', @@ -74,6 +51,9 @@ async function bootstrap() { } try { + // body parser + app.use(json({ limit: '50mb' })) + // clerk middleware app.use(clerkMiddleware({})) @@ -87,10 +67,7 @@ async function bootstrap() { ) // biome-ignore lint/suspicious/noExplicitAny: } catch (error: any) { - Logger.error( - `Error in file upload middleware: ${error.message}`, - 'Bootstrap', - ) + Logger.error(`Error in file upload middleware: ${error.message}`, 'Bootstrap') // Optionally, you can handle the error further or rethrow it }