From ec56a8bc857a74788df6523af25914da95c4c1d8 Mon Sep 17 00:00:00 2001 From: Kasper Fabricius Kristensen <45367945+kasperkristensen@users.noreply.github.com> Date: Tue, 11 Mar 2025 12:28:33 +0100 Subject: [PATCH] fix(medusa,utils,test-utils,types,framework,dashboard,admin-vite-plugin,admin-bundler): Fix broken plugin dependencies in development server (#11720) **What** - Reworks how admin extensions are loaded from plugins. - Reworks how extensions are managed internally in the dashboard project. **Why** - Previously we loaded extensions from plugins the same way we do for extension found in a users application. This being scanning the source code for possible extensions in `.medusa/server/src/admin`, and including any extensions that were discovered in the final virtual modules. - This was causing issues with how Vite optimizes dependencies, and would lead to CJS/ESM issues. Not sure of the exact cause of this, but the issue was pinpointed to Vite not being able to register correctly which dependencies to optimize when they were loaded through the virtual module from a plugin in `node_modules`. **What changed** - To circumvent the above issue we have changed to a different strategy for loading extensions from plugins. The changes are the following: - We now build plugins slightly different, if a plugin has admin extensions we now build those to `.medusa/server/src/admin/index.mjs` and `.medusa/server/src/admin/index.js` for a ESM and CJS build. - When determining how to load extensions from a source we follow these rules: - If the source has a `medusa-plugin-options.json` or is the root application we determine that it is a `local` extension source, and load extensions as previously through a virtual module. - If it has neither of the above, but has a `./admin` export in its package.json then we determine that it is a `package` extension, and we update the entry point for the dashboard to import the package and pass its extensions a long to the dashboard manager. **Changes required by plugin authors** - The change has no breaking changes, but requires plugin authors to update the `package.json` of their plugins to also include a `./admin` export. It should look like this: ```json { "name": "@medusajs/plugin", "version": "0.0.1", "description": "A starter for Medusa plugins.", "author": "Medusa (https://medusajs.com)", "license": "MIT", "files": [ ".medusa/server" ], "exports": { "./package.json": "./package.json", "./workflows": "./.medusa/server/src/workflows/index.js", "./.medusa/server/src/modules/*": "./.medusa/server/src/modules/*/index.js", "./modules/*": "./.medusa/server/src/modules/*/index.js", "./providers/*": "./.medusa/server/src/providers/*/index.js", "./*": "./.medusa/server/src/*.js", "./admin": { "import": "./.medusa/server/src/admin/index.mjs", "require": "./.medusa/server/src/admin/index.js", "default": "./.medusa/server/src/admin/index.js" } }, } ``` --- .changeset/cold-keys-press.md | 12 + packages/admin/admin-bundler/package.json | 8 +- .../src/{lib => commands}/build.ts | 2 +- .../src/{lib => commands}/develop.ts | 2 +- .../admin-bundler/src/commands/plugin.ts | 112 ++ .../src/{lib => commands}/serve.ts | 0 packages/admin/admin-bundler/src/entry.tsx | 15 - packages/admin/admin-bundler/src/index.css | 5 - packages/admin/admin-bundler/src/index.html | 16 - packages/admin/admin-bundler/src/index.ts | 8 +- .../admin/admin-bundler/src/lib/plugin.ts | 105 - .../src/plugins/clear-plugin-build.ts | 19 + .../src/plugins/inject-tailwindcss.ts | 96 + .../src/plugins/write-static-files.ts | 17 + packages/admin/admin-bundler/src/types.ts | 1 + .../src/{lib => utils}/config.ts | 59 +- .../src/utils/write-static-files.ts | 94 + .../admin/admin-vite-plugin/src/plugin.ts | 74 +- packages/admin/admin-vite-plugin/src/types.ts | 1 + .../generate-virtual-display-module.ts | 11 +- .../generate-virtual-form-module.ts | 27 +- .../generate-virtual-link-module.ts | 11 +- .../generate-virtual-menu-item-module.ts | 15 +- .../generate-virtual-route-module.ts | 11 +- .../generate-virtual-widget-module.ts | 11 +- packages/admin/dashboard/package.json | 1 - .../admin/dashboard/scripts/generate-types.js | 10 +- packages/admin/dashboard/src/app.tsx | 33 +- .../layout/main-layout/main-layout.tsx | 6 +- .../components/layout/nav-item/nav-item.tsx | 2 +- .../settings-layout/settings-layout.tsx | 5 +- .../dashboard-app.tsx} | 226 ++- .../form-extension-zone.tsx | 0 .../forms/form-extension-zone/index.ts | 0 .../forms/form-extension-zone/types.ts | 0 .../forms/form-extension-zone/utils.ts | 0 .../forms/hooks.tsx | 0 .../forms/index.ts | 0 .../{extensions => dashboard-app}/index.ts | 3 +- .../links/utils.ts | 0 .../dashboard-app/routes/get-route.map.tsx | 1735 +++++++++++++++++ .../routes/utils.ts | 7 +- .../{extensions => dashboard-app}/types.ts | 13 + .../dashboard-extension-manager/index.ts | 2 - .../dashboard-extension-context.tsx | 7 - .../dashboard-extension-provider.tsx | 18 - .../dashboard-extension-provider/index.ts | 2 - .../use-dashboard-extension.tsx | 12 - packages/admin/dashboard/src/index.ts | 2 + .../extension-provider/extension-context.tsx | 8 + .../extension-provider/extension-provider.tsx | 18 + .../src/providers/extension-provider/index.ts | 2 + .../extension-provider/use-extension.tsx | 10 + .../dashboard/src/providers/providers.tsx | 12 +- .../src/providers/router-provider/index.ts | 1 - .../router-provider/route-extensions.tsx | 13 - .../providers/router-provider/route-map.tsx | 1688 ---------------- .../router-provider/router-provider.tsx | 14 - .../router-provider/settings-extensions.tsx | 12 - .../api-key-management-detail.tsx | 4 +- .../api-key-management-list.tsx | 4 +- .../campaign-detail/campaign-detail.tsx | 4 +- .../campaigns/campaign-list/campaign-list.tsx | 4 +- .../category-detail/category-detail.tsx | 4 +- .../category-list/category-list.tsx | 4 +- .../collection-detail/collection-detail.tsx | 4 +- .../collection-list/collection-list.tsx | 4 +- .../customer-group-detail.tsx | 4 +- .../customer-group-list-table.tsx | 16 +- .../customer-group-list.tsx | 4 +- .../customer-detail/customer-detail.tsx | 4 +- .../customers/customer-list/customer-list.tsx | 4 +- .../inventory-detail/inventory-detail.tsx | 4 +- .../inventory-list/inventory-list.tsx | 4 +- .../location-detail/location-detail.tsx | 4 +- .../locations/location-list/location-list.tsx | 16 +- .../dashboard/src/routes/login/login.tsx | 4 +- .../orders/order-detail/order-detail.tsx | 4 +- .../routes/orders/order-list/order-list.tsx | 4 +- .../price-list-detail/price-list-detail.tsx | 4 +- .../price-list-list/price-list-list.tsx | 4 +- .../product-tag-detail/product-tag-detail.tsx | 4 +- .../product-tag-list/product-tag-list.tsx | 4 +- .../product-type-detail.tsx | 4 +- .../product-type-list/product-type-list.tsx | 4 +- .../product-variant-detail.tsx | 4 +- .../product-attributes-form.tsx | 6 +- .../product-create-details-form.tsx | 8 +- .../product-create-form.tsx | 8 +- .../product-create-organize-form.tsx | 8 +- .../product-attribute-section.tsx | 4 +- .../product-general-section.tsx | 4 +- .../product-organization-section.tsx | 4 +- .../products/product-detail/constants.ts | 2 +- .../product-detail/product-detail.tsx | 4 +- .../edit-product-form/edit-product-form.tsx | 10 +- .../products/product-list/product-list.tsx | 4 +- .../product-organization-form.tsx | 6 +- .../profile/profile-detail/profile-detail.tsx | 4 +- .../promotion-detail/promotion-detail.tsx | 4 +- .../promotion-list/promotions-list.tsx | 4 +- .../regions/region-detail/region-detail.tsx | 4 +- .../regions/region-list/region-list.tsx | 4 +- .../reservation-detail/reservation-detail.tsx | 6 +- .../reservation-list/reservation-list.tsx | 4 +- .../return-reason-list/return-reason-list.tsx | 4 +- .../sales-channel-detail.tsx | 4 +- .../sales-channel-list/sales-channel-list.tsx | 4 +- .../shipping-profile-detail.tsx | 4 +- .../shipping-profile-list.tsx | 4 +- .../index.ts | 0 .../store-currency-section.tsx | 18 +- .../store/store-detail/store-detail.tsx | 16 +- .../tax-region-detail/tax-region-detail.tsx | 4 +- .../tax-region-list/tax-region-list.tsx | 4 +- .../tax-region-detail.tsx | 4 +- .../routes/users/user-detail/user-detail.tsx | 4 +- .../src/routes/users/user-list/user-list.tsx | 4 +- .../workflow-detail.tsx | 4 +- .../workflow-execution-list.tsx | 4 +- packages/admin/dashboard/src/vite-env.d.ts | 3 + .../framework/src/build-tools/compiler.ts | 34 +- .../core/types/src/common/config-module.ts | 7 +- .../__tests__/get-resolved-plugins.spec.ts | 30 +- .../utils/src/common/get-resolved-plugins.ts} | 28 +- packages/core/utils/src/common/index.ts | 1 + .../src/medusa-test-runner-utils/use-db.ts | 12 +- packages/medusa/src/commands/db/generate.ts | 12 +- packages/medusa/src/commands/db/migrate.ts | 2 +- packages/medusa/src/commands/db/rollback.ts | 12 +- .../medusa/src/commands/db/run-scripts.ts | 2 +- packages/medusa/src/commands/db/sync-links.ts | 22 +- packages/medusa/src/loaders/admin.ts | 14 +- packages/medusa/src/loaders/index.ts | 2 +- yarn.lock | 101 +- 135 files changed, 2766 insertions(+), 2422 deletions(-) create mode 100644 .changeset/cold-keys-press.md rename packages/admin/admin-bundler/src/{lib => commands}/build.ts (88%) rename packages/admin/admin-bundler/src/{lib => commands}/develop.ts (97%) create mode 100644 packages/admin/admin-bundler/src/commands/plugin.ts rename packages/admin/admin-bundler/src/{lib => commands}/serve.ts (100%) delete mode 100644 packages/admin/admin-bundler/src/entry.tsx delete mode 100644 packages/admin/admin-bundler/src/index.css delete mode 100644 packages/admin/admin-bundler/src/index.html delete mode 100644 packages/admin/admin-bundler/src/lib/plugin.ts create mode 100644 packages/admin/admin-bundler/src/plugins/clear-plugin-build.ts create mode 100644 packages/admin/admin-bundler/src/plugins/inject-tailwindcss.ts create mode 100644 packages/admin/admin-bundler/src/plugins/write-static-files.ts rename packages/admin/admin-bundler/src/{lib => utils}/config.ts (61%) create mode 100644 packages/admin/admin-bundler/src/utils/write-static-files.ts rename packages/admin/dashboard/src/{extensions/dashboard-extension-manager/dashboard-extension-manager.tsx => dashboard-app/dashboard-app.tsx} (56%) rename packages/admin/dashboard/src/{extensions => dashboard-app}/forms/form-extension-zone/form-extension-zone.tsx (100%) rename packages/admin/dashboard/src/{extensions => dashboard-app}/forms/form-extension-zone/index.ts (100%) rename packages/admin/dashboard/src/{extensions => dashboard-app}/forms/form-extension-zone/types.ts (100%) rename packages/admin/dashboard/src/{extensions => dashboard-app}/forms/form-extension-zone/utils.ts (100%) rename packages/admin/dashboard/src/{extensions => dashboard-app}/forms/hooks.tsx (100%) rename packages/admin/dashboard/src/{extensions => dashboard-app}/forms/index.ts (100%) rename packages/admin/dashboard/src/{extensions => dashboard-app}/index.ts (70%) rename packages/admin/dashboard/src/{extensions => dashboard-app}/links/utils.ts (100%) create mode 100644 packages/admin/dashboard/src/dashboard-app/routes/get-route.map.tsx rename packages/admin/dashboard/src/{extensions => dashboard-app}/routes/utils.ts (98%) rename packages/admin/dashboard/src/{extensions => dashboard-app}/types.ts (87%) delete mode 100644 packages/admin/dashboard/src/extensions/dashboard-extension-manager/index.ts delete mode 100644 packages/admin/dashboard/src/extensions/dashboard-extension-provider/dashboard-extension-context.tsx delete mode 100644 packages/admin/dashboard/src/extensions/dashboard-extension-provider/dashboard-extension-provider.tsx delete mode 100644 packages/admin/dashboard/src/extensions/dashboard-extension-provider/index.ts delete mode 100644 packages/admin/dashboard/src/extensions/dashboard-extension-provider/use-dashboard-extension.tsx create mode 100644 packages/admin/dashboard/src/index.ts create mode 100644 packages/admin/dashboard/src/providers/extension-provider/extension-context.tsx create mode 100644 packages/admin/dashboard/src/providers/extension-provider/extension-provider.tsx create mode 100644 packages/admin/dashboard/src/providers/extension-provider/index.ts create mode 100644 packages/admin/dashboard/src/providers/extension-provider/use-extension.tsx delete mode 100644 packages/admin/dashboard/src/providers/router-provider/index.ts delete mode 100644 packages/admin/dashboard/src/providers/router-provider/route-extensions.tsx delete mode 100644 packages/admin/dashboard/src/providers/router-provider/route-map.tsx delete mode 100644 packages/admin/dashboard/src/providers/router-provider/router-provider.tsx delete mode 100644 packages/admin/dashboard/src/providers/router-provider/settings-extensions.tsx rename packages/admin/dashboard/src/routes/store/store-detail/components/store-currency-section/{store-currencies-section.tsx => }/index.ts (100%) rename packages/admin/dashboard/src/routes/store/store-detail/components/store-currency-section/{store-currencies-section.tsx => }/store-currency-section.tsx (93%) rename packages/{medusa/src/loaders => core/utils/src/common}/__tests__/get-resolved-plugins.spec.ts (89%) rename packages/{medusa/src/loaders/helpers/resolve-plugins.ts => core/utils/src/common/get-resolved-plugins.ts} (84%) diff --git a/.changeset/cold-keys-press.md b/.changeset/cold-keys-press.md new file mode 100644 index 0000000000..74376555e9 --- /dev/null +++ b/.changeset/cold-keys-press.md @@ -0,0 +1,12 @@ +--- +"@medusajs/admin-vite-plugin": patch +"@medusajs/admin-bundler": patch +"@medusajs/test-utils": patch +"@medusajs/dashboard": patch +"@medusajs/framework": patch +"@medusajs/types": patch +"@medusajs/utils": patch +"@medusajs/medusa": patch +--- + +fix(medusa,utils,test-utils,types,framework,dashboard,admin-vite-plugin,admib-bundler): Fix broken plugin dependencies in development server diff --git a/packages/admin/admin-bundler/package.json b/packages/admin/admin-bundler/package.json index 547c0be2ba..40f25c6bd6 100644 --- a/packages/admin/admin-bundler/package.json +++ b/packages/admin/admin-bundler/package.json @@ -4,7 +4,7 @@ "description": "Bundler for the Medusa admin dashboard.", "author": "Kasper Kristensen ", "scripts": { - "build": "tsup && copyfiles -f ./src/index.html ./src/entry.tsx ./src/index.css ./dist" + "build": "tsup" }, "main": "./dist/index.js", "types": "./dist/index.d.ts", @@ -20,7 +20,6 @@ "devDependencies": { "@medusajs/types": "2.6.1", "@types/compression": "^1.7.5", - "copyfiles": "^2.4.1", "express": "^4.21.0", "tsup": "^8.0.1", "typescript": "^5.3.3" @@ -29,19 +28,16 @@ "@medusajs/admin-shared": "2.6.1", "@medusajs/admin-vite-plugin": "2.6.1", "@medusajs/dashboard": "2.6.1", - "@rollup/plugin-node-resolve": "^16.0.0", "@vitejs/plugin-react": "^4.2.1", "autoprefixer": "^10.4.16", "compression": "^1.7.4", "express": "^4.21.0", "get-port": "^5.1.1", "glob": "^10.3.10", + "outdent": "^0.8.0", "postcss": "^8.4.32", "tailwindcss": "^3.3.6", "vite": "^5.4.14" }, - "peerDependencies": { - "react-dom": "^18.0.0" - }, "packageManager": "yarn@3.2.1" } diff --git a/packages/admin/admin-bundler/src/lib/build.ts b/packages/admin/admin-bundler/src/commands/build.ts similarity index 88% rename from packages/admin/admin-bundler/src/lib/build.ts rename to packages/admin/admin-bundler/src/commands/build.ts index 86f902f74b..9abb8e37b1 100644 --- a/packages/admin/admin-bundler/src/lib/build.ts +++ b/packages/admin/admin-bundler/src/commands/build.ts @@ -1,6 +1,6 @@ import type { InlineConfig } from "vite" import { BundlerOptions } from "../types" -import { getViteConfig } from "./config" +import { getViteConfig } from "../utils/config" export async function build(options: BundlerOptions) { const vite = await import("vite") diff --git a/packages/admin/admin-bundler/src/lib/develop.ts b/packages/admin/admin-bundler/src/commands/develop.ts similarity index 97% rename from packages/admin/admin-bundler/src/lib/develop.ts rename to packages/admin/admin-bundler/src/commands/develop.ts index f64d1b6e3e..099899e4dd 100644 --- a/packages/admin/admin-bundler/src/lib/develop.ts +++ b/packages/admin/admin-bundler/src/commands/develop.ts @@ -4,7 +4,7 @@ import path from "path" import type { InlineConfig, ViteDevServer } from "vite" import { BundlerOptions } from "../types" -import { getViteConfig } from "./config" +import { getViteConfig } from "../utils/config" const router = express.Router() diff --git a/packages/admin/admin-bundler/src/commands/plugin.ts b/packages/admin/admin-bundler/src/commands/plugin.ts new file mode 100644 index 0000000000..c9e35afe53 --- /dev/null +++ b/packages/admin/admin-bundler/src/commands/plugin.ts @@ -0,0 +1,112 @@ +import { readFileSync } from "fs" +import { builtinModules } from "node:module" +import path from "path" +import type { UserConfig } from "vite" +import { clearPluginBuild } from "../plugins/clear-plugin-build" + +interface PluginOptions { + root: string + outDir: string +} + +export async function plugin(options: PluginOptions) { + const vite = await import("vite") + const react = (await import("@vitejs/plugin-react")).default + const medusa = (await import("@medusajs/admin-vite-plugin")).default + + const pkg = JSON.parse( + readFileSync(path.resolve(options.root, "package.json"), "utf-8") + ) + const external = new Set([ + ...Object.keys(pkg.dependencies || {}), + ...Object.keys(pkg.peerDependencies || {}), + ...Object.keys(pkg.devDependencies || {}), + "react", + "react/jsx-runtime", + "react-router-dom", + "@medusajs/js-sdk", + "@medusajs/admin-sdk", + "@tanstack/react-query", + ]) + + const outDir = path.resolve(options.root, options.outDir, "src/admin") + const entryPoint = path.resolve( + options.root, + "src/admin/__admin-extensions__.js" + ) + + /** + * We need to ensure that the NODE_ENV is set to production, + * otherwise Vite will build the dev version of React. + */ + const originalNodeEnv = process.env.NODE_ENV + process.env.NODE_ENV = "production" + + const pluginConfig: UserConfig = { + build: { + lib: { + entry: entryPoint, + formats: ["es", "cjs"], + fileName: "index", + }, + emptyOutDir: false, + minify: false, + outDir, + rollupOptions: { + external: (id, importer) => { + // If there's no importer, it's a direct dependency + // Keep the existing external behavior + if (!importer) { + const idParts = id.split("/") + const name = idParts[0]?.startsWith("@") + ? `${idParts[0]}/${idParts[1]}` + : idParts[0] + + const builtinModulesWithNodePrefix = [ + ...builtinModules, + ...builtinModules.map((modName) => `node:${modName}`), + ] + + return Boolean( + (name && external.has(name)) || + (name && builtinModulesWithNodePrefix.includes(name)) + ) + } + + // For transient dependencies (those with importers), + // bundle them if they're not in our external set + const idParts = id.split("/") + const name = idParts[0]?.startsWith("@") + ? `${idParts[0]}/${idParts[1]}` + : idParts[0] + + return Boolean(name && external.has(name)) + }, + output: { + preserveModules: false, + interop: "auto", + chunkFileNames: () => { + return `_chunks/[name]-[hash]` + }, + }, + }, + }, + plugins: [ + react(), + medusa({ + pluginMode: true, + sources: [path.resolve(options.root, "src/admin")], + }), + clearPluginBuild({ outDir }), + ], + logLevel: "silent", + clearScreen: false, + } + + await vite.build(pluginConfig) + + /** + * Restore the original NODE_ENV + */ + process.env.NODE_ENV = originalNodeEnv +} diff --git a/packages/admin/admin-bundler/src/lib/serve.ts b/packages/admin/admin-bundler/src/commands/serve.ts similarity index 100% rename from packages/admin/admin-bundler/src/lib/serve.ts rename to packages/admin/admin-bundler/src/commands/serve.ts diff --git a/packages/admin/admin-bundler/src/entry.tsx b/packages/admin/admin-bundler/src/entry.tsx deleted file mode 100644 index 996d8d8030..0000000000 --- a/packages/admin/admin-bundler/src/entry.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import App from "@medusajs/dashboard"; -import React from "react"; -import ReactDOM from "react-dom/client"; -import "./index.css"; - -ReactDOM.createRoot(document.getElementById("medusa")!).render( - - - -) - - -if (import.meta.hot) { - import.meta.hot.accept() -} diff --git a/packages/admin/admin-bundler/src/index.css b/packages/admin/admin-bundler/src/index.css deleted file mode 100644 index c9b2a6f230..0000000000 --- a/packages/admin/admin-bundler/src/index.css +++ /dev/null @@ -1,5 +0,0 @@ -@import "@medusajs/dashboard/css"; - -@tailwind base; -@tailwind components; -@tailwind utilities; diff --git a/packages/admin/admin-bundler/src/index.html b/packages/admin/admin-bundler/src/index.html deleted file mode 100644 index d01be5fa97..0000000000 --- a/packages/admin/admin-bundler/src/index.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - -
- - - diff --git a/packages/admin/admin-bundler/src/index.ts b/packages/admin/admin-bundler/src/index.ts index d642941a6e..c3570ff546 100644 --- a/packages/admin/admin-bundler/src/index.ts +++ b/packages/admin/admin-bundler/src/index.ts @@ -1,6 +1,6 @@ -export { build } from "./lib/build" -export { develop } from "./lib/develop" -export { plugin } from "./lib/plugin" -export { serve } from "./lib/serve" +export { build } from "./commands/build" +export { develop } from "./commands/develop" +export { plugin } from "./commands/plugin" +export { serve } from "./commands/serve" export * from "./types" diff --git a/packages/admin/admin-bundler/src/lib/plugin.ts b/packages/admin/admin-bundler/src/lib/plugin.ts deleted file mode 100644 index f589646dad..0000000000 --- a/packages/admin/admin-bundler/src/lib/plugin.ts +++ /dev/null @@ -1,105 +0,0 @@ -import { readFileSync } from "fs" -import { rm } from "fs/promises" -import { glob } from "glob" -import path from "path" -import type { UserConfig } from "vite" - -interface PluginOptions { - root: string - outDir: string -} - -export async function plugin(options: PluginOptions) { - const vite = await import("vite") - const react = (await import("@vitejs/plugin-react")).default - const { nodeResolve } = await import("@rollup/plugin-node-resolve") - const entries = await glob(`${options.root}/src/admin/**/*.{ts,tsx,js,jsx}`) - - /** - * If there is no entry point, we can skip the build - */ - if (entries.length === 0) { - return - } - - const entryPoints = entries.reduce((acc, entry) => { - const outPath = entry - .replace(/^src\//, "") - .replace(/\.(ts|tsx|js|jsx)$/, "") - - acc[outPath] = path.resolve(options.root, entry) - return acc - }, {} as Record) - - const pkg = JSON.parse( - readFileSync(path.resolve(options.root, "package.json"), "utf-8") - ) - const external = new Set([ - ...Object.keys(pkg.dependencies || {}), - ...Object.keys(pkg.peerDependencies || {}), - ...Object.keys(pkg.devDependencies || {}), - "react", - "react-dom", - "react/jsx-runtime", - "react-router-dom", - "@medusajs/admin-sdk", - "@tanstack/react-query", - ]) - - /** - * We need to ensure that the NODE_ENV is set to production, - * otherwise Vite will build the dev version of React. - */ - const originalNodeEnv = process.env.NODE_ENV - process.env.NODE_ENV = "production" - - const pluginConfig: UserConfig = { - build: { - lib: { - entry: entryPoints, - formats: ["es"], - }, - emptyOutDir: false, - minify: false, - outDir: path.resolve(options.root, options.outDir), - rollupOptions: { - plugins: [nodeResolve() as any], - external: [...external, /node_modules/], - output: { - globals: { - react: "React", - "react-dom": "React-dom", - "react/jsx-runtime": "react/jsx-runtime", - }, - preserveModules: true, - entryFileNames: (chunkInfo) => { - return `${chunkInfo.name.replace(`${options.root}/`, "")}.js` - }, - }, - }, - }, - plugins: [ - react(), - { - name: "clear-admin-plugin", - buildStart: async () => { - const adminDir = path.join(options.root, options.outDir, "admin") - try { - await rm(adminDir, { recursive: true, force: true }) - } catch (e) { - // Directory might not exist, ignore - } - }, - }, - ], - logLevel: "silent", - clearScreen: false, - } - - await vite.build(pluginConfig) - - /** - * Restore the original NODE_ENV - */ - process.env.NODE_ENV = originalNodeEnv -} diff --git a/packages/admin/admin-bundler/src/plugins/clear-plugin-build.ts b/packages/admin/admin-bundler/src/plugins/clear-plugin-build.ts new file mode 100644 index 0000000000..9e608498ff --- /dev/null +++ b/packages/admin/admin-bundler/src/plugins/clear-plugin-build.ts @@ -0,0 +1,19 @@ +import { rm } from "node:fs/promises" +import path from "node:path" +import type { Plugin } from "vite" + +interface ClearPluginBuildOptions { + outDir: string +} + +export const clearPluginBuild = (options: ClearPluginBuildOptions): Plugin => ({ + name: "medusa:clear-plugin-build", + buildStart: async () => { + const adminDir = path.join(options.outDir, "admin") + try { + await rm(adminDir, { recursive: true, force: true }) + } catch (e) { + // Directory might not exist, ignore + } + }, +}) diff --git a/packages/admin/admin-bundler/src/plugins/inject-tailwindcss.ts b/packages/admin/admin-bundler/src/plugins/inject-tailwindcss.ts new file mode 100644 index 0000000000..f53c6e5716 --- /dev/null +++ b/packages/admin/admin-bundler/src/plugins/inject-tailwindcss.ts @@ -0,0 +1,96 @@ +import path from "node:path" +import type { Config } from "tailwindcss" +import type { Plugin } from "vite" + +interface InjectTailwindCSSOptions { + entry: string + sources?: string[] + plugins?: string[] +} + +export const injectTailwindCSS = ( + options: InjectTailwindCSSOptions +): Plugin => { + return { + name: "medusa:inject-tailwindcss", + config: () => ({ + css: { + postcss: { + plugins: [ + require("tailwindcss")({ + config: createTailwindConfig( + options.entry, + options.sources, + options.plugins + ), + }), + ], + }, + }, + }), + } +} + +function createTailwindConfig( + entry: string, + sources: string[] = [], + plugins: string[] = [] +) { + const root = path.join(entry, "**/*.{js,ts,jsx,tsx}") + const html = path.join(entry, "index.html") + + let dashboard = "" + + try { + dashboard = path.join( + path.dirname(require.resolve("@medusajs/dashboard")), + "**/*.{js,ts,jsx,tsx}" + ) + } catch (_e) { + // ignore + } + + let ui: string = "" + + try { + ui = path.join( + path.dirname(require.resolve("@medusajs/ui")), + "**/*.{js,ts,jsx,tsx}" + ) + } catch (_e) { + // ignore + } + + const sourceExtensions = sources.map((s) => + path.join(s, "**/*.{js,ts,jsx,tsx}") + ) + const pluginExtensions: string[] = [] + + for (const plugin of plugins) { + try { + const pluginPath = path.join( + path.dirname(require.resolve(plugin)), + "**/*.{js,ts,jsx,tsx}" + ) + + pluginExtensions.push(pluginPath) + } catch (_e) { + // ignore + } + } + + const config: Config = { + presets: [require("@medusajs/ui-preset")], + content: [ + html, + root, + dashboard, + ui, + ...sourceExtensions, + ...pluginExtensions, + ], + darkMode: "class", + } + + return config +} diff --git a/packages/admin/admin-bundler/src/plugins/write-static-files.ts b/packages/admin/admin-bundler/src/plugins/write-static-files.ts new file mode 100644 index 0000000000..18910d7bfe --- /dev/null +++ b/packages/admin/admin-bundler/src/plugins/write-static-files.ts @@ -0,0 +1,17 @@ +import type { Plugin } from "vite" +import { writeStaticFiles as writeStaticFilesUtils } from "../utils/write-static-files" + +interface WriteStaticFilesPluginOptions { + plugins?: string[] +} + +export const writeStaticFiles = ( + options: WriteStaticFilesPluginOptions +): Plugin => { + return { + name: "medusa:write-static-files", + buildStart: async (ctx) => { + await writeStaticFilesUtils(options.plugins) + }, + } +} diff --git a/packages/admin/admin-bundler/src/types.ts b/packages/admin/admin-bundler/src/types.ts index 491307037e..a1f62e3416 100644 --- a/packages/admin/admin-bundler/src/types.ts +++ b/packages/admin/admin-bundler/src/types.ts @@ -4,4 +4,5 @@ export type BundlerOptions = Required> & Pick & { outDir: string sources?: string[] + plugins?: string[] } diff --git a/packages/admin/admin-bundler/src/lib/config.ts b/packages/admin/admin-bundler/src/utils/config.ts similarity index 61% rename from packages/admin/admin-bundler/src/lib/config.ts rename to packages/admin/admin-bundler/src/utils/config.ts index 90128f92c2..fce808368c 100644 --- a/packages/admin/admin-bundler/src/lib/config.ts +++ b/packages/admin/admin-bundler/src/utils/config.ts @@ -1,7 +1,8 @@ import { VIRTUAL_MODULES } from "@medusajs/admin-shared" import path from "path" -import { Config } from "tailwindcss" import type { InlineConfig } from "vite" +import { injectTailwindCSS } from "../plugins/inject-tailwindcss" +import { writeStaticFiles } from "../plugins/write-static-files" import { BundlerOptions } from "../types" export async function getViteConfig( @@ -14,7 +15,7 @@ export async function getViteConfig( const getPort = await import("get-port") const hmrPort = await getPort.default() - const root = path.resolve(__dirname, "./") + const root = path.resolve(process.cwd(), ".medusa/client") const backendUrl = options.backendUrl ?? "" const storefrontUrl = options.storefrontUrl ?? "" @@ -52,16 +53,15 @@ export async function getViteConfig( port: hmrPort, }, }, - css: { - postcss: { - plugins: [ - require("tailwindcss")({ - config: createTailwindConfig(root, options.sources), - }), - ], - }, - }, plugins: [ + writeStaticFiles({ + plugins: options.plugins, + }), + injectTailwindCSS({ + entry: root, + sources: options.sources, + plugins: options.plugins, + }), react(), medusa({ sources: options.sources, @@ -76,40 +76,3 @@ export async function getViteConfig( return baseConfig } - -function createTailwindConfig(entry: string, sources: string[] = []) { - const root = path.join(entry, "**/*.{js,ts,jsx,tsx}") - const html = path.join(entry, "index.html") - - let dashboard = "" - - try { - dashboard = path.join( - path.dirname(require.resolve("@medusajs/dashboard")), - "**/*.{js,ts,jsx,tsx}" - ) - } catch (_e) { - // ignore - } - - let ui: string = "" - - try { - ui = path.join( - path.dirname(require.resolve("@medusajs/ui")), - "**/*.{js,ts,jsx,tsx}" - ) - } catch (_e) { - // ignore - } - - const extensions = sources.map((s) => path.join(s, "**/*.{js,ts,jsx,tsx}")) - - const config: Config = { - presets: [require("@medusajs/ui-preset")], - content: [html, root, dashboard, ui, ...extensions], - darkMode: "class", - } - - return config -} diff --git a/packages/admin/admin-bundler/src/utils/write-static-files.ts b/packages/admin/admin-bundler/src/utils/write-static-files.ts new file mode 100644 index 0000000000..93318fda55 --- /dev/null +++ b/packages/admin/admin-bundler/src/utils/write-static-files.ts @@ -0,0 +1,94 @@ +import { mkdir, writeFile } from "node:fs/promises" +import { join } from "node:path" +import outdent from "outdent" + +export async function writeStaticFiles(plugins?: string[]) { + const outDir = join(process.cwd(), ".medusa/client") + + await mkdir(outDir, { recursive: true }) + + const promises = [ + writeCSSFile(outDir), + writeEntryFile(outDir, plugins), + writeHTMLFile(outDir), + ] + + await Promise.all(promises) +} + +async function writeCSSFile(outDir: string) { + const css = outdent` + @import "@medusajs/dashboard/css"; + + @tailwind base; + @tailwind components; + @tailwind utilities; + ` + + await writeFile(join(outDir, "index.css"), css) +} + +function getPluginName(index: number) { + return `plugin${index}` +} + +async function writeEntryFile(outDir: string, plugins?: string[]) { + const entry = outdent` + import App from "@medusajs/dashboard"; + import React from "react"; + import ReactDOM from "react-dom/client"; + import "./index.css"; + + ${plugins + ?.map((plugin, idx) => `import ${getPluginName(idx)} from "${plugin}"`) + .join("\n")} + + let root = null + + if (!root) { + root = ReactDOM.createRoot(document.getElementById("medusa")) + } + + + root.render( + + getPluginName(idx)) + .join(", ")}]} /> + + ) + + + if (import.meta.hot) { + import.meta.hot.accept() + } + ` + + await writeFile(join(outDir, "entry.jsx"), entry) +} + +async function writeHTMLFile(outDir: string) { + const html = outdent` + + + + + + + + + +
+ + + + ` + + await writeFile(join(outDir, "index.html"), html) +} diff --git a/packages/admin/admin-vite-plugin/src/plugin.ts b/packages/admin/admin-vite-plugin/src/plugin.ts index 5cc2233ae0..c19d828e98 100644 --- a/packages/admin/admin-vite-plugin/src/plugin.ts +++ b/packages/admin/admin-vite-plugin/src/plugin.ts @@ -1,5 +1,6 @@ import { SourceMap } from "magic-string" -import path from "path" +import { rm, writeFile } from "node:fs/promises" +import path from "node:path" import type * as Vite from "vite" import { generateCustomFieldHashes } from "./custom-fields" import { generateRouteHashes } from "./routes" @@ -22,10 +23,17 @@ import { } from "./vmod" import { generateWidgetHash } from "./widgets" +enum Mode { + PLUGIN = "plugin", + APPLICATION = "application", +} + export const medusaVitePlugin: MedusaVitePlugin = (options) => { const hashMap = new Map() const _sources = new Set(options?.sources ?? []) + const mode = options?.pluginMode ? Mode.PLUGIN : Mode.APPLICATION + let watcher: Vite.FSWatcher | undefined function isFileInSources(file: string): boolean { @@ -66,9 +74,73 @@ export const medusaVitePlugin: MedusaVitePlugin = (options) => { } } + // Function to generate the index.js file + async function generatePluginEntryModule( + sources: Set + ): Promise { + // Generate all the module content + const widgetModule = await generateVirtualWidgetModule(sources, true) + const routeModule = await generateVirtualRouteModule(sources, true) + const menuItemModule = await generateVirtualMenuItemModule(sources, true) + const formModule = await generateVirtualFormModule(sources, true) + const displayModule = await generateVirtualDisplayModule(sources, true) + + // Create the index.js content that re-exports everything + return ` + // Auto-generated index file for Medusa Admin UI extensions + ${widgetModule.code} + ${routeModule.code} + ${menuItemModule.code} + ${formModule.code} + ${displayModule.code} + + const plugin = { + widgetModule, + routeModule, + menuItemModule, + formModule, + displayModule + } + + export default plugin + ` + } + + const pluginEntryFile = path.resolve( + process.cwd(), + "src/admin/__admin-extensions__.js" + ) + return { name: "@medusajs/admin-vite-plugin", enforce: "pre", + async buildStart() { + switch (mode) { + case Mode.PLUGIN: { + const code = await generatePluginEntryModule(_sources) + await writeFile(pluginEntryFile, code, "utf-8") + break + } + case Mode.APPLICATION: { + break + } + } + }, + async buildEnd() { + switch (mode) { + case Mode.PLUGIN: { + try { + await rm(pluginEntryFile, { force: true }) + } catch (error) { + // Ignore the error if the file doesn't exist + } + break + } + case Mode.APPLICATION: { + break + } + } + }, configureServer(server) { watcher = server.watcher watcher?.add(Array.from(_sources)) diff --git a/packages/admin/admin-vite-plugin/src/types.ts b/packages/admin/admin-vite-plugin/src/types.ts index a14af187e9..3a8e0c8527 100644 --- a/packages/admin/admin-vite-plugin/src/types.ts +++ b/packages/admin/admin-vite-plugin/src/types.ts @@ -56,6 +56,7 @@ export type LoadModuleOptions = export interface MedusaVitePluginOptions { sources?: string[] + pluginMode?: boolean } export type MedusaVitePlugin = (config?: MedusaVitePluginOptions) => Vite.Plugin diff --git a/packages/admin/admin-vite-plugin/src/virtual-modules/generate-virtual-display-module.ts b/packages/admin/admin-vite-plugin/src/virtual-modules/generate-virtual-display-module.ts index ec0c476a55..e8118b4af7 100644 --- a/packages/admin/admin-vite-plugin/src/virtual-modules/generate-virtual-display-module.ts +++ b/packages/admin/admin-vite-plugin/src/virtual-modules/generate-virtual-display-module.ts @@ -2,14 +2,19 @@ import { outdent } from "outdent" import { generateCustomFieldDisplays } from "../custom-fields" import { generateModule } from "../utils" -export async function generateVirtualDisplayModule(sources: Set) { +export async function generateVirtualDisplayModule( + sources: Set, + pluginMode = false +) { const displays = await generateCustomFieldDisplays(sources) const code = outdent` ${displays.imports.join("\n")} - export default { - ${displays.code} + ${ + pluginMode + ? `const displayModule = { ${displays.code} }` + : `export default { ${displays.code} }` } ` diff --git a/packages/admin/admin-vite-plugin/src/virtual-modules/generate-virtual-form-module.ts b/packages/admin/admin-vite-plugin/src/virtual-modules/generate-virtual-form-module.ts index e2ce152616..24f2248ded 100644 --- a/packages/admin/admin-vite-plugin/src/virtual-modules/generate-virtual-form-module.ts +++ b/packages/admin/admin-vite-plugin/src/virtual-modules/generate-virtual-form-module.ts @@ -1,29 +1,24 @@ import outdent from "outdent" import { generateCustomFieldForms } from "../custom-fields" -import { generateMenuItems } from "../routes" import { generateModule } from "../utils" -import { generateWidgets } from "../widgets" -export async function generateVirtualFormModule(sources: Set) { - const menuItems = await generateMenuItems(sources) - const widgets = await generateWidgets(sources) +export async function generateVirtualFormModule( + sources: Set, + pluginMode = false +) { const customFields = await generateCustomFieldForms(sources) - const imports = [ - ...menuItems.imports, - ...widgets.imports, - ...customFields.imports, - ] + const imports = [...customFields.imports] const code = outdent` ${imports.join("\n")} - export default { - ${menuItems.code}, - ${widgets.code}, - ${customFields.code}, - } - ` + ${ + pluginMode + ? `const formModule = { ${customFields.code} }` + : `export default { ${customFields.code} }` + } + ` return generateModule(code) } diff --git a/packages/admin/admin-vite-plugin/src/virtual-modules/generate-virtual-link-module.ts b/packages/admin/admin-vite-plugin/src/virtual-modules/generate-virtual-link-module.ts index ef37c4606e..c5a574b6ff 100644 --- a/packages/admin/admin-vite-plugin/src/virtual-modules/generate-virtual-link-module.ts +++ b/packages/admin/admin-vite-plugin/src/virtual-modules/generate-virtual-link-module.ts @@ -2,14 +2,19 @@ import { outdent } from "outdent" import { generateCustomFieldLinks } from "../custom-fields" import { generateModule } from "../utils" -export async function generateVirtualLinkModule(sources: Set) { +export async function generateVirtualLinkModule( + sources: Set, + pluginMode = false +) { const links = await generateCustomFieldLinks(sources) const code = outdent` ${links.imports.join("\n")} - export default { - ${links.code} + ${ + pluginMode + ? `const linkModule = { ${links.code} }` + : `export default { ${links.code} }` } ` diff --git a/packages/admin/admin-vite-plugin/src/virtual-modules/generate-virtual-menu-item-module.ts b/packages/admin/admin-vite-plugin/src/virtual-modules/generate-virtual-menu-item-module.ts index b76e0acc9b..2477cb857c 100644 --- a/packages/admin/admin-vite-plugin/src/virtual-modules/generate-virtual-menu-item-module.ts +++ b/packages/admin/admin-vite-plugin/src/virtual-modules/generate-virtual-menu-item-module.ts @@ -3,16 +3,21 @@ import outdent from "outdent" import { generateMenuItems } from "../routes" import { generateModule } from "../utils" -export async function generateVirtualMenuItemModule(sources: Set) { +export async function generateVirtualMenuItemModule( + sources: Set, + pluginMode = false +) { const menuItems = await generateMenuItems(sources) const code = outdent` ${menuItems.imports.join("\n")} - export default { - ${menuItems.code}, - } - ` + ${ + pluginMode + ? `const menuItemModule = { ${menuItems.code} }` + : `export default { ${menuItems.code} }` + } + ` return generateModule(code) } diff --git a/packages/admin/admin-vite-plugin/src/virtual-modules/generate-virtual-route-module.ts b/packages/admin/admin-vite-plugin/src/virtual-modules/generate-virtual-route-module.ts index 91d44e5614..1a0df1455d 100644 --- a/packages/admin/admin-vite-plugin/src/virtual-modules/generate-virtual-route-module.ts +++ b/packages/admin/admin-vite-plugin/src/virtual-modules/generate-virtual-route-module.ts @@ -2,7 +2,10 @@ import { outdent } from "outdent" import { generateRoutes } from "../routes" import { generateModule } from "../utils" -export async function generateVirtualRouteModule(sources: Set) { +export async function generateVirtualRouteModule( + sources: Set, + pluginMode = false +) { const routes = await generateRoutes(sources) const imports = [...routes.imports] @@ -10,8 +13,10 @@ export async function generateVirtualRouteModule(sources: Set) { const code = outdent` ${imports.join("\n")} - export default { - ${routes.code} + ${ + pluginMode + ? `const routeModule = { ${routes.code} }` + : `export default { ${routes.code} }` } ` diff --git a/packages/admin/admin-vite-plugin/src/virtual-modules/generate-virtual-widget-module.ts b/packages/admin/admin-vite-plugin/src/virtual-modules/generate-virtual-widget-module.ts index fef19bb4c7..b4a3d58def 100644 --- a/packages/admin/admin-vite-plugin/src/virtual-modules/generate-virtual-widget-module.ts +++ b/packages/admin/admin-vite-plugin/src/virtual-modules/generate-virtual-widget-module.ts @@ -2,7 +2,10 @@ import outdent from "outdent" import { generateModule } from "../utils" import { generateWidgets } from "../widgets" -export async function generateVirtualWidgetModule(sources: Set) { +export async function generateVirtualWidgetModule( + sources: Set, + pluginMode = false +) { const widgets = await generateWidgets(sources) const imports = [...widgets.imports] @@ -10,8 +13,10 @@ export async function generateVirtualWidgetModule(sources: Set) { const code = outdent` ${imports.join("\n")} - export default { - ${widgets.code}, + ${ + pluginMode + ? `const widgetModule = { ${widgets.code} }` + : `export default { ${widgets.code} }` } ` diff --git a/packages/admin/dashboard/package.json b/packages/admin/dashboard/package.json index ec8d2d27a2..0d6ad7e4ca 100644 --- a/packages/admin/dashboard/package.json +++ b/packages/admin/dashboard/package.json @@ -36,7 +36,6 @@ "files": [ "package.json", "src", - "index.html", "dist" ], "dependencies": { diff --git a/packages/admin/dashboard/scripts/generate-types.js b/packages/admin/dashboard/scripts/generate-types.js index 097a86c1d5..18e154396f 100644 --- a/packages/admin/dashboard/scripts/generate-types.js +++ b/packages/admin/dashboard/scripts/generate-types.js @@ -11,12 +11,12 @@ async function generateTypes() { const filePath = path.join(distDir, "index.d.ts") const fileContent = ` -import * as react_jsx_runtime from "react/jsx-runtime" + declare function App(props: { + plugins?: any[] + }): JSX.Element -declare const App: () => react_jsx_runtime.JSX.Element - -export default App -` + export default App + ` // Ensure the dist directory exists if (!fs.existsSync(distDir)) { diff --git a/packages/admin/dashboard/src/app.tsx b/packages/admin/dashboard/src/app.tsx index 855bcfbaf0..7f46055724 100644 --- a/packages/admin/dashboard/src/app.tsx +++ b/packages/admin/dashboard/src/app.tsx @@ -1,27 +1,32 @@ -import { DashboardExtensionManager } from "./extensions" -import { Providers } from "./providers/providers" -import { RouterProvider } from "./providers/router-provider" +import { DashboardApp } from "./dashboard-app" +import { DashboardPlugin } from "./dashboard-app/types" import displayModule from "virtual:medusa/displays" import formModule from "virtual:medusa/forms" import menuItemModule from "virtual:medusa/menu-items" +import routeModule from "virtual:medusa/routes" import widgetModule from "virtual:medusa/widgets" import "./index.css" -function App() { - const manager = new DashboardExtensionManager({ - displayModule, - formModule, - menuItemModule, - widgetModule, +const localPlugin = { + widgetModule, + routeModule, + displayModule, + formModule, + menuItemModule, +} + +interface AppProps { + plugins?: DashboardPlugin[] +} + +function App({ plugins = [] }: AppProps) { + const app = new DashboardApp({ + plugins: [localPlugin, ...plugins], }) - return ( - - - - ) + return
{app.render()}
} export default App diff --git a/packages/admin/dashboard/src/components/layout/main-layout/main-layout.tsx b/packages/admin/dashboard/src/components/layout/main-layout/main-layout.tsx index ca406063bc..272808f331 100644 --- a/packages/admin/dashboard/src/components/layout/main-layout/main-layout.tsx +++ b/packages/admin/dashboard/src/components/layout/main-layout/main-layout.tsx @@ -24,9 +24,9 @@ import { INavItem, NavItem } from "../../layout/nav-item" import { Shell } from "../../layout/shell" import { Link, useLocation, useNavigate } from "react-router-dom" -import { useDashboardExtension } from "../../../extensions" import { useLogout } from "../../../hooks/api" import { queryClient } from "../../../lib/query-client" +import { useExtension } from "../../../providers/extension-provider" import { useSearch } from "../../../providers/search-provider" import { UserMenu } from "../user-menu" @@ -283,7 +283,7 @@ const Searchbar = () => { const CoreRouteSection = () => { const coreRoutes = useCoreRoutes() - const { getMenu } = useDashboardExtension() + const { getMenu } = useExtension() const menuItems = getMenu("coreExtensions") @@ -308,7 +308,7 @@ const CoreRouteSection = () => { const ExtensionRouteSection = () => { const { t } = useTranslation() - const { getMenu } = useDashboardExtension() + const { getMenu } = useExtension() const menuItems = getMenu("coreExtensions").filter((item) => !item.nested) diff --git a/packages/admin/dashboard/src/components/layout/nav-item/nav-item.tsx b/packages/admin/dashboard/src/components/layout/nav-item/nav-item.tsx index 66c4fc0822..5ef7be021c 100644 --- a/packages/admin/dashboard/src/components/layout/nav-item/nav-item.tsx +++ b/packages/admin/dashboard/src/components/layout/nav-item/nav-item.tsx @@ -130,7 +130,7 @@ export const NavItem = ({ i.to === pathname)} state={ from ? { diff --git a/packages/admin/dashboard/src/components/layout/settings-layout/settings-layout.tsx b/packages/admin/dashboard/src/components/layout/settings-layout/settings-layout.tsx index ac4db2666e..dfdc4900c5 100644 --- a/packages/admin/dashboard/src/components/layout/settings-layout/settings-layout.tsx +++ b/packages/admin/dashboard/src/components/layout/settings-layout/settings-layout.tsx @@ -5,10 +5,9 @@ import { Fragment, useEffect, useMemo, useState } from "react" import { useTranslation } from "react-i18next" import { Link, useLocation } from "react-router-dom" +import { useExtension } from "../../../providers/extension-provider" import { INavItem, NavItem } from "../nav-item" import { Shell } from "../shell" - -import { useDashboardExtension } from "../../../extensions" import { UserMenu } from "../user-menu" export const SettingsLayout = () => { @@ -114,7 +113,7 @@ const getSafeFromValue = (from: string) => { } const SettingsSidebar = () => { - const { getMenu } = useDashboardExtension() + const { getMenu } = useExtension() const routes = useSettingRoutes() const developerRoutes = useDeveloperRoutes() diff --git a/packages/admin/dashboard/src/extensions/dashboard-extension-manager/dashboard-extension-manager.tsx b/packages/admin/dashboard/src/dashboard-app/dashboard-app.tsx similarity index 56% rename from packages/admin/dashboard/src/extensions/dashboard-extension-manager/dashboard-extension-manager.tsx rename to packages/admin/dashboard/src/dashboard-app/dashboard-app.tsx index 8302778b7f..2e2f23b3f1 100644 --- a/packages/admin/dashboard/src/extensions/dashboard-extension-manager/dashboard-extension-manager.tsx +++ b/packages/admin/dashboard/src/dashboard-app/dashboard-app.tsx @@ -7,87 +7,123 @@ import { NESTED_ROUTE_POSITIONS, } from "@medusajs/admin-shared" import * as React from "react" -import { INavItem } from "../../components/layout/nav-item" +import { + createBrowserRouter, + RouteObject, + RouterProvider, +} from "react-router-dom" +import { INavItem } from "../components/layout/nav-item" +import { Providers } from "../providers" +import { getRouteMap } from "./routes/get-route.map" +import { createRouteMap, getRouteExtensions } from "./routes/utils" import { ConfigExtension, ConfigField, ConfigFieldMap, + DashboardPlugin, DisplayExtension, DisplayMap, - DisplayModule, FormExtension, FormField, FormFieldExtension, FormFieldMap, - FormModule, FormZoneMap, MenuItemExtension, MenuItemKey, - MenuItemModule, - WidgetExtension, - WidgetModule, + MenuMap, + WidgetMap, ZoneStructure, -} from "../types" +} from "./types" -export type DashboardExtensionManagerProps = { - formModule: FormModule - displayModule: DisplayModule - menuItemModule: MenuItemModule - widgetModule: WidgetModule +type DashboardAppProps = { + plugins: DashboardPlugin[] } -export class DashboardExtensionManager { - private widgets: Map - private menus: Map +export class DashboardApp { + private widgets: WidgetMap + private menus: MenuMap private fields: FormFieldMap private configs: ConfigFieldMap private displays: DisplayMap + private coreRoutes: RouteObject[] + private settingsRoutes: RouteObject[] - constructor({ - widgetModule, - menuItemModule, - displayModule, - formModule, - }: DashboardExtensionManagerProps) { - this.widgets = this.populateWidgets(widgetModule.widgets) - this.menus = this.populateMenus(menuItemModule.menuItems) + constructor({ plugins }: DashboardAppProps) { + this.widgets = this.populateWidgets(plugins) + this.menus = this.populateMenus(plugins) - const { fields, configs } = this.populateForm(formModule) + const { coreRoutes, settingsRoutes } = this.populateRoutes(plugins) + this.coreRoutes = coreRoutes + this.settingsRoutes = settingsRoutes + + const { fields, configs } = this.populateForm(plugins) this.fields = fields this.configs = configs - this.displays = this.populateDisplays(displayModule) + this.displays = this.populateDisplays(plugins) } - private populateWidgets(widgets: WidgetExtension[] | undefined) { - const registry = new Map() + private populateRoutes(plugins: DashboardPlugin[]) { + const coreRoutes: RouteObject[] = [] + const settingsRoutes: RouteObject[] = [] - if (!widgets) { - return registry + for (const plugin of plugins) { + const filteredCoreRoutes = getRouteExtensions(plugin.routeModule, "core") + const filteredSettingsRoutes = getRouteExtensions( + plugin.routeModule, + "settings" + ) + + const coreRoutesMap = createRouteMap(filteredCoreRoutes) + const settingsRoutesMap = createRouteMap(filteredSettingsRoutes) + + coreRoutes.push(...coreRoutesMap) + settingsRoutes.push(...settingsRoutesMap) } - widgets.forEach((widget) => { - widget.zone.forEach((zone) => { - if (!registry.has(zone)) { - registry.set(zone, []) - } - registry.get(zone)!.push(widget.Component) + return { coreRoutes, settingsRoutes } + } + + private populateWidgets(plugins: DashboardPlugin[]) { + const registry = new Map() + + plugins.forEach((plugin) => { + const widgets = plugin.widgetModule.widgets + if (!widgets) { + return + } + + widgets.forEach((widget) => { + widget.zone.forEach((zone) => { + if (!registry.has(zone)) { + registry.set(zone, []) + } + registry.get(zone)!.push(widget.Component) + }) }) }) return registry } - private populateMenus(menuItems: MenuItemExtension[] | undefined) { + private populateMenus(plugins: DashboardPlugin[]) { const registry = new Map() const tempRegistry: Record = {} - if (!menuItems) { + // Collect all menu items from all plugins + const allMenuItems: MenuItemExtension[] = [] + plugins.forEach((plugin) => { + if (plugin.menuItemModule.menuItems) { + allMenuItems.push(...plugin.menuItemModule.menuItems) + } + }) + + if (allMenuItems.length === 0) { return registry } - menuItems.sort((a, b) => a.path.length - b.path.length) + allMenuItems.sort((a, b) => a.path.length - b.path.length) - menuItems.forEach((item) => { + allMenuItems.forEach((item) => { if (item.path.includes("/:")) { if (process.env.NODE_ENV === "development") { console.warn( @@ -114,7 +150,7 @@ export class DashboardExtensionManager { } // Find the parent item if it exists - const parentItem = menuItems.find( + const parentItem = allMenuItems.find( (menuItem) => menuItem.path === parentPath ) @@ -158,25 +194,62 @@ export class DashboardExtensionManager { return registry } - private populateForm(formModule: FormModule): { + private populateForm(plugins: DashboardPlugin[]): { fields: FormFieldMap configs: ConfigFieldMap } { const fields: FormFieldMap = new Map() const configs: ConfigFieldMap = new Map() - Object.entries(formModule.customFields).forEach( - ([model, customization]) => { - fields.set( - model as CustomFieldModel, - this.processFields(customization.forms) - ) - configs.set( - model as CustomFieldModel, - this.processConfigs(customization.configs) - ) - } - ) + plugins.forEach((plugin) => { + Object.entries(plugin.formModule.customFields).forEach( + ([model, customization]) => { + // Initialize maps if they don't exist for this model + if (!fields.has(model as CustomFieldModel)) { + fields.set(model as CustomFieldModel, new Map()) + } + if (!configs.has(model as CustomFieldModel)) { + configs.set(model as CustomFieldModel, new Map()) + } + + // Process forms + const modelFields = this.processFields(customization.forms) + const existingModelFields = fields.get(model as CustomFieldModel)! + + // Merge the maps + modelFields.forEach((zoneStructure, zone) => { + if (!existingModelFields.has(zone)) { + existingModelFields.set(zone, { components: [], tabs: new Map() }) + } + + const existingZoneStructure = existingModelFields.get(zone)! + + // Merge components + existingZoneStructure.components.push(...zoneStructure.components) + + // Merge tabs + zoneStructure.tabs.forEach((fields, tab) => { + if (!existingZoneStructure.tabs.has(tab)) { + existingZoneStructure.tabs.set(tab, []) + } + existingZoneStructure.tabs.get(tab)!.push(...fields) + }) + }) + + // Process configs + const modelConfigs = this.processConfigs(customization.configs) + const existingModelConfigs = configs.get(model as CustomFieldModel)! + + // Merge the config maps + modelConfigs.forEach((configFields, zone) => { + if (!existingModelConfigs.has(zone)) { + existingModelConfigs.set(zone, []) + } + existingModelConfigs.get(zone)!.push(...configFields) + }) + } + ) + }) return { fields, configs } } @@ -269,16 +342,36 @@ export class DashboardExtensionManager { } } - private populateDisplays(displayModule: DisplayModule): DisplayMap { + private populateDisplays(plugins: DashboardPlugin[]): DisplayMap { const displays = new Map< CustomFieldModel, Map[]> >() - Object.entries(displayModule.displays).forEach(([model, customization]) => { - displays.set( - model as CustomFieldModel, - this.processDisplays(customization) + plugins.forEach((plugin) => { + Object.entries(plugin.displayModule.displays).forEach( + ([model, customization]) => { + if (!displays.has(model as CustomFieldModel)) { + displays.set( + model as CustomFieldModel, + new Map< + CustomFieldContainerZone, + React.ComponentType<{ data: any }>[] + >() + ) + } + + const modelDisplays = displays.get(model as CustomFieldModel)! + const processedDisplays = this.processDisplays(customization) + + // Merge the displays + processedDisplays.forEach((components, zone) => { + if (!modelDisplays.has(zone)) { + modelDisplays.set(zone, []) + } + modelDisplays.get(zone)!.push(...components) + }) + } ) }) @@ -347,4 +440,21 @@ export class DashboardExtensionManager { getDisplays: this.getDisplays.bind(this), } } + + render() { + const routes = getRouteMap({ + settingsRoutes: this.settingsRoutes, + coreRoutes: this.coreRoutes, + }) + + const router = createBrowserRouter(routes, { + basename: __BASE__ || "/", + }) + + return ( + + + + ) + } } diff --git a/packages/admin/dashboard/src/extensions/forms/form-extension-zone/form-extension-zone.tsx b/packages/admin/dashboard/src/dashboard-app/forms/form-extension-zone/form-extension-zone.tsx similarity index 100% rename from packages/admin/dashboard/src/extensions/forms/form-extension-zone/form-extension-zone.tsx rename to packages/admin/dashboard/src/dashboard-app/forms/form-extension-zone/form-extension-zone.tsx diff --git a/packages/admin/dashboard/src/extensions/forms/form-extension-zone/index.ts b/packages/admin/dashboard/src/dashboard-app/forms/form-extension-zone/index.ts similarity index 100% rename from packages/admin/dashboard/src/extensions/forms/form-extension-zone/index.ts rename to packages/admin/dashboard/src/dashboard-app/forms/form-extension-zone/index.ts diff --git a/packages/admin/dashboard/src/extensions/forms/form-extension-zone/types.ts b/packages/admin/dashboard/src/dashboard-app/forms/form-extension-zone/types.ts similarity index 100% rename from packages/admin/dashboard/src/extensions/forms/form-extension-zone/types.ts rename to packages/admin/dashboard/src/dashboard-app/forms/form-extension-zone/types.ts diff --git a/packages/admin/dashboard/src/extensions/forms/form-extension-zone/utils.ts b/packages/admin/dashboard/src/dashboard-app/forms/form-extension-zone/utils.ts similarity index 100% rename from packages/admin/dashboard/src/extensions/forms/form-extension-zone/utils.ts rename to packages/admin/dashboard/src/dashboard-app/forms/form-extension-zone/utils.ts diff --git a/packages/admin/dashboard/src/extensions/forms/hooks.tsx b/packages/admin/dashboard/src/dashboard-app/forms/hooks.tsx similarity index 100% rename from packages/admin/dashboard/src/extensions/forms/hooks.tsx rename to packages/admin/dashboard/src/dashboard-app/forms/hooks.tsx diff --git a/packages/admin/dashboard/src/extensions/forms/index.ts b/packages/admin/dashboard/src/dashboard-app/forms/index.ts similarity index 100% rename from packages/admin/dashboard/src/extensions/forms/index.ts rename to packages/admin/dashboard/src/dashboard-app/forms/index.ts diff --git a/packages/admin/dashboard/src/extensions/index.ts b/packages/admin/dashboard/src/dashboard-app/index.ts similarity index 70% rename from packages/admin/dashboard/src/extensions/index.ts rename to packages/admin/dashboard/src/dashboard-app/index.ts index dd3e29f290..7136950301 100644 --- a/packages/admin/dashboard/src/extensions/index.ts +++ b/packages/admin/dashboard/src/dashboard-app/index.ts @@ -1,5 +1,4 @@ -export * from "./dashboard-extension-manager" -export * from "./dashboard-extension-provider" +export * from "./dashboard-app" export * from "./forms" export * from "./links/utils" export * from "./routes/utils" diff --git a/packages/admin/dashboard/src/extensions/links/utils.ts b/packages/admin/dashboard/src/dashboard-app/links/utils.ts similarity index 100% rename from packages/admin/dashboard/src/extensions/links/utils.ts rename to packages/admin/dashboard/src/dashboard-app/links/utils.ts diff --git a/packages/admin/dashboard/src/dashboard-app/routes/get-route.map.tsx b/packages/admin/dashboard/src/dashboard-app/routes/get-route.map.tsx new file mode 100644 index 0000000000..ee3de99151 --- /dev/null +++ b/packages/admin/dashboard/src/dashboard-app/routes/get-route.map.tsx @@ -0,0 +1,1735 @@ +import { HttpTypes } from "@medusajs/types" +import { t } from "i18next" +import { Outlet, RouteObject, UIMatch } from "react-router-dom" +import { ProtectedRoute } from "../../components/authentication/protected-route" +import { MainLayout } from "../../components/layout/main-layout" +import { PublicLayout } from "../../components/layout/public-layout" +import { SettingsLayout } from "../../components/layout/settings-layout" +import { ErrorBoundary } from "../../components/utilities/error-boundary" +import { TaxRegionDetailBreadcrumb } from "../../routes/tax-regions/tax-region-detail/breadcrumb" +import { taxRegionLoader } from "../../routes/tax-regions/tax-region-detail/loader" + +export function getRouteMap({ + settingsRoutes, + coreRoutes, +}: { + settingsRoutes: RouteObject[] + coreRoutes: RouteObject[] +}) { + return [ + { + element: , + errorElement: , + children: [ + { + element: , + children: [ + { + path: "/", + errorElement: , + lazy: () => import("../../routes/home"), + }, + { + path: "/products", + errorElement: , + handle: { + breadcrumb: () => t("products.domain"), + }, + children: [ + { + path: "", + lazy: () => import("../../routes/products/product-list"), + children: [ + { + path: "create", + lazy: () => + import("../../routes/products/product-create"), + }, + { + path: "import", + lazy: () => + import("../../routes/products/product-import"), + }, + { + path: "export", + lazy: () => + import("../../routes/products/product-export"), + }, + ], + }, + { + path: ":id", + errorElement: , + lazy: async () => { + const { Breadcrumb, loader } = await import( + "../../routes/products/product-detail" + ) + + return { + Component: Outlet, + loader, + handle: { + breadcrumb: ( + match: UIMatch + ) => , + }, + } + }, + children: [ + { + path: "", + lazy: () => + import("../../routes/products/product-detail"), + children: [ + { + path: "edit", + lazy: () => + import("../../routes/products/product-edit"), + }, + { + path: "edit-variant", + lazy: () => + import( + "../../routes/product-variants/product-variant-edit" + ), + }, + { + path: "sales-channels", + lazy: () => + import( + "../../routes/products/product-sales-channels" + ), + }, + { + path: "attributes", + lazy: () => + import("../../routes/products/product-attributes"), + }, + { + path: "organization", + lazy: () => + import( + "../../routes/products/product-organization" + ), + }, + { + path: "shipping-profile", + lazy: () => + import( + "../../routes/products/product-shipping-profile" + ), + }, + { + path: "media", + lazy: () => + import("../../routes/products/product-media"), + }, + { + path: "prices", + lazy: () => + import("../../routes/products/product-prices"), + }, + { + path: "options/create", + lazy: () => + import( + "../../routes/products/product-create-option" + ), + }, + { + path: "options/:option_id/edit", + lazy: () => + import("../../routes/products/product-edit-option"), + }, + { + path: "variants/create", + lazy: () => + import( + "../../routes/products/product-create-variant" + ), + }, + { + path: "stock", + lazy: () => + import("../../routes/products/product-stock"), + }, + { + path: "metadata/edit", + lazy: () => + import("../../routes/products/product-metadata"), + }, + ], + }, + { + path: "variants/:variant_id", + lazy: async () => { + const { Component, Breadcrumb, loader } = await import( + "../../routes/product-variants/product-variant-detail" + ) + + return { + Component, + loader, + handle: { + breadcrumb: ( + // eslint-disable-next-line max-len + match: UIMatch + ) => , + }, + } + }, + children: [ + { + path: "edit", + lazy: () => + import( + "../../routes/product-variants/product-variant-edit" + ), + }, + { + path: "prices", + lazy: () => + import("../../routes/products/product-prices"), + }, + { + path: "manage-items", + lazy: () => + import( + "../../routes/product-variants/product-variant-manage-inventory-items" + ), + }, + { + path: "metadata/edit", + lazy: () => + import( + "../../routes/product-variants/product-variant-metadata" + ), + }, + ], + }, + ], + }, + ], + }, + { + path: "/categories", + errorElement: , + handle: { + breadcrumb: () => t("categories.domain"), + }, + children: [ + { + path: "", + lazy: () => import("../../routes/categories/category-list"), + children: [ + { + path: "create", + lazy: () => + import("../../routes/categories/category-create"), + }, + { + path: "organize", + lazy: () => + import("../../routes/categories/category-organize"), + }, + ], + }, + { + path: ":id", + lazy: async () => { + const { Component, Breadcrumb, loader } = await import( + "../../routes/categories/category-detail" + ) + + return { + Component, + loader, + handle: { + breadcrumb: ( + match: UIMatch + ) => , + }, + } + }, + children: [ + { + path: "edit", + lazy: () => + import("../../routes/categories/category-edit"), + }, + { + path: "products", + lazy: () => + import("../../routes/categories/category-products"), + }, + { + path: "organize", + lazy: () => + import("../../routes/categories/category-organize"), + }, + { + path: "metadata/edit", + lazy: () => + import("../../routes/categories/categories-metadata"), + }, + ], + }, + ], + }, + { + path: "/orders", + errorElement: , + handle: { + breadcrumb: () => t("orders.domain"), + }, + children: [ + { + path: "", + lazy: () => import("../../routes/orders/order-list"), + }, + { + path: ":id", + lazy: async () => { + const { Component, Breadcrumb, loader } = await import( + "../../routes/orders/order-detail" + ) + + return { + Component, + loader, + handle: { + breadcrumb: ( + match: UIMatch + ) => , + }, + } + }, + children: [ + { + path: "fulfillment", + lazy: () => + import("../../routes/orders/order-create-fulfillment"), + }, + { + path: "returns/:return_id/receive", + lazy: () => + import("../../routes/orders/order-receive-return"), + }, + { + path: "allocate-items", + lazy: () => + import("../../routes/orders/order-allocate-items"), + }, + { + path: ":f_id/create-shipment", + lazy: () => + import("../../routes/orders/order-create-shipment"), + }, + { + path: "returns", + lazy: () => + import("../../routes/orders/order-create-return"), + }, + { + path: "claims", + lazy: () => + import("../../routes/orders/order-create-claim"), + }, + { + path: "exchanges", + lazy: () => + import("../../routes/orders/order-create-exchange"), + }, + { + path: "edits", + lazy: () => + import("../../routes/orders/order-create-edit"), + }, + { + path: "refund", + lazy: () => + import("../../routes/orders/order-create-refund"), + }, + { + path: "transfer", + lazy: () => + import("../../routes/orders/order-request-transfer"), + }, + { + path: "email", + lazy: () => + import("../../routes/orders/order-edit-email"), + }, + { + path: "shipping-address", + lazy: () => + import( + "../../routes/orders/order-edit-shipping-address" + ), + }, + { + path: "billing-address", + lazy: () => + import( + "../../routes/orders/order-edit-billing-address" + ), + }, + { + path: "metadata/edit", + lazy: () => import("../../routes/orders/order-metadata"), + }, + ], + }, + ], + }, + { + path: "/promotions", + errorElement: , + handle: { + breadcrumb: () => t("promotions.domain"), + }, + children: [ + { + path: "", + lazy: () => import("../../routes/promotions/promotion-list"), + }, + { + path: "create", + lazy: () => + import("../../routes/promotions/promotion-create"), + }, + { + path: ":id", + lazy: async () => { + const { Component, Breadcrumb, loader } = await import( + "../../routes/promotions/promotion-detail" + ) + + return { + Component, + loader, + handle: { + breadcrumb: ( + match: UIMatch + ) => , + }, + } + }, + children: [ + { + path: "edit", + lazy: () => + import( + "../../routes/promotions/promotion-edit-details" + ), + }, + { + path: "add-to-campaign", + lazy: () => + import( + "../../routes/promotions/promotion-add-campaign" + ), + }, + { + path: ":ruleType/edit", + lazy: () => + import("../../routes/promotions/common/edit-rules"), + }, + ], + }, + ], + }, + { + path: "/campaigns", + errorElement: , + handle: { + breadcrumb: () => t("campaigns.domain"), + }, + children: [ + { + path: "", + lazy: () => import("../../routes/campaigns/campaign-list"), + children: [], + }, + { + path: "create", + lazy: () => import("../../routes/campaigns/campaign-create"), + }, + { + path: ":id", + lazy: async () => { + const { Component, Breadcrumb, loader } = await import( + "../../routes/campaigns/campaign-detail" + ) + + return { + Component, + loader, + handle: { + breadcrumb: ( + match: UIMatch + ) => , + }, + } + }, + children: [ + { + path: "edit", + lazy: () => + import("../../routes/campaigns/campaign-edit"), + }, + { + path: "configuration", + lazy: () => + import("../../routes/campaigns/campaign-configuration"), + }, + { + path: "edit-budget", + lazy: () => + import("../../routes/campaigns/campaign-budget-edit"), + }, + { + path: "add-promotions", + lazy: () => + import( + "../../routes/campaigns/add-campaign-promotions" + ), + }, + ], + }, + ], + }, + { + path: "/collections", + errorElement: , + handle: { + breadcrumb: () => t("collections.domain"), + }, + children: [ + { + path: "", + lazy: () => + import("../../routes/collections/collection-list"), + children: [ + { + path: "create", + lazy: () => + import("../../routes/collections/collection-create"), + }, + ], + }, + { + path: ":id", + lazy: async () => { + const { Component, Breadcrumb, loader } = await import( + "../../routes/collections/collection-detail" + ) + + return { + Component, + loader, + handle: { + breadcrumb: ( + match: UIMatch + ) => , + }, + } + }, + children: [ + { + path: "edit", + lazy: () => + import("../../routes/collections/collection-edit"), + }, + { + path: "products", + lazy: () => + import( + "../../routes/collections/collection-add-products" + ), + }, + { + path: "metadata/edit", + lazy: () => + import("../../routes/collections/collection-metadata"), + }, + ], + }, + ], + }, + { + path: "/price-lists", + errorElement: , + handle: { + breadcrumb: () => t("priceLists.domain"), + }, + children: [ + { + path: "", + lazy: () => + import("../../routes/price-lists/price-list-list"), + children: [ + { + path: "create", + lazy: () => + import("../../routes/price-lists/price-list-create"), + }, + ], + }, + { + path: ":id", + lazy: async () => { + const { Component, Breadcrumb, loader } = await import( + "../../routes/price-lists/price-list-detail" + ) + + return { + Component, + loader, + handle: { + breadcrumb: ( + match: UIMatch + ) => , + }, + } + }, + children: [ + { + path: "edit", + lazy: () => + import("../../routes/price-lists/price-list-edit"), + }, + { + path: "configuration", + lazy: () => + import( + "../../routes/price-lists/price-list-configuration" + ), + }, + { + path: "products/add", + lazy: () => + import( + "../../routes/price-lists/price-list-prices-add" + ), + }, + { + path: "products/edit", + lazy: () => + import( + "../../routes/price-lists/price-list-prices-edit" + ), + }, + ], + }, + ], + }, + { + path: "/customers", + errorElement: , + handle: { + breadcrumb: () => t("customers.domain"), + }, + children: [ + { + path: "", + lazy: () => import("../../routes/customers/customer-list"), + children: [ + { + path: "create", + lazy: () => + import("../../routes/customers/customer-create"), + }, + ], + }, + { + path: ":id", + lazy: async () => { + const { Component, Breadcrumb, loader } = await import( + "../../routes/customers/customer-detail" + ) + + return { + Component, + loader, + handle: { + breadcrumb: ( + match: UIMatch + ) => , + }, + } + }, + children: [ + { + path: "edit", + lazy: () => + import("../../routes/customers/customer-edit"), + }, + { + path: "add-customer-groups", + lazy: () => + import( + "../../routes/customers/customers-add-customer-group" + ), + }, + { + path: ":order_id/transfer", + lazy: () => + import("../../routes/orders/order-request-transfer"), + }, + { + path: "metadata/edit", + lazy: () => + import("../../routes/customers/customer-metadata"), + }, + ], + }, + ], + }, + { + path: "/customer-groups", + errorElement: , + handle: { + breadcrumb: () => t("customerGroups.domain"), + }, + children: [ + { + path: "", + lazy: () => + import("../../routes/customer-groups/customer-group-list"), + children: [ + { + path: "create", + lazy: () => + import( + "../../routes/customer-groups/customer-group-create" + ), + }, + ], + }, + { + path: ":id", + lazy: async () => { + const { Component, Breadcrumb, loader } = await import( + "../../routes/customer-groups/customer-group-detail" + ) + + return { + Component, + loader, + handle: { + breadcrumb: ( + match: UIMatch + ) => , + }, + } + }, + children: [ + { + path: "edit", + lazy: () => + import( + "../../routes/customer-groups/customer-group-edit" + ), + }, + { + path: "add-customers", + lazy: () => + import( + "../../routes/customer-groups/customer-group-add-customers" + ), + }, + { + path: "metadata/edit", + lazy: () => + import( + "../../routes/customer-groups/customer-group-metadata" + ), + }, + ], + }, + ], + }, + { + path: "/reservations", + errorElement: , + handle: { + breadcrumb: () => t("reservations.domain"), + }, + children: [ + { + path: "", + lazy: () => + import("../../routes/reservations/reservation-list"), + children: [ + { + path: "create", + lazy: () => + import("../../routes/reservations/reservation-create"), + }, + ], + }, + { + path: ":id", + lazy: async () => { + const { Component, Breadcrumb, loader } = await import( + "../../routes/reservations/reservation-detail" + ) + + return { + Component, + loader, + handle: { + breadcrumb: ( + match: UIMatch + ) => , + }, + } + }, + children: [ + { + path: "edit", + lazy: () => + import( + "../../routes/reservations/reservation-detail/components/edit-reservation" + ), + }, + { + path: "metadata/edit", + lazy: () => + import( + "../../routes/reservations/reservation-metadata" + ), + }, + ], + }, + ], + }, + { + path: "/inventory", + errorElement: , + handle: { + breadcrumb: () => t("inventory.domain"), + }, + children: [ + { + path: "", + lazy: () => import("../../routes/inventory/inventory-list"), + children: [ + { + path: "create", + lazy: () => + import("../../routes/inventory/inventory-create"), + }, + { + path: "stock", + lazy: () => + import("../../routes/inventory/inventory-stock"), + }, + ], + }, + { + path: ":id", + lazy: async () => { + const { Component, Breadcrumb, loader } = await import( + "../../routes/inventory/inventory-detail" + ) + + return { + Component, + loader, + handle: { + breadcrumb: ( + match: UIMatch + ) => , + }, + } + }, + children: [ + { + path: "edit", + lazy: () => + import( + "../../routes/inventory/inventory-detail/components/edit-inventory-item" + ), + }, + { + path: "attributes", + lazy: () => + import( + "../../routes/inventory/inventory-detail/components/edit-inventory-item-attributes" + ), + }, + { + path: "metadata/edit", + lazy: () => + import("../../routes/inventory/inventory-metadata"), + }, + { + path: "locations", + lazy: () => + import( + "../../routes/inventory/inventory-detail/components/manage-locations" + ), + }, + { + path: "locations/:location_id", + lazy: () => + import( + "../../routes/inventory/inventory-detail/components/adjust-inventory" + ), + }, + ], + }, + ], + }, + ...coreRoutes, + ], + }, + ], + }, + { + element: , + errorElement: , + children: [ + { + path: "/settings", + handle: { + breadcrumb: () => t("app.nav.settings.header"), + }, + element: , + children: [ + { + index: true, + errorElement: , + lazy: () => import("../../routes/settings"), + }, + { + path: "profile", + errorElement: , + lazy: () => import("../../routes/profile/profile-detail"), + handle: { + breadcrumb: () => t("profile.domain"), + }, + children: [ + { + path: "edit", + lazy: () => import("../../routes/profile/profile-edit"), + }, + ], + }, + { + path: "regions", + errorElement: , + element: , + handle: { + breadcrumb: () => t("regions.domain"), + }, + children: [ + { + path: "", + lazy: () => import("../../routes/regions/region-list"), + children: [ + { + path: "create", + lazy: () => import("../../routes/regions/region-create"), + }, + ], + }, + { + path: ":id", + lazy: async () => { + const { Component, Breadcrumb, loader } = await import( + "../../routes/regions/region-detail" + ) + + return { + Component, + loader, + handle: { + breadcrumb: ( + match: UIMatch + ) => , + }, + } + }, + children: [ + { + path: "edit", + lazy: () => import("../../routes/regions/region-edit"), + }, + { + path: "countries/add", + lazy: () => + import("../../routes/regions/region-add-countries"), + }, + { + path: "metadata/edit", + lazy: () => + import("../../routes/regions/region-metadata"), + }, + ], + }, + ], + }, + { + path: "store", + errorElement: , + lazy: () => import("../../routes/store/store-detail"), + handle: { + breadcrumb: () => t("store.domain"), + }, + children: [ + { + path: "edit", + lazy: () => import("../../routes/store/store-edit"), + }, + { + path: "currencies", + lazy: () => import("../../routes/store/store-add-currencies"), + }, + { + path: "metadata/edit", + lazy: () => import("../../routes/store/store-metadata"), + }, + ], + }, + { + path: "users", + errorElement: , + element: , + handle: { + breadcrumb: () => t("users.domain"), + }, + children: [ + { + path: "", + lazy: () => import("../../routes/users/user-list"), + children: [ + { + path: "invite", + lazy: () => import("../../routes/users/user-invite"), + }, + ], + }, + { + path: ":id", + lazy: async () => { + const { Component, Breadcrumb, loader } = await import( + "../../routes/users/user-detail" + ) + + return { + Component, + loader, + handle: { + breadcrumb: ( + match: UIMatch + ) => , + }, + } + }, + children: [ + { + path: "edit", + lazy: () => import("../../routes/users/user-edit"), + }, + { + path: "metadata/edit", + lazy: () => import("../../routes/users/user-metadata"), + }, + ], + }, + ], + }, + { + path: "sales-channels", + errorElement: , + element: , + handle: { + breadcrumb: () => t("salesChannels.domain"), + }, + children: [ + { + path: "", + lazy: () => + import("../../routes/sales-channels/sales-channel-list"), + children: [ + { + path: "create", + lazy: () => + import( + "../../routes/sales-channels/sales-channel-create" + ), + }, + ], + }, + { + path: ":id", + lazy: async () => { + const { Component, Breadcrumb, loader } = await import( + "../../routes/sales-channels/sales-channel-detail" + ) + + return { + Component, + loader, + handle: { + breadcrumb: ( + match: UIMatch + ) => , + }, + } + }, + children: [ + { + path: "edit", + lazy: () => + import( + "../../routes/sales-channels/sales-channel-edit" + ), + }, + { + path: "add-products", + lazy: () => + import( + "../../routes/sales-channels/sales-channel-add-products" + ), + }, + { + path: "metadata/edit", + lazy: () => + import( + "../../routes/sales-channels/sales-channel-metadata" + ), + }, + ], + }, + ], + }, + { + path: "locations", + errorElement: , + element: , + handle: { + breadcrumb: () => t("locations.domain"), + }, + children: [ + { + path: "", + lazy: () => import("../../routes/locations/location-list"), + }, + { + path: "create", + lazy: () => import("../../routes/locations/location-create"), + }, + { + path: "shipping-profiles", + element: , + handle: { + breadcrumb: () => t("shippingProfile.domain"), + }, + children: [ + { + path: "", + lazy: () => + import( + "../../routes/shipping-profiles/shipping-profiles-list" + ), + children: [ + { + path: "create", + lazy: () => + import( + "../../routes/shipping-profiles/shipping-profile-create" + ), + }, + ], + }, + { + path: ":shipping_profile_id", + lazy: async () => { + const { Component, Breadcrumb, loader } = await import( + "../../routes/shipping-profiles/shipping-profile-detail" + ) + + return { + Component, + loader, + handle: { + breadcrumb: ( + // eslint-disable-next-line max-len + match: UIMatch + ) => , + }, + } + }, + children: [ + { + path: "metadata/edit", + lazy: () => + import( + "../../routes/shipping-profiles/shipping-profile-metadata" + ), + }, + ], + }, + ], + }, + { + path: ":location_id", + lazy: async () => { + const { Component, Breadcrumb, loader } = await import( + "../../routes/locations/location-detail" + ) + + return { + Component, + loader, + handle: { + breadcrumb: ( + match: UIMatch + ) => , + }, + } + }, + children: [ + { + path: "edit", + lazy: () => + import("../../routes/locations/location-edit"), + }, + { + path: "sales-channels", + lazy: () => + import( + "../../routes/locations/location-sales-channels" + ), + }, + { + path: "fulfillment-providers", + lazy: () => + import( + "../../routes/locations/location-fulfillment-providers" + ), + }, + { + path: "fulfillment-set/:fset_id", + children: [ + { + path: "service-zones/create", + lazy: () => + import( + "../../routes/locations/location-service-zone-create" + ), + }, + { + path: "service-zone/:zone_id", + children: [ + { + path: "edit", + lazy: () => + import( + "../../routes/locations/location-service-zone-edit" + ), + }, + { + path: "areas", + lazy: () => + import( + "../../routes/locations/location-service-zone-manage-areas" + ), + }, + { + path: "shipping-option", + children: [ + { + path: "create", + lazy: () => + import( + "../../routes/locations/location-service-zone-shipping-option-create" + ), + }, + { + path: ":so_id", + children: [ + { + path: "edit", + lazy: () => + import( + "../../routes/locations/location-service-zone-shipping-option-edit" + ), + }, + { + path: "pricing", + lazy: () => + import( + "../../routes/locations/location-service-zone-shipping-option-pricing" + ), + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + { + path: "product-tags", + errorElement: , + element: , + handle: { + breadcrumb: () => t("productTags.domain"), + }, + children: [ + { + path: "", + lazy: () => + import("../../routes/product-tags/product-tag-list"), + children: [ + { + path: "create", + lazy: () => + import("../../routes/product-tags/product-tag-create"), + }, + ], + }, + { + path: ":id", + lazy: async () => { + const { Component, Breadcrumb, loader } = await import( + "../../routes/product-tags/product-tag-detail" + ) + + return { + Component, + loader, + handle: { + breadcrumb: ( + match: UIMatch + ) => , + }, + } + }, + children: [ + { + path: "edit", + lazy: () => + import("../../routes/product-tags/product-tag-edit"), + }, + ], + }, + ], + }, + { + path: "workflows", + errorElement: , + element: , + handle: { + breadcrumb: () => t("workflowExecutions.domain"), + }, + children: [ + { + path: "", + lazy: () => + import( + "../../routes/workflow-executions/workflow-execution-list" + ), + }, + { + path: ":id", + lazy: async () => { + const { Component, Breadcrumb, loader } = await import( + "../../routes/workflow-executions/workflow-execution-detail" + ) + + return { + Component, + loader, + handle: { + breadcrumb: ( + // eslint-disable-next-line max-len + match: UIMatch + ) => , + }, + } + }, + }, + ], + }, + { + path: "product-types", + errorElement: , + element: , + handle: { + breadcrumb: () => t("productTypes.domain"), + }, + children: [ + { + path: "", + lazy: () => + import("../../routes/product-types/product-type-list"), + children: [ + { + path: "create", + lazy: () => + import( + "../../routes/product-types/product-type-create" + ), + }, + ], + }, + { + path: ":id", + lazy: async () => { + const { Component, Breadcrumb, loader } = await import( + "../../routes/product-types/product-type-detail" + ) + + return { + Component, + loader, + handle: { + breadcrumb: ( + match: UIMatch + ) => , + }, + } + }, + children: [ + { + path: "edit", + lazy: () => + import("../../routes/product-types/product-type-edit"), + }, + ], + }, + ], + }, + { + path: "publishable-api-keys", + element: , + handle: { + breadcrumb: () => t("apiKeyManagement.domain.publishable"), + }, + children: [ + { + path: "", + element: , + children: [ + { + path: "", + lazy: () => + import( + "../../routes/api-key-management/api-key-management-list" + ), + children: [ + { + path: "create", + lazy: () => + import( + "../../routes/api-key-management/api-key-management-create" + ), + }, + ], + }, + ], + }, + { + path: ":id", + lazy: async () => { + const { Component, Breadcrumb, loader } = await import( + "../../routes/api-key-management/api-key-management-detail" + ) + + return { + Component, + loader, + handle: { + breadcrumb: ( + match: UIMatch + ) => , + }, + } + }, + children: [ + { + path: "edit", + lazy: () => + import( + "../../routes/api-key-management/api-key-management-edit" + ), + }, + { + path: "sales-channels", + lazy: () => + import( + "../../routes/api-key-management/api-key-management-sales-channels" + ), + }, + ], + }, + ], + }, + { + path: "secret-api-keys", + element: , + handle: { + breadcrumb: () => t("apiKeyManagement.domain.secret"), + }, + children: [ + { + path: "", + element: , + children: [ + { + path: "", + lazy: () => + import( + "../../routes/api-key-management/api-key-management-list" + ), + children: [ + { + path: "create", + lazy: () => + import( + "../../routes/api-key-management/api-key-management-create" + ), + }, + ], + }, + ], + }, + { + path: ":id", + lazy: async () => { + const { Component, Breadcrumb, loader } = await import( + "../../routes/api-key-management/api-key-management-detail" + ) + + return { + Component, + loader, + handle: { + breadcrumb: ( + match: UIMatch + ) => , + }, + } + }, + children: [ + { + path: "edit", + lazy: () => + import( + "../../routes/api-key-management/api-key-management-edit" + ), + }, + ], + }, + ], + }, + { + path: "tax-regions", + element: , + handle: { + breadcrumb: () => t("taxRegions.domain"), + }, + children: [ + { + path: "", + lazy: () => + import("../../routes/tax-regions/tax-region-list"), + children: [ + { + path: "create", + lazy: () => + import("../../routes/tax-regions/tax-region-create"), + }, + ], + }, + { + path: ":id", + Component: Outlet, + loader: taxRegionLoader, + handle: { + breadcrumb: ( + match: UIMatch + ) => , + }, + children: [ + { + path: "", + lazy: async () => { + const { Component } = await import( + "../../routes/tax-regions/tax-region-detail" + ) + + return { + Component, + } + }, + children: [ + { + path: "provinces/create", + lazy: () => + import( + "../../routes/tax-regions/tax-region-province-create" + ), + }, + { + path: "overrides/create", + lazy: () => + import( + "../../routes/tax-regions/tax-region-tax-override-create" + ), + }, + { + path: "overrides/:tax_rate_id/edit", + lazy: () => + import( + "../../routes/tax-regions/tax-region-tax-override-edit" + ), + }, + { + path: "tax-rates/create", + lazy: () => + import( + "../../routes/tax-regions/tax-region-tax-rate-create" + ), + }, + { + path: "tax-rates/:tax_rate_id/edit", + lazy: () => + import( + "../../routes/tax-regions/tax-region-tax-rate-edit" + ), + }, + ], + }, + { + path: "provinces/:province_id", + lazy: async () => { + const { Component, Breadcrumb, loader } = await import( + "../../routes/tax-regions/tax-region-province-detail" + ) + + return { + Component, + loader, + handle: { + breadcrumb: ( + match: UIMatch + ) => , + }, + } + }, + children: [ + { + path: "tax-rates/create", + lazy: () => + import( + "../../routes/tax-regions/tax-region-tax-rate-create" + ), + }, + { + path: "tax-rates/:tax_rate_id/edit", + lazy: () => + import( + "../../routes/tax-regions/tax-region-tax-rate-edit" + ), + }, + { + path: "overrides/create", + lazy: () => + import( + "../../routes/tax-regions/tax-region-tax-override-create" + ), + }, + { + path: "overrides/:tax_rate_id/edit", + lazy: () => + import( + "../../routes/tax-regions/tax-region-tax-override-edit" + ), + }, + ], + }, + ], + }, + ], + }, + { + path: "return-reasons", + element: , + handle: { + breadcrumb: () => t("returnReasons.domain"), + }, + children: [ + { + path: "", + lazy: () => + import("../../routes/return-reasons/return-reason-list"), + children: [ + { + path: "create", + lazy: () => + import( + "../../routes/return-reasons/return-reason-create" + ), + }, + + { + path: ":id", + children: [ + { + path: "edit", + lazy: () => + import( + "../../routes/return-reasons/return-reason-edit" + ), + }, + ], + }, + ], + }, + ], + }, + ...settingsRoutes, + ], + }, + ], + }, + { + element: , + children: [ + { + errorElement: , + children: [ + { + path: "/login", + lazy: () => import("../../routes/login"), + }, + { + path: "/reset-password", + lazy: () => import("../../routes/reset-password"), + }, + { + path: "/invite", + lazy: () => import("../../routes/invite"), + }, + { + path: "*", + lazy: () => import("../../routes/no-match"), + }, + ], + }, + ], + }, + ] +} diff --git a/packages/admin/dashboard/src/extensions/routes/utils.ts b/packages/admin/dashboard/src/dashboard-app/routes/utils.ts similarity index 98% rename from packages/admin/dashboard/src/extensions/routes/utils.ts rename to packages/admin/dashboard/src/dashboard-app/routes/utils.ts index af2eb1aa60..d03f598a46 100644 --- a/packages/admin/dashboard/src/extensions/routes/utils.ts +++ b/packages/admin/dashboard/src/dashboard-app/routes/utils.ts @@ -137,7 +137,6 @@ const addRoute = ( if (!route) { route = createBranchRoute(currentSegment) - currentLevel.push(route) } const currentFullPath = fullPath @@ -157,8 +156,14 @@ const addRoute = ( route.handle = handle } + if (loader) { + route.loader = loader + } + leaf.children = processParallelRoutes(parallelRoutes, currentFullPath) route.children.push(leaf) + + currentLevel.push(route) } else { route.children ||= [] addRoute( diff --git a/packages/admin/dashboard/src/extensions/types.ts b/packages/admin/dashboard/src/dashboard-app/types.ts similarity index 87% rename from packages/admin/dashboard/src/extensions/types.ts rename to packages/admin/dashboard/src/dashboard-app/types.ts index 4d42070d69..7b3470f66e 100644 --- a/packages/admin/dashboard/src/extensions/types.ts +++ b/packages/admin/dashboard/src/dashboard-app/types.ts @@ -9,6 +9,7 @@ import { import { ComponentType } from "react" import { LoaderFunction } from "react-router-dom" import { ZodFirstPartySchemaTypes } from "zod" +import { INavItem } from "../components/layout/nav-item" export type RouteExtension = { Component: ComponentType @@ -119,3 +120,15 @@ export type DisplayMap = Map< CustomFieldModel, Map[]> > + +export type MenuMap = Map + +export type WidgetMap = Map + +export type DashboardPlugin = { + formModule: FormModule + displayModule: DisplayModule + menuItemModule: MenuItemModule + widgetModule: WidgetModule + routeModule: RouteModule +} diff --git a/packages/admin/dashboard/src/extensions/dashboard-extension-manager/index.ts b/packages/admin/dashboard/src/extensions/dashboard-extension-manager/index.ts deleted file mode 100644 index 456fea9b72..0000000000 --- a/packages/admin/dashboard/src/extensions/dashboard-extension-manager/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./dashboard-extension-manager"; - diff --git a/packages/admin/dashboard/src/extensions/dashboard-extension-provider/dashboard-extension-context.tsx b/packages/admin/dashboard/src/extensions/dashboard-extension-provider/dashboard-extension-context.tsx deleted file mode 100644 index f3afbf0576..0000000000 --- a/packages/admin/dashboard/src/extensions/dashboard-extension-provider/dashboard-extension-context.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import { createContext } from "react" -import { DashboardExtensionManager } from "../dashboard-extension-manager" - -type DasboardExtenstionContextValue = DashboardExtensionManager["api"] - -export const DashboardExtensionContext = - createContext(null) diff --git a/packages/admin/dashboard/src/extensions/dashboard-extension-provider/dashboard-extension-provider.tsx b/packages/admin/dashboard/src/extensions/dashboard-extension-provider/dashboard-extension-provider.tsx deleted file mode 100644 index 4efcb53787..0000000000 --- a/packages/admin/dashboard/src/extensions/dashboard-extension-provider/dashboard-extension-provider.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { PropsWithChildren } from "react" -import { DashboardExtensionManager } from "../dashboard-extension-manager/dashboard-extension-manager" -import { DashboardExtensionContext } from "./dashboard-extension-context" - -type DashboardExtensionProviderProps = PropsWithChildren<{ - api: DashboardExtensionManager["api"] -}> - -export const DashboardExtensionProvider = ({ - api, - children, -}: DashboardExtensionProviderProps) => { - return ( - - {children} - - ) -} diff --git a/packages/admin/dashboard/src/extensions/dashboard-extension-provider/index.ts b/packages/admin/dashboard/src/extensions/dashboard-extension-provider/index.ts deleted file mode 100644 index be9ca07a36..0000000000 --- a/packages/admin/dashboard/src/extensions/dashboard-extension-provider/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { DashboardExtensionProvider } from "./dashboard-extension-provider" -export { useDashboardExtension } from "./use-dashboard-extension" diff --git a/packages/admin/dashboard/src/extensions/dashboard-extension-provider/use-dashboard-extension.tsx b/packages/admin/dashboard/src/extensions/dashboard-extension-provider/use-dashboard-extension.tsx deleted file mode 100644 index 0c0a937188..0000000000 --- a/packages/admin/dashboard/src/extensions/dashboard-extension-provider/use-dashboard-extension.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { useContext } from "react" -import { DashboardExtensionContext } from "./dashboard-extension-context" - -export const useDashboardExtension = () => { - const context = useContext(DashboardExtensionContext) - if (!context) { - throw new Error( - "useDashboardExtension must be used within a DashboardExtensionProvider" - ) - } - return context -} diff --git a/packages/admin/dashboard/src/index.ts b/packages/admin/dashboard/src/index.ts new file mode 100644 index 0000000000..be69b51b82 --- /dev/null +++ b/packages/admin/dashboard/src/index.ts @@ -0,0 +1,2 @@ +export type { DashboardPlugin } from "./dashboard-app/dashboard-app" +export * from "./render" diff --git a/packages/admin/dashboard/src/providers/extension-provider/extension-context.tsx b/packages/admin/dashboard/src/providers/extension-provider/extension-context.tsx new file mode 100644 index 0000000000..cc490788dc --- /dev/null +++ b/packages/admin/dashboard/src/providers/extension-provider/extension-context.tsx @@ -0,0 +1,8 @@ +import { createContext } from "react" +import { DashboardApp } from "../../dashboard-app" + +type ExtensionContextValue = DashboardApp["api"] + +export const ExtensionContext = createContext( + null +) diff --git a/packages/admin/dashboard/src/providers/extension-provider/extension-provider.tsx b/packages/admin/dashboard/src/providers/extension-provider/extension-provider.tsx new file mode 100644 index 0000000000..37da07743c --- /dev/null +++ b/packages/admin/dashboard/src/providers/extension-provider/extension-provider.tsx @@ -0,0 +1,18 @@ +import { PropsWithChildren } from "react" +import { DashboardApp } from "../../dashboard-app/dashboard-app" +import { ExtensionContext } from "./extension-context" + +type ExtensionProviderProps = PropsWithChildren<{ + api: DashboardApp["api"] +}> + +export const ExtensionProvider = ({ + api, + children, +}: ExtensionProviderProps) => { + return ( + + {children} + + ) +} diff --git a/packages/admin/dashboard/src/providers/extension-provider/index.ts b/packages/admin/dashboard/src/providers/extension-provider/index.ts new file mode 100644 index 0000000000..7bf5e76c40 --- /dev/null +++ b/packages/admin/dashboard/src/providers/extension-provider/index.ts @@ -0,0 +1,2 @@ +export { ExtensionProvider } from "./extension-provider" +export { useExtension } from "./use-extension" diff --git a/packages/admin/dashboard/src/providers/extension-provider/use-extension.tsx b/packages/admin/dashboard/src/providers/extension-provider/use-extension.tsx new file mode 100644 index 0000000000..bab2a8b2b1 --- /dev/null +++ b/packages/admin/dashboard/src/providers/extension-provider/use-extension.tsx @@ -0,0 +1,10 @@ +import { useContext } from "react" +import { ExtensionContext } from "./extension-context" + +export const useExtension = () => { + const context = useContext(ExtensionContext) + if (!context) { + throw new Error("useExtension must be used within a ExtensionProvider") + } + return context +} diff --git a/packages/admin/dashboard/src/providers/providers.tsx b/packages/admin/dashboard/src/providers/providers.tsx index c52ad0ad97..9386b4abcc 100644 --- a/packages/admin/dashboard/src/providers/providers.tsx +++ b/packages/admin/dashboard/src/providers/providers.tsx @@ -3,22 +3,20 @@ import { QueryClientProvider } from "@tanstack/react-query" import type { PropsWithChildren } from "react" import { HelmetProvider } from "react-helmet-async" import { I18n } from "../components/utilities/i18n" -import { - DashboardExtensionManager, - DashboardExtensionProvider, -} from "../extensions" +import { DashboardApp } from "../dashboard-app" import { queryClient } from "../lib/query-client" +import { ExtensionProvider } from "./extension-provider" import { I18nProvider } from "./i18n-provider" import { ThemeProvider } from "./theme-provider" type ProvidersProps = PropsWithChildren<{ - api: DashboardExtensionManager["api"] + api: DashboardApp["api"] }> export const Providers = ({ api, children }: ProvidersProps) => { return ( - + @@ -28,7 +26,7 @@ export const Providers = ({ api, children }: ProvidersProps) => { - + ) } diff --git a/packages/admin/dashboard/src/providers/router-provider/index.ts b/packages/admin/dashboard/src/providers/router-provider/index.ts deleted file mode 100644 index 997dca4e24..0000000000 --- a/packages/admin/dashboard/src/providers/router-provider/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./router-provider" diff --git a/packages/admin/dashboard/src/providers/router-provider/route-extensions.tsx b/packages/admin/dashboard/src/providers/router-provider/route-extensions.tsx deleted file mode 100644 index 4e66e8c472..0000000000 --- a/packages/admin/dashboard/src/providers/router-provider/route-extensions.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import routeModule from "virtual:medusa/routes" -import { - createRouteMap, - getRouteExtensions, -} from "../../extensions/routes/utils" - -const routes = getRouteExtensions(routeModule, "core") - -/** - * Core Route extensions. - */ -export const RouteExtensions = createRouteMap(routes) -console.log(RouteExtensions) diff --git a/packages/admin/dashboard/src/providers/router-provider/route-map.tsx b/packages/admin/dashboard/src/providers/router-provider/route-map.tsx deleted file mode 100644 index d47846e10c..0000000000 --- a/packages/admin/dashboard/src/providers/router-provider/route-map.tsx +++ /dev/null @@ -1,1688 +0,0 @@ -import { HttpTypes } from "@medusajs/types" -import { Outlet, RouteObject, UIMatch } from "react-router-dom" - -import { t } from "i18next" -import { ProtectedRoute } from "../../components/authentication/protected-route" -import { MainLayout } from "../../components/layout/main-layout" -import { PublicLayout } from "../../components/layout/public-layout" -import { SettingsLayout } from "../../components/layout/settings-layout" -import { ErrorBoundary } from "../../components/utilities/error-boundary" -import { TaxRegionDetailBreadcrumb } from "../../routes/tax-regions/tax-region-detail/breadcrumb" -import { taxRegionLoader } from "../../routes/tax-regions/tax-region-detail/loader" -import { RouteExtensions } from "./route-extensions" -import { SettingsExtensions } from "./settings-extensions" - -export const RouteMap: RouteObject[] = [ - { - element: , - errorElement: , - children: [ - { - element: , - children: [ - { - path: "/", - errorElement: , - lazy: () => import("../../routes/home"), - }, - { - path: "/products", - errorElement: , - handle: { - breadcrumb: () => t("products.domain"), - }, - children: [ - { - path: "", - lazy: () => import("../../routes/products/product-list"), - children: [ - { - path: "create", - lazy: () => import("../../routes/products/product-create"), - }, - { - path: "import", - lazy: () => import("../../routes/products/product-import"), - }, - { - path: "export", - lazy: () => import("../../routes/products/product-export"), - }, - ], - }, - { - path: ":id", - errorElement: , - lazy: async () => { - const { Breadcrumb, loader } = await import( - "../../routes/products/product-detail" - ) - - return { - Component: Outlet, - loader, - handle: { - breadcrumb: ( - match: UIMatch - ) => , - }, - } - }, - children: [ - { - path: "", - lazy: () => import("../../routes/products/product-detail"), - children: [ - { - path: "edit", - lazy: () => - import("../../routes/products/product-edit"), - }, - { - path: "edit-variant", - lazy: () => - import( - "../../routes/product-variants/product-variant-edit" - ), - }, - { - path: "sales-channels", - lazy: () => - import( - "../../routes/products/product-sales-channels" - ), - }, - { - path: "attributes", - lazy: () => - import("../../routes/products/product-attributes"), - }, - { - path: "organization", - lazy: () => - import("../../routes/products/product-organization"), - }, - { - path: "shipping-profile", - lazy: () => - import( - "../../routes/products/product-shipping-profile" - ), - }, - { - path: "media", - lazy: () => - import("../../routes/products/product-media"), - }, - { - path: "prices", - lazy: () => - import("../../routes/products/product-prices"), - }, - { - path: "options/create", - lazy: () => - import("../../routes/products/product-create-option"), - }, - { - path: "options/:option_id/edit", - lazy: () => - import("../../routes/products/product-edit-option"), - }, - { - path: "variants/create", - lazy: () => - import( - "../../routes/products/product-create-variant" - ), - }, - { - path: "stock", - lazy: () => - import("../../routes/products/product-stock"), - }, - { - path: "metadata/edit", - lazy: () => - import("../../routes/products/product-metadata"), - }, - ], - }, - { - path: "variants/:variant_id", - lazy: async () => { - const { Component, Breadcrumb, loader } = await import( - "../../routes/product-variants/product-variant-detail" - ) - - return { - Component, - loader, - handle: { - breadcrumb: ( - // eslint-disable-next-line max-len - match: UIMatch - ) => , - }, - } - }, - children: [ - { - path: "edit", - lazy: () => - import( - "../../routes/product-variants/product-variant-edit" - ), - }, - { - path: "prices", - lazy: () => - import("../../routes/products/product-prices"), - }, - { - path: "manage-items", - lazy: () => - import( - "../../routes/product-variants/product-variant-manage-inventory-items" - ), - }, - { - path: "metadata/edit", - lazy: () => - import( - "../../routes/product-variants/product-variant-metadata" - ), - }, - ], - }, - ], - }, - ], - }, - { - path: "/categories", - errorElement: , - handle: { - breadcrumb: () => t("categories.domain"), - }, - children: [ - { - path: "", - lazy: () => import("../../routes/categories/category-list"), - children: [ - { - path: "create", - lazy: () => - import("../../routes/categories/category-create"), - }, - { - path: "organize", - lazy: () => - import("../../routes/categories/category-organize"), - }, - ], - }, - { - path: ":id", - lazy: async () => { - const { Component, Breadcrumb, loader } = await import( - "../../routes/categories/category-detail" - ) - - return { - Component, - loader, - handle: { - breadcrumb: ( - match: UIMatch - ) => , - }, - } - }, - children: [ - { - path: "edit", - lazy: () => import("../../routes/categories/category-edit"), - }, - { - path: "products", - lazy: () => - import("../../routes/categories/category-products"), - }, - { - path: "organize", - lazy: () => - import("../../routes/categories/category-organize"), - }, - { - path: "metadata/edit", - lazy: () => - import("../../routes/categories/categories-metadata"), - }, - ], - }, - ], - }, - { - path: "/orders", - errorElement: , - handle: { - breadcrumb: () => t("orders.domain"), - }, - children: [ - { - path: "", - lazy: () => import("../../routes/orders/order-list"), - }, - { - path: ":id", - lazy: async () => { - const { Component, Breadcrumb, loader } = await import( - "../../routes/orders/order-detail" - ) - - return { - Component, - loader, - handle: { - breadcrumb: ( - match: UIMatch - ) => , - }, - } - }, - children: [ - { - path: "fulfillment", - lazy: () => - import("../../routes/orders/order-create-fulfillment"), - }, - { - path: "returns/:return_id/receive", - lazy: () => - import("../../routes/orders/order-receive-return"), - }, - { - path: "allocate-items", - lazy: () => - import("../../routes/orders/order-allocate-items"), - }, - { - path: ":f_id/create-shipment", - lazy: () => - import("../../routes/orders/order-create-shipment"), - }, - { - path: "returns", - lazy: () => - import("../../routes/orders/order-create-return"), - }, - { - path: "claims", - lazy: () => - import("../../routes/orders/order-create-claim"), - }, - { - path: "exchanges", - lazy: () => - import("../../routes/orders/order-create-exchange"), - }, - { - path: "edits", - lazy: () => import("../../routes/orders/order-create-edit"), - }, - { - path: "refund", - lazy: () => - import("../../routes/orders/order-create-refund"), - }, - { - path: "transfer", - lazy: () => - import("../../routes/orders/order-request-transfer"), - }, - { - path: "email", - lazy: () => import("../../routes/orders/order-edit-email"), - }, - { - path: "shipping-address", - lazy: () => - import("../../routes/orders/order-edit-shipping-address"), - }, - { - path: "billing-address", - lazy: () => - import("../../routes/orders/order-edit-billing-address"), - }, - { - path: "metadata/edit", - lazy: () => import("../../routes/orders/order-metadata"), - }, - ], - }, - ], - }, - { - path: "/promotions", - errorElement: , - handle: { - breadcrumb: () => t("promotions.domain"), - }, - children: [ - { - path: "", - lazy: () => import("../../routes/promotions/promotion-list"), - }, - { - path: "create", - lazy: () => import("../../routes/promotions/promotion-create"), - }, - { - path: ":id", - lazy: async () => { - const { Component, Breadcrumb, loader } = await import( - "../../routes/promotions/promotion-detail" - ) - - return { - Component, - loader, - handle: { - breadcrumb: ( - match: UIMatch - ) => , - }, - } - }, - children: [ - { - path: "edit", - lazy: () => - import("../../routes/promotions/promotion-edit-details"), - }, - { - path: "add-to-campaign", - lazy: () => - import("../../routes/promotions/promotion-add-campaign"), - }, - { - path: ":ruleType/edit", - lazy: () => - import("../../routes/promotions/common/edit-rules"), - }, - ], - }, - ], - }, - { - path: "/campaigns", - errorElement: , - handle: { - breadcrumb: () => t("campaigns.domain"), - }, - children: [ - { - path: "", - lazy: () => import("../../routes/campaigns/campaign-list"), - children: [], - }, - { - path: "create", - lazy: () => import("../../routes/campaigns/campaign-create"), - }, - { - path: ":id", - lazy: async () => { - const { Component, Breadcrumb, loader } = await import( - "../../routes/campaigns/campaign-detail" - ) - - return { - Component, - loader, - handle: { - breadcrumb: ( - match: UIMatch - ) => , - }, - } - }, - children: [ - { - path: "edit", - lazy: () => import("../../routes/campaigns/campaign-edit"), - }, - { - path: "configuration", - lazy: () => - import("../../routes/campaigns/campaign-configuration"), - }, - { - path: "edit-budget", - lazy: () => - import("../../routes/campaigns/campaign-budget-edit"), - }, - { - path: "add-promotions", - lazy: () => - import("../../routes/campaigns/add-campaign-promotions"), - }, - ], - }, - ], - }, - { - path: "/collections", - errorElement: , - handle: { - breadcrumb: () => t("collections.domain"), - }, - children: [ - { - path: "", - lazy: () => import("../../routes/collections/collection-list"), - children: [ - { - path: "create", - lazy: () => - import("../../routes/collections/collection-create"), - }, - ], - }, - { - path: ":id", - lazy: async () => { - const { Component, Breadcrumb, loader } = await import( - "../../routes/collections/collection-detail" - ) - - return { - Component, - loader, - handle: { - breadcrumb: ( - match: UIMatch - ) => , - }, - } - }, - children: [ - { - path: "edit", - lazy: () => - import("../../routes/collections/collection-edit"), - }, - { - path: "products", - lazy: () => - import( - "../../routes/collections/collection-add-products" - ), - }, - { - path: "metadata/edit", - lazy: () => - import("../../routes/collections/collection-metadata"), - }, - ], - }, - ], - }, - { - path: "/price-lists", - errorElement: , - handle: { - breadcrumb: () => t("priceLists.domain"), - }, - children: [ - { - path: "", - lazy: () => import("../../routes/price-lists/price-list-list"), - children: [ - { - path: "create", - lazy: () => - import("../../routes/price-lists/price-list-create"), - }, - ], - }, - { - path: ":id", - lazy: async () => { - const { Component, Breadcrumb, loader } = await import( - "../../routes/price-lists/price-list-detail" - ) - - return { - Component, - loader, - handle: { - breadcrumb: ( - match: UIMatch - ) => , - }, - } - }, - children: [ - { - path: "edit", - lazy: () => - import("../../routes/price-lists/price-list-edit"), - }, - { - path: "configuration", - lazy: () => - import( - "../../routes/price-lists/price-list-configuration" - ), - }, - { - path: "products/add", - lazy: () => - import("../../routes/price-lists/price-list-prices-add"), - }, - { - path: "products/edit", - lazy: () => - import("../../routes/price-lists/price-list-prices-edit"), - }, - ], - }, - ], - }, - { - path: "/customers", - errorElement: , - handle: { - breadcrumb: () => t("customers.domain"), - }, - children: [ - { - path: "", - lazy: () => import("../../routes/customers/customer-list"), - children: [ - { - path: "create", - lazy: () => - import("../../routes/customers/customer-create"), - }, - ], - }, - { - path: ":id", - lazy: async () => { - const { Component, Breadcrumb, loader } = await import( - "../../routes/customers/customer-detail" - ) - - return { - Component, - loader, - handle: { - breadcrumb: ( - match: UIMatch - ) => , - }, - } - }, - children: [ - { - path: "edit", - lazy: () => import("../../routes/customers/customer-edit"), - }, - { - path: "add-customer-groups", - lazy: () => - import( - "../../routes/customers/customers-add-customer-group" - ), - }, - { - path: ":order_id/transfer", - lazy: () => - import("../../routes/orders/order-request-transfer"), - }, - { - path: "metadata/edit", - lazy: () => - import("../../routes/customers/customer-metadata"), - }, - ], - }, - ], - }, - { - path: "/customer-groups", - errorElement: , - handle: { - breadcrumb: () => t("customerGroups.domain"), - }, - children: [ - { - path: "", - lazy: () => - import("../../routes/customer-groups/customer-group-list"), - children: [ - { - path: "create", - lazy: () => - import( - "../../routes/customer-groups/customer-group-create" - ), - }, - ], - }, - { - path: ":id", - lazy: async () => { - const { Component, Breadcrumb, loader } = await import( - "../../routes/customer-groups/customer-group-detail" - ) - - return { - Component, - loader, - handle: { - breadcrumb: ( - match: UIMatch - ) => , - }, - } - }, - children: [ - { - path: "edit", - lazy: () => - import( - "../../routes/customer-groups/customer-group-edit" - ), - }, - { - path: "add-customers", - lazy: () => - import( - "../../routes/customer-groups/customer-group-add-customers" - ), - }, - { - path: "metadata/edit", - lazy: () => - import( - "../../routes/customer-groups/customer-group-metadata" - ), - }, - ], - }, - ], - }, - { - path: "/reservations", - errorElement: , - handle: { - breadcrumb: () => t("reservations.domain"), - }, - children: [ - { - path: "", - lazy: () => - import("../../routes/reservations/reservation-list"), - children: [ - { - path: "create", - lazy: () => - import("../../routes/reservations/reservation-create"), - }, - ], - }, - { - path: ":id", - lazy: async () => { - const { Component, Breadcrumb, loader } = await import( - "../../routes/reservations/reservation-detail" - ) - - return { - Component, - loader, - handle: { - breadcrumb: ( - match: UIMatch - ) => , - }, - } - }, - children: [ - { - path: "edit", - lazy: () => - import( - "../../routes/reservations/reservation-detail/components/edit-reservation" - ), - }, - { - path: "metadata/edit", - lazy: () => - import("../../routes/reservations/reservation-metadata"), - }, - ], - }, - ], - }, - { - path: "/inventory", - errorElement: , - handle: { - breadcrumb: () => t("inventory.domain"), - }, - children: [ - { - path: "", - lazy: () => import("../../routes/inventory/inventory-list"), - children: [ - { - path: "create", - lazy: () => - import("../../routes/inventory/inventory-create"), - }, - { - path: "stock", - lazy: () => - import("../../routes/inventory/inventory-stock"), - }, - ], - }, - { - path: ":id", - lazy: async () => { - const { Component, Breadcrumb, loader } = await import( - "../../routes/inventory/inventory-detail" - ) - - return { - Component, - loader, - handle: { - breadcrumb: ( - match: UIMatch - ) => , - }, - } - }, - children: [ - { - path: "edit", - lazy: () => - import( - "../../routes/inventory/inventory-detail/components/edit-inventory-item" - ), - }, - { - path: "attributes", - lazy: () => - import( - "../../routes/inventory/inventory-detail/components/edit-inventory-item-attributes" - ), - }, - { - path: "metadata/edit", - lazy: () => - import("../../routes/inventory/inventory-metadata"), - }, - { - path: "locations", - lazy: () => - import( - "../../routes/inventory/inventory-detail/components/manage-locations" - ), - }, - { - path: "locations/:location_id", - lazy: () => - import( - "../../routes/inventory/inventory-detail/components/adjust-inventory" - ), - }, - ], - }, - ], - }, - ...RouteExtensions, - ], - }, - ], - }, - { - element: , - errorElement: , - children: [ - { - path: "/settings", - handle: { - breadcrumb: () => t("app.nav.settings.header"), - }, - element: , - children: [ - { - index: true, - errorElement: , - lazy: () => import("../../routes/settings"), - }, - { - path: "profile", - errorElement: , - lazy: () => import("../../routes/profile/profile-detail"), - handle: { - breadcrumb: () => t("profile.domain"), - }, - children: [ - { - path: "edit", - lazy: () => import("../../routes/profile/profile-edit"), - }, - ], - }, - { - path: "regions", - errorElement: , - element: , - handle: { - breadcrumb: () => t("regions.domain"), - }, - children: [ - { - path: "", - lazy: () => import("../../routes/regions/region-list"), - children: [ - { - path: "create", - lazy: () => import("../../routes/regions/region-create"), - }, - ], - }, - { - path: ":id", - lazy: async () => { - const { Component, Breadcrumb, loader } = await import( - "../../routes/regions/region-detail" - ) - - return { - Component, - loader, - handle: { - breadcrumb: ( - match: UIMatch - ) => , - }, - } - }, - children: [ - { - path: "edit", - lazy: () => import("../../routes/regions/region-edit"), - }, - { - path: "countries/add", - lazy: () => - import("../../routes/regions/region-add-countries"), - }, - { - path: "metadata/edit", - lazy: () => import("../../routes/regions/region-metadata"), - }, - ], - }, - ], - }, - { - path: "store", - errorElement: , - lazy: () => import("../../routes/store/store-detail"), - handle: { - breadcrumb: () => t("store.domain"), - }, - children: [ - { - path: "edit", - lazy: () => import("../../routes/store/store-edit"), - }, - { - path: "currencies", - lazy: () => import("../../routes/store/store-add-currencies"), - }, - { - path: "metadata/edit", - lazy: () => import("../../routes/store/store-metadata"), - }, - ], - }, - { - path: "users", - errorElement: , - element: , - handle: { - breadcrumb: () => t("users.domain"), - }, - children: [ - { - path: "", - lazy: () => import("../../routes/users/user-list"), - children: [ - { - path: "invite", - lazy: () => import("../../routes/users/user-invite"), - }, - ], - }, - { - path: ":id", - lazy: async () => { - const { Component, Breadcrumb, loader } = await import( - "../../routes/users/user-detail" - ) - - return { - Component, - loader, - handle: { - breadcrumb: ( - match: UIMatch - ) => , - }, - } - }, - children: [ - { - path: "edit", - lazy: () => import("../../routes/users/user-edit"), - }, - { - path: "metadata/edit", - lazy: () => import("../../routes/users/user-metadata"), - }, - ], - }, - ], - }, - { - path: "sales-channels", - errorElement: , - element: , - handle: { - breadcrumb: () => t("salesChannels.domain"), - }, - children: [ - { - path: "", - lazy: () => - import("../../routes/sales-channels/sales-channel-list"), - children: [ - { - path: "create", - lazy: () => - import( - "../../routes/sales-channels/sales-channel-create" - ), - }, - ], - }, - { - path: ":id", - lazy: async () => { - const { Component, Breadcrumb, loader } = await import( - "../../routes/sales-channels/sales-channel-detail" - ) - - return { - Component, - loader, - handle: { - breadcrumb: ( - match: UIMatch - ) => , - }, - } - }, - children: [ - { - path: "edit", - lazy: () => - import("../../routes/sales-channels/sales-channel-edit"), - }, - { - path: "add-products", - lazy: () => - import( - "../../routes/sales-channels/sales-channel-add-products" - ), - }, - { - path: "metadata/edit", - lazy: () => - import( - "../../routes/sales-channels/sales-channel-metadata" - ), - }, - ], - }, - ], - }, - { - path: "locations", - errorElement: , - element: , - handle: { - breadcrumb: () => t("locations.domain"), - }, - children: [ - { - path: "", - lazy: () => import("../../routes/locations/location-list"), - }, - { - path: "create", - lazy: () => import("../../routes/locations/location-create"), - }, - { - path: "shipping-profiles", - element: , - handle: { - breadcrumb: () => t("shippingProfile.domain"), - }, - children: [ - { - path: "", - lazy: () => - import( - "../../routes/shipping-profiles/shipping-profiles-list" - ), - children: [ - { - path: "create", - lazy: () => - import( - "../../routes/shipping-profiles/shipping-profile-create" - ), - }, - ], - }, - { - path: ":shipping_profile_id", - lazy: async () => { - const { Component, Breadcrumb, loader } = await import( - "../../routes/shipping-profiles/shipping-profile-detail" - ) - - return { - Component, - loader, - handle: { - breadcrumb: ( - // eslint-disable-next-line max-len - match: UIMatch - ) => , - }, - } - }, - children: [ - { - path: "metadata/edit", - lazy: () => - import( - "../../routes/shipping-profiles/shipping-profile-metadata" - ), - }, - ], - }, - ], - }, - { - path: ":location_id", - lazy: async () => { - const { Component, Breadcrumb, loader } = await import( - "../../routes/locations/location-detail" - ) - - return { - Component, - loader, - handle: { - breadcrumb: ( - match: UIMatch - ) => , - }, - } - }, - children: [ - { - path: "edit", - lazy: () => import("../../routes/locations/location-edit"), - }, - { - path: "sales-channels", - lazy: () => - import("../../routes/locations/location-sales-channels"), - }, - { - path: "fulfillment-providers", - lazy: () => - import( - "../../routes/locations/location-fulfillment-providers" - ), - }, - { - path: "fulfillment-set/:fset_id", - children: [ - { - path: "service-zones/create", - lazy: () => - import( - "../../routes/locations/location-service-zone-create" - ), - }, - { - path: "service-zone/:zone_id", - children: [ - { - path: "edit", - lazy: () => - import( - "../../routes/locations/location-service-zone-edit" - ), - }, - { - path: "areas", - lazy: () => - import( - "../../routes/locations/location-service-zone-manage-areas" - ), - }, - { - path: "shipping-option", - children: [ - { - path: "create", - lazy: () => - import( - "../../routes/locations/location-service-zone-shipping-option-create" - ), - }, - { - path: ":so_id", - children: [ - { - path: "edit", - lazy: () => - import( - "../../routes/locations/location-service-zone-shipping-option-edit" - ), - }, - { - path: "pricing", - lazy: () => - import( - "../../routes/locations/location-service-zone-shipping-option-pricing" - ), - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - { - path: "product-tags", - errorElement: , - element: , - handle: { - breadcrumb: () => t("productTags.domain"), - }, - children: [ - { - path: "", - lazy: () => - import("../../routes/product-tags/product-tag-list"), - children: [ - { - path: "create", - lazy: () => - import("../../routes/product-tags/product-tag-create"), - }, - ], - }, - { - path: ":id", - lazy: async () => { - const { Component, Breadcrumb, loader } = await import( - "../../routes/product-tags/product-tag-detail" - ) - - return { - Component, - loader, - handle: { - breadcrumb: ( - match: UIMatch - ) => , - }, - } - }, - children: [ - { - path: "edit", - lazy: () => - import("../../routes/product-tags/product-tag-edit"), - }, - ], - }, - ], - }, - { - path: "workflows", - errorElement: , - element: , - handle: { - breadcrumb: () => t("workflowExecutions.domain"), - }, - children: [ - { - path: "", - lazy: () => - import( - "../../routes/workflow-executions/workflow-execution-list" - ), - }, - { - path: ":id", - lazy: async () => { - const { Component, Breadcrumb, loader } = await import( - "../../routes/workflow-executions/workflow-execution-detail" - ) - - return { - Component, - loader, - handle: { - breadcrumb: ( - match: UIMatch - ) => , - }, - } - }, - }, - ], - }, - { - path: "product-types", - errorElement: , - element: , - handle: { - breadcrumb: () => t("productTypes.domain"), - }, - children: [ - { - path: "", - lazy: () => - import("../../routes/product-types/product-type-list"), - children: [ - { - path: "create", - lazy: () => - import("../../routes/product-types/product-type-create"), - }, - ], - }, - { - path: ":id", - lazy: async () => { - const { Component, Breadcrumb, loader } = await import( - "../../routes/product-types/product-type-detail" - ) - - return { - Component, - loader, - handle: { - breadcrumb: ( - match: UIMatch - ) => , - }, - } - }, - children: [ - { - path: "edit", - lazy: () => - import("../../routes/product-types/product-type-edit"), - }, - ], - }, - ], - }, - { - path: "publishable-api-keys", - element: , - handle: { - breadcrumb: () => t("apiKeyManagement.domain.publishable"), - }, - children: [ - { - path: "", - element: , - children: [ - { - path: "", - lazy: () => - import( - "../../routes/api-key-management/api-key-management-list" - ), - children: [ - { - path: "create", - lazy: () => - import( - "../../routes/api-key-management/api-key-management-create" - ), - }, - ], - }, - ], - }, - { - path: ":id", - lazy: async () => { - const { Component, Breadcrumb, loader } = await import( - "../../routes/api-key-management/api-key-management-detail" - ) - - return { - Component, - loader, - handle: { - breadcrumb: ( - match: UIMatch - ) => , - }, - } - }, - children: [ - { - path: "edit", - lazy: () => - import( - "../../routes/api-key-management/api-key-management-edit" - ), - }, - { - path: "sales-channels", - lazy: () => - import( - "../../routes/api-key-management/api-key-management-sales-channels" - ), - }, - ], - }, - ], - }, - { - path: "secret-api-keys", - element: , - handle: { - breadcrumb: () => t("apiKeyManagement.domain.secret"), - }, - children: [ - { - path: "", - element: , - children: [ - { - path: "", - lazy: () => - import( - "../../routes/api-key-management/api-key-management-list" - ), - children: [ - { - path: "create", - lazy: () => - import( - "../../routes/api-key-management/api-key-management-create" - ), - }, - ], - }, - ], - }, - { - path: ":id", - lazy: async () => { - const { Component, Breadcrumb, loader } = await import( - "../../routes/api-key-management/api-key-management-detail" - ) - - return { - Component, - loader, - handle: { - breadcrumb: ( - match: UIMatch - ) => , - }, - } - }, - children: [ - { - path: "edit", - lazy: () => - import( - "../../routes/api-key-management/api-key-management-edit" - ), - }, - ], - }, - ], - }, - { - path: "tax-regions", - element: , - handle: { - breadcrumb: () => t("taxRegions.domain"), - }, - children: [ - { - path: "", - lazy: () => import("../../routes/tax-regions/tax-region-list"), - children: [ - { - path: "create", - lazy: () => - import("../../routes/tax-regions/tax-region-create"), - }, - ], - }, - { - path: ":id", - Component: Outlet, - loader: taxRegionLoader, - handle: { - breadcrumb: ( - match: UIMatch - ) => , - }, - children: [ - { - path: "", - lazy: async () => { - const { Component } = await import( - "../../routes/tax-regions/tax-region-detail" - ) - - return { - Component, - } - }, - children: [ - { - path: "provinces/create", - lazy: () => - import( - "../../routes/tax-regions/tax-region-province-create" - ), - }, - { - path: "overrides/create", - lazy: () => - import( - "../../routes/tax-regions/tax-region-tax-override-create" - ), - }, - { - path: "overrides/:tax_rate_id/edit", - lazy: () => - import( - "../../routes/tax-regions/tax-region-tax-override-edit" - ), - }, - { - path: "tax-rates/create", - lazy: () => - import( - "../../routes/tax-regions/tax-region-tax-rate-create" - ), - }, - { - path: "tax-rates/:tax_rate_id/edit", - lazy: () => - import( - "../../routes/tax-regions/tax-region-tax-rate-edit" - ), - }, - ], - }, - { - path: "provinces/:province_id", - lazy: async () => { - const { Component, Breadcrumb, loader } = await import( - "../../routes/tax-regions/tax-region-province-detail" - ) - - return { - Component, - loader, - handle: { - breadcrumb: ( - match: UIMatch - ) => , - }, - } - }, - children: [ - { - path: "tax-rates/create", - lazy: () => - import( - "../../routes/tax-regions/tax-region-tax-rate-create" - ), - }, - { - path: "tax-rates/:tax_rate_id/edit", - lazy: () => - import( - "../../routes/tax-regions/tax-region-tax-rate-edit" - ), - }, - { - path: "overrides/create", - lazy: () => - import( - "../../routes/tax-regions/tax-region-tax-override-create" - ), - }, - { - path: "overrides/:tax_rate_id/edit", - lazy: () => - import( - "../../routes/tax-regions/tax-region-tax-override-edit" - ), - }, - ], - }, - ], - }, - ], - }, - { - path: "return-reasons", - element: , - handle: { - breadcrumb: () => t("returnReasons.domain"), - }, - children: [ - { - path: "", - lazy: () => - import("../../routes/return-reasons/return-reason-list"), - children: [ - { - path: "create", - lazy: () => - import( - "../../routes/return-reasons/return-reason-create" - ), - }, - - { - path: ":id", - children: [ - { - path: "edit", - lazy: () => - import( - "../../routes/return-reasons/return-reason-edit" - ), - }, - ], - }, - ], - }, - ], - }, - ...SettingsExtensions, - ], - }, - ], - }, - { - element: , - children: [ - { - errorElement: , - children: [ - { - path: "/login", - lazy: () => import("../../routes/login"), - }, - { - path: "/reset-password", - lazy: () => import("../../routes/reset-password"), - }, - { - path: "/invite", - lazy: () => import("../../routes/invite"), - }, - { - path: "*", - lazy: () => import("../../routes/no-match"), - }, - ], - }, - ], - }, -] diff --git a/packages/admin/dashboard/src/providers/router-provider/router-provider.tsx b/packages/admin/dashboard/src/providers/router-provider/router-provider.tsx deleted file mode 100644 index 87b6041774..0000000000 --- a/packages/admin/dashboard/src/providers/router-provider/router-provider.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { - RouterProvider as Provider, - createBrowserRouter, -} from "react-router-dom" - -import { RouteMap } from "./route-map" - -const router = createBrowserRouter(RouteMap, { - basename: __BASE__ || "/", -}) - -export const RouterProvider = () => { - return -} diff --git a/packages/admin/dashboard/src/providers/router-provider/settings-extensions.tsx b/packages/admin/dashboard/src/providers/router-provider/settings-extensions.tsx deleted file mode 100644 index 0949739307..0000000000 --- a/packages/admin/dashboard/src/providers/router-provider/settings-extensions.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import routeModule from "virtual:medusa/routes" -import { - createRouteMap, - getRouteExtensions, -} from "../../extensions/routes/utils" - -const routes = getRouteExtensions(routeModule, "settings") - -/** - * Settings Route extensions. - */ -export const SettingsExtensions = createRouteMap(routes, "/settings") diff --git a/packages/admin/dashboard/src/routes/api-key-management/api-key-management-detail/api-key-management-detail.tsx b/packages/admin/dashboard/src/routes/api-key-management/api-key-management-detail/api-key-management-detail.tsx index 2735520caf..993c23e7e6 100644 --- a/packages/admin/dashboard/src/routes/api-key-management/api-key-management-detail/api-key-management-detail.tsx +++ b/packages/admin/dashboard/src/routes/api-key-management/api-key-management-detail/api-key-management-detail.tsx @@ -2,8 +2,8 @@ import { useLoaderData, useParams } from "react-router-dom" import { SingleColumnPageSkeleton } from "../../../components/common/skeleton" import { SingleColumnPage } from "../../../components/layout/pages" -import { useDashboardExtension } from "../../../extensions" import { useApiKey } from "../../../hooks/api/api-keys" +import { useExtension } from "../../../providers/extension-provider" import { ApiKeyType } from "../common/constants" import { ApiKeyGeneralSection } from "./components/api-key-general-section" import { ApiKeySalesChannelSection } from "./components/api-key-sales-channel-section" @@ -15,7 +15,7 @@ export const ApiKeyManagementDetail = () => { > const { id } = useParams() - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() const { api_key, isLoading, isError, error } = useApiKey(id!, { initialData: initialData, diff --git a/packages/admin/dashboard/src/routes/api-key-management/api-key-management-list/api-key-management-list.tsx b/packages/admin/dashboard/src/routes/api-key-management/api-key-management-list/api-key-management-list.tsx index b6b2cf000d..0c07b26437 100644 --- a/packages/admin/dashboard/src/routes/api-key-management/api-key-management-list/api-key-management-list.tsx +++ b/packages/admin/dashboard/src/routes/api-key-management/api-key-management-list/api-key-management-list.tsx @@ -3,11 +3,11 @@ import { getApiKeyTypeFromPathname } from "../common/utils" import { ApiKeyManagementListTable } from "./components/api-key-management-list-table" import { SingleColumnPage } from "../../../components/layout/pages" -import { useDashboardExtension } from "../../../extensions" +import { useExtension } from "../../../providers/extension-provider" export const ApiKeyManagementList = () => { const { pathname } = useLocation() - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() const keyType = getApiKeyTypeFromPathname(pathname) diff --git a/packages/admin/dashboard/src/routes/campaigns/campaign-detail/campaign-detail.tsx b/packages/admin/dashboard/src/routes/campaigns/campaign-detail/campaign-detail.tsx index a802e4e998..372d45d6f8 100644 --- a/packages/admin/dashboard/src/routes/campaigns/campaign-detail/campaign-detail.tsx +++ b/packages/admin/dashboard/src/routes/campaigns/campaign-detail/campaign-detail.tsx @@ -9,7 +9,7 @@ import { campaignLoader } from "./loader" import { TwoColumnPageSkeleton } from "../../../components/common/skeleton" import { TwoColumnPage } from "../../../components/layout/pages" -import { useDashboardExtension } from "../../../extensions" +import { useExtension } from "../../../providers/extension-provider" import { CampaignConfigurationSection } from "./components/campaign-configuration-section" import { CAMPAIGN_DETAIL_FIELDS } from "./constants" @@ -25,7 +25,7 @@ export const CampaignDetail = () => { { initialData } ) - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() if (isLoading || !campaign) { return ( diff --git a/packages/admin/dashboard/src/routes/campaigns/campaign-list/campaign-list.tsx b/packages/admin/dashboard/src/routes/campaigns/campaign-list/campaign-list.tsx index 7c01e276ad..0cdeab700d 100644 --- a/packages/admin/dashboard/src/routes/campaigns/campaign-list/campaign-list.tsx +++ b/packages/admin/dashboard/src/routes/campaigns/campaign-list/campaign-list.tsx @@ -1,9 +1,9 @@ import { SingleColumnPage } from "../../../components/layout/pages" -import { useDashboardExtension } from "../../../extensions" +import { useExtension } from "../../../providers/extension-provider" import { CampaignListTable } from "./components/campaign-list-table" export const CampaignList = () => { - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() return ( { const { id } = useParams() @@ -16,7 +16,7 @@ export const CategoryDetail = () => { ReturnType > - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() const { product_category, isLoading, isError, error } = useProductCategory( id!, diff --git a/packages/admin/dashboard/src/routes/categories/category-list/category-list.tsx b/packages/admin/dashboard/src/routes/categories/category-list/category-list.tsx index 0f77bd2578..8d06b910fc 100644 --- a/packages/admin/dashboard/src/routes/categories/category-list/category-list.tsx +++ b/packages/admin/dashboard/src/routes/categories/category-list/category-list.tsx @@ -1,9 +1,9 @@ import { SingleColumnPage } from "../../../components/layout/pages" -import { useDashboardExtension } from "../../../extensions" +import { useExtension } from "../../../providers/extension-provider" import { CategoryListTable } from "./components/category-list-table" export const CategoryList = () => { - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() return ( { initialData, }) - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() if (isLoading || !collection) { return diff --git a/packages/admin/dashboard/src/routes/collections/collection-list/collection-list.tsx b/packages/admin/dashboard/src/routes/collections/collection-list/collection-list.tsx index 29b514382d..43054e261c 100644 --- a/packages/admin/dashboard/src/routes/collections/collection-list/collection-list.tsx +++ b/packages/admin/dashboard/src/routes/collections/collection-list/collection-list.tsx @@ -1,9 +1,9 @@ import { SingleColumnPage } from "../../../components/layout/pages" -import { useDashboardExtension } from "../../../extensions" +import { useExtension } from "../../../providers/extension-provider" import { CollectionListTable } from "./components/collection-list-table" export const CollectionList = () => { - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() return ( { @@ -24,7 +24,7 @@ export const CustomerGroupDetail = () => { { initialData } ) - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() if (isLoading || !customer_group) { return diff --git a/packages/admin/dashboard/src/routes/customer-groups/customer-group-list/components/customer-group-list-table/customer-group-list-table.tsx b/packages/admin/dashboard/src/routes/customer-groups/customer-group-list/components/customer-group-list-table/customer-group-list-table.tsx index ff1ac01aac..ddeef19896 100644 --- a/packages/admin/dashboard/src/routes/customer-groups/customer-group-list/components/customer-group-list-table/customer-group-list-table.tsx +++ b/packages/admin/dashboard/src/routes/customer-groups/customer-group-list/components/customer-group-list-table/customer-group-list-table.tsx @@ -1,10 +1,10 @@ import { PencilSquare, Trash } from "@medusajs/icons" import { HttpTypes } from "@medusajs/types" import { - Container, - createDataTableColumnHelper, - toast, - usePrompt, + Container, + createDataTableColumnHelper, + toast, + usePrompt, } from "@medusajs/ui" import { keepPreviousData } from "@tanstack/react-query" import { useCallback, useMemo } from "react" @@ -14,19 +14,19 @@ import { useNavigate } from "react-router-dom" import { DataTable } from "../../../../../components/data-table" import { useDataTableDateFilters } from "../../../../../components/data-table/helpers/general/use-data-table-date-filters" import { SingleColumnPage } from "../../../../../components/layout/pages" -import { useDashboardExtension } from "../../../../../extensions" import { - useCustomerGroups, - useDeleteCustomerGroupLazy, + useCustomerGroups, + useDeleteCustomerGroupLazy, } from "../../../../../hooks/api" import { useDate } from "../../../../../hooks/use-date" import { useQueryParams } from "../../../../../hooks/use-query-params" +import { useExtension } from "../../../../../providers/extension-provider" const PAGE_SIZE = 10 export const CustomerGroupListTable = () => { const { t } = useTranslation() - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() const { q, order, offset, created_at, updated_at } = useQueryParams([ "q", diff --git a/packages/admin/dashboard/src/routes/customer-groups/customer-group-list/customer-group-list.tsx b/packages/admin/dashboard/src/routes/customer-groups/customer-group-list/customer-group-list.tsx index 7230f44218..1bd613e63c 100644 --- a/packages/admin/dashboard/src/routes/customer-groups/customer-group-list/customer-group-list.tsx +++ b/packages/admin/dashboard/src/routes/customer-groups/customer-group-list/customer-group-list.tsx @@ -1,9 +1,9 @@ import { SingleColumnPage } from "../../../components/layout/pages" -import { useDashboardExtension } from "../../../extensions" +import { useExtension } from "../../../providers/extension-provider" import { CustomerGroupListTable } from "./components/customer-group-list-table" export const CustomerGroupsList = () => { - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() return ( { initialData, }) - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() if (isLoading || !customer) { return diff --git a/packages/admin/dashboard/src/routes/customers/customer-list/customer-list.tsx b/packages/admin/dashboard/src/routes/customers/customer-list/customer-list.tsx index 69726a4f28..89324be89f 100644 --- a/packages/admin/dashboard/src/routes/customers/customer-list/customer-list.tsx +++ b/packages/admin/dashboard/src/routes/customers/customer-list/customer-list.tsx @@ -1,9 +1,9 @@ import { SingleColumnPage } from "../../../components/layout/pages" -import { useDashboardExtension } from "../../../extensions" +import { useExtension } from "../../../providers/extension-provider" import { CustomerListTable } from "./components/customer-list-table" export const CustomersList = () => { - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() return ( { @@ -35,7 +35,7 @@ export const InventoryDetail = () => { } ) - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() if (isLoading || !inventory_item) { return ( diff --git a/packages/admin/dashboard/src/routes/inventory/inventory-list/inventory-list.tsx b/packages/admin/dashboard/src/routes/inventory/inventory-list/inventory-list.tsx index a26036f8dc..52d9630bb4 100644 --- a/packages/admin/dashboard/src/routes/inventory/inventory-list/inventory-list.tsx +++ b/packages/admin/dashboard/src/routes/inventory/inventory-list/inventory-list.tsx @@ -1,9 +1,9 @@ import { SingleColumnPage } from "../../../components/layout/pages" -import { useDashboardExtension } from "../../../extensions" +import { useExtension } from "../../../providers/extension-provider" import { InventoryListTable } from "./components/inventory-list-table" export const InventoryItemListTable = () => { - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() return ( { { initialData } ) - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() if (isLoading || !location) { return ( diff --git a/packages/admin/dashboard/src/routes/locations/location-list/location-list.tsx b/packages/admin/dashboard/src/routes/locations/location-list/location-list.tsx index 1f99f9241b..11557f1351 100644 --- a/packages/admin/dashboard/src/routes/locations/location-list/location-list.tsx +++ b/packages/admin/dashboard/src/routes/locations/location-list/location-list.tsx @@ -1,19 +1,17 @@ -import { ShoppingBag, TriangleRightMini } from "@medusajs/icons" -import { Container, Heading, Text } from "@medusajs/ui" +import { ShoppingBag } from "@medusajs/icons" +import { Container, Heading } from "@medusajs/ui" import { useTranslation } from "react-i18next" -import { Link, useLoaderData } from "react-router-dom" +import { useLoaderData } from "react-router-dom" import { useStockLocations } from "../../../hooks/api/stock-locations" import LocationListItem from "./components/location-list-item/location-list-item" import { LOCATION_LIST_FIELDS } from "./constants" import { shippingListLoader } from "./loader" -import { ReactNode } from "react" -import { IconAvatar } from "../../../components/common/icon-avatar" -import { TwoColumnPage } from "../../../components/layout/pages" -import { useDashboardExtension } from "../../../extensions" -import { LocationListHeader } from "./components/location-list-header" import { SidebarLink } from "../../../components/common/sidebar-link/sidebar-link" +import { TwoColumnPage } from "../../../components/layout/pages" +import { useExtension } from "../../../providers/extension-provider" +import { LocationListHeader } from "./components/location-list-header" export function LocationList() { const initialData = useLoaderData() as Awaited< @@ -31,7 +29,7 @@ export function LocationList() { { initialData } ) - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() if (isError) { throw error diff --git a/packages/admin/dashboard/src/routes/login/login.tsx b/packages/admin/dashboard/src/routes/login/login.tsx index 497ed117d2..482b8d404b 100644 --- a/packages/admin/dashboard/src/routes/login/login.tsx +++ b/packages/admin/dashboard/src/routes/login/login.tsx @@ -7,9 +7,9 @@ import * as z from "zod" import { Form } from "../../components/common/form" import AvatarBox from "../../components/common/logo-box/avatar-box" -import { useDashboardExtension } from "../../extensions" import { useSignInWithEmailPass } from "../../hooks/api" import { isFetchError } from "../../lib/is-fetch-error" +import { useExtension } from "../../providers/extension-provider" const LoginSchema = z.object({ email: z.string().email(), @@ -20,7 +20,7 @@ export const Login = () => { const { t } = useTranslation() const location = useLocation() const navigate = useNavigate() - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() const from = location.state?.from?.pathname || "/orders" diff --git a/packages/admin/dashboard/src/routes/orders/order-detail/order-detail.tsx b/packages/admin/dashboard/src/routes/orders/order-detail/order-detail.tsx index de80b0be3b..77e01cdb9b 100644 --- a/packages/admin/dashboard/src/routes/orders/order-detail/order-detail.tsx +++ b/packages/admin/dashboard/src/routes/orders/order-detail/order-detail.tsx @@ -2,8 +2,8 @@ import { useLoaderData, useParams } from "react-router-dom" import { TwoColumnPageSkeleton } from "../../../components/common/skeleton" import { TwoColumnPage } from "../../../components/layout/pages" -import { useDashboardExtension } from "../../../extensions" import { useOrder, useOrderPreview } from "../../../hooks/api/orders" +import { useExtension } from "../../../providers/extension-provider" import { ActiveOrderClaimSection } from "./components/active-order-claim-section" import { ActiveOrderExchangeSection } from "./components/active-order-exchange-section" import { ActiveOrderReturnSection } from "./components/active-order-return-section" @@ -21,7 +21,7 @@ export const OrderDetail = () => { const initialData = useLoaderData() as Awaited> const { id } = useParams() - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() const { order, isLoading, isError, error } = useOrder( id!, diff --git a/packages/admin/dashboard/src/routes/orders/order-list/order-list.tsx b/packages/admin/dashboard/src/routes/orders/order-list/order-list.tsx index 96acaa61c0..af8b8c2b75 100644 --- a/packages/admin/dashboard/src/routes/orders/order-list/order-list.tsx +++ b/packages/admin/dashboard/src/routes/orders/order-list/order-list.tsx @@ -1,10 +1,10 @@ import { OrderListTable } from "./components/order-list-table" import { SingleColumnPage } from "../../../components/layout/pages" -import { useDashboardExtension } from "../../../extensions" +import { useExtension } from "../../../providers/extension-provider" export const OrderList = () => { - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() return ( { const { id } = useParams() const { price_list, isLoading, isError, error } = usePriceList(id!) - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() if (isLoading || !price_list) { return ( diff --git a/packages/admin/dashboard/src/routes/price-lists/price-list-list/price-list-list.tsx b/packages/admin/dashboard/src/routes/price-lists/price-list-list/price-list-list.tsx index 4d74ddef60..b9e8a947e0 100644 --- a/packages/admin/dashboard/src/routes/price-lists/price-list-list/price-list-list.tsx +++ b/packages/admin/dashboard/src/routes/price-lists/price-list-list/price-list-list.tsx @@ -1,9 +1,9 @@ import { SingleColumnPage } from "../../../components/layout/pages" -import { useDashboardExtension } from "../../../extensions" +import { useExtension } from "../../../providers/extension-provider" import { PriceListListTable } from "./components/price-list-list-table" export const PriceListList = () => { - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() return ( { ReturnType > - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() const { product_tag, isPending, isError, error } = useProductTag( id!, diff --git a/packages/admin/dashboard/src/routes/product-tags/product-tag-list/product-tag-list.tsx b/packages/admin/dashboard/src/routes/product-tags/product-tag-list/product-tag-list.tsx index a612a12498..cb14d031c2 100644 --- a/packages/admin/dashboard/src/routes/product-tags/product-tag-list/product-tag-list.tsx +++ b/packages/admin/dashboard/src/routes/product-tags/product-tag-list/product-tag-list.tsx @@ -1,9 +1,9 @@ import { SingleColumnPage } from "../../../components/layout/pages" -import { useDashboardExtension } from "../../../extensions" +import { useExtension } from "../../../providers/extension-provider" import { ProductTagListTable } from "./components/product-tag-list-table" export const ProductTagList = () => { - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() return ( { } ) - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() if (isPending || !product_type) { return diff --git a/packages/admin/dashboard/src/routes/product-types/product-type-list/product-type-list.tsx b/packages/admin/dashboard/src/routes/product-types/product-type-list/product-type-list.tsx index 837482e242..7bca2c2b55 100644 --- a/packages/admin/dashboard/src/routes/product-types/product-type-list/product-type-list.tsx +++ b/packages/admin/dashboard/src/routes/product-types/product-type-list/product-type-list.tsx @@ -1,9 +1,9 @@ import { SingleColumnPage } from "../../../components/layout/pages" -import { useDashboardExtension } from "../../../extensions" +import { useExtension } from "../../../providers/extension-provider" import { ProductTypeListTable } from "./components/product-type-list-table" export const ProductTypeList = () => { - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() return ( { } ) - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() if (isLoading || !variant) { return ( diff --git a/packages/admin/dashboard/src/routes/products/product-attributes/components/product-attributes-form/product-attributes-form.tsx b/packages/admin/dashboard/src/routes/products/product-attributes/components/product-attributes-form/product-attributes-form.tsx index 9eec54aed8..87a4d4b36c 100644 --- a/packages/admin/dashboard/src/routes/products/product-attributes/components/product-attributes-form/product-attributes-form.tsx +++ b/packages/admin/dashboard/src/routes/products/product-attributes/components/product-attributes-form/product-attributes-form.tsx @@ -8,10 +8,10 @@ import { RouteDrawer, useRouteModal } from "../../../../../components/modals" import { KeyboundForm } from "../../../../../components/utilities/keybound-form" import { FormExtensionZone, - useDashboardExtension, useExtendableForm, -} from "../../../../../extensions" +} from "../../../../../dashboard-app" import { useUpdateProduct } from "../../../../../hooks/api/products" +import { useExtension } from "../../../../../providers/extension-provider" type ProductAttributesFormProps = { product: HttpTypes.AdminProduct @@ -43,7 +43,7 @@ export const ProductAttributesForm = ({ }: ProductAttributesFormProps) => { const { t } = useTranslation() const { handleSuccess } = useRouteModal() - const { getFormConfigs, getFormFields } = useDashboardExtension() + const { getFormConfigs, getFormFields } = useExtension() const configs = getFormConfigs("product", "attributes") const fields = getFormFields("product", "attributes") diff --git a/packages/admin/dashboard/src/routes/products/product-create/components/product-create-details-form/product-create-details-form.tsx b/packages/admin/dashboard/src/routes/products/product-create/components/product-create-details-form/product-create-details-form.tsx index f19678c170..7e119b85ce 100644 --- a/packages/admin/dashboard/src/routes/products/product-create/components/product-create-details-form/product-create-details-form.tsx +++ b/packages/admin/dashboard/src/routes/products/product-create/components/product-create-details-form/product-create-details-form.tsx @@ -2,10 +2,8 @@ import { Divider, Heading } from "@medusajs/ui" import { UseFormReturn } from "react-hook-form" import { useTranslation } from "react-i18next" -import { - FormExtensionZone, - useDashboardExtension, -} from "../../../../../extensions" +import { FormExtensionZone } from "../../../../../dashboard-app" +import { useExtension } from "../../../../../providers/extension-provider" import { ProductCreateSchemaType } from "../../types" import { ProductCreateGeneralSection } from "./components/product-create-details-general-section" import { ProductCreateMediaSection } from "./components/product-create-details-media-section" @@ -16,7 +14,7 @@ type ProductAttributesProps = { } export const ProductCreateDetailsForm = ({ form }: ProductAttributesProps) => { - const { getFormFields } = useDashboardExtension() + const { getFormFields } = useExtension() const fields = getFormFields("product", "create", "general") return ( diff --git a/packages/admin/dashboard/src/routes/products/product-create/components/product-create-form/product-create-form.tsx b/packages/admin/dashboard/src/routes/products/product-create/components/product-create-form/product-create-form.tsx index f4ba63318f..7ec650dffb 100644 --- a/packages/admin/dashboard/src/routes/products/product-create/components/product-create-form/product-create-form.tsx +++ b/packages/admin/dashboard/src/routes/products/product-create/components/product-create-form/product-create-form.tsx @@ -8,12 +8,10 @@ import { useRouteModal, } from "../../../../../components/modals" import { KeyboundForm } from "../../../../../components/utilities/keybound-form" -import { - useDashboardExtension, - useExtendableForm, -} from "../../../../../extensions" +import { useExtendableForm } from "../../../../../dashboard-app/forms/hooks" import { useCreateProduct } from "../../../../../hooks/api/products" import { sdk } from "../../../../../lib/client" +import { useExtension } from "../../../../../providers/extension-provider" import { PRODUCT_CREATE_FORM_DEFAULTS, ProductCreateSchema, @@ -58,7 +56,7 @@ export const ProductCreateForm = ({ const { t } = useTranslation() const { handleSuccess } = useRouteModal() - const { getFormConfigs } = useDashboardExtension() + const { getFormConfigs } = useExtension() const configs = getFormConfigs("product", "create") const form = useExtendableForm({ diff --git a/packages/admin/dashboard/src/routes/products/product-create/components/product-create-organize-form/product-create-organize-form.tsx b/packages/admin/dashboard/src/routes/products/product-create/components/product-create-organize-form/product-create-organize-form.tsx index 37ef9882ba..377da3d74f 100644 --- a/packages/admin/dashboard/src/routes/products/product-create/components/product-create-organize-form/product-create-organize-form.tsx +++ b/packages/admin/dashboard/src/routes/products/product-create/components/product-create-organize-form/product-create-organize-form.tsx @@ -1,10 +1,8 @@ import { UseFormReturn } from "react-hook-form" import { StackedFocusModal } from "../../../../../components/modals" -import { - FormExtensionZone, - useDashboardExtension, -} from "../../../../../extensions" +import { FormExtensionZone } from "../../../../../dashboard-app" +import { useExtension } from "../../../../../providers/extension-provider" import { ProductCreateSchemaType } from "../../types" import { ProductCreateOrganizationSection } from "./components/product-create-organize-section" import { ProductCreateSalesChannelStackedModal } from "./components/product-create-sales-channel-stacked-modal" @@ -15,7 +13,7 @@ type ProductAttributesProps = { } export const ProductCreateOrganizeForm = ({ form }: ProductAttributesProps) => { - const { getFormFields } = useDashboardExtension() + const { getFormFields } = useExtension() const fields = getFormFields("product", "create", "organize") return ( diff --git a/packages/admin/dashboard/src/routes/products/product-detail/components/product-attribute-section/product-attribute-section.tsx b/packages/admin/dashboard/src/routes/products/product-detail/components/product-attribute-section/product-attribute-section.tsx index 66b85ddb4c..98ff3d00eb 100644 --- a/packages/admin/dashboard/src/routes/products/product-detail/components/product-attribute-section/product-attribute-section.tsx +++ b/packages/admin/dashboard/src/routes/products/product-detail/components/product-attribute-section/product-attribute-section.tsx @@ -4,8 +4,8 @@ import { Container, Heading } from "@medusajs/ui" import { useTranslation } from "react-i18next" import { ActionMenu } from "../../../../../components/common/action-menu" import { SectionRow } from "../../../../../components/common/section" -import { useDashboardExtension } from "../../../../../extensions" import { getFormattedCountry } from "../../../../../lib/addresses" +import { useExtension } from "../../../../../providers/extension-provider" type ProductAttributeSectionProps = { product: HttpTypes.AdminProduct @@ -15,7 +15,7 @@ export const ProductAttributeSection = ({ product, }: ProductAttributeSectionProps) => { const { t } = useTranslation() - const { getDisplays } = useDashboardExtension() + const { getDisplays } = useExtension() return ( diff --git a/packages/admin/dashboard/src/routes/products/product-detail/components/product-general-section/product-general-section.tsx b/packages/admin/dashboard/src/routes/products/product-detail/components/product-general-section/product-general-section.tsx index e95e345a08..f813836794 100644 --- a/packages/admin/dashboard/src/routes/products/product-detail/components/product-general-section/product-general-section.tsx +++ b/packages/admin/dashboard/src/routes/products/product-detail/components/product-general-section/product-general-section.tsx @@ -6,8 +6,8 @@ import { useNavigate } from "react-router-dom" import { ActionMenu } from "../../../../../components/common/action-menu" import { SectionRow } from "../../../../../components/common/section" -import { useDashboardExtension } from "../../../../../extensions" import { useDeleteProduct } from "../../../../../hooks/api/products" +import { useExtension } from "../../../../../providers/extension-provider" const productStatusColor = (status: string) => { switch (status) { @@ -34,7 +34,7 @@ export const ProductGeneralSection = ({ const { t } = useTranslation() const prompt = usePrompt() const navigate = useNavigate() - const { getDisplays } = useDashboardExtension() + const { getDisplays } = useExtension() const displays = getDisplays("product", "general") diff --git a/packages/admin/dashboard/src/routes/products/product-detail/components/product-organization-section/product-organization-section.tsx b/packages/admin/dashboard/src/routes/products/product-detail/components/product-organization-section/product-organization-section.tsx index c8f722513d..14415318ff 100644 --- a/packages/admin/dashboard/src/routes/products/product-detail/components/product-organization-section/product-organization-section.tsx +++ b/packages/admin/dashboard/src/routes/products/product-detail/components/product-organization-section/product-organization-section.tsx @@ -5,7 +5,7 @@ import { useTranslation } from "react-i18next" import { Link } from "react-router-dom" import { ActionMenu } from "../../../../../components/common/action-menu" import { SectionRow } from "../../../../../components/common/section" -import { useDashboardExtension } from "../../../../../extensions" +import { useExtension } from "../../../../../providers/extension-provider" type ProductOrganizationSectionProps = { product: HttpTypes.AdminProduct @@ -15,7 +15,7 @@ export const ProductOrganizationSection = ({ product, }: ProductOrganizationSectionProps) => { const { t } = useTranslation() - const { getDisplays } = useDashboardExtension() + const { getDisplays } = useExtension() return ( diff --git a/packages/admin/dashboard/src/routes/products/product-detail/constants.ts b/packages/admin/dashboard/src/routes/products/product-detail/constants.ts index fcc4006988..e5f98171e8 100644 --- a/packages/admin/dashboard/src/routes/products/product-detail/constants.ts +++ b/packages/admin/dashboard/src/routes/products/product-detail/constants.ts @@ -1,4 +1,4 @@ -import { getLinkedFields } from "../../../extensions" +import { getLinkedFields } from "../../../dashboard-app" export const PRODUCT_DETAIL_FIELDS = getLinkedFields( "product", diff --git a/packages/admin/dashboard/src/routes/products/product-detail/product-detail.tsx b/packages/admin/dashboard/src/routes/products/product-detail/product-detail.tsx index 78ece96f60..c9a9a62915 100644 --- a/packages/admin/dashboard/src/routes/products/product-detail/product-detail.tsx +++ b/packages/admin/dashboard/src/routes/products/product-detail/product-detail.tsx @@ -13,7 +13,7 @@ import { ProductVariantSection } from "./components/product-variant-section" import { PRODUCT_DETAIL_FIELDS } from "./constants" import { productLoader } from "./loader" -import { useDashboardExtension } from "../../../extensions" +import { useExtension } from "../../../providers/extension-provider" import { ProductShippingProfileSection } from "./components/product-shipping-profile-section" export const ProductDetail = () => { @@ -30,7 +30,7 @@ export const ProductDetail = () => { } ) - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() const after = getWidgets("product.details.after") const before = getWidgets("product.details.before") diff --git a/packages/admin/dashboard/src/routes/products/product-edit/components/edit-product-form/edit-product-form.tsx b/packages/admin/dashboard/src/routes/products/product-edit/components/edit-product-form/edit-product-form.tsx index 819d9c02a8..5020dd5c79 100644 --- a/packages/admin/dashboard/src/routes/products/product-edit/components/edit-product-form/edit-product-form.tsx +++ b/packages/admin/dashboard/src/routes/products/product-edit/components/edit-product-form/edit-product-form.tsx @@ -6,15 +6,13 @@ import { HttpTypes } from "@medusajs/types" import { Form } from "../../../../../components/common/form" import { SwitchBox } from "../../../../../components/common/switch-box" import { RouteDrawer, useRouteModal } from "../../../../../components/modals" -import { useExtendableForm } from "../../../../../extensions/forms/hooks" +import { useExtendableForm } from "../../../../../dashboard-app/forms/hooks" import { useUpdateProduct } from "../../../../../hooks/api/products" import { transformNullableFormData } from "../../../../../lib/form-helpers" import { KeyboundForm } from "../../../../../components/utilities/keybound-form" -import { - FormExtensionZone, - useDashboardExtension, -} from "../../../../../extensions" +import { FormExtensionZone } from "../../../../../dashboard-app" +import { useExtension } from "../../../../../providers/extension-provider" type EditProductFormProps = { product: HttpTypes.AdminProduct @@ -34,7 +32,7 @@ export const EditProductForm = ({ product }: EditProductFormProps) => { const { t } = useTranslation() const { handleSuccess } = useRouteModal() - const { getFormFields, getFormConfigs } = useDashboardExtension() + const { getFormFields, getFormConfigs } = useExtension() const fields = getFormFields("product", "edit") const configs = getFormConfigs("product", "edit") diff --git a/packages/admin/dashboard/src/routes/products/product-list/product-list.tsx b/packages/admin/dashboard/src/routes/products/product-list/product-list.tsx index c22841f97e..62c447c660 100644 --- a/packages/admin/dashboard/src/routes/products/product-list/product-list.tsx +++ b/packages/admin/dashboard/src/routes/products/product-list/product-list.tsx @@ -1,9 +1,9 @@ import { SingleColumnPage } from "../../../components/layout/pages" -import { useDashboardExtension } from "../../../extensions" +import { useExtension } from "../../../providers/extension-provider" import { ProductListTable } from "./components/product-list-table" export const ProductList = () => { - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() return ( { const { t } = useTranslation() const { handleSuccess } = useRouteModal() - const { getFormConfigs, getFormFields } = useDashboardExtension() + const { getFormConfigs, getFormFields } = useExtension() const configs = getFormConfigs("product", "organize") const fields = getFormFields("product", "organize") diff --git a/packages/admin/dashboard/src/routes/profile/profile-detail/profile-detail.tsx b/packages/admin/dashboard/src/routes/profile/profile-detail/profile-detail.tsx index a36aee5f5b..76e0f11301 100644 --- a/packages/admin/dashboard/src/routes/profile/profile-detail/profile-detail.tsx +++ b/packages/admin/dashboard/src/routes/profile/profile-detail/profile-detail.tsx @@ -3,11 +3,11 @@ import { ProfileGeneralSection } from "./components/profile-general-section" import { SingleColumnPageSkeleton } from "../../../components/common/skeleton" import { SingleColumnPage } from "../../../components/layout/pages" -import { useDashboardExtension } from "../../../extensions" +import { useExtension } from "../../../providers/extension-provider" export const ProfileDetail = () => { const { user, isPending: isLoading, isError, error } = useMe() - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() if (isLoading || !user) { return diff --git a/packages/admin/dashboard/src/routes/promotions/promotion-detail/promotion-detail.tsx b/packages/admin/dashboard/src/routes/promotions/promotion-detail/promotion-detail.tsx index 765952b9a8..a5fefa61c7 100644 --- a/packages/admin/dashboard/src/routes/promotions/promotion-detail/promotion-detail.tsx +++ b/packages/admin/dashboard/src/routes/promotions/promotion-detail/promotion-detail.tsx @@ -2,8 +2,8 @@ import { useLoaderData, useParams } from "react-router-dom" import { TwoColumnPageSkeleton } from "../../../components/common/skeleton" import { TwoColumnPage } from "../../../components/layout/pages" -import { useDashboardExtension } from "../../../extensions" import { usePromotion, usePromotionRules } from "../../../hooks/api/promotions" +import { useExtension } from "../../../providers/extension-provider" import { CampaignSection } from "./components/campaign-section" import { PromotionConditionsSection } from "./components/promotion-conditions-section" import { PromotionGeneralSection } from "./components/promotion-general-section" @@ -26,7 +26,7 @@ export const PromotionDetail = () => { const { rules: targetRules } = usePromotionRules(id!, "target-rules", query) const { rules: buyRules } = usePromotionRules(id!, "buy-rules", query) - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() if (isLoading || !promotion) { return ( diff --git a/packages/admin/dashboard/src/routes/promotions/promotion-list/promotions-list.tsx b/packages/admin/dashboard/src/routes/promotions/promotion-list/promotions-list.tsx index 1994f7e260..793b8b4cb4 100644 --- a/packages/admin/dashboard/src/routes/promotions/promotion-list/promotions-list.tsx +++ b/packages/admin/dashboard/src/routes/promotions/promotion-list/promotions-list.tsx @@ -1,9 +1,9 @@ import { SingleColumnPage } from "../../../components/layout/pages" -import { useDashboardExtension } from "../../../extensions" +import { useExtension } from "../../../providers/extension-provider" import { PromotionListTable } from "./components/promotion-list-table" export const PromotionsList = () => { - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() return ( { @@ -43,7 +43,7 @@ export const RegionDetail = () => { { enabled: !!region } ) - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() if (isLoading || isLoadingPreferences || !region) { return diff --git a/packages/admin/dashboard/src/routes/regions/region-list/region-list.tsx b/packages/admin/dashboard/src/routes/regions/region-list/region-list.tsx index 1a7eaea67d..6d6f81217f 100644 --- a/packages/admin/dashboard/src/routes/regions/region-list/region-list.tsx +++ b/packages/admin/dashboard/src/routes/regions/region-list/region-list.tsx @@ -1,9 +1,9 @@ import { SingleColumnPage } from "../../../components/layout/pages" -import { useDashboardExtension } from "../../../extensions" +import { useExtension } from "../../../providers/extension-provider" import { RegionListTable } from "./components/region-list-table" export const RegionList = () => { - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() return ( { const { id } = useParams() @@ -31,7 +31,7 @@ export const ReservationDetail = () => { { enabled: !!reservation?.inventory_item?.id! } ) - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() if (isLoading || !reservation) { return ( diff --git a/packages/admin/dashboard/src/routes/reservations/reservation-list/reservation-list.tsx b/packages/admin/dashboard/src/routes/reservations/reservation-list/reservation-list.tsx index 6de0532af8..b619cbfb8a 100644 --- a/packages/admin/dashboard/src/routes/reservations/reservation-list/reservation-list.tsx +++ b/packages/admin/dashboard/src/routes/reservations/reservation-list/reservation-list.tsx @@ -1,9 +1,9 @@ import { SingleColumnPage } from "../../../components/layout/pages" -import { useDashboardExtension } from "../../../extensions" +import { useExtension } from "../../../providers/extension-provider" import { ReservationListTable } from "./components/reservation-list-table" export const ReservationList = () => { - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() return ( { - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() return ( { initialData, }) - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() if (isLoading || !sales_channel) { return diff --git a/packages/admin/dashboard/src/routes/sales-channels/sales-channel-list/sales-channel-list.tsx b/packages/admin/dashboard/src/routes/sales-channels/sales-channel-list/sales-channel-list.tsx index 4378114428..8c7dc58a6e 100644 --- a/packages/admin/dashboard/src/routes/sales-channels/sales-channel-list/sales-channel-list.tsx +++ b/packages/admin/dashboard/src/routes/sales-channels/sales-channel-list/sales-channel-list.tsx @@ -1,10 +1,10 @@ import { SalesChannelListTable } from "./components/sales-channel-list-table" import { SingleColumnPage } from "../../../components/layout/pages" -import { useDashboardExtension } from "../../../extensions" +import { useExtension } from "../../../providers/extension-provider" export const SalesChannelList = () => { - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() return ( { @@ -21,7 +21,7 @@ export const ShippingProfileDetail = () => { { initialData } ) - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() if (isLoading || !shipping_profile) { return diff --git a/packages/admin/dashboard/src/routes/shipping-profiles/shipping-profiles-list/shipping-profile-list.tsx b/packages/admin/dashboard/src/routes/shipping-profiles/shipping-profiles-list/shipping-profile-list.tsx index 8fc9edc66d..7beabfc423 100644 --- a/packages/admin/dashboard/src/routes/shipping-profiles/shipping-profiles-list/shipping-profile-list.tsx +++ b/packages/admin/dashboard/src/routes/shipping-profiles/shipping-profiles-list/shipping-profile-list.tsx @@ -1,9 +1,9 @@ import { SingleColumnPage } from "../../../components/layout/pages" -import { useDashboardExtension } from "../../../extensions" +import { useExtension } from "../../../providers/extension-provider" import { ShippingProfileListTable } from "./components/shipping-profile-list-table" export const ShippingProfileList = () => { - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() return ( { const initialData = useLoaderData() as Awaited> @@ -16,7 +16,7 @@ export const StoreDetail = () => { initialData, }) - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() if (isPending || !store) { return diff --git a/packages/admin/dashboard/src/routes/tax-regions/tax-region-detail/tax-region-detail.tsx b/packages/admin/dashboard/src/routes/tax-regions/tax-region-detail/tax-region-detail.tsx index 327e8b08e3..9809b3cee0 100644 --- a/packages/admin/dashboard/src/routes/tax-regions/tax-region-detail/tax-region-detail.tsx +++ b/packages/admin/dashboard/src/routes/tax-regions/tax-region-detail/tax-region-detail.tsx @@ -7,7 +7,7 @@ import { TaxRegionProvinceSection } from "./components/tax-region-province-secti import { useState } from "react" import { SingleColumnPageSkeleton } from "../../../components/common/skeleton" -import { useDashboardExtension } from "../../../extensions" +import { useExtension } from "../../../providers/extension-provider" import { TaxRegionOverrideSection } from "./components/tax-region-override-section" import { TaxRegionSublevelAlert } from "./components/tax-region-sublevel-alert" import { taxRegionLoader } from "./loader" @@ -27,7 +27,7 @@ export const TaxRegionDetail = () => { error, } = useTaxRegion(id!, undefined, { initialData }) - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() if (isLoading || !taxRegion) { return diff --git a/packages/admin/dashboard/src/routes/tax-regions/tax-region-list/tax-region-list.tsx b/packages/admin/dashboard/src/routes/tax-regions/tax-region-list/tax-region-list.tsx index 012305045e..054ae44e53 100644 --- a/packages/admin/dashboard/src/routes/tax-regions/tax-region-list/tax-region-list.tsx +++ b/packages/admin/dashboard/src/routes/tax-regions/tax-region-list/tax-region-list.tsx @@ -1,9 +1,9 @@ import { SingleColumnPage } from "../../../components/layout/pages" -import { useDashboardExtension } from "../../../extensions" +import { useExtension } from "../../../providers/extension-provider" import { TaxRegionListView } from "./components/tax-region-list-view" export const TaxRegionsList = () => { - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() return ( { error, } = useTaxRegion(province_id!, undefined, { initialData }) - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() if (isLoading || !taxRegion) { return diff --git a/packages/admin/dashboard/src/routes/users/user-detail/user-detail.tsx b/packages/admin/dashboard/src/routes/users/user-detail/user-detail.tsx index 3cf6c5a1b1..5bd07259cc 100644 --- a/packages/admin/dashboard/src/routes/users/user-detail/user-detail.tsx +++ b/packages/admin/dashboard/src/routes/users/user-detail/user-detail.tsx @@ -6,7 +6,7 @@ import { userLoader } from "./loader" import { SingleColumnPageSkeleton } from "../../../components/common/skeleton" import { SingleColumnPage } from "../../../components/layout/pages" -import { useDashboardExtension } from "../../../extensions" +import { useExtension } from "../../../providers/extension-provider" export const UserDetail = () => { const initialData = useLoaderData() as Awaited> @@ -21,7 +21,7 @@ export const UserDetail = () => { initialData, }) - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() if (isLoading || !user) { return diff --git a/packages/admin/dashboard/src/routes/users/user-list/user-list.tsx b/packages/admin/dashboard/src/routes/users/user-list/user-list.tsx index c80449af83..f2f1e77265 100644 --- a/packages/admin/dashboard/src/routes/users/user-list/user-list.tsx +++ b/packages/admin/dashboard/src/routes/users/user-list/user-list.tsx @@ -1,9 +1,9 @@ import { SingleColumnPage } from "../../../components/layout/pages" -import { useDashboardExtension } from "../../../extensions" +import { useExtension } from "../../../providers/extension-provider" import { UserListTable } from "./components/user-list-table" export const UserList = () => { - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() return ( { const { workflow_execution, isLoading, isError, error } = useWorkflowExecution(id!) - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() if (isLoading || !workflow_execution) { return diff --git a/packages/admin/dashboard/src/routes/workflow-executions/workflow-execution-list/workflow-execution-list.tsx b/packages/admin/dashboard/src/routes/workflow-executions/workflow-execution-list/workflow-execution-list.tsx index 647eaf967e..d3a2ce8254 100644 --- a/packages/admin/dashboard/src/routes/workflow-executions/workflow-execution-list/workflow-execution-list.tsx +++ b/packages/admin/dashboard/src/routes/workflow-executions/workflow-execution-list/workflow-execution-list.tsx @@ -1,10 +1,10 @@ import { WorkflowExecutionListTable } from "./components/workflow-execution-list-table" import { SingleColumnPage } from "../../../components/layout/pages" -import { useDashboardExtension } from "../../../extensions" +import { useExtension } from "../../../providers/extension-provider" export const WorkflowExcecutionList = () => { - const { getWidgets } = useDashboardExtension() + const { getWidgets } = useExtension() return ( void + } } declare const __BACKEND_URL__: string | undefined diff --git a/packages/core/framework/src/build-tools/compiler.ts b/packages/core/framework/src/build-tools/compiler.ts index 19de5986fd..c697c0fa42 100644 --- a/packages/core/framework/src/build-tools/compiler.ts +++ b/packages/core/framework/src/build-tools/compiler.ts @@ -1,9 +1,9 @@ -import path from "path" -import chokidar from "chokidar" -import type tsStatic from "typescript" -import { FileSystem, getConfigFile } from "@medusajs/utils" -import { rm, access, constants, copyFile } from "fs/promises" import type { AdminOptions, ConfigModule, Logger } from "@medusajs/types" +import { FileSystem, getConfigFile, getResolvedPlugins } from "@medusajs/utils" +import chokidar from "chokidar" +import { access, constants, copyFile, rm } from "fs/promises" +import path from "path" +import type tsStatic from "typescript" /** * The compiler exposes the opinionated APIs for compiling Medusa @@ -25,7 +25,6 @@ export class Compiler { #logger: Logger #projectRoot: string #tsConfigPath: string - #adminSourceFolder: string #pluginsDistFolder: string #backendIgnoreFiles: string[] #adminOnlyDistFolder: string @@ -35,7 +34,6 @@ export class Compiler { this.#projectRoot = projectRoot this.#logger = logger this.#tsConfigPath = path.join(this.#projectRoot, "tsconfig.json") - this.#adminSourceFolder = path.join(this.#projectRoot, "src/admin") this.#adminOnlyDistFolder = path.join(this.#projectRoot, ".medusa/admin") this.#pluginsDistFolder = path.join(this.#projectRoot, ".medusa/server") this.#backendIgnoreFiles = [ @@ -335,6 +333,7 @@ export class Compiler { build: ( options: AdminOptions & { sources: string[] + plugins: string[] outDir: string } ) => Promise @@ -372,11 +371,30 @@ export class Compiler { ) } + const plugins = await getResolvedPlugins( + this.#projectRoot, + configFile.configModule, + true + ) + + const adminSources = plugins + .map((plugin) => + plugin.admin?.type === "local" ? plugin.admin.resolve : undefined + ) + .filter(Boolean) as string[] + + const adminPlugins = plugins + .map((plugin) => + plugin.admin?.type === "package" ? plugin.admin.resolve : undefined + ) + .filter(Boolean) as string[] + try { this.#logger.info("Compiling frontend source...") await adminBundler.build({ disable: false, - sources: [this.#adminSourceFolder], + sources: adminSources, + plugins: adminPlugins, ...configFile.configModule.admin, outDir: adminOnly ? this.#adminOnlyDistFolder diff --git a/packages/core/types/src/common/config-module.ts b/packages/core/types/src/common/config-module.ts index 46337eaae6..ee6e925304 100644 --- a/packages/core/types/src/common/config-module.ts +++ b/packages/core/types/src/common/config-module.ts @@ -962,12 +962,17 @@ export type InputConfig = Partial< } > +type PluginAdminDetails = { + type: "local" | "package" + resolve: string +} + export type PluginDetails = { resolve: string - adminResolve: string name: string id: string options: Record version: string + admin?: PluginAdminDetails modules?: InputConfigModules } diff --git a/packages/medusa/src/loaders/__tests__/get-resolved-plugins.spec.ts b/packages/core/utils/src/common/__tests__/get-resolved-plugins.spec.ts similarity index 89% rename from packages/medusa/src/loaders/__tests__/get-resolved-plugins.spec.ts rename to packages/core/utils/src/common/__tests__/get-resolved-plugins.spec.ts index 9058c0a4a1..3b96e8fb6f 100644 --- a/packages/medusa/src/loaders/__tests__/get-resolved-plugins.spec.ts +++ b/packages/core/utils/src/common/__tests__/get-resolved-plugins.spec.ts @@ -1,6 +1,7 @@ import path from "path" -import { defineConfig, FileSystem } from "@medusajs/framework/utils" -import { getResolvedPlugins } from "../helpers/resolve-plugins" +import { defineConfig } from "../define-config" +import { FileSystem } from "../file-system" +import { getResolvedPlugins } from "../get-resolved-plugins" const BASE_DIR = path.join(__dirname, "sample-proj") const fs = new FileSystem(BASE_DIR) @@ -34,10 +35,7 @@ describe("getResolvedPlugins | relative paths", () => { expect(plugins).toEqual([ { resolve: path.join(fs.basePath, "./plugins/dummy/.medusa/server/src"), - adminResolve: path.join( - fs.basePath, - "./plugins/dummy/.medusa/server/src/admin" - ), + admin: undefined, name: "my-dummy-plugin", id: "my-dummy-plugin", options: { apiKey: "asecret" }, @@ -75,10 +73,7 @@ describe("getResolvedPlugins | relative paths", () => { expect(plugins).toEqual([ { resolve: path.join(fs.basePath, "./plugins/dummy/.medusa/server/src"), - adminResolve: path.join( - fs.basePath, - "./plugins/dummy/.medusa/server/src/admin" - ), + admin: undefined, name: "my-dummy-plugin", id: "my-dummy-plugin", options: { apiKey: "asecret" }, @@ -151,7 +146,10 @@ describe("getResolvedPlugins | relative paths", () => { expect(plugins).toEqual([ { resolve: path.join(fs.basePath, "./plugins/dummy/.medusa/server/src"), - adminResolve: path.join(fs.basePath, "./plugins/dummy/src/admin"), + admin: { + type: "local", + resolve: path.join(fs.basePath, "./plugins/dummy/src/admin"), + }, name: "my-dummy-plugin", id: "my-dummy-plugin", options: { apiKey: "asecret" }, @@ -198,10 +196,7 @@ describe("getResolvedPlugins | package reference", () => { fs.basePath, "node_modules/@plugins/dummy/.medusa/server/src" ), - adminResolve: path.join( - fs.basePath, - "node_modules/@plugins/dummy/.medusa/server/src/admin" - ), + admin: undefined, name: "my-dummy-plugin", id: "my-dummy-plugin", options: { apiKey: "asecret" }, @@ -243,10 +238,7 @@ describe("getResolvedPlugins | package reference", () => { fs.basePath, "node_modules/@plugins/dummy/.medusa/server/src" ), - adminResolve: path.join( - fs.basePath, - "node_modules/@plugins/dummy/.medusa/server/src/admin" - ), + admin: undefined, name: "my-dummy-plugin", id: "my-dummy-plugin", options: { apiKey: "asecret" }, diff --git a/packages/medusa/src/loaders/helpers/resolve-plugins.ts b/packages/core/utils/src/common/get-resolved-plugins.ts similarity index 84% rename from packages/medusa/src/loaders/helpers/resolve-plugins.ts rename to packages/core/utils/src/common/get-resolved-plugins.ts index 0418d81656..a1c5d7f0b6 100644 --- a/packages/medusa/src/loaders/helpers/resolve-plugins.ts +++ b/packages/core/utils/src/common/get-resolved-plugins.ts @@ -1,7 +1,8 @@ -import path from "path" +import { ConfigModule, PluginDetails } from "@medusajs/types" import fs from "fs/promises" -import { isString, readDir } from "@medusajs/framework/utils" -import { ConfigModule, PluginDetails } from "@medusajs/framework/types" +import path from "path" +import { isString } from "./is-string" +import { readDir } from "./read-dir-recursive" const MEDUSA_APP_SOURCE_PATH = "src" const MEDUSA_PLUGIN_SOURCE_PATH = ".medusa/server/src" @@ -89,13 +90,27 @@ async function resolvePlugin( }) const pluginOptions = options ?? {} + const hasAdmin = + !!pkgJSON.contents.exports?.["./admin"] || !!pluginStaticOptions.srcDir + const isAdminLocal = hasAdmin && !!pluginStaticOptions.srcDir + + const adminConfig = hasAdmin + ? { + type: isAdminLocal ? ("local" as const) : ("package" as const), + resolve: path.join( + isAdminLocal ? pluginStaticOptions.srcDir : name, + "admin" + ), + } + : undefined + return { resolve, name, id: createPluginId(name), options: pluginOptions, version: pkgJSON.contents.version || "0.0.0", - adminResolve: path.join(pluginStaticOptions.srcDir ?? resolve, "admin"), + admin: adminConfig, modules: modules.map((mod) => { return { resolve: `${pluginPath}/${MEDUSA_PLUGIN_SOURCE_PATH}/modules/${mod.name}`, @@ -125,7 +140,10 @@ export async function getResolvedPlugins( resolve: extensionDirectory, name: MEDUSA_PROJECT_NAME, id: createPluginId(MEDUSA_PROJECT_NAME), - adminResolve: path.join(extensionDirectory, "admin"), + admin: { + type: "local", + resolve: path.join(extensionDirectory, "admin"), + }, options: configModule, version: createFileContentHash(process.cwd(), `**`), }) diff --git a/packages/core/utils/src/common/index.ts b/packages/core/utils/src/common/index.ts index 423c1e1b81..34952511c2 100644 --- a/packages/core/utils/src/common/index.ts +++ b/packages/core/utils/src/common/index.ts @@ -27,6 +27,7 @@ export * from "./get-config-file" export * from "./get-duplicates" export * from "./get-iso-string-from-date" export * from "./get-node-version" +export * from "./get-resolved-plugins" export * from "./get-selects-and-relations-from-object-array" export * from "./get-set-difference" export * from "./graceful-shutdown-server" diff --git a/packages/medusa-test-utils/src/medusa-test-runner-utils/use-db.ts b/packages/medusa-test-utils/src/medusa-test-runner-utils/use-db.ts index 24f2f5c0ac..eb6c17f061 100644 --- a/packages/medusa-test-utils/src/medusa-test-runner-utils/use-db.ts +++ b/packages/medusa-test-utils/src/medusa-test-runner-utils/use-db.ts @@ -1,7 +1,10 @@ import type { MedusaAppLoader } from "@medusajs/framework" -import { join } from "path" import { MedusaContainer } from "@medusajs/framework/types" -import { ContainerRegistrationKeys } from "@medusajs/framework/utils" +import { + ContainerRegistrationKeys, + getResolvedPlugins, +} from "@medusajs/framework/utils" +import { join } from "path" /** * Initiates the database connection @@ -53,11 +56,6 @@ export async function syncLinks( } async function loadCustomLinks(directory: string, container: MedusaContainer) { - // TODO: move to framework once settle down - const { - getResolvedPlugins, - } = require("@medusajs/medusa/loaders/helpers/resolve-plugins") - const configModule = container.resolve( ContainerRegistrationKeys.CONFIG_MODULE ) diff --git a/packages/medusa/src/commands/db/generate.ts b/packages/medusa/src/commands/db/generate.ts index 3380622738..73ab736cac 100644 --- a/packages/medusa/src/commands/db/generate.ts +++ b/packages/medusa/src/commands/db/generate.ts @@ -1,16 +1,16 @@ -import { join } from "path" +import { MedusaAppLoader } from "@medusajs/framework" +import { LinkLoader } from "@medusajs/framework/links" +import { logger } from "@medusajs/framework/logger" import { ContainerRegistrationKeys, + getResolvedPlugins, MedusaError, mergePluginModules, } from "@medusajs/framework/utils" -import { LinkLoader } from "@medusajs/framework/links" -import { logger } from "@medusajs/framework/logger" -import { MedusaAppLoader } from "@medusajs/framework" +import { join } from "path" -import { ensureDbExists } from "../utils" import { initializeContainer } from "../../loaders" -import { getResolvedPlugins } from "../../loaders/helpers/resolve-plugins" +import { ensureDbExists } from "../utils" const TERMINAL_SIZE = process.stdout.columns diff --git a/packages/medusa/src/commands/db/migrate.ts b/packages/medusa/src/commands/db/migrate.ts index 046210360b..fffc189319 100644 --- a/packages/medusa/src/commands/db/migrate.ts +++ b/packages/medusa/src/commands/db/migrate.ts @@ -3,6 +3,7 @@ import { LinkLoader } from "@medusajs/framework/links" import { logger } from "@medusajs/framework/logger" import { ContainerRegistrationKeys, + getResolvedPlugins, mergePluginModules, } from "@medusajs/framework/utils" import { join } from "path" @@ -10,7 +11,6 @@ import { join } from "path" import { fork } from "child_process" import path from "path" import { initializeContainer } from "../../loaders" -import { getResolvedPlugins } from "../../loaders/helpers/resolve-plugins" import { ensureDbExists } from "../utils" import { syncLinks } from "./sync-links" const TERMINAL_SIZE = process.stdout.columns diff --git a/packages/medusa/src/commands/db/rollback.ts b/packages/medusa/src/commands/db/rollback.ts index 23038daf4b..a43d95c774 100644 --- a/packages/medusa/src/commands/db/rollback.ts +++ b/packages/medusa/src/commands/db/rollback.ts @@ -1,16 +1,16 @@ -import { join } from "path" +import { MedusaAppLoader } from "@medusajs/framework" +import { LinkLoader } from "@medusajs/framework/links" +import { logger } from "@medusajs/framework/logger" import { ContainerRegistrationKeys, + getResolvedPlugins, MedusaError, mergePluginModules, } from "@medusajs/framework/utils" -import { LinkLoader } from "@medusajs/framework/links" -import { logger } from "@medusajs/framework/logger" -import { MedusaAppLoader } from "@medusajs/framework" +import { join } from "path" -import { ensureDbExists } from "../utils" import { initializeContainer } from "../../loaders" -import { getResolvedPlugins } from "../../loaders/helpers/resolve-plugins" +import { ensureDbExists } from "../utils" const TERMINAL_SIZE = process.stdout.columns diff --git a/packages/medusa/src/commands/db/run-scripts.ts b/packages/medusa/src/commands/db/run-scripts.ts index 67a4241a6c..f443be0f5d 100644 --- a/packages/medusa/src/commands/db/run-scripts.ts +++ b/packages/medusa/src/commands/db/run-scripts.ts @@ -4,6 +4,7 @@ import { logger } from "@medusajs/framework/logger" import { MigrationScriptsMigrator } from "@medusajs/framework/migrations" import { ContainerRegistrationKeys, + getResolvedPlugins, mergePluginModules, } from "@medusajs/framework/utils" import { dirname, join } from "path" @@ -11,7 +12,6 @@ import { dirname, join } from "path" import { MedusaModule } from "@medusajs/framework/modules-sdk" import { MedusaContainer, PluginDetails } from "@medusajs/types" import { initializeContainer } from "../../loaders" -import { getResolvedPlugins } from "../../loaders/helpers/resolve-plugins" import { ensureDbExists } from "../utils" const TERMINAL_SIZE = process.stdout.columns diff --git a/packages/medusa/src/commands/db/sync-links.ts b/packages/medusa/src/commands/db/sync-links.ts index 7d91ab0c01..a1be09f985 100644 --- a/packages/medusa/src/commands/db/sync-links.ts +++ b/packages/medusa/src/commands/db/sync-links.ts @@ -1,19 +1,19 @@ +import checkbox from "@inquirer/checkbox" +import { MedusaAppLoader } from "@medusajs/framework" +import { LinkLoader } from "@medusajs/framework/links" +import { logger } from "@medusajs/framework/logger" +import { LinkMigrationsPlannerAction } from "@medusajs/framework/types" +import { + ContainerRegistrationKeys, + getResolvedPlugins, + mergePluginModules, +} from "@medusajs/framework/utils" import boxen from "boxen" import chalk from "chalk" import { join } from "path" -import checkbox from "@inquirer/checkbox" -import { - ContainerRegistrationKeys, - mergePluginModules, -} from "@medusajs/framework/utils" -import { LinkMigrationsPlannerAction } from "@medusajs/framework/types" -import { LinkLoader } from "@medusajs/framework/links" -import { logger } from "@medusajs/framework/logger" -import { MedusaAppLoader } from "@medusajs/framework" -import { ensureDbExists } from "../utils" import { initializeContainer } from "../../loaders" -import { getResolvedPlugins } from "../../loaders/helpers/resolve-plugins" +import { ensureDbExists } from "../utils" /** * Groups action tables by their "action" property diff --git a/packages/medusa/src/loaders/admin.ts b/packages/medusa/src/loaders/admin.ts index c5fa3c238b..dd4059f6d9 100644 --- a/packages/medusa/src/loaders/admin.ts +++ b/packages/medusa/src/loaders/admin.ts @@ -5,7 +5,6 @@ import { PluginDetails, } from "@medusajs/framework/types" import { Express } from "express" -import fs from "fs" import path from "path" import { ADMIN_RELATIVE_OUTPUT_DIR } from "../utils" @@ -20,6 +19,7 @@ type IntializedOptions = Required> & AdminOptions & { outDir: string sources?: string[] + plugins?: string[] } const NOT_ALLOWED_PATHS = ["/auth", "/store", "/admin"] @@ -33,15 +33,23 @@ export default async function adminLoader({ const { admin } = configModule const sources: string[] = [] + const pluginAdminPaths: string[] = [] for (const plugin of plugins) { - if (fs.existsSync(plugin.adminResolve)) { - sources.push(plugin.adminResolve) + if (!plugin.admin) { + continue + } + + if (plugin.admin.type === "local") { + sources.push(plugin.admin.resolve) + } else { + pluginAdminPaths.push(plugin.admin.resolve) } } const adminOptions: IntializedOptions = { disable: false, sources, + plugins: pluginAdminPaths, ...admin, outDir: path.join(rootDirectory, ADMIN_RELATIVE_OUTPUT_DIR), } diff --git a/packages/medusa/src/loaders/index.ts b/packages/medusa/src/loaders/index.ts index 97a7cae2b5..f0bbb3a2b3 100644 --- a/packages/medusa/src/loaders/index.ts +++ b/packages/medusa/src/loaders/index.ts @@ -15,6 +15,7 @@ import { } from "@medusajs/framework/types" import { ContainerRegistrationKeys, + getResolvedPlugins, GraphQLSchema, mergePluginModules, promiseAll, @@ -27,7 +28,6 @@ import requestIp from "request-ip" import { v4 } from "uuid" import adminLoader from "./admin" import apiLoader from "./api" -import { getResolvedPlugins } from "./helpers/resolve-plugins" type Options = { directory: string diff --git a/yarn.lock b/yarn.lock index bf8dc56aac..5123a53a03 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5267,22 +5267,19 @@ __metadata: "@medusajs/admin-vite-plugin": 2.6.1 "@medusajs/dashboard": 2.6.1 "@medusajs/types": 2.6.1 - "@rollup/plugin-node-resolve": ^16.0.0 "@types/compression": ^1.7.5 "@vitejs/plugin-react": ^4.2.1 autoprefixer: ^10.4.16 compression: ^1.7.4 - copyfiles: ^2.4.1 express: ^4.21.0 get-port: ^5.1.1 glob: ^10.3.10 + outdent: ^0.8.0 postcss: ^8.4.32 tailwindcss: ^3.3.6 tsup: ^8.0.1 typescript: ^5.3.3 vite: ^5.4.14 - peerDependencies: - react-dom: ^18.0.0 languageName: unknown linkType: soft @@ -11296,24 +11293,6 @@ __metadata: languageName: node linkType: hard -"@rollup/plugin-node-resolve@npm:^16.0.0": - version: 16.0.0 - resolution: "@rollup/plugin-node-resolve@npm:16.0.0" - dependencies: - "@rollup/pluginutils": ^5.0.1 - "@types/resolve": 1.20.2 - deepmerge: ^4.2.2 - is-module: ^1.0.0 - resolve: ^1.22.1 - peerDependencies: - rollup: ^2.78.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - checksum: b63deb6fc14b37070ccaffacc8c10c9720f28ce7632f4fe2ee77064c0c79bcc3fe060fb77160e673c9fd847307252f25a2983030bd54f1888324063c69ae1399 - languageName: node - linkType: hard - "@rollup/plugin-replace@npm:^5.0.2": version: 5.0.5 resolution: "@rollup/plugin-replace@npm:5.0.5" @@ -17681,24 +17660,6 @@ __metadata: languageName: node linkType: hard -"copyfiles@npm:^2.4.1": - version: 2.4.1 - resolution: "copyfiles@npm:2.4.1" - dependencies: - glob: ^7.0.5 - minimatch: ^3.0.3 - mkdirp: ^1.0.4 - noms: 0.0.0 - through2: ^2.0.1 - untildify: ^4.0.0 - yargs: ^16.1.0 - bin: - copyfiles: copyfiles - copyup: copyfiles - checksum: e65cd055ec9acc14997b0ace83973d73f8d9c68167cbf4293c40b52d100af09a8c8da329042d52dc33422c0a8cbf74c6efb25e9ae088667721653659bd67bf57 - languageName: node - linkType: hard - "core-js-compat@npm:^3.31.0, core-js-compat@npm:^3.36.1": version: 3.37.0 resolution: "core-js-compat@npm:3.37.0" @@ -21493,7 +21454,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:7.2.3, glob@npm:^7.0.5, glob@npm:^7.1.1, glob@npm:^7.1.3, glob@npm:^7.1.4, glob@npm:^7.1.6, glob@npm:^7.2.0, glob@npm:~7.2.0": +"glob@npm:7.2.3, glob@npm:^7.1.1, glob@npm:^7.1.3, glob@npm:^7.1.4, glob@npm:^7.1.6, glob@npm:^7.2.0, glob@npm:~7.2.0": version: 7.2.3 resolution: "glob@npm:7.2.3" dependencies: @@ -22372,7 +22333,7 @@ __metadata: languageName: node linkType: hard -"inherits@npm:2, inherits@npm:2.0.4, inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.1, inherits@npm:~2.0.3": +"inherits@npm:2, inherits@npm:2.0.4, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3": version: 2.0.4 resolution: "inherits@npm:2.0.4" checksum: 4e531f648b29039fb7426fb94075e6545faa1eb9fe83c29f0b6d9e7263aceb4289d2d4557db0d428188eeb449cc7c5e77b0a0b2c4e248ff2a65933a0dee49ef2 @@ -23208,13 +23169,6 @@ __metadata: languageName: node linkType: hard -"isarray@npm:0.0.1": - version: 0.0.1 - resolution: "isarray@npm:0.0.1" - checksum: ed1e62da617f71fe348907c71743b5ed550448b455f8d269f89a7c7ddb8ae6e962de3dab6a74a237b06f5eb7f6ece7a45ada8ce96d87fe972926530f91ae3311 - languageName: node - linkType: hard - "isarray@npm:^2.0.5": version: 2.0.5 resolution: "isarray@npm:2.0.5" @@ -25454,7 +25408,7 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:2 || 3, minimatch@npm:^3.0.3, minimatch@npm:^3.0.4, minimatch@npm:^3.0.5, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": +"minimatch@npm:2 || 3, minimatch@npm:^3.0.4, minimatch@npm:^3.0.5, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": version: 3.1.2 resolution: "minimatch@npm:3.1.2" dependencies: @@ -25646,7 +25600,7 @@ __metadata: languageName: node linkType: hard -"mkdirp@npm:^1.0.3, mkdirp@npm:^1.0.4": +"mkdirp@npm:^1.0.3": version: 1.0.4 resolution: "mkdirp@npm:1.0.4" bin: @@ -26214,16 +26168,6 @@ __metadata: languageName: node linkType: hard -"noms@npm:0.0.0": - version: 0.0.0 - resolution: "noms@npm:0.0.0" - dependencies: - inherits: ^2.0.1 - readable-stream: ~1.0.31 - checksum: 7790dbbef45c593b5444b361cb9cde3260244ab66aaa199c0728d334525eb69df96231115cff260b71b92fc7a6915a642aa22f2f8448696d8dd6e7d7cebfccce - languageName: node - linkType: hard - "nopt@npm:^7.0.0": version: 7.2.1 resolution: "nopt@npm:7.2.1" @@ -29076,7 +29020,7 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:^2.2.2, readable-stream@npm:^2.3.5, readable-stream@npm:~2.3.6": +"readable-stream@npm:^2.2.2, readable-stream@npm:^2.3.5": version: 2.3.8 resolution: "readable-stream@npm:2.3.8" dependencies: @@ -29102,18 +29046,6 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:~1.0.31": - version: 1.0.34 - resolution: "readable-stream@npm:1.0.34" - dependencies: - core-util-is: ~1.0.0 - inherits: ~2.0.1 - isarray: 0.0.1 - string_decoder: ~0.10.x - checksum: 02272551396ed8930ddee1a088bdf0379f0f7cc47ac49ed8804e998076cb7daec9fbd2b1fd9c0490ec72e56e8bb3651abeb8080492b8e0a9c3f2158330908ed6 - languageName: node - linkType: hard - "readdirp@npm:~3.6.0": version: 3.6.0 resolution: "readdirp@npm:3.6.0" @@ -31399,13 +31331,6 @@ __metadata: languageName: node linkType: hard -"string_decoder@npm:~0.10.x": - version: 0.10.31 - resolution: "string_decoder@npm:0.10.31" - checksum: 1c628d78f974aa7539c496029f48e7019acc32487fc695464f9d6bdfec98edd7d933a06b3216bc2016918f6e75074c611d84430a53cb0e43071597d6c1ac5e25 - languageName: node - linkType: hard - "string_decoder@npm:~1.1.1": version: 1.1.1 resolution: "string_decoder@npm:1.1.1" @@ -31942,16 +31867,6 @@ __metadata: languageName: node linkType: hard -"through2@npm:^2.0.1": - version: 2.0.5 - resolution: "through2@npm:2.0.5" - dependencies: - readable-stream: ~2.3.6 - xtend: ~4.0.1 - checksum: cbfe5b57943fa12b4f8c043658c2a00476216d79c014895cef1ac7a1d9a8b31f6b438d0e53eecbb81054b93128324a82ecd59ec1a4f91f01f7ac113dcb14eade - languageName: node - linkType: hard - "through@npm:>=2.2.7 <3, through@npm:^2.3.6, through@npm:^2.3.8": version: 2.3.8 resolution: "through@npm:2.3.8" @@ -34266,7 +34181,7 @@ __metadata: languageName: node linkType: hard -"xtend@npm:^4.0.0, xtend@npm:^4.0.2, xtend@npm:~4.0.0, xtend@npm:~4.0.1": +"xtend@npm:^4.0.0, xtend@npm:^4.0.2, xtend@npm:~4.0.0": version: 4.0.2 resolution: "xtend@npm:4.0.2" checksum: 366ae4783eec6100f8a02dff02ac907bf29f9a00b82ac0264b4d8b832ead18306797e283cf19de776538babfdcb2101375ec5646b59f08c52128ac4ab812ed0e @@ -34422,7 +34337,7 @@ __metadata: languageName: node linkType: hard -"yargs@npm:^16.1.0, yargs@npm:^16.1.1": +"yargs@npm:^16.1.1": version: 16.2.0 resolution: "yargs@npm:16.2.0" dependencies: