@faapi/faapi 0.0.0-canary.2a7b6a3 → 0.0.0-canary.9a79cdf
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/cli/index.js +382 -108
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +23 -0
- package/dist/index.js +71 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -78,17 +78,47 @@ function toProdImportPath(sourceFile, importer) {
|
|
|
78
78
|
if (!rel.startsWith(".")) rel = "./" + rel;
|
|
79
79
|
return toProdExtension(rel);
|
|
80
80
|
}
|
|
81
|
-
function
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
81
|
+
function toRealPath(p) {
|
|
82
|
+
try {
|
|
83
|
+
return fs2.realpathSync(p);
|
|
84
|
+
} catch {
|
|
85
|
+
return p;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function isInsideDir(filePath, dir) {
|
|
89
|
+
const rel = path2.relative(dir, filePath);
|
|
90
|
+
return rel !== "" && !rel.startsWith("..") && !path2.isAbsolute(rel);
|
|
91
|
+
}
|
|
92
|
+
function toStrippedProdImportPath(sourceFile, rootDir, appDir) {
|
|
93
|
+
const appDirAbs = toRealPath(path2.resolve(rootDir, appDir));
|
|
94
|
+
const sourceReal = toRealPath(sourceFile);
|
|
95
|
+
let rel = path2.relative(appDirAbs, sourceReal);
|
|
96
|
+
rel = rel.split(path2.sep).join("/");
|
|
97
|
+
if (!rel.startsWith(".")) rel = "./" + rel;
|
|
98
|
+
return toProdExtension(rel);
|
|
99
|
+
}
|
|
100
|
+
function resolveRelativeSpecifier(importer, specifier) {
|
|
101
|
+
const importerDir = path2.dirname(importer);
|
|
102
|
+
const base = path2.resolve(importerDir, specifier);
|
|
103
|
+
if (PROD_EXTS.some((ext) => specifier.endsWith(ext))) {
|
|
104
|
+
return fs2.existsSync(base) ? base : null;
|
|
105
|
+
}
|
|
106
|
+
if (/\.(ts|tsx|jsx)$/.test(specifier)) {
|
|
107
|
+
return fs2.existsSync(base) ? base : null;
|
|
108
|
+
}
|
|
109
|
+
for (const ext of SOURCE_EXTS) {
|
|
110
|
+
const file = base + ext;
|
|
111
|
+
if (fs2.existsSync(file)) return file;
|
|
112
|
+
}
|
|
113
|
+
for (const indexExt of INDEX_EXTS) {
|
|
114
|
+
const file = base + indexExt;
|
|
115
|
+
if (fs2.existsSync(file)) return file;
|
|
116
|
+
}
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
function createAliasPlugin(config, options) {
|
|
120
|
+
const SPEC_RE2 = /(\bfrom\s*|import\s*\(\s*)(['"])([^'"]+)\2/g;
|
|
121
|
+
const appDirAbs = options?.rootDir && options?.appDir ? toRealPath(path2.resolve(options.rootDir, options.appDir)) : null;
|
|
92
122
|
return {
|
|
93
123
|
name: "faapi-alias",
|
|
94
124
|
setup(build) {
|
|
@@ -100,17 +130,44 @@ function createAliasPlugin(config) {
|
|
|
100
130
|
return void 0;
|
|
101
131
|
}
|
|
102
132
|
const importer = args.path;
|
|
133
|
+
const importerOutsideAppDir = appDirAbs ? !isInsideDir(importer, appDirAbs) : false;
|
|
103
134
|
let modified = false;
|
|
104
|
-
const newSource = source.replace(
|
|
105
|
-
if (specifier.startsWith("
|
|
135
|
+
const newSource = source.replace(SPEC_RE2, (full, prefix, quote, specifier) => {
|
|
136
|
+
if (specifier.startsWith("/") || specifier.startsWith("file:") || specifier.startsWith("node:")) {
|
|
137
|
+
return full;
|
|
138
|
+
}
|
|
139
|
+
if (specifier.startsWith("./") || specifier.startsWith("../")) {
|
|
140
|
+
const resolved = resolveRelativeSpecifier(importer, specifier);
|
|
141
|
+
if (resolved) {
|
|
142
|
+
if (PROD_EXTS.some((ext) => specifier.endsWith(ext))) {
|
|
143
|
+
return full;
|
|
144
|
+
}
|
|
145
|
+
if (appDirAbs && importerOutsideAppDir && isInsideDir(resolved, appDirAbs)) {
|
|
146
|
+
modified = true;
|
|
147
|
+
return `${prefix}${quote}${toStrippedProdImportPath(
|
|
148
|
+
resolved,
|
|
149
|
+
options.rootDir,
|
|
150
|
+
options.appDir
|
|
151
|
+
)}${quote}`;
|
|
152
|
+
}
|
|
153
|
+
modified = true;
|
|
154
|
+
return `${prefix}${quote}${toProdImportPath(resolved, importer)}${quote}`;
|
|
155
|
+
}
|
|
106
156
|
return full;
|
|
107
157
|
}
|
|
108
158
|
const candidates = resolveAlias(specifier, config);
|
|
109
159
|
for (const candidate of candidates) {
|
|
110
|
-
for (const ext of
|
|
160
|
+
for (const ext of SOURCE_EXTS) {
|
|
111
161
|
const file = candidate + ext;
|
|
112
162
|
if (fs2.existsSync(file)) {
|
|
113
163
|
modified = true;
|
|
164
|
+
if (appDirAbs && importerOutsideAppDir && isInsideDir(file, appDirAbs)) {
|
|
165
|
+
return `${prefix}${quote}${toStrippedProdImportPath(
|
|
166
|
+
file,
|
|
167
|
+
options.rootDir,
|
|
168
|
+
options.appDir
|
|
169
|
+
)}${quote}`;
|
|
170
|
+
}
|
|
114
171
|
return `${prefix}${quote}${toProdImportPath(file, importer)}${quote}`;
|
|
115
172
|
}
|
|
116
173
|
}
|
|
@@ -118,6 +175,13 @@ function createAliasPlugin(config) {
|
|
|
118
175
|
const file = candidate + indexExt;
|
|
119
176
|
if (fs2.existsSync(file)) {
|
|
120
177
|
modified = true;
|
|
178
|
+
if (appDirAbs && importerOutsideAppDir && isInsideDir(file, appDirAbs)) {
|
|
179
|
+
return `${prefix}${quote}${toStrippedProdImportPath(
|
|
180
|
+
file,
|
|
181
|
+
options.rootDir,
|
|
182
|
+
options.appDir
|
|
183
|
+
)}${quote}`;
|
|
184
|
+
}
|
|
121
185
|
return `${prefix}${quote}${toProdImportPath(file, importer)}${quote}`;
|
|
122
186
|
}
|
|
123
187
|
}
|
|
@@ -130,15 +194,31 @@ function createAliasPlugin(config) {
|
|
|
130
194
|
}
|
|
131
195
|
};
|
|
132
196
|
}
|
|
133
|
-
function buildAliasPlugins(rootDir) {
|
|
197
|
+
function buildAliasPlugins(rootDir, appDir) {
|
|
134
198
|
const tsconfig = readTsconfig(rootDir);
|
|
135
|
-
return
|
|
199
|
+
return [
|
|
200
|
+
createAliasPlugin(
|
|
201
|
+
tsconfig ?? { baseUrl: ".", paths: {} },
|
|
202
|
+
appDir ? { rootDir, appDir } : void 0
|
|
203
|
+
)
|
|
204
|
+
];
|
|
136
205
|
}
|
|
206
|
+
var PROD_EXTS, SOURCE_EXTS, INDEX_EXTS;
|
|
137
207
|
var init_aliasPlugin = __esm({
|
|
138
208
|
"src/cli/aliasPlugin.ts"() {
|
|
139
209
|
"use strict";
|
|
140
210
|
init_resolveAlias();
|
|
141
211
|
init_readTsconfig();
|
|
212
|
+
PROD_EXTS = [".js", ".mjs", ".cjs"];
|
|
213
|
+
SOURCE_EXTS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
|
|
214
|
+
INDEX_EXTS = [
|
|
215
|
+
"/index.ts",
|
|
216
|
+
"/index.tsx",
|
|
217
|
+
"/index.js",
|
|
218
|
+
"/index.jsx",
|
|
219
|
+
"/index.mjs",
|
|
220
|
+
"/index.cjs"
|
|
221
|
+
];
|
|
142
222
|
}
|
|
143
223
|
});
|
|
144
224
|
|
|
@@ -215,13 +295,24 @@ var init_deepMerge = __esm({
|
|
|
215
295
|
// src/cli/compileConfig.ts
|
|
216
296
|
import path4 from "path";
|
|
217
297
|
import fs4 from "fs";
|
|
298
|
+
function toRealPath2(p) {
|
|
299
|
+
try {
|
|
300
|
+
return fs4.realpathSync(p);
|
|
301
|
+
} catch {
|
|
302
|
+
return p;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
function isInsideDir2(filePath, dir) {
|
|
306
|
+
const rel = path4.relative(dir, filePath);
|
|
307
|
+
return rel !== "" && !rel.startsWith("..") && !path4.isAbsolute(rel);
|
|
308
|
+
}
|
|
218
309
|
function getEnv() {
|
|
219
310
|
return process.env.FAAPI_ENV || process.env.NODE_ENV || "development";
|
|
220
311
|
}
|
|
221
312
|
function findBaseConfig(rootDir) {
|
|
222
313
|
for (const f of BASE_CONFIG_FILES) {
|
|
223
314
|
if (fs4.existsSync(path4.join(rootDir, f))) {
|
|
224
|
-
return f
|
|
315
|
+
return f;
|
|
225
316
|
}
|
|
226
317
|
}
|
|
227
318
|
return null;
|
|
@@ -230,33 +321,141 @@ function findEnvConfig(rootDir, env) {
|
|
|
230
321
|
for (const ext of ENV_CONFIG_EXTS) {
|
|
231
322
|
const f = `faapi.config.${env}${ext}`;
|
|
232
323
|
if (fs4.existsSync(path4.join(rootDir, f))) {
|
|
233
|
-
return
|
|
324
|
+
return f;
|
|
234
325
|
}
|
|
235
326
|
}
|
|
236
327
|
return null;
|
|
237
328
|
}
|
|
329
|
+
function toProdExtension2(filePath) {
|
|
330
|
+
if (filePath.endsWith(".ts")) return filePath.slice(0, -3) + ".js";
|
|
331
|
+
if (filePath.endsWith(".tsx")) return filePath.slice(0, -4) + ".js";
|
|
332
|
+
if (filePath.endsWith(".jsx")) return filePath.slice(0, -4) + ".js";
|
|
333
|
+
return filePath;
|
|
334
|
+
}
|
|
335
|
+
function toProdImport(filename) {
|
|
336
|
+
return toProdExtension2(filename);
|
|
337
|
+
}
|
|
338
|
+
function extractRelativeSpecifiers(source) {
|
|
339
|
+
const specifiers = [];
|
|
340
|
+
let match;
|
|
341
|
+
SPEC_RE.lastIndex = 0;
|
|
342
|
+
while ((match = SPEC_RE.exec(source)) !== null) {
|
|
343
|
+
const specifier = match[3];
|
|
344
|
+
if (specifier.startsWith("./") || specifier.startsWith("../")) {
|
|
345
|
+
specifiers.push(specifier);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
return specifiers;
|
|
349
|
+
}
|
|
350
|
+
async function collectRelativeImports(entryFiles, rootDir, appDir) {
|
|
351
|
+
const appDirAbs = toRealPath2(path4.resolve(rootDir, appDir));
|
|
352
|
+
const visited = /* @__PURE__ */ new Set();
|
|
353
|
+
const appDirFiles = /* @__PURE__ */ new Set();
|
|
354
|
+
const nonAppDirFiles = /* @__PURE__ */ new Set();
|
|
355
|
+
async function collect(filePath) {
|
|
356
|
+
if (visited.has(filePath)) return;
|
|
357
|
+
visited.add(filePath);
|
|
358
|
+
let source;
|
|
359
|
+
try {
|
|
360
|
+
source = await fs4.promises.readFile(filePath, "utf8");
|
|
361
|
+
} catch {
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
const specifiers = extractRelativeSpecifiers(source);
|
|
365
|
+
for (const specifier of specifiers) {
|
|
366
|
+
const resolved = resolveRelativeSpecifier(filePath, specifier);
|
|
367
|
+
if (!resolved) continue;
|
|
368
|
+
if (/\.(js|mjs|cjs)$/.test(specifier)) continue;
|
|
369
|
+
if (isInsideDir2(resolved, appDirAbs)) {
|
|
370
|
+
appDirFiles.add(resolved);
|
|
371
|
+
} else {
|
|
372
|
+
nonAppDirFiles.add(resolved);
|
|
373
|
+
}
|
|
374
|
+
await collect(resolved);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
for (const entry of entryFiles) {
|
|
378
|
+
await collect(entry);
|
|
379
|
+
}
|
|
380
|
+
return {
|
|
381
|
+
appDirFiles: Array.from(appDirFiles),
|
|
382
|
+
nonAppDirFiles: Array.from(nonAppDirFiles)
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
function createExternalRelativePlugin() {
|
|
386
|
+
return {
|
|
387
|
+
name: "faapi-external-relative",
|
|
388
|
+
setup(build) {
|
|
389
|
+
build.onResolve({ filter: /^\.{1,2}\// }, (args) => ({
|
|
390
|
+
path: args.path,
|
|
391
|
+
external: true
|
|
392
|
+
}));
|
|
393
|
+
}
|
|
394
|
+
};
|
|
395
|
+
}
|
|
238
396
|
async function compileConfig(options) {
|
|
239
|
-
const { rootDir, outDir } = options;
|
|
240
|
-
const
|
|
241
|
-
if (!
|
|
397
|
+
const { rootDir, outDir, appDir = "src" } = options;
|
|
398
|
+
const baseConfigName = findBaseConfig(rootDir);
|
|
399
|
+
if (!baseConfigName) {
|
|
242
400
|
return { generated: false, outputFile: "" };
|
|
243
401
|
}
|
|
244
402
|
const env = getEnv();
|
|
245
|
-
const
|
|
246
|
-
const
|
|
403
|
+
const envConfigName = findEnvConfig(rootDir, env);
|
|
404
|
+
const absOutDir = path4.resolve(rootDir, outDir);
|
|
405
|
+
await fs4.promises.mkdir(absOutDir, { recursive: true });
|
|
406
|
+
const configEntryPoints = [path4.resolve(rootDir, baseConfigName)];
|
|
407
|
+
if (envConfigName) {
|
|
408
|
+
configEntryPoints.push(path4.resolve(rootDir, envConfigName));
|
|
409
|
+
}
|
|
410
|
+
const { appDirFiles, nonAppDirFiles } = await collectRelativeImports(
|
|
411
|
+
configEntryPoints,
|
|
412
|
+
rootDir,
|
|
413
|
+
appDir
|
|
414
|
+
);
|
|
415
|
+
const esbuild = await import("esbuild");
|
|
416
|
+
const aliasPlugins = buildAliasPlugins(rootDir, appDir);
|
|
417
|
+
const step1aEntries = [...configEntryPoints, ...nonAppDirFiles];
|
|
418
|
+
await esbuild.build({
|
|
419
|
+
entryPoints: step1aEntries,
|
|
420
|
+
outdir: absOutDir,
|
|
421
|
+
outbase: rootDir,
|
|
422
|
+
bundle: false,
|
|
423
|
+
platform: "node",
|
|
424
|
+
format: "esm",
|
|
425
|
+
sourcemap: true,
|
|
426
|
+
packages: "external",
|
|
427
|
+
plugins: aliasPlugins,
|
|
428
|
+
logLevel: "silent"
|
|
429
|
+
});
|
|
430
|
+
if (appDirFiles.length > 0) {
|
|
431
|
+
const appOutbase = appDir === "." ? rootDir : path4.resolve(rootDir, appDir);
|
|
432
|
+
await esbuild.build({
|
|
433
|
+
entryPoints: appDirFiles,
|
|
434
|
+
outdir: absOutDir,
|
|
435
|
+
outbase: appOutbase,
|
|
436
|
+
bundle: false,
|
|
437
|
+
platform: "node",
|
|
438
|
+
format: "esm",
|
|
439
|
+
sourcemap: true,
|
|
440
|
+
packages: "external",
|
|
441
|
+
plugins: aliasPlugins,
|
|
442
|
+
logLevel: "silent"
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
const baseImport = `import base from './${toProdImport(baseConfigName)}';`;
|
|
446
|
+
const imports = [baseImport];
|
|
247
447
|
let exportDefault;
|
|
248
|
-
if (
|
|
249
|
-
|
|
448
|
+
if (envConfigName) {
|
|
449
|
+
const envImport = `import env from './${toProdImport(envConfigName)}';`;
|
|
450
|
+
imports.push(envImport);
|
|
250
451
|
exportDefault = "export default deepMerge(base, env);";
|
|
251
452
|
} else {
|
|
252
453
|
exportDefault = "export default base;";
|
|
253
454
|
}
|
|
254
455
|
const entryCode = [...imports, DEEP_MERGE_SOURCE, exportDefault].join("\n");
|
|
255
|
-
const outputFile = path4.resolve(
|
|
256
|
-
await fs4.promises.mkdir(path4.dirname(outputFile), { recursive: true });
|
|
257
|
-
const esbuild = await import("esbuild");
|
|
456
|
+
const outputFile = path4.resolve(absOutDir, "faapi-config.js");
|
|
258
457
|
await esbuild.build({
|
|
259
|
-
stdin: { contents: entryCode, resolveDir:
|
|
458
|
+
stdin: { contents: entryCode, resolveDir: absOutDir, loader: "ts" },
|
|
260
459
|
outfile: outputFile,
|
|
261
460
|
bundle: true,
|
|
262
461
|
format: "esm",
|
|
@@ -264,17 +463,20 @@ async function compileConfig(options) {
|
|
|
264
463
|
target: "node20",
|
|
265
464
|
sourcemap: true,
|
|
266
465
|
packages: "external",
|
|
466
|
+
plugins: [createExternalRelativePlugin()],
|
|
267
467
|
logLevel: "silent"
|
|
268
468
|
});
|
|
269
469
|
return { generated: true, outputFile };
|
|
270
470
|
}
|
|
271
|
-
var BASE_CONFIG_FILES, ENV_CONFIG_EXTS;
|
|
471
|
+
var BASE_CONFIG_FILES, ENV_CONFIG_EXTS, SPEC_RE;
|
|
272
472
|
var init_compileConfig = __esm({
|
|
273
473
|
"src/cli/compileConfig.ts"() {
|
|
274
474
|
"use strict";
|
|
275
475
|
init_deepMerge();
|
|
476
|
+
init_aliasPlugin();
|
|
276
477
|
BASE_CONFIG_FILES = ["faapi.config.ts", "faapi.config.js"];
|
|
277
478
|
ENV_CONFIG_EXTS = [".ts", ".js"];
|
|
479
|
+
SPEC_RE = /(\bfrom\s*|import\s*\(\s*)(['"])([^'"]+)\2/g;
|
|
278
480
|
}
|
|
279
481
|
});
|
|
280
482
|
|
|
@@ -563,10 +765,35 @@ function resolveTypeReference(typeNode, checker, visited = /* @__PURE__ */ new S
|
|
|
563
765
|
const properties = typeName === "Pick" ? innerType.properties.filter((p) => keySet.has(p.name)) : innerType.properties.filter((p) => !keySet.has(p.name));
|
|
564
766
|
return { kind: "object", properties };
|
|
565
767
|
}
|
|
566
|
-
if (typeName === "Map"
|
|
768
|
+
if (typeName === "Map") {
|
|
769
|
+
if (!typeNode.typeArguments || typeNode.typeArguments.length !== 2) {
|
|
770
|
+
throw new SchemaExtractionError(
|
|
771
|
+
typeNode.getText(),
|
|
772
|
+
"Map \u5FC5\u987B\u5E26 2 \u4E2A\u7C7B\u578B\u53C2\u6570\uFF0C\u5982 Map<K, V>\uFF0C\u88F8 Map \u4E0D\u652F\u6301"
|
|
773
|
+
);
|
|
774
|
+
}
|
|
775
|
+
return {
|
|
776
|
+
kind: "map",
|
|
777
|
+
key: resolveTypeNode(typeNode.typeArguments[0], checker, visited),
|
|
778
|
+
value: resolveTypeNode(typeNode.typeArguments[1], checker, visited)
|
|
779
|
+
};
|
|
780
|
+
}
|
|
781
|
+
if (typeName === "Set") {
|
|
782
|
+
if (!typeNode.typeArguments || typeNode.typeArguments.length !== 1) {
|
|
783
|
+
throw new SchemaExtractionError(
|
|
784
|
+
typeNode.getText(),
|
|
785
|
+
"Set \u5FC5\u987B\u5E26 1 \u4E2A\u7C7B\u578B\u53C2\u6570\uFF0C\u5982 Set<T>\uFF0C\u88F8 Set \u4E0D\u652F\u6301"
|
|
786
|
+
);
|
|
787
|
+
}
|
|
788
|
+
return {
|
|
789
|
+
kind: "set",
|
|
790
|
+
element: resolveTypeNode(typeNode.typeArguments[0], checker, visited)
|
|
791
|
+
};
|
|
792
|
+
}
|
|
793
|
+
if (typeName === "WeakMap" || typeName === "WeakSet") {
|
|
567
794
|
throw new SchemaExtractionError(
|
|
568
795
|
typeNode.getText(),
|
|
569
|
-
`${typeName} \u8FD0\u884C\u65F6\u65E0\u6CD5\u6821\u9A8C\uFF0C\u8BF7\u6539\u7528\u5BF9\u8C61
|
|
796
|
+
`${typeName} \u8FD0\u884C\u65F6\u65E0\u6CD5\u679A\u4E3E\u6821\u9A8C\uFF0C\u8BF7\u6539\u7528 Map / Set \u6216\u5BF9\u8C61`
|
|
570
797
|
);
|
|
571
798
|
}
|
|
572
799
|
if (typeName === "Promise") {
|
|
@@ -1025,6 +1252,7 @@ var init_resolveInjection = __esm({
|
|
|
1025
1252
|
PARAM_TYPE_MAP = {
|
|
1026
1253
|
query: "query",
|
|
1027
1254
|
body: "body",
|
|
1255
|
+
form: "form",
|
|
1028
1256
|
headers: "headers",
|
|
1029
1257
|
params: "params",
|
|
1030
1258
|
context: "context",
|
|
@@ -1123,9 +1351,16 @@ function collectRouteSchemaSources(routes, rootDir) {
|
|
|
1123
1351
|
const inputType = getInputTypeForMethod(method);
|
|
1124
1352
|
const schemaName = getSchemaName(method, inputType);
|
|
1125
1353
|
const meta = analyzeInjection(code, method);
|
|
1126
|
-
const param = meta.params.find((p) => p.type === inputType);
|
|
1354
|
+
const param = meta.params.find((p) => p.type === inputType) ?? (inputType === "body" ? meta.params.find((p) => p.type === "form") : void 0);
|
|
1355
|
+
const isForm = param?.type === "form";
|
|
1127
1356
|
const typeInfo = param?.typeName ? extractTypeInfo(program, filePath, param.typeName) : null;
|
|
1128
|
-
sources.push({
|
|
1357
|
+
sources.push({
|
|
1358
|
+
urlPath: entry.urlPath,
|
|
1359
|
+
filePath,
|
|
1360
|
+
schemaName,
|
|
1361
|
+
typeInfo,
|
|
1362
|
+
coerce: isForm || void 0
|
|
1363
|
+
});
|
|
1129
1364
|
}
|
|
1130
1365
|
}
|
|
1131
1366
|
return { sources, allTypesByFile, mergedAllTypes };
|
|
@@ -1177,6 +1412,13 @@ function collectNamedTypes(type, ctx) {
|
|
|
1177
1412
|
collectNamedTypes(type.key, ctx);
|
|
1178
1413
|
collectNamedTypes(type.value, ctx);
|
|
1179
1414
|
return;
|
|
1415
|
+
case "map":
|
|
1416
|
+
collectNamedTypes(type.key, ctx);
|
|
1417
|
+
collectNamedTypes(type.value, ctx);
|
|
1418
|
+
return;
|
|
1419
|
+
case "set":
|
|
1420
|
+
collectNamedTypes(type.element, ctx);
|
|
1421
|
+
return;
|
|
1180
1422
|
case "ref": {
|
|
1181
1423
|
if (ctx.namedTypes.has(type.name)) return;
|
|
1182
1424
|
ctx.namedTypes.set(type.name, { kind: "any" });
|
|
@@ -1266,6 +1508,10 @@ function baseExpression(type, ctx) {
|
|
|
1266
1508
|
return 'z.preprocess((v) => (typeof v === "string" ? new Date(v) : v), z.date())';
|
|
1267
1509
|
case "record":
|
|
1268
1510
|
return `z.record(${runtimeTypeToZodExpression(type.key, ctx)}, ${runtimeTypeToZodExpression(type.value, ctx)})`;
|
|
1511
|
+
case "map":
|
|
1512
|
+
return `z.preprocess(coerceMap, z.map(${runtimeTypeToZodExpression(type.key, ctx)}, ${runtimeTypeToZodExpression(type.value, ctx)}))`;
|
|
1513
|
+
case "set":
|
|
1514
|
+
return `z.preprocess(coerceSet, z.set(${runtimeTypeToZodExpression(type.element, ctx)}))`;
|
|
1269
1515
|
case "ref":
|
|
1270
1516
|
if (type.name === ctx.entryTypeName) {
|
|
1271
1517
|
return `${ctx.entryExportName}Schema`;
|
|
@@ -1278,11 +1524,13 @@ function generateHelpersFileSource() {
|
|
|
1278
1524
|
"// faapi-helpers.js \u2014 faapi \u81EA\u52A8\u751F\u6210\u7684\u516C\u7528\u51FD\u6570\uFF08\u8BF7\u52FF\u624B\u52A8\u7F16\u8F91\uFF09",
|
|
1279
1525
|
COERCE_NUMBER_HELPER,
|
|
1280
1526
|
COERCE_BOOLEAN_HELPER,
|
|
1527
|
+
COERCE_MAP_HELPER,
|
|
1528
|
+
COERCE_SET_HELPER,
|
|
1281
1529
|
""
|
|
1282
1530
|
].join("\n");
|
|
1283
1531
|
}
|
|
1284
1532
|
function usesCoerceHelpers(code) {
|
|
1285
|
-
return code.includes("coerceNumber") || code.includes("coerceBoolean");
|
|
1533
|
+
return code.includes("coerceNumber") || code.includes("coerceBoolean") || code.includes("coerceMap") || code.includes("coerceSet");
|
|
1286
1534
|
}
|
|
1287
1535
|
function wrapCoercePreprocess(kind, inner) {
|
|
1288
1536
|
if (kind === "number") {
|
|
@@ -1369,6 +1617,10 @@ function containsRef(type, visited) {
|
|
|
1369
1617
|
return type.members.some((m) => containsRef(m, visited));
|
|
1370
1618
|
case "record":
|
|
1371
1619
|
return containsRef(type.key, visited) || containsRef(type.value, visited);
|
|
1620
|
+
case "map":
|
|
1621
|
+
return containsRef(type.key, visited) || containsRef(type.value, visited);
|
|
1622
|
+
case "set":
|
|
1623
|
+
return containsRef(type.element, visited);
|
|
1372
1624
|
default:
|
|
1373
1625
|
return false;
|
|
1374
1626
|
}
|
|
@@ -1397,7 +1649,7 @@ function generateZodSchemaSource(typeInfo, resolveType, exportName, coerce = fal
|
|
|
1397
1649
|
}
|
|
1398
1650
|
return lines.join("\n");
|
|
1399
1651
|
}
|
|
1400
|
-
var CodeGenContext, COERCE_NUMBER_HELPER, COERCE_BOOLEAN_HELPER, HELPERS_FILENAME;
|
|
1652
|
+
var CodeGenContext, COERCE_NUMBER_HELPER, COERCE_BOOLEAN_HELPER, COERCE_MAP_HELPER, COERCE_SET_HELPER, HELPERS_FILENAME;
|
|
1401
1653
|
var init_generateZodSchema = __esm({
|
|
1402
1654
|
"src/ast/generateZodSchema.ts"() {
|
|
1403
1655
|
"use strict";
|
|
@@ -1423,6 +1675,8 @@ var init_generateZodSchema = __esm({
|
|
|
1423
1675
|
};
|
|
1424
1676
|
COERCE_NUMBER_HELPER = 'export const coerceNumber = (v) => typeof v === "string" && v.trim() !== "" && !isNaN(Number(v)) ? Number(v) : v;';
|
|
1425
1677
|
COERCE_BOOLEAN_HELPER = 'export const coerceBoolean = (v) => v === "true" || v === "1" ? true : v === "false" || v === "0" ? false : v;';
|
|
1678
|
+
COERCE_MAP_HELPER = 'export const coerceMap = (v) => Array.isArray(v) ? new Map(v) : v instanceof Map ? v : (v && typeof v === "object" ? new Map(Object.entries(v)) : v);';
|
|
1679
|
+
COERCE_SET_HELPER = "export const coerceSet = (v) => v instanceof Set ? v : (Array.isArray(v) ? new Set(v) : v);";
|
|
1426
1680
|
HELPERS_FILENAME = "faapi-helpers.js";
|
|
1427
1681
|
}
|
|
1428
1682
|
});
|
|
@@ -1464,7 +1718,7 @@ function generateSchemaFileSource(sources, allTypes, helpersImportPath) {
|
|
|
1464
1718
|
if (!typeInfo) {
|
|
1465
1719
|
continue;
|
|
1466
1720
|
}
|
|
1467
|
-
const coerce = /(?:Query|Params)$/.test(schemaName);
|
|
1721
|
+
const coerce = source.coerce ?? /(?:Query|Params)$/.test(schemaName);
|
|
1468
1722
|
const block = [`// ${schemaName}`];
|
|
1469
1723
|
const schemaCode = generateZodSchemaSource(typeInfo, resolveType, schemaName, coerce).replace(
|
|
1470
1724
|
/^import \{ z \} from 'zod';\s*\n\s*\n/,
|
|
@@ -1476,7 +1730,9 @@ function generateSchemaFileSource(sources, allTypes, helpersImportPath) {
|
|
|
1476
1730
|
}
|
|
1477
1731
|
const allSchemaCode = schemaBlocks.join("\n");
|
|
1478
1732
|
if (helpersImportPath && usesCoerceHelpers(allSchemaCode)) {
|
|
1479
|
-
lines.push(
|
|
1733
|
+
lines.push(
|
|
1734
|
+
`import { coerceNumber, coerceBoolean, coerceMap, coerceSet } from '${helpersImportPath}';`
|
|
1735
|
+
);
|
|
1480
1736
|
}
|
|
1481
1737
|
lines.push("");
|
|
1482
1738
|
lines.push(...schemaBlocks);
|
|
@@ -4473,6 +4729,10 @@ function getBuiltinInjectionValue(type, ctx, body) {
|
|
|
4473
4729
|
return ctx.ip;
|
|
4474
4730
|
case "body":
|
|
4475
4731
|
return body;
|
|
4732
|
+
// form 与 body 共享解析结果(resolveInput 已按 Content-Type 解析 form-urlencoded)
|
|
4733
|
+
// 差异仅在 schema 校验(form coerce=true,由 collectRouteSchemaSources 标记)
|
|
4734
|
+
case "form":
|
|
4735
|
+
return body;
|
|
4476
4736
|
case "files":
|
|
4477
4737
|
if (body && typeof body === "object" && "files" in body) {
|
|
4478
4738
|
return body.files;
|
|
@@ -4891,6 +5151,44 @@ var init_helmet = __esm({
|
|
|
4891
5151
|
}
|
|
4892
5152
|
});
|
|
4893
5153
|
|
|
5154
|
+
// src/middleware/logger.ts
|
|
5155
|
+
function logger(options = {}) {
|
|
5156
|
+
return async (ctx, next) => {
|
|
5157
|
+
const log = options.log ?? console.log;
|
|
5158
|
+
const start = Date.now();
|
|
5159
|
+
try {
|
|
5160
|
+
const response = await next();
|
|
5161
|
+
const duration = Date.now() - start;
|
|
5162
|
+
const entry = {
|
|
5163
|
+
method: ctx.method,
|
|
5164
|
+
path: ctx.path,
|
|
5165
|
+
status: response.status,
|
|
5166
|
+
durationMs: duration
|
|
5167
|
+
};
|
|
5168
|
+
log(entry, `${ctx.method} ${ctx.path} ${response.status} ${duration}ms`);
|
|
5169
|
+
return response;
|
|
5170
|
+
} catch (err) {
|
|
5171
|
+
const duration = Date.now() - start;
|
|
5172
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
5173
|
+
const status = err?.statusCode ?? 500;
|
|
5174
|
+
const entry = {
|
|
5175
|
+
method: ctx.method,
|
|
5176
|
+
path: ctx.path,
|
|
5177
|
+
status,
|
|
5178
|
+
durationMs: duration,
|
|
5179
|
+
error: message
|
|
5180
|
+
};
|
|
5181
|
+
log(entry, `${ctx.method} ${ctx.path} ${status} ${duration}ms - ${message}`);
|
|
5182
|
+
throw err;
|
|
5183
|
+
}
|
|
5184
|
+
};
|
|
5185
|
+
}
|
|
5186
|
+
var init_logger = __esm({
|
|
5187
|
+
"src/middleware/logger.ts"() {
|
|
5188
|
+
"use strict";
|
|
5189
|
+
}
|
|
5190
|
+
});
|
|
5191
|
+
|
|
4894
5192
|
// src/errors/formatErrorResponse.ts
|
|
4895
5193
|
function formatErrorResponse(error) {
|
|
4896
5194
|
if (error instanceof ValidationError) {
|
|
@@ -5219,6 +5517,7 @@ function createServer(options) {
|
|
|
5219
5517
|
middlewares: globalMiddlewares,
|
|
5220
5518
|
injectors: globalInjectors,
|
|
5221
5519
|
helmet: helmetOption,
|
|
5520
|
+
logger: loggerOption,
|
|
5222
5521
|
bodyLimit = DEFAULT_BODY_LIMIT,
|
|
5223
5522
|
http2: http2Option
|
|
5224
5523
|
} = options;
|
|
@@ -5230,6 +5529,8 @@ function createServer(options) {
|
|
|
5230
5529
|
const helmOpts = typeof helmetOption === "object" ? helmetOption : {};
|
|
5231
5530
|
configMiddlewares.push(helmet(helmOpts));
|
|
5232
5531
|
}
|
|
5532
|
+
const loggerMiddlewareInst = loggerOption === false ? null : loggerOption === true || loggerOption === void 0 ? logger() : logger(loggerOption);
|
|
5533
|
+
if (loggerMiddlewareInst) configMiddlewares.push(loggerMiddlewareInst);
|
|
5233
5534
|
const server = (() => {
|
|
5234
5535
|
if (http2Option) {
|
|
5235
5536
|
const h2Opts = typeof http2Option === "object" ? http2Option : {};
|
|
@@ -5343,6 +5644,7 @@ var init_createServer = __esm({
|
|
|
5343
5644
|
init_getClientIp();
|
|
5344
5645
|
init_cors();
|
|
5345
5646
|
init_helmet();
|
|
5647
|
+
init_logger();
|
|
5346
5648
|
init_handleWsUpgrade();
|
|
5347
5649
|
init_serverUtils();
|
|
5348
5650
|
init_generateSchemaFiles();
|
|
@@ -5456,7 +5758,7 @@ function isFaapiConfigKey(key) {
|
|
|
5456
5758
|
}
|
|
5457
5759
|
async function createAppBase(options) {
|
|
5458
5760
|
const rootDir = options?.rootDir ?? process.cwd();
|
|
5459
|
-
const outDir = process.env.FAAPI_OUT_DIR ?? DEFAULT_OUT_DIR;
|
|
5761
|
+
const outDir = options?.outDir ?? process.env.FAAPI_OUT_DIR ?? DEFAULT_OUT_DIR;
|
|
5460
5762
|
const routesPath = path13.resolve(rootDir, outDir, ROUTES_FILE);
|
|
5461
5763
|
if (!fs9.existsSync(routesPath)) {
|
|
5462
5764
|
throw new Error(
|
|
@@ -5492,6 +5794,7 @@ async function createAppBase(options) {
|
|
|
5492
5794
|
middlewares: config?.middlewares,
|
|
5493
5795
|
injectors: config?.injectors,
|
|
5494
5796
|
helmet: config?.helmet,
|
|
5797
|
+
logger: config?.logger,
|
|
5495
5798
|
bodyLimit: config?.bodyLimit,
|
|
5496
5799
|
http2: config?.http2
|
|
5497
5800
|
});
|
|
@@ -5729,7 +6032,7 @@ __export(devCommand_exports, {
|
|
|
5729
6032
|
generateRouteArtifacts: () => generateRouteArtifacts
|
|
5730
6033
|
});
|
|
5731
6034
|
import path14 from "path";
|
|
5732
|
-
async function devCommand() {
|
|
6035
|
+
async function devCommand(options) {
|
|
5733
6036
|
const rootDir = process.cwd();
|
|
5734
6037
|
process.env.FAAPI_OUT_DIR = DEV_OUT_DIR2;
|
|
5735
6038
|
if (!process.env.NODE_ENV) process.env.NODE_ENV = "development";
|
|
@@ -5737,14 +6040,14 @@ async function devCommand() {
|
|
|
5737
6040
|
console.log("- Compiling config...");
|
|
5738
6041
|
await compileConfig({ rootDir, outDir: DEV_OUT_DIR2 });
|
|
5739
6042
|
const _config = await loadConfig(rootDir, DEV_OUT_DIR2);
|
|
5740
|
-
const appDir = process.env.FAAPI_APP_DIR ?? "src";
|
|
6043
|
+
const appDir = options?.appDir ?? process.env.FAAPI_APP_DIR ?? "src";
|
|
5741
6044
|
const patterns = appDir === "." ? ["api/**/*.ts"] : [`${appDir}/api/**/*.ts`];
|
|
5742
6045
|
console.log("- Compiling TypeScript...");
|
|
5743
6046
|
await compileDevRoutes({ rootDir, appDir, outDir: DEV_OUT_DIR2 });
|
|
5744
6047
|
console.log("- Generating route manifest and schema...");
|
|
5745
6048
|
await generateRouteArtifacts(rootDir, appDir, patterns);
|
|
5746
6049
|
console.log("- Starting dev app...");
|
|
5747
|
-
const app = await createDevApp({ rootDir });
|
|
6050
|
+
const app = await createDevApp({ rootDir, port: options?.port });
|
|
5748
6051
|
await app.listen();
|
|
5749
6052
|
startWatcher({ rootDir, appDir, app });
|
|
5750
6053
|
}
|
|
@@ -5777,18 +6080,16 @@ var init_devCommand = __esm({
|
|
|
5777
6080
|
// src/cli/compileBuildRoutes.ts
|
|
5778
6081
|
import path15 from "path";
|
|
5779
6082
|
import fs10 from "fs";
|
|
6083
|
+
import fg3 from "fast-glob";
|
|
5780
6084
|
async function compileBuildRoutes(options) {
|
|
5781
|
-
const {
|
|
5782
|
-
|
|
5783
|
-
|
|
5784
|
-
|
|
5785
|
-
|
|
5786
|
-
|
|
5787
|
-
|
|
5788
|
-
|
|
5789
|
-
logLevel = "silent"
|
|
5790
|
-
} = options;
|
|
5791
|
-
if (entries.length === 0) {
|
|
6085
|
+
const { rootDir, appDir, outDir, files, logLevel = "silent" } = options;
|
|
6086
|
+
const entryPoints = files ?? await fg3([`${appDir}/**/*.ts`], {
|
|
6087
|
+
cwd: rootDir,
|
|
6088
|
+
onlyFiles: true,
|
|
6089
|
+
absolute: true,
|
|
6090
|
+
ignore: ["**/*.test.ts", "**/*.e2e.test.ts", "**/*.d.ts"]
|
|
6091
|
+
});
|
|
6092
|
+
if (entryPoints.length === 0) {
|
|
5792
6093
|
return { compiledFiles: [] };
|
|
5793
6094
|
}
|
|
5794
6095
|
const absOutDir = path15.resolve(rootDir, outDir);
|
|
@@ -5797,21 +6098,20 @@ async function compileBuildRoutes(options) {
|
|
|
5797
6098
|
const esbuild = await import("esbuild");
|
|
5798
6099
|
const outbase = appDir === "." ? rootDir : path15.resolve(rootDir, appDir);
|
|
5799
6100
|
await esbuild.build({
|
|
5800
|
-
entryPoints
|
|
6101
|
+
entryPoints,
|
|
5801
6102
|
outdir: absOutDir,
|
|
5802
6103
|
outbase,
|
|
5803
|
-
bundle:
|
|
5804
|
-
splitting,
|
|
6104
|
+
bundle: false,
|
|
5805
6105
|
platform: "node",
|
|
5806
6106
|
format: "esm",
|
|
5807
6107
|
sourcemap: true,
|
|
5808
6108
|
packages: "external",
|
|
5809
6109
|
plugins,
|
|
5810
|
-
define,
|
|
5811
|
-
minifySyntax,
|
|
6110
|
+
define: { "process.env.NODE_ENV": '"production"' },
|
|
6111
|
+
minifySyntax: true,
|
|
5812
6112
|
logLevel
|
|
5813
6113
|
});
|
|
5814
|
-
return { compiledFiles:
|
|
6114
|
+
return { compiledFiles: entryPoints };
|
|
5815
6115
|
}
|
|
5816
6116
|
var init_compileBuildRoutes = __esm({
|
|
5817
6117
|
"src/cli/compileBuildRoutes.ts"() {
|
|
@@ -5827,65 +6127,37 @@ __export(buildCommand_exports, {
|
|
|
5827
6127
|
});
|
|
5828
6128
|
import path16 from "path";
|
|
5829
6129
|
import fs11 from "fs";
|
|
5830
|
-
import fg3 from "fast-glob";
|
|
5831
|
-
async function collectBundleEntries(rootDir, patterns, appDir) {
|
|
5832
|
-
const entries = /* @__PURE__ */ new Set();
|
|
5833
|
-
const handlerFiles = await fg3(patterns, {
|
|
5834
|
-
cwd: rootDir,
|
|
5835
|
-
onlyFiles: true,
|
|
5836
|
-
absolute: true
|
|
5837
|
-
});
|
|
5838
|
-
for (const f of handlerFiles) {
|
|
5839
|
-
if (f.endsWith("handler.ts")) entries.add(f);
|
|
5840
|
-
}
|
|
5841
|
-
const mwGlob = appDir === "." ? "**/middlewares.ts" : appDir + "/**/middlewares.ts";
|
|
5842
|
-
const mwFiles = await fg3([mwGlob], {
|
|
5843
|
-
cwd: rootDir,
|
|
5844
|
-
onlyFiles: true,
|
|
5845
|
-
absolute: true,
|
|
5846
|
-
ignore: ["**/*.test.ts", "**/*.e2e.test.ts", "**/*.d.ts"]
|
|
5847
|
-
});
|
|
5848
|
-
for (const f of mwFiles) entries.add(f);
|
|
5849
|
-
return Array.from(entries);
|
|
5850
|
-
}
|
|
5851
6130
|
async function buildCommand(options) {
|
|
5852
6131
|
const rootDir = options?.rootDir ?? process.cwd();
|
|
5853
|
-
const outdir =
|
|
6132
|
+
const outdir = options?.outDir ?? DEFAULT_PROD_OUT_DIR;
|
|
5854
6133
|
await compileConfig({ rootDir, outDir: outdir });
|
|
5855
6134
|
const _config = await loadConfig(rootDir, outdir);
|
|
5856
|
-
const appDir = process.env.FAAPI_APP_DIR ?? "src";
|
|
6135
|
+
const appDir = options?.appDir ?? process.env.FAAPI_APP_DIR ?? "src";
|
|
5857
6136
|
const patterns = appDir === "." ? ["api/**/*.ts"] : [`${appDir}/api/**/*.ts`];
|
|
5858
6137
|
console.log("faapi build started");
|
|
5859
6138
|
console.log(`- Root: ${rootDir}`);
|
|
5860
6139
|
console.log(`- AppDir: ${appDir}`);
|
|
5861
6140
|
console.log(`- Output: ${outdir}`);
|
|
5862
|
-
console.log("\n[1/
|
|
5863
|
-
const entries = await collectBundleEntries(rootDir, patterns, appDir);
|
|
5864
|
-
console.log(` ${entries.length} entry file(s)`);
|
|
5865
|
-
if (entries.length === 0) {
|
|
5866
|
-
console.warn(" ! No entry files found, nothing to build");
|
|
5867
|
-
return;
|
|
5868
|
-
}
|
|
5869
|
-
console.log("\n[2/7] Compiling TypeScript (bundle mode)...");
|
|
6141
|
+
console.log("\n[1/6] Compiling TypeScript (bundle: false)...");
|
|
5870
6142
|
const result = await compileBuildRoutes({
|
|
5871
6143
|
rootDir,
|
|
5872
6144
|
appDir,
|
|
5873
6145
|
outDir: outdir,
|
|
5874
|
-
entries,
|
|
5875
|
-
splitting: true,
|
|
5876
|
-
define: { "process.env.NODE_ENV": JSON.stringify("production") },
|
|
5877
|
-
minifySyntax: true,
|
|
5878
6146
|
logLevel: "silent"
|
|
5879
6147
|
});
|
|
5880
|
-
console.log(` Compiled ${result.compiledFiles.length}
|
|
5881
|
-
|
|
6148
|
+
console.log(` Compiled ${result.compiledFiles.length} file(s)`);
|
|
6149
|
+
if (result.compiledFiles.length === 0) {
|
|
6150
|
+
console.warn(" ! No source files found, nothing to build");
|
|
6151
|
+
return;
|
|
6152
|
+
}
|
|
6153
|
+
console.log("\n[2/6] Compiling config...");
|
|
5882
6154
|
const configResult = await compileConfig({ rootDir, outDir: outdir });
|
|
5883
6155
|
if (configResult.generated) {
|
|
5884
6156
|
console.log(` Written to ${configResult.outputFile}`);
|
|
5885
6157
|
} else {
|
|
5886
6158
|
console.log(" No config file found, skipped");
|
|
5887
6159
|
}
|
|
5888
|
-
console.log("\n[
|
|
6160
|
+
console.log("\n[3/6] Scanning routes...");
|
|
5889
6161
|
const { routes, wsRoutes } = await scanRoutes(rootDir, patterns, appDir, outdir);
|
|
5890
6162
|
const sorted = sortRoutes(routes);
|
|
5891
6163
|
console.log(` Found ${sorted.length} routes, ${wsRoutes.length} WS routes`);
|
|
@@ -5899,27 +6171,29 @@ async function buildCommand(options) {
|
|
|
5899
6171
|
}
|
|
5900
6172
|
}
|
|
5901
6173
|
}
|
|
5902
|
-
console.log("\n[
|
|
6174
|
+
console.log("\n[4/6] Generating schema...");
|
|
5903
6175
|
await generateSchemaFiles(sorted, rootDir, appDir, outdir);
|
|
5904
6176
|
console.log(` Schema: zod.js files under ${path16.resolve(rootDir, outdir)}`);
|
|
5905
|
-
console.log("\n[6
|
|
6177
|
+
console.log("\n[5/6] Generating routes manifest...");
|
|
5906
6178
|
const routesPath = path16.resolve(rootDir, outdir, "faapi-routes.js");
|
|
5907
6179
|
const serialized = serializeRoutes(sorted, wsRoutes, rootDir, appDir, outdir);
|
|
5908
6180
|
await writeRoutesModule(serialized, routesPath);
|
|
5909
6181
|
console.log(` Written to ${routesPath}`);
|
|
5910
|
-
console.log("\n[
|
|
6182
|
+
console.log("\n[6/6] Generating entry file...");
|
|
5911
6183
|
const mainPath = path16.resolve(rootDir, outdir, "main.js");
|
|
6184
|
+
const createProdAppArgs = options?.outDir && options.outDir !== DEFAULT_PROD_OUT_DIR ? `{ outDir: '${options.outDir}' }` : "";
|
|
6185
|
+
const listenArgs = options?.port ? String(options.port) : "";
|
|
5912
6186
|
const mainContent = `// \u7531 faapi build \u81EA\u52A8\u751F\u6210\uFF0C\u8BF7\u52FF\u624B\u52A8\u7F16\u8F91
|
|
5913
6187
|
import { createProdApp } from '@faapi/faapi';
|
|
5914
6188
|
|
|
5915
|
-
const app = await createProdApp();
|
|
5916
|
-
await app.listen();
|
|
6189
|
+
const app = await createProdApp(${createProdAppArgs});
|
|
6190
|
+
await app.listen(${listenArgs});
|
|
5917
6191
|
`;
|
|
5918
6192
|
await fs11.promises.writeFile(mainPath, mainContent, "utf-8");
|
|
5919
6193
|
console.log(` Written to ${mainPath}`);
|
|
5920
6194
|
console.log("\nfaapi build completed");
|
|
5921
6195
|
}
|
|
5922
|
-
var
|
|
6196
|
+
var DEFAULT_PROD_OUT_DIR;
|
|
5923
6197
|
var init_buildCommand = __esm({
|
|
5924
6198
|
"src/cli/buildCommand.ts"() {
|
|
5925
6199
|
"use strict";
|
|
@@ -5931,7 +6205,7 @@ var init_buildCommand = __esm({
|
|
|
5931
6205
|
init_compileBuildRoutes();
|
|
5932
6206
|
init_compileConfig();
|
|
5933
6207
|
init_loadConfig();
|
|
5934
|
-
|
|
6208
|
+
DEFAULT_PROD_OUT_DIR = "dist";
|
|
5935
6209
|
}
|
|
5936
6210
|
});
|
|
5937
6211
|
|
|
@@ -6522,13 +6796,13 @@ var cac = (name = "") => new CAC(name);
|
|
|
6522
6796
|
|
|
6523
6797
|
// src/cli/index.ts
|
|
6524
6798
|
var cli = cac("faapi");
|
|
6525
|
-
cli.command("").alias("dev").action(async () => {
|
|
6799
|
+
cli.command("").alias("dev").option("--port <number>", "\u670D\u52A1\u7AEF\u53E3\uFF08\u9ED8\u8BA4 3000\uFF09").option("--appDir <dir>", "\u6E90\u7801\u76EE\u5F55\u524D\u7F00\uFF08\u9ED8\u8BA4 src\uFF09").action(async (options) => {
|
|
6526
6800
|
const { devCommand: devCommand2 } = await Promise.resolve().then(() => (init_devCommand(), devCommand_exports));
|
|
6527
|
-
await devCommand2();
|
|
6801
|
+
await devCommand2(options);
|
|
6528
6802
|
});
|
|
6529
|
-
cli.command("build", "Build for production").action(async () => {
|
|
6803
|
+
cli.command("build", "Build for production").option("--port <number>", "prod \u670D\u52A1\u7AEF\u53E3\uFF0C\u5199\u5165 dist/main.js").option("--appDir <dir>", "\u6E90\u7801\u76EE\u5F55\u524D\u7F00\uFF08\u9ED8\u8BA4 src\uFF09").option("--outDir <dir>", "\u4EA7\u7269\u8F93\u51FA\u76EE\u5F55\uFF08\u9ED8\u8BA4 dist\uFF09").action(async (options) => {
|
|
6530
6804
|
const { buildCommand: buildCommand2 } = await Promise.resolve().then(() => (init_buildCommand(), buildCommand_exports));
|
|
6531
|
-
await buildCommand2();
|
|
6805
|
+
await buildCommand2(options);
|
|
6532
6806
|
});
|
|
6533
6807
|
cli.help();
|
|
6534
6808
|
cli.parse();
|