diff --git a/.github/workflows/dispatch.yml b/.github/workflows/dispatch.yml index 52280d5..39e7696 100644 --- a/.github/workflows/dispatch.yml +++ b/.github/workflows/dispatch.yml @@ -34,7 +34,7 @@ jobs: - name: Get changed files id: changed-files - uses: tj-actions/changed-files@v44 + uses: tj-actions/changed-files@v47 - name: Generate Matrix from changed Workspaces id: generate-matrix diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 365605b..f1af624 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -80,7 +80,7 @@ jobs: publish-npm: name: Publish npm package (requires approval) - if: needs.prepare.outputs.PROJECT == 'phantom-api' + if: needs.prepare.outputs.PROJECT == 'phantom-api-client' runs-on: ubuntu-latest needs: [prepare, build] environment: release # configure environment protection to require manual approval @@ -91,10 +91,12 @@ jobs: with: node-version: '20' registry-url: 'https://registry.npmjs.org' + - name: Enable Corepack and Yarn 4 + run: corepack enable && corepack prepare yarn@4.9.2 --activate - name: Install dependencies run: yarn install --immutable - name: Build package - run: yarn workspace phantom-api build + run: yarn workspace ${{ needs.prepare.outputs.PROJECT }} build - name: Publish to npm env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.pnp.cjs b/.pnp.cjs index abafa14..1b19346 100755 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -19,7 +19,7 @@ const RAW_RUNTIME_STATE = "reference": "workspace:admin-interface"\ },\ {\ - "name": "phantom-api",\ + "name": "phantom-api-client",\ "reference": "workspace:phantom-api"\ },\ {\ @@ -36,8 +36,8 @@ const RAW_RUNTIME_STATE = "pnpZipBackend": "libzip",\ "fallbackExclusionList": [\ ["admin-interface", ["workspace:admin-interface"]],\ - ["phantom-api", ["workspace:phantom-api"]],\ ["phantom-api-backend", ["workspace:phantom-api-backend"]],\ + ["phantom-api-client", ["workspace:phantom-api"]],\ ["phantom-api-monorepo", ["workspace:."]],\ ["public-doc", ["workspace:public-doc"]]\ ],\ @@ -54,13 +54,13 @@ const RAW_RUNTIME_STATE = ["bcrypt", "npm:6.0.0"],\ ["chalk", "npm:4.1.2"],\ ["dotenv", "npm:17.0.1"],\ - ["knip", "virtual:86b7be8dd38592cba87ca3cf1abb5c0da2fddca4c831b45c5226d5764450c4ed3356411563665401336a08f50800bdcaac8524aac051e69b6ab65518e750122f#npm:5.61.3"],\ + ["knip", "virtual:896f9be96c54671e2a764d12dd66a3c4ecec90363a4b99a53cdfb2433e3475682e845d14c63ddcdbf06d1acefddd1660a84614f14966ab898a8eeadc4720efae#npm:5.61.3"],\ ["oxlint", "npm:1.5.0"],\ - ["phantom-api", "workspace:phantom-api"],\ + ["phantom-api-client", "workspace:phantom-api"],\ ["phantom-api-monorepo", "workspace:."],\ ["syncpack", "npm:13.0.4"],\ - ["typedoc", "virtual:86b7be8dd38592cba87ca3cf1abb5c0da2fddca4c831b45c5226d5764450c4ed3356411563665401336a08f50800bdcaac8524aac051e69b6ab65518e750122f#npm:0.28.7"],\ - ["typedoc-plugin-markdown", "virtual:86b7be8dd38592cba87ca3cf1abb5c0da2fddca4c831b45c5226d5764450c4ed3356411563665401336a08f50800bdcaac8524aac051e69b6ab65518e750122f#npm:4.7.0"],\ + ["typedoc", "virtual:896f9be96c54671e2a764d12dd66a3c4ecec90363a4b99a53cdfb2433e3475682e845d14c63ddcdbf06d1acefddd1660a84614f14966ab898a8eeadc4720efae#npm:0.28.7"],\ + ["typedoc-plugin-markdown", "virtual:896f9be96c54671e2a764d12dd66a3c4ecec90363a4b99a53cdfb2433e3475682e845d14c63ddcdbf06d1acefddd1660a84614f14966ab898a8eeadc4720efae#npm:4.7.0"],\ ["typescript", "patch:typescript@npm%3A5.8.3#optional!builtin::version=5.8.3&hash=5786d5"]\ ],\ "linkType": "SOFT"\ @@ -3473,7 +3473,7 @@ const RAW_RUNTIME_STATE = ["date-fns", "npm:4.1.0"],\ ["globals", "npm:16.3.0"],\ ["jsdom", "virtual:4253337b4cd30e157fb9d4ddb93d42b7428af1121c63f21457fca930fbd00d9ed15d11be45331f32e1dd585b11e6fb86d2599a3fe4a31802e79ec051db662869#npm:26.1.0"],\ - ["knip", "virtual:86b7be8dd38592cba87ca3cf1abb5c0da2fddca4c831b45c5226d5764450c4ed3356411563665401336a08f50800bdcaac8524aac051e69b6ab65518e750122f#npm:5.61.3"],\ + ["knip", "virtual:896f9be96c54671e2a764d12dd66a3c4ecec90363a4b99a53cdfb2433e3475682e845d14c63ddcdbf06d1acefddd1660a84614f14966ab898a8eeadc4720efae#npm:5.61.3"],\ ["lucide-react", "virtual:4253337b4cd30e157fb9d4ddb93d42b7428af1121c63f21457fca930fbd00d9ed15d11be45331f32e1dd585b11e6fb86d2599a3fe4a31802e79ec051db662869#npm:0.525.0"],\ ["oxlint", "npm:1.5.0"],\ ["pino", "npm:9.7.0"],\ @@ -6220,7 +6220,7 @@ const RAW_RUNTIME_STATE = ["strip-json-comments", "npm:5.0.2"],\ ["typescript", null],\ ["zod", "npm:3.25.74"],\ - ["zod-validation-error", "virtual:52c4e47a1af756c3581c016437724dd5a5e123197e605dce921a7b4af2b3533a11fae8e21384c44d753eea716bc74d9d7e456af9c6f0c8febe78a352dae48df9#npm:3.5.2"]\ + ["zod-validation-error", "virtual:aa6259b8503d49478c75bdf954304de1eeb552f83b6568d48b0d23d4e117945e0883c37f5f299a20a524c3b7f9d93bf26042037f77783fb50df340aedfd39bf6#npm:3.5.2"]\ ],\ "packagePeers": [\ "@types/node",\ @@ -6229,8 +6229,8 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "HARD"\ }],\ - ["virtual:86b7be8dd38592cba87ca3cf1abb5c0da2fddca4c831b45c5226d5764450c4ed3356411563665401336a08f50800bdcaac8524aac051e69b6ab65518e750122f#npm:5.61.3", {\ - "packageLocation": "./.yarn/__virtual__/knip-virtual-52c4e47a1a/0/cache/knip-npm-5.61.3-faa1de9466-2f8abef328.zip/node_modules/knip/",\ + ["virtual:896f9be96c54671e2a764d12dd66a3c4ecec90363a4b99a53cdfb2433e3475682e845d14c63ddcdbf06d1acefddd1660a84614f14966ab898a8eeadc4720efae#npm:5.61.3", {\ + "packageLocation": "./.yarn/__virtual__/knip-virtual-aa6259b850/0/cache/knip-npm-5.61.3-faa1de9466-2f8abef328.zip/node_modules/knip/",\ "packageDependencies": [\ ["@nodelib/fs.walk", "npm:1.2.8"],\ ["@types/node", "npm:24.0.10"],\ @@ -6239,7 +6239,7 @@ const RAW_RUNTIME_STATE = ["formatly", "npm:0.2.4"],\ ["jiti", "npm:2.4.2"],\ ["js-yaml", "npm:4.1.0"],\ - ["knip", "virtual:86b7be8dd38592cba87ca3cf1abb5c0da2fddca4c831b45c5226d5764450c4ed3356411563665401336a08f50800bdcaac8524aac051e69b6ab65518e750122f#npm:5.61.3"],\ + ["knip", "virtual:896f9be96c54671e2a764d12dd66a3c4ecec90363a4b99a53cdfb2433e3475682e845d14c63ddcdbf06d1acefddd1660a84614f14966ab898a8eeadc4720efae#npm:5.61.3"],\ ["minimist", "npm:1.2.8"],\ ["oxc-resolver", "npm:11.5.0"],\ ["picocolors", "npm:1.1.1"],\ @@ -6248,7 +6248,7 @@ const RAW_RUNTIME_STATE = ["strip-json-comments", "npm:5.0.2"],\ ["typescript", "patch:typescript@npm%3A5.8.3#optional!builtin::version=5.8.3&hash=5786d5"],\ ["zod", "npm:3.25.74"],\ - ["zod-validation-error", "virtual:52c4e47a1af756c3581c016437724dd5a5e123197e605dce921a7b4af2b3533a11fae8e21384c44d753eea716bc74d9d7e456af9c6f0c8febe78a352dae48df9#npm:3.5.2"]\ + ["zod-validation-error", "virtual:aa6259b8503d49478c75bdf954304de1eeb552f83b6568d48b0d23d4e117945e0883c37f5f299a20a524c3b7f9d93bf26042037f77783fb50df340aedfd39bf6#npm:3.5.2"]\ ],\ "packagePeers": [\ "@types/node",\ @@ -7391,24 +7391,6 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["phantom-api", [\ - ["workspace:phantom-api", {\ - "packageLocation": "./phantom-api/",\ - "packageDependencies": [\ - ["@types/node", "npm:24.0.10"],\ - ["axios", "npm:1.10.0"],\ - ["chalk", "npm:4.1.2"],\ - ["commander", "npm:12.1.0"],\ - ["knip", "virtual:86b7be8dd38592cba87ca3cf1abb5c0da2fddca4c831b45c5226d5764450c4ed3356411563665401336a08f50800bdcaac8524aac051e69b6ab65518e750122f#npm:5.61.3"],\ - ["oxlint", "npm:1.5.0"],\ - ["phantom-api", "workspace:phantom-api"],\ - ["typedoc", "virtual:86b7be8dd38592cba87ca3cf1abb5c0da2fddca4c831b45c5226d5764450c4ed3356411563665401336a08f50800bdcaac8524aac051e69b6ab65518e750122f#npm:0.28.7"],\ - ["typedoc-plugin-markdown", "virtual:86b7be8dd38592cba87ca3cf1abb5c0da2fddca4c831b45c5226d5764450c4ed3356411563665401336a08f50800bdcaac8524aac051e69b6ab65518e750122f#npm:4.7.0"],\ - ["typescript", "patch:typescript@npm%3A5.8.3#optional!builtin::version=5.8.3&hash=5786d5"]\ - ],\ - "linkType": "SOFT"\ - }]\ - ]],\ ["phantom-api-backend", [\ ["workspace:phantom-api-backend", {\ "packageLocation": "./phantom-api-backend/",\ @@ -7441,7 +7423,7 @@ const RAW_RUNTIME_STATE = ["express-validator", "npm:7.2.1"],\ ["helmet", "npm:8.1.0"],\ ["jsonwebtoken", "npm:9.0.2"],\ - ["knip", "virtual:86b7be8dd38592cba87ca3cf1abb5c0da2fddca4c831b45c5226d5764450c4ed3356411563665401336a08f50800bdcaac8524aac051e69b6ab65518e750122f#npm:5.61.3"],\ + ["knip", "virtual:896f9be96c54671e2a764d12dd66a3c4ecec90363a4b99a53cdfb2433e3475682e845d14c63ddcdbf06d1acefddd1660a84614f14966ab898a8eeadc4720efae#npm:5.61.3"],\ ["oxlint", "npm:1.5.0"],\ ["pg", "virtual:09e1a04afd45af093cd8c29b97ddf4d19df61499634c38d0af82bb90c3d7132ade4b7fe95e3fb270962602a48f0e33defa03b58e28d078240eaec795cfcd7520#npm:8.16.3"],\ ["phantom-api-backend", "workspace:phantom-api-backend"],\ @@ -7450,8 +7432,8 @@ const RAW_RUNTIME_STATE = ["redis", "npm:4.7.1"],\ ["supertest", "npm:7.1.1"],\ ["tsx", "npm:4.20.3"],\ - ["typedoc", "virtual:86b7be8dd38592cba87ca3cf1abb5c0da2fddca4c831b45c5226d5764450c4ed3356411563665401336a08f50800bdcaac8524aac051e69b6ab65518e750122f#npm:0.28.7"],\ - ["typedoc-plugin-markdown", "virtual:86b7be8dd38592cba87ca3cf1abb5c0da2fddca4c831b45c5226d5764450c4ed3356411563665401336a08f50800bdcaac8524aac051e69b6ab65518e750122f#npm:4.7.0"],\ + ["typedoc", "virtual:896f9be96c54671e2a764d12dd66a3c4ecec90363a4b99a53cdfb2433e3475682e845d14c63ddcdbf06d1acefddd1660a84614f14966ab898a8eeadc4720efae#npm:0.28.7"],\ + ["typedoc-plugin-markdown", "virtual:896f9be96c54671e2a764d12dd66a3c4ecec90363a4b99a53cdfb2433e3475682e845d14c63ddcdbf06d1acefddd1660a84614f14966ab898a8eeadc4720efae#npm:4.7.0"],\ ["typescript", "patch:typescript@npm%3A5.8.3#optional!builtin::version=5.8.3&hash=5786d5"],\ ["vitest", "virtual:09e1a04afd45af093cd8c29b97ddf4d19df61499634c38d0af82bb90c3d7132ade4b7fe95e3fb270962602a48f0e33defa03b58e28d078240eaec795cfcd7520#npm:3.2.4"],\ ["zod", "npm:3.25.74"]\ @@ -7459,6 +7441,24 @@ const RAW_RUNTIME_STATE = "linkType": "SOFT"\ }]\ ]],\ + ["phantom-api-client", [\ + ["workspace:phantom-api", {\ + "packageLocation": "./phantom-api/",\ + "packageDependencies": [\ + ["@types/node", "npm:24.0.10"],\ + ["axios", "npm:1.10.0"],\ + ["chalk", "npm:4.1.2"],\ + ["commander", "npm:12.1.0"],\ + ["knip", "virtual:896f9be96c54671e2a764d12dd66a3c4ecec90363a4b99a53cdfb2433e3475682e845d14c63ddcdbf06d1acefddd1660a84614f14966ab898a8eeadc4720efae#npm:5.61.3"],\ + ["oxlint", "npm:1.5.0"],\ + ["phantom-api-client", "workspace:phantom-api"],\ + ["typedoc", "virtual:896f9be96c54671e2a764d12dd66a3c4ecec90363a4b99a53cdfb2433e3475682e845d14c63ddcdbf06d1acefddd1660a84614f14966ab898a8eeadc4720efae#npm:0.28.7"],\ + ["typedoc-plugin-markdown", "virtual:896f9be96c54671e2a764d12dd66a3c4ecec90363a4b99a53cdfb2433e3475682e845d14c63ddcdbf06d1acefddd1660a84614f14966ab898a8eeadc4720efae#npm:4.7.0"],\ + ["typescript", "patch:typescript@npm%3A5.8.3#optional!builtin::version=5.8.3&hash=5786d5"]\ + ],\ + "linkType": "SOFT"\ + }]\ + ]],\ ["phantom-api-monorepo", [\ ["workspace:.", {\ "packageLocation": "./",\ @@ -7469,13 +7469,13 @@ const RAW_RUNTIME_STATE = ["bcrypt", "npm:6.0.0"],\ ["chalk", "npm:4.1.2"],\ ["dotenv", "npm:17.0.1"],\ - ["knip", "virtual:86b7be8dd38592cba87ca3cf1abb5c0da2fddca4c831b45c5226d5764450c4ed3356411563665401336a08f50800bdcaac8524aac051e69b6ab65518e750122f#npm:5.61.3"],\ + ["knip", "virtual:896f9be96c54671e2a764d12dd66a3c4ecec90363a4b99a53cdfb2433e3475682e845d14c63ddcdbf06d1acefddd1660a84614f14966ab898a8eeadc4720efae#npm:5.61.3"],\ ["oxlint", "npm:1.5.0"],\ - ["phantom-api", "workspace:phantom-api"],\ + ["phantom-api-client", "workspace:phantom-api"],\ ["phantom-api-monorepo", "workspace:."],\ ["syncpack", "npm:13.0.4"],\ - ["typedoc", "virtual:86b7be8dd38592cba87ca3cf1abb5c0da2fddca4c831b45c5226d5764450c4ed3356411563665401336a08f50800bdcaac8524aac051e69b6ab65518e750122f#npm:0.28.7"],\ - ["typedoc-plugin-markdown", "virtual:86b7be8dd38592cba87ca3cf1abb5c0da2fddca4c831b45c5226d5764450c4ed3356411563665401336a08f50800bdcaac8524aac051e69b6ab65518e750122f#npm:4.7.0"],\ + ["typedoc", "virtual:896f9be96c54671e2a764d12dd66a3c4ecec90363a4b99a53cdfb2433e3475682e845d14c63ddcdbf06d1acefddd1660a84614f14966ab898a8eeadc4720efae#npm:0.28.7"],\ + ["typedoc-plugin-markdown", "virtual:896f9be96c54671e2a764d12dd66a3c4ecec90363a4b99a53cdfb2433e3475682e845d14c63ddcdbf06d1acefddd1660a84614f14966ab898a8eeadc4720efae#npm:4.7.0"],\ ["typescript", "patch:typescript@npm%3A5.8.3#optional!builtin::version=5.8.3&hash=5786d5"]\ ],\ "linkType": "SOFT"\ @@ -9367,15 +9367,15 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "SOFT"\ }],\ - ["virtual:86b7be8dd38592cba87ca3cf1abb5c0da2fddca4c831b45c5226d5764450c4ed3356411563665401336a08f50800bdcaac8524aac051e69b6ab65518e750122f#npm:0.28.7", {\ - "packageLocation": "./.yarn/__virtual__/typedoc-virtual-9af8bed98b/0/cache/typedoc-npm-0.28.7-01bffbbb89-30c942fa28.zip/node_modules/typedoc/",\ + ["virtual:896f9be96c54671e2a764d12dd66a3c4ecec90363a4b99a53cdfb2433e3475682e845d14c63ddcdbf06d1acefddd1660a84614f14966ab898a8eeadc4720efae#npm:0.28.7", {\ + "packageLocation": "./.yarn/__virtual__/typedoc-virtual-5b61b0313a/0/cache/typedoc-npm-0.28.7-01bffbbb89-30c942fa28.zip/node_modules/typedoc/",\ "packageDependencies": [\ ["@gerrit0/mini-shiki", "npm:3.7.0"],\ ["@types/typescript", null],\ ["lunr", "npm:2.3.9"],\ ["markdown-it", "npm:14.1.0"],\ ["minimatch", "npm:9.0.5"],\ - ["typedoc", "virtual:86b7be8dd38592cba87ca3cf1abb5c0da2fddca4c831b45c5226d5764450c4ed3356411563665401336a08f50800bdcaac8524aac051e69b6ab65518e750122f#npm:0.28.7"],\ + ["typedoc", "virtual:896f9be96c54671e2a764d12dd66a3c4ecec90363a4b99a53cdfb2433e3475682e845d14c63ddcdbf06d1acefddd1660a84614f14966ab898a8eeadc4720efae#npm:0.28.7"],\ ["typescript", "patch:typescript@npm%3A5.8.3#optional!builtin::version=5.8.3&hash=5786d5"],\ ["yaml", "npm:2.8.0"]\ ],\ @@ -9394,12 +9394,12 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "SOFT"\ }],\ - ["virtual:86b7be8dd38592cba87ca3cf1abb5c0da2fddca4c831b45c5226d5764450c4ed3356411563665401336a08f50800bdcaac8524aac051e69b6ab65518e750122f#npm:4.7.0", {\ - "packageLocation": "./.yarn/__virtual__/typedoc-plugin-markdown-virtual-67888ea667/0/cache/typedoc-plugin-markdown-npm-4.7.0-cab25d8c3f-066cb8a0f9.zip/node_modules/typedoc-plugin-markdown/",\ + ["virtual:896f9be96c54671e2a764d12dd66a3c4ecec90363a4b99a53cdfb2433e3475682e845d14c63ddcdbf06d1acefddd1660a84614f14966ab898a8eeadc4720efae#npm:4.7.0", {\ + "packageLocation": "./.yarn/__virtual__/typedoc-plugin-markdown-virtual-fe35c66dc1/0/cache/typedoc-plugin-markdown-npm-4.7.0-cab25d8c3f-066cb8a0f9.zip/node_modules/typedoc-plugin-markdown/",\ "packageDependencies": [\ ["@types/typedoc", null],\ - ["typedoc", "virtual:86b7be8dd38592cba87ca3cf1abb5c0da2fddca4c831b45c5226d5764450c4ed3356411563665401336a08f50800bdcaac8524aac051e69b6ab65518e750122f#npm:0.28.7"],\ - ["typedoc-plugin-markdown", "virtual:86b7be8dd38592cba87ca3cf1abb5c0da2fddca4c831b45c5226d5764450c4ed3356411563665401336a08f50800bdcaac8524aac051e69b6ab65518e750122f#npm:4.7.0"]\ + ["typedoc", "virtual:896f9be96c54671e2a764d12dd66a3c4ecec90363a4b99a53cdfb2433e3475682e845d14c63ddcdbf06d1acefddd1660a84614f14966ab898a8eeadc4720efae#npm:0.28.7"],\ + ["typedoc-plugin-markdown", "virtual:896f9be96c54671e2a764d12dd66a3c4ecec90363a4b99a53cdfb2433e3475682e845d14c63ddcdbf06d1acefddd1660a84614f14966ab898a8eeadc4720efae#npm:4.7.0"]\ ],\ "packagePeers": [\ "@types/typedoc",\ @@ -10088,12 +10088,12 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "SOFT"\ }],\ - ["virtual:52c4e47a1af756c3581c016437724dd5a5e123197e605dce921a7b4af2b3533a11fae8e21384c44d753eea716bc74d9d7e456af9c6f0c8febe78a352dae48df9#npm:3.5.2", {\ - "packageLocation": "./.yarn/__virtual__/zod-validation-error-virtual-f05ad98462/0/cache/zod-validation-error-npm-3.5.2-ff101b0599-da50926ec9.zip/node_modules/zod-validation-error/",\ + ["virtual:aa6259b8503d49478c75bdf954304de1eeb552f83b6568d48b0d23d4e117945e0883c37f5f299a20a524c3b7f9d93bf26042037f77783fb50df340aedfd39bf6#npm:3.5.2", {\ + "packageLocation": "./.yarn/__virtual__/zod-validation-error-virtual-202d84f88d/0/cache/zod-validation-error-npm-3.5.2-ff101b0599-da50926ec9.zip/node_modules/zod-validation-error/",\ "packageDependencies": [\ ["@types/zod", null],\ ["zod", "npm:3.25.74"],\ - ["zod-validation-error", "virtual:52c4e47a1af756c3581c016437724dd5a5e123197e605dce921a7b4af2b3533a11fae8e21384c44d753eea716bc74d9d7e456af9c6f0c8febe78a352dae48df9#npm:3.5.2"]\ + ["zod-validation-error", "virtual:aa6259b8503d49478c75bdf954304de1eeb552f83b6568d48b0d23d4e117945e0883c37f5f299a20a524c3b7f9d93bf26042037f77783fb50df340aedfd39bf6#npm:3.5.2"]\ ],\ "packagePeers": [\ "@types/zod",\ diff --git a/Dockerfile b/Dockerfile index 986b8c3..3e285ca 100644 --- a/Dockerfile +++ b/Dockerfile @@ -41,7 +41,9 @@ COPY phantom-api-backend/ ./phantom-api-backend/ COPY admin-interface/ ./admin-interface/ # Build des projets nécessaires à l'image -ENV NODE_OPTIONS="--experimental-loader=./.pnp.loader.mjs" +# Utilise un chemin absolu pour le loader PnP, car les scripts workspace +# s'exécutent depuis le dossier du package (sinon ./ pointe vers le workspace) +ENV NODE_OPTIONS="--experimental-loader=/app/.pnp.loader.mjs" RUN yarn workspace phantom-api-backend build \ && yarn workspace admin-interface build @@ -75,9 +77,13 @@ COPY --from=builder --chown=phantom:phantom /app/package.json ./package.json RUN mkdir -p /app/data /app/logs && \ chown -R phantom:phantom /app/data /app/logs -# Install production dependencies (en root pour éviter les problèmes de permissions) -WORKDIR /app/phantom-api-backend -RUN npm install --production --omit=dev +# Enable corepack for yarn support +RUN corepack enable + +# Install production dependencies using yarn (en root pour éviter les problèmes de permissions) +WORKDIR /app +ENV NODE_OPTIONS="--experimental-loader=/app/.pnp.loader.mjs" +RUN yarn workspaces focus phantom-api-backend --production # Change ownership après installation RUN chown -R phantom:phantom /app @@ -89,4 +95,5 @@ EXPOSE 3000 HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \ CMD curl -f http://localhost:3000/health || exit 1 +ENV NODE_OPTIONS="--experimental-loader=/app/.pnp.loader.mjs" CMD ["node", "dist/index.js"] diff --git a/README.md b/README.md index afe8d10..c770bc4 100644 --- a/README.md +++ b/README.md @@ -2,21 +2,27 @@ Phantom API Logo -

