@mercurjs/dashboard-sdk 2.3.8-canary.1 → 2.3.8-canary.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +29 -0
- package/dist/index.d.cts +6 -3
- package/dist/index.d.ts +6 -3
- package/dist/index.js +24 -0
- package/dist/{types-BTgTMD_t.d.cts → types-DG9Yya-_.d.cts} +104 -5
- package/dist/{types-BTgTMD_t.d.ts → types-DG9Yya-_.d.ts} +104 -5
- package/dist/vite.cjs +613 -634
- package/dist/vite.d.cts +4 -4
- package/dist/vite.d.ts +4 -4
- package/dist/vite.js +615 -635
- package/package.json +1 -1
package/dist/vite.cjs
CHANGED
|
@@ -36,8 +36,8 @@ __export(vite_exports, {
|
|
|
36
36
|
module.exports = __toCommonJS(vite_exports);
|
|
37
37
|
|
|
38
38
|
// src/plugin.ts
|
|
39
|
-
var
|
|
40
|
-
var
|
|
39
|
+
var import_path5 = __toESM(require("path"), 1);
|
|
40
|
+
var import_fs6 = __toESM(require("fs"), 1);
|
|
41
41
|
var import_module = require("module");
|
|
42
42
|
|
|
43
43
|
// src/utils.ts
|
|
@@ -64,6 +64,8 @@ var I18N_VIRTUAL_MODULE = "virtual:mercur/i18n";
|
|
|
64
64
|
var WIDGETS_VIRTUAL_MODULE = "virtual:mercur/widgets";
|
|
65
65
|
var NAVIGATION_VIRTUAL_MODULE = "virtual:mercur/navigation";
|
|
66
66
|
var CUSTOM_FIELDS_VIRTUAL_MODULE = "virtual:mercur/custom-fields";
|
|
67
|
+
var LAYOUTS_VIRTUAL_MODULE = "virtual:mercur/layouts";
|
|
68
|
+
var PREFERENCES_VIRTUAL_MODULE = "virtual:mercur/preferences";
|
|
67
69
|
var RESOLVED_CONFIG_MODULE = "\0" + CONFIG_VIRTUAL_MODULE;
|
|
68
70
|
var RESOLVED_ROUTES_MODULE = "\0" + ROUTES_VIRTUAL_MODULE;
|
|
69
71
|
var RESOLVED_MENU_ITEMS_MODULE = "\0" + MENU_ITEMS_VIRTUAL_MODULE;
|
|
@@ -71,6 +73,8 @@ var RESOLVED_I18N_MODULE = "\0" + I18N_VIRTUAL_MODULE;
|
|
|
71
73
|
var RESOLVED_WIDGETS_MODULE = "\0" + WIDGETS_VIRTUAL_MODULE;
|
|
72
74
|
var RESOLVED_NAVIGATION_MODULE = "\0" + NAVIGATION_VIRTUAL_MODULE;
|
|
73
75
|
var RESOLVED_CUSTOM_FIELDS_MODULE = "\0" + CUSTOM_FIELDS_VIRTUAL_MODULE;
|
|
76
|
+
var RESOLVED_LAYOUTS_MODULE = "\0" + LAYOUTS_VIRTUAL_MODULE;
|
|
77
|
+
var RESOLVED_PREFERENCES_MODULE = "\0" + PREFERENCES_VIRTUAL_MODULE;
|
|
74
78
|
var VIRTUAL_MODULES = [
|
|
75
79
|
CONFIG_VIRTUAL_MODULE,
|
|
76
80
|
ROUTES_VIRTUAL_MODULE,
|
|
@@ -78,8 +82,12 @@ var VIRTUAL_MODULES = [
|
|
|
78
82
|
I18N_VIRTUAL_MODULE,
|
|
79
83
|
WIDGETS_VIRTUAL_MODULE,
|
|
80
84
|
NAVIGATION_VIRTUAL_MODULE,
|
|
81
|
-
CUSTOM_FIELDS_VIRTUAL_MODULE
|
|
85
|
+
CUSTOM_FIELDS_VIRTUAL_MODULE,
|
|
86
|
+
LAYOUTS_VIRTUAL_MODULE,
|
|
87
|
+
PREFERENCES_VIRTUAL_MODULE
|
|
82
88
|
];
|
|
89
|
+
var LAYOUT_PREFERENCES_FILE = "_layouts";
|
|
90
|
+
var NAVIGATION_FILE = "_navigation";
|
|
83
91
|
|
|
84
92
|
// src/utils.ts
|
|
85
93
|
function normalizePath(filePath) {
|
|
@@ -118,9 +126,9 @@ function resolveExports(moduleExports) {
|
|
|
118
126
|
}
|
|
119
127
|
return moduleExports;
|
|
120
128
|
}
|
|
121
|
-
async function getFileExports(
|
|
129
|
+
async function getFileExports(path6) {
|
|
122
130
|
const { unregister } = await safeRegister();
|
|
123
|
-
const module2 = require(
|
|
131
|
+
const module2 = require(path6);
|
|
124
132
|
unregister();
|
|
125
133
|
return resolveExports(module2);
|
|
126
134
|
}
|
|
@@ -146,13 +154,13 @@ function hasDefaultExport(ast) {
|
|
|
146
154
|
ExportDefaultDeclaration() {
|
|
147
155
|
found = true;
|
|
148
156
|
},
|
|
149
|
-
AssignmentExpression(
|
|
150
|
-
if (
|
|
157
|
+
AssignmentExpression(path6) {
|
|
158
|
+
if (path6.node.left.type === "MemberExpression" && path6.node.left.object.type === "Identifier" && path6.node.left.object.name === "exports" && path6.node.left.property.type === "Identifier" && path6.node.left.property.name === "default") {
|
|
151
159
|
found = true;
|
|
152
160
|
}
|
|
153
161
|
},
|
|
154
|
-
ExportNamedDeclaration(
|
|
155
|
-
const specifiers =
|
|
162
|
+
ExportNamedDeclaration(path6) {
|
|
163
|
+
const specifiers = path6.node.specifiers;
|
|
156
164
|
if (specifiers?.some(
|
|
157
165
|
(s) => s.type === "ExportSpecifier" && s.exported.type === "Identifier" && s.exported.name === "default"
|
|
158
166
|
)) {
|
|
@@ -164,252 +172,16 @@ function hasDefaultExport(ast) {
|
|
|
164
172
|
}
|
|
165
173
|
|
|
166
174
|
// src/routes.ts
|
|
167
|
-
var
|
|
168
|
-
var
|
|
169
|
-
function getRoute(file, routesDir) {
|
|
170
|
-
const importPath = normalizePath(file);
|
|
171
|
-
const normalizedRoutesDir = normalizePath(routesDir);
|
|
172
|
-
return importPath.replace(normalizedRoutesDir, "").replace(/\[\[\*\]\]/g, "*?").replace(/\[\*\]/g, "*").replace(/\(([^[\])]+)\)/g, "$1?").replace(/\[\[([^\]]+)\]\]/g, ":$1?").replace(/\[([^\]]+)\]/g, ":$1").replace(
|
|
173
|
-
new RegExp(
|
|
174
|
-
`/page\\.(${VALID_FILE_EXTENSIONS.map((ext) => ext.slice(1)).join("|")})$`
|
|
175
|
-
),
|
|
176
|
-
""
|
|
177
|
-
) || "/";
|
|
178
|
-
}
|
|
179
|
-
function crawlRoutes(dir, pattern = "page") {
|
|
180
|
-
const files = [];
|
|
181
|
-
if (!import_fs2.default.existsSync(dir)) {
|
|
182
|
-
return files;
|
|
183
|
-
}
|
|
184
|
-
const entries = import_fs2.default.readdirSync(dir, { withFileTypes: true });
|
|
185
|
-
for (const entry of entries) {
|
|
186
|
-
const fullPath = import_path2.default.join(dir, entry.name);
|
|
187
|
-
if (entry.isDirectory()) {
|
|
188
|
-
files.push(...crawlRoutes(fullPath, pattern));
|
|
189
|
-
} else if (entry.isFile()) {
|
|
190
|
-
const ext = import_path2.default.extname(entry.name);
|
|
191
|
-
const baseName = import_path2.default.basename(entry.name, ext);
|
|
192
|
-
if (baseName === pattern && VALID_FILE_EXTENSIONS.includes(ext)) {
|
|
193
|
-
files.push(fullPath);
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
return files;
|
|
198
|
-
}
|
|
199
|
-
function hasConfigPublic(ast) {
|
|
200
|
-
let found = false;
|
|
201
|
-
traverse(ast, {
|
|
202
|
-
ExportNamedDeclaration(path10) {
|
|
203
|
-
const declaration = path10.node.declaration;
|
|
204
|
-
if (!(0, import_types.isVariableDeclaration)(declaration)) return;
|
|
205
|
-
for (const decl of declaration.declarations) {
|
|
206
|
-
if ((0, import_types.isVariableDeclarator)(decl) && (0, import_types.isIdentifier)(decl.id, { name: "config" }) && decl.init?.type === "ObjectExpression") {
|
|
207
|
-
const publicProp = decl.init.properties.find(
|
|
208
|
-
(prop) => (0, import_types.isObjectProperty)(prop) && (0, import_types.isIdentifier)(prop.key, { name: "public" }) && (0, import_types.isBooleanLiteral)(prop.value, { value: true })
|
|
209
|
-
);
|
|
210
|
-
if (publicProp) {
|
|
211
|
-
found = true;
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
});
|
|
217
|
-
return found;
|
|
218
|
-
}
|
|
219
|
-
function getNamedExports(ast) {
|
|
220
|
-
let hasHandle = false;
|
|
221
|
-
let hasLoader = false;
|
|
222
|
-
traverse(ast, {
|
|
223
|
-
ExportNamedDeclaration(path10) {
|
|
224
|
-
const declaration = path10.node.declaration;
|
|
225
|
-
if (declaration?.type === "VariableDeclaration") {
|
|
226
|
-
declaration.declarations.forEach((decl) => {
|
|
227
|
-
if (decl.id.type === "Identifier" && decl.id.name === "handle") {
|
|
228
|
-
hasHandle = true;
|
|
229
|
-
}
|
|
230
|
-
if (decl.id.type === "Identifier" && decl.id.name === "loader") {
|
|
231
|
-
hasLoader = true;
|
|
232
|
-
}
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
|
-
if (declaration?.type === "FunctionDeclaration" && declaration.id?.name === "loader") {
|
|
236
|
-
hasLoader = true;
|
|
237
|
-
}
|
|
238
|
-
if (declaration?.type === "FunctionDeclaration" && declaration.id?.name === "handle") {
|
|
239
|
-
hasHandle = true;
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
});
|
|
243
|
-
return { hasHandle, hasLoader };
|
|
244
|
-
}
|
|
245
|
-
function generateRouteComponentName(index) {
|
|
246
|
-
return `RouteComponent${index}`;
|
|
247
|
-
}
|
|
248
|
-
function generateHandleName(index) {
|
|
249
|
-
return `RouteHandle${index}`;
|
|
250
|
-
}
|
|
251
|
-
function generateLoaderName(index) {
|
|
252
|
-
return `RouteLoader${index}`;
|
|
253
|
-
}
|
|
254
|
-
function generateImports(file, index, hasHandle, hasLoader) {
|
|
255
|
-
const imports = [];
|
|
256
|
-
const componentName = generateRouteComponentName(index);
|
|
257
|
-
const importPath = normalizePath(file);
|
|
258
|
-
if (!hasHandle && !hasLoader) {
|
|
259
|
-
imports.push(`import ${componentName} from "${importPath}"`);
|
|
260
|
-
} else {
|
|
261
|
-
const namedImports = [
|
|
262
|
-
hasHandle && `handle as ${generateHandleName(index)}`,
|
|
263
|
-
hasLoader && `loader as ${generateLoaderName(index)}`
|
|
264
|
-
].filter(Boolean).join(", ");
|
|
265
|
-
imports.push(`import ${componentName}, { ${namedImports} } from "${importPath}"`);
|
|
266
|
-
}
|
|
267
|
-
return imports;
|
|
268
|
-
}
|
|
269
|
-
function generateRouteObject(routePath, index, hasHandle, hasLoader, isPublic) {
|
|
270
|
-
return {
|
|
271
|
-
Component: generateRouteComponentName(index),
|
|
272
|
-
path: routePath,
|
|
273
|
-
handle: hasHandle ? generateHandleName(index) : void 0,
|
|
274
|
-
loader: hasLoader ? generateLoaderName(index) : void 0,
|
|
275
|
-
isPublic
|
|
276
|
-
};
|
|
277
|
-
}
|
|
278
|
-
function formatRoute(route, indent = " ") {
|
|
279
|
-
let result = `${indent}{
|
|
280
|
-
`;
|
|
281
|
-
result += `${indent} Component: ${route.Component},
|
|
282
|
-
`;
|
|
283
|
-
result += `${indent} path: "${route.path}"`;
|
|
284
|
-
if (route.handle) {
|
|
285
|
-
result += `,
|
|
286
|
-
${indent} handle: ${route.handle}`;
|
|
287
|
-
}
|
|
288
|
-
if (route.loader) {
|
|
289
|
-
result += `,
|
|
290
|
-
${indent} loader: ${route.loader}`;
|
|
291
|
-
}
|
|
292
|
-
if (route.isPublic) {
|
|
293
|
-
result += `,
|
|
294
|
-
${indent} isPublic: true`;
|
|
295
|
-
}
|
|
296
|
-
if (route.children?.length) {
|
|
297
|
-
result += `,
|
|
298
|
-
${indent} children: [
|
|
299
|
-
`;
|
|
300
|
-
result += route.children.map((child) => formatRoute(child, indent + " ")).join(",\n");
|
|
301
|
-
result += `
|
|
302
|
-
${indent} ]`;
|
|
303
|
-
}
|
|
304
|
-
result += `
|
|
305
|
-
${indent}}`;
|
|
306
|
-
return result;
|
|
307
|
-
}
|
|
308
|
-
function parseFile(file, routesDir, index) {
|
|
309
|
-
try {
|
|
310
|
-
const code = import_fs2.default.readFileSync(file, "utf-8");
|
|
311
|
-
const ast = (0, import_parser.parse)(code, getParserOptions(file));
|
|
312
|
-
if (!hasDefaultExport(ast)) {
|
|
313
|
-
return null;
|
|
314
|
-
}
|
|
315
|
-
const { hasHandle, hasLoader } = getNamedExports(ast);
|
|
316
|
-
const isPublic = hasConfigPublic(ast);
|
|
317
|
-
const routePath = getRoute(file, routesDir);
|
|
318
|
-
const imports = generateImports(file, index, hasHandle, hasLoader);
|
|
319
|
-
const route = generateRouteObject(routePath, index, hasHandle, hasLoader, isPublic);
|
|
320
|
-
return {
|
|
321
|
-
imports,
|
|
322
|
-
route
|
|
323
|
-
};
|
|
324
|
-
} catch {
|
|
325
|
-
return null;
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
function buildRouteTree(results) {
|
|
329
|
-
const routeMap = /* @__PURE__ */ new Map();
|
|
330
|
-
const sortedResults = [...results].sort(
|
|
331
|
-
(a, b) => a.route.path.split("/").length - b.route.path.split("/").length
|
|
332
|
-
);
|
|
333
|
-
for (const result of sortedResults) {
|
|
334
|
-
const routePath = result.route.path;
|
|
335
|
-
const isParallel = routePath.includes("/@");
|
|
336
|
-
if (isParallel) {
|
|
337
|
-
const parentPath = routePath.split("/@")[0];
|
|
338
|
-
const parent = routeMap.get(parentPath);
|
|
339
|
-
if (parent) {
|
|
340
|
-
parent.route.children = parent.route.children ?? [];
|
|
341
|
-
parent.route.children.push({
|
|
342
|
-
...result.route,
|
|
343
|
-
path: result.route.path.replace("/@", "/")
|
|
344
|
-
});
|
|
345
|
-
parent.imports.push(...result.imports);
|
|
346
|
-
} else {
|
|
347
|
-
routeMap.set(routePath, result);
|
|
348
|
-
}
|
|
349
|
-
} else {
|
|
350
|
-
routeMap.set(routePath, result);
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
return Array.from(routeMap.values());
|
|
354
|
-
}
|
|
355
|
-
function generateRoutes({ srcDir, pluginExtensions }) {
|
|
356
|
-
const routesDir = import_path2.default.join(srcDir, "routes");
|
|
357
|
-
let index = 0;
|
|
358
|
-
const results = [];
|
|
359
|
-
for (const file of crawlRoutes(routesDir)) {
|
|
360
|
-
const result = parseFile(file, routesDir, index);
|
|
361
|
-
if (result) {
|
|
362
|
-
results.push(result);
|
|
363
|
-
index++;
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
const pluginDeclarations = pluginExtensions.map(
|
|
367
|
-
(ext, i) => `import __plugin${i} from "${normalizePath(ext)}"`
|
|
368
|
-
);
|
|
369
|
-
const pluginSpreads = pluginExtensions.map(
|
|
370
|
-
(_, i) => ` ...(__plugin${i}.routeModule?.routes ?? [])`
|
|
371
|
-
);
|
|
372
|
-
const routeTree = buildRouteTree(results);
|
|
373
|
-
const appImports = routeTree.flatMap((r) => r.imports);
|
|
374
|
-
const appRoutes = routeTree.map((r) => formatRoute(r.route));
|
|
375
|
-
const allImports = [...appImports];
|
|
376
|
-
const allRoutes = [...appRoutes, ...pluginSpreads];
|
|
377
|
-
if (allImports.length === 0 && pluginDeclarations.length === 0 && allRoutes.length === 0) {
|
|
378
|
-
return `export const customRoutes = []`;
|
|
379
|
-
}
|
|
380
|
-
return `${allImports.join("\n")}
|
|
381
|
-
|
|
382
|
-
${pluginDeclarations.join("\n")}
|
|
175
|
+
var import_fs5 = __toESM(require("fs"), 1);
|
|
176
|
+
var import_path4 = __toESM(require("path"), 1);
|
|
383
177
|
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
}
|
|
178
|
+
// src/layers.ts
|
|
179
|
+
var import_fs4 = __toESM(require("fs"), 1);
|
|
180
|
+
var import_path3 = __toESM(require("path"), 1);
|
|
388
181
|
|
|
389
182
|
// src/menu-items.ts
|
|
390
|
-
var
|
|
391
|
-
|
|
392
|
-
function crawlRoutes2(dir, pattern = "page") {
|
|
393
|
-
const files = [];
|
|
394
|
-
if (!import_fs3.default.existsSync(dir)) {
|
|
395
|
-
return files;
|
|
396
|
-
}
|
|
397
|
-
const entries = import_fs3.default.readdirSync(dir, { withFileTypes: true });
|
|
398
|
-
for (const entry of entries) {
|
|
399
|
-
const fullPath = import_path3.default.join(dir, entry.name);
|
|
400
|
-
if (entry.isDirectory()) {
|
|
401
|
-
files.push(...crawlRoutes2(fullPath, pattern));
|
|
402
|
-
} else if (entry.isFile()) {
|
|
403
|
-
const ext = import_path3.default.extname(entry.name);
|
|
404
|
-
const baseName = import_path3.default.basename(entry.name, ext);
|
|
405
|
-
if (baseName === pattern && VALID_FILE_EXTENSIONS.includes(ext)) {
|
|
406
|
-
files.push(fullPath);
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
return files;
|
|
411
|
-
}
|
|
412
|
-
function getRoute2(file, routesDir) {
|
|
183
|
+
var import_fs2 = __toESM(require("fs"), 1);
|
|
184
|
+
function getRoute(file, routesDir) {
|
|
413
185
|
const importPath = normalizePath(file);
|
|
414
186
|
const normalizedRoutesDir = normalizePath(routesDir);
|
|
415
187
|
return importPath.replace(normalizedRoutesDir, "").replace(/\[\[\*\]\]/g, "*?").replace(/\[\*\]/g, "*").replace(/\(([^[\])]+)\)/g, "$1?").replace(/\[\[([^\]]+)\]\]/g, ":$1?").replace(/\[([^\]]+)\]/g, ":$1").replace(
|
|
@@ -419,9 +191,9 @@ function getRoute2(file, routesDir) {
|
|
|
419
191
|
""
|
|
420
192
|
) || "/";
|
|
421
193
|
}
|
|
422
|
-
function getConfigObjectProperties(
|
|
423
|
-
if ((0, import_types.isVariableDeclarator)(
|
|
424
|
-
const decl = (0, import_types.isIdentifier)(
|
|
194
|
+
function getConfigObjectProperties(path6) {
|
|
195
|
+
if ((0, import_types.isVariableDeclarator)(path6.node)) {
|
|
196
|
+
const decl = (0, import_types.isIdentifier)(path6.node.id, { name: "config" }) ? path6.node : null;
|
|
425
197
|
if (!decl) return null;
|
|
426
198
|
if ((0, import_types.isCallExpression)(decl.init) && decl.init.arguments.length > 0 && (0, import_types.isObjectExpression)(decl.init.arguments[0])) {
|
|
427
199
|
return decl.init.arguments[0].properties;
|
|
@@ -431,7 +203,7 @@ function getConfigObjectProperties(path10) {
|
|
|
431
203
|
}
|
|
432
204
|
return null;
|
|
433
205
|
}
|
|
434
|
-
const declaration =
|
|
206
|
+
const declaration = path6.node.declaration;
|
|
435
207
|
if ((0, import_types.isVariableDeclaration)(declaration)) {
|
|
436
208
|
const configDecl = declaration.declarations.find(
|
|
437
209
|
(d) => (0, import_types.isVariableDeclarator)(d) && (0, import_types.isIdentifier)(d.id, { name: "config" })
|
|
@@ -507,21 +279,21 @@ function processConfigProperties(properties) {
|
|
|
507
279
|
}
|
|
508
280
|
function getRouteConfig(file) {
|
|
509
281
|
try {
|
|
510
|
-
const code =
|
|
282
|
+
const code = import_fs2.default.readFileSync(file, "utf-8");
|
|
511
283
|
const ast = (0, import_parser.parse)(code, getParserOptions(file));
|
|
512
284
|
let config = null;
|
|
513
285
|
let configFound = false;
|
|
514
286
|
traverse(ast, {
|
|
515
|
-
VariableDeclarator(
|
|
287
|
+
VariableDeclarator(path6) {
|
|
516
288
|
if (configFound) return;
|
|
517
|
-
const properties = getConfigObjectProperties(
|
|
289
|
+
const properties = getConfigObjectProperties(path6);
|
|
518
290
|
if (!properties) return;
|
|
519
291
|
config = processConfigProperties(properties);
|
|
520
292
|
if (config) configFound = true;
|
|
521
293
|
},
|
|
522
|
-
ExportNamedDeclaration(
|
|
294
|
+
ExportNamedDeclaration(path6) {
|
|
523
295
|
if (configFound) return;
|
|
524
|
-
const properties = getConfigObjectProperties(
|
|
296
|
+
const properties = getConfigObjectProperties(path6);
|
|
525
297
|
if (!properties) return;
|
|
526
298
|
config = processConfigProperties(properties);
|
|
527
299
|
if (config) configFound = true;
|
|
@@ -544,7 +316,7 @@ function generateMenuItem(config, file, routesDir, index) {
|
|
|
544
316
|
return {
|
|
545
317
|
label: `${configName}.label`,
|
|
546
318
|
icon: config.icon ? `${configName}.icon` : void 0,
|
|
547
|
-
path:
|
|
319
|
+
path: getRoute(file, routesDir),
|
|
548
320
|
rank: config.rank,
|
|
549
321
|
nested: config.nested,
|
|
550
322
|
group: config.group,
|
|
@@ -574,75 +346,485 @@ function parseMenuItemFile(file, routesDir, index) {
|
|
|
574
346
|
if (!config) {
|
|
575
347
|
return null;
|
|
576
348
|
}
|
|
577
|
-
return {
|
|
578
|
-
import: generateImport(file, index),
|
|
579
|
-
menuItem: generateMenuItem(config, file, routesDir, index)
|
|
580
|
-
};
|
|
349
|
+
return {
|
|
350
|
+
import: generateImport(file, index),
|
|
351
|
+
menuItem: generateMenuItem(config, file, routesDir, index)
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
function generateMenuItems(config) {
|
|
355
|
+
const { header, names } = emitLayers(config);
|
|
356
|
+
return `${header}
|
|
357
|
+
|
|
358
|
+
const byPath = new Map()
|
|
359
|
+
for (const item of [
|
|
360
|
+
${spreadLayers(names, "menuItemModule", "menuItems")}
|
|
361
|
+
]) {
|
|
362
|
+
byPath.set(item.path, item)
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
export default { menuItems: [...byPath.values()] }`;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// src/widgets.ts
|
|
369
|
+
var import_fs3 = __toESM(require("fs"), 1);
|
|
370
|
+
var import_path2 = __toESM(require("path"), 1);
|
|
371
|
+
function readNumber(value) {
|
|
372
|
+
if ((0, import_types.isNumericLiteral)(value)) return value.value;
|
|
373
|
+
if ((0, import_types.isUnaryExpression)(value) && value.operator === "-" && (0, import_types.isNumericLiteral)(value.argument)) {
|
|
374
|
+
return -value.argument.value;
|
|
375
|
+
}
|
|
376
|
+
return void 0;
|
|
377
|
+
}
|
|
378
|
+
function extractStrings(value, zones) {
|
|
379
|
+
if ((0, import_types.isStringLiteral)(value)) {
|
|
380
|
+
zones.push(value.value);
|
|
381
|
+
} else if ((0, import_types.isArrayExpression)(value)) {
|
|
382
|
+
for (const el of value.elements) {
|
|
383
|
+
if ((0, import_types.isStringLiteral)(el)) zones.push(el.value);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
function readWidgetConfig(properties) {
|
|
388
|
+
const zones = [];
|
|
389
|
+
const permissions = [];
|
|
390
|
+
let id;
|
|
391
|
+
let label;
|
|
392
|
+
let section;
|
|
393
|
+
let order;
|
|
394
|
+
let replace;
|
|
395
|
+
for (const prop of properties) {
|
|
396
|
+
if (!(0, import_types.isObjectProperty)(prop)) continue;
|
|
397
|
+
if ((0, import_types.isIdentifier)(prop.key, { name: "zone" })) {
|
|
398
|
+
extractStrings(prop.value, zones);
|
|
399
|
+
}
|
|
400
|
+
if ((0, import_types.isIdentifier)(prop.key, { name: "permission" })) {
|
|
401
|
+
extractStrings(prop.value, permissions);
|
|
402
|
+
}
|
|
403
|
+
if ((0, import_types.isIdentifier)(prop.key, { name: "id" }) && (0, import_types.isStringLiteral)(prop.value)) {
|
|
404
|
+
id = prop.value.value;
|
|
405
|
+
}
|
|
406
|
+
if ((0, import_types.isIdentifier)(prop.key, { name: "label" }) && (0, import_types.isStringLiteral)(prop.value)) {
|
|
407
|
+
label = prop.value.value;
|
|
408
|
+
}
|
|
409
|
+
if ((0, import_types.isIdentifier)(prop.key, { name: "section" }) && (0, import_types.isStringLiteral)(prop.value)) {
|
|
410
|
+
section = prop.value.value;
|
|
411
|
+
}
|
|
412
|
+
if ((0, import_types.isIdentifier)(prop.key, { name: "order" })) {
|
|
413
|
+
order = readNumber(prop.value);
|
|
414
|
+
}
|
|
415
|
+
if ((0, import_types.isIdentifier)(prop.key, { name: "replace" }) && (0, import_types.isStringLiteral)(prop.value)) {
|
|
416
|
+
replace = prop.value.value;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
if (zones.length === 0) return null;
|
|
420
|
+
return { zones, id, label, permissions, section, order, replace };
|
|
421
|
+
}
|
|
422
|
+
function getConfigProperties(node) {
|
|
423
|
+
if ((0, import_types.isCallExpression)(node) && node.arguments.length > 0 && (0, import_types.isObjectExpression)(node.arguments[0])) {
|
|
424
|
+
return node.arguments[0].properties;
|
|
425
|
+
}
|
|
426
|
+
if ((0, import_types.isObjectExpression)(node)) {
|
|
427
|
+
return node.properties;
|
|
428
|
+
}
|
|
429
|
+
return null;
|
|
430
|
+
}
|
|
431
|
+
function getWidgetConfig(file) {
|
|
432
|
+
try {
|
|
433
|
+
const code = import_fs3.default.readFileSync(file, "utf-8");
|
|
434
|
+
const ast = (0, import_parser.parse)(code, getParserOptions(file));
|
|
435
|
+
if (!hasDefaultExport(ast)) return null;
|
|
436
|
+
let info = null;
|
|
437
|
+
const visit = (declaration) => {
|
|
438
|
+
if (info) return;
|
|
439
|
+
if (!(0, import_types.isVariableDeclaration)(declaration)) return;
|
|
440
|
+
for (const decl of declaration.declarations) {
|
|
441
|
+
if ((0, import_types.isVariableDeclarator)(decl) && (0, import_types.isIdentifier)(decl.id, { name: "config" })) {
|
|
442
|
+
const props = getConfigProperties(decl.init);
|
|
443
|
+
if (props) info = readWidgetConfig(props);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
};
|
|
447
|
+
traverse(ast, {
|
|
448
|
+
ExportNamedDeclaration(p) {
|
|
449
|
+
visit(p.node.declaration);
|
|
450
|
+
},
|
|
451
|
+
VariableDeclaration(p) {
|
|
452
|
+
visit(p.node);
|
|
453
|
+
}
|
|
454
|
+
});
|
|
455
|
+
return info;
|
|
456
|
+
} catch {
|
|
457
|
+
return null;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
function hashPath(relative) {
|
|
461
|
+
let hash = 0;
|
|
462
|
+
for (let i = 0; i < relative.length; i++) {
|
|
463
|
+
hash = (hash << 5) - hash + relative.charCodeAt(i);
|
|
464
|
+
hash |= 0;
|
|
465
|
+
}
|
|
466
|
+
return Math.abs(hash).toString(36).slice(0, 6);
|
|
467
|
+
}
|
|
468
|
+
function widgetId(info, file, widgetsDir) {
|
|
469
|
+
if (info.id) return info.id;
|
|
470
|
+
const relative = normalizePath(import_path2.default.relative(widgetsDir, file));
|
|
471
|
+
return `Widget-${hashPath(relative)}`;
|
|
472
|
+
}
|
|
473
|
+
function parseWidgetFile(file, widgetsDir, index) {
|
|
474
|
+
const info = getWidgetConfig(file);
|
|
475
|
+
if (!info) return null;
|
|
476
|
+
const name = `Widget${index}`;
|
|
477
|
+
const importPath = normalizePath(file);
|
|
478
|
+
const zonesLiteral = JSON.stringify(info.zones);
|
|
479
|
+
const id = widgetId(info, file, widgetsDir);
|
|
480
|
+
return {
|
|
481
|
+
import: `import ${name} from "${importPath}"`,
|
|
482
|
+
entry: ` { Component: ${name}, zone: ${zonesLiteral}, widgetId: ${JSON.stringify(
|
|
483
|
+
id
|
|
484
|
+
)}${info.label ? `, label: ${JSON.stringify(info.label)}` : ""}${info.permissions.length ? `, permission: ${JSON.stringify(info.permissions)}` : ""}${info.section ? `, section: ${JSON.stringify(info.section)}` : ""}${info.order !== void 0 ? `, order: ${info.order}` : ""}${info.replace ? `, replace: ${JSON.stringify(info.replace)}` : ""} }`
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
function collectWidgets(srcDir, startIndex = 0) {
|
|
488
|
+
const widgetsDir = import_path2.default.join(srcDir, "widgets");
|
|
489
|
+
let index = startIndex;
|
|
490
|
+
const results = [];
|
|
491
|
+
for (const file of crawlModuleFiles(widgetsDir)) {
|
|
492
|
+
const result = parseWidgetFile(file, widgetsDir, index);
|
|
493
|
+
if (result) {
|
|
494
|
+
results.push(result);
|
|
495
|
+
index++;
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
return {
|
|
499
|
+
imports: results.map((r) => r.import),
|
|
500
|
+
entries: results.map((r) => r.entry)
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
function generateWidgets(config) {
|
|
504
|
+
const { header, names } = emitLayers(config);
|
|
505
|
+
return `${header}
|
|
506
|
+
|
|
507
|
+
const byId = new Map()
|
|
508
|
+
for (const widget of [
|
|
509
|
+
${spreadLayers(names, "widgetModule", "widgets")}
|
|
510
|
+
]) {
|
|
511
|
+
byId.set(widget.widgetId, widget)
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
export default { widgets: [...byId.values()] }`;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
// src/layers.ts
|
|
518
|
+
function layerSources({
|
|
519
|
+
pluginExtensions,
|
|
520
|
+
projectDir,
|
|
521
|
+
srcDir
|
|
522
|
+
}) {
|
|
523
|
+
return [
|
|
524
|
+
...pluginExtensions.map((entry) => ({ entry })),
|
|
525
|
+
...projectDir ? [{ srcDir: projectDir }] : [],
|
|
526
|
+
{ srcDir }
|
|
527
|
+
];
|
|
528
|
+
}
|
|
529
|
+
function findFile(dir, stem) {
|
|
530
|
+
for (const ext of VALID_FILE_EXTENSIONS) {
|
|
531
|
+
const file = import_path3.default.join(dir, `${stem}${ext}`);
|
|
532
|
+
if (import_fs4.default.existsSync(file)) return file;
|
|
533
|
+
}
|
|
534
|
+
return null;
|
|
535
|
+
}
|
|
536
|
+
function collectLayer(srcDir, layer, startIndex = 0) {
|
|
537
|
+
const name = `__layer${layer}`;
|
|
538
|
+
const routesDir = import_path3.default.join(srcDir, "routes");
|
|
539
|
+
let index = startIndex;
|
|
540
|
+
const routeResults = [];
|
|
541
|
+
const menuItemResults = [];
|
|
542
|
+
for (const file of crawlRoutes(routesDir)) {
|
|
543
|
+
const route = parseFile(file, routesDir, index);
|
|
544
|
+
if (route) routeResults.push(route);
|
|
545
|
+
const menuItem = parseMenuItemFile(file, routesDir, index);
|
|
546
|
+
if (menuItem) menuItemResults.push(menuItem);
|
|
547
|
+
index++;
|
|
548
|
+
}
|
|
549
|
+
const routeTree = buildRouteTree(routeResults);
|
|
550
|
+
const routeImports = routeTree.flatMap((r) => r.imports);
|
|
551
|
+
const routes = routeTree.map((r) => formatRoute(r.route));
|
|
552
|
+
const menuItemImports = menuItemResults.map((r) => r.import);
|
|
553
|
+
const menuItems = menuItemResults.map((r) => formatMenuItem(r.menuItem));
|
|
554
|
+
const widgets = collectWidgets(srcDir, index);
|
|
555
|
+
index += widgets.entries.length;
|
|
556
|
+
const cfFiles = crawlModuleFiles(import_path3.default.join(srcDir, "custom-fields"));
|
|
557
|
+
const cfImports = cfFiles.map(
|
|
558
|
+
(file, i) => `import __cf${layer}_${i} from "${normalizePath(file)}"`
|
|
559
|
+
);
|
|
560
|
+
const cfRefs = cfFiles.map((_, i) => ` __cf${layer}_${i}`);
|
|
561
|
+
const layoutFiles = crawlModuleFiles(import_path3.default.join(srcDir, "layouts"));
|
|
562
|
+
const layoutImports = layoutFiles.map(
|
|
563
|
+
(file, i) => `import __layout${layer}_${i} from "${normalizePath(file)}"`
|
|
564
|
+
);
|
|
565
|
+
const layoutRefs = layoutFiles.map((_, i) => ` __layout${layer}_${i}`);
|
|
566
|
+
const i18nFile = findFile(import_path3.default.join(srcDir, "i18n"), "index");
|
|
567
|
+
const i18nName = `__i18n${layer}`;
|
|
568
|
+
const navigationFile = findFile(srcDir, NAVIGATION_FILE);
|
|
569
|
+
const navigationName = `__navigation${layer}`;
|
|
570
|
+
const preferencesFile = findFile(srcDir, LAYOUT_PREFERENCES_FILE);
|
|
571
|
+
const preferencesName = `__preferences${layer}`;
|
|
572
|
+
const imports = [
|
|
573
|
+
...routeImports,
|
|
574
|
+
...menuItemImports,
|
|
575
|
+
...widgets.imports,
|
|
576
|
+
...cfImports,
|
|
577
|
+
...layoutImports,
|
|
578
|
+
...i18nFile ? [`import ${i18nName} from "${normalizePath(i18nFile)}"`] : [],
|
|
579
|
+
...navigationFile ? [`import ${navigationName} from "${normalizePath(navigationFile)}"`] : [],
|
|
580
|
+
...preferencesFile ? [`import ${preferencesName} from "${normalizePath(preferencesFile)}"`] : []
|
|
581
|
+
];
|
|
582
|
+
const declaration = `const ${name} = {
|
|
583
|
+
routeModule: { routes: [
|
|
584
|
+
${routes.join(",\n")}
|
|
585
|
+
] },
|
|
586
|
+
menuItemModule: { menuItems: [
|
|
587
|
+
${menuItems.join(",\n")}
|
|
588
|
+
] },
|
|
589
|
+
widgetModule: { widgets: [
|
|
590
|
+
${widgets.entries.join(",\n")}
|
|
591
|
+
] },
|
|
592
|
+
customFieldsModule: { configs: [
|
|
593
|
+
${cfRefs.join(",\n")}
|
|
594
|
+
] },
|
|
595
|
+
layoutModule: { layouts: [
|
|
596
|
+
${layoutRefs.join(",\n")}
|
|
597
|
+
] },
|
|
598
|
+
i18nModule: ${i18nFile ? i18nName : "{}"},
|
|
599
|
+
navigationModule: ${navigationFile ? navigationName : "{}"},
|
|
600
|
+
preferenceModule: ${preferencesFile ? preferencesName : "{}"},
|
|
601
|
+
}`;
|
|
602
|
+
return { imports, declaration, name, nextIndex: index };
|
|
603
|
+
}
|
|
604
|
+
function emitLayers(config) {
|
|
605
|
+
const lines = [];
|
|
606
|
+
const declarations = [];
|
|
607
|
+
const names = [];
|
|
608
|
+
let index = 0;
|
|
609
|
+
layerSources(config).forEach((source, layer) => {
|
|
610
|
+
if ("entry" in source) {
|
|
611
|
+
const name = `__layer${layer}`;
|
|
612
|
+
lines.push(`import ${name} from "${normalizePath(source.entry)}"`);
|
|
613
|
+
names.push(name);
|
|
614
|
+
return;
|
|
615
|
+
}
|
|
616
|
+
const collected = collectLayer(source.srcDir, layer, index);
|
|
617
|
+
index = collected.nextIndex;
|
|
618
|
+
lines.push(...collected.imports);
|
|
619
|
+
declarations.push(collected.declaration);
|
|
620
|
+
names.push(collected.name);
|
|
621
|
+
});
|
|
622
|
+
return { header: [...lines, ...declarations].join("\n"), names };
|
|
623
|
+
}
|
|
624
|
+
function spreadLayers(names, key, list) {
|
|
625
|
+
return names.map((name) => ` ...(${name}.${key}?.${list} ?? [])`).join(",\n");
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
// src/routes.ts
|
|
629
|
+
function getRoute2(file, routesDir) {
|
|
630
|
+
const importPath = normalizePath(file);
|
|
631
|
+
const normalizedRoutesDir = normalizePath(routesDir);
|
|
632
|
+
return importPath.replace(normalizedRoutesDir, "").replace(/\[\[\*\]\]/g, "*?").replace(/\[\*\]/g, "*").replace(/\(([^[\])]+)\)/g, "$1?").replace(/\[\[([^\]]+)\]\]/g, ":$1?").replace(/\[([^\]]+)\]/g, ":$1").replace(
|
|
633
|
+
new RegExp(
|
|
634
|
+
`/page\\.(${VALID_FILE_EXTENSIONS.map((ext) => ext.slice(1)).join("|")})$`
|
|
635
|
+
),
|
|
636
|
+
""
|
|
637
|
+
) || "/";
|
|
638
|
+
}
|
|
639
|
+
function crawlRoutes(dir, pattern = "page") {
|
|
640
|
+
const files = [];
|
|
641
|
+
if (!import_fs5.default.existsSync(dir)) {
|
|
642
|
+
return files;
|
|
643
|
+
}
|
|
644
|
+
const entries = import_fs5.default.readdirSync(dir, { withFileTypes: true });
|
|
645
|
+
for (const entry of entries) {
|
|
646
|
+
const fullPath = import_path4.default.join(dir, entry.name);
|
|
647
|
+
if (entry.isDirectory()) {
|
|
648
|
+
files.push(...crawlRoutes(fullPath, pattern));
|
|
649
|
+
} else if (entry.isFile()) {
|
|
650
|
+
const ext = import_path4.default.extname(entry.name);
|
|
651
|
+
const baseName = import_path4.default.basename(entry.name, ext);
|
|
652
|
+
if (baseName === pattern && VALID_FILE_EXTENSIONS.includes(ext)) {
|
|
653
|
+
files.push(fullPath);
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
return files;
|
|
658
|
+
}
|
|
659
|
+
function hasConfigPublic(ast) {
|
|
660
|
+
let found = false;
|
|
661
|
+
traverse(ast, {
|
|
662
|
+
ExportNamedDeclaration(path6) {
|
|
663
|
+
const declaration = path6.node.declaration;
|
|
664
|
+
if (!(0, import_types.isVariableDeclaration)(declaration)) return;
|
|
665
|
+
for (const decl of declaration.declarations) {
|
|
666
|
+
if ((0, import_types.isVariableDeclarator)(decl) && (0, import_types.isIdentifier)(decl.id, { name: "config" }) && decl.init?.type === "ObjectExpression") {
|
|
667
|
+
const publicProp = decl.init.properties.find(
|
|
668
|
+
(prop) => (0, import_types.isObjectProperty)(prop) && (0, import_types.isIdentifier)(prop.key, { name: "public" }) && (0, import_types.isBooleanLiteral)(prop.value, { value: true })
|
|
669
|
+
);
|
|
670
|
+
if (publicProp) {
|
|
671
|
+
found = true;
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
});
|
|
677
|
+
return found;
|
|
678
|
+
}
|
|
679
|
+
function getNamedExports(ast) {
|
|
680
|
+
let hasHandle = false;
|
|
681
|
+
let hasLoader = false;
|
|
682
|
+
traverse(ast, {
|
|
683
|
+
ExportNamedDeclaration(path6) {
|
|
684
|
+
const declaration = path6.node.declaration;
|
|
685
|
+
if (declaration?.type === "VariableDeclaration") {
|
|
686
|
+
declaration.declarations.forEach((decl) => {
|
|
687
|
+
if (decl.id.type === "Identifier" && decl.id.name === "handle") {
|
|
688
|
+
hasHandle = true;
|
|
689
|
+
}
|
|
690
|
+
if (decl.id.type === "Identifier" && decl.id.name === "loader") {
|
|
691
|
+
hasLoader = true;
|
|
692
|
+
}
|
|
693
|
+
});
|
|
694
|
+
}
|
|
695
|
+
if (declaration?.type === "FunctionDeclaration" && declaration.id?.name === "loader") {
|
|
696
|
+
hasLoader = true;
|
|
697
|
+
}
|
|
698
|
+
if (declaration?.type === "FunctionDeclaration" && declaration.id?.name === "handle") {
|
|
699
|
+
hasHandle = true;
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
});
|
|
703
|
+
return { hasHandle, hasLoader };
|
|
704
|
+
}
|
|
705
|
+
function generateRouteComponentName(index) {
|
|
706
|
+
return `RouteComponent${index}`;
|
|
707
|
+
}
|
|
708
|
+
function generateHandleName(index) {
|
|
709
|
+
return `RouteHandle${index}`;
|
|
710
|
+
}
|
|
711
|
+
function generateLoaderName(index) {
|
|
712
|
+
return `RouteLoader${index}`;
|
|
713
|
+
}
|
|
714
|
+
function generateImports(file, index, hasHandle, hasLoader) {
|
|
715
|
+
const imports = [];
|
|
716
|
+
const componentName = generateRouteComponentName(index);
|
|
717
|
+
const importPath = normalizePath(file);
|
|
718
|
+
if (!hasHandle && !hasLoader) {
|
|
719
|
+
imports.push(`import ${componentName} from "${importPath}"`);
|
|
720
|
+
} else {
|
|
721
|
+
const namedImports = [
|
|
722
|
+
hasHandle && `handle as ${generateHandleName(index)}`,
|
|
723
|
+
hasLoader && `loader as ${generateLoaderName(index)}`
|
|
724
|
+
].filter(Boolean).join(", ");
|
|
725
|
+
imports.push(`import ${componentName}, { ${namedImports} } from "${importPath}"`);
|
|
726
|
+
}
|
|
727
|
+
return imports;
|
|
728
|
+
}
|
|
729
|
+
function generateRouteObject(routePath, index, hasHandle, hasLoader, isPublic) {
|
|
730
|
+
return {
|
|
731
|
+
Component: generateRouteComponentName(index),
|
|
732
|
+
path: routePath,
|
|
733
|
+
handle: hasHandle ? generateHandleName(index) : void 0,
|
|
734
|
+
loader: hasLoader ? generateLoaderName(index) : void 0,
|
|
735
|
+
isPublic
|
|
736
|
+
};
|
|
737
|
+
}
|
|
738
|
+
function formatRoute(route, indent = " ") {
|
|
739
|
+
let result = `${indent}{
|
|
740
|
+
`;
|
|
741
|
+
result += `${indent} Component: ${route.Component},
|
|
742
|
+
`;
|
|
743
|
+
result += `${indent} path: "${route.path}"`;
|
|
744
|
+
if (route.handle) {
|
|
745
|
+
result += `,
|
|
746
|
+
${indent} handle: ${route.handle}`;
|
|
747
|
+
}
|
|
748
|
+
if (route.loader) {
|
|
749
|
+
result += `,
|
|
750
|
+
${indent} loader: ${route.loader}`;
|
|
751
|
+
}
|
|
752
|
+
if (route.isPublic) {
|
|
753
|
+
result += `,
|
|
754
|
+
${indent} isPublic: true`;
|
|
755
|
+
}
|
|
756
|
+
if (route.children?.length) {
|
|
757
|
+
result += `,
|
|
758
|
+
${indent} children: [
|
|
759
|
+
`;
|
|
760
|
+
result += route.children.map((child) => formatRoute(child, indent + " ")).join(",\n");
|
|
761
|
+
result += `
|
|
762
|
+
${indent} ]`;
|
|
763
|
+
}
|
|
764
|
+
result += `
|
|
765
|
+
${indent}}`;
|
|
766
|
+
return result;
|
|
581
767
|
}
|
|
582
|
-
function
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
if (result) {
|
|
589
|
-
results.push(result);
|
|
590
|
-
index++;
|
|
768
|
+
function parseFile(file, routesDir, index) {
|
|
769
|
+
try {
|
|
770
|
+
const code = import_fs5.default.readFileSync(file, "utf-8");
|
|
771
|
+
const ast = (0, import_parser.parse)(code, getParserOptions(file));
|
|
772
|
+
if (!hasDefaultExport(ast)) {
|
|
773
|
+
return null;
|
|
591
774
|
}
|
|
775
|
+
const { hasHandle, hasLoader } = getNamedExports(ast);
|
|
776
|
+
const isPublic = hasConfigPublic(ast);
|
|
777
|
+
const routePath = getRoute2(file, routesDir);
|
|
778
|
+
const imports = generateImports(file, index, hasHandle, hasLoader);
|
|
779
|
+
const route = generateRouteObject(routePath, index, hasHandle, hasLoader, isPublic);
|
|
780
|
+
return {
|
|
781
|
+
imports,
|
|
782
|
+
route
|
|
783
|
+
};
|
|
784
|
+
} catch {
|
|
785
|
+
return null;
|
|
592
786
|
}
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
);
|
|
596
|
-
const
|
|
597
|
-
(
|
|
787
|
+
}
|
|
788
|
+
function buildRouteTree(results) {
|
|
789
|
+
const routeMap = /* @__PURE__ */ new Map();
|
|
790
|
+
const sortedResults = [...results].sort(
|
|
791
|
+
(a, b) => a.route.path.split("/").length - b.route.path.split("/").length
|
|
598
792
|
);
|
|
599
|
-
const
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
793
|
+
for (const result of sortedResults) {
|
|
794
|
+
const routePath = result.route.path;
|
|
795
|
+
const isParallel = routePath.includes("/@");
|
|
796
|
+
if (isParallel) {
|
|
797
|
+
const parentPath = routePath.split("/@")[0];
|
|
798
|
+
const parent = routeMap.get(parentPath);
|
|
799
|
+
if (parent) {
|
|
800
|
+
parent.route.children = parent.route.children ?? [];
|
|
801
|
+
parent.route.children.push({
|
|
802
|
+
...result.route,
|
|
803
|
+
path: result.route.path.replace("/@", "/")
|
|
804
|
+
});
|
|
805
|
+
parent.imports.push(...result.imports);
|
|
806
|
+
} else {
|
|
807
|
+
routeMap.set(routePath, result);
|
|
808
|
+
}
|
|
809
|
+
} else {
|
|
810
|
+
routeMap.set(routePath, result);
|
|
811
|
+
}
|
|
605
812
|
}
|
|
606
|
-
return
|
|
607
|
-
|
|
608
|
-
|
|
813
|
+
return Array.from(routeMap.values());
|
|
814
|
+
}
|
|
815
|
+
function generateRoutes(config) {
|
|
816
|
+
const { header, names } = emitLayers(config);
|
|
817
|
+
return `${header}
|
|
609
818
|
|
|
610
|
-
export
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
]
|
|
614
|
-
}`;
|
|
819
|
+
export const customRoutes = [
|
|
820
|
+
${spreadLayers(names, "routeModule", "routes")}
|
|
821
|
+
]`;
|
|
615
822
|
}
|
|
616
823
|
|
|
617
824
|
// src/i18n.ts
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
const i18nDir = import_path4.default.join(srcDir, "i18n");
|
|
622
|
-
if (!import_fs4.default.existsSync(i18nDir)) {
|
|
623
|
-
return null;
|
|
624
|
-
}
|
|
625
|
-
for (const ext of VALID_FILE_EXTENSIONS) {
|
|
626
|
-
const filePath = import_path4.default.join(i18nDir, `index${ext}`);
|
|
627
|
-
if (import_fs4.default.existsSync(filePath)) {
|
|
628
|
-
return filePath;
|
|
629
|
-
}
|
|
630
|
-
}
|
|
631
|
-
return null;
|
|
632
|
-
}
|
|
633
|
-
function generateI18n({ srcDir, pluginExtensions }) {
|
|
634
|
-
const indexFile = findI18nIndex(srcDir);
|
|
635
|
-
const imports = [
|
|
636
|
-
...indexFile ? [`import appI18n from "${normalizePath(indexFile)}"`] : [],
|
|
637
|
-
...pluginExtensions.map(
|
|
638
|
-
(ext, i) => `import __plugin${i} from "${normalizePath(ext)}"`
|
|
639
|
-
)
|
|
640
|
-
];
|
|
641
|
-
const sources = [
|
|
642
|
-
...pluginExtensions.map((_, i) => `(__plugin${i}.i18nModule ?? {})`),
|
|
643
|
-
...indexFile ? ["appI18n"] : []
|
|
644
|
-
];
|
|
645
|
-
return `${imports.join("\n")}
|
|
825
|
+
function generateI18n(config) {
|
|
826
|
+
const { header, names } = emitLayers(config);
|
|
827
|
+
return `${header}
|
|
646
828
|
|
|
647
829
|
function deepMerge(target, source) {
|
|
648
830
|
const result = { ...target }
|
|
@@ -668,205 +850,62 @@ function mergeResources(target, source) {
|
|
|
668
850
|
return result
|
|
669
851
|
}
|
|
670
852
|
|
|
671
|
-
export default [${
|
|
853
|
+
export default [${names.map((name) => `(${name}.i18nModule ?? {})`).join(", ")}].reduce(mergeResources, {})
|
|
672
854
|
`;
|
|
673
855
|
}
|
|
674
856
|
|
|
675
|
-
// src/
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
function readWidgetConfig(properties) {
|
|
688
|
-
const zones = [];
|
|
689
|
-
const permissions = [];
|
|
690
|
-
let id;
|
|
691
|
-
let label;
|
|
692
|
-
for (const prop of properties) {
|
|
693
|
-
if (!(0, import_types.isObjectProperty)(prop)) continue;
|
|
694
|
-
if ((0, import_types.isIdentifier)(prop.key, { name: "zone" })) {
|
|
695
|
-
extractStrings(prop.value, zones);
|
|
696
|
-
}
|
|
697
|
-
if ((0, import_types.isIdentifier)(prop.key, { name: "permission" })) {
|
|
698
|
-
extractStrings(prop.value, permissions);
|
|
699
|
-
}
|
|
700
|
-
if ((0, import_types.isIdentifier)(prop.key, { name: "id" }) && (0, import_types.isStringLiteral)(prop.value)) {
|
|
701
|
-
id = prop.value.value;
|
|
857
|
+
// src/navigation.ts
|
|
858
|
+
function generateNavigation(config) {
|
|
859
|
+
const { header, names } = emitLayers(config);
|
|
860
|
+
return `${header}
|
|
861
|
+
|
|
862
|
+
const groups = new Map()
|
|
863
|
+
const items = new Map()
|
|
864
|
+
for (const navigation of [${names.map((name) => `${name}.navigationModule ?? {}`).join(", ")}]) {
|
|
865
|
+
for (const group of navigation.groups ?? []) {
|
|
866
|
+
if (group?.id) groups.set(group.id, { ...(groups.get(group.id) ?? {}), ...group })
|
|
702
867
|
}
|
|
703
|
-
|
|
704
|
-
|
|
868
|
+
for (const item of navigation.items ?? []) {
|
|
869
|
+
if (item?.id) items.set(item.id, { ...(items.get(item.id) ?? {}), ...item })
|
|
705
870
|
}
|
|
706
|
-
}
|
|
707
|
-
if (zones.length === 0) return null;
|
|
708
|
-
return { zones, id, label, permissions };
|
|
709
|
-
}
|
|
710
|
-
function getConfigProperties(node) {
|
|
711
|
-
if ((0, import_types.isCallExpression)(node) && node.arguments.length > 0 && (0, import_types.isObjectExpression)(node.arguments[0])) {
|
|
712
|
-
return node.arguments[0].properties;
|
|
713
|
-
}
|
|
714
|
-
if ((0, import_types.isObjectExpression)(node)) {
|
|
715
|
-
return node.properties;
|
|
716
|
-
}
|
|
717
|
-
return null;
|
|
718
|
-
}
|
|
719
|
-
function getWidgetConfig(file) {
|
|
720
|
-
try {
|
|
721
|
-
const code = import_fs5.default.readFileSync(file, "utf-8");
|
|
722
|
-
const ast = (0, import_parser.parse)(code, getParserOptions(file));
|
|
723
|
-
if (!hasDefaultExport(ast)) return null;
|
|
724
|
-
let info = null;
|
|
725
|
-
const visit = (declaration) => {
|
|
726
|
-
if (info) return;
|
|
727
|
-
if (!(0, import_types.isVariableDeclaration)(declaration)) return;
|
|
728
|
-
for (const decl of declaration.declarations) {
|
|
729
|
-
if ((0, import_types.isVariableDeclarator)(decl) && (0, import_types.isIdentifier)(decl.id, { name: "config" })) {
|
|
730
|
-
const props = getConfigProperties(decl.init);
|
|
731
|
-
if (props) info = readWidgetConfig(props);
|
|
732
|
-
}
|
|
733
|
-
}
|
|
734
|
-
};
|
|
735
|
-
traverse(ast, {
|
|
736
|
-
ExportNamedDeclaration(p) {
|
|
737
|
-
visit(p.node.declaration);
|
|
738
|
-
},
|
|
739
|
-
VariableDeclaration(p) {
|
|
740
|
-
visit(p.node);
|
|
741
|
-
}
|
|
742
|
-
});
|
|
743
|
-
return info;
|
|
744
|
-
} catch {
|
|
745
|
-
return null;
|
|
746
|
-
}
|
|
747
|
-
}
|
|
748
|
-
function hashPath(relative) {
|
|
749
|
-
let hash = 0;
|
|
750
|
-
for (let i = 0; i < relative.length; i++) {
|
|
751
|
-
hash = (hash << 5) - hash + relative.charCodeAt(i);
|
|
752
|
-
hash |= 0;
|
|
753
|
-
}
|
|
754
|
-
return Math.abs(hash).toString(36).slice(0, 6);
|
|
755
|
-
}
|
|
756
|
-
function widgetId(info, file, widgetsDir) {
|
|
757
|
-
if (info.id) return info.id;
|
|
758
|
-
const relative = normalizePath(import_path5.default.relative(widgetsDir, file));
|
|
759
|
-
return `Widget-${hashPath(relative)}`;
|
|
760
|
-
}
|
|
761
|
-
function parseWidgetFile(file, widgetsDir, index) {
|
|
762
|
-
const info = getWidgetConfig(file);
|
|
763
|
-
if (!info) return null;
|
|
764
|
-
const name = `Widget${index}`;
|
|
765
|
-
const importPath = normalizePath(file);
|
|
766
|
-
const zonesLiteral = JSON.stringify(info.zones);
|
|
767
|
-
const id = widgetId(info, file, widgetsDir);
|
|
768
|
-
return {
|
|
769
|
-
import: `import ${name} from "${importPath}"`,
|
|
770
|
-
entry: ` { Component: ${name}, zone: ${zonesLiteral}, widgetId: ${JSON.stringify(
|
|
771
|
-
id
|
|
772
|
-
)}${info.label ? `, label: ${JSON.stringify(info.label)}` : ""}${info.permissions.length ? `, permission: ${JSON.stringify(info.permissions)}` : ""} }`
|
|
773
|
-
};
|
|
774
871
|
}
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
let index = startIndex;
|
|
778
|
-
const results = [];
|
|
779
|
-
for (const file of crawlModuleFiles(widgetsDir)) {
|
|
780
|
-
const result = parseWidgetFile(file, widgetsDir, index);
|
|
781
|
-
if (result) {
|
|
782
|
-
results.push(result);
|
|
783
|
-
index++;
|
|
784
|
-
}
|
|
785
|
-
}
|
|
786
|
-
return {
|
|
787
|
-
imports: results.map((r) => r.import),
|
|
788
|
-
entries: results.map((r) => r.entry)
|
|
789
|
-
};
|
|
872
|
+
|
|
873
|
+
export default { groups: [...groups.values()], items: [...items.values()] }`;
|
|
790
874
|
}
|
|
791
|
-
function generateWidgets({
|
|
792
|
-
srcDir,
|
|
793
|
-
pluginExtensions
|
|
794
|
-
}) {
|
|
795
|
-
const { imports, entries: widgetEntries } = collectWidgets(srcDir);
|
|
796
|
-
const pluginDeclarations = pluginExtensions.map(
|
|
797
|
-
(ext, i) => `import __plugin${i} from "${normalizePath(ext)}"`
|
|
798
|
-
);
|
|
799
|
-
const pluginSpreads = pluginExtensions.map(
|
|
800
|
-
(_, i) => ` ...(__plugin${i}.widgetModule?.widgets ?? [])`
|
|
801
|
-
);
|
|
802
|
-
const entries = [...widgetEntries, ...pluginSpreads];
|
|
803
|
-
if (imports.length === 0 && pluginDeclarations.length === 0 && entries.length === 0) {
|
|
804
|
-
return `export default { widgets: [] }`;
|
|
805
|
-
}
|
|
806
|
-
return `${imports.join("\n")}
|
|
807
875
|
|
|
808
|
-
|
|
876
|
+
// src/custom-fields.ts
|
|
877
|
+
function generateCustomFields(config) {
|
|
878
|
+
const { header, names } = emitLayers(config);
|
|
879
|
+
return `${header}
|
|
809
880
|
|
|
810
881
|
export default {
|
|
811
|
-
|
|
812
|
-
${
|
|
882
|
+
configs: [
|
|
883
|
+
${spreadLayers(names, "customFieldsModule", "configs")}
|
|
813
884
|
]
|
|
814
885
|
}`;
|
|
815
886
|
}
|
|
816
887
|
|
|
817
|
-
// src/
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
function generateNavigation({ srcDir }) {
|
|
828
|
-
const file = findNavigationFile(srcDir);
|
|
829
|
-
if (!file) {
|
|
830
|
-
return `export default { items: [] }`;
|
|
831
|
-
}
|
|
832
|
-
return `import navigationConfig from "${normalizePath(file)}"
|
|
833
|
-
export default navigationConfig`;
|
|
888
|
+
// src/layouts-module.ts
|
|
889
|
+
function generateLayouts(config) {
|
|
890
|
+
const { header, names } = emitLayers(config);
|
|
891
|
+
return `${header}
|
|
892
|
+
|
|
893
|
+
const byId = new Map()
|
|
894
|
+
for (const layout of [
|
|
895
|
+
${spreadLayers(names, "layoutModule", "layouts")}
|
|
896
|
+
]) {
|
|
897
|
+
if (layout?.id) byId.set(layout.id, layout)
|
|
834
898
|
}
|
|
835
899
|
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
function generateCustomFields({
|
|
839
|
-
srcDir,
|
|
840
|
-
pluginExtensions
|
|
841
|
-
}) {
|
|
842
|
-
const dir = import_path7.default.join(srcDir, "custom-fields");
|
|
843
|
-
const files = crawlModuleFiles(dir);
|
|
844
|
-
const imports = files.map(
|
|
845
|
-
(file, i) => `import __cf${i} from "${normalizePath(file)}"`
|
|
846
|
-
);
|
|
847
|
-
const localRefs = files.map((_, i) => `__cf${i}`);
|
|
848
|
-
const pluginDeclarations = pluginExtensions.map(
|
|
849
|
-
(ext, i) => `const __plugin${i} = (await import("${normalizePath(ext)}")).default`
|
|
850
|
-
);
|
|
851
|
-
const pluginSpreads = pluginExtensions.map(
|
|
852
|
-
(_, i) => ` ...(__plugin${i}.customFieldsModule?.configs ?? [])`
|
|
853
|
-
);
|
|
854
|
-
const configs = [
|
|
855
|
-
...pluginSpreads,
|
|
856
|
-
...localRefs.map((ref) => ` ${ref}`)
|
|
857
|
-
];
|
|
858
|
-
if (configs.length === 0 && pluginDeclarations.length === 0) {
|
|
859
|
-
return `export default { configs: [] }`;
|
|
860
|
-
}
|
|
861
|
-
return `${imports.join("\n")}
|
|
900
|
+
export default { layouts: [...byId.values()] }`;
|
|
901
|
+
}
|
|
862
902
|
|
|
863
|
-
|
|
903
|
+
// src/preferences-module.ts
|
|
904
|
+
function generatePreferences(config) {
|
|
905
|
+
const { header, names } = emitLayers(config);
|
|
906
|
+
return `${header}
|
|
864
907
|
|
|
865
|
-
export default {
|
|
866
|
-
configs: [
|
|
867
|
-
${configs.join(",\n")}
|
|
868
|
-
]
|
|
869
|
-
}`;
|
|
908
|
+
export default { layers: [${names.map((name) => `${name}.preferenceModule ?? {}`).join(", ")}] }`;
|
|
870
909
|
}
|
|
871
910
|
|
|
872
911
|
// src/virtual-modules.ts
|
|
@@ -901,6 +940,12 @@ function loadVirtualModule({
|
|
|
901
940
|
if (id === RESOLVED_CUSTOM_FIELDS_MODULE) {
|
|
902
941
|
return generateCustomFields(mercurConfig);
|
|
903
942
|
}
|
|
943
|
+
if (id === RESOLVED_LAYOUTS_MODULE) {
|
|
944
|
+
return generateLayouts(mercurConfig);
|
|
945
|
+
}
|
|
946
|
+
if (id === RESOLVED_PREFERENCES_MODULE) {
|
|
947
|
+
return generatePreferences(mercurConfig);
|
|
948
|
+
}
|
|
904
949
|
return null;
|
|
905
950
|
}
|
|
906
951
|
function loadConfigModule(mercurConfig) {
|
|
@@ -918,19 +963,42 @@ function loadI18nModule(mercurConfig) {
|
|
|
918
963
|
|
|
919
964
|
// src/plugin.ts
|
|
920
965
|
function isRouteFile(file) {
|
|
921
|
-
const basename =
|
|
966
|
+
const basename = import_path5.default.basename(file, import_path5.default.extname(file));
|
|
922
967
|
return basename === "page";
|
|
923
968
|
}
|
|
924
969
|
function isWidgetFile(file) {
|
|
925
970
|
return normalizeSep(file).includes("/src/widgets/");
|
|
926
971
|
}
|
|
927
972
|
function isNavigationFile(file) {
|
|
928
|
-
const basename =
|
|
929
|
-
return basename ===
|
|
973
|
+
const basename = import_path5.default.basename(file, import_path5.default.extname(file));
|
|
974
|
+
return basename === NAVIGATION_FILE;
|
|
975
|
+
}
|
|
976
|
+
function isPreferencesFile(file) {
|
|
977
|
+
const basename = import_path5.default.basename(file, import_path5.default.extname(file));
|
|
978
|
+
return basename === LAYOUT_PREFERENCES_FILE;
|
|
930
979
|
}
|
|
931
980
|
function isCustomFieldFile(file) {
|
|
932
981
|
return normalizeSep(file).includes("/src/custom-fields/");
|
|
933
982
|
}
|
|
983
|
+
function isLayoutFile(file) {
|
|
984
|
+
return normalizeSep(file).includes("/layouts/");
|
|
985
|
+
}
|
|
986
|
+
function isI18nFile(file) {
|
|
987
|
+
return normalizeSep(file).includes("/i18n/");
|
|
988
|
+
}
|
|
989
|
+
var LAYERED_MODULES = [
|
|
990
|
+
RESOLVED_ROUTES_MODULE,
|
|
991
|
+
RESOLVED_MENU_ITEMS_MODULE,
|
|
992
|
+
RESOLVED_WIDGETS_MODULE,
|
|
993
|
+
RESOLVED_NAVIGATION_MODULE,
|
|
994
|
+
RESOLVED_CUSTOM_FIELDS_MODULE,
|
|
995
|
+
RESOLVED_LAYOUTS_MODULE,
|
|
996
|
+
RESOLVED_PREFERENCES_MODULE,
|
|
997
|
+
RESOLVED_I18N_MODULE
|
|
998
|
+
];
|
|
999
|
+
function isExtensionFile(file) {
|
|
1000
|
+
return isRouteFile(file) || isWidgetFile(file) || isNavigationFile(file) || isPreferencesFile(file) || isCustomFieldFile(file) || isLayoutFile(file) || isI18nFile(file);
|
|
1001
|
+
}
|
|
934
1002
|
function normalizeSep(file) {
|
|
935
1003
|
return file.replace(/\\/g, "/");
|
|
936
1004
|
}
|
|
@@ -951,7 +1019,7 @@ function isMedusaVirtualModule(id) {
|
|
|
951
1019
|
return MEDUSA_VIRTUAL_MODULES.includes(id);
|
|
952
1020
|
}
|
|
953
1021
|
function filterResolvableDeps(specifiers, fromDir) {
|
|
954
|
-
const require2 = (0, import_module.createRequire)(
|
|
1022
|
+
const require2 = (0, import_module.createRequire)(import_path5.default.join(fromDir, "noop.js"));
|
|
955
1023
|
return specifiers.filter((specifier) => {
|
|
956
1024
|
try {
|
|
957
1025
|
require2.resolve(specifier);
|
|
@@ -969,44 +1037,44 @@ function isResolvedMedusaVirtualModule(id) {
|
|
|
969
1037
|
}
|
|
970
1038
|
function findNodeModulesRoot(configDir) {
|
|
971
1039
|
let dir = configDir;
|
|
972
|
-
while (dir !==
|
|
973
|
-
const candidate =
|
|
974
|
-
if (
|
|
1040
|
+
while (dir !== import_path5.default.dirname(dir)) {
|
|
1041
|
+
const candidate = import_path5.default.join(dir, "node_modules");
|
|
1042
|
+
if (import_fs6.default.existsSync(candidate) && import_fs6.default.statSync(candidate).isDirectory()) {
|
|
975
1043
|
return candidate;
|
|
976
1044
|
}
|
|
977
|
-
dir =
|
|
1045
|
+
dir = import_path5.default.dirname(dir);
|
|
978
1046
|
}
|
|
979
|
-
return
|
|
1047
|
+
return import_path5.default.join(configDir, "node_modules");
|
|
980
1048
|
}
|
|
981
1049
|
function resolvePluginRoot(resolve, configDir, nodeModulesRoot) {
|
|
982
1050
|
if (resolve.startsWith(".")) {
|
|
983
1051
|
try {
|
|
984
|
-
const resolved =
|
|
985
|
-
return
|
|
1052
|
+
const resolved = import_path5.default.resolve(configDir, resolve);
|
|
1053
|
+
return import_fs6.default.existsSync(resolved) ? import_fs6.default.realpathSync(resolved) : null;
|
|
986
1054
|
} catch {
|
|
987
1055
|
return null;
|
|
988
1056
|
}
|
|
989
1057
|
}
|
|
990
|
-
const require2 = (0, import_module.createRequire)(
|
|
1058
|
+
const require2 = (0, import_module.createRequire)(import_path5.default.join(configDir, "noop.js"));
|
|
991
1059
|
try {
|
|
992
|
-
return
|
|
993
|
-
|
|
1060
|
+
return import_fs6.default.realpathSync(
|
|
1061
|
+
import_path5.default.dirname(require2.resolve(`${resolve}/package.json`))
|
|
994
1062
|
);
|
|
995
1063
|
} catch {
|
|
996
1064
|
}
|
|
997
1065
|
try {
|
|
998
|
-
let dir =
|
|
999
|
-
while (dir !==
|
|
1000
|
-
if (
|
|
1001
|
-
return
|
|
1066
|
+
let dir = import_path5.default.dirname(require2.resolve(resolve));
|
|
1067
|
+
while (dir !== import_path5.default.dirname(dir)) {
|
|
1068
|
+
if (import_fs6.default.existsSync(import_path5.default.join(dir, "package.json"))) {
|
|
1069
|
+
return import_fs6.default.realpathSync(dir);
|
|
1002
1070
|
}
|
|
1003
|
-
dir =
|
|
1071
|
+
dir = import_path5.default.dirname(dir);
|
|
1004
1072
|
}
|
|
1005
1073
|
} catch {
|
|
1006
1074
|
}
|
|
1007
1075
|
try {
|
|
1008
|
-
const packagePath =
|
|
1009
|
-
return
|
|
1076
|
+
const packagePath = import_path5.default.join(nodeModulesRoot, resolve);
|
|
1077
|
+
return import_fs6.default.existsSync(packagePath) ? import_fs6.default.realpathSync(packagePath) : null;
|
|
1010
1078
|
} catch {
|
|
1011
1079
|
return null;
|
|
1012
1080
|
}
|
|
@@ -1024,13 +1092,13 @@ function resolvePluginExtensions(plugins, configDir, appType) {
|
|
|
1024
1092
|
);
|
|
1025
1093
|
continue;
|
|
1026
1094
|
}
|
|
1027
|
-
const extFile =
|
|
1095
|
+
const extFile = import_path5.default.join(
|
|
1028
1096
|
pluginRoot,
|
|
1029
1097
|
".medusa/server/src",
|
|
1030
1098
|
appType,
|
|
1031
1099
|
"index.mjs"
|
|
1032
1100
|
);
|
|
1033
|
-
if (
|
|
1101
|
+
if (import_fs6.default.existsSync(extFile)) {
|
|
1034
1102
|
extensions.push(extFile);
|
|
1035
1103
|
}
|
|
1036
1104
|
}
|
|
@@ -1044,7 +1112,7 @@ function trimTrailingSlashes(value) {
|
|
|
1044
1112
|
return end === value.length ? value : value.slice(0, end);
|
|
1045
1113
|
}
|
|
1046
1114
|
async function loadMedusaConfig(medusaConfigPath, root, options) {
|
|
1047
|
-
const configDir =
|
|
1115
|
+
const configDir = import_path5.default.dirname(medusaConfigPath);
|
|
1048
1116
|
try {
|
|
1049
1117
|
const previousCwd = process.cwd();
|
|
1050
1118
|
let mod;
|
|
@@ -1074,7 +1142,7 @@ async function loadMedusaConfig(medusaConfigPath, root, options) {
|
|
|
1074
1142
|
const value = modules[key];
|
|
1075
1143
|
if (!value || typeof value !== "object" || !value.options?.appDir)
|
|
1076
1144
|
continue;
|
|
1077
|
-
const appDir =
|
|
1145
|
+
const appDir = import_path5.default.resolve(configDir, value.options.appDir);
|
|
1078
1146
|
if (appDir === root) {
|
|
1079
1147
|
base = value.options.path;
|
|
1080
1148
|
appType = key === "vendor_ui" ? "vendor" : "admin";
|
|
@@ -1085,7 +1153,9 @@ async function loadMedusaConfig(medusaConfigPath, root, options) {
|
|
|
1085
1153
|
(plugin) => plugin.resolve !== "@medusajs/draft-order"
|
|
1086
1154
|
) ?? [];
|
|
1087
1155
|
const pluginExtensions = resolvePluginExtensions(plugins, configDir, appType);
|
|
1088
|
-
|
|
1156
|
+
const projectCandidate = import_path5.default.join(configDir, "src", appType);
|
|
1157
|
+
const projectDir = import_fs6.default.existsSync(projectCandidate) && import_fs6.default.realpathSync(projectCandidate) !== root ? projectCandidate : void 0;
|
|
1158
|
+
return { base, pluginExtensions, projectDir, vendorAppUrl };
|
|
1089
1159
|
} catch (error) {
|
|
1090
1160
|
console.warn(
|
|
1091
1161
|
`[@mercurjs/dashboard-sdk] Could not load the Medusa config from "${medusaConfigPath}": ${error instanceof Error ? error.message : String(error)}. Building with base "/" and no plugin extensions \u2014 if this panel is served under a sub-path (e.g. /dashboard), its assets will not resolve.`
|
|
@@ -1101,11 +1171,11 @@ function mercurDashboardPlugin(pluginConfig) {
|
|
|
1101
1171
|
async config(viteConfig) {
|
|
1102
1172
|
root = viteConfig.root || process.cwd();
|
|
1103
1173
|
const isDevelopment = (viteConfig.mode || process.env.NODE_ENV || "development") !== "production";
|
|
1104
|
-
const medusaConfigPath =
|
|
1174
|
+
const medusaConfigPath = import_path5.default.resolve(
|
|
1105
1175
|
root,
|
|
1106
1176
|
pluginConfig.medusaConfigPath
|
|
1107
1177
|
);
|
|
1108
|
-
const { base, pluginExtensions, vendorAppUrl } = await loadMedusaConfig(
|
|
1178
|
+
const { base, pluginExtensions, projectDir, vendorAppUrl } = await loadMedusaConfig(
|
|
1109
1179
|
medusaConfigPath,
|
|
1110
1180
|
root,
|
|
1111
1181
|
{
|
|
@@ -1113,7 +1183,7 @@ function mercurDashboardPlugin(pluginConfig) {
|
|
|
1113
1183
|
vendorUrl: pluginConfig.vendorUrl
|
|
1114
1184
|
}
|
|
1115
1185
|
);
|
|
1116
|
-
const srcDir =
|
|
1186
|
+
const srcDir = import_path5.default.join(root, "src");
|
|
1117
1187
|
const backendUrl = pluginConfig.backendUrl ?? "http://localhost:9000";
|
|
1118
1188
|
const imageLimit = pluginConfig.imageLimit ?? 2 * 1024 * 1024;
|
|
1119
1189
|
config = {
|
|
@@ -1122,6 +1192,7 @@ function mercurDashboardPlugin(pluginConfig) {
|
|
|
1122
1192
|
base,
|
|
1123
1193
|
root,
|
|
1124
1194
|
srcDir,
|
|
1195
|
+
projectDir,
|
|
1125
1196
|
pluginExtensions,
|
|
1126
1197
|
imageLimit
|
|
1127
1198
|
};
|
|
@@ -1136,16 +1207,7 @@ function mercurDashboardPlugin(pluginConfig) {
|
|
|
1136
1207
|
dedupe: ["i18next", "react-i18next", "react", "react-dom"]
|
|
1137
1208
|
},
|
|
1138
1209
|
optimizeDeps: {
|
|
1139
|
-
exclude: [
|
|
1140
|
-
"virtual:mercur/config",
|
|
1141
|
-
"virtual:mercur/routes",
|
|
1142
|
-
"virtual:mercur/menu-items",
|
|
1143
|
-
"virtual:mercur/i18n",
|
|
1144
|
-
"virtual:mercur/widgets",
|
|
1145
|
-
"virtual:mercur/navigation",
|
|
1146
|
-
"virtual:mercur/custom-fields",
|
|
1147
|
-
...MEDUSA_VIRTUAL_MODULES
|
|
1148
|
-
],
|
|
1210
|
+
exclude: [...VIRTUAL_MODULES, ...MEDUSA_VIRTUAL_MODULES],
|
|
1149
1211
|
include: filterResolvableDeps(
|
|
1150
1212
|
[
|
|
1151
1213
|
"react",
|
|
@@ -1191,10 +1253,9 @@ function mercurDashboardPlugin(pluginConfig) {
|
|
|
1191
1253
|
}
|
|
1192
1254
|
};
|
|
1193
1255
|
const handleChange = (file) => {
|
|
1194
|
-
if (
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
if (isCustomFieldFile(file)) invalidate(RESOLVED_CUSTOM_FIELDS_MODULE, true);
|
|
1256
|
+
if (!isExtensionFile(file)) return;
|
|
1257
|
+
for (const moduleId of LAYERED_MODULES) invalidate(moduleId, false);
|
|
1258
|
+
server.ws.send({ type: "full-reload" });
|
|
1198
1259
|
};
|
|
1199
1260
|
server.watcher.on("add", handleChange);
|
|
1200
1261
|
server.watcher.on("unlink", handleChange);
|
|
@@ -1204,103 +1265,21 @@ function mercurDashboardPlugin(pluginConfig) {
|
|
|
1204
1265
|
const mod = server.moduleGraph.getModuleById(moduleId);
|
|
1205
1266
|
if (mod) server.moduleGraph.invalidateModule(mod);
|
|
1206
1267
|
};
|
|
1207
|
-
if (
|
|
1208
|
-
|
|
1209
|
-
if (isNavigationFile(file)) invalidate(RESOLVED_NAVIGATION_MODULE);
|
|
1210
|
-
if (isCustomFieldFile(file)) invalidate(RESOLVED_CUSTOM_FIELDS_MODULE);
|
|
1268
|
+
if (!isExtensionFile(file)) return;
|
|
1269
|
+
for (const moduleId of LAYERED_MODULES) invalidate(moduleId);
|
|
1211
1270
|
}
|
|
1212
1271
|
};
|
|
1213
1272
|
}
|
|
1214
1273
|
|
|
1215
1274
|
// src/generate-plugin-entry.ts
|
|
1216
|
-
var import_path9 = __toESM(require("path"), 1);
|
|
1217
|
-
var import_fs8 = __toESM(require("fs"), 1);
|
|
1218
|
-
function findI18nIndex2(srcDir) {
|
|
1219
|
-
const i18nDir = import_path9.default.join(srcDir, "i18n");
|
|
1220
|
-
if (!import_fs8.default.existsSync(i18nDir)) return null;
|
|
1221
|
-
for (const ext of VALID_FILE_EXTENSIONS) {
|
|
1222
|
-
const filePath = import_path9.default.join(i18nDir, `index${ext}`);
|
|
1223
|
-
if (import_fs8.default.existsSync(filePath)) return filePath;
|
|
1224
|
-
}
|
|
1225
|
-
return null;
|
|
1226
|
-
}
|
|
1227
1275
|
function generatePluginEntryModule(srcDir) {
|
|
1228
|
-
const
|
|
1229
|
-
const files = crawlRoutes(routesDir);
|
|
1230
|
-
let index = 0;
|
|
1231
|
-
const routeResults = [];
|
|
1232
|
-
const menuItemResults = [];
|
|
1233
|
-
for (const file of files) {
|
|
1234
|
-
const route = parseFile(file, routesDir, index);
|
|
1235
|
-
if (route) {
|
|
1236
|
-
routeResults.push(route);
|
|
1237
|
-
}
|
|
1238
|
-
const menuItem = parseMenuItemFile(file, routesDir, index);
|
|
1239
|
-
if (menuItem) {
|
|
1240
|
-
menuItemResults.push(menuItem);
|
|
1241
|
-
}
|
|
1242
|
-
index++;
|
|
1243
|
-
}
|
|
1244
|
-
const routeTree = buildRouteTree(routeResults.filter(Boolean));
|
|
1245
|
-
const routeImports = routeTree.flatMap((r) => r.imports);
|
|
1246
|
-
const routes = routeTree.map((r) => formatRoute(r.route));
|
|
1247
|
-
const menuItemImports = menuItemResults.filter(Boolean).map((r) => r.import);
|
|
1248
|
-
const menuItems = menuItemResults.filter(Boolean).map((r) => formatMenuItem(r.menuItem));
|
|
1249
|
-
const { imports: widgetImports, entries: widgetEntries } = collectWidgets(
|
|
1250
|
-
srcDir,
|
|
1251
|
-
index
|
|
1252
|
-
);
|
|
1253
|
-
const cfFiles = crawlModuleFiles(import_path9.default.join(srcDir, "custom-fields"));
|
|
1254
|
-
const cfImports = cfFiles.map(
|
|
1255
|
-
(file, i) => `import __cf${i} from "${normalizePath(file)}"`
|
|
1256
|
-
);
|
|
1257
|
-
const cfRefs = cfFiles.map((_, i) => ` __cf${i}`);
|
|
1258
|
-
const i18nFile = findI18nIndex2(srcDir);
|
|
1259
|
-
const i18nImport = i18nFile ? `import i18nResources from "${normalizePath(i18nFile)}"` : "";
|
|
1260
|
-
const i18nValue = i18nFile ? "i18nResources" : "{}";
|
|
1261
|
-
const allImports = [
|
|
1262
|
-
...routeImports,
|
|
1263
|
-
...menuItemImports,
|
|
1264
|
-
...widgetImports,
|
|
1265
|
-
...cfImports
|
|
1266
|
-
];
|
|
1267
|
-
if (i18nImport) allImports.push(i18nImport);
|
|
1276
|
+
const { imports, declaration, name } = collectLayer(srcDir, 0);
|
|
1268
1277
|
return `// Auto-generated plugin extensions entry
|
|
1269
|
-
${
|
|
1270
|
-
|
|
1271
|
-
const routeModule = {
|
|
1272
|
-
routes: [
|
|
1273
|
-
${routes.join(",\n")}
|
|
1274
|
-
]
|
|
1275
|
-
}
|
|
1276
|
-
|
|
1277
|
-
const menuItemModule = {
|
|
1278
|
-
menuItems: [
|
|
1279
|
-
${menuItems.join(",\n")}
|
|
1280
|
-
]
|
|
1281
|
-
}
|
|
1282
|
-
|
|
1283
|
-
const widgetModule = {
|
|
1284
|
-
widgets: [
|
|
1285
|
-
${widgetEntries.join(",\n")}
|
|
1286
|
-
]
|
|
1287
|
-
}
|
|
1288
|
-
|
|
1289
|
-
const customFieldsModule = {
|
|
1290
|
-
configs: [
|
|
1291
|
-
${cfRefs.join(",\n")}
|
|
1292
|
-
]
|
|
1293
|
-
}
|
|
1278
|
+
${imports.join("\n")}
|
|
1294
1279
|
|
|
1295
|
-
|
|
1296
|
-
routeModule,
|
|
1297
|
-
menuItemModule,
|
|
1298
|
-
widgetModule,
|
|
1299
|
-
customFieldsModule,
|
|
1300
|
-
i18nModule: ${i18nValue},
|
|
1301
|
-
}
|
|
1280
|
+
${declaration}
|
|
1302
1281
|
|
|
1303
|
-
export default
|
|
1282
|
+
export default ${name}
|
|
1304
1283
|
`;
|
|
1305
1284
|
}
|
|
1306
1285
|
// Annotate the CommonJS export names for ESM import in node:
|