@pracht/cli 1.1.5 → 1.2.1
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/CHANGELOG.md +22 -0
- package/bin/pracht.js +1 -40
- package/dist/build-DlABFPbG.mjs +214 -0
- package/dist/build-metadata-BOChHO8g.mjs +58 -0
- package/dist/dev-BCFe3g38.mjs +25 -0
- package/dist/doctor-CQq64tfW.mjs +25 -0
- package/dist/generate-sHtRHRAH.mjs +400 -0
- package/dist/index.mjs +41 -0
- package/dist/inspect-DP-h3vLw.mjs +123 -0
- package/dist/manifest-DGq1n5LT.mjs +99 -0
- package/dist/project-DUyH_7eJ.mjs +148 -0
- package/dist/verification-CId4crSF.mjs +372 -0
- package/dist/verify-D7Bg1Su6.mjs +31 -0
- package/package.json +6 -2
- package/src/build-metadata.ts +101 -0
- package/{lib/build-shared.js → src/build-shared.ts} +30 -20
- package/src/commands/build.ts +137 -0
- package/src/commands/dev.ts +27 -0
- package/src/commands/doctor.ts +33 -0
- package/{lib/commands/generate.js → src/commands/generate.ts} +193 -149
- package/{lib/commands/inspect.js → src/commands/inspect.ts} +83 -34
- package/src/commands/verify.ts +37 -0
- package/src/constants.ts +26 -0
- package/src/index.ts +21 -0
- package/{lib/manifest.js → src/manifest.ts} +32 -13
- package/{lib/project.js → src/project.ts} +51 -34
- package/src/utils.ts +72 -0
- package/{lib/verification.js → src/verification.ts} +103 -34
- package/tsdown.config.ts +8 -0
- package/lib/build-metadata.js +0 -73
- package/lib/cli.js +0 -164
- package/lib/commands/build.js +0 -120
- package/lib/commands/dev.js +0 -16
- package/lib/commands/doctor.js +0 -21
- package/lib/commands/verify.js +0 -21
- package/lib/constants.js +0 -22
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
import { readFileSync, writeFileSync } from "node:fs";
|
|
2
2
|
|
|
3
|
+
import { defineCommand } from "citty";
|
|
4
|
+
|
|
3
5
|
import {
|
|
4
6
|
ensureTrailingNewline,
|
|
5
7
|
parseApiMethods,
|
|
6
8
|
parseCommaList,
|
|
7
|
-
parseFlags,
|
|
8
|
-
printGenerateHelp,
|
|
9
9
|
quote,
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
requireStringOption,
|
|
14
|
-
} from "../cli.js";
|
|
10
|
+
requireEnum,
|
|
11
|
+
requirePositiveInteger,
|
|
12
|
+
} from "../utils.js";
|
|
15
13
|
import {
|
|
16
14
|
extractRegistryEntries,
|
|
17
15
|
insertArrayItem,
|
|
@@ -29,20 +27,103 @@ import {
|
|
|
29
27
|
resolveRouteModulePath,
|
|
30
28
|
resolveScopedFile,
|
|
31
29
|
writeGeneratedFile,
|
|
30
|
+
type ProjectConfig,
|
|
32
31
|
} from "../project.js";
|
|
33
32
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const options = parseFlags(rest);
|
|
42
|
-
const project = readProjectConfig(process.cwd());
|
|
43
|
-
const result = runGenerate(kind, options, project);
|
|
33
|
+
interface GenerateResult {
|
|
34
|
+
created: string[];
|
|
35
|
+
kind: string;
|
|
36
|
+
updated: string[];
|
|
37
|
+
}
|
|
44
38
|
|
|
45
|
-
|
|
39
|
+
const routeCommand = defineCommand({
|
|
40
|
+
meta: {
|
|
41
|
+
name: "route",
|
|
42
|
+
description: "Scaffold a route module",
|
|
43
|
+
},
|
|
44
|
+
args: {
|
|
45
|
+
path: { type: "string", required: true, description: "Route path (e.g. /dashboard)" },
|
|
46
|
+
render: { type: "string", description: "Render mode: ssr, spa, ssg, or isg" },
|
|
47
|
+
shell: { type: "string", description: "Shell name" },
|
|
48
|
+
middleware: { type: "string", description: "Middleware names (comma-separated)" },
|
|
49
|
+
loader: { type: "boolean", description: "Include loader" },
|
|
50
|
+
"error-boundary": { type: "boolean", description: "Include error boundary" },
|
|
51
|
+
"static-paths": { type: "boolean", description: "Include static paths" },
|
|
52
|
+
title: { type: "string", description: "Page title" },
|
|
53
|
+
revalidate: { type: "string", description: "ISG revalidation seconds" },
|
|
54
|
+
json: { type: "boolean", description: "Output as JSON" },
|
|
55
|
+
},
|
|
56
|
+
async run({ args }) {
|
|
57
|
+
const project = readProjectConfig(process.cwd());
|
|
58
|
+
const result = generateRoute(args, project);
|
|
59
|
+
outputResult(result, Boolean(args.json));
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
const shellCommand = defineCommand({
|
|
64
|
+
meta: {
|
|
65
|
+
name: "shell",
|
|
66
|
+
description: "Scaffold a shell component",
|
|
67
|
+
},
|
|
68
|
+
args: {
|
|
69
|
+
name: { type: "string", required: true, description: "Shell name" },
|
|
70
|
+
json: { type: "boolean", description: "Output as JSON" },
|
|
71
|
+
},
|
|
72
|
+
async run({ args }) {
|
|
73
|
+
const project = readProjectConfig(process.cwd());
|
|
74
|
+
const result = generateShell(args.name, project);
|
|
75
|
+
outputResult(result, Boolean(args.json));
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
const middlewareCommand = defineCommand({
|
|
80
|
+
meta: {
|
|
81
|
+
name: "middleware",
|
|
82
|
+
description: "Scaffold a middleware function",
|
|
83
|
+
},
|
|
84
|
+
args: {
|
|
85
|
+
name: { type: "string", required: true, description: "Middleware name" },
|
|
86
|
+
json: { type: "boolean", description: "Output as JSON" },
|
|
87
|
+
},
|
|
88
|
+
async run({ args }) {
|
|
89
|
+
const project = readProjectConfig(process.cwd());
|
|
90
|
+
const result = generateMiddleware(args.name, project);
|
|
91
|
+
outputResult(result, Boolean(args.json));
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
const apiCommand = defineCommand({
|
|
96
|
+
meta: {
|
|
97
|
+
name: "api",
|
|
98
|
+
description: "Scaffold an API route",
|
|
99
|
+
},
|
|
100
|
+
args: {
|
|
101
|
+
path: { type: "string", required: true, description: "API endpoint path" },
|
|
102
|
+
methods: { type: "string", description: "HTTP methods (comma-separated, e.g. GET,POST)" },
|
|
103
|
+
json: { type: "boolean", description: "Output as JSON" },
|
|
104
|
+
},
|
|
105
|
+
async run({ args }) {
|
|
106
|
+
const project = readProjectConfig(process.cwd());
|
|
107
|
+
const result = generateApi(args, project);
|
|
108
|
+
outputResult(result, Boolean(args.json));
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
export default defineCommand({
|
|
113
|
+
meta: {
|
|
114
|
+
name: "generate",
|
|
115
|
+
description: "Scaffold framework files",
|
|
116
|
+
},
|
|
117
|
+
subCommands: {
|
|
118
|
+
route: routeCommand,
|
|
119
|
+
shell: shellCommand,
|
|
120
|
+
middleware: middlewareCommand,
|
|
121
|
+
api: apiCommand,
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
function outputResult(result: GenerateResult, json: boolean): void {
|
|
126
|
+
if (json) {
|
|
46
127
|
console.log(JSON.stringify({ ok: true, ...result }, null, 2));
|
|
47
128
|
return;
|
|
48
129
|
}
|
|
@@ -56,36 +137,31 @@ export async function generateCommand(args) {
|
|
|
56
137
|
}
|
|
57
138
|
}
|
|
58
139
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
if (kind === "api") {
|
|
70
|
-
return generateApi(options, project);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
throw new Error(`Unknown generate kind: ${kind}`);
|
|
140
|
+
interface RouteArgs {
|
|
141
|
+
"error-boundary"?: boolean;
|
|
142
|
+
loader?: boolean;
|
|
143
|
+
middleware?: string;
|
|
144
|
+
path: string;
|
|
145
|
+
render?: string;
|
|
146
|
+
revalidate?: string;
|
|
147
|
+
shell?: string;
|
|
148
|
+
"static-paths"?: boolean;
|
|
149
|
+
title?: string;
|
|
74
150
|
}
|
|
75
151
|
|
|
76
|
-
function generateRoute(
|
|
77
|
-
const routePath = normalizeRoutePathString(
|
|
78
|
-
const render =
|
|
79
|
-
const includeLoader = Boolean(
|
|
80
|
-
const includeErrorBoundary = Boolean(
|
|
81
|
-
const middleware = parseCommaList(
|
|
152
|
+
function generateRoute(args: RouteArgs, project: ProjectConfig): GenerateResult {
|
|
153
|
+
const routePath = normalizeRoutePathString(args.path);
|
|
154
|
+
const render = requireEnum(args.render, "render", ["spa", "ssr", "ssg", "isg"], "ssr");
|
|
155
|
+
const includeLoader = Boolean(args.loader);
|
|
156
|
+
const includeErrorBoundary = Boolean(args["error-boundary"]);
|
|
157
|
+
const middleware = parseCommaList(args.middleware);
|
|
82
158
|
const includeStaticPaths =
|
|
83
|
-
Boolean(
|
|
159
|
+
Boolean(args["static-paths"]) ||
|
|
84
160
|
(hasDynamicSegments(routePath) && (render === "ssg" || render === "isg"));
|
|
85
|
-
const title =
|
|
161
|
+
const title = args.title ?? titleFromPath(routePath);
|
|
86
162
|
|
|
87
163
|
if (project.mode === "pages") {
|
|
88
|
-
if (
|
|
164
|
+
if (args.shell) {
|
|
89
165
|
throw new Error("`pracht generate route --shell` is only available for manifest apps.");
|
|
90
166
|
}
|
|
91
167
|
if (middleware.length > 0) {
|
|
@@ -113,7 +189,7 @@ function generateRoute(options, project) {
|
|
|
113
189
|
extractRegistryEntries(manifestSource, "middleware").map((entry) => entry.name),
|
|
114
190
|
);
|
|
115
191
|
|
|
116
|
-
const shellName =
|
|
192
|
+
const shellName = args.shell;
|
|
117
193
|
if (shellName && !registeredShells.has(shellName)) {
|
|
118
194
|
throw new Error(`Shell "${shellName}" is not registered in ${project.appFile}.`);
|
|
119
195
|
}
|
|
@@ -152,7 +228,7 @@ function generateRoute(options, project) {
|
|
|
152
228
|
meta.push(`middleware: [${middleware.map((item) => quote(item)).join(", ")}]`);
|
|
153
229
|
}
|
|
154
230
|
if (render === "isg") {
|
|
155
|
-
const seconds =
|
|
231
|
+
const seconds = requirePositiveInteger(args.revalidate, "revalidate", 3600);
|
|
156
232
|
meta.push(`revalidate: timeRevalidate(${seconds})`);
|
|
157
233
|
}
|
|
158
234
|
|
|
@@ -182,7 +258,15 @@ function generatePagesRoute({
|
|
|
182
258
|
render,
|
|
183
259
|
routePath,
|
|
184
260
|
title,
|
|
185
|
-
}
|
|
261
|
+
}: {
|
|
262
|
+
includeErrorBoundary: boolean;
|
|
263
|
+
includeLoader: boolean;
|
|
264
|
+
includeStaticPaths: boolean;
|
|
265
|
+
project: ProjectConfig;
|
|
266
|
+
render: string;
|
|
267
|
+
routePath: string;
|
|
268
|
+
title: string;
|
|
269
|
+
}): GenerateResult {
|
|
186
270
|
const routeFile = resolvePagesRouteModulePath(project, routePath, ".tsx");
|
|
187
271
|
writeGeneratedFile(
|
|
188
272
|
routeFile.absolutePath,
|
|
@@ -203,14 +287,13 @@ function generatePagesRoute({
|
|
|
203
287
|
};
|
|
204
288
|
}
|
|
205
289
|
|
|
206
|
-
function generateShell(
|
|
290
|
+
function generateShell(name: string, project: ProjectConfig): GenerateResult {
|
|
207
291
|
if (project.mode === "pages") {
|
|
208
292
|
throw new Error(
|
|
209
293
|
"Pages router apps use a single `_app` shell. `pracht generate shell` is only available for manifest apps.",
|
|
210
294
|
);
|
|
211
295
|
}
|
|
212
296
|
|
|
213
|
-
const name = requireStringOption(options, "name");
|
|
214
297
|
const manifestPath = resolveProjectPath(project.root, project.appFile);
|
|
215
298
|
assertFileExists(manifestPath, `App manifest not found at ${project.appFile}.`);
|
|
216
299
|
|
|
@@ -232,14 +315,13 @@ function generateShell(options, project) {
|
|
|
232
315
|
};
|
|
233
316
|
}
|
|
234
317
|
|
|
235
|
-
function generateMiddleware(
|
|
318
|
+
function generateMiddleware(name: string, project: ProjectConfig): GenerateResult {
|
|
236
319
|
if (project.mode === "pages") {
|
|
237
320
|
throw new Error(
|
|
238
321
|
"Pages router apps do not use manifest middleware registration. `pracht generate middleware` is only available for manifest apps.",
|
|
239
322
|
);
|
|
240
323
|
}
|
|
241
324
|
|
|
242
|
-
const name = requireStringOption(options, "name");
|
|
243
325
|
const manifestPath = resolveProjectPath(project.root, project.appFile);
|
|
244
326
|
assertFileExists(manifestPath, `App manifest not found at ${project.appFile}.`);
|
|
245
327
|
|
|
@@ -261,9 +343,14 @@ function generateMiddleware(options, project) {
|
|
|
261
343
|
};
|
|
262
344
|
}
|
|
263
345
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
346
|
+
interface ApiArgs {
|
|
347
|
+
methods?: string;
|
|
348
|
+
path: string;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
function generateApi(args: ApiArgs, project: ProjectConfig): GenerateResult {
|
|
352
|
+
const endpointPath = normalizeApiPath(args.path);
|
|
353
|
+
const methods = parseApiMethods(args.methods);
|
|
267
354
|
const apiFile = resolveApiModulePath(project, endpointPath);
|
|
268
355
|
writeGeneratedFile(apiFile.absolutePath, buildApiRouteSource({ endpointPath, methods }));
|
|
269
356
|
|
|
@@ -274,16 +361,19 @@ function generateApi(options, project) {
|
|
|
274
361
|
};
|
|
275
362
|
}
|
|
276
363
|
|
|
277
|
-
|
|
278
|
-
includeErrorBoundary
|
|
279
|
-
includeLoader
|
|
280
|
-
includeStaticPaths
|
|
281
|
-
routePath
|
|
282
|
-
title
|
|
283
|
-
}
|
|
364
|
+
interface RouteModuleParts {
|
|
365
|
+
includeErrorBoundary: boolean;
|
|
366
|
+
includeLoader: boolean;
|
|
367
|
+
includeStaticPaths: boolean;
|
|
368
|
+
routePath: string;
|
|
369
|
+
title: string;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
function buildRouteModuleSections(opts: RouteModuleParts): string[] {
|
|
373
|
+
const { includeErrorBoundary, includeLoader, includeStaticPaths, routePath, title } = opts;
|
|
284
374
|
const params = dynamicParamNames(routePath);
|
|
285
|
-
const imports = [];
|
|
286
|
-
const sections = [];
|
|
375
|
+
const imports: string[] = [];
|
|
376
|
+
const sections: string[] = [];
|
|
287
377
|
|
|
288
378
|
if (includeLoader) {
|
|
289
379
|
imports.push("LoaderArgs", "RouteComponentProps");
|
|
@@ -315,8 +405,6 @@ function buildManifestRouteModuleSource({
|
|
|
315
405
|
);
|
|
316
406
|
}
|
|
317
407
|
|
|
318
|
-
sections.push("export function head() {", ` return { title: ${quote(title)} };`, "}", "");
|
|
319
|
-
|
|
320
408
|
if (includeLoader) {
|
|
321
409
|
sections.push(
|
|
322
410
|
"export function Component({ data }: RouteComponentProps<typeof loader>) {",
|
|
@@ -349,89 +437,39 @@ function buildManifestRouteModuleSource({
|
|
|
349
437
|
);
|
|
350
438
|
}
|
|
351
439
|
|
|
352
|
-
return
|
|
440
|
+
return sections;
|
|
353
441
|
}
|
|
354
442
|
|
|
355
|
-
function
|
|
356
|
-
|
|
357
|
-
includeLoader,
|
|
358
|
-
includeStaticPaths,
|
|
359
|
-
render,
|
|
360
|
-
routePath,
|
|
361
|
-
title,
|
|
362
|
-
}) {
|
|
363
|
-
const params = dynamicParamNames(routePath);
|
|
364
|
-
const imports = [];
|
|
365
|
-
const sections = [];
|
|
366
|
-
|
|
367
|
-
if (includeLoader) {
|
|
368
|
-
imports.push("LoaderArgs", "RouteComponentProps");
|
|
369
|
-
}
|
|
370
|
-
if (includeErrorBoundary) {
|
|
371
|
-
imports.push("ErrorBoundaryProps");
|
|
372
|
-
}
|
|
443
|
+
function buildManifestRouteModuleSource(opts: RouteModuleParts): string {
|
|
444
|
+
const sections = buildRouteModuleSections(opts);
|
|
373
445
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
"}",
|
|
386
|
-
"",
|
|
387
|
-
);
|
|
388
|
-
}
|
|
446
|
+
// Insert head() before the Component export (after loader/getStaticPaths)
|
|
447
|
+
const componentIdx = sections.findIndex((s) => s.startsWith("export function Component"));
|
|
448
|
+
const insertAt = componentIdx === -1 ? sections.length : componentIdx;
|
|
449
|
+
sections.splice(
|
|
450
|
+
insertAt,
|
|
451
|
+
0,
|
|
452
|
+
"export function head() {",
|
|
453
|
+
` return { title: ${quote(opts.title)} };`,
|
|
454
|
+
"}",
|
|
455
|
+
"",
|
|
456
|
+
);
|
|
389
457
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
"export function getStaticPaths() {",
|
|
393
|
-
` return [${buildStaticPathsStub(params)}];`,
|
|
394
|
-
"}",
|
|
395
|
-
"",
|
|
396
|
-
);
|
|
397
|
-
}
|
|
458
|
+
return `${sections.join("\n")}\n`;
|
|
459
|
+
}
|
|
398
460
|
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
"export function Component({ data }: RouteComponentProps<typeof loader>) {",
|
|
402
|
-
" return (",
|
|
403
|
-
" <section>",
|
|
404
|
-
` <h1>${escapeJsxText(title)}</h1>`,
|
|
405
|
-
" <p>{data.message}</p>",
|
|
406
|
-
" </section>",
|
|
407
|
-
" );",
|
|
408
|
-
"}",
|
|
409
|
-
);
|
|
410
|
-
} else {
|
|
411
|
-
sections.push(
|
|
412
|
-
"export function Component() {",
|
|
413
|
-
" return (",
|
|
414
|
-
" <section>",
|
|
415
|
-
` <h1>${escapeJsxText(title)}</h1>`,
|
|
416
|
-
" </section>",
|
|
417
|
-
" );",
|
|
418
|
-
"}",
|
|
419
|
-
);
|
|
420
|
-
}
|
|
461
|
+
function buildPagesRouteModuleSource(opts: RouteModuleParts & { render: string }): string {
|
|
462
|
+
const sections = buildRouteModuleSections(opts);
|
|
421
463
|
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
" return <p>{error.message}</p>;",
|
|
427
|
-
"}",
|
|
428
|
-
);
|
|
429
|
-
}
|
|
464
|
+
// Insert RENDER_MODE before the first exported declaration (after imports)
|
|
465
|
+
const firstExportIdx = sections.findIndex((s) => s.startsWith("export"));
|
|
466
|
+
const insertAt = firstExportIdx === -1 ? sections.length : firstExportIdx;
|
|
467
|
+
sections.splice(insertAt, 0, `export const RENDER_MODE = ${quote(opts.render)};`, "");
|
|
430
468
|
|
|
431
469
|
return `${sections.join("\n")}\n`;
|
|
432
470
|
}
|
|
433
471
|
|
|
434
|
-
function buildShellModuleSource(name) {
|
|
472
|
+
function buildShellModuleSource(name: string): string {
|
|
435
473
|
const title = titleCase(name);
|
|
436
474
|
return [
|
|
437
475
|
'import type { ShellProps } from "@pracht/core";',
|
|
@@ -451,7 +489,7 @@ function buildShellModuleSource(name) {
|
|
|
451
489
|
].join("\n");
|
|
452
490
|
}
|
|
453
491
|
|
|
454
|
-
function buildMiddlewareModuleSource() {
|
|
492
|
+
function buildMiddlewareModuleSource(): string {
|
|
455
493
|
return [
|
|
456
494
|
'import type { MiddlewareFn } from "@pracht/core";',
|
|
457
495
|
"",
|
|
@@ -462,7 +500,13 @@ function buildMiddlewareModuleSource() {
|
|
|
462
500
|
].join("\n");
|
|
463
501
|
}
|
|
464
502
|
|
|
465
|
-
function buildApiRouteSource({
|
|
503
|
+
function buildApiRouteSource({
|
|
504
|
+
endpointPath,
|
|
505
|
+
methods,
|
|
506
|
+
}: {
|
|
507
|
+
endpointPath: string;
|
|
508
|
+
methods: string[];
|
|
509
|
+
}): string {
|
|
466
510
|
const methodLines = methods.flatMap((method, index) => {
|
|
467
511
|
const lines = buildApiMethodSource(method, methods, endpointPath);
|
|
468
512
|
if (index === methods.length - 1) return lines;
|
|
@@ -472,7 +516,7 @@ function buildApiRouteSource({ endpointPath, methods }) {
|
|
|
472
516
|
return ['import type { BaseRouteArgs } from "@pracht/core";', "", ...methodLines, ""].join("\n");
|
|
473
517
|
}
|
|
474
518
|
|
|
475
|
-
function buildApiMethodSource(method, methods, endpointPath) {
|
|
519
|
+
function buildApiMethodSource(method: string, methods: string[], endpointPath: string): string[] {
|
|
476
520
|
if (method === "DELETE" || method === "HEAD") {
|
|
477
521
|
return [
|
|
478
522
|
`export function ${method}(_args: BaseRouteArgs) {`,
|
|
@@ -509,22 +553,22 @@ function buildApiMethodSource(method, methods, endpointPath) {
|
|
|
509
553
|
];
|
|
510
554
|
}
|
|
511
555
|
|
|
512
|
-
function normalizeRoutePathString(value) {
|
|
556
|
+
function normalizeRoutePathString(value: string): string {
|
|
513
557
|
if (!value || value === "/") return "/";
|
|
514
558
|
const normalized = `/${value}`.replace(/\/+/g, "/");
|
|
515
559
|
return normalized !== "/" && normalized.endsWith("/") ? normalized.slice(0, -1) : normalized;
|
|
516
560
|
}
|
|
517
561
|
|
|
518
|
-
function normalizeApiPath(value) {
|
|
562
|
+
function normalizeApiPath(value: string): string {
|
|
519
563
|
const normalized = normalizeRoutePathString(value).replace(/^\/api(?=\/|$)/, "");
|
|
520
564
|
return normalized || "/";
|
|
521
565
|
}
|
|
522
566
|
|
|
523
|
-
function hasDynamicSegments(routePath) {
|
|
567
|
+
function hasDynamicSegments(routePath: string): boolean {
|
|
524
568
|
return routePath.split("/").some((segment) => segment.startsWith(":") || segment === "*");
|
|
525
569
|
}
|
|
526
570
|
|
|
527
|
-
function dynamicParamNames(routePath) {
|
|
571
|
+
function dynamicParamNames(routePath: string): string[] {
|
|
528
572
|
return routePath
|
|
529
573
|
.split("/")
|
|
530
574
|
.filter(Boolean)
|
|
@@ -533,10 +577,10 @@ function dynamicParamNames(routePath) {
|
|
|
533
577
|
if (segment === "*") return "slug";
|
|
534
578
|
return null;
|
|
535
579
|
})
|
|
536
|
-
.filter(
|
|
580
|
+
.filter((s): s is string => s !== null);
|
|
537
581
|
}
|
|
538
582
|
|
|
539
|
-
function routeIdFromPath(routePath) {
|
|
583
|
+
function routeIdFromPath(routePath: string): string {
|
|
540
584
|
if (routePath === "/") return "index";
|
|
541
585
|
return routePath
|
|
542
586
|
.split("/")
|
|
@@ -545,13 +589,13 @@ function routeIdFromPath(routePath) {
|
|
|
545
589
|
.join("-");
|
|
546
590
|
}
|
|
547
591
|
|
|
548
|
-
function titleFromPath(routePath) {
|
|
592
|
+
function titleFromPath(routePath: string): string {
|
|
549
593
|
if (routePath === "/") return "Home";
|
|
550
594
|
const lastSegment = routePath.split("/").filter(Boolean).at(-1) ?? "Page";
|
|
551
595
|
return titleCase(lastSegment.replace(/^:/, "").replace(/\*/g, "slug"));
|
|
552
596
|
}
|
|
553
597
|
|
|
554
|
-
function titleCase(value) {
|
|
598
|
+
function titleCase(value: string): string {
|
|
555
599
|
return value
|
|
556
600
|
.split(/[-_/]/)
|
|
557
601
|
.filter(Boolean)
|
|
@@ -559,7 +603,7 @@ function titleCase(value) {
|
|
|
559
603
|
.join(" ");
|
|
560
604
|
}
|
|
561
605
|
|
|
562
|
-
function buildStaticPathsStub(params) {
|
|
606
|
+
function buildStaticPathsStub(params: string[]): string {
|
|
563
607
|
if (params.length === 0) {
|
|
564
608
|
return "{}";
|
|
565
609
|
}
|
|
@@ -567,6 +611,6 @@ function buildStaticPathsStub(params) {
|
|
|
567
611
|
return `{ ${params.map((name) => `${name}: ${quote(`example-${name}`)}`).join(", ")} }`;
|
|
568
612
|
}
|
|
569
613
|
|
|
570
|
-
function escapeJsxText(value) {
|
|
614
|
+
function escapeJsxText(value: string): string {
|
|
571
615
|
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">");
|
|
572
616
|
}
|