@mokup/cli 1.1.0 → 1.1.2
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 +64 -591
- package/dist/index.d.cts +4 -41
- package/dist/index.d.mts +4 -41
- package/dist/index.d.ts +4 -41
- package/dist/index.mjs +62 -588
- package/package.json +11 -12
package/dist/index.mjs
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
import { promises } from 'node:fs';
|
|
2
2
|
import process, { cwd } from 'node:process';
|
|
3
|
-
import { join,
|
|
3
|
+
import { join, relative, extname, dirname, resolve } from '@mokup/shared/pathe';
|
|
4
|
+
import { resolveDirectoryConfig as resolveDirectoryConfig$1, isPromise } from '@mokup/shared/config-utils';
|
|
5
|
+
import { loadModule } from '@mokup/shared/module-loader';
|
|
6
|
+
import { configExtensions } from '@mokup/shared/route-constants';
|
|
7
|
+
import { collectFiles, isSupportedFile } from '@mokup/shared/mock-files';
|
|
8
|
+
import { resolveDirs as resolveDirs$1, normalizeIgnorePrefix } from '@mokup/shared/scan-utils';
|
|
9
|
+
import { toPosix, hasIgnoredPrefix, matchesFilter } from '@mokup/shared/path-utils';
|
|
4
10
|
import { Buffer } from 'node:buffer';
|
|
5
|
-
import { createRequire } from 'node:module';
|
|
6
|
-
import { pathToFileURL } from 'node:url';
|
|
7
11
|
import { build } from '@mokup/shared/esbuild';
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
12
|
+
import { compareRouteScore, parseRouteTemplate } from '@mokup/runtime';
|
|
13
|
+
import { createRouteUtils } from '@mokup/shared/route-utils';
|
|
14
|
+
import { loadRules as loadRules$1 } from '@mokup/shared/load-rules';
|
|
15
|
+
import { createDefineConfig } from '@mokup/shared/define-config';
|
|
11
16
|
import { createFetchServer, serve } from '@mokup/server/node';
|
|
12
17
|
import { createLogger } from '@mokup/shared/logger';
|
|
13
18
|
import { Command } from 'commander';
|
|
@@ -68,263 +73,48 @@ async function writeManifestModule(outDir, manifest) {
|
|
|
68
73
|
await promises.writeFile(join(outDir, "mokup.manifest.d.mts"), dts.join("\n"), "utf8");
|
|
69
74
|
}
|
|
70
75
|
|
|
71
|
-
const configExtensions = [".ts", ".js", ".mjs", ".cjs"];
|
|
72
|
-
const middlewareSymbol$1 = Symbol.for("mokup.config.middlewares");
|
|
73
|
-
async function loadModule$1(file) {
|
|
74
|
-
const ext = configExtensions.find((extension) => file.endsWith(extension));
|
|
75
|
-
if (ext === ".cjs") {
|
|
76
|
-
const require = createRequire(import.meta.url);
|
|
77
|
-
delete require.cache[file];
|
|
78
|
-
return require(file);
|
|
79
|
-
}
|
|
80
|
-
if (ext === ".js" || ext === ".mjs") {
|
|
81
|
-
return import(`${pathToFileURL(file).href}?t=${Date.now()}`);
|
|
82
|
-
}
|
|
83
|
-
if (ext === ".ts") {
|
|
84
|
-
const result = await build({
|
|
85
|
-
entryPoints: [file],
|
|
86
|
-
bundle: true,
|
|
87
|
-
format: "esm",
|
|
88
|
-
platform: "node",
|
|
89
|
-
sourcemap: "inline",
|
|
90
|
-
target: "es2020",
|
|
91
|
-
write: false
|
|
92
|
-
});
|
|
93
|
-
const output = result.outputFiles[0];
|
|
94
|
-
const code = output?.text ?? "";
|
|
95
|
-
const dataUrl = `data:text/javascript;base64,${Buffer.from(code).toString(
|
|
96
|
-
"base64"
|
|
97
|
-
)}`;
|
|
98
|
-
return import(`${dataUrl}#${Date.now()}`);
|
|
99
|
-
}
|
|
100
|
-
return null;
|
|
101
|
-
}
|
|
102
|
-
function getConfigFileCandidates(dir) {
|
|
103
|
-
return configExtensions.map((extension) => join(dir, `index.config${extension}`));
|
|
104
|
-
}
|
|
105
|
-
async function findConfigFile(dir, cache) {
|
|
106
|
-
const cached = cache.get(dir);
|
|
107
|
-
if (cached !== void 0) {
|
|
108
|
-
return cached;
|
|
109
|
-
}
|
|
110
|
-
for (const candidate of getConfigFileCandidates(dir)) {
|
|
111
|
-
try {
|
|
112
|
-
await promises.stat(candidate);
|
|
113
|
-
cache.set(dir, candidate);
|
|
114
|
-
return candidate;
|
|
115
|
-
} catch {
|
|
116
|
-
continue;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
cache.set(dir, null);
|
|
120
|
-
return null;
|
|
121
|
-
}
|
|
122
76
|
async function loadConfig(file) {
|
|
123
|
-
const mod = await loadModule
|
|
77
|
+
const mod = await loadModule(file);
|
|
124
78
|
if (!mod) {
|
|
125
79
|
return null;
|
|
126
80
|
}
|
|
127
81
|
const raw = mod?.default ?? mod;
|
|
128
|
-
const value = isPromise
|
|
82
|
+
const value = isPromise(raw) ? await raw : raw;
|
|
129
83
|
if (!value || typeof value !== "object") {
|
|
130
84
|
return null;
|
|
131
85
|
}
|
|
132
86
|
return value;
|
|
133
87
|
}
|
|
134
|
-
function isPromise$1(value) {
|
|
135
|
-
return !!value && typeof value.then === "function";
|
|
136
|
-
}
|
|
137
|
-
function normalizeMiddlewares(value, source, log, position) {
|
|
138
|
-
if (!value) {
|
|
139
|
-
return [];
|
|
140
|
-
}
|
|
141
|
-
const list = Array.isArray(value) ? value : [value];
|
|
142
|
-
const middlewares = [];
|
|
143
|
-
list.forEach((entry, index) => {
|
|
144
|
-
if (typeof entry !== "function") {
|
|
145
|
-
log?.(`Invalid middleware in ${source}`);
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
148
|
-
middlewares.push({ file: source, index, position });
|
|
149
|
-
});
|
|
150
|
-
return middlewares;
|
|
151
|
-
}
|
|
152
|
-
function readMiddlewareMeta(config) {
|
|
153
|
-
const value = config[middlewareSymbol$1];
|
|
154
|
-
if (!value || typeof value !== "object") {
|
|
155
|
-
return null;
|
|
156
|
-
}
|
|
157
|
-
const meta = value;
|
|
158
|
-
return {
|
|
159
|
-
pre: Array.isArray(meta.pre) ? meta.pre : [],
|
|
160
|
-
normal: Array.isArray(meta.normal) ? meta.normal : [],
|
|
161
|
-
post: Array.isArray(meta.post) ? meta.post : []
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
88
|
async function resolveDirectoryConfig(params) {
|
|
165
89
|
const { file, rootDir, log, configCache, fileCache } = params;
|
|
166
|
-
const
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
}
|
|
181
|
-
chain.reverse();
|
|
182
|
-
const merged = {};
|
|
183
|
-
const preMiddlewares = [];
|
|
184
|
-
const normalMiddlewares = [];
|
|
185
|
-
const postMiddlewares = [];
|
|
186
|
-
for (const dir of chain) {
|
|
187
|
-
const configPath = await findConfigFile(dir, fileCache);
|
|
188
|
-
if (!configPath) {
|
|
189
|
-
continue;
|
|
190
|
-
}
|
|
191
|
-
let config = configCache.get(configPath);
|
|
192
|
-
if (config === void 0) {
|
|
193
|
-
config = await loadConfig(configPath);
|
|
194
|
-
configCache.set(configPath, config);
|
|
195
|
-
}
|
|
196
|
-
if (!config) {
|
|
197
|
-
log?.(`Invalid config in ${configPath}`);
|
|
198
|
-
continue;
|
|
199
|
-
}
|
|
200
|
-
if (config.headers) {
|
|
201
|
-
merged.headers = { ...merged.headers ?? {}, ...config.headers };
|
|
202
|
-
}
|
|
203
|
-
if (typeof config.status === "number") {
|
|
204
|
-
merged.status = config.status;
|
|
205
|
-
}
|
|
206
|
-
if (typeof config.delay === "number") {
|
|
207
|
-
merged.delay = config.delay;
|
|
208
|
-
}
|
|
209
|
-
if (typeof config.enabled === "boolean") {
|
|
210
|
-
merged.enabled = config.enabled;
|
|
211
|
-
}
|
|
212
|
-
if (typeof config.ignorePrefix !== "undefined") {
|
|
213
|
-
merged.ignorePrefix = config.ignorePrefix;
|
|
214
|
-
}
|
|
215
|
-
if (typeof config.include !== "undefined") {
|
|
216
|
-
merged.include = config.include;
|
|
217
|
-
}
|
|
218
|
-
if (typeof config.exclude !== "undefined") {
|
|
219
|
-
merged.exclude = config.exclude;
|
|
220
|
-
}
|
|
221
|
-
const meta = readMiddlewareMeta(config);
|
|
222
|
-
const normalizedPre = normalizeMiddlewares(
|
|
223
|
-
meta?.pre,
|
|
224
|
-
configPath,
|
|
225
|
-
log,
|
|
226
|
-
"pre"
|
|
227
|
-
);
|
|
228
|
-
const normalizedNormal = normalizeMiddlewares(
|
|
229
|
-
meta?.normal,
|
|
230
|
-
configPath,
|
|
231
|
-
log,
|
|
232
|
-
"normal"
|
|
233
|
-
);
|
|
234
|
-
const normalizedLegacy = normalizeMiddlewares(
|
|
235
|
-
config.middleware,
|
|
236
|
-
configPath,
|
|
237
|
-
log,
|
|
238
|
-
"normal"
|
|
239
|
-
);
|
|
240
|
-
const normalizedPost = normalizeMiddlewares(
|
|
241
|
-
meta?.post,
|
|
242
|
-
configPath,
|
|
243
|
-
log,
|
|
244
|
-
"post"
|
|
245
|
-
);
|
|
246
|
-
if (normalizedPre.length > 0) {
|
|
247
|
-
preMiddlewares.push(...normalizedPre);
|
|
248
|
-
}
|
|
249
|
-
if (normalizedNormal.length > 0) {
|
|
250
|
-
normalMiddlewares.push(...normalizedNormal);
|
|
251
|
-
}
|
|
252
|
-
if (normalizedLegacy.length > 0) {
|
|
253
|
-
normalMiddlewares.push(...normalizedLegacy);
|
|
254
|
-
}
|
|
255
|
-
if (normalizedPost.length > 0) {
|
|
256
|
-
postMiddlewares.push(...normalizedPost);
|
|
257
|
-
}
|
|
258
|
-
}
|
|
90
|
+
const resolved = await resolveDirectoryConfig$1({
|
|
91
|
+
file,
|
|
92
|
+
rootDir,
|
|
93
|
+
configExtensions,
|
|
94
|
+
configCache,
|
|
95
|
+
fileCache,
|
|
96
|
+
loadConfig,
|
|
97
|
+
warn: log,
|
|
98
|
+
mapMiddleware: (_handler, index, position, source) => ({
|
|
99
|
+
file: source,
|
|
100
|
+
index,
|
|
101
|
+
position
|
|
102
|
+
})
|
|
103
|
+
});
|
|
259
104
|
return {
|
|
260
|
-
|
|
261
|
-
|
|
105
|
+
headers: resolved.headers,
|
|
106
|
+
status: resolved.status,
|
|
107
|
+
delay: resolved.delay,
|
|
108
|
+
enabled: resolved.enabled,
|
|
109
|
+
ignorePrefix: resolved.ignorePrefix,
|
|
110
|
+
include: resolved.include,
|
|
111
|
+
exclude: resolved.exclude,
|
|
112
|
+
middlewares: resolved.middlewares
|
|
262
113
|
};
|
|
263
114
|
}
|
|
264
115
|
|
|
265
|
-
const supportedExtensions = /* @__PURE__ */ new Set([
|
|
266
|
-
".json",
|
|
267
|
-
".jsonc",
|
|
268
|
-
".ts",
|
|
269
|
-
".js",
|
|
270
|
-
".mjs",
|
|
271
|
-
".cjs"
|
|
272
|
-
]);
|
|
273
|
-
async function exists(path) {
|
|
274
|
-
try {
|
|
275
|
-
await promises.stat(path);
|
|
276
|
-
return true;
|
|
277
|
-
} catch {
|
|
278
|
-
return false;
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
async function walkDir(dir, rootDir, files) {
|
|
282
|
-
const entries = await promises.readdir(dir, { withFileTypes: true });
|
|
283
|
-
for (const entry of entries) {
|
|
284
|
-
if (entry.name === "node_modules" || entry.name === ".git") {
|
|
285
|
-
continue;
|
|
286
|
-
}
|
|
287
|
-
const fullPath = join(dir, entry.name);
|
|
288
|
-
if (entry.isDirectory()) {
|
|
289
|
-
await walkDir(fullPath, rootDir, files);
|
|
290
|
-
continue;
|
|
291
|
-
}
|
|
292
|
-
if (entry.isFile()) {
|
|
293
|
-
files.push({ file: fullPath, rootDir });
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
async function collectFiles(dirs) {
|
|
298
|
-
const files = [];
|
|
299
|
-
for (const dir of dirs) {
|
|
300
|
-
if (!await exists(dir)) {
|
|
301
|
-
continue;
|
|
302
|
-
}
|
|
303
|
-
await walkDir(dir, dir, files);
|
|
304
|
-
}
|
|
305
|
-
return files;
|
|
306
|
-
}
|
|
307
116
|
function resolveDirs(dir, root) {
|
|
308
|
-
|
|
309
|
-
const resolved = Array.isArray(raw) ? raw : raw ? [raw] : ["mock"];
|
|
310
|
-
const normalized = resolved.map(
|
|
311
|
-
(entry) => isAbsolute(entry) ? entry : resolve(root, entry)
|
|
312
|
-
);
|
|
313
|
-
return Array.from(new Set(normalized));
|
|
314
|
-
}
|
|
315
|
-
function normalizeIgnorePrefix(value, fallback = ["."]) {
|
|
316
|
-
const list = typeof value === "undefined" ? fallback : Array.isArray(value) ? value : [value];
|
|
317
|
-
return list.filter((entry) => typeof entry === "string" && entry.length > 0);
|
|
318
|
-
}
|
|
319
|
-
function isSupportedFile(file) {
|
|
320
|
-
if (file.endsWith(".d.ts")) {
|
|
321
|
-
return false;
|
|
322
|
-
}
|
|
323
|
-
if (basename(file).startsWith("index.config.")) {
|
|
324
|
-
return false;
|
|
325
|
-
}
|
|
326
|
-
const ext = extname(file).toLowerCase();
|
|
327
|
-
return supportedExtensions.has(ext);
|
|
117
|
+
return resolveDirs$1(dir, root);
|
|
328
118
|
}
|
|
329
119
|
|
|
330
120
|
function getHandlerModulePath(file, handlersDir, root) {
|
|
@@ -426,119 +216,28 @@ async function bundleHandlers(files, root, handlersDir) {
|
|
|
426
216
|
});
|
|
427
217
|
}
|
|
428
218
|
|
|
429
|
-
const
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
"PATCH",
|
|
434
|
-
"DELETE",
|
|
435
|
-
"OPTIONS",
|
|
436
|
-
"HEAD"
|
|
437
|
-
]);
|
|
438
|
-
const methodSuffixSet = new Set(
|
|
439
|
-
Array.from(methodSet, (method) => method.toLowerCase())
|
|
440
|
-
);
|
|
441
|
-
const jsonExtensions = /* @__PURE__ */ new Set([".json", ".jsonc"]);
|
|
442
|
-
function normalizePrefix(prefix) {
|
|
443
|
-
if (!prefix) {
|
|
444
|
-
return "";
|
|
445
|
-
}
|
|
446
|
-
const normalized = prefix.startsWith("/") ? prefix : `/${prefix}`;
|
|
447
|
-
return normalized.endsWith("/") ? normalized.slice(0, -1) : normalized;
|
|
448
|
-
}
|
|
449
|
-
function resolveTemplate(template, prefix) {
|
|
450
|
-
const normalized = template.startsWith("/") ? template : `/${template}`;
|
|
451
|
-
if (!prefix) {
|
|
452
|
-
return normalized;
|
|
453
|
-
}
|
|
454
|
-
const normalizedPrefix = normalizePrefix(prefix);
|
|
455
|
-
if (!normalizedPrefix) {
|
|
456
|
-
return normalized;
|
|
457
|
-
}
|
|
458
|
-
if (normalized === normalizedPrefix || normalized.startsWith(`${normalizedPrefix}/`)) {
|
|
459
|
-
return normalized;
|
|
460
|
-
}
|
|
461
|
-
if (normalized === "/") {
|
|
462
|
-
return `${normalizedPrefix}/`;
|
|
463
|
-
}
|
|
464
|
-
return `${normalizedPrefix}${normalized}`;
|
|
465
|
-
}
|
|
466
|
-
function stripMethodSuffix(base) {
|
|
467
|
-
const segments = base.split(".");
|
|
468
|
-
const last = segments.at(-1);
|
|
469
|
-
if (last && methodSuffixSet.has(last.toLowerCase())) {
|
|
470
|
-
segments.pop();
|
|
471
|
-
return {
|
|
472
|
-
name: segments.join("."),
|
|
473
|
-
method: last.toUpperCase()
|
|
474
|
-
};
|
|
475
|
-
}
|
|
476
|
-
return {
|
|
477
|
-
name: base,
|
|
478
|
-
method: void 0
|
|
479
|
-
};
|
|
480
|
-
}
|
|
219
|
+
const routeUtils = createRouteUtils({
|
|
220
|
+
parseRouteTemplate,
|
|
221
|
+
compareRouteScore
|
|
222
|
+
});
|
|
481
223
|
function deriveRouteFromFile(file, rootDir, log) {
|
|
482
|
-
|
|
483
|
-
const ext = extname(rel);
|
|
484
|
-
const withoutExt = rel.slice(0, rel.length - ext.length);
|
|
485
|
-
const dir = dirname(withoutExt);
|
|
486
|
-
const base = basename(withoutExt);
|
|
487
|
-
const { name, method } = stripMethodSuffix(base);
|
|
488
|
-
const resolvedMethod = method ?? (jsonExtensions.has(ext) ? "GET" : void 0);
|
|
489
|
-
if (!resolvedMethod) {
|
|
490
|
-
log?.(`Skip mock without method suffix: ${file}`);
|
|
491
|
-
return null;
|
|
492
|
-
}
|
|
493
|
-
if (!name) {
|
|
494
|
-
log?.(`Skip mock with empty route name: ${file}`);
|
|
495
|
-
return null;
|
|
496
|
-
}
|
|
497
|
-
const joined = dir === "." ? name : join(dir, name);
|
|
498
|
-
const segments = toPosix(joined).split("/");
|
|
499
|
-
if (segments.at(-1) === "index") {
|
|
500
|
-
segments.pop();
|
|
501
|
-
}
|
|
502
|
-
const template = segments.length === 0 ? "/" : `/${segments.join("/")}`;
|
|
503
|
-
const parsed = parseRouteTemplate(template);
|
|
504
|
-
if (parsed.errors.length > 0) {
|
|
505
|
-
for (const error of parsed.errors) {
|
|
506
|
-
log?.(`${error} in ${file}`);
|
|
507
|
-
}
|
|
508
|
-
return null;
|
|
509
|
-
}
|
|
510
|
-
for (const warning of parsed.warnings) {
|
|
511
|
-
log?.(`${warning} in ${file}`);
|
|
512
|
-
}
|
|
513
|
-
return {
|
|
514
|
-
template: parsed.template,
|
|
515
|
-
method: resolvedMethod,
|
|
516
|
-
tokens: parsed.tokens,
|
|
517
|
-
score: parsed.score
|
|
518
|
-
};
|
|
224
|
+
return routeUtils.deriveRouteFromFile(file, rootDir, log);
|
|
519
225
|
}
|
|
520
226
|
function resolveRule(params) {
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
}
|
|
536
|
-
return {
|
|
537
|
-
method,
|
|
538
|
-
template: parsed.template,
|
|
539
|
-
tokens: parsed.tokens,
|
|
540
|
-
score: parsed.score
|
|
541
|
-
};
|
|
227
|
+
return routeUtils.resolveRule({
|
|
228
|
+
rule: params.rule,
|
|
229
|
+
derivedTemplate: params.derivedTemplate,
|
|
230
|
+
derivedMethod: params.derivedMethod,
|
|
231
|
+
prefix: params.prefix,
|
|
232
|
+
file: params.file,
|
|
233
|
+
warn: params.log,
|
|
234
|
+
build: (base) => ({
|
|
235
|
+
method: base.method,
|
|
236
|
+
template: base.template,
|
|
237
|
+
tokens: base.tokens,
|
|
238
|
+
score: base.score
|
|
239
|
+
})
|
|
240
|
+
});
|
|
542
241
|
}
|
|
543
242
|
function sortRoutes(routes) {
|
|
544
243
|
return routes.sort((a, b) => {
|
|
@@ -549,80 +248,8 @@ function sortRoutes(routes) {
|
|
|
549
248
|
});
|
|
550
249
|
}
|
|
551
250
|
|
|
552
|
-
async function readJsonFile(file) {
|
|
553
|
-
try {
|
|
554
|
-
const content = await promises.readFile(file, "utf8");
|
|
555
|
-
const errors = [];
|
|
556
|
-
const data = parse(content, errors, {
|
|
557
|
-
allowTrailingComma: true,
|
|
558
|
-
disallowComments: false
|
|
559
|
-
});
|
|
560
|
-
if (errors.length > 0) {
|
|
561
|
-
return void 0;
|
|
562
|
-
}
|
|
563
|
-
return data;
|
|
564
|
-
} catch {
|
|
565
|
-
return void 0;
|
|
566
|
-
}
|
|
567
|
-
}
|
|
568
|
-
async function loadModule(file) {
|
|
569
|
-
const ext = extname(file).toLowerCase();
|
|
570
|
-
if (ext === ".cjs") {
|
|
571
|
-
const require = createRequire(import.meta.url);
|
|
572
|
-
delete require.cache[file];
|
|
573
|
-
return require(file);
|
|
574
|
-
}
|
|
575
|
-
if (ext === ".js" || ext === ".mjs") {
|
|
576
|
-
return import(`${pathToFileURL(file).href}?t=${Date.now()}`);
|
|
577
|
-
}
|
|
578
|
-
if (ext === ".ts") {
|
|
579
|
-
const result = await build({
|
|
580
|
-
entryPoints: [file],
|
|
581
|
-
bundle: true,
|
|
582
|
-
format: "esm",
|
|
583
|
-
platform: "node",
|
|
584
|
-
sourcemap: "inline",
|
|
585
|
-
target: "es2020",
|
|
586
|
-
write: false
|
|
587
|
-
});
|
|
588
|
-
const output = result.outputFiles[0];
|
|
589
|
-
const code = output?.text ?? "";
|
|
590
|
-
const dataUrl = `data:text/javascript;base64,${Buffer.from(code).toString(
|
|
591
|
-
"base64"
|
|
592
|
-
)}`;
|
|
593
|
-
return import(`${dataUrl}#${Date.now()}`);
|
|
594
|
-
}
|
|
595
|
-
return null;
|
|
596
|
-
}
|
|
597
251
|
async function loadRules(file) {
|
|
598
|
-
|
|
599
|
-
if (ext === ".json" || ext === ".jsonc") {
|
|
600
|
-
const json = await readJsonFile(file);
|
|
601
|
-
if (typeof json === "undefined") {
|
|
602
|
-
return [];
|
|
603
|
-
}
|
|
604
|
-
return [
|
|
605
|
-
{
|
|
606
|
-
handler: json
|
|
607
|
-
}
|
|
608
|
-
];
|
|
609
|
-
}
|
|
610
|
-
const mod = await loadModule(file);
|
|
611
|
-
const value = mod?.default ?? mod;
|
|
612
|
-
if (!value) {
|
|
613
|
-
return [];
|
|
614
|
-
}
|
|
615
|
-
if (Array.isArray(value)) {
|
|
616
|
-
return value;
|
|
617
|
-
}
|
|
618
|
-
if (typeof value === "function") {
|
|
619
|
-
return [
|
|
620
|
-
{
|
|
621
|
-
handler: value
|
|
622
|
-
}
|
|
623
|
-
];
|
|
624
|
-
}
|
|
625
|
-
return [value];
|
|
252
|
+
return loadRules$1(file, { loadModule });
|
|
626
253
|
}
|
|
627
254
|
|
|
628
255
|
async function buildManifest(options = {}) {
|
|
@@ -786,165 +413,12 @@ async function buildManifest(options = {}) {
|
|
|
786
413
|
};
|
|
787
414
|
}
|
|
788
415
|
|
|
789
|
-
const
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
}
|
|
796
|
-
return context;
|
|
797
|
-
}
|
|
798
|
-
function runWithContext(context, fn) {
|
|
799
|
-
contextStack.push(context);
|
|
800
|
-
try {
|
|
801
|
-
const result = fn();
|
|
802
|
-
if (isPromise(result)) {
|
|
803
|
-
return result.finally(() => {
|
|
804
|
-
contextStack.pop();
|
|
805
|
-
});
|
|
806
|
-
}
|
|
807
|
-
contextStack.pop();
|
|
808
|
-
return result;
|
|
809
|
-
} catch (error) {
|
|
810
|
-
contextStack.pop();
|
|
811
|
-
throw error;
|
|
812
|
-
}
|
|
813
|
-
}
|
|
814
|
-
function isPromise(value) {
|
|
815
|
-
return !!value && typeof value.then === "function";
|
|
816
|
-
}
|
|
817
|
-
function normalizeHookError(policy) {
|
|
818
|
-
if (policy === "throw" || policy === "silent") {
|
|
819
|
-
return policy;
|
|
820
|
-
}
|
|
821
|
-
return "warn";
|
|
822
|
-
}
|
|
823
|
-
function reportHookError(error, policy) {
|
|
824
|
-
if (policy === "silent") {
|
|
825
|
-
return;
|
|
826
|
-
}
|
|
827
|
-
if (policy === "warn") {
|
|
828
|
-
console.warn("[@mokup/cli] defineConfig hook failed:", error);
|
|
829
|
-
}
|
|
830
|
-
}
|
|
831
|
-
function runHookSequence(stage, hooks, policy, setStage) {
|
|
832
|
-
if (hooks.length === 0) {
|
|
833
|
-
return;
|
|
834
|
-
}
|
|
835
|
-
setStage(stage);
|
|
836
|
-
let chain = null;
|
|
837
|
-
const runHook = (hook) => {
|
|
838
|
-
try {
|
|
839
|
-
const result = hook();
|
|
840
|
-
if (isPromise(result)) {
|
|
841
|
-
return result.catch((error) => {
|
|
842
|
-
if (policy === "throw") {
|
|
843
|
-
throw error;
|
|
844
|
-
}
|
|
845
|
-
reportHookError(error, policy);
|
|
846
|
-
});
|
|
847
|
-
}
|
|
848
|
-
return void 0;
|
|
849
|
-
} catch (error) {
|
|
850
|
-
if (policy === "throw") {
|
|
851
|
-
throw error;
|
|
852
|
-
}
|
|
853
|
-
reportHookError(error, policy);
|
|
854
|
-
return void 0;
|
|
855
|
-
}
|
|
856
|
-
};
|
|
857
|
-
for (const hook of hooks) {
|
|
858
|
-
if (chain) {
|
|
859
|
-
chain = chain.then(() => runHook(hook));
|
|
860
|
-
continue;
|
|
861
|
-
}
|
|
862
|
-
const result = runHook(hook);
|
|
863
|
-
if (isPromise(result)) {
|
|
864
|
-
chain = result;
|
|
865
|
-
}
|
|
866
|
-
}
|
|
867
|
-
if (!chain) {
|
|
868
|
-
setStage("normal");
|
|
869
|
-
return;
|
|
870
|
-
}
|
|
871
|
-
return chain.finally(() => {
|
|
872
|
-
setStage("normal");
|
|
873
|
-
});
|
|
874
|
-
}
|
|
875
|
-
function attachMetadata(config, meta) {
|
|
876
|
-
Object.defineProperty(config, middlewareSymbol, {
|
|
877
|
-
value: meta,
|
|
878
|
-
enumerable: false
|
|
879
|
-
});
|
|
880
|
-
return config;
|
|
881
|
-
}
|
|
882
|
-
function normalizeConfig(value) {
|
|
883
|
-
return value && typeof value === "object" ? value : {};
|
|
884
|
-
}
|
|
885
|
-
function onBeforeAll(handler) {
|
|
886
|
-
if (typeof handler !== "function") {
|
|
887
|
-
throw new TypeError("onBeforeAll expects a function");
|
|
888
|
-
}
|
|
889
|
-
const context = getActiveContext();
|
|
890
|
-
context.hooks.pre.push(handler);
|
|
891
|
-
}
|
|
892
|
-
function onAfterAll(handler) {
|
|
893
|
-
if (typeof handler !== "function") {
|
|
894
|
-
throw new TypeError("onAfterAll expects a function");
|
|
895
|
-
}
|
|
896
|
-
const context = getActiveContext();
|
|
897
|
-
context.hooks.post.push(handler);
|
|
898
|
-
}
|
|
899
|
-
function defineConfig(input) {
|
|
900
|
-
if (typeof input === "function") {
|
|
901
|
-
const pre = [];
|
|
902
|
-
const normal = [];
|
|
903
|
-
const post = [];
|
|
904
|
-
let stage = "normal";
|
|
905
|
-
const app = {
|
|
906
|
-
use: (...handlers) => {
|
|
907
|
-
if (stage === "pre") {
|
|
908
|
-
pre.push(...handlers);
|
|
909
|
-
return;
|
|
910
|
-
}
|
|
911
|
-
if (stage === "post") {
|
|
912
|
-
post.push(...handlers);
|
|
913
|
-
return;
|
|
914
|
-
}
|
|
915
|
-
normal.push(...handlers);
|
|
916
|
-
}
|
|
917
|
-
};
|
|
918
|
-
const context = {
|
|
919
|
-
app,
|
|
920
|
-
hooks: { pre: [], post: [] },
|
|
921
|
-
setStage: (next) => {
|
|
922
|
-
stage = next;
|
|
923
|
-
}
|
|
924
|
-
};
|
|
925
|
-
const result = runWithContext(context, () => input({ app }));
|
|
926
|
-
const finalize = (value) => {
|
|
927
|
-
const config2 = normalizeConfig(value);
|
|
928
|
-
const policy = normalizeHookError(config2.hookError);
|
|
929
|
-
const preResult = runHookSequence("pre", context.hooks.pre, policy, context.setStage);
|
|
930
|
-
const runPost = () => runHookSequence("post", context.hooks.post, policy, context.setStage);
|
|
931
|
-
if (isPromise(preResult)) {
|
|
932
|
-
return preResult.then(runPost).then(() => attachMetadata(config2, { pre, normal, post }));
|
|
933
|
-
}
|
|
934
|
-
const postResult = runPost();
|
|
935
|
-
if (isPromise(postResult)) {
|
|
936
|
-
return postResult.then(() => attachMetadata(config2, { pre, normal, post }));
|
|
937
|
-
}
|
|
938
|
-
return attachMetadata(config2, { pre, normal, post });
|
|
939
|
-
};
|
|
940
|
-
if (isPromise(result)) {
|
|
941
|
-
return result.then(finalize);
|
|
942
|
-
}
|
|
943
|
-
return finalize(result);
|
|
944
|
-
}
|
|
945
|
-
const config = normalizeConfig(input);
|
|
946
|
-
return attachMetadata(config, { pre: [], normal: [], post: [] });
|
|
947
|
-
}
|
|
416
|
+
const shared = createDefineConfig({
|
|
417
|
+
logPrefix: "[@mokup/cli]"
|
|
418
|
+
});
|
|
419
|
+
const defineConfig = shared.defineConfig;
|
|
420
|
+
const onBeforeAll = shared.onBeforeAll;
|
|
421
|
+
const onAfterAll = shared.onAfterAll;
|
|
948
422
|
|
|
949
423
|
const logger = createLogger();
|
|
950
424
|
function collectValues(value, previous) {
|