From 6cfb93cab2654f1286562c8e8bfcc9168927b2c8 Mon Sep 17 00:00:00 2001 From: ymc9 <104139426+ymc9@users.noreply.github.com> Date: Sat, 9 Dec 2023 15:08:32 +0800 Subject: [PATCH 1/4] add redwood package --- packages/misc/LICENSE | 21 +++ packages/misc/redwood/LICENSE | 1 + packages/misc/redwood/README.md | 5 + packages/misc/redwood/package.json | 48 +++++++ packages/misc/redwood/src/index.ts | 14 ++ packages/misc/redwood/src/setup.ts | 1 + packages/misc/redwood/tsconfig.json | 8 ++ pnpm-lock.yaml | 202 +++++++++++++++++++++++++++- pnpm-workspace.yaml | 1 + 9 files changed, 299 insertions(+), 2 deletions(-) create mode 100644 packages/misc/LICENSE create mode 120000 packages/misc/redwood/LICENSE create mode 100644 packages/misc/redwood/README.md create mode 100644 packages/misc/redwood/package.json create mode 100644 packages/misc/redwood/src/index.ts create mode 100644 packages/misc/redwood/src/setup.ts create mode 100644 packages/misc/redwood/tsconfig.json diff --git a/packages/misc/LICENSE b/packages/misc/LICENSE new file mode 100644 index 000000000..91d4584d3 --- /dev/null +++ b/packages/misc/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 ZenStack + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/misc/redwood/LICENSE b/packages/misc/redwood/LICENSE new file mode 120000 index 000000000..5853aaea5 --- /dev/null +++ b/packages/misc/redwood/LICENSE @@ -0,0 +1 @@ +../../../LICENSE \ No newline at end of file diff --git a/packages/misc/redwood/README.md b/packages/misc/redwood/README.md new file mode 100644 index 000000000..ee9e8c003 --- /dev/null +++ b/packages/misc/redwood/README.md @@ -0,0 +1,5 @@ +# ZenStack RedwoodJS Integration + +This package is for integrating ZenStack into [RedwoodJS](https://redwoodjs.com/) projects. + +Visit [Homepage](https://zenstack.dev) for more details. diff --git a/packages/misc/redwood/package.json b/packages/misc/redwood/package.json new file mode 100644 index 000000000..4140dbf88 --- /dev/null +++ b/packages/misc/redwood/package.json @@ -0,0 +1,48 @@ +{ + "name": "@zenstackhq/redwood", + "displayName": "ZenStack RedwoodJS setup and runtime package", + "version": "0.5.0", + "description": "For using ZenStack with RedwoodJS projects.", + "repository": { + "type": "git", + "url": "https://github.com/zenstackhq/zenstack" + }, + "scripts": { + "clean": "rimraf dist", + "build": "pnpm lint --max-warnings=0 && pnpm clean && tsc && copyfiles ./package.json ./README.md ../../LICENSE dist", + "watch": "concurrently \"tsc --watch\" \"tsup-node --config ./tsup-browser.config.ts --watch\" \"tsup-node --config ./tsup-cross.config.ts --watch\"", + "lint": "eslint src --ext ts", + "prepublishOnly": "pnpm build" + }, + "main": "index.js", + "types": "index.d.ts", + "exports": { + ".": { + "default": "./index.js", + "types": "./index.d.ts" + }, + "./setup": { + "default": "./setup.js" + }, + "./package.json": { + "default": "./package.json" + } + }, + "publishConfig": { + "directory": "dist", + "linkDirectory": true + }, + "author": { + "name": "ZenStack Team" + }, + "homepage": "https://zenstack.dev", + "license": "MIT", + "bin": "node setup.js", + "dependencies": { + "@zenstackhq/runtime": "workspace:*", + "colors": "1.4.0" + }, + "devDependencies": { + "graphql-yoga": "^5.0.2" + } +} diff --git a/packages/misc/redwood/src/index.ts b/packages/misc/redwood/src/index.ts new file mode 100644 index 000000000..64931cd31 --- /dev/null +++ b/packages/misc/redwood/src/index.ts @@ -0,0 +1,14 @@ +import { enhance, type AuthUser } from '@zenstackhq/runtime'; +import { type Plugin } from 'graphql-yoga'; + +export function useZenStack( + db: PrismaClient +): Plugin<{ currentUser: AuthUser; db: PrismaClient }> { + return { + onContextBuilding() { + return ({ context }) => { + context.db = enhance(db, { user: context?.currentUser }); + }; + }, + }; +} diff --git a/packages/misc/redwood/src/setup.ts b/packages/misc/redwood/src/setup.ts new file mode 100644 index 000000000..db1c296ff --- /dev/null +++ b/packages/misc/redwood/src/setup.ts @@ -0,0 +1 @@ +console.log('Setup redwood'); diff --git a/packages/misc/redwood/tsconfig.json b/packages/misc/redwood/tsconfig.json new file mode 100644 index 000000000..a11845a55 --- /dev/null +++ b/packages/misc/redwood/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "lib": ["ESNext"], + "outDir": "dist" + }, + "include": ["src/**/*.ts"] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 287b72216..fe419f07d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -68,6 +68,20 @@ importers: version: 1.2.0 publishDirectory: dist + packages/misc/redwood: + dependencies: + '@zenstackhq/runtime': + specifier: workspace:* + version: link:../../runtime/dist + colors: + specifier: 1.4.0 + version: 1.4.0 + devDependencies: + graphql-yoga: + specifier: ^5.0.2 + version: 5.0.2(graphql@16.8.1) + publishDirectory: dist + packages/plugins/openapi: dependencies: '@prisma/generator-helper': @@ -573,7 +587,7 @@ importers: version: 2.0.2 prettier: specifier: ^2.8.3 - version: 2.8.3 + version: 2.8.8 semver: specifier: ^7.3.8 version: 7.5.3 @@ -1506,6 +1520,21 @@ packages: '@jridgewell/trace-mapping': 0.3.9 dev: true + /@envelop/core@5.0.0: + resolution: {integrity: sha512-aJdnH/ptv+cvwfvciCBe7TSvccBwo9g0S5f6u35TBVzRVqIGkK03lFlIL+x1cnfZgN9EfR2b1PH2galrT1CdCQ==} + engines: {node: '>=18.0.0'} + dependencies: + '@envelop/types': 5.0.0 + tslib: 2.6.0 + dev: true + + /@envelop/types@5.0.0: + resolution: {integrity: sha512-IPjmgSc4KpQRlO4qbEDnBEixvtb06WDmjKfi/7fkZaryh5HuOmTtixe1EupQI5XfXO8joc3d27uUZ0QdC++euA==} + engines: {node: '>=18.0.0'} + dependencies: + tslib: 2.6.0 + dev: true + /@esbuild/android-arm64@0.17.19: resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==} engines: {node: '>=12'} @@ -2182,6 +2211,90 @@ packages: fast-json-stringify: 5.7.0 dev: true + /@graphql-tools/executor@1.2.0(graphql@16.8.1): + resolution: {integrity: sha512-SKlIcMA71Dha5JnEWlw4XxcaJ+YupuXg0QCZgl2TOLFz4SkGCwU/geAsJvUJFwK2RbVLpQv/UMq67lOaBuwDtg==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/utils': 10.0.11(graphql@16.8.1) + '@graphql-typed-document-node/core': 3.2.0(graphql@16.8.1) + '@repeaterjs/repeater': 3.0.5 + graphql: 16.8.1 + tslib: 2.6.0 + value-or-promise: 1.0.12 + dev: true + + /@graphql-tools/merge@9.0.1(graphql@16.8.1): + resolution: {integrity: sha512-hIEExWO9fjA6vzsVjJ3s0cCQ+Q/BEeMVJZtMXd7nbaVefVy0YDyYlEkeoYYNV3NVVvu1G9lr6DM1Qd0DGo9Caw==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/utils': 10.0.11(graphql@16.8.1) + graphql: 16.8.1 + tslib: 2.6.0 + dev: true + + /@graphql-tools/schema@10.0.2(graphql@16.8.1): + resolution: {integrity: sha512-TbPsIZnWyDCLhgPGnDjt4hosiNU2mF/rNtSk5BVaXWnZqvKJ6gzJV4fcHcvhRIwtscDMW2/YTnK6dLVnk8pc4w==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/merge': 9.0.1(graphql@16.8.1) + '@graphql-tools/utils': 10.0.11(graphql@16.8.1) + graphql: 16.8.1 + tslib: 2.6.0 + value-or-promise: 1.0.12 + dev: true + + /@graphql-tools/utils@10.0.11(graphql@16.8.1): + resolution: {integrity: sha512-vVjXgKn6zjXIlYBd7yJxCVMYGb5j18gE3hx3Qw3mNsSEsYQXbJbPdlwb7Fc9FogsJei5AaqiQerqH4kAosp1nQ==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-typed-document-node/core': 3.2.0(graphql@16.8.1) + cross-inspect: 1.0.0 + dset: 3.1.3 + graphql: 16.8.1 + tslib: 2.6.0 + dev: true + + /@graphql-typed-document-node/core@3.2.0(graphql@16.8.1): + resolution: {integrity: sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + graphql: 16.8.1 + dev: true + + /@graphql-yoga/logger@2.0.0: + resolution: {integrity: sha512-Mg8psdkAp+YTG1OGmvU+xa6xpsAmSir0hhr3yFYPyLNwzUj95DdIwsMpKadDj9xDpYgJcH3Hp/4JMal9DhQimA==} + engines: {node: '>=18.0.0'} + dependencies: + tslib: 2.6.0 + dev: true + + /@graphql-yoga/subscription@5.0.0: + resolution: {integrity: sha512-Ri7sK8hmxd/kwaEa0YT8uqQUb2wOLsmBMxI90QDyf96lzOMJRgBuNYoEkU1pSgsgmW2glceZ96sRYfaXqwVxUw==} + engines: {node: '>=18.0.0'} + dependencies: + '@graphql-yoga/typed-event-target': 3.0.0 + '@repeaterjs/repeater': 3.0.5 + '@whatwg-node/events': 0.1.1 + tslib: 2.6.0 + dev: true + + /@graphql-yoga/typed-event-target@3.0.0: + resolution: {integrity: sha512-w+liuBySifrstuHbFrHoHAEyVnDFVib+073q8AeAJ/qqJfvFvAwUPLLtNohR/WDVRgSasfXtl3dcNuVJWN+rjg==} + engines: {node: '>=18.0.0'} + dependencies: + '@repeaterjs/repeater': 3.0.5 + tslib: 2.6.0 + dev: true + /@humanwhocodes/config-array@0.11.13: resolution: {integrity: sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==} engines: {node: '>=10.10.0'} @@ -2498,6 +2611,10 @@ packages: resolution: {integrity: sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==} dev: true + /@kamilkisiela/fast-url-parser@1.1.4: + resolution: {integrity: sha512-gbkePEBupNydxCelHCESvFSFM8XPh1Zs/OAVRW/rKpEqPAl5PbOM90Si8mv9bvnR53uPD2s/FiRxdvSejpRJew==} + dev: true + /@manypkg/find-root@1.1.0: resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} dependencies: @@ -3497,6 +3614,10 @@ packages: openapi-types: 12.1.0 dev: true + /@repeaterjs/repeater@3.0.5: + resolution: {integrity: sha512-l3YHBLAol6d/IKnB9LhpD0cEZWAoe3eFKUyTYWmFmCO2Q/WOckxLQAUyMZWwZV2M/m3+4vgRoaolFqaII82/TA==} + dev: true + /@rollup/plugin-alias@5.0.1(rollup@3.29.4): resolution: {integrity: sha512-JObvbWdOHoMy9W7SU0lvGhDtWq9PllP5mjpAy+TUslZG/WzOId9u80Hsqq1vCUn9pFJ0cxpdcnAv+QzU2zFH3Q==} engines: {node: '>=14.0.0'} @@ -4866,6 +4987,38 @@ packages: resolution: {integrity: sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ==} dev: true + /@whatwg-node/events@0.1.1: + resolution: {integrity: sha512-AyQEn5hIPV7Ze+xFoXVU3QTHXVbWPrzaOkxtENMPMuNL6VVHrp4hHfDt9nrQpjO7BgvuM95dMtkycX5M/DZR3w==} + engines: {node: '>=16.0.0'} + dev: true + + /@whatwg-node/fetch@0.9.14: + resolution: {integrity: sha512-wurZC82zzZwXRDSW0OS9l141DynaJQh7Yt0FD1xZ8niX7/Et/7RoiLiltbVU1fSF1RR9z6ndEaTUQBAmddTm1w==} + engines: {node: '>=16.0.0'} + dependencies: + '@whatwg-node/node-fetch': 0.5.2 + urlpattern-polyfill: 9.0.0 + dev: true + + /@whatwg-node/node-fetch@0.5.2: + resolution: {integrity: sha512-uVYCnmWoCiGbv5AtnSx5nZ1kQJ+U8f269/yHB62y7wXPdjYx6o4sBSefnfwUI8HNf4rf16VbvGR/AzuABhDD5g==} + engines: {node: '>=16.0.0'} + dependencies: + '@kamilkisiela/fast-url-parser': 1.1.4 + '@whatwg-node/events': 0.1.1 + busboy: 1.6.0 + fast-querystring: 1.1.2 + tslib: 2.6.0 + dev: true + + /@whatwg-node/server@0.9.19: + resolution: {integrity: sha512-GViwZq7iE1qCV6fSL2JHAHPQb6Jn2Ke34pkC5Wv7nAZi0qIqqPcBrEUG7TbJc79hYjCSrzRTi7FEs2xyWnQn7Q==} + engines: {node: '>=16.0.0'} + dependencies: + '@whatwg-node/fetch': 0.9.14 + tslib: 2.6.0 + dev: true + /abab@2.0.6: resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==} dev: true @@ -6212,6 +6365,13 @@ packages: - encoding dev: false + /cross-inspect@1.0.0: + resolution: {integrity: sha512-4PFfn4b5ZN6FMNGSZlyb7wUhuN8wvj8t/VQHZdM4JsDcruGJ8L2kf9zao98QIrBPFCpdk27qst/AGTl7pL3ypQ==} + engines: {node: '>=16.0.0'} + dependencies: + tslib: 2.6.0 + dev: true + /cross-spawn@5.1.0: resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==} dependencies: @@ -6713,6 +6873,11 @@ packages: engines: {node: '>=12'} dev: true + /dset@3.1.3: + resolution: {integrity: sha512-20TuZZHCEZ2O71q9/+8BwKwZ0QtD9D8ObhrihJPr+vLLYlSuAU3/zL4cSlgbfeoGHTjCSJBa7NGcrF9/Bx/WJQ==} + engines: {node: '>=4'} + dev: true + /duplexer@0.1.2: resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} dev: true @@ -8137,6 +8302,31 @@ packages: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} dev: true + /graphql-yoga@5.0.2(graphql@16.8.1): + resolution: {integrity: sha512-+r0aZ5sBQaWTFEwmDdPR+XcsYaIIh40IA34F7rhnyY57KXgs18ZkCZ9NPvfi6XEuqkHEvc2PFox05c5NRSJ26g==} + engines: {node: '>=18.0.0'} + peerDependencies: + graphql: ^15.2.0 || ^16.0.0 + dependencies: + '@envelop/core': 5.0.0 + '@graphql-tools/executor': 1.2.0(graphql@16.8.1) + '@graphql-tools/schema': 10.0.2(graphql@16.8.1) + '@graphql-tools/utils': 10.0.11(graphql@16.8.1) + '@graphql-yoga/logger': 2.0.0 + '@graphql-yoga/subscription': 5.0.0 + '@whatwg-node/fetch': 0.9.14 + '@whatwg-node/server': 0.9.19 + dset: 3.1.3 + graphql: 16.8.1 + lru-cache: 10.0.1 + tslib: 2.6.0 + dev: true + + /graphql@16.8.1: + resolution: {integrity: sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==} + engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} + dev: true + /gzip-size@7.0.0: resolution: {integrity: sha512-O1Ld7Dr+nqPnmGpdhzLmMTQ4vAsD+rHwMm1NLUmoUFFymBOMKxCCrtDxqdBRYXdeEPEi3SyoR4TizJLQrnKBNA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -11590,7 +11780,6 @@ packages: resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} engines: {node: '>=10.13.0'} hasBin: true - dev: true /pretty-bytes@6.1.1: resolution: {integrity: sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==} @@ -13794,6 +13983,10 @@ packages: resolution: {integrity: sha512-Qp95D4TPJl1kC9SKigDcqgyM2VDVO4RiJc2d4qe5GrYm+zbIQCWWKAFaJNQ4BhdFeDGwBmAxqJBwWSJDb9T3BQ==} dev: true + /urlpattern-polyfill@9.0.0: + resolution: {integrity: sha512-WHN8KDQblxd32odxeIgo83rdVDE2bvdkb86it7bMhYZwWKJz0+O0RK/eZiHYnM+zgt/U7hAHOlCQGfjjvSkw2g==} + dev: true + /use-sync-external-store@1.2.0(react@18.2.0): resolution: {integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==} peerDependencies: @@ -13839,6 +14032,11 @@ packages: spdx-correct: 3.2.0 spdx-expression-parse: 3.0.1 + /value-or-promise@1.0.12: + resolution: {integrity: sha512-Z6Uz+TYwEqE7ZN50gwn+1LCVo9ZVrpxRPOhOLnncYkY1ZzOYtrX8Fwf/rFktZ8R5mJms6EZf5TqNOMeZmnPq9Q==} + engines: {node: '>=12'} + dev: true + /vary@1.1.2: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 928f8bfc9..8f0a6928e 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,4 +1,5 @@ packages: - 'packages/*' - 'packages/plugins/*' + - 'packages/misc/*' - 'tests/*' From da343d7bed6b4e03ebc54e023b1bc6623006a2b9 Mon Sep 17 00:00:00 2001 From: ymc9 <104139426+ymc9@users.noreply.github.com> Date: Mon, 25 Dec 2023 22:15:29 +0800 Subject: [PATCH 2/4] feat: implement redwood setup --- packages/misc/redwood/package.json | 22 ++- packages/misc/redwood/src/commands/setup.ts | 171 ++++++++++++++++++++ packages/misc/redwood/src/index.ts | 3 + packages/misc/redwood/src/setup.ts | 1 - packages/misc/redwood/src/utils.ts | 6 + pnpm-lock.yaml | 40 +++-- 6 files changed, 208 insertions(+), 35 deletions(-) create mode 100644 packages/misc/redwood/src/commands/setup.ts delete mode 100644 packages/misc/redwood/src/setup.ts create mode 100644 packages/misc/redwood/src/utils.ts diff --git a/packages/misc/redwood/package.json b/packages/misc/redwood/package.json index 4140dbf88..68ef09b8d 100644 --- a/packages/misc/redwood/package.json +++ b/packages/misc/redwood/package.json @@ -9,8 +9,8 @@ }, "scripts": { "clean": "rimraf dist", - "build": "pnpm lint --max-warnings=0 && pnpm clean && tsc && copyfiles ./package.json ./README.md ../../LICENSE dist", - "watch": "concurrently \"tsc --watch\" \"tsup-node --config ./tsup-browser.config.ts --watch\" \"tsup-node --config ./tsup-cross.config.ts --watch\"", + "build": "pnpm lint --max-warnings=0 && pnpm clean && tsc", + "watch": "tsc --watch", "lint": "eslint src --ext ts", "prepublishOnly": "pnpm build" }, @@ -18,31 +18,27 @@ "types": "index.d.ts", "exports": { ".": { - "default": "./index.js", - "types": "./index.d.ts" - }, - "./setup": { - "default": "./setup.js" + "default": "./dist/index.js", + "types": "./dist/index.d.ts" }, "./package.json": { "default": "./package.json" } }, - "publishConfig": { - "directory": "dist", - "linkDirectory": true - }, "author": { "name": "ZenStack Team" }, "homepage": "https://zenstack.dev", "license": "MIT", - "bin": "node setup.js", "dependencies": { "@zenstackhq/runtime": "workspace:*", - "colors": "1.4.0" + "colors": "1.4.0", + "ora": "^5.4.1", + "ts-morph": "^16.0.0", + "yargs": "^17.7.2" }, "devDependencies": { + "@types/yargs": "^17.0.32", "graphql-yoga": "^5.0.2" } } diff --git a/packages/misc/redwood/src/commands/setup.ts b/packages/misc/redwood/src/commands/setup.ts new file mode 100644 index 000000000..b60db156b --- /dev/null +++ b/packages/misc/redwood/src/commands/setup.ts @@ -0,0 +1,171 @@ +import colors from 'colors'; +import fs from 'fs'; +import ora from 'ora'; +import path from 'path'; +import { exit } from 'process'; +import { Project, SyntaxKind, type PropertyAssignment } from 'ts-morph'; +import type { CommandModule } from 'yargs'; +import { execSync } from '../utils'; + +export interface SetupOptions { + side: string; + prisma: string; +} + +function installDependencies(args: SetupOptions) { + const spinner = ora(`Installing dependencies in "${args.side}"`).start(); + try { + execSync('yarn add --dev zenstack@latest'); + execSync('yarn add @zenstackhq/runtime@latest @zenstackhq/redwood@latest'); + spinner.succeed(); + } catch (err) { + spinner.fail(); + throw err; + } +} + +function bootstrapSchema(args: SetupOptions) { + const spinner = ora('Bootstrapping schema').start(); + try { + const zmodel = path.join(path.dirname(args.prisma), 'schema.zmodel'); + if (!fs.existsSync(zmodel)) { + fs.cpSync(args.prisma, zmodel); + } else { + console.warn(colors.blue(`\nSchema file "${zmodel}" already exists. Skipping.`)); + } + + const pkgJson = path.join('./package.json'); + if (fs.existsSync(pkgJson)) { + const content = fs.readFileSync(pkgJson, 'utf-8'); + const pkg = JSON.parse(content); + if (!pkg.zenstack) { + pkg.zenstack = { schema: zmodel }; + fs.writeFileSync(pkgJson, JSON.stringify(pkg, null, 4)); + } + } + + spinner.succeed(); + } catch (err) { + spinner.fail(); + throw err; + } +} + +function installGraphQLPlugin(args: SetupOptions) { + const spinner = ora('Installing GraphQL plugin').start(); + try { + let sourcePath: string | undefined; + if (fs.existsSync(path.join('src', 'functions', 'graphql.ts'))) { + sourcePath = path.join('src', 'functions', 'graphql.ts'); + } else if (fs.existsSync(path.join('src', 'functions', 'graphql.js'))) { + sourcePath = path.join('src', 'functions', 'graphql.js'); + } + + if (!sourcePath) { + console.error( + colors.red( + `Unable to find handler source file: ${path.join(args.side, 'src', 'functions', 'graphql.(js|ts)')}` + ) + ); + exit(1); + } + + const project = new Project(); + const sf = project.addSourceFileAtPathIfExists(sourcePath)!; + let changed = false; + let identified = false; + + const imports = sf.getImportDeclarations(); + if (!imports.some((i) => i.getModuleSpecifierValue() === '@zenstackhq/redwood')) { + sf.addImportDeclaration({ + moduleSpecifier: '@zenstackhq/redwood', + namedImports: ['useZenStack'], + }); + changed = true; + } + + sf.getDescendantsOfKind(SyntaxKind.CallExpression).forEach((expr) => { + if (identified) { + return; + } + + if (expr.getExpression().asKind(SyntaxKind.Identifier)?.getText() === 'createGraphQLHandler') { + const arg = expr.getArguments()[0]?.asKind(SyntaxKind.ObjectLiteralExpression); + if (arg) { + identified = true; + const props = arg.getProperties(); + const pluginsProp = props.find( + (p): p is PropertyAssignment => + p.asKind(SyntaxKind.PropertyAssignment)?.getName() === 'extraPlugins' + ); + if (pluginsProp) { + const pluginArr = pluginsProp.getInitializerIfKind(SyntaxKind.ArrayLiteralExpression); + if (pluginArr) { + if (!pluginArr.getElements().some((e) => e.getText().includes('useZenStack'))) { + pluginArr.addElement('useZenStack(db)'); + changed = true; + } + } + } else { + arg.addPropertyAssignment({ + name: 'extraPlugins', + initializer: '[useZenStack(db)]', + }); + changed = true; + } + } + } + }); + + if (!identified) { + console.warn( + colors.yellow( + '\nUnable to determine how to install ZenStack GraphQL plugin. Please add it manually following https://zenstack.dev/docs/guides/redwood.' + ) + ); + } + + if (changed) { + sf.formatText(); + project.saveSync(); + } + + spinner.succeed(); + } catch (err) { + spinner.fail(); + throw err; + } +} + +const setupCommand: CommandModule = { + command: 'setup', + describe: 'Set up ZenStack environment', + builder: (yargs) => { + return yargs + .option('side', { alias: 's', default: 'api' }) + .option('prisma', { alias: 'p', default: 'db/schema.prisma' }); + }, + handler: async (args) => { + if (!fs.existsSync(args.side)) { + console.error( + colors.red(`Can't find side directory "${args.side}". Use --side to specify a side directory.`) + ); + exit(1); + } + + const prismaSchema = path.join(args.side, args.prisma); + if (!fs.existsSync(prismaSchema)) { + console.error( + colors.red(`Can't find Prisma schema "${prismaSchema}". Use --prisma to specify a different location.`) + ); + exit(1); + } + + process.chdir(args.side); + installDependencies(args); + bootstrapSchema(args); + installGraphQLPlugin(args); + }, +}; + +export default setupCommand; diff --git a/packages/misc/redwood/src/index.ts b/packages/misc/redwood/src/index.ts index 64931cd31..3bc8b09e3 100644 --- a/packages/misc/redwood/src/index.ts +++ b/packages/misc/redwood/src/index.ts @@ -1,5 +1,6 @@ import { enhance, type AuthUser } from '@zenstackhq/runtime'; import { type Plugin } from 'graphql-yoga'; +import setup from './commands/setup'; export function useZenStack( db: PrismaClient @@ -12,3 +13,5 @@ export function useZenStack( }, }; } + +export const commands = [setup]; diff --git a/packages/misc/redwood/src/setup.ts b/packages/misc/redwood/src/setup.ts deleted file mode 100644 index db1c296ff..000000000 --- a/packages/misc/redwood/src/setup.ts +++ /dev/null @@ -1 +0,0 @@ -console.log('Setup redwood'); diff --git a/packages/misc/redwood/src/utils.ts b/packages/misc/redwood/src/utils.ts new file mode 100644 index 000000000..f0928cc68 --- /dev/null +++ b/packages/misc/redwood/src/utils.ts @@ -0,0 +1,6 @@ +import { execSync as _exec, StdioOptions } from 'child_process'; + +export function execSync(cmd: string, stdio: StdioOptions = 'inherit', env?: Record): void { + const mergedEnv = { ...process.env, ...env }; + _exec(cmd, { encoding: 'utf-8', stdio, env: mergedEnv }); +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 22a0b1b0d..c5ad9bdde 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -88,11 +88,22 @@ importers: colors: specifier: 1.4.0 version: 1.4.0 + ora: + specifier: ^5.4.1 + version: 5.4.1 + ts-morph: + specifier: ^16.0.0 + version: 16.0.0 + yargs: + specifier: ^17.7.2 + version: 17.7.2 devDependencies: + '@types/yargs': + specifier: ^17.0.32 + version: 17.0.32 graphql-yoga: specifier: ^5.0.2 version: 5.0.2(graphql@16.8.1) - publishDirectory: dist packages/plugins/openapi: dependencies: @@ -4162,7 +4173,7 @@ packages: /@ts-morph/common@0.17.0: resolution: {integrity: sha512-RMSSvSfs9kb0VzkvQ2NWobwnj7TxCA9vI/IjR9bDHqgAyVbu2T0DN4wiKVqomyDWqO7dPr/tErSfq7urQ1Q37g==} dependencies: - fast-glob: 3.3.0 + fast-glob: 3.3.1 minimatch: 5.1.6 mkdirp: 1.0.4 path-browserify: 1.0.1 @@ -4528,6 +4539,12 @@ packages: '@types/yargs-parser': 21.0.0 dev: true + /@types/yargs@17.0.32: + resolution: {integrity: sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==} + dependencies: + '@types/yargs-parser': 21.0.0 + dev: true + /@typescript-eslint/eslint-plugin@6.13.1(@typescript-eslint/parser@6.13.1)(eslint@8.55.0)(typescript@5.3.2): resolution: {integrity: sha512-5bQDGkXaxD46bPvQt08BUz9YSaO4S0fB1LB5JHQuXTfkGPI3+UUeS387C/e9jRie5GqT8u5kFTrMvAjtX4O5kA==} engines: {node: ^16.0.0 || >=18.0.0} @@ -6056,7 +6073,6 @@ packages: string-width: 4.2.3 strip-ansi: 6.0.1 wrap-ansi: 7.0.0 - dev: true /clone@1.0.4: resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} @@ -7375,7 +7391,6 @@ packages: /escalade@3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} engines: {node: '>=6'} - dev: true /escape-html@1.0.3: resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} @@ -7707,17 +7722,6 @@ packages: resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==} dev: true - /fast-glob@3.3.0: - resolution: {integrity: sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==} - engines: {node: '>=8.6.0'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.5 - dev: false - /fast-glob@3.3.1: resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==} engines: {node: '>=8.6.0'} @@ -8091,7 +8095,6 @@ packages: /get-caller-file@2.0.5: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} - dev: true /get-func-name@2.0.0: resolution: {integrity: sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==} @@ -12272,7 +12275,6 @@ packages: /require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} - dev: true /require-from-string@2.0.2: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} @@ -14598,7 +14600,6 @@ packages: ansi-styles: 4.3.0 string-width: 4.2.3 strip-ansi: 6.0.1 - dev: true /wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} @@ -14663,7 +14664,6 @@ packages: /y18n@5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} - dev: true /yallist@2.1.2: resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==} @@ -14707,7 +14707,6 @@ packages: /yargs-parser@21.1.1: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} - dev: true /yargs@15.4.1: resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} @@ -14750,7 +14749,6 @@ packages: string-width: 4.2.3 y18n: 5.0.8 yargs-parser: 21.1.1 - dev: true /yauzl@2.10.0: resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} From aaa1c0747bea02dd88e7aa17c3ccc130b9322d94 Mon Sep 17 00:00:00 2001 From: ymc9 <104139426+ymc9@users.noreply.github.com> Date: Sat, 30 Dec 2023 17:27:04 +0800 Subject: [PATCH 3/4] feat: RedwoodJS integration package --- packages/misc/redwood/package.json | 24 +- packages/misc/redwood/src/cli-passthrough.ts | 51 ++ packages/misc/redwood/src/commands/setup.ts | 332 ++++--- packages/misc/redwood/src/graphql.ts | 61 ++ packages/misc/redwood/src/index.ts | 24 +- packages/misc/redwood/src/utils.ts | 24 +- .../runtime/src/enhancements/policy/index.ts | 10 +- packages/runtime/src/enhancements/proxy.ts | 20 +- packages/schema/src/cli/cli-util.ts | 16 +- packages/schema/src/cli/plugin-runner.ts | 3 +- .../src/plugins/prisma/schema-generator.ts | 20 +- packages/schema/src/utils/pkg-utils.ts | 9 + pnpm-lock.yaml | 851 +++++++++++++++++- 13 files changed, 1213 insertions(+), 232 deletions(-) create mode 100644 packages/misc/redwood/src/cli-passthrough.ts create mode 100644 packages/misc/redwood/src/graphql.ts diff --git a/packages/misc/redwood/package.json b/packages/misc/redwood/package.json index 68ef09b8d..d60812d62 100644 --- a/packages/misc/redwood/package.json +++ b/packages/misc/redwood/package.json @@ -1,8 +1,8 @@ { "name": "@zenstackhq/redwood", - "displayName": "ZenStack RedwoodJS setup and runtime package", - "version": "0.5.0", - "description": "For using ZenStack with RedwoodJS projects.", + "displayName": "ZenStack RedwoodJS Integration", + "version": "1.6.0", + "description": "CLI and runtime for integrating ZenStack with RedwoodJS projects.", "repository": { "type": "git", "url": "https://github.com/zenstackhq/zenstack" @@ -14,13 +14,17 @@ "lint": "eslint src --ext ts", "prepublishOnly": "pnpm build" }, - "main": "index.js", - "types": "index.d.ts", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", "exports": { ".": { "default": "./dist/index.js", "types": "./dist/index.d.ts" }, + "./graphql": { + "default": "./dist/graphql.js", + "types": "./dist/graphql.d.ts" + }, "./package.json": { "default": "./package.json" } @@ -33,11 +37,17 @@ "dependencies": { "@zenstackhq/runtime": "workspace:*", "colors": "1.4.0", - "ora": "^5.4.1", - "ts-morph": "^16.0.0", + "ts-morph": "^16.0.0" + }, + "peerDependencies": { + "execa": "^5.0.0", + "listr2": "^6.0.0", + "terminal-link": "^2.0.0", "yargs": "^17.7.2" }, "devDependencies": { + "@redwoodjs/graphql-server": "^6.6.0", + "@redwoodjs/cli-helpers": "^6.6.0", "@types/yargs": "^17.0.32", "graphql-yoga": "^5.0.2" } diff --git a/packages/misc/redwood/src/cli-passthrough.ts b/packages/misc/redwood/src/cli-passthrough.ts new file mode 100644 index 000000000..4e327b5b6 --- /dev/null +++ b/packages/misc/redwood/src/cli-passthrough.ts @@ -0,0 +1,51 @@ +import { getPaths } from '@redwoodjs/cli-helpers'; +import colors from 'colors'; +import execa from 'execa'; +import { CommandModule } from 'yargs'; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +async function runCommand(command: string, options: any) { + const args = ['zenstack', command]; + for (const [name, value] of Object.entries(options)) { + args.push(name.length > 1 ? `--${name}` : `-${name}`); + if (typeof value === 'string') { + // Make sure options that take multiple quoted words + // are passed to zenstack with quotes. + value.split(' ').length > 1 ? args.push(`"${value}"`) : args.push(value); + } + } + + console.log(); + console.log(colors.green('Running ZenStack CLI...')); + console.log(colors.underline('$ npx ' + args.join(' '))); + console.log(); + + try { + await execa('npx', args, { cwd: getPaths().api.base, shell: true, stdio: 'inherit', cleanup: true }); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } catch (e: any) { + process.exit(e?.exitCode || 1); + } +} + +/** + * Creates a yargs command that passes all options to the ZenStack CLI command. + */ +export function makePassthroughCommand(command: string): CommandModule { + return { + command, + describe: `Run \`zenstack ${command} ...\``, + builder: (yargs) => { + return yargs + .strictOptions(false) + .strictCommands(false) + .strict(false) + .parserConfiguration({ 'camel-case-expansion': false, 'boolean-negation': false }) + .help(false) + .version(false); + }, + handler: async ({ _, $0: _$0, ...options }) => { + await runCommand(command, options); + }, + }; +} diff --git a/packages/misc/redwood/src/commands/setup.ts b/packages/misc/redwood/src/commands/setup.ts index b60db156b..e0ddfb81b 100644 --- a/packages/misc/redwood/src/commands/setup.ts +++ b/packages/misc/redwood/src/commands/setup.ts @@ -1,170 +1,226 @@ +import { getPaths } from '@redwoodjs/cli-helpers'; import colors from 'colors'; +import execa from 'execa'; import fs from 'fs'; -import ora from 'ora'; +import { Listr, ListrTask } from 'listr2'; import path from 'path'; -import { exit } from 'process'; +import terminalLink from 'terminal-link'; import { Project, SyntaxKind, type PropertyAssignment } from 'ts-morph'; import type { CommandModule } from 'yargs'; -import { execSync } from '../utils'; - -export interface SetupOptions { - side: string; - prisma: string; -} - -function installDependencies(args: SetupOptions) { - const spinner = ora(`Installing dependencies in "${args.side}"`).start(); - try { - execSync('yarn add --dev zenstack@latest'); - execSync('yarn add @zenstackhq/runtime@latest @zenstackhq/redwood@latest'); - spinner.succeed(); - } catch (err) { - spinner.fail(); - throw err; - } +import { addApiPackages } from '../utils'; + +function installDependencies() { + return addApiPackages([ + { pkg: 'zenstack', dev: true }, + { pkg: '@zenstackhq/runtime' }, + { pkg: '@zenstackhq/redwood' }, + ]); } -function bootstrapSchema(args: SetupOptions) { - const spinner = ora('Bootstrapping schema').start(); - try { - const zmodel = path.join(path.dirname(args.prisma), 'schema.zmodel'); - if (!fs.existsSync(zmodel)) { - fs.cpSync(args.prisma, zmodel); - } else { - console.warn(colors.blue(`\nSchema file "${zmodel}" already exists. Skipping.`)); - } - - const pkgJson = path.join('./package.json'); - if (fs.existsSync(pkgJson)) { - const content = fs.readFileSync(pkgJson, 'utf-8'); - const pkg = JSON.parse(content); - if (!pkg.zenstack) { - pkg.zenstack = { schema: zmodel }; - fs.writeFileSync(pkgJson, JSON.stringify(pkg, null, 4)); +// copy schema.prisma to schema.zmodel, and update package.json +function bootstrapSchema() { + return { + title: 'Bootstrapping ZModel schema...', + task: () => { + const apiPaths = getPaths().api; + const zmodel = path.join(path.dirname(apiPaths.dbSchema), 'schema.zmodel'); + if (!fs.existsSync(zmodel)) { + fs.cpSync(apiPaths.dbSchema, zmodel); + } else { + console.info( + colors.blue(`Schema file "${path.relative(getPaths().base, zmodel)}" already exists. Skipping.`) + ); } - } - spinner.succeed(); - } catch (err) { - spinner.fail(); - throw err; - } + const pkgJson = path.join(apiPaths.base, 'package.json'); + if (fs.existsSync(pkgJson)) { + const content = fs.readFileSync(pkgJson, 'utf-8'); + const pkg = JSON.parse(content); + if (!pkg.zenstack) { + pkg.zenstack = { + schema: path.relative(apiPaths.base, zmodel), + prisma: path.relative(apiPaths.base, apiPaths.dbSchema), + }; + fs.writeFileSync(pkgJson, JSON.stringify(pkg, null, 4)); + } + } + }, + }; } -function installGraphQLPlugin(args: SetupOptions) { - const spinner = ora('Installing GraphQL plugin').start(); - try { - let sourcePath: string | undefined; - if (fs.existsSync(path.join('src', 'functions', 'graphql.ts'))) { - sourcePath = path.join('src', 'functions', 'graphql.ts'); - } else if (fs.existsSync(path.join('src', 'functions', 'graphql.js'))) { - sourcePath = path.join('src', 'functions', 'graphql.js'); - } - - if (!sourcePath) { - console.error( - colors.red( - `Unable to find handler source file: ${path.join(args.side, 'src', 'functions', 'graphql.(js|ts)')}` - ) - ); - exit(1); - } - - const project = new Project(); - const sf = project.addSourceFileAtPathIfExists(sourcePath)!; - let changed = false; - let identified = false; - - const imports = sf.getImportDeclarations(); - if (!imports.some((i) => i.getModuleSpecifierValue() === '@zenstackhq/redwood')) { - sf.addImportDeclaration({ - moduleSpecifier: '@zenstackhq/redwood', - namedImports: ['useZenStack'], - }); - changed = true; - } +// install ZenStack GraphQLYoga plugin +function installGraphQLPlugin() { + return { + title: 'Installing GraphQL plugin...', + task: async () => { + // locate "api/functions/graphql.[js|ts]" + let sourcePath: string | undefined; + const functionsDir = getPaths().api.functions; + if (fs.existsSync(path.join(functionsDir, 'graphql.ts'))) { + sourcePath = path.join(functionsDir, 'graphql.ts'); + } else if (fs.existsSync(path.join(functionsDir, 'graphql.js'))) { + sourcePath = path.join(functionsDir, 'graphql.js'); + } - sf.getDescendantsOfKind(SyntaxKind.CallExpression).forEach((expr) => { - if (identified) { + if (!sourcePath) { + console.warn( + colors.yellow(`Unable to find handler source file: ${path.join(functionsDir, 'graphql.(js|ts)')}`) + ); return; } - if (expr.getExpression().asKind(SyntaxKind.Identifier)?.getText() === 'createGraphQLHandler') { - const arg = expr.getArguments()[0]?.asKind(SyntaxKind.ObjectLiteralExpression); - if (arg) { - identified = true; - const props = arg.getProperties(); - const pluginsProp = props.find( - (p): p is PropertyAssignment => - p.asKind(SyntaxKind.PropertyAssignment)?.getName() === 'extraPlugins' - ); - if (pluginsProp) { - const pluginArr = pluginsProp.getInitializerIfKind(SyntaxKind.ArrayLiteralExpression); - if (pluginArr) { - if (!pluginArr.getElements().some((e) => e.getText().includes('useZenStack'))) { - pluginArr.addElement('useZenStack(db)'); - changed = true; + // add import + const project = new Project(); + const sf = project.addSourceFileAtPathIfExists(sourcePath)!; + let changed = false; + let identified = false; + + const imports = sf.getImportDeclarations(); + if (!imports.some((i) => i.getModuleSpecifierValue() === '@zenstackhq/redwood')) { + sf.addImportDeclaration({ + moduleSpecifier: '@zenstackhq/redwood', + namedImports: ['useZenStack'], + }); + changed = true; + } + + // add "extraPlugins" option to `createGraphQLHandler` call + sf.getDescendantsOfKind(SyntaxKind.CallExpression).forEach((expr) => { + if (identified) { + return; + } + + if (expr.getExpression().asKind(SyntaxKind.Identifier)?.getText() === 'createGraphQLHandler') { + const arg = expr.getArguments()[0]?.asKind(SyntaxKind.ObjectLiteralExpression); + if (arg) { + identified = true; + const props = arg.getProperties(); + const pluginsProp = props.find( + (p): p is PropertyAssignment => + p.asKind(SyntaxKind.PropertyAssignment)?.getName() === 'extraPlugins' + ); + if (pluginsProp) { + const pluginArr = pluginsProp.getInitializerIfKind(SyntaxKind.ArrayLiteralExpression); + if (pluginArr) { + if (!pluginArr.getElements().some((e) => e.getText().includes('useZenStack'))) { + pluginArr.addElement('useZenStack(db)'); + changed = true; + } } + } else { + arg.addPropertyAssignment({ + name: 'extraPlugins', + initializer: '[useZenStack(db)]', + }); + changed = true; } - } else { - arg.addPropertyAssignment({ - name: 'extraPlugins', - initializer: '[useZenStack(db)]', - }); - changed = true; } } + }); + + if (!identified) { + console.warn( + colors.yellow( + 'Unable to determine how to install ZenStack GraphQL plugin. Please add it manually following https://zenstack.dev/docs/guides/redwood.' + ) + ); + } + + if (changed) { + sf.formatText(); + await project.save(); + } + }, + }; +} + +// eject templates used for `yarn rw generate service` +function ejectServiceTemplates() { + return { + title: 'Ejecting service templates...', + task: async () => { + if (fs.existsSync(path.join(getPaths().api.base, 'generators', 'service'))) { + console.info(colors.blue('Service templates already ejected. Skipping.')); + return; } - }); - if (!identified) { - console.warn( - colors.yellow( - '\nUnable to determine how to install ZenStack GraphQL plugin. Please add it manually following https://zenstack.dev/docs/guides/redwood.' - ) + await execa('yarn', ['rw', 'setup', 'generator', 'service'], { cwd: getPaths().api.base }); + const serviceTemplateTsFile = path.join( + getPaths().api.base, + 'generators', + 'service', + 'service.ts.template' ); - } + const serviceTemplateJsFile = path.join( + getPaths().api.base, + 'generators', + 'service', + 'service.js.template' + ); + const serviceTemplateFile = fs.existsSync(serviceTemplateTsFile) + ? serviceTemplateTsFile + : fs.existsSync(serviceTemplateJsFile) + ? serviceTemplateJsFile + : undefined; + + if (!serviceTemplateFile) { + console.warn(colors.red('Unable to find the ejected service template file.')); + return; + } - if (changed) { - sf.formatText(); - project.saveSync(); - } + // replace `db.` with `context.db.` + const templateContent = fs.readFileSync(serviceTemplateFile, 'utf-8'); + const newTemplateContent = templateContent + .replace(/^import { db } from.*\n$/gm, '') + .replace(/return db\./g, 'return context.db.'); + fs.writeFileSync(serviceTemplateFile, newTemplateContent); + }, + }; +} - spinner.succeed(); - } catch (err) { - spinner.fail(); - throw err; - } +function whatsNext() { + const zmodel = path.relative(getPaths().base, path.join(path.dirname(getPaths().api.dbSchema), 'schema.zmodel')); + const task: ListrTask = { + title: `What's next...`, + task: (_ctx, task) => { + task.title = + `What's next...\n\n` + + ` - Install ${terminalLink('ZenStack IDE extensions', 'https://zenstack.dev/docs/guides/ide')}.\n` + + ` - Use "${zmodel}" to model your database schema and access control.\n` + + ` - Run \`yarn rw @zenstackhq generate\` to regenerate Prisma schema and client.\n` + + ` - Learn ${terminalLink( + "how ZenStack extends Prisma's power", + 'https://zenstack.dev/docs/the-complete-guide/part1' + )}.\n` + + ` - Create a sample schema with \`yarn rw @zenstackhq sample\`.\n` + + ` - Join ${terminalLink( + 'Discord community', + 'https://discord.gg/Ykhr738dUe' + )} for questions and updates.\n`; + }, + }; + return task; } -const setupCommand: CommandModule = { +const setupCommand: CommandModule = { command: 'setup', describe: 'Set up ZenStack environment', - builder: (yargs) => { - return yargs - .option('side', { alias: 's', default: 'api' }) - .option('prisma', { alias: 'p', default: 'db/schema.prisma' }); - }, - handler: async (args) => { - if (!fs.existsSync(args.side)) { - console.error( - colors.red(`Can't find side directory "${args.side}". Use --side to specify a side directory.`) - ); - exit(1); + handler: async () => { + const tasks = new Listr([ + installDependencies(), + bootstrapSchema(), + installGraphQLPlugin(), + ejectServiceTemplates(), + whatsNext(), + ]); + + try { + await tasks.run(); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } catch (e: any) { + console.error(colors.red(e.message)); + process.exit(e?.exitCode || 1); } - - const prismaSchema = path.join(args.side, args.prisma); - if (!fs.existsSync(prismaSchema)) { - console.error( - colors.red(`Can't find Prisma schema "${prismaSchema}". Use --prisma to specify a different location.`) - ); - exit(1); - } - - process.chdir(args.side); - installDependencies(args); - bootstrapSchema(args); - installGraphQLPlugin(args); }, }; diff --git a/packages/misc/redwood/src/graphql.ts b/packages/misc/redwood/src/graphql.ts new file mode 100644 index 000000000..69267b5e2 --- /dev/null +++ b/packages/misc/redwood/src/graphql.ts @@ -0,0 +1,61 @@ +import { ForbiddenError } from '@redwoodjs/graphql-server'; +import { + CrudFailureReason, + EnhancementOptions, + PrismaErrorCode, + ValidationError, + enhance, + isPrismaClientKnownRequestError, + type AuthUser, +} from '@zenstackhq/runtime'; +import { type Plugin } from 'graphql-yoga'; + +/** + * Plugin options + */ +export type ZenStackPluginOptions = EnhancementOptions; + +/** + * A GraphQLYoga plugin that adds a ZenStack-enhanced PrismaClient into the context + * as `context.db`. + * @param db The original PrismaClient. + * @param getAuthUser A hook function for getting the current user. By default `context.currentUser` is used. + * @param options Options for creating the enhanced PrismaClient. See https://zenstack.dev/docs/reference/runtime-api#enhance for more details. + * @returns + */ +export function useZenStack( + db: PrismaClient, + getAuthUser?: (currentUser: unknown) => Promise, + options?: ZenStackPluginOptions +): Plugin<{ currentUser: unknown; db: PrismaClient }> { + return { + onContextBuilding: () => { + return async ({ context }) => { + const user = getAuthUser ? await getAuthUser(context.currentUser) : (context.currentUser as AuthUser); + context.db = enhance( + db, + { user }, + { + errorTransformer: transformError, + ...options, + } + ); + }; + }, + }; +} + +// Transforms ZenStack errors into appropriate RedwoodJS errors +function transformError(error: unknown) { + if (isPrismaClientKnownRequestError(error) && error.code === PrismaErrorCode.CONSTRAINED_FAILED) { + if ( + error.meta?.reason === CrudFailureReason.ACCESS_POLICY_VIOLATION || + error.meta?.reason === CrudFailureReason.RESULT_NOT_READABLE + ) { + return new ForbiddenError(error.message); + } else if (error.meta?.reason === CrudFailureReason.DATA_VALIDATION_VIOLATION) { + return new ValidationError(error.message); + } + } + return error; +} diff --git a/packages/misc/redwood/src/index.ts b/packages/misc/redwood/src/index.ts index 3bc8b09e3..67585bb3f 100644 --- a/packages/misc/redwood/src/index.ts +++ b/packages/misc/redwood/src/index.ts @@ -1,17 +1,11 @@ -import { enhance, type AuthUser } from '@zenstackhq/runtime'; -import { type Plugin } from 'graphql-yoga'; +import { makePassthroughCommand } from './cli-passthrough'; import setup from './commands/setup'; -export function useZenStack( - db: PrismaClient -): Plugin<{ currentUser: AuthUser; db: PrismaClient }> { - return { - onContextBuilding() { - return ({ context }) => { - context.db = enhance(db, { user: context?.currentUser }); - }; - }, - }; -} - -export const commands = [setup]; +export const commands = [ + setup, + makePassthroughCommand('generate'), + makePassthroughCommand('info'), + makePassthroughCommand('format'), + makePassthroughCommand('repl'), +]; +export * from './graphql'; diff --git a/packages/misc/redwood/src/utils.ts b/packages/misc/redwood/src/utils.ts index f0928cc68..dbf8a1a04 100644 --- a/packages/misc/redwood/src/utils.ts +++ b/packages/misc/redwood/src/utils.ts @@ -1,6 +1,20 @@ -import { execSync as _exec, StdioOptions } from 'child_process'; +import { getPaths } from '@redwoodjs/cli-helpers'; +import execa from 'execa'; -export function execSync(cmd: string, stdio: StdioOptions = 'inherit', env?: Record): void { - const mergedEnv = { ...process.env, ...env }; - _exec(cmd, { encoding: 'utf-8', stdio, env: mergedEnv }); -} +/** + * Utility for adding npm dependencies to "api" package + */ +export const addApiPackages = (apiPackages: { pkg: string; dev?: boolean }[]) => ({ + title: 'Adding required api packages...', + task: async () => { + const devPkgs = apiPackages.filter((p) => p.dev).map((p) => p.pkg); + if (devPkgs.length > 0) { + await execa('yarn', ['add', '-D', ...devPkgs], { cwd: getPaths().api.base }); + } + + const runtimePkgs = apiPackages.filter((p) => !p.dev).map((p) => p.pkg); + if (runtimePkgs.length > 0) { + await execa('yarn', ['add', ...runtimePkgs], { cwd: getPaths().api.base }); + } + }, +}); diff --git a/packages/runtime/src/enhancements/policy/index.ts b/packages/runtime/src/enhancements/policy/index.ts index 22c4cf580..678f777ef 100644 --- a/packages/runtime/src/enhancements/policy/index.ts +++ b/packages/runtime/src/enhancements/policy/index.ts @@ -7,7 +7,7 @@ import { getIdFields, type ModelMeta } from '../../cross'; import { getDefaultModelMeta, getDefaultPolicy, getDefaultZodSchemas } from '../../loader'; import { AuthUser, DbClientContract } from '../../types'; import { hasAllFields } from '../../validation'; -import { makeProxy } from '../proxy'; +import { ErrorTransformer, makeProxy } from '../proxy'; import type { CommonEnhancementOptions, PolicyDef, ZodSchemas } from '../types'; import { PolicyProxyHandler } from './handler'; @@ -41,6 +41,11 @@ export interface WithPolicyOptions extends CommonEnhancementOptions { * Whether to log Prisma query */ logPrismaQuery?: boolean; + + /** + * Hook for transforming errors before they are thrown to the caller. + */ + errorTransformer?: ErrorTransformer; } /** @@ -110,6 +115,7 @@ export function withPolicy( context?.user, options?.logPrismaQuery ), - 'policy' + 'policy', + options?.errorTransformer ); } diff --git a/packages/runtime/src/enhancements/proxy.ts b/packages/runtime/src/enhancements/proxy.ts index 8c4d85ceb..358bff153 100644 --- a/packages/runtime/src/enhancements/proxy.ts +++ b/packages/runtime/src/enhancements/proxy.ts @@ -10,6 +10,11 @@ import { createDeferredPromise } from './policy/promise'; */ export type BatchResult = { count: number }; +/** + * Function for transforming errors. + */ +export type ErrorTransformer = (error: unknown) => unknown; + /** * Interface for proxy that intercepts Prisma operations. */ @@ -174,7 +179,8 @@ export function makeProxy( prisma: any, modelMeta: ModelMeta, makeHandler: (prisma: object, model: string) => T, - name = 'unnamed_enhancer' + name = 'unnamed_enhancer', + errorTransformer?: ErrorTransformer ) { const models = Object.keys(modelMeta.fields).map((k) => k.toLowerCase()); const proxy = new Proxy(prisma, { @@ -227,7 +233,7 @@ export function makeProxy( return propVal; } - return createHandlerProxy(makeHandler(target, prop), propVal); + return createHandlerProxy(makeHandler(target, prop), propVal, errorTransformer); }, }); @@ -235,7 +241,11 @@ export function makeProxy( } // A proxy for capturing errors and processing stack trace -function createHandlerProxy(handler: T, origTarget: any): T { +function createHandlerProxy( + handler: T, + origTarget: any, + errorTransformer?: ErrorTransformer +): T { return new Proxy(handler, { get(target, propKey) { const prop = target[propKey as keyof T]; @@ -266,6 +276,10 @@ function createHandlerProxy(handler: T, origTarget (err as any).internalStack = err.stack; err.stack = cleanCallStack(capture.stack, propKey.toString(), err.message); } + + if (errorTransformer) { + err = errorTransformer ? errorTransformer(err) : err; + } reject(err); } ); diff --git a/packages/schema/src/cli/cli-util.ts b/packages/schema/src/cli/cli-util.ts index bb9aa525b..000e92ca7 100644 --- a/packages/schema/src/cli/cli-util.ts +++ b/packages/schema/src/cli/cli-util.ts @@ -15,6 +15,7 @@ import { getVersion } from '../utils/version-utils'; import { CliError } from './cli-error'; import { ZModelFormatter } from '../language-server/zmodel-formatter'; import { TextDocument } from 'vscode-languageserver-textdocument'; +import { getPackageJson } from '../utils/pkg-utils'; // required minimal version of Prisma export const requiredPrismaVersion = '4.8.0'; @@ -280,17 +281,10 @@ export async function formatDocument(fileName: string) { export function getDefaultSchemaLocation() { let location = path.resolve('schema.zmodel'); - if (fs.existsSync('./package.json')) { - try { - // eslint-disable-next-line @typescript-eslint/no-var-requires - const pkgJson = require(path.resolve('./package.json')); - if (typeof pkgJson.zenstack?.schema === 'string') { - location = path.resolve(pkgJson.zenstack.schema); - } - } catch (e) { - console.error(e); - // noop - } + // handle override from package.json + const pkgJson = getPackageJson(); + if (typeof pkgJson?.zenstack?.schema === 'string') { + location = path.resolve(pkgJson.zenstack.schema); } return location; diff --git a/packages/schema/src/cli/plugin-runner.ts b/packages/schema/src/cli/plugin-runner.ts index d76d43522..0609fd4fb 100644 --- a/packages/schema/src/cli/plugin-runner.ts +++ b/packages/schema/src/cli/plugin-runner.ts @@ -18,6 +18,7 @@ import fs from 'fs'; import ora from 'ora'; import path from 'path'; import { ensureDefaultOutputFolder } from '../plugins/plugin-utils'; +import { getDefaultPrismaOutputFile } from '../plugins/prisma/schema-generator'; import telemetry from '../telemetry'; import { getVersion } from '../utils/version-utils'; @@ -54,7 +55,7 @@ export class PluginRunner { const plugins: PluginInfo[] = []; const pluginDecls = options.schema.declarations.filter((d): d is Plugin => isPlugin(d)); - let prismaOutput = resolvePath('./prisma/schema.prisma', { schemaPath: options.schemaPath }); + let prismaOutput = getDefaultPrismaOutputFile(options.schemaPath); for (const pluginDecl of pluginDecls) { const pluginProvider = this.getPluginProvider(pluginDecl); diff --git a/packages/schema/src/plugins/prisma/schema-generator.ts b/packages/schema/src/plugins/prisma/schema-generator.ts index 0605f468b..45a025d27 100644 --- a/packages/schema/src/plugins/prisma/schema-generator.ts +++ b/packages/schema/src/plugins/prisma/schema-generator.ts @@ -63,6 +63,7 @@ import { SimpleField, } from './prisma-builder'; import { ZModelCodeGenerator } from '@zenstackhq/sdk'; +import { getPackageJson } from '../../utils/pkg-utils'; const MODEL_PASSTHROUGH_ATTR = '@@prisma.passthrough'; const FIELD_PASSTHROUGH_ATTR = '@prisma.passthrough'; @@ -112,8 +113,9 @@ export default class PrismaSchemaGenerator { } } - let outFile = (options.output as string) ?? './prisma/schema.prisma'; - outFile = resolvePath(outFile, options); + const outFile = options.output + ? resolvePath(options.output as string, options) + : getDefaultPrismaOutputFile(options.schemaPath); if (!fs.existsSync(path.dirname(outFile))) { fs.mkdirSync(path.dirname(outFile), { recursive: true }); @@ -430,3 +432,17 @@ export default class PrismaSchemaGenerator { _enum.addField(field.name, attributes, documentations); } } + +export function getDefaultPrismaOutputFile(schemaPath: string) { + let result: string | undefined; + + // handle override from package.json + const pkgJson = getPackageJson(); + if (typeof pkgJson.zenstack?.prisma === 'string') { + result = path.resolve(pkgJson.zenstack.prisma); + } else { + result = './prisma/schema.prisma'; + } + + return resolvePath(result, { schemaPath }); +} diff --git a/packages/schema/src/utils/pkg-utils.ts b/packages/schema/src/utils/pkg-utils.ts index 0d3633cd7..ffb9b0aea 100644 --- a/packages/schema/src/utils/pkg-utils.ts +++ b/packages/schema/src/utils/pkg-utils.ts @@ -84,3 +84,12 @@ export function ensurePackage( installPackage(pkg, dev, pkgManager, tag, resolvePath, exactVersion); } } + +export function getPackageJson() { + const pkgJsonPath = path.join(process.cwd(), 'package.json'); + if (fs.existsSync(pkgJsonPath)) { + return JSON.parse(fs.readFileSync(pkgJsonPath, 'utf-8')); + } else { + return undefined; + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c5ad9bdde..6eefd606f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -88,9 +88,15 @@ importers: colors: specifier: 1.4.0 version: 1.4.0 - ora: - specifier: ^5.4.1 - version: 5.4.1 + execa: + specifier: ^5.0.0 + version: 5.1.1 + listr2: + specifier: ^6.0.0 + version: 6.6.1 + terminal-link: + specifier: ^2.0.0 + version: 2.1.1 ts-morph: specifier: ^16.0.0 version: 16.0.0 @@ -98,6 +104,12 @@ importers: specifier: ^17.7.2 version: 17.7.2 devDependencies: + '@redwoodjs/cli-helpers': + specifier: ^6.6.0 + version: 6.6.0 + '@redwoodjs/graphql-server': + specifier: ^6.6.0 + version: 6.6.0 '@types/yargs': specifier: ^17.0.32 version: 17.0.32 @@ -1251,6 +1263,14 @@ packages: '@babel/plugin-syntax-typescript': 7.22.5(@babel/core@7.23.2) dev: true + /@babel/runtime-corejs3@7.23.6: + resolution: {integrity: sha512-Djs/ZTAnpyj0nyg7p1J6oiE/tZ9G2stqAFlLGZynrW+F3k2w2jGK2mLOBxzYIOcZYA89+c3d3wXKpYLcpwcU6w==} + engines: {node: '>=6.9.0'} + dependencies: + core-js-pure: 3.35.0 + regenerator-runtime: 0.14.1 + dev: true + /@babel/runtime@7.22.5: resolution: {integrity: sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA==} engines: {node: '>=6.9.0'} @@ -1272,33 +1292,6 @@ packages: '@babel/types': 7.23.0 dev: true - /@babel/template@7.22.5: - resolution: {integrity: sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.22.13 - '@babel/parser': 7.23.0 - '@babel/types': 7.23.0 - dev: true - - /@babel/traverse@7.22.8: - resolution: {integrity: sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.22.13 - '@babel/generator': 7.23.0 - '@babel/helper-environment-visitor': 7.22.5 - '@babel/helper-function-name': 7.22.5 - '@babel/helper-hoist-variables': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - '@babel/parser': 7.23.0 - '@babel/types': 7.23.0 - debug: 4.3.4 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - dev: true - /@babel/traverse@7.23.2: resolution: {integrity: sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==} engines: {node: '>=6.9.0'} @@ -1546,6 +1539,14 @@ packages: '@jridgewell/trace-mapping': 0.3.9 dev: true + /@envelop/core@4.0.3: + resolution: {integrity: sha512-O0Vz8E0TObT6ijAob8jYFVJavcGywKThM3UAsxUIBBVPYZTMiqI9lo2gmAnbMUnrDcAYkUTZEW9FDYPRdF5l6g==} + engines: {node: '>=16.0.0'} + dependencies: + '@envelop/types': 4.0.1 + tslib: 2.6.0 + dev: true + /@envelop/core@5.0.0: resolution: {integrity: sha512-aJdnH/ptv+cvwfvciCBe7TSvccBwo9g0S5f6u35TBVzRVqIGkK03lFlIL+x1cnfZgN9EfR2b1PH2galrT1CdCQ==} engines: {node: '>=18.0.0'} @@ -1554,6 +1555,61 @@ packages: tslib: 2.6.0 dev: true + /@envelop/depth-limit@3.0.3(@envelop/core@4.0.3)(graphql@16.8.1): + resolution: {integrity: sha512-fDyLQDVlSG3DPJmzwb6pdnpK67rNy9KLkN8LTthZOmEXGz0WuVP1EOOnjYY7PE566BySbNXl5z1lTeOPHR1KUw==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@envelop/core': ^4.0.3 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@envelop/core': 4.0.3 + graphql: 16.8.1 + graphql-depth-limit: 1.1.0(graphql@16.8.1) + tslib: 2.6.0 + dev: true + + /@envelop/disable-introspection@5.0.3(@envelop/core@4.0.3)(graphql@16.8.1): + resolution: {integrity: sha512-PoKbaeCVGdgkgQUGl46L33SBB/bYKVOe1QHEW8++n9lnTTTLJTyo8EbtJb++UcuQCaaKn277fkUyc9sR9fOh5w==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@envelop/core': ^4.0.3 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@envelop/core': 4.0.3 + graphql: 16.8.1 + tslib: 2.6.0 + dev: true + + /@envelop/filter-operation-type@5.0.3(@envelop/core@4.0.3)(graphql@16.8.1): + resolution: {integrity: sha512-z6gYb+y4O6lsOH+KMwrfYzN7b0ybGAZWSk/++z913nOSxtPm42sYdCQ56upw+tN/WHNxwKejCO54TjhrSdUX9Q==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@envelop/core': ^4.0.3 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@envelop/core': 4.0.3 + graphql: 16.8.1 + tslib: 2.6.0 + dev: true + + /@envelop/on-resolve@3.0.3(@envelop/core@4.0.3)(graphql@16.8.1): + resolution: {integrity: sha512-Mo2w3CHmyLCScFuIO2VS2Co44vlPSc4zwujz0x+/zyaJ+eCwBQMRuE9u+9ORjvKImNxrbXI9FQVNlbF0iDk4iQ==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@envelop/core': ^4.0.3 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@envelop/core': 4.0.3 + graphql: 16.8.1 + dev: true + + /@envelop/types@4.0.1: + resolution: {integrity: sha512-ULo27/doEsP7uUhm2iTnElx13qTO6I5FKvmLoX41cpfuw8x6e0NUFknoqhEsLzAbgz8xVS5mjwcxGCXh4lDYzg==} + engines: {node: '>=16.0.0'} + dependencies: + tslib: 2.6.0 + dev: true + /@envelop/types@5.0.0: resolution: {integrity: sha512-IPjmgSc4KpQRlO4qbEDnBEixvtb06WDmjKfi/7fkZaryh5HuOmTtixe1EupQI5XfXO8joc3d27uUZ0QdC++euA==} engines: {node: '>=18.0.0'} @@ -2173,6 +2229,98 @@ packages: dev: true optional: true + /@escape.tech/graphql-armor-block-field-suggestions@2.1.0: + resolution: {integrity: sha512-Sna+jK02oUDJMWSfA7ica69HdtBroP3VakeMUK0+QgWlAEBEphT+SzKGDX5vn6sS7sAsEoY50gUAIgtTG+2qVw==} + engines: {node: '>=16.0.0'} + dependencies: + graphql: 16.8.1 + optionalDependencies: + '@envelop/core': 4.0.3 + dev: true + + /@escape.tech/graphql-armor-cost-limit@2.1.0: + resolution: {integrity: sha512-zejjLm3vn4MQDpXRaPGXclo1Tq1lc93Ltoh3UoqUDiFV29ZUAnSnuuEw/AdbkK+YFrSIfZYMAGDV8AZ2Xz76RQ==} + engines: {node: '>=16.0.0'} + dependencies: + graphql: 16.8.1 + optionalDependencies: + '@envelop/core': 4.0.3 + '@escape.tech/graphql-armor-types': 0.5.0 + dev: true + + /@escape.tech/graphql-armor-max-aliases@2.1.0: + resolution: {integrity: sha512-jaqB8YWIpfDSNrbiGEt301MQqSH7cLu+ZYZjEQ/irL5rqbSN1c9zE+nqEP1cXxB8jB6D+vp8jU30rrZWS9goAQ==} + engines: {node: '>=16.0.0'} + dependencies: + graphql: 16.8.1 + optionalDependencies: + '@envelop/core': 4.0.3 + '@escape.tech/graphql-armor-types': 0.5.0 + dev: true + + /@escape.tech/graphql-armor-max-depth@2.2.0: + resolution: {integrity: sha512-v0z2yelQL614mYFpYL/iRkieq/7H2XKbvJ6RvbGMFFSqo3eSIz8fyX0f6pyswR7myQxki4ur0MFxSn8S5jjfqw==} + engines: {node: '>=16.0.0'} + dependencies: + graphql: 16.8.1 + optionalDependencies: + '@envelop/core': 4.0.3 + '@escape.tech/graphql-armor-types': 0.5.0 + dev: true + + /@escape.tech/graphql-armor-max-directives@2.1.0: + resolution: {integrity: sha512-0OuvWBbOVdphyLPafqTknM4EIrFsGHjv9DcSw8mM7Ol0kKLwYG7tGuBmEzwopRntkqW3utID5tMtf/B6px/Eyw==} + engines: {node: '>=16.0.0'} + dependencies: + graphql: 16.8.1 + optionalDependencies: + '@envelop/core': 4.0.3 + '@escape.tech/graphql-armor-types': 0.5.0 + dev: true + + /@escape.tech/graphql-armor-max-tokens@2.2.0: + resolution: {integrity: sha512-s6IBS8R4fxQ9cVX1USf4dUOWEDbVVrlcGmVOuTCyW1LnpFJQ5vWCs0n93Lsw2ge/MlRIkZEtGuiXdr0YmLU4Pg==} + engines: {node: '>=16.0.0'} + dependencies: + graphql: 16.8.1 + optionalDependencies: + '@envelop/core': 4.0.3 + '@escape.tech/graphql-armor-types': 0.5.0 + dev: true + + /@escape.tech/graphql-armor-types@0.5.0: + resolution: {integrity: sha512-a7KMhb1qVHFFWw4bvGYQI637YaIZRozbfc+Fj1Vv/pwnTCJOzOgnvKO8+WBXJsFFGJ2Kj+fRORmSpz7J+lJF1w==} + requiresBuild: true + dependencies: + graphql: 16.8.1 + dev: true + optional: true + + /@escape.tech/graphql-armor@2.3.1(@envelop/core@4.0.3): + resolution: {integrity: sha512-2HV6ApCeb52eVTeXjgpo00VLDZkiQfxeMi9KTPHsK8/1f3X60gx51szHwTRYhPUeimUquRcxqlO36Iq3rbhywQ==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@apollo/server': ^4.0.0 + '@envelop/core': ^4.0.0 + '@escape.tech/graphql-armor-types': 0.5.0 + peerDependenciesMeta: + '@apollo/server': + optional: true + '@envelop/core': + optional: true + '@escape.tech/graphql-armor-types': + optional: true + dependencies: + '@envelop/core': 4.0.3 + '@escape.tech/graphql-armor-block-field-suggestions': 2.1.0 + '@escape.tech/graphql-armor-cost-limit': 2.1.0 + '@escape.tech/graphql-armor-max-aliases': 2.1.0 + '@escape.tech/graphql-armor-max-depth': 2.2.0 + '@escape.tech/graphql-armor-max-directives': 2.1.0 + '@escape.tech/graphql-armor-max-tokens': 2.2.0 + graphql: 16.8.1 + dev: true + /@eslint-community/eslint-utils@4.4.0(eslint@8.55.0): resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -2296,6 +2444,13 @@ packages: graphql: 16.8.1 dev: true + /@graphql-yoga/logger@1.0.0: + resolution: {integrity: sha512-JYoxwnPggH2BfO+dWlWZkDeFhyFZqaTRGLvFhy+Pjp2UxitEW6nDrw+pEDw/K9tJwMjIFMmTT9VfTqrnESmBHg==} + engines: {node: '>=16.0.0'} + dependencies: + tslib: 2.6.0 + dev: true + /@graphql-yoga/logger@2.0.0: resolution: {integrity: sha512-Mg8psdkAp+YTG1OGmvU+xa6xpsAmSir0hhr3yFYPyLNwzUj95DdIwsMpKadDj9xDpYgJcH3Hp/4JMal9DhQimA==} engines: {node: '>=18.0.0'} @@ -2303,6 +2458,16 @@ packages: tslib: 2.6.0 dev: true + /@graphql-yoga/subscription@4.0.0: + resolution: {integrity: sha512-0qsN/BPPZNMoC2CZ8i+P6PgiJyHh1H35aKDt37qARBDaIOKDQuvEOq7+4txUKElcmXi7DYFo109FkhSQoEajrg==} + engines: {node: '>=16.0.0'} + dependencies: + '@graphql-yoga/typed-event-target': 2.0.0 + '@repeaterjs/repeater': 3.0.5 + '@whatwg-node/events': 0.1.1 + tslib: 2.6.0 + dev: true + /@graphql-yoga/subscription@5.0.0: resolution: {integrity: sha512-Ri7sK8hmxd/kwaEa0YT8uqQUb2wOLsmBMxI90QDyf96lzOMJRgBuNYoEkU1pSgsgmW2glceZ96sRYfaXqwVxUw==} engines: {node: '>=18.0.0'} @@ -2313,6 +2478,14 @@ packages: tslib: 2.6.0 dev: true + /@graphql-yoga/typed-event-target@2.0.0: + resolution: {integrity: sha512-oA/VGxGmaSDym1glOHrltw43qZsFwLLjBwvh57B79UKX/vo3+UQcRgOyE44c5RP7DCYjkrC2tuArZmb6jCzysw==} + engines: {node: '>=16.0.0'} + dependencies: + '@repeaterjs/repeater': 3.0.5 + tslib: 2.6.0 + dev: true + /@graphql-yoga/typed-event-target@3.0.0: resolution: {integrity: sha512-w+liuBySifrstuHbFrHoHAEyVnDFVib+073q8AeAJ/qqJfvFvAwUPLLtNohR/WDVRgSasfXtl3dcNuVJWN+rjg==} engines: {node: '>=18.0.0'} @@ -2346,6 +2519,10 @@ packages: resolution: {integrity: sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==} dev: true + /@iarna/toml@2.2.5: + resolution: {integrity: sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==} + dev: true + /@ioredis/commands@1.2.0: resolution: {integrity: sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==} dev: true @@ -3162,6 +3339,11 @@ packages: engines: {node: '>=8.0.0'} dev: false + /@opentelemetry/api@1.7.0: + resolution: {integrity: sha512-AdY5wvN0P2vXBi3b29hxZgSFvdhdxPB9+f0B6s//P9Q8nibRWeA3cHm8UmLpio9ABigkVHJ5NMPk+Mz8VCCyrw==} + engines: {node: '>=8.0.0'} + dev: true + /@paralleldrive/cuid2@2.2.0: resolution: {integrity: sha512-CVQDpPIUHrUGGLdrMGz1NmqZvqmsB2j2rCIQEu1EvxWjlFh4fhvEGmgR409cY20/67/WlJsggenq0no3p3kYsw==} dependencies: @@ -3349,6 +3531,17 @@ packages: prisma: 4.16.2 dev: true + /@prisma/client@5.7.0: + resolution: {integrity: sha512-cZmglCrfNbYpzUtz7HscVHl38e9CrUs31nrVoGUK1nIPXGgt8hT4jj2s657UXcNdQ/jBUxDgGmHyu2Nyrq1txg==} + engines: {node: '>=16.13'} + requiresBuild: true + peerDependencies: + prisma: '*' + peerDependenciesMeta: + prisma: + optional: true + dev: true + /@prisma/debug@4.16.2: resolution: {integrity: sha512-7L7WbG0qNNZYgLpsVB8rCHCXEyHFyIycRlRDNwkVfjQmACC2OW6AWCYCbfdjQhkF/t7+S3njj8wAWAocSs+Brw==} dependencies: @@ -3369,10 +3562,18 @@ packages: - supports-color dev: false + /@prisma/debug@5.7.0: + resolution: {integrity: sha512-tZ+MOjWlVvz1kOEhNYMa4QUGURY+kgOUBqLHYIV8jmCsMuvA1tWcn7qtIMLzYWCbDcQT4ZS8xDgK0R2gl6/0wA==} + dev: true + /@prisma/engines-version@4.16.1-1.4bc8b6e1b66cb932731fb1bdbbc550d1e010de81: resolution: {integrity: sha512-q617EUWfRIDTriWADZ4YiWRZXCa/WuhNgLTVd+HqWLffjMSPzyM5uOWoauX91wvQClSKZU4pzI4JJLQ9Kl62Qg==} dev: true + /@prisma/engines-version@5.7.0-41.79fb5193cf0a8fdbef536e4b4a159cad677ab1b9: + resolution: {integrity: sha512-V6tgRVi62jRwTm0Hglky3Scwjr/AKFBFtS+MdbsBr7UOuiu1TKLPc6xfPiyEN1+bYqjEtjxwGsHgahcJsd1rNg==} + dev: true + /@prisma/engines@4.16.2: resolution: {integrity: sha512-vx1nxVvN4QeT/cepQce68deh/Turxy5Mr+4L4zClFuK1GlxN3+ivxfuv+ej/gvidWn1cE1uAhW7ALLNlYbRUAw==} requiresBuild: true @@ -3382,6 +3583,16 @@ packages: requiresBuild: true dev: false + /@prisma/engines@5.7.0: + resolution: {integrity: sha512-TkOMgMm60n5YgEKPn9erIvFX2/QuWnl3GBo6yTRyZKk5O5KQertXiNnrYgSLy0SpsKmhovEPQb+D4l0SzyE7XA==} + requiresBuild: true + dependencies: + '@prisma/debug': 5.7.0 + '@prisma/engines-version': 5.7.0-41.79fb5193cf0a8fdbef536e4b4a159cad677ab1b9 + '@prisma/fetch-engine': 5.7.0 + '@prisma/get-platform': 5.7.0 + dev: true + /@prisma/fetch-engine@4.16.2: resolution: {integrity: sha512-lnCnHcOaNn0kw8qTJbVcNhyfIf5Lus2GFXbj3qpkdKEIB9xLgqkkuTP+35q1xFaqwQ0vy4HFpdRUpFP7njE15g==} dependencies: @@ -3432,6 +3643,14 @@ packages: - supports-color dev: false + /@prisma/fetch-engine@5.7.0: + resolution: {integrity: sha512-zIn/qmO+N/3FYe7/L9o+yZseIU8ivh4NdPKSkQRIHfg2QVTVMnbhGoTcecbxfVubeTp+DjcbjS0H9fCuM4W04w==} + dependencies: + '@prisma/debug': 5.7.0 + '@prisma/engines-version': 5.7.0-41.79fb5193cf0a8fdbef536e4b4a159cad677ab1b9 + '@prisma/get-platform': 5.7.0 + dev: true + /@prisma/generator-helper@4.16.2: resolution: {integrity: sha512-bMOH7y73Ui7gpQrioFeavMQA+Tf8ksaVf8Nhs9rQNzuSg8SSV6E9baczob0L5KGZTSgYoqnrRxuo03kVJYrnIg==} dependencies: @@ -3454,6 +3673,12 @@ packages: - supports-color dev: false + /@prisma/generator-helper@5.7.0: + resolution: {integrity: sha512-Fn4hJHKGJ49+E8sxpfslRauB3Goa3RAENJ/W25NMR754B9KxvmbCJyE3MT/lIZxML2nGgIdXYUtoDHZHnRaKDw==} + dependencies: + '@prisma/debug': 5.7.0 + dev: true + /@prisma/get-platform@4.16.2: resolution: {integrity: sha512-fnDey1/iSefHJRMB+w243BhWENf+paRouPMdCqIVqu8dYkR1NqhldblsSUC4Zr2sKS7Ta2sK4OLdt9IH+PZTfw==} dependencies: @@ -3488,6 +3713,12 @@ packages: - supports-color dev: false + /@prisma/get-platform@5.7.0: + resolution: {integrity: sha512-ZeV/Op4bZsWXuw5Tg05WwRI8BlKiRFhsixPcAM+5BKYSiUZiMKIi713tfT3drBq8+T0E1arNZgYSA9QYcglWNA==} + dependencies: + '@prisma/debug': 5.7.0 + dev: true + /@prisma/internals@4.16.2: resolution: {integrity: sha512-/3OiSADA3RRgsaeEE+MDsBgL6oAMwddSheXn6wtYGUnjERAV/BmF5bMMLnTykesQqwZ1s8HrISrJ0Vf6cjOxMg==} dependencies: @@ -3590,6 +3821,19 @@ packages: - supports-color dev: false + /@prisma/internals@5.7.0: + resolution: {integrity: sha512-O9x47W1DECAyvNjYUx6oZHmTX10emKuBgsFHZemUbkIcJdCsp3X8Cy2JMJ5z3hqkRX6a6omMamFsWjuTARoaSw==} + dependencies: + '@prisma/debug': 5.7.0 + '@prisma/engines': 5.7.0 + '@prisma/fetch-engine': 5.7.0 + '@prisma/generator-helper': 5.7.0 + '@prisma/get-platform': 5.7.0 + '@prisma/prisma-schema-wasm': 5.7.0-41.79fb5193cf0a8fdbef536e4b4a159cad677ab1b9 + arg: 5.0.2 + prompts: 2.4.2 + dev: true + /@prisma/prisma-fmt-wasm@4.16.1-1.4bc8b6e1b66cb932731fb1bdbbc550d1e010de81: resolution: {integrity: sha512-g090+dEH7wrdCw359+8J9+TGH84qK28V/dxwINjhhNCtju9lej99z9w/AVsJP9UhhcCPS4psYz4iu8d53uxVpA==} dev: false @@ -3598,6 +3842,10 @@ packages: resolution: {integrity: sha512-JFdsnSgBPN8reDTLOI9Vh/6ccCb2aD1LbY/LWQnkcIgNo6IdpzvuM+qRVbBuA6IZP2SdqQI8Lu6RL2P8EFBQUA==} dev: false + /@prisma/prisma-schema-wasm@5.7.0-41.79fb5193cf0a8fdbef536e4b4a159cad677ab1b9: + resolution: {integrity: sha512-w+HdQtux0dJDEn6BG3fgNn+fXErXiekj9n//uHRAgrmZghockJkhnikOmG8aSXjTb1Tu5DrGasBX+rYX6rHT1w==} + dev: true + /@readme/better-ajv-errors@1.6.0(ajv@8.12.0): resolution: {integrity: sha512-9gO9rld84Jgu13kcbKRU+WHseNhaVt76wYMeRDGsUGYxwJtI3RmEJ9LY9dZCYQGI8eUZLuxb5qDja0nqklpFjQ==} engines: {node: '>=14'} @@ -3640,6 +3888,137 @@ packages: openapi-types: 12.1.0 dev: true + /@redwoodjs/api@6.6.0: + resolution: {integrity: sha512-QUlSI6YDurBDtE9t2FC/2JpGM+iVHxN6FoOfRqrfLsTPjrkH2pq7CPI38O5zOjWdsOkha0nxiV4te25cfgG5Lg==} + hasBin: true + peerDependencies: + memjs: 1.3.1 + redis: 4.6.7 + peerDependenciesMeta: + memjs: + optional: true + redis: + optional: true + dependencies: + '@babel/runtime-corejs3': 7.23.6 + '@prisma/client': 5.7.0 + '@whatwg-node/fetch': 0.9.14 + core-js: 3.34.0 + humanize-string: 2.1.0 + jsonwebtoken: 9.0.2 + pascalcase: 1.0.0 + pino: 8.16.2 + title-case: 3.0.3 + transitivePeerDependencies: + - prisma + dev: true + + /@redwoodjs/cli-helpers@6.6.0: + resolution: {integrity: sha512-mwBNnMMWe4EWrbMfcYTTmdUb+saGYBBtqKB1IAxzJQdHEX1jwxwZRM2adRZ1mPHFu+Qg9DZD7GlowaYD6cQaaw==} + dependencies: + '@babel/core': 7.23.2 + '@babel/runtime-corejs3': 7.23.6 + '@iarna/toml': 2.2.5 + '@opentelemetry/api': 1.7.0 + '@redwoodjs/project-config': 6.6.0 + '@redwoodjs/telemetry': 6.6.0 + chalk: 4.1.2 + core-js: 3.34.0 + dotenv: 16.3.1 + execa: 5.1.1 + listr2: 6.6.1 + lodash: 4.17.21 + pascalcase: 1.0.0 + prettier: 2.8.8 + prompts: 2.4.2 + terminal-link: 2.1.1 + transitivePeerDependencies: + - enquirer + - supports-color + dev: true + + /@redwoodjs/graphql-server@6.6.0: + resolution: {integrity: sha512-LuSHmQyZm9E8STfJszSAoNyMHREI/nx2zlA1UzQOG4605YgpljI2wXUxYw7UWCH3rU66Gt0daKdv8GSo2nPlSg==} + dependencies: + '@babel/runtime-corejs3': 7.23.6 + '@envelop/core': 4.0.3 + '@envelop/depth-limit': 3.0.3(@envelop/core@4.0.3)(graphql@16.8.1) + '@envelop/disable-introspection': 5.0.3(@envelop/core@4.0.3)(graphql@16.8.1) + '@envelop/filter-operation-type': 5.0.3(@envelop/core@4.0.3)(graphql@16.8.1) + '@envelop/on-resolve': 3.0.3(@envelop/core@4.0.3)(graphql@16.8.1) + '@escape.tech/graphql-armor': 2.3.1(@envelop/core@4.0.3) + '@graphql-tools/merge': 9.0.1(graphql@16.8.1) + '@graphql-tools/schema': 10.0.2(graphql@16.8.1) + '@graphql-tools/utils': 10.0.11(graphql@16.8.1) + '@opentelemetry/api': 1.7.0 + '@redwoodjs/api': 6.6.0 + core-js: 3.34.0 + graphql: 16.8.1 + graphql-scalars: 1.22.4(graphql@16.8.1) + graphql-tag: 2.12.6(graphql@16.8.1) + graphql-yoga: 4.0.4(graphql@16.8.1) + lodash: 4.17.21 + uuid: 9.0.1 + transitivePeerDependencies: + - '@apollo/server' + - '@escape.tech/graphql-armor-types' + - memjs + - prisma + - redis + dev: true + + /@redwoodjs/project-config@6.6.0: + resolution: {integrity: sha512-L0RZbzQfJrPTfR+w5OfY/FrZny2kXXXwY5ZUhb4k7yXCx3jXG9CrB71/Latek60H45DvS6eyfUd/d1T3lCb/eA==} + dependencies: + '@iarna/toml': 2.2.5 + deepmerge: 4.3.1 + fast-glob: 3.3.2 + string-env-interpolation: 1.0.1 + dev: true + + /@redwoodjs/structure@6.6.0: + resolution: {integrity: sha512-8i4ujrhBklYNPQ7/uAf/W/rrRs9/2dIwVxTjvQz8N7NU4s3J0IrdHj5Q74vIyGOCBA8Lx3SbyXVGjIdg1sdx5g==} + dependencies: + '@babel/runtime-corejs3': 7.23.6 + '@iarna/toml': 2.2.5 + '@prisma/internals': 5.7.0 + '@redwoodjs/project-config': 6.6.0 + '@types/line-column': 1.0.0 + camelcase: 6.3.0 + core-js: 3.34.0 + deepmerge: 4.3.1 + dotenv-defaults: 5.0.2 + enquirer: 2.4.1 + fast-glob: 3.3.2 + graphql: 16.8.1 + lazy-get-decorator: 2.2.1 + line-column: 1.0.2 + lodash: 4.17.21 + lodash-decorators: 6.0.1(lodash@4.17.21) + lru-cache: 7.18.3 + proxyquire: 2.1.3 + ts-morph: 15.1.0 + vscode-languageserver: 6.1.1 + vscode-languageserver-textdocument: 1.0.8 + vscode-languageserver-types: 3.17.3 + yargs-parser: 21.1.1 + dev: true + + /@redwoodjs/telemetry@6.6.0: + resolution: {integrity: sha512-9VEwngUBtbaPLaSdIQtthUiqrDHo4KFzDAmilvHUyV9Wgq49lCt/lpt7Dm3fO9C8l7n5WunXOKi7X2pp/IE1xw==} + dependencies: + '@babel/runtime-corejs3': 7.23.6 + '@redwoodjs/project-config': 6.6.0 + '@redwoodjs/structure': 6.6.0 + '@whatwg-node/fetch': 0.9.14 + ci-info: 4.0.0 + core-js: 3.34.0 + envinfo: 7.11.0 + systeminformation: 5.21.20 + uuid: 9.0.1 + yargs: 17.7.2 + dev: true + /@repeaterjs/repeater@3.0.5: resolution: {integrity: sha512-l3YHBLAol6d/IKnB9LhpD0cEZWAoe3eFKUyTYWmFmCO2Q/WOckxLQAUyMZWwZV2M/m3+4vgRoaolFqaII82/TA==} dev: true @@ -4170,6 +4549,15 @@ packages: engines: {node: '>=10.13.0'} dev: true + /@ts-morph/common@0.16.0: + resolution: {integrity: sha512-SgJpzkTgZKLKqQniCjLaE3c2L2sdL7UShvmTmPBejAKd2OKV/yfMpQ2IWpAuA+VY5wy7PkSUaEObIqEK6afFuw==} + dependencies: + fast-glob: 3.3.2 + minimatch: 5.1.6 + mkdirp: 1.0.4 + path-browserify: 1.0.1 + dev: true + /@ts-morph/common@0.17.0: resolution: {integrity: sha512-RMSSvSfs9kb0VzkvQ2NWobwnj7TxCA9vI/IjR9bDHqgAyVbu2T0DN4wiKVqomyDWqO7dPr/tErSfq7urQ1Q37g==} dependencies: @@ -4370,6 +4758,10 @@ packages: '@types/node': 18.0.0 dev: true + /@types/line-column@1.0.0: + resolution: {integrity: sha512-wbw+IDRw/xY/RGy+BL6f4Eey4jsUgHQrMuA4Qj0CSG3x/7C2Oc57pmRoM2z3M4DkylWRz+G1pfX06sCXQm0J+w==} + dev: true + /@types/mime@1.3.2: resolution: {integrity: sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==} dev: true @@ -4921,8 +5313,8 @@ packages: '@babel/core': 7.23.2 '@babel/helper-module-imports': 7.22.5 '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.23.2) - '@babel/template': 7.22.5 - '@babel/traverse': 7.22.8 + '@babel/template': 7.22.15 + '@babel/traverse': 7.23.2 '@babel/types': 7.23.0 '@vue/babel-helper-vue-transform-on': 1.1.5 camelcase: 6.3.0 @@ -5185,6 +5577,12 @@ packages: dependencies: type-fest: 0.21.3 + /ansi-escapes@5.0.0: + resolution: {integrity: sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA==} + engines: {node: '>=12'} + dependencies: + type-fest: 1.4.0 + /ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -5192,7 +5590,6 @@ packages: /ansi-regex@6.0.1: resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} engines: {node: '>=12'} - dev: true /ansi-styles@3.2.1: resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} @@ -5214,7 +5611,6 @@ packages: /ansi-styles@6.2.1: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} - dev: true /any-promise@1.3.0: resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} @@ -5308,7 +5704,6 @@ packages: /arg@5.0.2: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} - dev: false /argparse@1.0.10: resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} @@ -5703,6 +6098,10 @@ packages: /buffer-crc32@0.2.13: resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + /buffer-equal-constant-time@1.0.1: + resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} + dev: true + /buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} dev: true @@ -5990,6 +6389,11 @@ packages: resolution: {integrity: sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==} engines: {node: '>=8'} + /ci-info@4.0.0: + resolution: {integrity: sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==} + engines: {node: '>=8'} + dev: true + /citty@0.1.4: resolution: {integrity: sha512-Q3bK1huLxzQrvj7hImJ7Z1vKYJRPQCDnd0EjXfHMidcjecGOMuLrmuQmtWmFkuKLcMThlGh1yCKG8IEc6VeNXQ==} dependencies: @@ -6016,6 +6420,12 @@ packages: restore-cursor: 3.1.0 dev: false + /cli-cursor@4.0.0: + resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + restore-cursor: 4.0.0 + /cli-spinners@2.9.0: resolution: {integrity: sha512-4/aL9X3Wh0yiMQlE+eeRhWP6vclO3QRtw1JHKIT0FFUs5FjpFmESqtMvYZ0+lbzBw900b95mS0hohy+qn2VK/g==} engines: {node: '>=6'} @@ -6035,7 +6445,6 @@ packages: dependencies: slice-ansi: 5.0.0 string-width: 5.1.2 - dev: true /client-only@0.0.1: resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} @@ -6090,7 +6499,6 @@ packages: /code-block-writer@11.0.3: resolution: {integrity: sha512-NiujjUFB4SwScJq2bwbYUtXbZhBSlY6vYzm++3Q6oC+U+injTqfPYFK8wS9COOmb2lueqp0ZRB4nK1VYeHgNyw==} - dev: false /code-error-fragment@0.0.230: resolution: {integrity: sha512-cadkfKp6932H8UkhzE/gcUqhRMNf8jHzkAN7+5Myabswaghu4xABTgPHDCjW+dBAJxj/SpkTYokpzDqY4pCzQw==} @@ -6139,7 +6547,6 @@ packages: /colorette@2.0.20: resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} - dev: true /colors@1.4.0: resolution: {integrity: sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==} @@ -6333,6 +6740,16 @@ packages: yargs: 16.2.0 dev: true + /core-js-pure@3.35.0: + resolution: {integrity: sha512-f+eRYmkou59uh7BPcyJ8MC76DiGhspj1KMxVIcF24tzP8NA9HVa1uC7BTW2tgx7E1QVCzDzsgp7kArrzhlz8Ew==} + requiresBuild: true + dev: true + + /core-js@3.34.0: + resolution: {integrity: sha512-aDdvlDder8QmY91H88GzNi9EtQi2TjvQhpCX6B1v/dAZHU1AuLgHvRh54RiOerpEhEW46Tkf+vgAViB/CWC0ag==} + requiresBuild: true + dev: true + /core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} @@ -6636,6 +7053,13 @@ packages: engines: {node: '>=0.10.0'} dev: true + /decamelize@2.0.0: + resolution: {integrity: sha512-Ikpp5scV3MSYxY39ymh45ZLEecsTdv/Xj2CaQfI8RLMuwi7XvjX9H/fhraiSuU+C5w5NTDu4ZU72xNiZnurBPg==} + engines: {node: '>=4'} + dependencies: + xregexp: 4.0.0 + dev: true + /decimal.js@10.4.2: resolution: {integrity: sha512-ic1yEvwT6GuvaYwBLLY6/aFFgjZdySKTE8en/fkU3QICTmRtgtSlFn0u0BXN06InZwtfCelR7j8LRiDI/02iGA==} @@ -6895,6 +7319,17 @@ packages: type-fest: 3.13.1 dev: true + /dotenv-defaults@5.0.2: + resolution: {integrity: sha512-y5z4NhblzwNk8XBIYVzjLcFkANK0rxbRDO6kGOfH9QrVYIGVEX52IqwSprKVsaLHM9pnNkCSxazZF/JPydDPvA==} + dependencies: + dotenv: 14.3.2 + dev: true + + /dotenv@14.3.2: + resolution: {integrity: sha512-vwEppIphpFdvaMCaHfCEv9IgwcxMljMw2TnAQBB4VWPvzXQLTb82jwmdOKzlEVUL3gNFT4l4TPKO+Bn+sqcrVQ==} + engines: {node: '>=12'} + dev: true + /dotenv@16.0.3: resolution: {integrity: sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==} engines: {node: '>=12'} @@ -6915,6 +7350,11 @@ packages: /eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + /ecdsa-sig-formatter@1.0.11: + resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} + dependencies: + safe-buffer: 5.2.1 dev: true /ee-first@1.1.1: @@ -6939,7 +7379,6 @@ packages: /emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - dev: true /emphasize@4.2.0: resolution: {integrity: sha512-yGKvcFUHlBsUPwlxTlzKLR8+zhpbitkFOMCUxN8fTJng9bdH3WNzUGkhdaGdjndSUgqmMPBN7umfwnUdLz5Axg==} @@ -6984,6 +7423,14 @@ packages: ansi-colors: 4.1.3 dev: true + /enquirer@2.4.1: + resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} + engines: {node: '>=8.6'} + dependencies: + ansi-colors: 4.1.3 + strip-ansi: 6.0.1 + dev: true + /entities@2.1.0: resolution: {integrity: sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==} dev: true @@ -6998,6 +7445,12 @@ packages: engines: {node: '>=6'} dev: false + /envinfo@7.11.0: + resolution: {integrity: sha512-G9/6xF1FPbIw0TtalAMaVPpiq2aDEuKLXM314jPVAO9r2fo2a4BLqMNkmRS7O/xPPZ+COAhGIz3ETvHEV3eUcg==} + engines: {node: '>=4'} + hasBin: true + dev: true + /errno@0.1.8: resolution: {integrity: sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==} hasBin: true @@ -7584,6 +8037,9 @@ packages: engines: {node: '>=6'} dev: true + /eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + /events@3.3.0: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} @@ -7732,6 +8188,17 @@ packages: merge2: 1.4.1 micromatch: 4.0.5 + /fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + dev: true + /fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} dev: true @@ -7842,6 +8309,14 @@ packages: resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} dev: true + /fill-keys@1.0.2: + resolution: {integrity: sha512-tcgI872xXjwFF4xgQmLxi76GnwJG3g/3isB1l4/G5Z4zrbddGpBjqZCO9oEAcB5wX0Hj/5iQB3toxfO7in1hHA==} + engines: {node: '>=0.10.0'} + dependencies: + is-object: 1.0.2 + merge-descriptors: 1.0.1 + dev: true + /fill-range@7.0.1: resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} engines: {node: '>=8'} @@ -8320,6 +8795,56 @@ packages: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} dev: true + /graphql-depth-limit@1.1.0(graphql@16.8.1): + resolution: {integrity: sha512-+3B2BaG8qQ8E18kzk9yiSdAa75i/hnnOwgSeAxVJctGQPvmeiLtqKOYF6HETCyRjiF7Xfsyal0HbLlxCQkgkrw==} + engines: {node: '>=6.0.0'} + peerDependencies: + graphql: '*' + dependencies: + arrify: 1.0.1 + graphql: 16.8.1 + dev: true + + /graphql-scalars@1.22.4(graphql@16.8.1): + resolution: {integrity: sha512-ILnv7jq5VKHLUyoaTFX7lgYrjCd6vTee9i8/B+D4zJKJT5TguOl0KkpPEbXHjmeor8AZYrVsrYUHdqRBMX1pjA==} + engines: {node: '>=10'} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + graphql: 16.8.1 + tslib: 2.6.0 + dev: true + + /graphql-tag@2.12.6(graphql@16.8.1): + resolution: {integrity: sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==} + engines: {node: '>=10'} + peerDependencies: + graphql: ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + graphql: 16.8.1 + tslib: 2.6.0 + dev: true + + /graphql-yoga@4.0.4(graphql@16.8.1): + resolution: {integrity: sha512-MvCLhFecYNIKuxAZisPjpIL9lxRYbpgPSNKENDO/8CV3oiFlsLJHZb5dp2sVAeLafXHeZ9TgkijLthUBc1+Jag==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^15.2.0 || ^16.0.0 + dependencies: + '@envelop/core': 4.0.3 + '@graphql-tools/executor': 1.2.0(graphql@16.8.1) + '@graphql-tools/schema': 10.0.2(graphql@16.8.1) + '@graphql-tools/utils': 10.0.11(graphql@16.8.1) + '@graphql-yoga/logger': 1.0.0 + '@graphql-yoga/subscription': 4.0.0 + '@whatwg-node/fetch': 0.9.14 + '@whatwg-node/server': 0.9.19 + dset: 3.1.3 + graphql: 16.8.1 + lru-cache: 10.0.1 + tslib: 2.6.0 + dev: true + /graphql-yoga@5.0.2(graphql@16.8.1): resolution: {integrity: sha512-+r0aZ5sBQaWTFEwmDdPR+XcsYaIIh40IA34F7rhnyY57KXgs18ZkCZ9NPvfi6XEuqkHEvc2PFox05c5NRSJ26g==} engines: {node: '>=18.0.0'} @@ -8575,6 +9100,13 @@ packages: engines: {node: '>=16.17.0'} dev: true + /humanize-string@2.1.0: + resolution: {integrity: sha512-sQ+hqmxyXW8Cj7iqxcQxD7oSy3+AXnIZXdUF9lQMkzaG8dtbKAB8U7lCtViMnwQ+MpdCKsO2Kiij3G6UUXq/Xg==} + engines: {node: '>=6'} + dependencies: + decamelize: 2.0.0 + dev: true + /iconv-lite@0.4.24: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} @@ -8781,7 +9313,6 @@ packages: /is-fullwidth-code-point@4.0.0: resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} engines: {node: '>=12'} - dev: true /is-generator-fn@2.1.0: resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} @@ -8823,6 +9354,10 @@ packages: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} + /is-object@1.0.2: + resolution: {integrity: sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==} + dev: true + /is-path-cwd@2.2.0: resolution: {integrity: sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==} engines: {node: '>=6'} @@ -8988,6 +9523,13 @@ packages: /isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + /isobject@2.1.0: + resolution: {integrity: sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==} + engines: {node: '>=0.10.0'} + dependencies: + isarray: 1.0.0 + dev: true + /isomorphic-fetch@3.0.0: resolution: {integrity: sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==} dependencies: @@ -9673,6 +10215,37 @@ packages: resolution: {integrity: sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==} dev: true + /jsonwebtoken@9.0.2: + resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==} + engines: {node: '>=12', npm: '>=6'} + dependencies: + jws: 3.2.2 + lodash.includes: 4.3.0 + lodash.isboolean: 3.0.3 + lodash.isinteger: 4.0.4 + lodash.isnumber: 3.0.3 + lodash.isplainobject: 4.0.6 + lodash.isstring: 4.0.1 + lodash.once: 4.1.1 + ms: 2.1.3 + semver: 7.5.4 + dev: true + + /jwa@1.4.1: + resolution: {integrity: sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==} + dependencies: + buffer-equal-constant-time: 1.0.1 + ecdsa-sig-formatter: 1.0.11 + safe-buffer: 5.2.1 + dev: true + + /jws@3.2.2: + resolution: {integrity: sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==} + dependencies: + jwa: 1.4.1 + safe-buffer: 5.2.1 + dev: true + /keytar@7.9.0: resolution: {integrity: sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ==} requiresBuild: true @@ -9727,6 +10300,10 @@ packages: vscode-languageserver-textdocument: 1.0.8 vscode-uri: 3.0.7 + /lazy-get-decorator@2.2.1: + resolution: {integrity: sha512-Z5uxqhXT+h3s1az3JaEAi9eh8+p4pIUE3qJGgfkx9zIEiA3bIpg4ChxODLwCpFr9S+PDEJ/2Q1UaMqy8RdVCxg==} + dev: true + /lazystream@1.0.1: resolution: {integrity: sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==} engines: {node: '>= 0.6.3'} @@ -9759,6 +10336,13 @@ packages: engines: {node: '>=10'} dev: true + /line-column@1.0.2: + resolution: {integrity: sha512-Ktrjk5noGYlHsVnYWh62FLVs4hTb8A3e+vucNZMgPeAOITdshMSgv4cCZQeRDjm7+goqmo6+liZwTXo+U3sVww==} + dependencies: + isarray: 1.0.0 + isobject: 2.1.0 + dev: true + /lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} @@ -9791,6 +10375,22 @@ packages: uqr: 0.1.2 dev: true + /listr2@6.6.1: + resolution: {integrity: sha512-+rAXGHh0fkEWdXBmX+L6mmfmXmXvDGEKzkjxO+8mP3+nI/r/CWznVBvsibXdxda9Zz0OW2e2ikphN3OwCT/jSg==} + engines: {node: '>=16.0.0'} + peerDependencies: + enquirer: '>= 2.3.0 < 3' + peerDependenciesMeta: + enquirer: + optional: true + dependencies: + cli-truncate: 3.1.0 + colorette: 2.0.20 + eventemitter3: 5.0.1 + log-update: 5.0.1 + rfdc: 1.3.0 + wrap-ansi: 8.1.0 + /load-module@4.2.1: resolution: {integrity: sha512-Sbfg6R4LjvyThJpqUoADHMjyoI2+cL4msbCQeZ9kkY/CqP/TT2938eftKm7x4I2gd4/A+DEe6nePkbfWYbXwSw==} engines: {node: '>=12.17'} @@ -9834,6 +10434,16 @@ packages: dependencies: p-locate: 5.0.0 + /lodash-decorators@6.0.1(lodash@4.17.21): + resolution: {integrity: sha512-1M0YC8G3nFTkejZEk2ehyvryEdcqj6xATH+ybI8j53cLs/bKRsavaE//y7nz/A0vxEFhxYqev7vdWfsuTJ1AtQ==} + engines: {node: '>=0.12.0'} + peerDependencies: + lodash: 4.x + dependencies: + lodash: 4.17.21 + tslib: 1.14.1 + dev: true + /lodash.camelcase@4.3.0: resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} dev: true @@ -9853,13 +10463,32 @@ packages: resolution: {integrity: sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==} dev: false + /lodash.includes@4.3.0: + resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==} + dev: true + /lodash.isarguments@3.1.0: resolution: {integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==} dev: true + /lodash.isboolean@3.0.3: + resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==} + dev: true + + /lodash.isinteger@4.0.4: + resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==} + dev: true + + /lodash.isnumber@3.0.3: + resolution: {integrity: sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==} + dev: true + /lodash.isplainobject@4.0.6: resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} - dev: false + + /lodash.isstring@4.0.1: + resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==} + dev: true /lodash.memoize@4.1.2: resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} @@ -9869,6 +10498,10 @@ packages: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} dev: true + /lodash.once@4.1.1: + resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} + dev: true + /lodash.pick@4.4.0: resolution: {integrity: sha512-hXt6Ul/5yWjfklSGvLQl8vM//l3FtyHZeuelpzK6mm99pNvN9yTDruNZPEJZD1oWrqo+izBmB7oUfWgcCX7s4Q==} dev: true @@ -9900,6 +10533,16 @@ packages: is-unicode-supported: 0.1.0 dev: false + /log-update@5.0.1: + resolution: {integrity: sha512-5UtUDQ/6edw4ofyljDNcOVJQ4c7OjDro4h3y8e1GQL5iYElYclVHJ3zeWchylvMaKnDbDilC8irOVyexnA/Slw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + ansi-escapes: 5.0.0 + cli-cursor: 4.0.0 + slice-ansi: 5.0.0 + strip-ansi: 7.1.0 + wrap-ansi: 8.1.0 + /loose-envify@1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true @@ -9956,6 +10599,11 @@ packages: dependencies: yallist: 4.0.0 + /lru-cache@7.18.3: + resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} + engines: {node: '>=12'} + dev: true + /lz-string@1.5.0: resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} hasBin: true @@ -10236,6 +10884,10 @@ packages: ufo: 1.3.1 dev: true + /module-not-found-error@1.0.1: + resolution: {integrity: sha512-pEk4ECWQXV6z2zjhRZUongnLJNUeGQJ3w6OQ5ctGwD+i5o93qjRQUk2Rt6VdNeu3sEP0AB4LcfvdebpxBRVr4g==} + dev: true + /mri@1.2.0: resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} engines: {node: '>=4'} @@ -11117,9 +11769,13 @@ packages: tslib: 2.6.0 dev: false + /pascalcase@1.0.0: + resolution: {integrity: sha512-BSExi0rRnCHReJys6NocaK+cfTXNinAegfWBvr0JD3hiaEG7Nuc7r0CIdOJunXrs8gU/sbHQ9dxVAtiVQisjmg==} + engines: {node: '>=8'} + dev: true + /path-browserify@1.0.1: resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} - dev: false /path-case@3.0.4: resolution: {integrity: sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==} @@ -11285,6 +11941,13 @@ packages: split2: 4.2.0 dev: true + /pino-abstract-transport@1.1.0: + resolution: {integrity: sha512-lsleG3/2a/JIWUtf9Q5gUNErBqwIu1tUKTT3dUzaf5DySw9ra1wcqKjJjLX1VTY64Wk1eEOYsVGSaGfCK85ekA==} + dependencies: + readable-stream: 4.4.0 + split2: 4.2.0 + dev: true + /pino-std-serializers@6.2.2: resolution: {integrity: sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==} dev: true @@ -11306,6 +11969,23 @@ packages: thread-stream: 2.3.0 dev: true + /pino@8.16.2: + resolution: {integrity: sha512-2advCDGVEvkKu9TTVSa/kWW7Z3htI/sBKEZpqiHk6ive0i/7f5b1rsU8jn0aimxqfnSz5bj/nOYkwhBUn5xxvg==} + hasBin: true + dependencies: + atomic-sleep: 1.0.0 + fast-redact: 3.2.0 + on-exit-leak-free: 2.1.0 + pino-abstract-transport: 1.1.0 + pino-std-serializers: 6.2.2 + process-warning: 2.2.0 + quick-format-unescaped: 4.0.4 + real-require: 0.2.0 + safe-stable-stringify: 2.4.3 + sonic-boom: 3.7.0 + thread-stream: 2.3.0 + dev: true + /pirates@4.0.6: resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} engines: {node: '>= 6'} @@ -11910,6 +12590,14 @@ packages: ipaddr.js: 1.9.1 dev: true + /proxyquire@2.1.3: + resolution: {integrity: sha512-BQWfCqYM+QINd+yawJz23tbBM40VIGXOdDw3X344KcclI/gtBbdWF6SlQ4nK/bYhF9d27KYug9WzljHC6B9Ysg==} + dependencies: + fill-keys: 1.0.2 + module-not-found-error: 1.0.1 + resolve: 1.22.2 + dev: true + /prr@1.0.1: resolution: {integrity: sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==} dev: true @@ -12208,6 +12896,10 @@ packages: resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} dev: true + /regenerator-runtime@0.14.1: + resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} + dev: true + /regexp-to-ast@0.5.0: resolution: {integrity: sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw==} @@ -12327,6 +13019,13 @@ packages: signal-exit: 3.0.7 dev: false + /restore-cursor@4.0.0: + resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + /ret@0.2.2: resolution: {integrity: sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==} engines: {node: '>=4'} @@ -12343,7 +13042,6 @@ packages: /rfdc@1.3.0: resolution: {integrity: sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==} - dev: true /rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} @@ -12674,7 +13372,6 @@ packages: dependencies: ansi-styles: 6.2.1 is-fullwidth-code-point: 4.0.0 - dev: true /smartwrap@2.0.2: resolution: {integrity: sha512-vCsKNQxb7PnCNd2wY1WClWifAc2lwqsG8OaswpJkVJsvMGcnEntdTCDajZCkk93Ay1U3t/9puJmb525Rg5MZBA==} @@ -12706,6 +13403,12 @@ packages: atomic-sleep: 1.0.0 dev: true + /sonic-boom@3.7.0: + resolution: {integrity: sha512-IudtNvSqA/ObjN97tfgNmOKyDOs4dNcg4cUUsHDebqsgb8wGBBwb31LIgShNO8fye0dFI52X1+tFoKKI6Rq1Gg==} + dependencies: + atomic-sleep: 1.0.0 + dev: true + /source-map-js@1.0.2: resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} engines: {node: '>=0.10.0'} @@ -12841,6 +13544,10 @@ packages: queue-tick: 1.0.1 dev: true + /string-env-interpolation@1.0.1: + resolution: {integrity: sha512-78lwMoCcn0nNu8LszbP1UA7g55OeE4v7rCeWnM5B453rnNr4aq+5it3FEYtZrSEiMvHZOZ9Jlqb0OD0M2VInqg==} + dev: true + /string-length@4.0.2: resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} engines: {node: '>=10'} @@ -12864,7 +13571,6 @@ packages: eastasianwidth: 0.2.0 emoji-regex: 9.2.2 strip-ansi: 7.1.0 - dev: true /string.prototype.trim@1.2.7: resolution: {integrity: sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==} @@ -12916,7 +13622,6 @@ packages: engines: {node: '>=12'} dependencies: ansi-regex: 6.0.1 - dev: true /strip-bom@3.0.0: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} @@ -13094,7 +13799,6 @@ packages: dependencies: has-flag: 4.0.0 supports-color: 7.2.0 - dev: false /supports-preserve-symlinks-flag@1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} @@ -13169,6 +13873,13 @@ packages: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} dev: true + /systeminformation@5.21.20: + resolution: {integrity: sha512-AyS1fNc+MDoAJtFknFbbo587H8h6yejJwM+H9rVusnOToIEkiMehMyD5JM7o3j55Cto20MawIZrcgNMgd4BfOQ==} + engines: {node: '>=8.0.0'} + os: [darwin, linux, win32, freebsd, openbsd, netbsd, sunos, android] + hasBin: true + dev: true + /table-layout@1.0.2: resolution: {integrity: sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A==} engines: {node: '>=8.0.0'} @@ -13274,7 +13985,6 @@ packages: dependencies: ansi-escapes: 4.3.2 supports-hyperlinks: 2.3.0 - dev: false /terser@5.21.0: resolution: {integrity: sha512-WtnFKrxu9kaoXuiZFSGrcAvvBqAdmKx0SFNmVNYdJamMu9yyN3I/QF0FbH4QcqJQ+y1CJnzxGIKH0cSj+FGYRw==} @@ -13347,6 +14057,12 @@ packages: engines: {node: '>=14.0.0'} dev: true + /title-case@3.0.3: + resolution: {integrity: sha512-e1zGYRvbffpcHIrnuqT0Dh+gEJtDaxDSoG4JAIpq4oDFyooziLBIiYQv0GBT4FUAnUop5uZ1hiIAj7oAF6sOCA==} + dependencies: + tslib: 2.6.0 + dev: true + /tmp@0.0.33: resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} engines: {node: '>=0.6.0'} @@ -13474,6 +14190,13 @@ packages: yargs-parser: 21.1.1 dev: true + /ts-morph@15.1.0: + resolution: {integrity: sha512-RBsGE2sDzUXFTnv8Ba22QfeuKbgvAGJFuTN7HfmIRUkgT/NaVLfDM/8OFm2NlFkGlWEXdpW5OaFIp1jvqdDuOg==} + dependencies: + '@ts-morph/common': 0.16.0 + code-block-writer: 11.0.3 + dev: true + /ts-morph@16.0.0: resolution: {integrity: sha512-jGNF0GVpFj0orFw55LTsQxVYEUOCWBAbR5Ls7fTYE5pQsbW18ssTb/6UXx/GYAEjS+DQTp8VoTw0vqYMiaaQuw==} dependencies: @@ -13650,6 +14373,10 @@ packages: resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} engines: {node: '>=8'} + /type-fest@1.4.0: + resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==} + engines: {node: '>=10'} + /type-fest@3.13.1: resolution: {integrity: sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==} engines: {node: '>=14.16'} @@ -14031,6 +14758,11 @@ packages: resolution: {integrity: sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==} hasBin: true + /uuid@9.0.1: + resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + hasBin: true + dev: true + /v8-compile-cache-lib@3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} dev: true @@ -14351,6 +15083,17 @@ packages: /vscode-languageserver-types@3.17.2: resolution: {integrity: sha512-zHhCWatviizPIq9B7Vh9uvrH6x3sK8itC84HkamnBWoDFJtzBf7SWlpLCZUit72b3os45h6RWQNC9xHRDF8dRA==} + /vscode-languageserver-types@3.17.3: + resolution: {integrity: sha512-SYU4z1dL0PyIMd4Vj8YOqFvHu7Hz/enbWtpfnVbJHU4Nd1YNYx8u0ennumc6h48GQNeOLxmwySmnADouT/AuZA==} + dev: true + + /vscode-languageserver@6.1.1: + resolution: {integrity: sha512-DueEpkUAkD5XTR4MLYNr6bQIp/UFR0/IPApgXU3YfCBCB08u2sm9hRCs6DxYZELkk++STPjpcjksR2H8qI3cDQ==} + hasBin: true + dependencies: + vscode-languageserver-protocol: 3.17.2 + dev: true + /vscode-languageserver@7.0.0: resolution: {integrity: sha512-60HTx5ID+fLRcgdHfmz0LDZAXYEV68fzwG0JWwEPBode9NuMYTIxuYXPg4ngO8i8+Ou0lM7y6GzaYWbiDL0drw==} hasBin: true @@ -14601,6 +15344,14 @@ packages: string-width: 4.2.3 strip-ansi: 6.0.1 + /wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + /wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} @@ -14647,6 +15398,10 @@ packages: resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} dev: true + /xregexp@4.0.0: + resolution: {integrity: sha512-PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg==} + dev: true + /xtend@4.0.2: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} From 32a5727a61e3c5f0d7a5ad14e5e2ac4dfd6df80a Mon Sep 17 00:00:00 2001 From: ymc9 <104139426+ymc9@users.noreply.github.com> Date: Sun, 31 Dec 2023 15:51:12 +0800 Subject: [PATCH 4/4] update README --- packages/misc/redwood/README.md | 78 ++++++++++++++++++++++++++++++++- 1 file changed, 76 insertions(+), 2 deletions(-) diff --git a/packages/misc/redwood/README.md b/packages/misc/redwood/README.md index ee9e8c003..55daa78fa 100644 --- a/packages/misc/redwood/README.md +++ b/packages/misc/redwood/README.md @@ -1,5 +1,79 @@ # ZenStack RedwoodJS Integration -This package is for integrating ZenStack into [RedwoodJS](https://redwoodjs.com/) projects. +This package provides the CLI and runtime APIs for integrating [ZenStack](https://zenstack.dev) into a [RedwoodJS](https://redwoodjs.com/) project. You can use ZenStack as a drop-in replacement to Prisma and define flexible access control policies declaratively inside the database schema. It's especially useful for building multi-tenant applications which tend to have complex authorization requirements beyond RBAC. -Visit [Homepage](https://zenstack.dev) for more details. +ZenStack is a full-stack toolkit built above Prisma ORM. It extends Prisma at the schema and the runtime level for adding the following capabilities: + +- Flexible access control +- Data validation rules +- Multi-file schemas +- Custom attributes and functions in schemas + +Visit [homepage](https://zenstack.dev) for more details. + +## Setting up + +This package leverages RedwoodJS's experimental feature to register a custom CLI command to `yarn redwood`. To enable it, add the following to `redwood.toml`: + +```toml +[experimental.cli] + autoInstall = true + [[experimental.cli.plugins]] + package = "@zenstackhq/redwood" +``` + +Then you can run `yarn rw @zenstackhq setup` to install ZenStack into your Redwood project. The setup command will: + +1. Install ZenStack dependencies. +2. Copy your Prisma schema file "api/db/schema.prisma" to "api/db/schema.zmodel". +3. Add a "zenstack" section into "api/package.json" to specify the location of both the "schema.prisma" and "schema.zmodel" files. +4. Install a GraphQLYoga plugin in "api/src/functions/graphql.[ts|js]". +5. Eject service templates and modify the templates to use `context.db` (ZenStack-enhanced `PrismaClient`) instead of `db` for data access. + +## Modeling data and access policies + +ZenStack's ZModel language is a superset of Prisma schema language. You should use it to define both the data schema and access policies. The regular Prisma schema file will be regenerated from the ZModel file when you run + +```bash +yarn rw @zenstackhq generate +``` + +[The Complete Guide](https://zenstack.dev/docs/the-complete-guide/part1/) of ZenStack is the best way to learn how to author ZModel schemas. You can also use the + +```bash +yarn rw @zenstackhq sample +``` + +command to browse a list of sample schemas and create from them. + +## Development workflow + +The workflow of using ZenStack is very similar to using Prisma in RedwoodJS projects. The two main differences are: + +1. Generation + + You should run `yarn rw @zenstackhq generate` in place of `yarn rw prisma generate`. The ZenStack's generate command internally regenerates the Prisma schema from the ZModel schema, runs `prisma generate` automatically, and also generates other modules for supporting access policy enforcement at the runtime. + +2. Database access in services + + In your service code, you should use `context.db` instead of `db` for accessing the database. The `context.db` is an enhanced Prisma client that enforces access policies. + + The "setup" command prepared a customized service code template. When you run `yarn rw g service`, the generated code will already use `context.db`. + +Other Prisma-related workflows like generation migration or pushing schema to the database stay unchanged. + +## Deployment + +You should run the "generate" command in your deployment script before `yarn rw deploy`. For example, to deploy to Vercel, the command can be: + +```bash +yarn rw @zenstackhq generate && yarn rw deploy vercel +``` + +## Sample application + +You can find a complete multi-tenant Todo application built with RedwoodJS and ZenStack at: [https://github.com/zenstackhq/sample-todo-redwood](https://github.com/zenstackhq/sample-todo-redwood). + +## Getting help + +The best way to getting help and updates about ZenStack is by joining our [Discord server](https://discord.gg/Ykhr738dUe).