- CI Status - Latest Release - License - Node.js Version - Yarn - npm version - Docker image version -

+ + + + + + + + + + +
Latest Releasenpm versionDocker image version
DockerLicense
# Phantom API - Self-Generating Backend A dynamic backend system that automatically creates API endpoints, database tables, and validation schemas based on api call from frontend. +- [Website](https://phantom-api.dev) +- [github](https://github.com/Salnika/phantom-api.dev) +- [Complete Documentation](https://salnika.github.io/phantom-api.dev/) + ## Features - **Dynamic API**: Single route `/api/:resource/:action` handles all operations @@ -42,9 +48,6 @@ A dynamic backend system that automatically creates API endpoints, database tabl │ └── data/ # SQLite database files ├── admin-interface/ # admin (React admin panel) ├── phantom-api/ # client (NPM package for frontend integration) -├── demo/ # Vite React demo application -├── website/ # Marketing website -├── public-doc/ # MkDocs documentation ├── ecosystem.config.js # PM2 process configuration ├── Dockerfile # Backend containerization └── docker-compose.yml # Multi-service orchestration diff --git a/package.json b/package.json index e19b278..1143ce2 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "dotenv": "^17.0.1", "knip": "^5.61.3", "oxlint": "^1.0.0", - "phantom-api": "workspace:*", + "phantom-api-client": "workspace:*", "syncpack": "^13.0.4", "typedoc": "^0.28.7", "typedoc-plugin-markdown": "^4.7.0", @@ -41,4 +41,4 @@ "admin-interface", "public-doc" ] -} \ No newline at end of file +} diff --git a/phantom-api/README.md b/phantom-api/README.md index eafb8ec..8aafb7e 100644 --- a/phantom-api/README.md +++ b/phantom-api/README.md @@ -1,237 +1,344 @@
- Phantom API Logo + Phantom API Logo # Phantom API Client - - **Dynamic backend system that builds type-safe, schema-based APIs with zero boilerplate** - + + **The official TypeScript/JavaScript client for Phantom API - Create powerful backends without the complexity.** + [![npm version](https://img.shields.io/npm/v/phantom-api-client.svg)](https://www.npmjs.com/package/phantom-api-client) [![npm downloads](https://img.shields.io/npm/dm/phantom-api-client.svg)](https://www.npmjs.com/package/phantom-api-client) [![GitHub stars](https://img.shields.io/github/stars/salnika/phantom-api.dev.svg)](https://github.com/salnika/phantom-api.dev) - [![License: CC BY-NC-SA 4.0](https://img.shields.io/badge/License-CC%20BY--NC--SA%204.0-blue.svg)](https://creativecommons.org/licenses/by-nc-sa/4.0/) - [![Documentation](https://img.shields.io/badge/docs-phantom--api.dev-blue)](https://phantom-api.dev) + [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
-## TL;DR +# Phantom API - Self-Generating Backend -**Phantom API is a dynamic backend system that builds type-safe, schema-based APIs with zero boilerplate.** +A dynamic backend system that automatically creates API endpoints, database tables, and validation schemas based on api call from frontend. -Skip writing database schemas, migrations, validation rules, and REST endpoints. Just call your API and watch it build itself in real-time. +- [Website](https://phantom-api.dev) +- [github](https://github.com/Salnika/phantom-api.dev) +- [Complete Documentation](https://salnika.github.io/phantom-api.dev/) -## Quick Example +## Features -```typescript -import { createClient } from 'phantom-api-client'; - -const client = createClient({ baseURL: 'https://api.example.com' }); -const tasks = client.resource('Task'); +- **Dynamic API**: Single route `/api/:resource/:action` handles all operations +- **Dynamic Table Creation**: Tables automatically created from API calls, no configuration needed +- **Advanced Relations**: Foreign keys, cascading deletes, self-referencing tables +- **Rich Field Types**: String, text, integer, boolean, datetime, enum, JSON, email +- **Zod Validation**: Automatic schema generation and validation +- **🆕 Advanced Policies Management**: Role-based, attribute-based, and custom access control policies +- **JWT Security**: Secure authentication with configurable roles and permissions +- **Admin Interface**: Modern React-based admin panel with policy management and logs viewer +- **Client Package**: TypeScript NPM package for frontend integration +- **Process Management**: PM2 ecosystem for production deployment +- **Structured Logging**: Pino logger with file rotation and admin interface +- **Docker Ready**: Containerized backend with persistent SQLite storage -// 🎯 This single call creates the database table, validation schema, and REST endpoints -await tasks.create({ name: 'Write README', done: false, priority: 'high' }); +## Project Structure -// ✅ Table "tasks" now exists with columns: id, name, done, priority, created_at -const list = await tasks.read({ where: { done: false } }); ``` +├── phantom-api-backend/ # backend (Express server with dynamic API) +│ ├── src/ # TypeScript source code +│ ├── meta/ # Optional schema files (auto-generated) +│ ├── logs/ # Application and error logs +│ └── data/ # SQLite database files +├── admin-interface/ # admin (React admin panel) +├── phantom-api/ # client (NPM package for frontend integration) +├── ecosystem.config.js # PM2 process configuration +├── Dockerfile # Backend containerization +└── docker-compose.yml # Multi-service orchestration +``` + +## Prerequisites -[→ See complete examples](https://phantom-api.dev/docs/examples) +Before getting started, ensure you have the following installed: -## Installation +### Required +- **Node.js** 18+ (recommended: 22+) +- **Yarn** 4.9.2 (package manager) +- **Git** (version control) +### Optional (for full development experience) +- **PM2** (process management): `yarn add -g pm2` +- **Python 3.8+** and **MkDocs** (documentation): `pip install mkdocs mkdocs-material` +- **Docker** and **Docker Compose** (containerization) + +### Installation Verification ```bash -npm install phantom-api-client -# or -yarn add phantom-api-client -# or -bun add phantom-api-client +# Check versions +node --version # Should be 18+ +yarn --version # Should be 4.9.2 +git --version # Any recent version + +# Optional tools +pm2 --version # For process management +mkdocs --version # For documentation server +docker --version # For containerized deployment ``` -## Documentation +## Quick Start -📚 **[Full documentation →](https://phantom-api.dev)** +### 1. Install Dependencies +```bash +yarn install +``` -## Why Phantom API? +### 2. Environment Setup +Copy the example environment file and configure it: +```bash +cp .env.example .env +``` -🧠 **Data-first**: Auto-generates tables, validations, and routes from your actual data -🔐 **Fine-grained permissions**: Built-in policy system with role-based and attribute-based access control -⚡️ **Fast to deploy**: No backend code required - works with any frontend framework -🧱 **Works everywhere**: Next.js, React Native, Vue, Svelte, vanilla JavaScript -🎯 **Type-safe**: Full TypeScript support with auto-generated types -🔄 **Real-time**: Built-in WebSocket support for live data updates +Edit `.env` with your configuration: +```env +# Server Configuration +PORT=3000 +NODE_ENV=development -## Feature Comparison +# JWT Secret Key (CHANGE THIS IN PRODUCTION!) +JWT_SECRET=your-super-secret-jwt-key-change-this-in-production -| Tool | Backend Code Needed | Permissions | Hosted | Custom Logic | -|------|-------------------|-------------|---------|--------------| -| **Phantom** | ❌ None | ✅ Built-in | ✅ | ✅ With Hooks | -| Supabase | ✅ SQL/Edge Functions | ⚠️ Limited | ✅ | ✅ | -| Strapi | ✅ JS/TS | ✅ Advanced | ❌ | ✅ | -| Hasura | ❌ GraphQL Config | ⚠️ Complex | ✅ | ⚠️ Indirect | -| Firebase | ✅ Cloud Functions | ⚠️ Basic Rules | ✅ | ⚠️ Limited | +# Database Configuration +DB_PATH=./data/phantom.db -## Core Features +# Admin Panel Configuration +ADMIN_EMAIL=admin@phantom-api.com +ADMIN_PASSWORD=admin123 +``` -### 🚀 Dynamic Resource Creation +### 3. Start All Services with PM2 +```bash +# Install PM2 globally (if not already installed) +yarn add -g pm2 -```typescript -// Creates table, schema, and endpoints automatically -const users = client.resource('User'); -const posts = client.resource('Post'); -const comments = client.resource('Comment'); - -// Relationships detected from field names -await posts.create({ - title: 'Hello World', - content: 'My first post!', - authorId: 'user_123' // 👈 Auto-creates foreign key to User table -}); -``` +# Start all services +yarn pm2:start -### 🔍 Advanced Querying +# Check status +pm2 status -```typescript -const posts = await client.resource('Post').read({ - where: { - published: true, - createdAt: { gte: '2024-01-01' }, - tags: { contains: 'javascript' } - }, - populate: ['author', 'comments'], - sort: ['-createdAt'], - limit: 20 -}); +# View logs +yarn pm2:logs ``` -### ⚡ Batch Operations +Services will run on: +- **Backend**: http://localhost:3000 - API endpoints and data management +- **Admin Interface**: http://localhost:5173 - Modern admin panel with logs viewer +- **# Demo Frontend**: http://localhost:5174 - Example application using the API +- **Website**: http://localhost:5175 - Marketing and documentation site +- **Documentation**: http://localhost:8000 - MkDocs technical documentation -```typescript -const results = await client.batch([ - { resource: 'User', action: 'create', data: { name: 'Alice' } }, - { resource: 'User', action: 'create', data: { name: 'Bob' } }, - { resource: 'Post', action: 'create', data: { title: 'Hello', authorId: 'user_123' } } -]); -``` +### 4. Alternative: Start Individual Services +```bash +# Backend only +cd phantom-api-backend && yarn dev -### 🎯 Type Safety +# Admin interface only +cd admin-interface && yarn dev -```typescript -interface User { - id: string; - email: string; - name: string; - createdAt: Date; -} +# Demo frontend only +cd demo && yarn dev -const user = await client.resource('User').create({ - email: 'john@example.com', - name: 'John Doe' -}); -// user is fully typed! ✅ +# Documentation server only +cd public-doc && mkdocs serve ``` -## Real-World Usage - -### E-commerce Store +### 5. Use Client Package ```typescript -// Product catalog with categories and inventory -await client.resource('Product').create({ - name: 'iPhone 15 Pro', - price: 999.99, - categoryId: 'electronics', - inStock: true, - variants: ['128GB', '256GB', '512GB'] -}); +import { setEndpoint, setToken, resource } from 'phantom-api'; + +// Configure +setEndpoint('http://localhost:3000'); +setToken('your-jwt-token'); // optional + +// Use resources +const users = resource('User'); +await users.create({ email: 'test@example.com', name: 'John' }); +const allUsers = await users.read(); + +// Update a user +await users.update({ id: allUsers[0].id, name: 'John Doe Updated' }); + +// Delete a user +await users.delete({ id: allUsers[0].id }); ``` -### Social Media App -```typescript -// User posts with likes and comments -await client.resource('Post').create({ - content: 'Building with Phantom API! 🚀', - authorId: 'user_123', - tags: ['#phantomapi', '#nocode'] -}); +## Docker Deployment -await client.resource('Like').create({ - postId: 'post_456', - userId: 'user_789' -}); +For containerized deployment with optimized production setup: + +```bash +# Copy environment template +cp .env.example .env + +# Generate secure JWT secret (32+ characters) +openssl rand -base64 32 +# Copy to JWT_SECRET in .env + +# Build and start +docker-compose up --build -d + +# Verify deployment +curl http://localhost:3000/health ``` -### Task Management +**Services accessible at:** +- Backend API: http://localhost:3000 +- Admin Interface: http://localhost:3000/admin +- Health Check: http://localhost:3000/health + +For detailed Docker configuration, see documentation at http://localhost:8000 (when MkDocs is running). + +## Dynamic Table Creation + +Phantom API creates database tables automatically from your API calls - no configuration files needed! + +### How It Works + +1. **Call Any Resource**: Simply use `resource('AnyTableName')` in your frontend +2. **Auto-Detection**: The system detects field types from the data you send +3. **Table Creation**: SQLite tables are created instantly with appropriate columns +4. **Schema Evolution**: New fields are automatically added when you send new data + +### Field Type Detection + ```typescript -// Project tasks with assignments -await client.resource('Task').create({ - title: 'Design new homepage', - description: 'Create wireframes and mockups', - assigneeId: 'user_456', - projectId: 'proj_123', - status: 'in_progress', - priority: 'high', - dueDate: '2024-02-15' +// These calls automatically create a User table +const User = resource('User'); +User.create({ + email: 'user@example.com', // → VARCHAR (email format detected) + name: 'John Doe', // → VARCHAR + age: 30, // → INTEGER + isActive: true, // → BOOLEAN + birthDate: '1990-01-01', // → DATE + createdAt: new Date(), // → DATETIME + metadata: { role: 'admin' } // → JSON }); ``` -## Authentication & Security +### Automatic Relations ```typescript -// JWT authentication -const client = createClient({ - baseURL: 'https://api.yourapp.com', - token: 'your-jwt-token' +// Foreign key relationships are auto-detected +const Article = resource('Article'); +Article.create({ + title: 'My Article', + content: 'Article content...', + authorId: 'user_123', // → Creates FK to User table + categoryId: 'cat_456' // → Creates FK to Category table }); ``` -## Migration & Deployment +### Supported Data Types -### CLI Tools -```bash -# Preview database changes -phantom-migration --preview +- **String**: Text fields, emails, URLs +- **Integer**: Numbers, IDs, counts +- **Boolean**: true/false values +- **Date**: ISO date strings +- **DateTime**: ISO datetime strings +- **JSON**: Objects and arrays +- **Relations**: Foreign keys (detected by 'Id' suffix) -# Apply migrations -phantom-migration --apply +## API Usage -# Seed development data -phantom-seed --file ./seeds/demo.json -``` +All operations use POST requests to `/api/:resource/:action`: -### Environment Management -```typescript -const devClient = createClient({ - baseURL: 'http://localhost:3000' -}); +### Create +```bash +curl -X POST http://localhost:3000/api/User/create \ + -H "Content-Type: application/json" \ + -d '{"email": "user@example.com", "name": "John Doe"}' +``` -const prodClient = createClient({ - baseURL: 'https://api.yourapp.com', - token: process.env.PHANTOM_API_TOKEN -}); +### Read +```bash +# Get all +curl -X POST http://localhost:3000/api/User/read \ + -H "Content-Type: application/json" \ + -d '{}' + +# Get by ID +curl -X POST http://localhost:3000/api/User/read \ + -H "Content-Type: application/json" \ + -d '{"id": "user_123"}' ``` -## Roadmap / Contributing +### Update +```bash +curl -X POST http://localhost:3000/api/User/update \ + -H "Content-Type: application/json" \ + -d '{"id": "user_123", "name": "Jane Doe"}' +``` -We're actively developing Phantom API! Here's what's coming: +### Delete +```bash +curl -X POST http://localhost:3000/api/User/delete \ + -H "Content-Type: application/json" \ + -d '{"id": "user_123"}' +``` -- 🔄 Real-time subscriptions -- 📊 Advanced analytics dashboard -- 🤖 AI-powered schema suggestions -- 📱 Mobile SDKs (React Native, Flutter) +## Authentication & Authorization + +### JWT Authentication +Generate JWT tokens in the admin interface with configurable roles: +- `anon`: Anonymous access (limited) +- `user`: Standard user permissions +- `admin`: Administrative access +- `moderator`: Content moderation permissions +- `viewer`: Read-only access +- `editor`: Content editing permissions + +### Advanced Policies System +Phantom API now includes a comprehensive policies management system: + +- **Role-Based Access Control (RBAC)**: Traditional role-based permissions +- **Attribute-Based Access Control (ABAC)**: Dynamic permissions based on user/resource attributes +- **Custom Policies**: Complex business logic with conditional rules +- **Policy Templates**: Pre-built policies for common scenarios +- **Real-time Testing**: Test policies before deployment +- **Analytics & Monitoring**: Track policy usage and access patterns + +**Example Policy:** +```json +{ + "name": "User Data Ownership", + "type": "ATTRIBUTE_BASED", + "rules": [ + { + "resource": "User", + "action": "update", + "effect": "ALLOW", + "conditions": [ + { + "field": "user.id", + "operator": "eq", + "value": "${resource.id}", + "context": "user" + } + ] + } + ] +} +``` -**Want to contribute?** Check out our [GitHub Issues](https://github.com/salnika/phantom-api.dev/issues) or join our community! +**Security Note**: Make sure to change the default JWT_SECRET in production! -## Community & Support +📖 **[Complete Policies Documentation](./POLICIES_DOCUMENTATION.md)** -- 📖 **Documentation**: [phantom-api.dev](https://phantom-api.dev) -- 💬 **Discord**: [Join our community](https://discord.gg/phantom-api) -- 🐛 **Issues**: [GitHub Issues](https://github.com/salnika/phantom-api.dev/issues) -- 🔄 **Updates**: Follow [@PhantomAPI](https://twitter.com/phantomapi) on Twitter +## How It Works -## License +1. **Frontend Call**: `resource('User').create({ email: 'test@mail.com', name: 'MARTIN' })` +2. **Auto-Detection**: System analyzes data types and structure +3. **Table Creation**: SQLite table created instantly if it doesn't exist +4. **Schema Evolution**: New columns added automatically for new fields +5. **Response**: Data saved and returned with generated ID -CC BY-NC-SA 4.0 – see the LICENSE file in the repository root. +The system learns from your data and automatically: +- Creates tables with appropriate column types +- Detects relationships from field names (e.g., 'authorId' → User table) +- Generates validation schemas on-the-fly +- Provides admin interface for data management ---- +**Zero configuration required** - just start coding and let Phantom API handle the database! -
- Built with ❤️ by the Phantom API team
- Stop writing boilerplate. Start building features. -
+Perfect for rapid prototyping and dynamic applications! diff --git a/phantom-api/package.json b/phantom-api/package.json index cb842e2..8f31fbf 100644 --- a/phantom-api/package.json +++ b/phantom-api/package.json @@ -1,5 +1,5 @@ { - "name": "phantom-api", + "name": "phantom-api-client", "version": "0.2.0-alpha", "bin": { "phantom-migration": "dist/migration-cli.js", diff --git a/yarn.lock b/yarn.lock index 6f3de0c..d6d5672 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6041,42 +6041,42 @@ __metadata: languageName: unknown linkType: soft -"phantom-api-monorepo@workspace:.": +"phantom-api-client@workspace:*, phantom-api-client@workspace:phantom-api": version: 0.0.0-use.local - resolution: "phantom-api-monorepo@workspace:." + resolution: "phantom-api-client@workspace:phantom-api" dependencies: - "@changesets/cli": "npm:^2.29.5" - "@types/bcrypt": "npm:^5.0.2" "@types/node": "npm:^24.0.9" - bcrypt: "npm:^6.0.0" + axios: "npm:^1.10.0" chalk: "npm:^4.1.2" - dotenv: "npm:^17.0.1" + commander: "npm:^12.0.0" knip: "npm:^5.61.3" oxlint: "npm:^1.0.0" - phantom-api: "workspace:*" - syncpack: "npm:^13.0.4" typedoc: "npm:^0.28.7" typedoc-plugin-markdown: "npm:^4.7.0" typescript: "npm:^5.8.3" + bin: + phantom-migration: dist/migration-cli.js + phantom-seed: dist/seed-cli.js languageName: unknown linkType: soft -"phantom-api@workspace:*, phantom-api@workspace:phantom-api": +"phantom-api-monorepo@workspace:.": version: 0.0.0-use.local - resolution: "phantom-api@workspace:phantom-api" + resolution: "phantom-api-monorepo@workspace:." dependencies: + "@changesets/cli": "npm:^2.29.5" + "@types/bcrypt": "npm:^5.0.2" "@types/node": "npm:^24.0.9" - axios: "npm:^1.10.0" + bcrypt: "npm:^6.0.0" chalk: "npm:^4.1.2" - commander: "npm:^12.0.0" + dotenv: "npm:^17.0.1" knip: "npm:^5.61.3" oxlint: "npm:^1.0.0" + phantom-api-client: "workspace:*" + syncpack: "npm:^13.0.4" typedoc: "npm:^0.28.7" typedoc-plugin-markdown: "npm:^4.7.0" typescript: "npm:^5.8.3" - bin: - phantom-migration: dist/migration-cli.js - phantom-seed: dist/seed-cli.js languageName: unknown linkType: soft