@mokup/cli 1.0.5 → 1.0.7
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 +99 -11
- package/dist/index.d.cts +241 -2
- package/dist/index.d.mts +241 -2
- package/dist/index.d.ts +241 -2
- package/dist/index.mjs +99 -12
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -10,6 +10,7 @@ const esbuild = require('@mokup/shared/esbuild');
|
|
|
10
10
|
const runtime = require('@mokup/runtime');
|
|
11
11
|
const jsoncParser = require('@mokup/shared/jsonc-parser');
|
|
12
12
|
const node = require('@mokup/server/node');
|
|
13
|
+
const logger$1 = require('@mokup/shared/logger');
|
|
13
14
|
const commander = require('commander');
|
|
14
15
|
|
|
15
16
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
@@ -74,6 +75,7 @@ async function writeManifestModule(outDir, manifest) {
|
|
|
74
75
|
}
|
|
75
76
|
|
|
76
77
|
const configExtensions = [".ts", ".js", ".mjs", ".cjs"];
|
|
78
|
+
const middlewareSymbol$1 = Symbol.for("mokup.config.middlewares");
|
|
77
79
|
async function loadModule$1(file) {
|
|
78
80
|
const ext = configExtensions.find((extension) => file.endsWith(extension));
|
|
79
81
|
if (ext === ".cjs") {
|
|
@@ -134,7 +136,7 @@ async function loadConfig(file) {
|
|
|
134
136
|
}
|
|
135
137
|
return value;
|
|
136
138
|
}
|
|
137
|
-
function normalizeMiddlewares(value, source, log) {
|
|
139
|
+
function normalizeMiddlewares(value, source, log, position) {
|
|
138
140
|
if (!value) {
|
|
139
141
|
return [];
|
|
140
142
|
}
|
|
@@ -145,10 +147,22 @@ function normalizeMiddlewares(value, source, log) {
|
|
|
145
147
|
log?.(`Invalid middleware in ${source}`);
|
|
146
148
|
return;
|
|
147
149
|
}
|
|
148
|
-
middlewares.push({ file: source, index });
|
|
150
|
+
middlewares.push({ file: source, index, position });
|
|
149
151
|
});
|
|
150
152
|
return middlewares;
|
|
151
153
|
}
|
|
154
|
+
function readMiddlewareMeta(config) {
|
|
155
|
+
const value = config[middlewareSymbol$1];
|
|
156
|
+
if (!value || typeof value !== "object") {
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
const meta = value;
|
|
160
|
+
return {
|
|
161
|
+
pre: Array.isArray(meta.pre) ? meta.pre : [],
|
|
162
|
+
normal: Array.isArray(meta.normal) ? meta.normal : [],
|
|
163
|
+
post: Array.isArray(meta.post) ? meta.post : []
|
|
164
|
+
};
|
|
165
|
+
}
|
|
152
166
|
async function resolveDirectoryConfig(params) {
|
|
153
167
|
const { file, rootDir, log, configCache, fileCache } = params;
|
|
154
168
|
const resolvedRoot = pathe.normalize(rootDir);
|
|
@@ -167,7 +181,10 @@ async function resolveDirectoryConfig(params) {
|
|
|
167
181
|
current = parent;
|
|
168
182
|
}
|
|
169
183
|
chain.reverse();
|
|
170
|
-
const merged = {
|
|
184
|
+
const merged = {};
|
|
185
|
+
const preMiddlewares = [];
|
|
186
|
+
const normalMiddlewares = [];
|
|
187
|
+
const postMiddlewares = [];
|
|
171
188
|
for (const dir of chain) {
|
|
172
189
|
const configPath = await findConfigFile(dir, fileCache);
|
|
173
190
|
if (!configPath) {
|
|
@@ -203,12 +220,48 @@ async function resolveDirectoryConfig(params) {
|
|
|
203
220
|
if (typeof config.exclude !== "undefined") {
|
|
204
221
|
merged.exclude = config.exclude;
|
|
205
222
|
}
|
|
206
|
-
const
|
|
207
|
-
|
|
208
|
-
|
|
223
|
+
const meta = readMiddlewareMeta(config);
|
|
224
|
+
const normalizedPre = normalizeMiddlewares(
|
|
225
|
+
meta?.pre,
|
|
226
|
+
configPath,
|
|
227
|
+
log,
|
|
228
|
+
"pre"
|
|
229
|
+
);
|
|
230
|
+
const normalizedNormal = normalizeMiddlewares(
|
|
231
|
+
meta?.normal,
|
|
232
|
+
configPath,
|
|
233
|
+
log,
|
|
234
|
+
"normal"
|
|
235
|
+
);
|
|
236
|
+
const normalizedLegacy = normalizeMiddlewares(
|
|
237
|
+
config.middleware,
|
|
238
|
+
configPath,
|
|
239
|
+
log,
|
|
240
|
+
"normal"
|
|
241
|
+
);
|
|
242
|
+
const normalizedPost = normalizeMiddlewares(
|
|
243
|
+
meta?.post,
|
|
244
|
+
configPath,
|
|
245
|
+
log,
|
|
246
|
+
"post"
|
|
247
|
+
);
|
|
248
|
+
if (normalizedPre.length > 0) {
|
|
249
|
+
preMiddlewares.push(...normalizedPre);
|
|
250
|
+
}
|
|
251
|
+
if (normalizedNormal.length > 0) {
|
|
252
|
+
normalMiddlewares.push(...normalizedNormal);
|
|
253
|
+
}
|
|
254
|
+
if (normalizedLegacy.length > 0) {
|
|
255
|
+
normalMiddlewares.push(...normalizedLegacy);
|
|
256
|
+
}
|
|
257
|
+
if (normalizedPost.length > 0) {
|
|
258
|
+
postMiddlewares.push(...normalizedPost);
|
|
209
259
|
}
|
|
210
260
|
}
|
|
211
|
-
return
|
|
261
|
+
return {
|
|
262
|
+
...merged,
|
|
263
|
+
middlewares: [...preMiddlewares, ...normalMiddlewares, ...postMiddlewares]
|
|
264
|
+
};
|
|
212
265
|
}
|
|
213
266
|
|
|
214
267
|
function toPosix(value) {
|
|
@@ -763,6 +816,40 @@ async function buildManifest(options = {}) {
|
|
|
763
816
|
};
|
|
764
817
|
}
|
|
765
818
|
|
|
819
|
+
const middlewareSymbol = Symbol.for("mokup.config.middlewares");
|
|
820
|
+
function createRegistry(list) {
|
|
821
|
+
return {
|
|
822
|
+
use: (...handlers) => {
|
|
823
|
+
list.push(...handlers);
|
|
824
|
+
}
|
|
825
|
+
};
|
|
826
|
+
}
|
|
827
|
+
function attachMetadata(config, meta) {
|
|
828
|
+
Object.defineProperty(config, middlewareSymbol, {
|
|
829
|
+
value: meta,
|
|
830
|
+
enumerable: false
|
|
831
|
+
});
|
|
832
|
+
return config;
|
|
833
|
+
}
|
|
834
|
+
function defineConfig(input) {
|
|
835
|
+
if (typeof input === "function") {
|
|
836
|
+
const pre = [];
|
|
837
|
+
const normal = [];
|
|
838
|
+
const post = [];
|
|
839
|
+
const context = {
|
|
840
|
+
pre: createRegistry(pre),
|
|
841
|
+
normal: createRegistry(normal),
|
|
842
|
+
post: createRegistry(post)
|
|
843
|
+
};
|
|
844
|
+
const result = input(context);
|
|
845
|
+
const config2 = result && typeof result === "object" ? result : {};
|
|
846
|
+
return attachMetadata(config2, { pre, normal, post });
|
|
847
|
+
}
|
|
848
|
+
const config = input && typeof input === "object" ? input : {};
|
|
849
|
+
return attachMetadata(config, { pre: [], normal: [], post: [] });
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
const logger = logger$1.createLogger();
|
|
766
853
|
function collectValues(value, previous) {
|
|
767
854
|
return [...previous ?? [], value];
|
|
768
855
|
}
|
|
@@ -775,7 +862,7 @@ function toBuildOptions(options) {
|
|
|
775
862
|
const buildOptions = {
|
|
776
863
|
handlers: options.handlers !== false,
|
|
777
864
|
log: (message) => {
|
|
778
|
-
|
|
865
|
+
logger.info(message);
|
|
779
866
|
}
|
|
780
867
|
};
|
|
781
868
|
if (options.dir && options.dir.length > 0) {
|
|
@@ -846,7 +933,7 @@ function createCli() {
|
|
|
846
933
|
const host = entry.host ?? "localhost";
|
|
847
934
|
const port = entry.port ?? 8080;
|
|
848
935
|
const playgroundEnabled = playground !== false;
|
|
849
|
-
const playgroundPath = "/
|
|
936
|
+
const playgroundPath = "/__mokup";
|
|
850
937
|
const server = await node.createFetchServer({
|
|
851
938
|
entries: entry,
|
|
852
939
|
playground
|
|
@@ -860,9 +947,9 @@ function createCli() {
|
|
|
860
947
|
(info) => {
|
|
861
948
|
const resolvedHost = typeof info === "string" ? host : info?.address ?? host;
|
|
862
949
|
const resolvedPort = typeof info === "string" ? port : info?.port ?? port;
|
|
863
|
-
|
|
950
|
+
logger.info(`Mock server ready at http://${resolvedHost}:${resolvedPort}`);
|
|
864
951
|
if (playgroundEnabled) {
|
|
865
|
-
|
|
952
|
+
logger.info(`Playground at http://${resolvedHost}:${resolvedPort}${playgroundPath}`);
|
|
866
953
|
}
|
|
867
954
|
}
|
|
868
955
|
);
|
|
@@ -904,4 +991,5 @@ async function runCli(argv = process__default.argv) {
|
|
|
904
991
|
|
|
905
992
|
exports.buildManifest = buildManifest;
|
|
906
993
|
exports.createCli = createCli;
|
|
994
|
+
exports.defineConfig = defineConfig;
|
|
907
995
|
exports.runCli = runCli;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,25 +1,264 @@
|
|
|
1
1
|
import { Manifest } from '@mokup/runtime';
|
|
2
|
+
import { MiddlewareHandler } from '@mokup/shared/hono';
|
|
2
3
|
import { Command } from 'commander';
|
|
3
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Options for building a mokup manifest.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* import type { BuildOptions } from '@mokup/cli'
|
|
10
|
+
*
|
|
11
|
+
* const options: BuildOptions = {
|
|
12
|
+
* dir: 'mock',
|
|
13
|
+
* outDir: '.mokup',
|
|
14
|
+
* }
|
|
15
|
+
*/
|
|
4
16
|
interface BuildOptions {
|
|
17
|
+
/**
|
|
18
|
+
* Directory or directories to scan for mock files.
|
|
19
|
+
*
|
|
20
|
+
* @default "mock"
|
|
21
|
+
*/
|
|
5
22
|
dir?: string | string[];
|
|
23
|
+
/**
|
|
24
|
+
* Output directory for manifest artifacts.
|
|
25
|
+
*
|
|
26
|
+
* @default ".mokup"
|
|
27
|
+
*/
|
|
6
28
|
outDir?: string;
|
|
29
|
+
/**
|
|
30
|
+
* URL prefix to apply to generated routes.
|
|
31
|
+
*
|
|
32
|
+
* @default ""
|
|
33
|
+
*/
|
|
7
34
|
prefix?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Include filter for files.
|
|
37
|
+
*
|
|
38
|
+
* @default undefined
|
|
39
|
+
*/
|
|
8
40
|
include?: RegExp | RegExp[];
|
|
41
|
+
/**
|
|
42
|
+
* Exclude filter for files.
|
|
43
|
+
*
|
|
44
|
+
* @default undefined
|
|
45
|
+
*/
|
|
9
46
|
exclude?: RegExp | RegExp[];
|
|
47
|
+
/**
|
|
48
|
+
* Ignore file or folder prefixes.
|
|
49
|
+
*
|
|
50
|
+
* @default ["."]
|
|
51
|
+
*/
|
|
10
52
|
ignorePrefix?: string | string[];
|
|
53
|
+
/**
|
|
54
|
+
* Emit handler bundles for module-based responses.
|
|
55
|
+
*
|
|
56
|
+
* @default true
|
|
57
|
+
*/
|
|
11
58
|
handlers?: boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Project root used to resolve paths.
|
|
61
|
+
*
|
|
62
|
+
* @default process.cwd()
|
|
63
|
+
*/
|
|
12
64
|
root?: string;
|
|
65
|
+
/**
|
|
66
|
+
* Optional logger for build messages.
|
|
67
|
+
*
|
|
68
|
+
* @default undefined
|
|
69
|
+
*/
|
|
13
70
|
log?: (message: string) => void;
|
|
14
71
|
}
|
|
72
|
+
/**
|
|
73
|
+
* Route rule shape used in build-time resolution.
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* import type { RouteRule } from '@mokup/cli'
|
|
77
|
+
*
|
|
78
|
+
* const rule: RouteRule = { handler: { ok: true } }
|
|
79
|
+
*/
|
|
80
|
+
interface RouteRule {
|
|
81
|
+
/** Route handler or static value. */
|
|
82
|
+
handler: unknown;
|
|
83
|
+
/**
|
|
84
|
+
* Enable or disable this rule.
|
|
85
|
+
*
|
|
86
|
+
* @default true
|
|
87
|
+
*/
|
|
88
|
+
enabled?: boolean;
|
|
89
|
+
/**
|
|
90
|
+
* Override response status code.
|
|
91
|
+
*
|
|
92
|
+
* @default 200
|
|
93
|
+
*/
|
|
94
|
+
status?: number;
|
|
95
|
+
/**
|
|
96
|
+
* Additional response headers.
|
|
97
|
+
*
|
|
98
|
+
* @default {}
|
|
99
|
+
*/
|
|
100
|
+
headers?: Record<string, string>;
|
|
101
|
+
/**
|
|
102
|
+
* Delay in milliseconds before responding.
|
|
103
|
+
*
|
|
104
|
+
* @default 0
|
|
105
|
+
*/
|
|
106
|
+
delay?: number;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Directory-level config used during manifest build.
|
|
110
|
+
*
|
|
111
|
+
* @example
|
|
112
|
+
* import type { RouteDirectoryConfig } from '@mokup/cli'
|
|
113
|
+
*
|
|
114
|
+
* const config: RouteDirectoryConfig = {
|
|
115
|
+
* headers: { 'x-mokup': 'dir' },
|
|
116
|
+
* }
|
|
117
|
+
*/
|
|
118
|
+
interface RouteDirectoryConfig {
|
|
119
|
+
/**
|
|
120
|
+
* Headers applied to routes in this directory.
|
|
121
|
+
*
|
|
122
|
+
* @default {}
|
|
123
|
+
*/
|
|
124
|
+
headers?: Record<string, string>;
|
|
125
|
+
/**
|
|
126
|
+
* Default status code override.
|
|
127
|
+
*
|
|
128
|
+
* @default 200
|
|
129
|
+
*/
|
|
130
|
+
status?: number;
|
|
131
|
+
/**
|
|
132
|
+
* Default delay in milliseconds.
|
|
133
|
+
*
|
|
134
|
+
* @default 0
|
|
135
|
+
*/
|
|
136
|
+
delay?: number;
|
|
137
|
+
/**
|
|
138
|
+
* Enable or disable this directory.
|
|
139
|
+
*
|
|
140
|
+
* @default true
|
|
141
|
+
*/
|
|
142
|
+
enabled?: boolean;
|
|
143
|
+
/**
|
|
144
|
+
* Ignore prefixes applied to files in this directory.
|
|
145
|
+
*
|
|
146
|
+
* @default ["."]
|
|
147
|
+
*/
|
|
148
|
+
ignorePrefix?: string | string[];
|
|
149
|
+
/**
|
|
150
|
+
* Include filter for files.
|
|
151
|
+
*
|
|
152
|
+
* @default undefined
|
|
153
|
+
*/
|
|
154
|
+
include?: RegExp | RegExp[];
|
|
155
|
+
/**
|
|
156
|
+
* Exclude filter for files.
|
|
157
|
+
*
|
|
158
|
+
* @default undefined
|
|
159
|
+
*/
|
|
160
|
+
exclude?: RegExp | RegExp[];
|
|
161
|
+
/**
|
|
162
|
+
* Middleware for the directory.
|
|
163
|
+
*
|
|
164
|
+
* @default undefined
|
|
165
|
+
*/
|
|
166
|
+
middleware?: MiddlewareHandler | MiddlewareHandler[];
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Middleware execution position.
|
|
170
|
+
*
|
|
171
|
+
* @example
|
|
172
|
+
* import type { MiddlewarePosition } from '@mokup/cli'
|
|
173
|
+
*
|
|
174
|
+
* const position: MiddlewarePosition = 'pre'
|
|
175
|
+
*/
|
|
176
|
+
type MiddlewarePosition = 'pre' | 'normal' | 'post';
|
|
177
|
+
/**
|
|
178
|
+
* Middleware registry used by defineConfig.
|
|
179
|
+
*
|
|
180
|
+
* @example
|
|
181
|
+
* import type { MiddlewareRegistry } from '@mokup/cli'
|
|
182
|
+
*
|
|
183
|
+
* const registry: MiddlewareRegistry = { use: () => {} }
|
|
184
|
+
*/
|
|
185
|
+
interface MiddlewareRegistry {
|
|
186
|
+
use: (...handlers: MiddlewareHandler[]) => void;
|
|
187
|
+
}
|
|
15
188
|
|
|
189
|
+
/**
|
|
190
|
+
* Build and write a mokup manifest to disk.
|
|
191
|
+
*
|
|
192
|
+
* @param options - Build options.
|
|
193
|
+
* @returns Build output metadata.
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* import { buildManifest } from '@mokup/cli'
|
|
197
|
+
*
|
|
198
|
+
* const result = await buildManifest({ dir: 'mock', outDir: '.mokup' })
|
|
199
|
+
*/
|
|
16
200
|
declare function buildManifest(options?: BuildOptions): Promise<{
|
|
17
201
|
manifest: Manifest;
|
|
18
202
|
manifestPath: string;
|
|
19
203
|
}>;
|
|
20
204
|
|
|
205
|
+
type DefineConfigFactory = (context: {
|
|
206
|
+
pre: MiddlewareRegistry;
|
|
207
|
+
normal: MiddlewareRegistry;
|
|
208
|
+
post: MiddlewareRegistry;
|
|
209
|
+
}) => RouteDirectoryConfig | void;
|
|
210
|
+
/**
|
|
211
|
+
* Define a directory config with Hono-style middleware registration.
|
|
212
|
+
*
|
|
213
|
+
* @param input - Config object or factory callback.
|
|
214
|
+
* @returns Route directory config with middleware metadata.
|
|
215
|
+
*
|
|
216
|
+
* @example
|
|
217
|
+
* import { defineConfig } from '@mokup/cli'
|
|
218
|
+
*
|
|
219
|
+
* export default defineConfig(({ pre, normal, post }) => {
|
|
220
|
+
* pre.use(async (c, next) => {
|
|
221
|
+
* c.header('x-before', '1')
|
|
222
|
+
* await next()
|
|
223
|
+
* })
|
|
224
|
+
*
|
|
225
|
+
* normal.use(async (_c, next) => {
|
|
226
|
+
* await next()
|
|
227
|
+
* })
|
|
228
|
+
*
|
|
229
|
+
* post.use(async (c, next) => {
|
|
230
|
+
* await next()
|
|
231
|
+
* c.header('x-after', '1')
|
|
232
|
+
* })
|
|
233
|
+
*
|
|
234
|
+
* return { delay: 120 }
|
|
235
|
+
* })
|
|
236
|
+
*/
|
|
237
|
+
declare function defineConfig(input: RouteDirectoryConfig | DefineConfigFactory): RouteDirectoryConfig;
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Create the mokup CLI program instance.
|
|
241
|
+
*
|
|
242
|
+
* @returns A configured CLI program.
|
|
243
|
+
*
|
|
244
|
+
* @example
|
|
245
|
+
* import { createCli } from '@mokup/cli'
|
|
246
|
+
*
|
|
247
|
+
* const cli = createCli()
|
|
248
|
+
*/
|
|
21
249
|
declare function createCli(): Command;
|
|
250
|
+
/**
|
|
251
|
+
* Run the mokup CLI with the provided argv.
|
|
252
|
+
*
|
|
253
|
+
* @param argv - CLI arguments.
|
|
254
|
+
* @returns Exit code or void.
|
|
255
|
+
*
|
|
256
|
+
* @example
|
|
257
|
+
* import { runCli } from '@mokup/cli'
|
|
258
|
+
*
|
|
259
|
+
* await runCli(['node', 'mokup', 'build', '--dir', 'mock'])
|
|
260
|
+
*/
|
|
22
261
|
declare function runCli(argv?: string[]): Promise<void>;
|
|
23
262
|
|
|
24
|
-
export { buildManifest, createCli, runCli };
|
|
25
|
-
export type { BuildOptions };
|
|
263
|
+
export { buildManifest, createCli, defineConfig, runCli };
|
|
264
|
+
export type { BuildOptions, MiddlewarePosition, MiddlewareRegistry, RouteDirectoryConfig, RouteRule };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,25 +1,264 @@
|
|
|
1
1
|
import { Manifest } from '@mokup/runtime';
|
|
2
|
+
import { MiddlewareHandler } from '@mokup/shared/hono';
|
|
2
3
|
import { Command } from 'commander';
|
|
3
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Options for building a mokup manifest.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* import type { BuildOptions } from '@mokup/cli'
|
|
10
|
+
*
|
|
11
|
+
* const options: BuildOptions = {
|
|
12
|
+
* dir: 'mock',
|
|
13
|
+
* outDir: '.mokup',
|
|
14
|
+
* }
|
|
15
|
+
*/
|
|
4
16
|
interface BuildOptions {
|
|
17
|
+
/**
|
|
18
|
+
* Directory or directories to scan for mock files.
|
|
19
|
+
*
|
|
20
|
+
* @default "mock"
|
|
21
|
+
*/
|
|
5
22
|
dir?: string | string[];
|
|
23
|
+
/**
|
|
24
|
+
* Output directory for manifest artifacts.
|
|
25
|
+
*
|
|
26
|
+
* @default ".mokup"
|
|
27
|
+
*/
|
|
6
28
|
outDir?: string;
|
|
29
|
+
/**
|
|
30
|
+
* URL prefix to apply to generated routes.
|
|
31
|
+
*
|
|
32
|
+
* @default ""
|
|
33
|
+
*/
|
|
7
34
|
prefix?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Include filter for files.
|
|
37
|
+
*
|
|
38
|
+
* @default undefined
|
|
39
|
+
*/
|
|
8
40
|
include?: RegExp | RegExp[];
|
|
41
|
+
/**
|
|
42
|
+
* Exclude filter for files.
|
|
43
|
+
*
|
|
44
|
+
* @default undefined
|
|
45
|
+
*/
|
|
9
46
|
exclude?: RegExp | RegExp[];
|
|
47
|
+
/**
|
|
48
|
+
* Ignore file or folder prefixes.
|
|
49
|
+
*
|
|
50
|
+
* @default ["."]
|
|
51
|
+
*/
|
|
10
52
|
ignorePrefix?: string | string[];
|
|
53
|
+
/**
|
|
54
|
+
* Emit handler bundles for module-based responses.
|
|
55
|
+
*
|
|
56
|
+
* @default true
|
|
57
|
+
*/
|
|
11
58
|
handlers?: boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Project root used to resolve paths.
|
|
61
|
+
*
|
|
62
|
+
* @default process.cwd()
|
|
63
|
+
*/
|
|
12
64
|
root?: string;
|
|
65
|
+
/**
|
|
66
|
+
* Optional logger for build messages.
|
|
67
|
+
*
|
|
68
|
+
* @default undefined
|
|
69
|
+
*/
|
|
13
70
|
log?: (message: string) => void;
|
|
14
71
|
}
|
|
72
|
+
/**
|
|
73
|
+
* Route rule shape used in build-time resolution.
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* import type { RouteRule } from '@mokup/cli'
|
|
77
|
+
*
|
|
78
|
+
* const rule: RouteRule = { handler: { ok: true } }
|
|
79
|
+
*/
|
|
80
|
+
interface RouteRule {
|
|
81
|
+
/** Route handler or static value. */
|
|
82
|
+
handler: unknown;
|
|
83
|
+
/**
|
|
84
|
+
* Enable or disable this rule.
|
|
85
|
+
*
|
|
86
|
+
* @default true
|
|
87
|
+
*/
|
|
88
|
+
enabled?: boolean;
|
|
89
|
+
/**
|
|
90
|
+
* Override response status code.
|
|
91
|
+
*
|
|
92
|
+
* @default 200
|
|
93
|
+
*/
|
|
94
|
+
status?: number;
|
|
95
|
+
/**
|
|
96
|
+
* Additional response headers.
|
|
97
|
+
*
|
|
98
|
+
* @default {}
|
|
99
|
+
*/
|
|
100
|
+
headers?: Record<string, string>;
|
|
101
|
+
/**
|
|
102
|
+
* Delay in milliseconds before responding.
|
|
103
|
+
*
|
|
104
|
+
* @default 0
|
|
105
|
+
*/
|
|
106
|
+
delay?: number;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Directory-level config used during manifest build.
|
|
110
|
+
*
|
|
111
|
+
* @example
|
|
112
|
+
* import type { RouteDirectoryConfig } from '@mokup/cli'
|
|
113
|
+
*
|
|
114
|
+
* const config: RouteDirectoryConfig = {
|
|
115
|
+
* headers: { 'x-mokup': 'dir' },
|
|
116
|
+
* }
|
|
117
|
+
*/
|
|
118
|
+
interface RouteDirectoryConfig {
|
|
119
|
+
/**
|
|
120
|
+
* Headers applied to routes in this directory.
|
|
121
|
+
*
|
|
122
|
+
* @default {}
|
|
123
|
+
*/
|
|
124
|
+
headers?: Record<string, string>;
|
|
125
|
+
/**
|
|
126
|
+
* Default status code override.
|
|
127
|
+
*
|
|
128
|
+
* @default 200
|
|
129
|
+
*/
|
|
130
|
+
status?: number;
|
|
131
|
+
/**
|
|
132
|
+
* Default delay in milliseconds.
|
|
133
|
+
*
|
|
134
|
+
* @default 0
|
|
135
|
+
*/
|
|
136
|
+
delay?: number;
|
|
137
|
+
/**
|
|
138
|
+
* Enable or disable this directory.
|
|
139
|
+
*
|
|
140
|
+
* @default true
|
|
141
|
+
*/
|
|
142
|
+
enabled?: boolean;
|
|
143
|
+
/**
|
|
144
|
+
* Ignore prefixes applied to files in this directory.
|
|
145
|
+
*
|
|
146
|
+
* @default ["."]
|
|
147
|
+
*/
|
|
148
|
+
ignorePrefix?: string | string[];
|
|
149
|
+
/**
|
|
150
|
+
* Include filter for files.
|
|
151
|
+
*
|
|
152
|
+
* @default undefined
|
|
153
|
+
*/
|
|
154
|
+
include?: RegExp | RegExp[];
|
|
155
|
+
/**
|
|
156
|
+
* Exclude filter for files.
|
|
157
|
+
*
|
|
158
|
+
* @default undefined
|
|
159
|
+
*/
|
|
160
|
+
exclude?: RegExp | RegExp[];
|
|
161
|
+
/**
|
|
162
|
+
* Middleware for the directory.
|
|
163
|
+
*
|
|
164
|
+
* @default undefined
|
|
165
|
+
*/
|
|
166
|
+
middleware?: MiddlewareHandler | MiddlewareHandler[];
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Middleware execution position.
|
|
170
|
+
*
|
|
171
|
+
* @example
|
|
172
|
+
* import type { MiddlewarePosition } from '@mokup/cli'
|
|
173
|
+
*
|
|
174
|
+
* const position: MiddlewarePosition = 'pre'
|
|
175
|
+
*/
|
|
176
|
+
type MiddlewarePosition = 'pre' | 'normal' | 'post';
|
|
177
|
+
/**
|
|
178
|
+
* Middleware registry used by defineConfig.
|
|
179
|
+
*
|
|
180
|
+
* @example
|
|
181
|
+
* import type { MiddlewareRegistry } from '@mokup/cli'
|
|
182
|
+
*
|
|
183
|
+
* const registry: MiddlewareRegistry = { use: () => {} }
|
|
184
|
+
*/
|
|
185
|
+
interface MiddlewareRegistry {
|
|
186
|
+
use: (...handlers: MiddlewareHandler[]) => void;
|
|
187
|
+
}
|
|
15
188
|
|
|
189
|
+
/**
|
|
190
|
+
* Build and write a mokup manifest to disk.
|
|
191
|
+
*
|
|
192
|
+
* @param options - Build options.
|
|
193
|
+
* @returns Build output metadata.
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* import { buildManifest } from '@mokup/cli'
|
|
197
|
+
*
|
|
198
|
+
* const result = await buildManifest({ dir: 'mock', outDir: '.mokup' })
|
|
199
|
+
*/
|
|
16
200
|
declare function buildManifest(options?: BuildOptions): Promise<{
|
|
17
201
|
manifest: Manifest;
|
|
18
202
|
manifestPath: string;
|
|
19
203
|
}>;
|
|
20
204
|
|
|
205
|
+
type DefineConfigFactory = (context: {
|
|
206
|
+
pre: MiddlewareRegistry;
|
|
207
|
+
normal: MiddlewareRegistry;
|
|
208
|
+
post: MiddlewareRegistry;
|
|
209
|
+
}) => RouteDirectoryConfig | void;
|
|
210
|
+
/**
|
|
211
|
+
* Define a directory config with Hono-style middleware registration.
|
|
212
|
+
*
|
|
213
|
+
* @param input - Config object or factory callback.
|
|
214
|
+
* @returns Route directory config with middleware metadata.
|
|
215
|
+
*
|
|
216
|
+
* @example
|
|
217
|
+
* import { defineConfig } from '@mokup/cli'
|
|
218
|
+
*
|
|
219
|
+
* export default defineConfig(({ pre, normal, post }) => {
|
|
220
|
+
* pre.use(async (c, next) => {
|
|
221
|
+
* c.header('x-before', '1')
|
|
222
|
+
* await next()
|
|
223
|
+
* })
|
|
224
|
+
*
|
|
225
|
+
* normal.use(async (_c, next) => {
|
|
226
|
+
* await next()
|
|
227
|
+
* })
|
|
228
|
+
*
|
|
229
|
+
* post.use(async (c, next) => {
|
|
230
|
+
* await next()
|
|
231
|
+
* c.header('x-after', '1')
|
|
232
|
+
* })
|
|
233
|
+
*
|
|
234
|
+
* return { delay: 120 }
|
|
235
|
+
* })
|
|
236
|
+
*/
|
|
237
|
+
declare function defineConfig(input: RouteDirectoryConfig | DefineConfigFactory): RouteDirectoryConfig;
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Create the mokup CLI program instance.
|
|
241
|
+
*
|
|
242
|
+
* @returns A configured CLI program.
|
|
243
|
+
*
|
|
244
|
+
* @example
|
|
245
|
+
* import { createCli } from '@mokup/cli'
|
|
246
|
+
*
|
|
247
|
+
* const cli = createCli()
|
|
248
|
+
*/
|
|
21
249
|
declare function createCli(): Command;
|
|
250
|
+
/**
|
|
251
|
+
* Run the mokup CLI with the provided argv.
|
|
252
|
+
*
|
|
253
|
+
* @param argv - CLI arguments.
|
|
254
|
+
* @returns Exit code or void.
|
|
255
|
+
*
|
|
256
|
+
* @example
|
|
257
|
+
* import { runCli } from '@mokup/cli'
|
|
258
|
+
*
|
|
259
|
+
* await runCli(['node', 'mokup', 'build', '--dir', 'mock'])
|
|
260
|
+
*/
|
|
22
261
|
declare function runCli(argv?: string[]): Promise<void>;
|
|
23
262
|
|
|
24
|
-
export { buildManifest, createCli, runCli };
|
|
25
|
-
export type { BuildOptions };
|
|
263
|
+
export { buildManifest, createCli, defineConfig, runCli };
|
|
264
|
+
export type { BuildOptions, MiddlewarePosition, MiddlewareRegistry, RouteDirectoryConfig, RouteRule };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,25 +1,264 @@
|
|
|
1
1
|
import { Manifest } from '@mokup/runtime';
|
|
2
|
+
import { MiddlewareHandler } from '@mokup/shared/hono';
|
|
2
3
|
import { Command } from 'commander';
|
|
3
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Options for building a mokup manifest.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* import type { BuildOptions } from '@mokup/cli'
|
|
10
|
+
*
|
|
11
|
+
* const options: BuildOptions = {
|
|
12
|
+
* dir: 'mock',
|
|
13
|
+
* outDir: '.mokup',
|
|
14
|
+
* }
|
|
15
|
+
*/
|
|
4
16
|
interface BuildOptions {
|
|
17
|
+
/**
|
|
18
|
+
* Directory or directories to scan for mock files.
|
|
19
|
+
*
|
|
20
|
+
* @default "mock"
|
|
21
|
+
*/
|
|
5
22
|
dir?: string | string[];
|
|
23
|
+
/**
|
|
24
|
+
* Output directory for manifest artifacts.
|
|
25
|
+
*
|
|
26
|
+
* @default ".mokup"
|
|
27
|
+
*/
|
|
6
28
|
outDir?: string;
|
|
29
|
+
/**
|
|
30
|
+
* URL prefix to apply to generated routes.
|
|
31
|
+
*
|
|
32
|
+
* @default ""
|
|
33
|
+
*/
|
|
7
34
|
prefix?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Include filter for files.
|
|
37
|
+
*
|
|
38
|
+
* @default undefined
|
|
39
|
+
*/
|
|
8
40
|
include?: RegExp | RegExp[];
|
|
41
|
+
/**
|
|
42
|
+
* Exclude filter for files.
|
|
43
|
+
*
|
|
44
|
+
* @default undefined
|
|
45
|
+
*/
|
|
9
46
|
exclude?: RegExp | RegExp[];
|
|
47
|
+
/**
|
|
48
|
+
* Ignore file or folder prefixes.
|
|
49
|
+
*
|
|
50
|
+
* @default ["."]
|
|
51
|
+
*/
|
|
10
52
|
ignorePrefix?: string | string[];
|
|
53
|
+
/**
|
|
54
|
+
* Emit handler bundles for module-based responses.
|
|
55
|
+
*
|
|
56
|
+
* @default true
|
|
57
|
+
*/
|
|
11
58
|
handlers?: boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Project root used to resolve paths.
|
|
61
|
+
*
|
|
62
|
+
* @default process.cwd()
|
|
63
|
+
*/
|
|
12
64
|
root?: string;
|
|
65
|
+
/**
|
|
66
|
+
* Optional logger for build messages.
|
|
67
|
+
*
|
|
68
|
+
* @default undefined
|
|
69
|
+
*/
|
|
13
70
|
log?: (message: string) => void;
|
|
14
71
|
}
|
|
72
|
+
/**
|
|
73
|
+
* Route rule shape used in build-time resolution.
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* import type { RouteRule } from '@mokup/cli'
|
|
77
|
+
*
|
|
78
|
+
* const rule: RouteRule = { handler: { ok: true } }
|
|
79
|
+
*/
|
|
80
|
+
interface RouteRule {
|
|
81
|
+
/** Route handler or static value. */
|
|
82
|
+
handler: unknown;
|
|
83
|
+
/**
|
|
84
|
+
* Enable or disable this rule.
|
|
85
|
+
*
|
|
86
|
+
* @default true
|
|
87
|
+
*/
|
|
88
|
+
enabled?: boolean;
|
|
89
|
+
/**
|
|
90
|
+
* Override response status code.
|
|
91
|
+
*
|
|
92
|
+
* @default 200
|
|
93
|
+
*/
|
|
94
|
+
status?: number;
|
|
95
|
+
/**
|
|
96
|
+
* Additional response headers.
|
|
97
|
+
*
|
|
98
|
+
* @default {}
|
|
99
|
+
*/
|
|
100
|
+
headers?: Record<string, string>;
|
|
101
|
+
/**
|
|
102
|
+
* Delay in milliseconds before responding.
|
|
103
|
+
*
|
|
104
|
+
* @default 0
|
|
105
|
+
*/
|
|
106
|
+
delay?: number;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Directory-level config used during manifest build.
|
|
110
|
+
*
|
|
111
|
+
* @example
|
|
112
|
+
* import type { RouteDirectoryConfig } from '@mokup/cli'
|
|
113
|
+
*
|
|
114
|
+
* const config: RouteDirectoryConfig = {
|
|
115
|
+
* headers: { 'x-mokup': 'dir' },
|
|
116
|
+
* }
|
|
117
|
+
*/
|
|
118
|
+
interface RouteDirectoryConfig {
|
|
119
|
+
/**
|
|
120
|
+
* Headers applied to routes in this directory.
|
|
121
|
+
*
|
|
122
|
+
* @default {}
|
|
123
|
+
*/
|
|
124
|
+
headers?: Record<string, string>;
|
|
125
|
+
/**
|
|
126
|
+
* Default status code override.
|
|
127
|
+
*
|
|
128
|
+
* @default 200
|
|
129
|
+
*/
|
|
130
|
+
status?: number;
|
|
131
|
+
/**
|
|
132
|
+
* Default delay in milliseconds.
|
|
133
|
+
*
|
|
134
|
+
* @default 0
|
|
135
|
+
*/
|
|
136
|
+
delay?: number;
|
|
137
|
+
/**
|
|
138
|
+
* Enable or disable this directory.
|
|
139
|
+
*
|
|
140
|
+
* @default true
|
|
141
|
+
*/
|
|
142
|
+
enabled?: boolean;
|
|
143
|
+
/**
|
|
144
|
+
* Ignore prefixes applied to files in this directory.
|
|
145
|
+
*
|
|
146
|
+
* @default ["."]
|
|
147
|
+
*/
|
|
148
|
+
ignorePrefix?: string | string[];
|
|
149
|
+
/**
|
|
150
|
+
* Include filter for files.
|
|
151
|
+
*
|
|
152
|
+
* @default undefined
|
|
153
|
+
*/
|
|
154
|
+
include?: RegExp | RegExp[];
|
|
155
|
+
/**
|
|
156
|
+
* Exclude filter for files.
|
|
157
|
+
*
|
|
158
|
+
* @default undefined
|
|
159
|
+
*/
|
|
160
|
+
exclude?: RegExp | RegExp[];
|
|
161
|
+
/**
|
|
162
|
+
* Middleware for the directory.
|
|
163
|
+
*
|
|
164
|
+
* @default undefined
|
|
165
|
+
*/
|
|
166
|
+
middleware?: MiddlewareHandler | MiddlewareHandler[];
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Middleware execution position.
|
|
170
|
+
*
|
|
171
|
+
* @example
|
|
172
|
+
* import type { MiddlewarePosition } from '@mokup/cli'
|
|
173
|
+
*
|
|
174
|
+
* const position: MiddlewarePosition = 'pre'
|
|
175
|
+
*/
|
|
176
|
+
type MiddlewarePosition = 'pre' | 'normal' | 'post';
|
|
177
|
+
/**
|
|
178
|
+
* Middleware registry used by defineConfig.
|
|
179
|
+
*
|
|
180
|
+
* @example
|
|
181
|
+
* import type { MiddlewareRegistry } from '@mokup/cli'
|
|
182
|
+
*
|
|
183
|
+
* const registry: MiddlewareRegistry = { use: () => {} }
|
|
184
|
+
*/
|
|
185
|
+
interface MiddlewareRegistry {
|
|
186
|
+
use: (...handlers: MiddlewareHandler[]) => void;
|
|
187
|
+
}
|
|
15
188
|
|
|
189
|
+
/**
|
|
190
|
+
* Build and write a mokup manifest to disk.
|
|
191
|
+
*
|
|
192
|
+
* @param options - Build options.
|
|
193
|
+
* @returns Build output metadata.
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* import { buildManifest } from '@mokup/cli'
|
|
197
|
+
*
|
|
198
|
+
* const result = await buildManifest({ dir: 'mock', outDir: '.mokup' })
|
|
199
|
+
*/
|
|
16
200
|
declare function buildManifest(options?: BuildOptions): Promise<{
|
|
17
201
|
manifest: Manifest;
|
|
18
202
|
manifestPath: string;
|
|
19
203
|
}>;
|
|
20
204
|
|
|
205
|
+
type DefineConfigFactory = (context: {
|
|
206
|
+
pre: MiddlewareRegistry;
|
|
207
|
+
normal: MiddlewareRegistry;
|
|
208
|
+
post: MiddlewareRegistry;
|
|
209
|
+
}) => RouteDirectoryConfig | void;
|
|
210
|
+
/**
|
|
211
|
+
* Define a directory config with Hono-style middleware registration.
|
|
212
|
+
*
|
|
213
|
+
* @param input - Config object or factory callback.
|
|
214
|
+
* @returns Route directory config with middleware metadata.
|
|
215
|
+
*
|
|
216
|
+
* @example
|
|
217
|
+
* import { defineConfig } from '@mokup/cli'
|
|
218
|
+
*
|
|
219
|
+
* export default defineConfig(({ pre, normal, post }) => {
|
|
220
|
+
* pre.use(async (c, next) => {
|
|
221
|
+
* c.header('x-before', '1')
|
|
222
|
+
* await next()
|
|
223
|
+
* })
|
|
224
|
+
*
|
|
225
|
+
* normal.use(async (_c, next) => {
|
|
226
|
+
* await next()
|
|
227
|
+
* })
|
|
228
|
+
*
|
|
229
|
+
* post.use(async (c, next) => {
|
|
230
|
+
* await next()
|
|
231
|
+
* c.header('x-after', '1')
|
|
232
|
+
* })
|
|
233
|
+
*
|
|
234
|
+
* return { delay: 120 }
|
|
235
|
+
* })
|
|
236
|
+
*/
|
|
237
|
+
declare function defineConfig(input: RouteDirectoryConfig | DefineConfigFactory): RouteDirectoryConfig;
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Create the mokup CLI program instance.
|
|
241
|
+
*
|
|
242
|
+
* @returns A configured CLI program.
|
|
243
|
+
*
|
|
244
|
+
* @example
|
|
245
|
+
* import { createCli } from '@mokup/cli'
|
|
246
|
+
*
|
|
247
|
+
* const cli = createCli()
|
|
248
|
+
*/
|
|
21
249
|
declare function createCli(): Command;
|
|
250
|
+
/**
|
|
251
|
+
* Run the mokup CLI with the provided argv.
|
|
252
|
+
*
|
|
253
|
+
* @param argv - CLI arguments.
|
|
254
|
+
* @returns Exit code or void.
|
|
255
|
+
*
|
|
256
|
+
* @example
|
|
257
|
+
* import { runCli } from '@mokup/cli'
|
|
258
|
+
*
|
|
259
|
+
* await runCli(['node', 'mokup', 'build', '--dir', 'mock'])
|
|
260
|
+
*/
|
|
22
261
|
declare function runCli(argv?: string[]): Promise<void>;
|
|
23
262
|
|
|
24
|
-
export { buildManifest, createCli, runCli };
|
|
25
|
-
export type { BuildOptions };
|
|
263
|
+
export { buildManifest, createCli, defineConfig, runCli };
|
|
264
|
+
export type { BuildOptions, MiddlewarePosition, MiddlewareRegistry, RouteDirectoryConfig, RouteRule };
|
package/dist/index.mjs
CHANGED
|
@@ -8,6 +8,7 @@ import { build } from '@mokup/shared/esbuild';
|
|
|
8
8
|
import { parseRouteTemplate, compareRouteScore } from '@mokup/runtime';
|
|
9
9
|
import { parse } from '@mokup/shared/jsonc-parser';
|
|
10
10
|
import { createFetchServer, serve } from '@mokup/server/node';
|
|
11
|
+
import { createLogger } from '@mokup/shared/logger';
|
|
11
12
|
import { Command } from 'commander';
|
|
12
13
|
|
|
13
14
|
async function writeBundle(outDir, hasHandlers) {
|
|
@@ -67,6 +68,7 @@ async function writeManifestModule(outDir, manifest) {
|
|
|
67
68
|
}
|
|
68
69
|
|
|
69
70
|
const configExtensions = [".ts", ".js", ".mjs", ".cjs"];
|
|
71
|
+
const middlewareSymbol$1 = Symbol.for("mokup.config.middlewares");
|
|
70
72
|
async function loadModule$1(file) {
|
|
71
73
|
const ext = configExtensions.find((extension) => file.endsWith(extension));
|
|
72
74
|
if (ext === ".cjs") {
|
|
@@ -127,7 +129,7 @@ async function loadConfig(file) {
|
|
|
127
129
|
}
|
|
128
130
|
return value;
|
|
129
131
|
}
|
|
130
|
-
function normalizeMiddlewares(value, source, log) {
|
|
132
|
+
function normalizeMiddlewares(value, source, log, position) {
|
|
131
133
|
if (!value) {
|
|
132
134
|
return [];
|
|
133
135
|
}
|
|
@@ -138,10 +140,22 @@ function normalizeMiddlewares(value, source, log) {
|
|
|
138
140
|
log?.(`Invalid middleware in ${source}`);
|
|
139
141
|
return;
|
|
140
142
|
}
|
|
141
|
-
middlewares.push({ file: source, index });
|
|
143
|
+
middlewares.push({ file: source, index, position });
|
|
142
144
|
});
|
|
143
145
|
return middlewares;
|
|
144
146
|
}
|
|
147
|
+
function readMiddlewareMeta(config) {
|
|
148
|
+
const value = config[middlewareSymbol$1];
|
|
149
|
+
if (!value || typeof value !== "object") {
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
const meta = value;
|
|
153
|
+
return {
|
|
154
|
+
pre: Array.isArray(meta.pre) ? meta.pre : [],
|
|
155
|
+
normal: Array.isArray(meta.normal) ? meta.normal : [],
|
|
156
|
+
post: Array.isArray(meta.post) ? meta.post : []
|
|
157
|
+
};
|
|
158
|
+
}
|
|
145
159
|
async function resolveDirectoryConfig(params) {
|
|
146
160
|
const { file, rootDir, log, configCache, fileCache } = params;
|
|
147
161
|
const resolvedRoot = normalize(rootDir);
|
|
@@ -160,7 +174,10 @@ async function resolveDirectoryConfig(params) {
|
|
|
160
174
|
current = parent;
|
|
161
175
|
}
|
|
162
176
|
chain.reverse();
|
|
163
|
-
const merged = {
|
|
177
|
+
const merged = {};
|
|
178
|
+
const preMiddlewares = [];
|
|
179
|
+
const normalMiddlewares = [];
|
|
180
|
+
const postMiddlewares = [];
|
|
164
181
|
for (const dir of chain) {
|
|
165
182
|
const configPath = await findConfigFile(dir, fileCache);
|
|
166
183
|
if (!configPath) {
|
|
@@ -196,12 +213,48 @@ async function resolveDirectoryConfig(params) {
|
|
|
196
213
|
if (typeof config.exclude !== "undefined") {
|
|
197
214
|
merged.exclude = config.exclude;
|
|
198
215
|
}
|
|
199
|
-
const
|
|
200
|
-
|
|
201
|
-
|
|
216
|
+
const meta = readMiddlewareMeta(config);
|
|
217
|
+
const normalizedPre = normalizeMiddlewares(
|
|
218
|
+
meta?.pre,
|
|
219
|
+
configPath,
|
|
220
|
+
log,
|
|
221
|
+
"pre"
|
|
222
|
+
);
|
|
223
|
+
const normalizedNormal = normalizeMiddlewares(
|
|
224
|
+
meta?.normal,
|
|
225
|
+
configPath,
|
|
226
|
+
log,
|
|
227
|
+
"normal"
|
|
228
|
+
);
|
|
229
|
+
const normalizedLegacy = normalizeMiddlewares(
|
|
230
|
+
config.middleware,
|
|
231
|
+
configPath,
|
|
232
|
+
log,
|
|
233
|
+
"normal"
|
|
234
|
+
);
|
|
235
|
+
const normalizedPost = normalizeMiddlewares(
|
|
236
|
+
meta?.post,
|
|
237
|
+
configPath,
|
|
238
|
+
log,
|
|
239
|
+
"post"
|
|
240
|
+
);
|
|
241
|
+
if (normalizedPre.length > 0) {
|
|
242
|
+
preMiddlewares.push(...normalizedPre);
|
|
243
|
+
}
|
|
244
|
+
if (normalizedNormal.length > 0) {
|
|
245
|
+
normalMiddlewares.push(...normalizedNormal);
|
|
246
|
+
}
|
|
247
|
+
if (normalizedLegacy.length > 0) {
|
|
248
|
+
normalMiddlewares.push(...normalizedLegacy);
|
|
249
|
+
}
|
|
250
|
+
if (normalizedPost.length > 0) {
|
|
251
|
+
postMiddlewares.push(...normalizedPost);
|
|
202
252
|
}
|
|
203
253
|
}
|
|
204
|
-
return
|
|
254
|
+
return {
|
|
255
|
+
...merged,
|
|
256
|
+
middlewares: [...preMiddlewares, ...normalMiddlewares, ...postMiddlewares]
|
|
257
|
+
};
|
|
205
258
|
}
|
|
206
259
|
|
|
207
260
|
function toPosix(value) {
|
|
@@ -756,6 +809,40 @@ async function buildManifest(options = {}) {
|
|
|
756
809
|
};
|
|
757
810
|
}
|
|
758
811
|
|
|
812
|
+
const middlewareSymbol = Symbol.for("mokup.config.middlewares");
|
|
813
|
+
function createRegistry(list) {
|
|
814
|
+
return {
|
|
815
|
+
use: (...handlers) => {
|
|
816
|
+
list.push(...handlers);
|
|
817
|
+
}
|
|
818
|
+
};
|
|
819
|
+
}
|
|
820
|
+
function attachMetadata(config, meta) {
|
|
821
|
+
Object.defineProperty(config, middlewareSymbol, {
|
|
822
|
+
value: meta,
|
|
823
|
+
enumerable: false
|
|
824
|
+
});
|
|
825
|
+
return config;
|
|
826
|
+
}
|
|
827
|
+
function defineConfig(input) {
|
|
828
|
+
if (typeof input === "function") {
|
|
829
|
+
const pre = [];
|
|
830
|
+
const normal = [];
|
|
831
|
+
const post = [];
|
|
832
|
+
const context = {
|
|
833
|
+
pre: createRegistry(pre),
|
|
834
|
+
normal: createRegistry(normal),
|
|
835
|
+
post: createRegistry(post)
|
|
836
|
+
};
|
|
837
|
+
const result = input(context);
|
|
838
|
+
const config2 = result && typeof result === "object" ? result : {};
|
|
839
|
+
return attachMetadata(config2, { pre, normal, post });
|
|
840
|
+
}
|
|
841
|
+
const config = input && typeof input === "object" ? input : {};
|
|
842
|
+
return attachMetadata(config, { pre: [], normal: [], post: [] });
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
const logger = createLogger();
|
|
759
846
|
function collectValues(value, previous) {
|
|
760
847
|
return [...previous ?? [], value];
|
|
761
848
|
}
|
|
@@ -768,7 +855,7 @@ function toBuildOptions(options) {
|
|
|
768
855
|
const buildOptions = {
|
|
769
856
|
handlers: options.handlers !== false,
|
|
770
857
|
log: (message) => {
|
|
771
|
-
|
|
858
|
+
logger.info(message);
|
|
772
859
|
}
|
|
773
860
|
};
|
|
774
861
|
if (options.dir && options.dir.length > 0) {
|
|
@@ -839,7 +926,7 @@ function createCli() {
|
|
|
839
926
|
const host = entry.host ?? "localhost";
|
|
840
927
|
const port = entry.port ?? 8080;
|
|
841
928
|
const playgroundEnabled = playground !== false;
|
|
842
|
-
const playgroundPath = "/
|
|
929
|
+
const playgroundPath = "/__mokup";
|
|
843
930
|
const server = await createFetchServer({
|
|
844
931
|
entries: entry,
|
|
845
932
|
playground
|
|
@@ -853,9 +940,9 @@ function createCli() {
|
|
|
853
940
|
(info) => {
|
|
854
941
|
const resolvedHost = typeof info === "string" ? host : info?.address ?? host;
|
|
855
942
|
const resolvedPort = typeof info === "string" ? port : info?.port ?? port;
|
|
856
|
-
|
|
943
|
+
logger.info(`Mock server ready at http://${resolvedHost}:${resolvedPort}`);
|
|
857
944
|
if (playgroundEnabled) {
|
|
858
|
-
|
|
945
|
+
logger.info(`Playground at http://${resolvedHost}:${resolvedPort}${playgroundPath}`);
|
|
859
946
|
}
|
|
860
947
|
}
|
|
861
948
|
);
|
|
@@ -895,4 +982,4 @@ async function runCli(argv = process.argv) {
|
|
|
895
982
|
await program.parseAsync(argv);
|
|
896
983
|
}
|
|
897
984
|
|
|
898
|
-
export { buildManifest, createCli, runCli };
|
|
985
|
+
export { buildManifest, createCli, defineConfig, runCli };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mokup/cli",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.7",
|
|
5
5
|
"description": "CLI for building mokup manifests and handlers.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"homepage": "https://mokup.icebreaker.top",
|
|
@@ -28,9 +28,9 @@
|
|
|
28
28
|
],
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"commander": "^14.0.0",
|
|
31
|
-
"@mokup/
|
|
32
|
-
"@mokup/shared": "1.0.
|
|
33
|
-
"@mokup/
|
|
31
|
+
"@mokup/server": "1.1.4",
|
|
32
|
+
"@mokup/shared": "1.0.2",
|
|
33
|
+
"@mokup/runtime": "1.0.3"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@types/node": "^25.0.10",
|