feat(medusa,dashboard,admin-sdk): Run admin dashboard from Medusa instance (#7330)

This commit is contained in:
Kasper Fabricius Kristensen authored and GitHub committed 2024-05-15 19:52:09 +02:00
1 parent ec5415ea1a
commit 490586f566
82 files changed
+3946 -788

No files matched your search

+2 -2
View File
@@ -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",
+156
View File
@@ -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`)
}
+51
View File
@@ -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
}
+1
View File
@@ -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 ?? [],
+3
View File
@@ -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({