feat(medusa,dashboard,admin-sdk): Run admin dashboard from Medusa instance (#7330)
This commit is contained in:
1 parent
ec5415ea1a
commit
490586f566
82 files changed
+3946
-788
No files matched your search
@@ -23,14 +23,12 @@
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@medusajs/types": "^1.11.16",
|
||||
"@swc/core": "^1.4.8",
|
||||
"@swc/jest": "^0.2.36",
|
||||
"@types/express": "^4.17.17",
|
||||
"@types/ioredis": "^4.28.10",
|
||||
"@types/jsonwebtoken": "^8.5.9",
|
||||
"@types/lodash": "^4.14.191",
|
||||
"@types/multer": "^1.4.7",
|
||||
"@types/papaparse": "^5.3.7",
|
||||
"cross-env": "^5.2.1",
|
||||
"jest": "^25.5.4",
|
||||
"medusa-interfaces": "^1.3.9",
|
||||
@@ -51,6 +49,7 @@
|
||||
"medusa-interfaces": "^1.3.7"
|
||||
},
|
||||
"dependencies": {
|
||||
"@medusajs/admin-sdk": "0.0.1",
|
||||
"@medusajs/core-flows": "^0.0.9",
|
||||
"@medusajs/link-modules": "^0.2.11",
|
||||
"@medusajs/medusa-cli": "^1.3.22",
|
||||
@@ -58,6 +57,7 @@
|
||||
"@medusajs/orchestration": "^0.5.7",
|
||||
"@medusajs/utils": "^1.11.9",
|
||||
"@medusajs/workflows-sdk": "^0.1.6",
|
||||
"@swc/core": "^1.4.8",
|
||||
"awilix": "^8.0.0",
|
||||
"body-parser": "^1.19.0",
|
||||
"boxen": "^5.0.1",
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
import { ConfigModule } from "@medusajs/types"
|
||||
import { transformFile } from "@swc/core"
|
||||
import { getConfigFile } from "medusa-core-utils"
|
||||
import fs from "node:fs/promises"
|
||||
import path from "path"
|
||||
|
||||
type BuildArgs = {
|
||||
directory: string
|
||||
}
|
||||
|
||||
type FileConfig = {
|
||||
inputDir: string
|
||||
outputDir: string
|
||||
targetExtension?: string
|
||||
}
|
||||
|
||||
const INPUT_DIR = "./src"
|
||||
const OUTPUT_DIR = "./dist"
|
||||
|
||||
const COMPILE_EXTENSIONS = [".ts", ".tsx", ".js", ".jsx"]
|
||||
const IGNORE_EXTENSIONS = [".md"]
|
||||
|
||||
async function clean(path: string) {
|
||||
await fs.rm(path, { recursive: true }).catch(() => {})
|
||||
}
|
||||
|
||||
async function findFiles(dir: string): Promise<string[]> {
|
||||
try {
|
||||
const files = await fs.readdir(dir, { withFileTypes: true })
|
||||
const paths = await Promise.all(
|
||||
files.map(async (file) => {
|
||||
const res = path.join(dir, file.name)
|
||||
return file.isDirectory() ? findFiles(res) : res
|
||||
})
|
||||
)
|
||||
return paths.flat()
|
||||
} catch (e) {
|
||||
console.log(`Failed to read directory ${dir}`)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
const getOutputPath = (file: string, config: FileConfig) => {
|
||||
const { inputDir, outputDir, targetExtension } = config
|
||||
|
||||
const inputDirName = path.basename(inputDir)
|
||||
const outputDirName = path.basename(outputDir)
|
||||
|
||||
const relativePath = file.replace(inputDirName, outputDirName)
|
||||
let outputPath = relativePath
|
||||
|
||||
if (targetExtension) {
|
||||
const currentExtension = path.extname(outputPath)
|
||||
outputPath = outputPath.replace(currentExtension, targetExtension)
|
||||
}
|
||||
|
||||
return outputPath
|
||||
}
|
||||
|
||||
const writeToOut = async (
|
||||
file: string,
|
||||
content: string,
|
||||
config: FileConfig
|
||||
) => {
|
||||
const outputPath = getOutputPath(file, config)
|
||||
|
||||
await fs.mkdir(outputPath.replace(/\/[^/]+$/, ""), { recursive: true })
|
||||
await fs.writeFile(outputPath, content)
|
||||
}
|
||||
|
||||
async function copyToOut(file: string, config: FileConfig) {
|
||||
const outputPath = getOutputPath(file, config)
|
||||
const dirNameRegex = new RegExp("\\" + path.sep + "([^\\" + path.sep + "]+)$")
|
||||
|
||||
await fs.mkdir(outputPath.replace(dirNameRegex, ""), { recursive: true })
|
||||
await fs.copyFile(file, outputPath)
|
||||
}
|
||||
|
||||
const medusaTransform = async (file: string) => {
|
||||
if (COMPILE_EXTENSIONS.some((ext) => file.endsWith(ext))) {
|
||||
const outputPath = getOutputPath(file, {
|
||||
inputDir: INPUT_DIR,
|
||||
outputDir: OUTPUT_DIR,
|
||||
})
|
||||
const output = await transformFile(file, {
|
||||
sourceFileName: path.relative(path.dirname(outputPath), file),
|
||||
sourceMaps: "inline",
|
||||
module: {
|
||||
type: "commonjs",
|
||||
},
|
||||
jsc: {
|
||||
parser: {
|
||||
syntax: "typescript",
|
||||
decorators: true,
|
||||
},
|
||||
transform: {
|
||||
decoratorMetadata: true,
|
||||
},
|
||||
},
|
||||
})
|
||||
await writeToOut(file, output.code, {
|
||||
inputDir: INPUT_DIR,
|
||||
outputDir: OUTPUT_DIR,
|
||||
targetExtension: ".js",
|
||||
})
|
||||
} else if (!IGNORE_EXTENSIONS.some((ext) => file.endsWith(ext))) {
|
||||
// Copy non-ts files
|
||||
await copyToOut(file, { inputDir: INPUT_DIR, outputDir: OUTPUT_DIR })
|
||||
}
|
||||
}
|
||||
|
||||
export default async function ({ directory }: BuildArgs) {
|
||||
const started = Date.now()
|
||||
|
||||
const { configModule, error } = getConfigFile<ConfigModule>(
|
||||
directory,
|
||||
"medusa-config"
|
||||
)
|
||||
|
||||
if (error) {
|
||||
console.log(`Failed to load medusa-config.js`)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
const input = path.join(directory, INPUT_DIR)
|
||||
const dist = path.join(directory, OUTPUT_DIR)
|
||||
|
||||
await clean(dist)
|
||||
|
||||
const files = await findFiles(input)
|
||||
|
||||
await Promise.all(files.map(medusaTransform))
|
||||
|
||||
const adminOptions = {
|
||||
disable: false,
|
||||
path: "/app" as const,
|
||||
outDir: "./build",
|
||||
...configModule.admin,
|
||||
}
|
||||
|
||||
if (!adminOptions.disable) {
|
||||
try {
|
||||
const { build: buildProductionBuild } = await import(
|
||||
"@medusajs/admin-sdk"
|
||||
)
|
||||
|
||||
await buildProductionBuild(adminOptions)
|
||||
} catch (error) {
|
||||
console.log("Failed to build admin")
|
||||
}
|
||||
}
|
||||
|
||||
const time = Date.now() - started
|
||||
|
||||
console.log(`Build completed in ${time}ms`)
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
import { AdminOptions, ConfigModule } from "@medusajs/types"
|
||||
import { Express } from "express"
|
||||
|
||||
type Options = {
|
||||
app: Express
|
||||
configModule: ConfigModule
|
||||
}
|
||||
|
||||
type IntializedOptions = Required<
|
||||
Pick<AdminOptions, "path" | "disable" | "outDir">
|
||||
> &
|
||||
AdminOptions
|
||||
|
||||
export default async function adminLoader({ app, configModule }: Options) {
|
||||
const { admin } = configModule
|
||||
|
||||
const adminOptions: IntializedOptions = {
|
||||
disable: false,
|
||||
path: "/app",
|
||||
outDir: "./build",
|
||||
...admin,
|
||||
}
|
||||
|
||||
if (admin?.disable) {
|
||||
return app
|
||||
}
|
||||
|
||||
if (process.env.COMMAND_INITIATED_BY === "develop") {
|
||||
return initDevelopmentServer(app, adminOptions)
|
||||
}
|
||||
|
||||
return serveProductionBuild(app, adminOptions)
|
||||
}
|
||||
|
||||
async function initDevelopmentServer(app: Express, options: IntializedOptions) {
|
||||
const { develop } = await import("@medusajs/admin-sdk")
|
||||
|
||||
const adminMiddleware = await develop(options)
|
||||
app.use(options.path, adminMiddleware)
|
||||
return app
|
||||
}
|
||||
|
||||
async function serveProductionBuild(app: Express, options: IntializedOptions) {
|
||||
const { serve } = await import("@medusajs/admin-sdk")
|
||||
|
||||
const adminRoute = await serve(options)
|
||||
|
||||
app.use(options.path, adminRoute)
|
||||
|
||||
return app
|
||||
}
|
||||
@@ -77,6 +77,7 @@ export default (rootDirectory: string): ConfigModule => {
|
||||
...configModule?.projectConfig,
|
||||
worker_mode,
|
||||
},
|
||||
admin: configModule?.admin ?? {},
|
||||
modules: configModule.modules ?? {},
|
||||
featureFlags: configModule?.featureFlags ?? {},
|
||||
plugins: configModule?.plugins ?? [],
|
||||
|
||||
@@ -7,6 +7,7 @@ import { createMedusaContainer } from "medusa-core-utils"
|
||||
import requestIp from "request-ip"
|
||||
import { v4 } from "uuid"
|
||||
import { MedusaContainer } from "../types/global"
|
||||
import adminLoader from "./admin"
|
||||
import apiLoader from "./api"
|
||||
import loadConfig from "./config"
|
||||
import expressLoader from "./express"
|
||||
@@ -54,6 +55,8 @@ async function loadEntrypoints(
|
||||
next()
|
||||
})
|
||||
|
||||
await adminLoader({ app: expressApp, configModule })
|
||||
|
||||
// subscribersLoader({ container })
|
||||
|
||||
await apiLoader({
|
||||
|
||||
Reference in new issue
Block a user