diff --git a/.npmrc b/.npmrc deleted file mode 100644 index e9d14ac4a..000000000 --- a/.npmrc +++ /dev/null @@ -1,2 +0,0 @@ -registry=https://registry.npmjs.org/ -@lifeforge:registry=https://registry.lifeforge.dev/ diff --git a/bun.lock b/bun.lock index 71eca5489..0c24a0159 100644 --- a/bun.lock +++ b/bun.lock @@ -26,6 +26,7 @@ }, "devDependencies": { "@eslint/js": "^9.26.0", + "@lifeforge/configs": "workspace:*", "@originjs/vite-plugin-federation": "^1.4.1", "@trivago/prettier-plugin-sort-imports": "^5.2.2", "@types/lodash": "^4.17.21", @@ -60,6 +61,30 @@ "name": "@lifeforge/lifeforge--achievements", "version": "0.0.11", "peerDependencies": { + "@lifeforge/configs": "workspace:*", + "@lifeforge/federation": "workspace:*", + "@lifeforge/server-utils": "workspace:*", + "@lifeforge/shared": "workspace:*", + "@lifeforge/ui": "workspace:*", + }, + }, + "apps/lifeforge--utility-widgets": { + "name": "@lifeforge/lifeforge--utility-widgets", + "version": "0.0.1", + "dependencies": { + "@iconify/react": "^6.0.2", + "@lifeforge/shared": "workspace:*", + "@lifeforge/ui": "workspace:*", + "vite": "^7.1.9", + }, + "devDependencies": { + "@types/react": "^19.2.0", + "@types/react-dom": "^19.2.0", + "vite": "^7.1.9", + }, + "peerDependencies": { + "@lifeforge/configs": "workspace:*", + "@lifeforge/federation": "workspace:*", "@lifeforge/server-utils": "workspace:*", "@lifeforge/shared": "workspace:*", "@lifeforge/ui": "workspace:*", @@ -83,34 +108,8 @@ "@types/react-virtualized": "^9.22.3", }, "peerDependencies": { - "@lifeforge/server-utils": "workspace:*", - "@lifeforge/shared": "workspace:*", - "@lifeforge/ui": "workspace:*", - }, - }, - "apps/lifeforge-module-localIpWidget": { - "name": "@lifeforge/lifeforge--local-ip-widget", - "version": "0.0.1", - "dependencies": { - "@iconify/react": "^6.0.2", - "@lifeforge/shared": "workspace:*", - "@lifeforge/ui": "workspace:*", - "@tanstack/react-query": "^5.90.11", - "@uidotdev/usehooks": "^2.4.1", - "clsx": "^2.1.1", - "dayjs": "^1.11.18", - "react": "^19.2.0", - "react-i18next": "^15.1.1", - "react-toastify": "^11.0.5", - "vite": "^7.1.9", - "zod": "^4.1.12", - }, - "devDependencies": { - "@types/react": "^19.2.0", - "@types/react-dom": "^19.2.0", - "vite": "^7.1.9", - }, - "peerDependencies": { + "@lifeforge/configs": "workspace:*", + "@lifeforge/federation": "workspace:*", "@lifeforge/server-utils": "workspace:*", "@lifeforge/shared": "workspace:*", "@lifeforge/ui": "workspace:*", @@ -129,6 +128,8 @@ "@types/jsdom": "^27.0.0", }, "peerDependencies": { + "@lifeforge/configs": "workspace:*", + "@lifeforge/federation": "workspace:*", "@lifeforge/server-utils": "workspace:*", "@lifeforge/shared": "workspace:*", "@lifeforge/ui": "workspace:*", @@ -142,44 +143,32 @@ "@dnd-kit/sortable": "^10.0.0", "@dnd-kit/utilities": "^3.2.2", "@iconify/react": "^6.0.2", + "@lifeforge/federation": "workspace:*", "@lifeforge/shared": "workspace:*", "@lifeforge/ui": "workspace:*", - "@tanstack/react-query": "^5.90.11", "@types/node": "^24.7.2", "@types/react-virtualized": "^9.22.3", - "@uidotdev/usehooks": "^2.4.1", "babel-plugin-react-compiler": "^19.1.0-rc.2", - "clsx": "^2.1.1", "copy-to-clipboard": "^3.3.3", "crypto-js": "^4.2.0", "daisyui": "^5.0.35", - "dayjs": "^1.11.13", "dnd-core": "^16.0.1", "eslint-plugin-react-compiler": "^19.1.0-rc.2", - "i18next": "^25.6.0", "i18next-http-backend": "^2.7.3", - "lodash": "^4.17.21", "lodash-es": "^4.17.22", - "opentype.js": "^1.3.4", "postcss": "^8.5.3", "pretty-bytes": "^7.1.0", "qrcode.react": "^4.2.0", - "react": "^19.2.0", "react-custom-scrollbars": "^4.2.1", - "react-dom": "^19.2.0", "react-dropzone": "^14.3.8", "react-error-boundary": "^6.0.0", "react-grid-layout": "^1.5.2", - "react-i18next": "^15.5.1", "react-router": "^7.9.4", - "react-toastify": "^11.0.5", "react-virtualized": "^9.22.6", "recharts": "^2.15.0", "socket.io-client": "^4.8.1", - "tinycolor2": "^1.6.0", "typescript": "^5.9.3", "uuid": "^13.0.0", - "zod": "4.3.5", }, "devDependencies": { "@originjs/vite-plugin-federation": "^1.4.1", @@ -191,6 +180,7 @@ "@types/tinycolor2": "^1.4.6", "@vitejs/plugin-react": "^4.4.1", "glob": "^13.0.0", + "rollup-plugin-visualizer": "^7.0.1", "vite": "^7.0.5", }, }, @@ -242,7 +232,34 @@ "name": "@lifeforge/lifeforge--lang-en", "version": "0.0.1", }, - "packages/lifeforge-log": { + "packages/configs": { + "name": "@lifeforge/configs", + "version": "0.0.1", + "devDependencies": { + "typescript": "^5.9.3", + }, + "peerDependencies": { + "@originjs/vite-plugin-federation": "^1.4.1", + "@vitejs/plugin-react": "^4.4.1", + "vite": "^7.1.9", + }, + }, + "packages/federation": { + "name": "@lifeforge/federation", + "version": "0.0.1", + "dependencies": { + "@lifeforge/shared": "workspace:*", + "zod": "4.3.5", + }, + "devDependencies": { + "@types/react": "^19.2.0", + "typescript": "^5.9.3", + }, + "peerDependencies": { + "react": "^19.2.0", + }, + }, + "packages/log": { "name": "@lifeforge/log", "version": "0.1.0", "dependencies": { @@ -257,7 +274,7 @@ "vitest": "^4.0.0", }, }, - "packages/lifeforge-server-utils": { + "packages/server-utils": { "name": "@lifeforge/server-utils", "version": "0.0.1", "dependencies": { @@ -306,45 +323,32 @@ "@radix-ui/react-checkbox": "^1.3.3", "@radix-ui/react-dropdown-menu": "^2.1.16", "@radix-ui/react-select": "^2.2.6", - "@tanstack/react-query": "^5.90.11", - "@uidotdev/usehooks": "^2.4.1", "@uiw/react-color": "^2.9.0", - "@vanilla-extract/css": "^1.20.1", "@vanilla-extract/recipes": "^0.5.7", "@vanilla-extract/sprinkles": "^1.6.5", "@vitejs/plugin-react": "^4.7.0", "@yudiel/react-qr-scanner": "^2.3.1", - "clsx": "^2.1.1", "color-sorter": "^6.2.0", "crypto-js": "^4.2.0", "culori": "^4.0.2", - "dayjs": "^1.11.18", "dom-css": "^2.1.0", "file-type-mime": "^0.4.7", - "i18next": "^25.6.0", "i18next-http-backend": "^2.7.3", "javascript-color-gradient": "^2.5.0", - "lodash": "^4.17.21", "prop-types": "^15.8.1", "raf": "^3.4.1", - "react": "^19.2.0", "react-currency-input-field": "^3.10.0", "react-datepicker": "^8.7.0", - "react-dom": "^19.2.0", "react-dropzone": "^14.3.8", - "react-i18next": "^15.7.4", "react-medium-image-zoom": "^5.4.0", "react-number-format": "^5.4.5", "react-otp-input": "^3.1.1", "react-photo-album": "^2.4.1", "react-router": "^7.9.4", - "react-toastify": "^11.0.5", "react-tooltip": "^5.30.0", "react-virtualized": "^9.22.6", "rrule": "^2.8.1", - "tinycolor2": "^1.6.0", "uuid": "^11.1.0", - "zod": "4.3.5", "zustand": "^5.0.8", }, "devDependencies": { @@ -391,13 +395,10 @@ "cors": "^2.8.5", "crypto": "^1.0.1", "crypto-js": "^4.2.0", - "dayjs": "^1.11.19", - "dotenv": "^16.5.0", "express": "^4.21.2", "express-rate-limit": "^7.4.1", "groq-sdk": "^0.5.0", "helmet": "^7.2.0", - "lodash": "^4.17.21", "morgan": "^1.10.0", "multer": "^1.4.5-lts.1", "node-cache": "^5.1.2", @@ -409,7 +410,6 @@ "speakeasy": "^2.0.0", "tesseract.js": "^6.0.1", "uuid": "^9.0.1", - "zod": "4.3.5", }, "devDependencies": { "@eslint/js": "^9.31.0", @@ -437,22 +437,14 @@ "name": "@lifeforge/shared", "version": "0.0.1", "dependencies": { - "@tanstack/react-query": "^5.90.11", "axios": "^1.12.2", - "clsx": "^2.1.1", "crypto-js": "^4.2.0", "culori": "^4.0.2", "javascript-color-gradient": "^2.5.0", "json-schema-to-ts": "^3.1.1", - "lodash": "^4.17.21", "nuqs": "^2.7.1", - "react": "^19.2.0", - "react-i18next": "^15.1.1", "react-router": "^7.9.4", - "react-toastify": "^11.0.5", "socket.io-client": "^4.8.1", - "tinycolor2": "^1.6.0", - "zod": "4.3.5", }, "devDependencies": { "@types/crypto-js": "^4.2.2", @@ -764,21 +756,25 @@ "@lifeforge/client": ["@lifeforge/client@workspace:client"], + "@lifeforge/configs": ["@lifeforge/configs@workspace:packages/configs"], + + "@lifeforge/federation": ["@lifeforge/federation@workspace:packages/federation"], + "@lifeforge/lifeforge--achievements": ["@lifeforge/lifeforge--achievements@workspace:apps/lifeforge--achievements"], "@lifeforge/lifeforge--lang-en": ["@lifeforge/lifeforge--lang-en@workspace:locales/lifeforge--lang-en"], - "@lifeforge/lifeforge--local-ip-widget": ["@lifeforge/lifeforge--local-ip-widget@workspace:apps/lifeforge-module-localIpWidget"], + "@lifeforge/lifeforge--utility-widgets": ["@lifeforge/lifeforge--utility-widgets@workspace:apps/lifeforge--utility-widgets"], "@lifeforge/lifeforge--wallet": ["@lifeforge/lifeforge--wallet@workspace:apps/lifeforge--wallet"], - "@lifeforge/log": ["@lifeforge/log@workspace:packages/lifeforge-log"], + "@lifeforge/log": ["@lifeforge/log@workspace:packages/log"], "@lifeforge/melvinchia3636--modrinth": ["@lifeforge/melvinchia3636--modrinth@workspace:apps/melvinchia3636--modrinth"], "@lifeforge/server": ["@lifeforge/server@workspace:server"], - "@lifeforge/server-utils": ["@lifeforge/server-utils@workspace:packages/lifeforge-server-utils"], + "@lifeforge/server-utils": ["@lifeforge/server-utils@workspace:packages/server-utils"], "@lifeforge/shared": ["@lifeforge/shared@workspace:shared"], @@ -1608,6 +1604,8 @@ "bun-types": ["bun-types@1.3.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-4N0ig0fEomHt5R0KCFWjovxow98rIoRwKolrYdCcknNwMekCXRnWEUvgu5soYV8QXtVsrUD8B95MBOZGPvr6KQ=="], + "bundle-name": ["bundle-name@4.1.0", "", { "dependencies": { "run-applescript": "^7.0.0" } }, "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q=="], + "bundle-require": ["bundle-require@5.1.0", "", { "dependencies": { "load-tsconfig": "^0.2.3" }, "peerDependencies": { "esbuild": ">=0.18" } }, "sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA=="], "busboy": ["busboy@1.6.0", "", { "dependencies": { "streamsearch": "^1.1.0" } }, "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA=="], @@ -1896,8 +1894,14 @@ "deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="], + "default-browser": ["default-browser@5.5.0", "", { "dependencies": { "bundle-name": "^4.1.0", "default-browser-id": "^5.0.0" } }, "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw=="], + + "default-browser-id": ["default-browser-id@5.0.1", "", {}, "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q=="], + "define-data-property": ["define-data-property@1.1.4", "", { "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "gopd": "^1.0.1" } }, "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A=="], + "define-lazy-prop": ["define-lazy-prop@3.0.0", "", {}, "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg=="], + "define-properties": ["define-properties@1.2.1", "", { "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" } }, "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg=="], "define-property": ["define-property@2.0.2", "", { "dependencies": { "is-descriptor": "^1.0.2", "isobject": "^3.0.1" } }, "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ=="], @@ -2280,6 +2284,8 @@ "get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="], + "get-east-asian-width": ["get-east-asian-width@1.6.0", "", {}, "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA=="], + "get-func-name": ["get-func-name@2.0.2", "", {}, "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ=="], "get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="], @@ -2484,6 +2490,8 @@ "is-descriptor": ["is-descriptor@1.0.4", "", { "dependencies": { "is-accessor-descriptor": "^1.0.2", "is-data-descriptor": "^1.0.1" } }, "sha512-bv5z95W0dDtLfKwDfkTNxaRxmISBD3eQBKJeVxv2AQ7MjuUnDNG7cIQqvFtMOUYhsILWHhMayWdoGqNqYYYjww=="], + "is-docker": ["is-docker@3.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="], + "is-electron": ["is-electron@2.2.2", "", {}, "sha512-FO/Rhvz5tuw4MCWkpMzHFKWD2LsfHzIb7i6MdPYZ/KW7AlxawyLkqdy+jPZP1WubqEADE3O4FUENlJHDfQASRg=="], "is-extendable": ["is-extendable@0.1.1", "", {}, "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw=="], @@ -2500,6 +2508,10 @@ "is-hexadecimal": ["is-hexadecimal@1.0.4", "", {}, "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw=="], + "is-in-ssh": ["is-in-ssh@1.0.0", "", {}, "sha512-jYa6Q9rH90kR1vKB6NM7qqd1mge3Fx4Dhw5TVlK1MUBqhEOuCagrEHMevNuCcbECmXZ0ThXkRm+Ymr51HwEPAw=="], + + "is-inside-container": ["is-inside-container@1.0.0", "", { "dependencies": { "is-docker": "^3.0.0" }, "bin": { "is-inside-container": "cli.js" } }, "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA=="], + "is-installed-globally": ["is-installed-globally@0.4.0", "", { "dependencies": { "global-dirs": "^3.0.0", "is-path-inside": "^3.0.2" } }, "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ=="], "is-map": ["is-map@2.0.3", "", {}, "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw=="], @@ -2548,6 +2560,8 @@ "is-windows": ["is-windows@1.0.2", "", {}, "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA=="], + "is-wsl": ["is-wsl@3.1.1", "", { "dependencies": { "is-inside-container": "^1.0.0" } }, "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw=="], + "is-yarn-global": ["is-yarn-global@0.3.0", "", {}, "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw=="], "isarray": ["isarray@1.0.0", "", {}, "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="], @@ -2968,6 +2982,8 @@ "onetime": ["onetime@6.0.0", "", { "dependencies": { "mimic-fn": "^4.0.0" } }, "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ=="], + "open": ["open@11.0.0", "", { "dependencies": { "default-browser": "^5.4.0", "define-lazy-prop": "^3.0.0", "is-in-ssh": "^1.0.0", "is-inside-container": "^1.0.0", "powershell-utils": "^0.1.0", "wsl-utils": "^0.3.0" } }, "sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw=="], + "openai": ["openai@6.39.0", "", { "peerDependencies": { "ws": "^8.18.0", "zod": "^3.25 || ^4.0" }, "optionalPeers": ["ws", "zod"], "bin": { "openai": "bin/cli" } }, "sha512-O61LIsimY3acVabwvomwFhwrnN36yvHY2quIfy9keEcFytGgWeV35yLHQ6NVMLSBxRpHmcg2yuhCnlu2HT4pLQ=="], "opencollective-postinstall": ["opencollective-postinstall@2.0.3", "", { "bin": { "opencollective-postinstall": "index.js" } }, "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q=="], @@ -3080,6 +3096,8 @@ "postcss-value-parser": ["postcss-value-parser@4.2.0", "", {}, "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="], + "powershell-utils": ["powershell-utils@0.1.0", "", {}, "sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A=="], + "prefix-style": ["prefix-style@2.0.1", "", {}, "sha512-gdr1MBNVT0drzTq95CbSNdsrBDoHGlb2aDJP/FoY+1e+jSDPOb1Cv554gH2MGiSr2WTcXi/zu+NaFzfcHQkfBQ=="], "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="], @@ -3314,6 +3332,8 @@ "rollup": ["rollup@4.60.4", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.60.4", "@rollup/rollup-android-arm64": "4.60.4", "@rollup/rollup-darwin-arm64": "4.60.4", "@rollup/rollup-darwin-x64": "4.60.4", "@rollup/rollup-freebsd-arm64": "4.60.4", "@rollup/rollup-freebsd-x64": "4.60.4", "@rollup/rollup-linux-arm-gnueabihf": "4.60.4", "@rollup/rollup-linux-arm-musleabihf": "4.60.4", "@rollup/rollup-linux-arm64-gnu": "4.60.4", "@rollup/rollup-linux-arm64-musl": "4.60.4", "@rollup/rollup-linux-loong64-gnu": "4.60.4", "@rollup/rollup-linux-loong64-musl": "4.60.4", "@rollup/rollup-linux-ppc64-gnu": "4.60.4", "@rollup/rollup-linux-ppc64-musl": "4.60.4", "@rollup/rollup-linux-riscv64-gnu": "4.60.4", "@rollup/rollup-linux-riscv64-musl": "4.60.4", "@rollup/rollup-linux-s390x-gnu": "4.60.4", "@rollup/rollup-linux-x64-gnu": "4.60.4", "@rollup/rollup-linux-x64-musl": "4.60.4", "@rollup/rollup-openbsd-x64": "4.60.4", "@rollup/rollup-openharmony-arm64": "4.60.4", "@rollup/rollup-win32-arm64-msvc": "4.60.4", "@rollup/rollup-win32-ia32-msvc": "4.60.4", "@rollup/rollup-win32-x64-gnu": "4.60.4", "@rollup/rollup-win32-x64-msvc": "4.60.4", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-WHeFSbZYsPu3+bLoNRUuAO+wavNlocOPf3wSHTP7hcFKVnJeWsYlCDbr3mTS14FCizf9ccIxXA8sGL8zKeQN3g=="], + "rollup-plugin-visualizer": ["rollup-plugin-visualizer@7.0.1", "", { "dependencies": { "open": "^11.0.0", "picomatch": "^4.0.2", "source-map": "^0.7.4", "yargs": "^18.0.0" }, "peerDependencies": { "rolldown": "1.x || ^1.0.0-beta || ^1.0.0-rc", "rollup": "2.x || 3.x || 4.x" }, "optionalPeers": ["rolldown", "rollup"], "bin": { "rollup-plugin-visualizer": "dist/bin/cli.js" } }, "sha512-UJUT4+1Ho4OcWmPYU3sYXgUqI8B8Ayfe06MX7y0qCJ1K8aGoKtR/NDd/2nZqM7ADkrzny+I99Ul7GgyoiVNAgg=="], + "rotating-file-stream": ["rotating-file-stream@3.2.9", "", {}, "sha512-i9i0KkHh12ryl4xtELg+0gyoFre2PJ9RcQQLzquWsiqygyYsrZLckrqqYrthhnJZGZb4g+KUHtcoWYVq34gaug=="], "roughjs": ["roughjs@4.6.6", "", { "dependencies": { "hachure-fill": "^0.5.2", "path-data-parser": "^0.1.0", "points-on-curve": "^0.2.0", "points-on-path": "^0.2.1" } }, "sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ=="], @@ -3328,6 +3348,8 @@ "rrweb-snapshot": ["rrweb-snapshot@2.0.0-alpha.20", "", { "dependencies": { "postcss": "^8.4.38" } }, "sha512-YTNf9YVeaGRo/jxY3FKBge2c/Ojd/KTHmuWloUSB+oyPXuY73ZeeG873qMMmhIpqEn7hn7aBF1eWEQmP7wjf8A=="], + "run-applescript": ["run-applescript@7.1.0", "", {}, "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q=="], + "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], "rw": ["rw@1.3.3", "", {}, "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ=="], @@ -3784,6 +3806,8 @@ "ws": ["ws@8.21.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g=="], + "wsl-utils": ["wsl-utils@0.3.1", "", { "dependencies": { "is-wsl": "^3.1.0", "powershell-utils": "^0.1.0" } }, "sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg=="], + "xdg-basedir": ["xdg-basedir@3.0.0", "", {}, "sha512-1Dly4xqlulvPD3fZUQJLY+FUIeqN3N2MM3uqe4rCJftAvOjFa3jFGfctOgluGx4ahPbUCsZkmJILiP0Vi4T6lQ=="], "xml-name-validator": ["xml-name-validator@5.0.0", "", {}, "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg=="], @@ -3852,18 +3876,10 @@ "@joshwooding/vite-plugin-react-docgen-typescript/magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], - "@lifeforge/client/opentype.js": ["opentype.js@1.3.5", "", { "bin": { "ot": "bin/ot" } }, "sha512-thKDiELidAApOvXlncrpwDZKJCa9fXLEKM4+FoEWI+qTLDeNb+h7EkN+8a7KQODsB1GZ+Exz9KknkoPrEdXZDw=="], - - "@lifeforge/client/react-i18next": ["react-i18next@15.7.4", "", { "dependencies": { "@babel/runtime": "^7.27.6", "html-parse-stringify": "^3.0.1" }, "peerDependencies": { "i18next": ">= 23.4.0", "react": ">= 16.8.0", "react-dom": "*", "react-native": "*", "typescript": "^5" }, "optionalPeers": ["react-dom", "react-native", "typescript"] }, "sha512-nyU8iKNrI5uDJch0z9+Y5XEr34b0wkyYj3Rp+tfbahxtlswxSCjcUL9H0nqXo9IR3/t5Y5PKIA3fx3MfUyR9Xw=="], - - "@lifeforge/lifeforge--local-ip-widget/react-i18next": ["react-i18next@15.7.4", "", { "dependencies": { "@babel/runtime": "^7.27.6", "html-parse-stringify": "^3.0.1" }, "peerDependencies": { "i18next": ">= 23.4.0", "react": ">= 16.8.0", "react-dom": "*", "react-native": "*", "typescript": "^5" }, "optionalPeers": ["react-dom", "react-native", "typescript"] }, "sha512-nyU8iKNrI5uDJch0z9+Y5XEr34b0wkyYj3Rp+tfbahxtlswxSCjcUL9H0nqXo9IR3/t5Y5PKIA3fx3MfUyR9Xw=="], - "@lifeforge/log/@types/node": ["@types/node@25.9.1", "", { "dependencies": { "undici-types": ">=7.24.0 <7.24.7" } }, "sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg=="], "@lifeforge/server/@types/jsdom": ["@types/jsdom@21.1.7", "", { "dependencies": { "@types/node": "*", "@types/tough-cookie": "*", "parse5": "^7.0.0" } }, "sha512-yOriVnggzrnQ3a9OKOCxaVuSug3w3/SbOj5i7VwXWZEyUNl3bLF9V3MfxGbZKuwqJOQyRfqXyROBB1CoZLFWzA=="], - "@lifeforge/server/dotenv": ["dotenv@16.6.1", "", {}, "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow=="], - "@lifeforge/server/uuid": ["uuid@9.0.1", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="], "@lifeforge/server-utils/groq-sdk": ["groq-sdk@0.20.1", "", { "dependencies": { "@types/node": "^18.11.18", "@types/node-fetch": "^2.6.4", "abort-controller": "^3.0.0", "agentkeepalive": "^4.2.1", "form-data-encoder": "1.7.2", "formdata-node": "^4.3.2", "node-fetch": "^2.6.7" } }, "sha512-I/U7mHDcanKHR/P0oKSSS0M6oHR69G1QgtMplqmF3gSejJ5ihV7l+/0OqbNoqOzYoQKG4XH7O4zCqMoTKCztQQ=="], @@ -3874,10 +3890,6 @@ "@lifeforge/server-utils/uuid": ["uuid@11.1.1", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ=="], - "@lifeforge/shared/react-i18next": ["react-i18next@15.7.4", "", { "dependencies": { "@babel/runtime": "^7.27.6", "html-parse-stringify": "^3.0.1" }, "peerDependencies": { "i18next": ">= 23.4.0", "react": ">= 16.8.0", "react-dom": "*", "react-native": "*", "typescript": "^5" }, "optionalPeers": ["react-dom", "react-native", "typescript"] }, "sha512-nyU8iKNrI5uDJch0z9+Y5XEr34b0wkyYj3Rp+tfbahxtlswxSCjcUL9H0nqXo9IR3/t5Y5PKIA3fx3MfUyR9Xw=="], - - "@lifeforge/ui/react-i18next": ["react-i18next@15.7.4", "", { "dependencies": { "@babel/runtime": "^7.27.6", "html-parse-stringify": "^3.0.1" }, "peerDependencies": { "i18next": ">= 23.4.0", "react": ">= 16.8.0", "react-dom": "*", "react-native": "*", "typescript": "^5" }, "optionalPeers": ["react-dom", "react-native", "typescript"] }, "sha512-nyU8iKNrI5uDJch0z9+Y5XEr34b0wkyYj3Rp+tfbahxtlswxSCjcUL9H0nqXo9IR3/t5Y5PKIA3fx3MfUyR9Xw=="], - "@lifeforge/ui/uuid": ["uuid@11.1.1", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ=="], "@lifeforge/ui/vitest": ["vitest@1.6.1", "", { "dependencies": { "@vitest/expect": "1.6.1", "@vitest/runner": "1.6.1", "@vitest/snapshot": "1.6.1", "@vitest/spy": "1.6.1", "@vitest/utils": "1.6.1", "acorn-walk": "^8.3.2", "chai": "^4.3.10", "debug": "^4.3.4", "execa": "^8.0.1", "local-pkg": "^0.5.0", "magic-string": "^0.30.5", "pathe": "^1.1.1", "picocolors": "^1.0.0", "std-env": "^3.5.0", "strip-literal": "^2.0.0", "tinybench": "^2.5.1", "tinypool": "^0.8.3", "vite": "^5.0.0", "vite-node": "1.6.1", "why-is-node-running": "^2.2.2" }, "peerDependencies": { "@edge-runtime/vm": "*", "@types/node": "^18.0.0 || >=20.0.0", "@vitest/browser": "1.6.1", "@vitest/ui": "1.6.1", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@types/node", "@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-Ljb1cnSJSivGN0LqXd/zmDbWEM0RNNg2t1QW/XUhYl/qPqyu7CsqeWtqQXHVaJsecLPuDoak2oJcZN2QoRIOag=="], @@ -4282,6 +4294,8 @@ "rollup/@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], + "rollup-plugin-visualizer/yargs": ["yargs@18.0.0", "", { "dependencies": { "cliui": "^9.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "string-width": "^7.2.0", "y18n": "^5.0.5", "yargs-parser": "^22.0.0" } }, "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg=="], + "rrweb/fflate": ["fflate@0.4.8", "", {}, "sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA=="], "rrweb/rrweb-snapshot": ["rrweb-snapshot@2.0.0-alpha.4", "", {}, "sha512-KQ2OtPpXO5jLYqg1OnXS/Hf+EzqnZyP5A+XPqBCjYpj3XIje/Od4gdUwjbFo3cVuWq5Cw5Y1d3/xwgIS7/XpQQ=="], @@ -4756,6 +4770,12 @@ "regex-not/extend-shallow/is-extendable": ["is-extendable@1.0.1", "", { "dependencies": { "is-plain-object": "^2.0.4" } }, "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA=="], + "rollup-plugin-visualizer/yargs/cliui": ["cliui@9.0.1", "", { "dependencies": { "string-width": "^7.2.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" } }, "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w=="], + + "rollup-plugin-visualizer/yargs/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="], + + "rollup-plugin-visualizer/yargs/yargs-parser": ["yargs-parser@22.0.0", "", {}, "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw=="], + "send/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], "snapdragon-util/kind-of/is-buffer": ["is-buffer@1.1.6", "", {}, "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="], @@ -4956,6 +4976,10 @@ "micromatch/braces/fill-range/to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], + "rollup-plugin-visualizer/yargs/cliui/wrap-ansi": ["wrap-ansi@9.0.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", "strip-ansi": "^7.1.0" } }, "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww=="], + + "rollup-plugin-visualizer/yargs/string-width/emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="], + "storybook/@vitest/expect/@vitest/utils/@vitest/pretty-format": ["@vitest/pretty-format@3.2.4", "", { "dependencies": { "tinyrainbow": "^2.0.0" } }, "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA=="], "storybook/@vitest/expect/@vitest/utils/loupe": ["loupe@3.2.1", "", {}, "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ=="], @@ -5218,6 +5242,8 @@ "micromatch/braces/fill-range/to-regex-range/is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], + "rollup-plugin-visualizer/yargs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], + "typescript-eslint/@typescript-eslint/typescript-estree/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], "typescript-eslint/@typescript-eslint/utils/@typescript-eslint/scope-manager/@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@5.0.1", "", {}, "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA=="], diff --git a/bunfig.toml b/bunfig.toml deleted file mode 100644 index cbf7f2a12..000000000 --- a/bunfig.toml +++ /dev/null @@ -1,3 +0,0 @@ -[install] -[install.scopes] -"@lifeforge" = "https://registry.lifeforge.dev/:_authToken=${FORGISTRY_TOKEN}" diff --git a/client/src/core/accountSettings/manifest.ts b/client/src/core/accountSettings/manifest.ts index ff9c65c1b..229f18134 100644 --- a/client/src/core/accountSettings/manifest.ts +++ b/client/src/core/accountSettings/manifest.ts @@ -1,6 +1,6 @@ import { lazy } from 'react' -import type { ModuleCategory } from '@lifeforge/shared' +import type { ModuleCategory } from '@lifeforge/federation' export default { routes: { diff --git a/client/src/core/apiKeys/components/EntryItem.tsx b/client/src/core/apiKeys/components/EntryItem.tsx index 3c1c981fc..2cf451c52 100644 --- a/client/src/core/apiKeys/components/EntryItem.tsx +++ b/client/src/core/apiKeys/components/EntryItem.tsx @@ -6,7 +6,7 @@ import { useCallback, useState } from 'react' import { useTranslation } from 'react-i18next' import { toast } from 'react-toastify' -import { useFederation } from '@lifeforge/shared' +import { useFederation } from '@lifeforge/federation' import { Box, Button, diff --git a/client/src/core/apiKeys/manifest.ts b/client/src/core/apiKeys/manifest.ts index 955300978..177cd50a3 100644 --- a/client/src/core/apiKeys/manifest.ts +++ b/client/src/core/apiKeys/manifest.ts @@ -1,6 +1,6 @@ import { lazy } from 'react' -import type { ModuleCategory } from '@lifeforge/shared' +import type { ModuleCategory } from '@lifeforge/federation' export default { routes: { diff --git a/client/src/core/apiKeys/modals/ModulesRequiredListModal.tsx b/client/src/core/apiKeys/modals/ModulesRequiredListModal.tsx index d314021c1..292538c3a 100644 --- a/client/src/core/apiKeys/modals/ModulesRequiredListModal.tsx +++ b/client/src/core/apiKeys/modals/ModulesRequiredListModal.tsx @@ -1,6 +1,6 @@ import { useTranslation } from 'react-i18next' -import { useFederation } from '@lifeforge/shared' +import { useFederation } from '@lifeforge/federation' import { Box, Card, diff --git a/client/src/core/backups/manifest.ts b/client/src/core/backups/manifest.ts index a3593a680..9b4e29c1a 100644 --- a/client/src/core/backups/manifest.ts +++ b/client/src/core/backups/manifest.ts @@ -1,6 +1,6 @@ import { lazy } from 'react' -import type { ModuleCategory } from '@lifeforge/shared' +import type { ModuleCategory } from '@lifeforge/federation' export default { routes: { diff --git a/client/src/core/dashboard/manifest.ts b/client/src/core/dashboard/manifest.ts index 85019ab59..1e938ec9c 100644 --- a/client/src/core/dashboard/manifest.ts +++ b/client/src/core/dashboard/manifest.ts @@ -1,6 +1,6 @@ import { lazy } from 'react' -import type { ModuleCategory } from '@lifeforge/shared' +import type { ModuleCategory } from '@lifeforge/federation' export default { routes: { diff --git a/client/src/core/dashboard/providers/WidgetProvider.tsx b/client/src/core/dashboard/providers/WidgetProvider.tsx index 5e2e13d81..b0cfdf409 100644 --- a/client/src/core/dashboard/providers/WidgetProvider.tsx +++ b/client/src/core/dashboard/providers/WidgetProvider.tsx @@ -7,7 +7,8 @@ import { useState } from 'react' -import { useFederation, widgetConfigSchema } from '@lifeforge/shared' +import { widgetConfigSchema } from '@lifeforge/shared' +import { useFederation } from '@lifeforge/federation' import { LoadingScreen } from '@lifeforge/ui' export interface WidgetEntry { diff --git a/client/src/core/documentation/manifest.ts b/client/src/core/documentation/manifest.ts index 267d7c6d8..800c9ae10 100644 --- a/client/src/core/documentation/manifest.ts +++ b/client/src/core/documentation/manifest.ts @@ -1,6 +1,6 @@ import { lazy } from 'react' -import type { ModuleCategory } from '@lifeforge/shared' +import type { ModuleCategory } from '@lifeforge/federation' export default { routes: { diff --git a/client/src/core/moduleManager/manifest.ts b/client/src/core/moduleManager/manifest.ts index 7cfc96f23..556ac0c1d 100644 --- a/client/src/core/moduleManager/manifest.ts +++ b/client/src/core/moduleManager/manifest.ts @@ -1,6 +1,6 @@ import { lazy } from 'react' -import type { ModuleCategory } from '@lifeforge/shared' +import type { ModuleCategory } from '@lifeforge/federation' export default { routes: { diff --git a/client/src/core/moduleManager/pages/Categories/components/CategoryItem.tsx b/client/src/core/moduleManager/pages/Categories/components/CategoryItem.tsx index d76593265..7c8d6e97d 100644 --- a/client/src/core/moduleManager/pages/Categories/components/CategoryItem.tsx +++ b/client/src/core/moduleManager/pages/Categories/components/CategoryItem.tsx @@ -2,7 +2,7 @@ import { useSortable } from '@dnd-kit/sortable' import { CSS } from '@dnd-kit/utilities' import { toast } from 'react-toastify' -import { useFederation } from '@lifeforge/shared' +import { useFederation } from '@lifeforge/federation' import { Box, Button, diff --git a/client/src/core/moduleManager/pages/Categories/index.tsx b/client/src/core/moduleManager/pages/Categories/index.tsx index 1d40521a1..15e91f7b4 100644 --- a/client/src/core/moduleManager/pages/Categories/index.tsx +++ b/client/src/core/moduleManager/pages/Categories/index.tsx @@ -17,7 +17,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' import { toast } from 'react-toastify' -import { SYSTEM_CATEGORIES, useFederation } from '@lifeforge/shared' +import { SYSTEM_CATEGORIES, useFederation } from '@lifeforge/federation' import { Alert, Button, diff --git a/client/src/core/moduleManager/pages/Modules/components/ModuleItem.tsx b/client/src/core/moduleManager/pages/Modules/components/ModuleItem.tsx index 24926d098..f7dcde31f 100644 --- a/client/src/core/moduleManager/pages/Modules/components/ModuleItem.tsx +++ b/client/src/core/moduleManager/pages/Modules/components/ModuleItem.tsx @@ -2,7 +2,8 @@ import { useMutation } from '@tanstack/react-query' import { useTranslation } from 'react-i18next' import { toast } from 'react-toastify' -import { useAPIOnlineStatus, useFederation } from '@lifeforge/shared' +import { useAPIOnlineStatus } from '@lifeforge/shared' +import { useFederation } from '@lifeforge/federation' import { Box, Card, diff --git a/client/src/core/moduleManager/pages/Modules/index.tsx b/client/src/core/moduleManager/pages/Modules/index.tsx index f476358f0..6696926e1 100644 --- a/client/src/core/moduleManager/pages/Modules/index.tsx +++ b/client/src/core/moduleManager/pages/Modules/index.tsx @@ -2,7 +2,8 @@ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' import { useMemo } from 'react' import { toast } from 'react-toastify' -import { useFederation, usePersonalization } from '@lifeforge/shared' +import { usePersonalization } from '@lifeforge/shared' +import { useFederation } from '@lifeforge/federation' import { EmptyStateScreen, Grid, diff --git a/client/src/core/personalization/manifest.ts b/client/src/core/personalization/manifest.ts index 9b37664eb..6c88fad33 100644 --- a/client/src/core/personalization/manifest.ts +++ b/client/src/core/personalization/manifest.ts @@ -1,6 +1,6 @@ import { lazy } from 'react' -import type { ModuleCategory } from '@lifeforge/shared' +import type { ModuleCategory } from '@lifeforge/federation' export default { routes: { diff --git a/client/src/federation/loaders/loadCoreModules.ts b/client/src/federation/loaders/loadCoreModules.ts deleted file mode 100644 index 25bd854fe..000000000 --- a/client/src/federation/loaders/loadCoreModules.ts +++ /dev/null @@ -1,21 +0,0 @@ -import type { ModuleCategory } from '@lifeforge/shared' - -import accountSettings from '@/core/accountSettings/manifest' -import apiKeys from '@/core/apiKeys/manifest' -import backups from '@/core/backups/manifest' -import dashboard from '@/core/dashboard/manifest' -import documentation from '@/core/documentation/manifest' -import moduleManager from '@/core/moduleManager/manifest' -import personalization from '@/core/personalization/manifest' - -export default function loadCoreModules(): ModuleCategory['items'][number][] { - return [ - accountSettings, - apiKeys, - backups, - dashboard, - documentation, - personalization, - moduleManager - ] -} diff --git a/client/src/federation/providers/CoreFederationProvider.tsx b/client/src/federation/providers/CoreFederationProvider.tsx index 42a5f0fef..77d33dd02 100644 --- a/client/src/federation/providers/CoreFederationProvider.tsx +++ b/client/src/federation/providers/CoreFederationProvider.tsx @@ -1,13 +1,36 @@ import { useEffect } from 'react' -import { useFederation } from '@lifeforge/shared' +import { + type ModuleConfig, + loadModules, + useFederation +} from '@lifeforge/federation' -import loadModules from '../loaders/loadModules' +import accountSettings from '@/core/accountSettings/manifest' +import apiKeys from '@/core/apiKeys/manifest' +import backups from '@/core/backups/manifest' +import dashboard from '@/core/dashboard/manifest' +import documentation from '@/core/documentation/manifest' +import moduleManager from '@/core/moduleManager/manifest' +import personalization from '@/core/personalization/manifest' +import forgeAPI from '@/forgeAPI' -// Force full reload instead of HMR to ensure clean state -if (import.meta.hot) { - import.meta.hot.invalidate() -} +const coreModules = [ + accountSettings, + apiKeys, + backups, + dashboard, + documentation, + personalization, + moduleManager +] + +const devModeImports = import.meta.env.DEV + ? import.meta.glob<{ default: ModuleConfig }>( + '../../../../apps/*/client/manifest.ts', + { eager: false } + ) + : {} export default function CoreFederationProvider({ children @@ -28,7 +51,7 @@ export default function CoreFederationProvider({ setError(null) try { - const result = await loadModules() + const result = await loadModules(forgeAPI, coreModules, devModeImports) setModules(result.routes) setGlobalProviders(result.globalProviders) diff --git a/client/src/index.css b/client/src/index.css index e604087af..c1a12ce9e 100644 --- a/client/src/index.css +++ b/client/src/index.css @@ -3,7 +3,7 @@ @import 'react-grid-layout/css/styles.css'; @import '@lifeforge/ui/dist/index.css'; -@import '@core/dashboard/index.css'; +@import './core/dashboard/index.css'; @source '../../apps/*/client/src'; @source '../../apps/*/client/dist'; diff --git a/client/src/providers/features/APIKeyStatusProvider.tsx b/client/src/providers/features/APIKeyStatusProvider.tsx index e49fe2219..d5579e97b 100644 --- a/client/src/providers/features/APIKeyStatusProvider.tsx +++ b/client/src/providers/features/APIKeyStatusProvider.tsx @@ -1,7 +1,8 @@ import { useQuery } from '@tanstack/react-query' import { useTranslation } from 'react-i18next' -import { Link, type ModuleCategory } from '@lifeforge/shared' +import { Link } from '@lifeforge/shared' +import { type ModuleCategory } from '@lifeforge/federation' import { Button, Card, diff --git a/client/src/providers/features/ExternalModuleProviders.tsx b/client/src/providers/features/ExternalModuleProviders.tsx index 1eaf2b110..ad3aeb003 100644 --- a/client/src/providers/features/ExternalModuleProviders.tsx +++ b/client/src/providers/features/ExternalModuleProviders.tsx @@ -1,4 +1,4 @@ -import { useFederation } from '@lifeforge/shared' +import { useFederation } from '@lifeforge/federation' function ExternalModuleProviders({ children }: { children: React.ReactNode }) { const { globalProviders } = useFederation() diff --git a/client/src/providers/index.tsx b/client/src/providers/index.tsx index 97e00f43b..8cabe6e2c 100644 --- a/client/src/providers/index.tsx +++ b/client/src/providers/index.tsx @@ -6,13 +6,13 @@ import { APIOnlineStatusProvider, AuthProvider, EncryptionProvider, - FederationProvider, MainSidebarStateProvider, NuqsProvider, PersonalizationProvider, SocketProvider, ToastProvider } from '@lifeforge/shared' +import { FederationProvider } from '@lifeforge/federation' import { APIOnlineStatusWrapper, BackgroundProvider, diff --git a/client/src/routes/components/Sidebar/MainSidebarTitle.tsx b/client/src/routes/components/Sidebar/MainSidebarTitle.tsx index 463ed1f89..2464dbd1a 100644 --- a/client/src/routes/components/Sidebar/MainSidebarTitle.tsx +++ b/client/src/routes/components/Sidebar/MainSidebarTitle.tsx @@ -1,6 +1,7 @@ import { useMemo } from 'react' -import { useFederation, usePersonalization } from '@lifeforge/shared' +import { usePersonalization } from '@lifeforge/shared' +import { useFederation } from '@lifeforge/federation' import { SidebarTitle } from '@lifeforge/ui' function MainSidebarTitle({ title }: { title: string }) { diff --git a/client/src/routes/components/Sidebar/SidebarItems.tsx b/client/src/routes/components/Sidebar/SidebarItems.tsx index f063ccfb5..67432eb11 100644 --- a/client/src/routes/components/Sidebar/SidebarItems.tsx +++ b/client/src/routes/components/Sidebar/SidebarItems.tsx @@ -4,10 +4,10 @@ import { Fragment, useEffect, useMemo, useState } from 'react' import { normalizeSubnamespace, useAuth, - useFederation, useLocation, useMainSidebarState } from '@lifeforge/shared' +import { useFederation } from '@lifeforge/federation' import { Box, EmptyStateScreen, diff --git a/client/src/routes/hooks/useAppRouter.ts b/client/src/routes/hooks/useAppRouter.ts index cf79237a0..bd831b691 100644 --- a/client/src/routes/hooks/useAppRouter.ts +++ b/client/src/routes/hooks/useAppRouter.ts @@ -2,7 +2,8 @@ import { useEffect, useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' import type { DataRouter } from '@lifeforge/shared' -import { createBrowserRouter, useAuth, useFederation } from '@lifeforge/shared' +import { createBrowserRouter, useAuth } from '@lifeforge/shared' +import { useFederation } from '@lifeforge/federation' import { createAuthLoadingConfig, diff --git a/client/src/routes/hooks/useTitleEffect.ts b/client/src/routes/hooks/useTitleEffect.ts index a9033ed85..1761361b6 100644 --- a/client/src/routes/hooks/useTitleEffect.ts +++ b/client/src/routes/hooks/useTitleEffect.ts @@ -1,7 +1,8 @@ import _ from 'lodash' import { useEffect } from 'react' -import { useFederation, useLocation } from '@lifeforge/shared' +import { useLocation } from '@lifeforge/shared' +import { useFederation } from '@lifeforge/federation' function useTitleEffect() { const { modules } = useFederation() diff --git a/client/src/routes/utils/routeBuilder.tsx b/client/src/routes/utils/routeBuilder.tsx index 6c55f7c26..df171932b 100644 --- a/client/src/routes/utils/routeBuilder.tsx +++ b/client/src/routes/utils/routeBuilder.tsx @@ -1,10 +1,7 @@ import { Suspense } from 'react' -import type { - ModuleCategory, - ModuleConfig, - RouteObject -} from '@lifeforge/shared' +import type { RouteObject } from '@lifeforge/shared' +import type { ModuleCategory, ModuleConfig } from '@lifeforge/federation' import { LoadingScreen, ModalManager, ModuleWrapper } from '@lifeforge/ui' import APIKeyStatusProvider from '@/providers/features/APIKeyStatusProvider' diff --git a/client/src/routes/utils/routerFactory.tsx b/client/src/routes/utils/routerFactory.tsx index 72ce3a512..c4993fefc 100644 --- a/client/src/routes/utils/routerFactory.tsx +++ b/client/src/routes/utils/routerFactory.tsx @@ -1,5 +1,6 @@ import { Navigate } from '@lifeforge/shared' -import type { ModuleCategory, RouteObject } from '@lifeforge/shared' +import type { RouteObject } from '@lifeforge/shared' +import type { ModuleCategory } from '@lifeforge/federation' import { LoadingScreen, NotFoundScreen } from '@lifeforge/ui' import Auth from '@/core/auth' diff --git a/client/tsconfig.json b/client/tsconfig.json index 47e5027f0..0dc2b92ff 100644 --- a/client/tsconfig.json +++ b/client/tsconfig.json @@ -2,10 +2,17 @@ "compilerOptions": { "target": "ES2020", "useDefineForClassFields": true, - "lib": ["ES2020", "DOM", "DOM.Iterable", "ES2024.Object"], + "lib": [ + "ES2020", + "DOM", + "DOM.Iterable", + "ES2024.Object" + ], "module": "ESNext", "skipLibCheck": true, - "types": ["node"], + "types": [ + "node" + ], /* Bundler mode */ "outDir": "${configDir}/tsbuild", "moduleResolution": "bundler", @@ -22,9 +29,16 @@ "rootDir": "../", "baseUrl": "./", "paths": { - "@/*": ["./src/*"], - "@core/*": ["../core/*"] + "@/*": [ + "./src/*" + ], + "@core/*": [ + "../core/*" + ] } }, - "include": ["./src/**/*"] -} + "include": [ + "./src/**/*", + "./vite.config.ts" + ] +} \ No newline at end of file diff --git a/client/vite.config.ts b/client/vite.config.ts index f88932320..875d6be93 100644 --- a/client/vite.config.ts +++ b/client/vite.config.ts @@ -1,171 +1,3 @@ -// import MillionLint from '@million/lint' -import federation from '@originjs/vite-plugin-federation' -import { vanillaExtractPlugin } from '@vanilla-extract/vite-plugin' -import react from '@vitejs/plugin-react' -import { globSync } from 'glob' -import path from 'node:path' -import { type Alias, defineConfig } from 'vite' +import { defineClientConfig } from '@lifeforge/configs' -const ReactCompilerConfig = { - sources: filename => { - return true - } -} - -export const alias: Alias[] = [ - { - find: /^@lifeforge\/shared$/, - replacement: path.resolve(__dirname, '../shared/src/index.ts') - }, - { - find: /^@lifeforge\/ui$/, - replacement: path.resolve(__dirname, '../packages/ui/src/index.ts') - }, - { - find: '@providers', - replacement: path.resolve(__dirname, './src/providers') - }, - { find: '@utils', replacement: path.resolve(__dirname, './src/utils') }, - { find: '@core', replacement: path.resolve(__dirname, './src/core') }, - { find: '@modules', replacement: path.resolve(__dirname, '../apps') }, - { - find: '@', - replacement: '@', - customResolver: (id, importer, options) => { - let rootDir = '' - const isAppModule = - importer?.includes('/apps/') && - importer?.includes('/client/') && - !importer?.includes('/client/src/') - - const isManifest = id === '@/manifest' || id === '@/manifest.ts' - - if (isManifest) { - rootDir = importer?.split('/src/')[0] || '' - } else if (importer?.endsWith('manifest.ts')) { - rootDir = importer.replace('manifest.ts', 'src/') - } else if (isAppModule) { - const clientMatch = importer?.match(/(.+\/client)\//) - rootDir = clientMatch?.[1] || '' - } else { - rootDir = importer?.split('/src/')[0] + '/src' || '' - } - - const matched = globSync([ - path.resolve(rootDir, id.slice(2) + '.{tsx,ts,json}'), - path.resolve(rootDir, id.slice(2), 'index.{tsx,ts}'), - path.resolve(rootDir, id.slice(2)) - ]) - if (!matched[0]) { - console.log([ - path.resolve(rootDir, id.slice(2) + '.{tsx,ts,json}'), - path.resolve(rootDir, id.slice(2), 'index.{tsx,ts}'), - path.resolve(rootDir, id.slice(2)) - ]) - console.log( - `[vite] failed to resolve import "${id}" from "${importer}"` - ) - return null - } - return matched[0] - } - } -] - -export default defineConfig(({ command }) => { - const isDev = command === 'serve' - const activeAlias = isDev - ? alias - : alias.filter(a => { - if (a.find instanceof RegExp) { - return ( - !a.find.test('@lifeforge/shared') && !a.find.test('@lifeforge/ui') - ) - } - return a.find !== '@lifeforge/shared' && a.find !== '@lifeforge/ui' - }) - - return { - envDir: path.resolve(__dirname, '../env'), - plugins: [ - // MillionLint.vite({}), - react({ - babel: { - plugins: [['babel-plugin-react-compiler', ReactCompilerConfig]] - } - }), - vanillaExtractPlugin(), - federation({ - name: 'host', - remotes: { - None: '' - }, - shared: [ - 'react', - 'react-dom', - '@lifeforge/shared', - '@lifeforge/ui', - '@tanstack/react-query', - 'i18next', - 'react-i18next' - ] - }) - ], - server: { - fs: { - strict: true - }, - watch: { - ignored: ['**/node_modules/**', '**/.git/**'] - }, - allowedHosts: ['_.melvinchia.dev'] - }, - resolve: { - alias: activeAlias - }, - build: { - commonjsOptions: { - transformMixedEsModules: true - }, - target: 'esnext', - sourcemap: false, - rollupOptions: { - output: { - manualChunks(id) { - if (id.includes('node_modules')) { - return id - .toString() - .split('node_modules/') - .pop()! - .split('/')[0] - .toString() - } - } - } - } - }, - optimizeDeps: { - exclude: ['@lifeforge/shared', '@lifeforge/ui'], - esbuildOptions: { - sourcemap: false, - target: 'esnext' - } - }, - css: { - postcss: { - plugins: [ - { - postcssPlugin: 'internal:charset-removal', - AtRule: { - charset: atRule => { - if (atRule.name === 'charset') { - atRule.remove() - } - } - } - } - ] - } - } - } -}) +export default defineClientConfig(__dirname) diff --git a/docker/client/Dockerfile b/docker/client/Dockerfile index a9945882f..4b0a92ed6 100644 --- a/docker/client/Dockerfile +++ b/docker/client/Dockerfile @@ -19,13 +19,13 @@ RUN --mount=type=cache,target=/root/.bun/install/cache \ bun install --linker isolated # Build @lifeforge/log (required by forge CLI used in prebuild) -RUN cd /app/packages/lifeforge-log && bun run build +RUN cd /app/packages/log && bun run build # Build shared package (required by server types) RUN cd /app/shared && bun run build # Build @lifeforge/server-utils (required by server types) -RUN cd /app/packages/lifeforge-server-utils && bun run build +RUN cd /app/packages/server-utils && bun run build # Build client RUN cd /app/client && bun run build diff --git a/docker/db-init/Dockerfile b/docker/db-init/Dockerfile index 1d694d5d9..9e1d9afbd 100644 --- a/docker/db-init/Dockerfile +++ b/docker/db-init/Dockerfile @@ -20,10 +20,10 @@ RUN --mount=type=cache,target=/root/.bun/install/cache \ bun install --linker isolated # Build @lifeforge/log (required by tools) -RUN cd /app/packages/lifeforge-log && bun run build +RUN cd /app/packages/log && bun run build # Build @lifeforge/server-utils (required by schema files) -RUN cd /app/packages/lifeforge-server-utils && bun run build +RUN cd /app/packages/server-utils && bun run build # Build forge CLI RUN cd /app/tools && bun run build @@ -53,13 +53,13 @@ COPY --from=builder /app/shared/dist ./shared/dist COPY --from=builder /app/shared/package.json ./shared/package.json # Copy @lifeforge/server-utils (required by schema files) -COPY --from=builder /app/packages/lifeforge-server-utils/dist ./packages/lifeforge-server-utils/dist -COPY --from=builder /app/packages/lifeforge-server-utils/package.json ./packages/lifeforge-server-utils/package.json +COPY --from=builder /app/packages/server-utils/dist ./packages/server-utils/dist +COPY --from=builder /app/packages/server-utils/package.json ./packages/server-utils/package.json # Create node_modules symlinks for package resolution RUN mkdir -p node_modules/@lifeforge && \ ln -sf /app/shared node_modules/shared && \ - ln -sf /app/packages/lifeforge-server-utils node_modules/@lifeforge/server-utils + ln -sf /app/packages/server-utils node_modules/@lifeforge/server-utils # Install minimal dependencies for schema evaluation RUN echo '{"dependencies":{"zod":"^4.0.0"}}' > package.json && bun install diff --git a/docker/server/Dockerfile b/docker/server/Dockerfile index 0813ce6d8..ddb04e6b9 100644 --- a/docker/server/Dockerfile +++ b/docker/server/Dockerfile @@ -20,10 +20,10 @@ RUN --mount=type=cache,target=/root/.bun/install/cache \ RUN cd /lifeforge/shared && bun run build # Build @lifeforge/log package -RUN cd /lifeforge/packages/lifeforge-log && bun run build +RUN cd /lifeforge/packages/log && bun run build # Build lifeforge-server-utils package -RUN cd /lifeforge/packages/lifeforge-server-utils && bun run build +RUN cd /lifeforge/packages/server-utils && bun run build # Build server bundle RUN cd /lifeforge/server && bun run build @@ -54,12 +54,12 @@ COPY --from=builder /lifeforge/shared/dist ./shared/dist COPY --from=builder /lifeforge/shared/package.json ./shared/package.json # Copy @lifeforge/log package -COPY --from=builder /lifeforge/packages/lifeforge-log/dist ./packages/lifeforge-log/dist -COPY --from=builder /lifeforge/packages/lifeforge-log/package.json ./packages/lifeforge-log/package.json +COPY --from=builder /lifeforge/packages/log/dist ./packages/log/dist +COPY --from=builder /lifeforge/packages/log/package.json ./packages/log/package.json # Copy lifeforge-server-utils package (required by module bundles at runtime) -COPY --from=builder /lifeforge/packages/lifeforge-server-utils/dist ./packages/lifeforge-server-utils/dist -COPY --from=builder /lifeforge/packages/lifeforge-server-utils/package.json ./packages/lifeforge-server-utils/package.json +COPY --from=builder /lifeforge/packages/server-utils/dist ./packages/server-utils/dist +COPY --from=builder /lifeforge/packages/server-utils/package.json ./packages/server-utils/package.json # Install server dependencies COPY --from=builder /lifeforge/server/package.docker.json ./package.json diff --git a/docker/server/entrypoint.sh b/docker/server/entrypoint.sh index 61f4f8b61..4e107645c 100644 --- a/docker/server/entrypoint.sh +++ b/docker/server/entrypoint.sh @@ -15,10 +15,10 @@ mkdir -p /lifeforge/node_modules/@lifeforge ln -sf /lifeforge/shared /lifeforge/node_modules/shared # Symlink @lifeforge/log (required by server-utils) -ln -sf /lifeforge/packages/lifeforge-log /lifeforge/node_modules/@lifeforge/log +ln -sf /lifeforge/packages/log /lifeforge/node_modules/@lifeforge/log # Symlink @lifeforge/server-utils (required by module bundles) -ln -sf /lifeforge/packages/lifeforge-server-utils /lifeforge/node_modules/@lifeforge/server-utils +ln -sf /lifeforge/packages/server-utils /lifeforge/node_modules/@lifeforge/server-utils # Check if modules are mounted if [ -d "/lifeforge/apps" ] && [ "$(ls -A /lifeforge/apps 2>/dev/null)" ]; then diff --git a/packages/configs/src/client-vite.config.ts b/packages/configs/src/client-vite.config.ts new file mode 100644 index 000000000..98061ffb1 --- /dev/null +++ b/packages/configs/src/client-vite.config.ts @@ -0,0 +1,131 @@ +// import MillionLint from '@million/lint' +import federation from '@originjs/vite-plugin-federation' +import { vanillaExtractPlugin } from '@vanilla-extract/vite-plugin' +import react from '@vitejs/plugin-react' +import path from 'node:path' +import { type UserConfig, defineConfig } from 'vite' +import { customResolver } from './resolver' + +const ReactCompilerConfig = { + sources: () => { + return true + } +} + +export const SHARED_PACKAGES = { + '@lifeforge/shared': { + aliasRegex: /^@lifeforge\/shared$/, + entryPoint: '../shared/src/index.ts' + }, + '@lifeforge/federation': { + aliasRegex: /^@lifeforge\/federation$/, + entryPoint: '../packages/federation/src/index.ts' + }, + '@lifeforge/ui': { + aliasRegex: /^@lifeforge\/ui$/, + entryPoint: '../packages/ui/src/index.ts' + } +} + +/** + * Creates the standard client/host Vite configuration for LifeForge. + */ +export function defineClientConfig(dirname: string) { + const aliasList = [ + ...Object.entries(SHARED_PACKAGES).map(([, { aliasRegex, entryPoint }]) => ({ + find: aliasRegex, + replacement: path.resolve(dirname, entryPoint) + })), + { find: '@modules', replacement: path.resolve(dirname, '../apps') }, + { + find: '@', + replacement: '@', + customResolver + } + ] + + return defineConfig(({ command }) => { + const isDev = command === 'serve' + + const sharedAliases = new Set( + Object.values(SHARED_PACKAGES).map(p => p.aliasRegex.toString()) + ) + + const activeAlias = isDev + ? aliasList + : aliasList.filter(a => !sharedAliases.has(a.find.toString())) + + return { + envDir: path.resolve(dirname, '../env'), + plugins: [ + // MillionLint.vite({}), + react({ + babel: { + plugins: [['babel-plugin-react-compiler', ReactCompilerConfig]] + } + }), + vanillaExtractPlugin(), + federation({ + name: 'host', + remotes: { + None: '' + }, + shared: [ + 'react', + 'react-dom', + '@tanstack/react-query', + 'i18next', + 'react-i18next', + ...Object.keys(SHARED_PACKAGES) + ] + }) + ], + server: { + fs: { + strict: true + }, + watch: { + ignored: ['**/node_modules/**', '**/.git/**'] + } + }, + resolve: { + alias: activeAlias + }, + build: { + commonjsOptions: { + transformMixedEsModules: true + }, + target: 'esnext', + sourcemap: false, + rollupOptions: { + output: { + experimentalMinChunkSize: 5000 + } + } + }, + optimizeDeps: { + exclude: Object.keys(SHARED_PACKAGES), + esbuildOptions: { + sourcemap: false, + target: 'esnext' + } + }, + css: { + postcss: { + plugins: [ + { + postcssPlugin: 'internal:charset-removal', + AtRule: { + charset: atRule => { + if (atRule.name === 'charset') { + atRule.remove() + } + } + } + } + ] + } + } + } + }) +} diff --git a/packages/configs/src/index.ts b/packages/configs/src/index.ts new file mode 100644 index 000000000..3240d5be4 --- /dev/null +++ b/packages/configs/src/index.ts @@ -0,0 +1,3 @@ +export { defineModuleConfig } from './module-vite.config' +export { defineClientConfig, SHARED_PACKAGES } from './client-vite.config' +export { customResolver } from './resolver' diff --git a/packages/configs/src/module-vite.config.ts b/packages/configs/src/module-vite.config.ts new file mode 100644 index 000000000..a03dbc5de --- /dev/null +++ b/packages/configs/src/module-vite.config.ts @@ -0,0 +1,109 @@ +import federation from '@originjs/vite-plugin-federation' +import react from '@vitejs/plugin-react' +import path from 'node:path' +import { type UserConfig, defineConfig, loadEnv, mergeConfig } from 'vite' + +interface ModuleConfigOptions { + dirname: string + pkg: { + name: string + [key: string]: any + } +} + +/** + * Creates a standard Vite configuration for LifeForge modules. + * Supports custom overrides via the second parameter. + */ +export function defineModuleConfig( + { dirname, pkg }: ModuleConfigOptions, + overrides: UserConfig | ((env: any) => UserConfig) = {} +) { + const isDocker = process.env.DOCKER_BUILD === 'true' + const outDir = isDocker ? 'dist-docker' : 'dist' + const moduleName = pkg.name.replace('@lifeforge/', '') + + return defineConfig((configEnv) => { + const isDev = configEnv.command === 'serve' + + // 1. Resolve environment variables natively from the root env folder + const envDir = path.resolve(dirname, '../../../env') + const env = loadEnv(configEnv.mode, envDir, '') + const apiHost = isDocker ? '/api' : env.VITE_API_HOST + + if (!apiHost) { + throw new Error('VITE_API_HOST is not defined') + } + + // 2. Base default configuration + const baseConfig: UserConfig = { + base: `${apiHost}/modules/${moduleName}/`, + envDir, + plugins: [ + react(), + federation({ + name: moduleName, + filename: 'remoteEntry.js', + exposes: { + './Manifest': './manifest.ts' + }, + shared: { + react: { generate: false }, + 'react-dom': { generate: false }, + '@lifeforge/shared': { generate: false }, + '@lifeforge/federation': { generate: false }, + '@lifeforge/ui': { generate: false }, + 'react-i18next': { generate: false }, + i18next: { generate: false }, + '@tanstack/react-query': { generate: false } + } + }) + ], + resolve: { + alias: [ + ...(isDev + ? [ + { + find: /^@lifeforge\/shared$/, + replacement: path.resolve(dirname, '../../../shared/src/index.ts') + }, + { + find: /^@lifeforge\/federation$/, + replacement: path.resolve( + dirname, + '../../../packages/federation/src/index.ts' + ) + }, + { + find: /^@lifeforge\/ui$/, + replacement: path.resolve( + dirname, + '../../../packages/ui/src/index.ts' + ) + } + ] + : []), + { + find: /^@\/manifest$/, + replacement: path.resolve(dirname, './manifest.ts') + }, + { find: /^@\/(.*)$/, replacement: path.resolve(dirname, './src/$1') }, + { find: /^@$/, replacement: path.resolve(dirname, './src/index') } + ] + }, + build: { + outDir, + target: 'esnext', + modulePreload: false + } + } + + // 3. Resolve custom overrides if they are passed as a function + const resolvedOverrides = typeof overrides === 'function' + ? overrides(configEnv) + : overrides + + // 4. Merge base configuration with the module-specific overrides + return mergeConfig(baseConfig, resolvedOverrides) + }) +} diff --git a/packages/configs/src/resolver.ts b/packages/configs/src/resolver.ts new file mode 100644 index 000000000..2deb4fbc4 --- /dev/null +++ b/packages/configs/src/resolver.ts @@ -0,0 +1,50 @@ +import fs from 'node:fs' +import path from 'node:path' + +/** + * Custom resolver for Vite to resolve '@/' imports within a monorepo setup. + * Supports resolving from the client src directory, client root for manifest files, + * and falls back to package src directories. + */ +export function customResolver(id: string, importer: string | undefined): string | null { + if (!importer) { + return null + } + + let rootDir: string + const clientMatch = importer.match(/(.+\/client)/) + if (clientMatch) { + const clientDir = clientMatch[1] + rootDir = + id === '@/manifest' || id === '@/manifest.ts' + ? clientDir + : `${clientDir}/src` + } else { + const srcMatch = importer.match(/(.+\/src)/) + if (!srcMatch) { + return null + } + rootDir = srcMatch[1] + } + + const basePath = path.resolve(rootDir, id.slice(2)) + const candidates = [ + `${basePath}.tsx`, + `${basePath}.ts`, + `${basePath}.json`, + path.resolve(basePath, 'index.tsx'), + path.resolve(basePath, 'index.ts'), + basePath + ] + + for (const candidate of candidates) { + if (fs.existsSync(candidate)) { + return candidate + } + } + + console.log( + `[vite] failed to resolve import "${id}" from "${importer}"` + ) + return null +} diff --git a/packages/configs/tsconfig.json b/packages/configs/tsconfig.json new file mode 100644 index 000000000..2f8537a84 --- /dev/null +++ b/packages/configs/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig/base.json", + "compilerOptions": { + "declaration": true, + "rootDir": "./src", + "outDir": "./dist", + "noEmit": false + }, + "include": ["src/**/*.ts"] +} diff --git a/packages/configs/tsconfig/base.json b/packages/configs/tsconfig/base.json new file mode 100644 index 000000000..f8a7f403c --- /dev/null +++ b/packages/configs/tsconfig/base.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "lib": ["ESNext", "DOM", "DOM.Iterable"], + "target": "ESNext", + "module": "ESNext", + "moduleDetection": "force", + "jsx": "react-jsx", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "verbatimModuleSyntax": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noFallthroughCasesInSwitch": true, + "experimentalDecorators": true, + "skipLibCheck": true, + "noUnusedLocals": false, + "noUnusedParameters": false, + "noPropertyAccessFromIndexSignature": false + } +} diff --git a/packages/configs/tsconfig/module.json b/packages/configs/tsconfig/module.json new file mode 100644 index 000000000..6b71dce96 --- /dev/null +++ b/packages/configs/tsconfig/module.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "jsx": "react-jsx", + "target": "ES2020", + "lib": ["ES2020", "DOM", "DOM.Iterable", "ES2024.Object"], + "module": "ESNext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "verbatimModuleSyntax": true, + "composite": true, + "noEmit": true, + "skipLibCheck": true, + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "useDefineForClassFields": true, + "noFallthroughCasesInSwitch": true + } +} diff --git a/packages/configs/vite.config.ts b/packages/configs/vite.config.ts new file mode 100644 index 000000000..dd45f0b80 --- /dev/null +++ b/packages/configs/vite.config.ts @@ -0,0 +1,25 @@ +import { defineConfig } from 'vite' +import path from 'node:path' + +export default defineConfig({ + build: { + lib: { + entry: path.resolve(__dirname, 'src/index.ts'), + formats: ['es'], + fileName: 'index' + }, + rollupOptions: { + external: [ + 'node:path', + 'node:fs', + 'vite', + '@originjs/vite-plugin-federation', + '@vitejs/plugin-react', + '@vanilla-extract/vite-plugin' + ] + }, + outDir: 'dist', + minify: false, + sourcemap: true + } +}) diff --git a/shared/src/api/core/createForgeModuleClient.ts b/packages/federation/src/api/createForgeModuleClient.ts similarity index 70% rename from shared/src/api/core/createForgeModuleClient.ts rename to packages/federation/src/api/createForgeModuleClient.ts index 9e7076edc..2d153ccb3 100644 --- a/shared/src/api/core/createForgeModuleClient.ts +++ b/packages/federation/src/api/createForgeModuleClient.ts @@ -1,6 +1,6 @@ -import type { ModuleConfig } from '../../interfaces/module_config.types' -import type { ProxyTree } from '../typescript/forge_proxy.types' -import createForgeProxy from './createForgeProxy' +import { createForgeProxy } from '@lifeforge/shared' +import type { ProxyTree } from '@lifeforge/shared' +import type { ModuleConfig } from '../interfaces/module_config.types' /** * Wraps a module configuration and automatically appends a type-safe `forgeAPI` proxy client diff --git a/packages/federation/src/index.ts b/packages/federation/src/index.ts new file mode 100644 index 000000000..32f3a3872 --- /dev/null +++ b/packages/federation/src/index.ts @@ -0,0 +1,36 @@ +export type { + ModuleConfig, + ModuleCategory +} from './interfaces/module_config.types' + +export { + moduleConfigSchema +} from './interfaces/module_config.types' + +export { default as createForgeModuleClient } from './api/createForgeModuleClient' + +export { + default as FederationProvider, + useFederation, + SYSTEM_CATEGORIES +} from './providers/FederationProvider' + +export { + default as loadModules +} from './loaders/loadModules' + +export { + loadModuleConfig, + fetchModuleManifest, + type FederatedModule +} from './loaders/loadModuleConfig' + +export { + default as loadCoreModules +} from './loaders/loadCoreModules' + +export { + sortRoutes, + fetchCategoryOrder, + type CategoryOrder +} from './utils/sortRoutes' diff --git a/shared/src/interfaces/module_config.types.ts b/packages/federation/src/interfaces/module_config.types.ts similarity index 62% rename from shared/src/interfaces/module_config.types.ts rename to packages/federation/src/interfaces/module_config.types.ts index 0465085da..30e995c3e 100644 --- a/shared/src/interfaces/module_config.types.ts +++ b/packages/federation/src/interfaces/module_config.types.ts @@ -1,7 +1,6 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import z from 'zod' +import { z } from 'zod' -import type WidgetConfig from './widget_config.types' +import type { WidgetConfig } from '@lifeforge/shared' export interface ModuleConfig { provider?: React.LazyExoticComponent> @@ -35,10 +34,7 @@ export const moduleConfigSchema: z.ZodType = z.object({ .optional(), hidden: z.boolean().optional(), disabled: z - .union([ - z.boolean(), - z.custom<() => Promise>(val => typeof val === 'function') - ]) + .union([z.boolean(), z.custom<() => Promise>(val => typeof val === 'function')]) .optional(), clearQueryOnUnmount: z.boolean().optional(), contract: z.any().optional(), @@ -54,39 +50,12 @@ export const moduleConfigSchema: z.ZodType = z.object({ .optional() }) -export const packageJSONSchema = z.object({ - name: z.string(), - displayName: z.string(), - version: z.string(), - description: z.string(), - author: z.string(), - scripts: z - .object({ - types: z.string() - }) - .optional(), - dependencies: z.record(z.string(), z.string()).optional(), - devDependencies: z.record(z.string(), z.string()).optional(), - lifeforge: z.object({ - icon: z.string(), - category: z.string(), - APIKeyAccess: z - .record( - z.string(), - z.object({ - usage: z.string(), - required: z.boolean() - }) - ) - .optional() - }) -}) export interface ModuleCategory { title: string items: (ModuleConfig & { name: string - moduleId: string + moduleId?: string displayName: string version: string author: string diff --git a/packages/federation/src/loaders/loadCoreModules.ts b/packages/federation/src/loaders/loadCoreModules.ts new file mode 100644 index 000000000..7e012eb76 --- /dev/null +++ b/packages/federation/src/loaders/loadCoreModules.ts @@ -0,0 +1,8 @@ +import type { ModuleCategory } from '../interfaces/module_config.types' + +/** + * Loads core modules statically + */ +export default function loadCoreModules(): ModuleCategory['items'][number][] { + return [] +} diff --git a/client/src/federation/loaders/loadModuleConfig.ts b/packages/federation/src/loaders/loadModuleConfig.ts similarity index 77% rename from client/src/federation/loaders/loadModuleConfig.ts rename to packages/federation/src/loaders/loadModuleConfig.ts index fa3648c9f..32086d956 100644 --- a/client/src/federation/loaders/loadModuleConfig.ts +++ b/packages/federation/src/loaders/loadModuleConfig.ts @@ -1,28 +1,28 @@ +import { globalProxyRegistry } from '@lifeforge/shared' import { - __federation_method_getRemote as getRemote, - __federation_method_setRemote as setRemote, - __federation_method_unwrapDefault as unwrapModule - // @ts-expect-error - Virtual federation methods -} from 'virtual:__federation__' - -import { - type InferOutput, type ModuleCategory, type ModuleConfig, - globalProxyRegistry, moduleConfigSchema -} from '@lifeforge/shared' +} from '../interfaces/module_config.types' -import forgeAPI from '@/forgeAPI' - -type FederatedModule = InferOutput< - typeof forgeAPI.modules.manifest ->['modules'][number] +export interface FederatedModule { + name: string + displayName: string + version: string + description: string + author: string + icon: string + category: string + remoteEntryUrl: string + isDevMode: boolean + APIKeyAccess?: Record + moduleId: string +} /** * Fetches module manifest from the server */ -export async function fetchModuleManifest(): Promise { +export async function fetchModuleManifest(forgeAPI: any): Promise { try { const { modules } = await forgeAPI.modules.manifest.query() @@ -38,16 +38,12 @@ export async function fetchModuleManifest(): Promise { * Maps module short name to import function for dev mode * Uses Vite's glob import for dynamic loading from apps directory */ -const devModeImports = import.meta.glob<{ default: ModuleConfig }>( - '../../../../apps/*/client/manifest.ts', - { eager: false } -) - /** * Gets the dev mode import function for a module */ function getDevModeImport( - moduleName: string + moduleName: string, + devModeImports: Record Promise<{ default: ModuleConfig }>> ): (() => Promise<{ default: ModuleConfig }>) | null { // Module names are like "lifeforge--music" or "jiahuiiiii--stock" // The glob path is "../../apps/lifeforge--music/client/manifest.ts" @@ -66,13 +62,14 @@ function getDevModeImport( * Loads a module config - either from dev source or federation bundle */ export async function loadModuleConfig( - mod: FederatedModule + mod: FederatedModule, + devModeImports: Record Promise<{ default: ModuleConfig }>> = {} ): Promise { let unwrapped: ModuleConfig // Dev mode: import directly from source for hot-reload if (import.meta.env.DEV && mod.isDevMode) { - const devImport = getDevModeImport(mod.name) + const devImport = getDevModeImport(mod.name, devModeImports) if (devImport) { const devModule = await devImport() @@ -90,7 +87,6 @@ export async function loadModuleConfig( } const validation = moduleConfigSchema.safeParse(unwrapped) - if (!validation.success) { throw new Error( `Module configuration validation failed for ${mod.name}: ${validation.error.message}` @@ -133,6 +129,12 @@ export async function loadModuleConfig( async function loadFromFederation(mod: FederatedModule): Promise { const remoteName = mod.name.replace(/-+/g, '_') + const { + __federation_method_setRemote: setRemote, + __federation_method_getRemote: getRemote, + __federation_method_unwrapDefault: unwrapModule + } = await import('virtual:__federation__') + setRemote(remoteName, { url: `${import.meta.env.VITE_API_HOST}${mod.remoteEntryUrl}`, format: 'esm', diff --git a/client/src/federation/loaders/loadModules.ts b/packages/federation/src/loaders/loadModules.ts similarity index 78% rename from client/src/federation/loaders/loadModules.ts rename to packages/federation/src/loaders/loadModules.ts index fd5350f53..26385008c 100644 --- a/client/src/federation/loaders/loadModules.ts +++ b/packages/federation/src/loaders/loadModules.ts @@ -1,5 +1,4 @@ -import type { ModuleCategory } from '@lifeforge/shared' - +import type { ModuleCategory, ModuleConfig } from '../interfaces/module_config.types' import { type CategoryOrder, fetchCategoryOrder, @@ -21,7 +20,10 @@ function addToRoute( const categoryIndex = routes.findIndex(cat => cat.title === category) if (categoryIndex > -1) { - routes[categoryIndex].items.push(moduleConfig) + const cat = routes[categoryIndex] + if (cat) { + cat.items.push(moduleConfig) + } } else { routes.push({ title: category, @@ -35,7 +37,11 @@ function addToRoute( * Loads core modules (static) and federated modules (dynamic) from the server * Collects providers from module manifests */ -export default async function loadModules(): Promise<{ +export default async function loadModules( + forgeAPI: any, + coreModules: ModuleCategory['items'][number][] = [], + devModeImports: Record Promise<{ default: ModuleConfig }>> = {} +): Promise<{ routes: ModuleCategory[] globalProviders: GlobalProviderComponent[] categoryTranslations: CategoryOrder @@ -44,9 +50,6 @@ export default async function loadModules(): Promise<{ const globalProviders: GlobalProviderComponent[] = [] - // Load core modules (static imports) - const coreModules = loadCoreModules() - for (const mod of coreModules) { addToRoute(ROUTES, mod.category, mod) @@ -58,13 +61,13 @@ export default async function loadModules(): Promise<{ // Fetch federated modules and category order (which includes translations) const [serverManifest, categoryOrder] = await Promise.all([ - fetchModuleManifest(), - fetchCategoryOrder() + fetchModuleManifest(forgeAPI), + fetchCategoryOrder(forgeAPI) ]) for (const mod of serverManifest) { try { - const moduleConfig = await loadModuleConfig(mod) + const moduleConfig = await loadModuleConfig(mod, devModeImports) addToRoute(ROUTES, mod.category, moduleConfig) diff --git a/shared/src/providers/FederationProvider.tsx b/packages/federation/src/providers/FederationProvider.tsx similarity index 97% rename from shared/src/providers/FederationProvider.tsx rename to packages/federation/src/providers/FederationProvider.tsx index 4cdaca294..c84cab97c 100644 --- a/shared/src/providers/FederationProvider.tsx +++ b/packages/federation/src/providers/FederationProvider.tsx @@ -1,6 +1,6 @@ import { createContext, useContext, useMemo, useRef, useState } from 'react' -import type { ModuleCategory } from '..' +import type { ModuleCategory } from '../interfaces/module_config.types' export const SYSTEM_CATEGORIES = [ '', diff --git a/packages/federation/src/types/virtual.d.ts b/packages/federation/src/types/virtual.d.ts new file mode 100644 index 000000000..28a355bfd --- /dev/null +++ b/packages/federation/src/types/virtual.d.ts @@ -0,0 +1,5 @@ +declare module 'virtual:__federation__' { + export const __federation_method_getRemote: any + export const __federation_method_setRemote: any + export const __federation_method_unwrapDefault: any +} diff --git a/client/src/federation/utils/sortRoutes.ts b/packages/federation/src/utils/sortRoutes.ts similarity index 90% rename from client/src/federation/utils/sortRoutes.ts rename to packages/federation/src/utils/sortRoutes.ts index dd8e09498..c6c75d97c 100644 --- a/client/src/federation/utils/sortRoutes.ts +++ b/packages/federation/src/utils/sortRoutes.ts @@ -1,13 +1,12 @@ -import { type ModuleCategory, SYSTEM_CATEGORIES } from '@lifeforge/shared' - -import forgeAPI from '@/forgeAPI' +import type { ModuleCategory } from '../interfaces/module_config.types' +import { SYSTEM_CATEGORIES } from '../providers/FederationProvider' export type CategoryOrder = Record> /** * Fetches category order (with translations) from the server */ -export async function fetchCategoryOrder(): Promise { +export async function fetchCategoryOrder(forgeAPI: any): Promise { try { return (await forgeAPI.modules.categories.list.query()) ?? {} } catch (e) { diff --git a/packages/federation/tsconfig.json b/packages/federation/tsconfig.json new file mode 100644 index 000000000..dade79589 --- /dev/null +++ b/packages/federation/tsconfig.json @@ -0,0 +1,19 @@ +{ + "extends": "@lifeforge/configs/tsconfig/base.json", + "compilerOptions": { + "lib": ["ESNext", "DOM"], + "target": "ESNext", + "module": "ESNext", + "declaration": true, + "rootDir": "./src", + "outDir": "./dist", + "noEmit": false, + "strict": true, + "skipLibCheck": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedIndexedAccess": true, + "types": ["vite/client"] + }, + "include": ["./src/**/*"], + "exclude": ["dist", "node_modules"] +} diff --git a/packages/lifeforge-log/package.json b/packages/lifeforge-log/package.json deleted file mode 100644 index 29062cebd..000000000 --- a/packages/lifeforge-log/package.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "@lifeforge/log", - "version": "0.1.0", - "description": "Unified logging package for LifeForge ecosystem", - "type": "module", - "main": "./dist/index.js", - "types": "./dist/index.d.ts", - "exports": { - ".": { - "types": "./dist/index.d.ts", - "import": "./dist/index.js" - }, - "./cli": { - "types": "./dist/loggers/cliLogger.d.ts", - "import": "./dist/loggers/cliLogger.js" - } - }, - "scripts": { - "build": "bun build ./src/index.ts ./src/loggers/cliLogger.ts --outdir=dist --target=node && bun tsc --project tsconfig.json", - "test": "vitest run", - "test:watch": "vitest" - }, - "dependencies": { - "pino": "^9.6.0", - "pino-pretty": "^13.0.0", - "rotating-file-stream": "^3.2.7", - "chalk": "^5.4.0" - }, - "devDependencies": { - "@types/node": "^25.0.6", - "typescript": "^5.9.0", - "vitest": "^4.0.0" - } -} diff --git a/packages/lifeforge-server-utils/package.json b/packages/lifeforge-server-utils/package.json deleted file mode 100644 index 4b401e644..000000000 --- a/packages/lifeforge-server-utils/package.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "name": "@lifeforge/server-utils", - "version": "0.0.1", - "description": "Server SDK for LifeForge modules", - "type": "module", - "main": "./dist/index.js", - "types": "./dist/index.d.ts", - "exports": { - ".": { - "types": "./dist/index.d.ts", - "require": "./dist/index.js", - "import": "./dist/index.js", - "default": "./dist/index.js" - } - }, - "scripts": { - "build": "rm -rf dist && bun build ./src/index.ts --outdir=dist --target=node && bun tsc --emitDeclarationOnly", - "types": "bun tsc --emitDeclarationOnly" - }, - "dependencies": { - "chalk": "^5.6.2", - "crypto-js": "^4.2.0", - "express": "^4.21.2", - "form-data": "^4.0.0", - "groq-sdk": "^0.20.0", - "ical.js": "^2.1.0", - "lodash": "^4.17.21", - "multer": "^1.4.5-lts.1", - "openai": "^4.81.0", - "pdf2pic": "^3.1.5", - "@lifeforge/shared": "workspace:*", - "socket.io": "^4.8.3", - "tesseract.js": "^5.1.1", - "uuid": "^11.1.0", - "zod": "4.3.5", - "@lifeforge/log": "workspace:*" - }, - "devDependencies": { - "@types/crypto-js": "^4.2.2", - "@types/express": "^4.17.23", - "@types/express-serve-static-core": "4", - "@types/lodash": "^4.17.21", - "@types/multer": "^1.4.13", - "typescript": "^5.8.3", - "vitest": "^4.1.7" - }, - "peerDependencies": { - "pocketbase": "^0.26.2" - } -} diff --git a/packages/lifeforge-log/src/index.ts b/packages/log/src/index.ts similarity index 100% rename from packages/lifeforge-log/src/index.ts rename to packages/log/src/index.ts diff --git a/packages/lifeforge-log/src/loggers/cliLogger.ts b/packages/log/src/loggers/cliLogger.ts similarity index 100% rename from packages/lifeforge-log/src/loggers/cliLogger.ts rename to packages/log/src/loggers/cliLogger.ts diff --git a/packages/lifeforge-log/src/loggers/logger.ts b/packages/log/src/loggers/logger.ts similarity index 100% rename from packages/lifeforge-log/src/loggers/logger.ts rename to packages/log/src/loggers/logger.ts diff --git a/packages/lifeforge-log/src/tests/logger.test.ts b/packages/log/src/tests/logger.test.ts similarity index 100% rename from packages/lifeforge-log/src/tests/logger.test.ts rename to packages/log/src/tests/logger.test.ts diff --git a/packages/lifeforge-log/src/utils/config.ts b/packages/log/src/utils/config.ts similarity index 100% rename from packages/lifeforge-log/src/utils/config.ts rename to packages/log/src/utils/config.ts diff --git a/packages/lifeforge-log/src/utils/fileTransport.ts b/packages/log/src/utils/fileTransport.ts similarity index 100% rename from packages/lifeforge-log/src/utils/fileTransport.ts rename to packages/log/src/utils/fileTransport.ts diff --git a/packages/lifeforge-log/tsconfig.json b/packages/log/tsconfig.json similarity index 100% rename from packages/lifeforge-log/tsconfig.json rename to packages/log/tsconfig.json diff --git a/packages/lifeforge-server-utils/src/index.ts b/packages/server-utils/src/index.ts similarity index 100% rename from packages/lifeforge-server-utils/src/index.ts rename to packages/server-utils/src/index.ts diff --git a/packages/lifeforge-server-utils/src/routes/ClientError.ts b/packages/server-utils/src/routes/ClientError.ts similarity index 100% rename from packages/lifeforge-server-utils/src/routes/ClientError.ts rename to packages/server-utils/src/routes/ClientError.ts diff --git a/packages/lifeforge-server-utils/src/routes/forgeContract.test.ts b/packages/server-utils/src/routes/forgeContract.test.ts similarity index 100% rename from packages/lifeforge-server-utils/src/routes/forgeContract.test.ts rename to packages/server-utils/src/routes/forgeContract.test.ts diff --git a/packages/lifeforge-server-utils/src/routes/forgeContract.ts b/packages/server-utils/src/routes/forgeContract.ts similarity index 100% rename from packages/lifeforge-server-utils/src/routes/forgeContract.ts rename to packages/server-utils/src/routes/forgeContract.ts diff --git a/packages/lifeforge-server-utils/src/routes/forgeRouter.ts b/packages/server-utils/src/routes/forgeRouter.ts similarity index 100% rename from packages/lifeforge-server-utils/src/routes/forgeRouter.ts rename to packages/server-utils/src/routes/forgeRouter.ts diff --git a/packages/lifeforge-server-utils/src/typescript/core/core_context.types.ts b/packages/server-utils/src/typescript/core/core_context.types.ts similarity index 100% rename from packages/lifeforge-server-utils/src/typescript/core/core_context.types.ts rename to packages/server-utils/src/typescript/core/core_context.types.ts diff --git a/packages/lifeforge-server-utils/src/typescript/core/forge_contract.types.ts b/packages/server-utils/src/typescript/core/forge_contract.types.ts similarity index 100% rename from packages/lifeforge-server-utils/src/typescript/core/forge_contract.types.ts rename to packages/server-utils/src/typescript/core/forge_contract.types.ts diff --git a/packages/lifeforge-server-utils/src/typescript/core/tempfile_manager.types.ts b/packages/server-utils/src/typescript/core/tempfile_manager.types.ts similarity index 100% rename from packages/lifeforge-server-utils/src/typescript/core/tempfile_manager.types.ts rename to packages/server-utils/src/typescript/core/tempfile_manager.types.ts diff --git a/packages/lifeforge-server-utils/src/typescript/pb/PBService.interface.ts b/packages/server-utils/src/typescript/pb/PBService.interface.ts similarity index 100% rename from packages/lifeforge-server-utils/src/typescript/pb/PBService.interface.ts rename to packages/server-utils/src/typescript/pb/PBService.interface.ts diff --git a/packages/lifeforge-server-utils/src/typescript/pb/pb_service.types.ts b/packages/server-utils/src/typescript/pb/pb_service.types.ts similarity index 100% rename from packages/lifeforge-server-utils/src/typescript/pb/pb_service.types.ts rename to packages/server-utils/src/typescript/pb/pb_service.types.ts diff --git a/packages/lifeforge-server-utils/src/typescript/response/response.types.ts b/packages/server-utils/src/typescript/response/response.types.ts similarity index 100% rename from packages/lifeforge-server-utils/src/typescript/response/response.types.ts rename to packages/server-utils/src/typescript/response/response.types.ts diff --git a/packages/lifeforge-server-utils/src/typescript/response/response_helpers.types.ts b/packages/server-utils/src/typescript/response/response_helpers.types.ts similarity index 100% rename from packages/lifeforge-server-utils/src/typescript/response/response_helpers.types.ts rename to packages/server-utils/src/typescript/response/response_helpers.types.ts diff --git a/packages/lifeforge-server-utils/src/typescript/standalone/location.types.ts b/packages/server-utils/src/typescript/standalone/location.types.ts similarity index 100% rename from packages/lifeforge-server-utils/src/typescript/standalone/location.types.ts rename to packages/server-utils/src/typescript/standalone/location.types.ts diff --git a/packages/lifeforge-server-utils/src/typescript/standalone/media.types.ts b/packages/server-utils/src/typescript/standalone/media.types.ts similarity index 100% rename from packages/lifeforge-server-utils/src/typescript/standalone/media.types.ts rename to packages/server-utils/src/typescript/standalone/media.types.ts diff --git a/packages/lifeforge-server-utils/src/utils/extractProjectRoot.ts b/packages/server-utils/src/utils/extractProjectRoot.ts similarity index 100% rename from packages/lifeforge-server-utils/src/utils/extractProjectRoot.ts rename to packages/server-utils/src/utils/extractProjectRoot.ts diff --git a/packages/lifeforge-server-utils/src/utils/getCallerModuleId.ts b/packages/server-utils/src/utils/getCallerModuleId.ts similarity index 100% rename from packages/lifeforge-server-utils/src/utils/getCallerModuleId.ts rename to packages/server-utils/src/utils/getCallerModuleId.ts diff --git a/packages/lifeforge-server-utils/src/utils/outputStatus.ts b/packages/server-utils/src/utils/outputStatus.ts similarity index 100% rename from packages/lifeforge-server-utils/src/utils/outputStatus.ts rename to packages/server-utils/src/utils/outputStatus.ts diff --git a/packages/lifeforge-server-utils/src/utils/schemaUtils.ts b/packages/server-utils/src/utils/schemaUtils.ts similarity index 100% rename from packages/lifeforge-server-utils/src/utils/schemaUtils.ts rename to packages/server-utils/src/utils/schemaUtils.ts diff --git a/packages/lifeforge-server-utils/src/utils/writeContractFile.ts b/packages/server-utils/src/utils/writeContractFile.ts similarity index 100% rename from packages/lifeforge-server-utils/src/utils/writeContractFile.ts rename to packages/server-utils/src/utils/writeContractFile.ts diff --git a/packages/lifeforge-server-utils/tsconfig.json b/packages/server-utils/tsconfig.json similarity index 100% rename from packages/lifeforge-server-utils/tsconfig.json rename to packages/server-utils/tsconfig.json diff --git a/packages/ui/src/styles/index.css b/packages/ui/src/styles/index.css index 887e94525..f1c7d648d 100644 --- a/packages/ui/src/styles/index.css +++ b/packages/ui/src/styles/index.css @@ -1,5 +1,5 @@ @import '../../node_modules/react-medium-image-zoom/dist/styles.css'; -@import '../../node_modules/react-toastify/dist/ReactToastify.css'; +@import 'react-toastify/dist/ReactToastify.css'; @import '../../node_modules/react-tooltip/dist/react-tooltip.css'; @import '../../node_modules/react-virtualized/styles.css'; @import '../../node_modules/react-datepicker/dist/react-datepicker.css'; diff --git a/server/src/lib/modules/utils/scanFederatedModules.ts b/server/src/lib/modules/utils/scanFederatedModules.ts index 249b11a69..fb8a68b75 100644 --- a/server/src/lib/modules/utils/scanFederatedModules.ts +++ b/server/src/lib/modules/utils/scanFederatedModules.ts @@ -1,9 +1,35 @@ +import { generateModuleId } from '@functions/modules/loadModuleRoutes' import fs from 'fs' import path from 'path' +import { z } from 'zod' -import { packageJSONSchema } from '@lifeforge/shared' - -import { generateModuleId } from '@functions/modules/loadModuleRoutes' +export const packageJSONSchema = z.object({ + name: z.string(), + displayName: z.string(), + version: z.string(), + description: z.string(), + author: z.string(), + scripts: z + .object({ + types: z.string() + }) + .optional(), + dependencies: z.record(z.string(), z.string()).optional(), + devDependencies: z.record(z.string(), z.string()).optional(), + lifeforge: z.object({ + icon: z.string(), + category: z.string(), + APIKeyAccess: z + .record( + z.string(), + z.object({ + usage: z.string(), + required: z.boolean() + }) + ) + .optional() + }) +}) /** * Module manifest entry for federated modules diff --git a/server/tsconfig.json b/server/tsconfig.json index bf59cfff1..091b269ec 100644 --- a/server/tsconfig.json +++ b/server/tsconfig.json @@ -1,17 +1,9 @@ { + "extends": "@lifeforge/configs/tsconfig/base.json", "compilerOptions": { - "target": "ESNext", + "verbatimModuleSyntax": false, "outDir": "./dist", - "module": "ESNext", - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "strict": true, - "skipLibCheck": true, - "moduleResolution": "bundler", - "strictFunctionTypes": true, - "strictNullChecks": true, "allowUnusedLabels": false, - "experimentalDecorators": true, "emitDecoratorMetadata": true, "useDefineForClassFields": false, "noUnusedLocals": true, diff --git a/shared/src/index.ts b/shared/src/index.ts index b367f1632..cda8fa9c6 100644 --- a/shared/src/index.ts +++ b/shared/src/index.ts @@ -21,7 +21,6 @@ export { useMainSidebarState as useMainSidebarState } from './providers/SidebarS export { useAuth } from './providers/AuthProvider' export { useModuleSidebarState } from './providers/ModuleSidebarStateProvider' export { useModuleHeaderState } from './providers/ModuleHeaderStateProvider' -export { useFederation } from './providers/FederationProvider' export { default as AuthProvider } from './providers/AuthProvider' export { default as APIEndpointProvider } from './providers/APIEndpointProvider' export { default as PersonalizationProvider } from './providers/PersonalizationProvider' @@ -34,7 +33,6 @@ export { default as NuqsProvider } from './providers/NuqsProvider' export { default as EncryptionProvider } from './providers/EncryptionProvider' export { default as ModuleSidebarStateProvider } from './providers/ModuleSidebarStateProvider' export { default as ModuleHeaderStateProvider } from './providers/ModuleHeaderStateProvider' -export { default as FederationProvider } from './providers/FederationProvider' export { type SocketEvent, useSocketContext } from './providers/SocketProvider' // Useful hooks @@ -57,12 +55,8 @@ export { default as fetchAPI } from './utils/fetchAPI' export { default as getBrowserInfo } from './utils/getBrowserInfo' export { default as normalizeSubnamespace } from './utils/normalizeSubnamespace' export { default as parseCollectionName } from './utils/parseCollectionName' - -export { packageJSONSchema } from './interfaces/module_config.types' - // Forge API client and types export { default as createForgeProxy } from './api/core/createForgeProxy' -export { default as createForgeModuleClient } from './api/core/createForgeModuleClient' export { default as ForgeEndpoint } from './api/core/forgeEndpoint' export type { ProxyTree, @@ -75,12 +69,6 @@ export type { IDashboardLayout, IBackdropFilters } from './providers/PersonalizationProvider/interfaces/personalization_provider_interfaces' -export type { - ModuleConfig, - ModuleCategory -} from './interfaces/module_config.types' -export { moduleConfigSchema } from './interfaces/module_config.types' export type { default as WidgetConfig } from './interfaces/widget_config.types' export { widgetConfigSchema } from './interfaces/widget_config.types' export { globalProxyRegistry } from './api/core/registry' -export { SYSTEM_CATEGORIES } from './providers/FederationProvider' diff --git a/shared/tsconfig.json b/shared/tsconfig.json index e15e5d9d1..ada49013d 100644 --- a/shared/tsconfig.json +++ b/shared/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "../tsconfig.json", + "extends": "@lifeforge/configs/tsconfig/base.json", "compilerOptions": { // Environment setup "lib": ["ESNext", "DOM"], diff --git a/tools/src/commands/modules/functions/packageJSONSchema.ts b/tools/src/commands/modules/functions/packageJSONSchema.ts new file mode 100644 index 000000000..4e630537e --- /dev/null +++ b/tools/src/commands/modules/functions/packageJSONSchema.ts @@ -0,0 +1,29 @@ +import z from 'zod' + +export const packageJSONSchema = z.object({ + name: z.string(), + displayName: z.string(), + version: z.string(), + description: z.string(), + author: z.string(), + scripts: z + .object({ + types: z.string() + }) + .optional(), + dependencies: z.record(z.string(), z.string()).optional(), + devDependencies: z.record(z.string(), z.string()).optional(), + lifeforge: z.object({ + icon: z.string(), + category: z.string(), + APIKeyAccess: z + .record( + z.string(), + z.object({ + usage: z.string(), + required: z.boolean() + }) + ) + .optional() + }) +}) diff --git a/tools/src/commands/modules/functions/validateModuleAuthor.ts b/tools/src/commands/modules/functions/validateModuleAuthor.ts index 477547ac7..89779a9a0 100644 --- a/tools/src/commands/modules/functions/validateModuleAuthor.ts +++ b/tools/src/commands/modules/functions/validateModuleAuthor.ts @@ -6,11 +6,11 @@ import { validateMaintainerAccess } from '@/utils/github-cli' import logger from '@/utils/logger' import { checkAuth } from '@/utils/registry' +import { packageJSONSchema } from './packageJSONSchema' + export default async function validateModuleAuthor(modulePath: string) { const auth = await checkAuth() - const { packageJSONSchema } = await import('@lifeforge/shared') - const packageJson = z.safeParse( packageJSONSchema, JSON.parse(fs.readFileSync(path.join(modulePath, 'package.json'), 'utf-8')) diff --git a/tools/src/commands/modules/functions/validateModuleStructure.ts b/tools/src/commands/modules/functions/validateModuleStructure.ts index ae844684b..5943677d0 100644 --- a/tools/src/commands/modules/functions/validateModuleStructure.ts +++ b/tools/src/commands/modules/functions/validateModuleStructure.ts @@ -4,6 +4,8 @@ import z from 'zod' import logger from '@/utils/logger' +import { packageJSONSchema } from './packageJSONSchema' + const MODULE_STRUCTURE: Array<{ type: 'folder' | 'file' name: string @@ -36,8 +38,6 @@ const MODULE_STRUCTURE: Array<{ validate: async (content: string) => { const json = JSON.parse(content) - const { packageJSONSchema } = await import('@lifeforge/shared') - const result = z.safeParse(packageJSONSchema, json) return result.success diff --git a/tools/tsconfig.json b/tools/tsconfig.json index a77f6cfd4..e89e29499 100644 --- a/tools/tsconfig.json +++ b/tools/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "../tsconfig.json", + "extends": "@lifeforge/configs/tsconfig/base.json", "compilerOptions": { "rootDir": ".", "baseUrl": ".", diff --git a/tsconfig.eslint.json b/tsconfig.eslint.json index 78683fe83..4d3a36b2b 100644 --- a/tsconfig.eslint.json +++ b/tsconfig.eslint.json @@ -2,14 +2,17 @@ "extends": "./tsconfig.json", "include": [ "apps/**/*", - "packages/*/src", - "packages/*/.storybook", - "client/src", - "server/src", - "docs/src", - "shared/src", - "scripts/*", - "tools/src", - "tools/scripts" + "packages/**/*", + "client/**/*", + "server/**/*", + "shared/**/*", + "docs/**/*", + "scripts/**/*", + "tools/**/*" + ], + "exclude": [ + "**/node_modules", + "**/dist", + "**/dist-docker" ] -} +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index eb2ecc916..276ec88d8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,26 +1,3 @@ { - "compilerOptions": { - // Environment setup & latest features - "lib": ["ESNext", "DOM", "DOM.Iterable"], - "target": "ESNext", - "module": "ESNext", - "moduleDetection": "force", - "jsx": "react-jsx", - // Module resolution - "moduleResolution": "bundler", - "allowSyntheticDefaultImports": true, - "esModuleInterop": true, - "verbatimModuleSyntax": true, - // Strictness and best practices - "strict": true, - "forceConsistentCasingInFileNames": true, - "noFallthroughCasesInSwitch": true, - "experimentalDecorators": true, - // Output control - "skipLibCheck": true, - // Optional strict flags (disabled by default) - "noUnusedLocals": false, - "noUnusedParameters": false, - "noPropertyAccessFromIndexSignature": false - } + "extends": "@lifeforge/configs/tsconfig/base.json" }