@pracht/cli 1.2.0 → 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 +11 -0
- package/dist/{build-BzQAQjuy.mjs → build-DlABFPbG.mjs} +3 -1
- package/dist/{build-metadata-IABPFFKk.mjs → build-metadata-BOChHO8g.mjs} +11 -2
- package/dist/{doctor-BcoqyBk-.mjs → doctor-CQq64tfW.mjs} +1 -1
- package/dist/{generate-BXkePCIx.mjs → generate-sHtRHRAH.mjs} +15 -19
- package/dist/index.mjs +5 -5
- package/dist/{inspect-DIjjCfs3.mjs → inspect-DP-h3vLw.mjs} +4 -9
- package/dist/{project-DydjqBoS.mjs → project-DUyH_7eJ.mjs} +5 -12
- package/dist/{verification-Dfl3X4Zo.mjs → verification-CId4crSF.mjs} +1 -1
- package/dist/{verify-CObGxWtW.mjs → verify-D7Bg1Su6.mjs} +1 -1
- package/package.json +2 -2
- package/src/build-metadata.ts +17 -2
- package/src/build-shared.ts +1 -17
- package/src/commands/build.ts +5 -0
- package/src/commands/generate.ts +27 -89
- package/src/commands/inspect.ts +2 -4
- package/src/constants.ts +3 -9
- package/src/project.ts +5 -16
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# @pracht/cli
|
|
2
2
|
|
|
3
|
+
## 1.2.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#116](https://github.com/JoviDeCroock/pracht/pull/116) [`411da18`](https://github.com/JoviDeCroock/pracht/commit/411da18d0fa8bbc20270729584c6677376be7f24) Thanks [@kinngh](https://github.com/kinngh)! - Strip server-only route and shell exports from client module imports so inline loaders can statically import server-only dependencies without evaluating them in browser bundles.
|
|
8
|
+
|
|
9
|
+
- [#117](https://github.com/JoviDeCroock/pracht/pull/117) [`39a226d`](https://github.com/JoviDeCroock/pracht/commit/39a226d1023317c357df8b72e020034a2c68d896) Thanks [@JoviDeCroock](https://github.com/JoviDeCroock)! - Copy public/ folder contents to dist/client/ during build so that static assets like favicons and robots.txt are available for deployment platforms
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [[`f0ed41e`](https://github.com/JoviDeCroock/pracht/commit/f0ed41e4b886e751fbdfd29ae10f880c3aa364d4), [`49732fc`](https://github.com/JoviDeCroock/pracht/commit/49732fc78a776cbaabe9579e5a7f2fb154497479), [`d88c9e4`](https://github.com/JoviDeCroock/pracht/commit/d88c9e4b8347c4d3ecacdbc5f7674ee38af0092e), [`7ee2a93`](https://github.com/JoviDeCroock/pracht/commit/7ee2a936357a0f0b4ff7f5a7f6f3206b070f3890), [`00c4014`](https://github.com/JoviDeCroock/pracht/commit/00c401410b13c2d904c0beafc4da62dfb8f0f91e), [`f0ed41e`](https://github.com/JoviDeCroock/pracht/commit/f0ed41e4b886e751fbdfd29ae10f880c3aa364d4)]:
|
|
12
|
+
- @pracht/core@0.2.7
|
|
13
|
+
|
|
3
14
|
## 1.2.0
|
|
4
15
|
|
|
5
16
|
### Minor Changes
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { r as VERSION } from "./index.mjs";
|
|
2
|
-
import { t as readClientBuildAssets } from "./build-metadata-
|
|
2
|
+
import { t as readClientBuildAssets } from "./build-metadata-BOChHO8g.mjs";
|
|
3
3
|
import { defineCommand } from "citty";
|
|
4
4
|
import { cpSync, existsSync, mkdirSync, readdirSync, rmSync, writeFileSync } from "node:fs";
|
|
5
5
|
import { dirname, join, resolve } from "node:path";
|
|
@@ -157,6 +157,8 @@ var build_default = defineCommand({
|
|
|
157
157
|
});
|
|
158
158
|
}
|
|
159
159
|
}
|
|
160
|
+
const publicDir = resolve(root, "public");
|
|
161
|
+
if (existsSync(publicDir)) cpSync(publicDir, clientDir, { recursive: true });
|
|
160
162
|
if (existsSync(serverEntry)) {
|
|
161
163
|
const serverMod = await import(serverEntry);
|
|
162
164
|
const { prerenderApp } = serverMod;
|
|
@@ -2,6 +2,7 @@ import { existsSync, readFileSync } from "node:fs";
|
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
3
|
//#region src/build-metadata.ts
|
|
4
4
|
const MANIFEST_PATHS = ["dist/client/.vite/manifest.json", "dist/.vite/manifest.json"];
|
|
5
|
+
const PRACHT_CLIENT_MODULE_QUERY = "pracht-client";
|
|
5
6
|
function readClientBuildAssets(root = process.cwd()) {
|
|
6
7
|
const manifestPath = MANIFEST_PATHS.map((candidate) => resolve(root, candidate)).find((path) => existsSync(path));
|
|
7
8
|
if (!manifestPath) return {
|
|
@@ -36,8 +37,9 @@ function readClientBuildAssets(root = process.cwd()) {
|
|
|
36
37
|
for (const [key, entry] of Object.entries(manifest)) {
|
|
37
38
|
if (!entry.src) continue;
|
|
38
39
|
const deps = collectTransitiveDeps(key);
|
|
39
|
-
|
|
40
|
-
if (deps.
|
|
40
|
+
const manifestKey = stripPrachtClientModuleQuery(entry.src);
|
|
41
|
+
if (deps.css.length > 0) cssManifest[manifestKey] = deps.css.map((file) => `/${file}`);
|
|
42
|
+
if (deps.js.length > 0) jsManifest[manifestKey] = deps.js.map((file) => `/${file}`);
|
|
41
43
|
}
|
|
42
44
|
return {
|
|
43
45
|
clientEntryUrl: clientEntry ? `/${clientEntry.file}` : null,
|
|
@@ -45,5 +47,12 @@ function readClientBuildAssets(root = process.cwd()) {
|
|
|
45
47
|
jsManifest
|
|
46
48
|
};
|
|
47
49
|
}
|
|
50
|
+
function stripPrachtClientModuleQuery(id) {
|
|
51
|
+
const queryStart = id.indexOf("?");
|
|
52
|
+
if (queryStart === -1) return id;
|
|
53
|
+
const path = id.slice(0, queryStart);
|
|
54
|
+
const query = id.slice(queryStart + 1).split("&").filter((part) => part !== PRACHT_CLIENT_MODULE_QUERY);
|
|
55
|
+
return query.length > 0 ? `${path}?${query.join("&")}` : path;
|
|
56
|
+
}
|
|
48
57
|
//#endregion
|
|
49
58
|
export { readClientBuildAssets as t };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as toManifestModulePath, i as insertArrayItem, n as extractRegistryEntries, o as upsertObjectEntry, t as ensureCoreNamedImport } from "./manifest-DGq1n5LT.mjs";
|
|
2
|
-
import { _ as requireEnum, a as readProjectConfig, c as resolveProjectPath, d as writeGeneratedFile, f as ensureTrailingNewline, g as quote, h as parseCommaList, l as resolveRouteModulePath, m as parseApiMethods, n as displayPath, o as resolveApiModulePath, s as resolvePagesRouteModulePath, t as assertFileExists, u as resolveScopedFile, v as requirePositiveInteger } from "./project-
|
|
2
|
+
import { _ as requireEnum, a as readProjectConfig, c as resolveProjectPath, d as writeGeneratedFile, f as ensureTrailingNewline, g as quote, h as parseCommaList, l as resolveRouteModulePath, m as parseApiMethods, n as displayPath, o as resolveApiModulePath, s as resolvePagesRouteModulePath, t as assertFileExists, u as resolveScopedFile, v as requirePositiveInteger } from "./project-DUyH_7eJ.mjs";
|
|
3
3
|
import { defineCommand } from "citty";
|
|
4
4
|
import { readFileSync, writeFileSync } from "node:fs";
|
|
5
5
|
var generate_default = defineCommand({
|
|
@@ -260,7 +260,8 @@ function generateApi(args, project) {
|
|
|
260
260
|
updated: []
|
|
261
261
|
};
|
|
262
262
|
}
|
|
263
|
-
function
|
|
263
|
+
function buildRouteModuleSections(opts) {
|
|
264
|
+
const { includeErrorBoundary, includeLoader, includeStaticPaths, routePath, title } = opts;
|
|
264
265
|
const params = dynamicParamNames(routePath);
|
|
265
266
|
const imports = [];
|
|
266
267
|
const sections = [];
|
|
@@ -272,28 +273,23 @@ function buildManifestRouteModuleSource({ includeErrorBoundary, includeLoader, i
|
|
|
272
273
|
}
|
|
273
274
|
if (includeLoader) sections.push("export async function loader(_args: LoaderArgs) {", ` return { message: ${quote(`Welcome to ${title}.`)} };`, "}", "");
|
|
274
275
|
if (includeStaticPaths) sections.push("export function getStaticPaths() {", ` return [${buildStaticPathsStub(params)}];`, "}", "");
|
|
275
|
-
sections.push("export function head() {", ` return { title: ${quote(title)} };`, "}", "");
|
|
276
276
|
if (includeLoader) sections.push("export function Component({ data }: RouteComponentProps<typeof loader>) {", " return (", " <section>", ` <h1>${escapeJsxText(title)}</h1>`, " <p>{data.message}</p>", " </section>", " );", "}");
|
|
277
277
|
else sections.push("export function Component() {", " return (", " <section>", ` <h1>${escapeJsxText(title)}</h1>`, " </section>", " );", "}");
|
|
278
278
|
if (includeErrorBoundary) sections.push("", "export function ErrorBoundary({ error }: ErrorBoundaryProps) {", " return <p>{error.message}</p>;", "}");
|
|
279
|
+
return sections;
|
|
280
|
+
}
|
|
281
|
+
function buildManifestRouteModuleSource(opts) {
|
|
282
|
+
const sections = buildRouteModuleSections(opts);
|
|
283
|
+
const componentIdx = sections.findIndex((s) => s.startsWith("export function Component"));
|
|
284
|
+
const insertAt = componentIdx === -1 ? sections.length : componentIdx;
|
|
285
|
+
sections.splice(insertAt, 0, "export function head() {", ` return { title: ${quote(opts.title)} };`, "}", "");
|
|
279
286
|
return `${sections.join("\n")}\n`;
|
|
280
287
|
}
|
|
281
|
-
function buildPagesRouteModuleSource(
|
|
282
|
-
const
|
|
283
|
-
const
|
|
284
|
-
const
|
|
285
|
-
|
|
286
|
-
if (includeErrorBoundary) imports.push("ErrorBoundaryProps");
|
|
287
|
-
if (imports.length > 0) {
|
|
288
|
-
sections.push(`import type { ${imports.join(", ")} } from "@pracht/core";`);
|
|
289
|
-
sections.push("");
|
|
290
|
-
}
|
|
291
|
-
sections.push(`export const RENDER_MODE = ${quote(render)};`, "");
|
|
292
|
-
if (includeLoader) sections.push("export async function loader(_args: LoaderArgs) {", ` return { message: ${quote(`Welcome to ${title}.`)} };`, "}", "");
|
|
293
|
-
if (includeStaticPaths) sections.push("export function getStaticPaths() {", ` return [${buildStaticPathsStub(params)}];`, "}", "");
|
|
294
|
-
if (includeLoader) sections.push("export function Component({ data }: RouteComponentProps<typeof loader>) {", " return (", " <section>", ` <h1>${escapeJsxText(title)}</h1>`, " <p>{data.message}</p>", " </section>", " );", "}");
|
|
295
|
-
else sections.push("export function Component() {", " return (", " <section>", ` <h1>${escapeJsxText(title)}</h1>`, " </section>", " );", "}");
|
|
296
|
-
if (includeErrorBoundary) sections.push("", "export function ErrorBoundary({ error }: ErrorBoundaryProps) {", " return <p>{error.message}</p>;", "}");
|
|
288
|
+
function buildPagesRouteModuleSource(opts) {
|
|
289
|
+
const sections = buildRouteModuleSections(opts);
|
|
290
|
+
const firstExportIdx = sections.findIndex((s) => s.startsWith("export"));
|
|
291
|
+
const insertAt = firstExportIdx === -1 ? sections.length : firstExportIdx;
|
|
292
|
+
sections.splice(insertAt, 0, `export const RENDER_MODE = ${quote(opts.render)};`, "");
|
|
297
293
|
return `${sections.join("\n")}\n`;
|
|
298
294
|
}
|
|
299
295
|
function buildShellModuleSource(name) {
|
package/dist/index.mjs
CHANGED
|
@@ -29,12 +29,12 @@ runMain(defineCommand({
|
|
|
29
29
|
description: "The pracht CLI"
|
|
30
30
|
},
|
|
31
31
|
subCommands: {
|
|
32
|
-
build: () => import("./build-
|
|
32
|
+
build: () => import("./build-DlABFPbG.mjs").then((m) => m.default),
|
|
33
33
|
dev: () => import("./dev-BCFe3g38.mjs").then((m) => m.default),
|
|
34
|
-
doctor: () => import("./doctor-
|
|
35
|
-
generate: () => import("./generate-
|
|
36
|
-
inspect: () => import("./inspect-
|
|
37
|
-
verify: () => import("./verify-
|
|
34
|
+
doctor: () => import("./doctor-CQq64tfW.mjs").then((m) => m.default),
|
|
35
|
+
generate: () => import("./generate-sHtRHRAH.mjs").then((m) => m.default),
|
|
36
|
+
inspect: () => import("./inspect-DP-h3vLw.mjs").then((m) => m.default),
|
|
37
|
+
verify: () => import("./verify-D7Bg1Su6.mjs").then((m) => m.default)
|
|
38
38
|
}
|
|
39
39
|
}));
|
|
40
40
|
//#endregion
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { t as HTTP_METHODS } from "./index.mjs";
|
|
2
|
-
import { t as readClientBuildAssets } from "./build-metadata-
|
|
3
|
-
import { a as readProjectConfig, c as resolveProjectPath, p as handleCliError } from "./project-
|
|
2
|
+
import { t as readClientBuildAssets } from "./build-metadata-BOChHO8g.mjs";
|
|
3
|
+
import { a as readProjectConfig, c as resolveProjectPath, p as handleCliError } from "./project-DUyH_7eJ.mjs";
|
|
4
4
|
import { defineCommand } from "citty";
|
|
5
|
-
import { readFileSync } from "node:fs";
|
|
5
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
6
6
|
import { resolve } from "node:path";
|
|
7
7
|
import { createServer } from "vite";
|
|
8
8
|
//#region src/commands/inspect.ts
|
|
@@ -45,12 +45,7 @@ async function runInspect(root, { target = "all" } = {}) {
|
|
|
45
45
|
if (!project.configFile) throw new Error("Missing vite config. `pracht inspect` requires a project with pracht configured.");
|
|
46
46
|
if (!project.hasPrachtPlugin) throw new Error("vite.config does not appear to register the pracht plugin.");
|
|
47
47
|
if (project.mode === "manifest") {
|
|
48
|
-
|
|
49
|
-
try {
|
|
50
|
-
readFileSync(manifestPath, "utf-8");
|
|
51
|
-
} catch {
|
|
52
|
-
throw new Error(`App manifest is missing at ${project.appFile}.`);
|
|
53
|
-
}
|
|
48
|
+
if (!existsSync(resolveProjectPath(project.root, project.appFile))) throw new Error(`App manifest is missing at ${project.appFile}.`);
|
|
54
49
|
}
|
|
55
50
|
const server = await createServer({
|
|
56
51
|
root,
|
|
@@ -67,7 +67,7 @@ function resolveScopedFile(root, configDir, fileName) {
|
|
|
67
67
|
return resolve(resolveProjectPath(root, configDir), fileName);
|
|
68
68
|
}
|
|
69
69
|
function resolveRouteModulePath(project, routePath, extension) {
|
|
70
|
-
const segments =
|
|
70
|
+
const segments = segmentsFromPath(routePath);
|
|
71
71
|
const relativePath = segments.length === 0 ? `index${extension}` : `${segments.join("/")}${extension}`;
|
|
72
72
|
return {
|
|
73
73
|
absolutePath: resolve(resolveProjectPath(project.root, project.routesDir), relativePath),
|
|
@@ -75,7 +75,7 @@ function resolveRouteModulePath(project, routePath, extension) {
|
|
|
75
75
|
};
|
|
76
76
|
}
|
|
77
77
|
function resolvePagesRouteModulePath(project, routePath, extension) {
|
|
78
|
-
const segments =
|
|
78
|
+
const segments = segmentsFromPath(routePath);
|
|
79
79
|
const relativePath = segments.length === 0 ? `index${extension}` : `${segments.join("/")}${extension}`;
|
|
80
80
|
return {
|
|
81
81
|
absolutePath: resolve(resolveProjectPath(project.root, project.pagesDir), relativePath),
|
|
@@ -83,7 +83,7 @@ function resolvePagesRouteModulePath(project, routePath, extension) {
|
|
|
83
83
|
};
|
|
84
84
|
}
|
|
85
85
|
function resolveApiModulePath(project, endpointPath) {
|
|
86
|
-
const segments =
|
|
86
|
+
const segments = segmentsFromPath(endpointPath);
|
|
87
87
|
const relativePath = segments.length === 0 ? "index.ts" : `${segments.join("/")}.ts`;
|
|
88
88
|
return {
|
|
89
89
|
absolutePath: resolve(resolveProjectPath(project.root, project.apiDir), relativePath),
|
|
@@ -137,15 +137,8 @@ function normalizeConfigPath(value) {
|
|
|
137
137
|
if (!value) return value;
|
|
138
138
|
return value.startsWith("/") ? value : `/${value}`;
|
|
139
139
|
}
|
|
140
|
-
function
|
|
141
|
-
return
|
|
142
|
-
if (segment.startsWith(":")) return `[${segment.slice(1)}]`;
|
|
143
|
-
if (segment === "*") return "[...slug]";
|
|
144
|
-
return segment;
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
function segmentsFromApiPath(endpointPath) {
|
|
148
|
-
return endpointPath.split("/").filter(Boolean).map((segment) => {
|
|
140
|
+
function segmentsFromPath(path) {
|
|
141
|
+
return path.split("/").filter(Boolean).map((segment) => {
|
|
149
142
|
if (segment.startsWith(":")) return `[${segment.slice(1)}]`;
|
|
150
143
|
if (segment === "*") return "[...slug]";
|
|
151
144
|
return segment;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as extractRegistryEntries, r as extractRelativeModulePaths } from "./manifest-DGq1n5LT.mjs";
|
|
2
|
-
import { a as readProjectConfig, c as resolveProjectPath, i as listFilesRecursively, n as displayPath, r as hasPagesAppShell } from "./project-
|
|
2
|
+
import { a as readProjectConfig, c as resolveProjectPath, i as listFilesRecursively, n as displayPath, r as hasPagesAppShell } from "./project-DUyH_7eJ.mjs";
|
|
3
3
|
import { existsSync, readFileSync } from "node:fs";
|
|
4
4
|
import { basename, dirname, relative, resolve } from "node:path";
|
|
5
5
|
import { execFileSync } from "node:child_process";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pracht/cli",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"homepage": "https://github.com/JoviDeCroock/pracht/tree/main/packages/cli",
|
|
6
6
|
"bugs": {
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"citty": "^0.1.6",
|
|
23
|
-
"@pracht/core": "0.2.
|
|
23
|
+
"@pracht/core": "0.2.7"
|
|
24
24
|
},
|
|
25
25
|
"scripts": {
|
|
26
26
|
"build": "tsdown"
|
package/src/build-metadata.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { existsSync, readFileSync } from "node:fs";
|
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
3
|
|
|
4
4
|
const MANIFEST_PATHS = ["dist/client/.vite/manifest.json", "dist/.vite/manifest.json"];
|
|
5
|
+
const PRACHT_CLIENT_MODULE_QUERY = "pracht-client";
|
|
5
6
|
|
|
6
7
|
interface ViteManifestEntry {
|
|
7
8
|
css?: string[];
|
|
@@ -70,11 +71,12 @@ export function readClientBuildAssets(root: string = process.cwd()): ClientBuild
|
|
|
70
71
|
if (!entry.src) continue;
|
|
71
72
|
|
|
72
73
|
const deps = collectTransitiveDeps(key);
|
|
74
|
+
const manifestKey = stripPrachtClientModuleQuery(entry.src);
|
|
73
75
|
if (deps.css.length > 0) {
|
|
74
|
-
cssManifest[
|
|
76
|
+
cssManifest[manifestKey] = deps.css.map((file) => `/${file}`);
|
|
75
77
|
}
|
|
76
78
|
if (deps.js.length > 0) {
|
|
77
|
-
jsManifest[
|
|
79
|
+
jsManifest[manifestKey] = deps.js.map((file) => `/${file}`);
|
|
78
80
|
}
|
|
79
81
|
}
|
|
80
82
|
|
|
@@ -84,3 +86,16 @@ export function readClientBuildAssets(root: string = process.cwd()): ClientBuild
|
|
|
84
86
|
jsManifest,
|
|
85
87
|
};
|
|
86
88
|
}
|
|
89
|
+
|
|
90
|
+
function stripPrachtClientModuleQuery(id: string): string {
|
|
91
|
+
const queryStart = id.indexOf("?");
|
|
92
|
+
if (queryStart === -1) return id;
|
|
93
|
+
|
|
94
|
+
const path = id.slice(0, queryStart);
|
|
95
|
+
const query = id
|
|
96
|
+
.slice(queryStart + 1)
|
|
97
|
+
.split("&")
|
|
98
|
+
.filter((part) => part !== PRACHT_CLIENT_MODULE_QUERY);
|
|
99
|
+
|
|
100
|
+
return query.length > 0 ? `${path}?${query.join("&")}` : path;
|
|
101
|
+
}
|
package/src/build-shared.ts
CHANGED
|
@@ -1,26 +1,10 @@
|
|
|
1
1
|
import { cpSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { VERSION } from "./constants.js";
|
|
5
5
|
|
|
6
6
|
const ROUTE_STATE_REQUEST_HEADER = "x-pracht-route-state-request";
|
|
7
7
|
|
|
8
|
-
interface HeaderSettable {
|
|
9
|
-
setHeader(key: string, value: string): void;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export function setDefaultSecurityHeaders(
|
|
13
|
-
res: HeaderSettable,
|
|
14
|
-
headers: Record<string, string> = {},
|
|
15
|
-
): void {
|
|
16
|
-
for (const [key, value] of Object.entries({
|
|
17
|
-
...DEFAULT_SECURITY_HEADERS,
|
|
18
|
-
...headers,
|
|
19
|
-
})) {
|
|
20
|
-
res.setHeader(key, value);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
8
|
interface VercelBuildOutputOptions {
|
|
25
9
|
functionName?: string;
|
|
26
10
|
headersManifest?: Record<string, Record<string, string>>;
|
package/src/commands/build.ts
CHANGED
|
@@ -53,6 +53,11 @@ export default defineCommand({
|
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
const publicDir = resolve(root, "public");
|
|
57
|
+
if (existsSync(publicDir)) {
|
|
58
|
+
cpSync(publicDir, clientDir, { recursive: true });
|
|
59
|
+
}
|
|
60
|
+
|
|
56
61
|
if (existsSync(serverEntry)) {
|
|
57
62
|
const serverMod = await import(serverEntry);
|
|
58
63
|
const { prerenderApp } = serverMod;
|
package/src/commands/generate.ts
CHANGED
|
@@ -361,19 +361,16 @@ function generateApi(args: ApiArgs, project: ProjectConfig): GenerateResult {
|
|
|
361
361
|
};
|
|
362
362
|
}
|
|
363
363
|
|
|
364
|
-
|
|
365
|
-
includeErrorBoundary,
|
|
366
|
-
includeLoader,
|
|
367
|
-
includeStaticPaths,
|
|
368
|
-
routePath,
|
|
369
|
-
title,
|
|
370
|
-
}: {
|
|
364
|
+
interface RouteModuleParts {
|
|
371
365
|
includeErrorBoundary: boolean;
|
|
372
366
|
includeLoader: boolean;
|
|
373
367
|
includeStaticPaths: boolean;
|
|
374
368
|
routePath: string;
|
|
375
369
|
title: string;
|
|
376
|
-
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
function buildRouteModuleSections(opts: RouteModuleParts): string[] {
|
|
373
|
+
const { includeErrorBoundary, includeLoader, includeStaticPaths, routePath, title } = opts;
|
|
377
374
|
const params = dynamicParamNames(routePath);
|
|
378
375
|
const imports: string[] = [];
|
|
379
376
|
const sections: string[] = [];
|
|
@@ -408,8 +405,6 @@ function buildManifestRouteModuleSource({
|
|
|
408
405
|
);
|
|
409
406
|
}
|
|
410
407
|
|
|
411
|
-
sections.push("export function head() {", ` return { title: ${quote(title)} };`, "}", "");
|
|
412
|
-
|
|
413
408
|
if (includeLoader) {
|
|
414
409
|
sections.push(
|
|
415
410
|
"export function Component({ data }: RouteComponentProps<typeof loader>) {",
|
|
@@ -442,91 +437,34 @@ function buildManifestRouteModuleSource({
|
|
|
442
437
|
);
|
|
443
438
|
}
|
|
444
439
|
|
|
445
|
-
return
|
|
440
|
+
return sections;
|
|
446
441
|
}
|
|
447
442
|
|
|
448
|
-
function
|
|
449
|
-
|
|
450
|
-
includeLoader,
|
|
451
|
-
includeStaticPaths,
|
|
452
|
-
render,
|
|
453
|
-
routePath,
|
|
454
|
-
title,
|
|
455
|
-
}: {
|
|
456
|
-
includeErrorBoundary: boolean;
|
|
457
|
-
includeLoader: boolean;
|
|
458
|
-
includeStaticPaths: boolean;
|
|
459
|
-
render: string;
|
|
460
|
-
routePath: string;
|
|
461
|
-
title: string;
|
|
462
|
-
}): string {
|
|
463
|
-
const params = dynamicParamNames(routePath);
|
|
464
|
-
const imports: string[] = [];
|
|
465
|
-
const sections: string[] = [];
|
|
466
|
-
|
|
467
|
-
if (includeLoader) {
|
|
468
|
-
imports.push("LoaderArgs", "RouteComponentProps");
|
|
469
|
-
}
|
|
470
|
-
if (includeErrorBoundary) {
|
|
471
|
-
imports.push("ErrorBoundaryProps");
|
|
472
|
-
}
|
|
443
|
+
function buildManifestRouteModuleSource(opts: RouteModuleParts): string {
|
|
444
|
+
const sections = buildRouteModuleSections(opts);
|
|
473
445
|
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
"}",
|
|
486
|
-
"",
|
|
487
|
-
);
|
|
488
|
-
}
|
|
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
|
+
);
|
|
489
457
|
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
"export function getStaticPaths() {",
|
|
493
|
-
` return [${buildStaticPathsStub(params)}];`,
|
|
494
|
-
"}",
|
|
495
|
-
"",
|
|
496
|
-
);
|
|
497
|
-
}
|
|
458
|
+
return `${sections.join("\n")}\n`;
|
|
459
|
+
}
|
|
498
460
|
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
"export function Component({ data }: RouteComponentProps<typeof loader>) {",
|
|
502
|
-
" return (",
|
|
503
|
-
" <section>",
|
|
504
|
-
` <h1>${escapeJsxText(title)}</h1>`,
|
|
505
|
-
" <p>{data.message}</p>",
|
|
506
|
-
" </section>",
|
|
507
|
-
" );",
|
|
508
|
-
"}",
|
|
509
|
-
);
|
|
510
|
-
} else {
|
|
511
|
-
sections.push(
|
|
512
|
-
"export function Component() {",
|
|
513
|
-
" return (",
|
|
514
|
-
" <section>",
|
|
515
|
-
` <h1>${escapeJsxText(title)}</h1>`,
|
|
516
|
-
" </section>",
|
|
517
|
-
" );",
|
|
518
|
-
"}",
|
|
519
|
-
);
|
|
520
|
-
}
|
|
461
|
+
function buildPagesRouteModuleSource(opts: RouteModuleParts & { render: string }): string {
|
|
462
|
+
const sections = buildRouteModuleSections(opts);
|
|
521
463
|
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
" return <p>{error.message}</p>;",
|
|
527
|
-
"}",
|
|
528
|
-
);
|
|
529
|
-
}
|
|
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)};`, "");
|
|
530
468
|
|
|
531
469
|
return `${sections.join("\n")}\n`;
|
|
532
470
|
}
|
package/src/commands/inspect.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readFileSync } from "node:fs";
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
3
|
|
|
4
4
|
import { defineCommand } from "citty";
|
|
@@ -85,9 +85,7 @@ async function runInspect(root: string, { target = "all" } = {}): Promise<Inspec
|
|
|
85
85
|
|
|
86
86
|
if (project.mode === "manifest") {
|
|
87
87
|
const manifestPath = resolveProjectPath(project.root, project.appFile);
|
|
88
|
-
|
|
89
|
-
readFileSync(manifestPath, "utf-8");
|
|
90
|
-
} catch {
|
|
88
|
+
if (!existsSync(manifestPath)) {
|
|
91
89
|
throw new Error(`App manifest is missing at ${project.appFile}.`);
|
|
92
90
|
}
|
|
93
91
|
}
|
package/src/constants.ts
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
"referrer-policy": "strict-origin-when-cross-origin",
|
|
5
|
-
"x-content-type-options": "nosniff",
|
|
6
|
-
"x-frame-options": "SAMEORIGIN",
|
|
7
|
-
};
|
|
1
|
+
import type { HttpMethod } from "@pracht/core";
|
|
2
|
+
|
|
3
|
+
export type { HttpMethod };
|
|
8
4
|
|
|
9
5
|
export const VERSION = "0.0.0";
|
|
10
6
|
|
|
@@ -19,8 +15,6 @@ export const PROJECT_DEFAULTS = {
|
|
|
19
15
|
shellsDir: "/src/shells",
|
|
20
16
|
};
|
|
21
17
|
|
|
22
|
-
export type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "HEAD" | "OPTIONS";
|
|
23
|
-
|
|
24
18
|
export const HTTP_METHODS = new Set<HttpMethod>([
|
|
25
19
|
"GET",
|
|
26
20
|
"POST",
|
package/src/project.ts
CHANGED
|
@@ -56,7 +56,7 @@ export function resolveRouteModulePath(
|
|
|
56
56
|
routePath: string,
|
|
57
57
|
extension: string,
|
|
58
58
|
): { absolutePath: string; relativePath: string } {
|
|
59
|
-
const segments =
|
|
59
|
+
const segments = segmentsFromPath(routePath);
|
|
60
60
|
const relativePath =
|
|
61
61
|
segments.length === 0 ? `index${extension}` : `${segments.join("/")}${extension}`;
|
|
62
62
|
const absolutePath = resolve(resolveProjectPath(project.root, project.routesDir), relativePath);
|
|
@@ -68,7 +68,7 @@ export function resolvePagesRouteModulePath(
|
|
|
68
68
|
routePath: string,
|
|
69
69
|
extension: string,
|
|
70
70
|
): { absolutePath: string; relativePath: string } {
|
|
71
|
-
const segments =
|
|
71
|
+
const segments = segmentsFromPath(routePath);
|
|
72
72
|
const relativePath =
|
|
73
73
|
segments.length === 0 ? `index${extension}` : `${segments.join("/")}${extension}`;
|
|
74
74
|
const absolutePath = resolve(resolveProjectPath(project.root, project.pagesDir), relativePath);
|
|
@@ -79,7 +79,7 @@ export function resolveApiModulePath(
|
|
|
79
79
|
project: ProjectConfig,
|
|
80
80
|
endpointPath: string,
|
|
81
81
|
): { absolutePath: string; relativePath: string } {
|
|
82
|
-
const segments =
|
|
82
|
+
const segments = segmentsFromPath(endpointPath);
|
|
83
83
|
const relativePath = segments.length === 0 ? "index.ts" : `${segments.join("/")}.ts`;
|
|
84
84
|
const absolutePath = resolve(resolveProjectPath(project.root, project.apiDir), relativePath);
|
|
85
85
|
return { absolutePath, relativePath };
|
|
@@ -148,19 +148,8 @@ function normalizeConfigPath(value: string): string {
|
|
|
148
148
|
return value.startsWith("/") ? value : `/${value}`;
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
-
function
|
|
152
|
-
return
|
|
153
|
-
.split("/")
|
|
154
|
-
.filter(Boolean)
|
|
155
|
-
.map((segment) => {
|
|
156
|
-
if (segment.startsWith(":")) return `[${segment.slice(1)}]`;
|
|
157
|
-
if (segment === "*") return "[...slug]";
|
|
158
|
-
return segment;
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
function segmentsFromApiPath(endpointPath: string): string[] {
|
|
163
|
-
return endpointPath
|
|
151
|
+
function segmentsFromPath(path: string): string[] {
|
|
152
|
+
return path
|
|
164
153
|
.split("/")
|
|
165
154
|
.filter(Boolean)
|
|
166
155
|
.map((segment) => {
|