raktajs 0.1.0
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/README.md +90 -0
- package/dist/auto-import/generator.d.ts +4 -0
- package/dist/auto-import/generator.d.ts.map +1 -0
- package/dist/auto-import/index.d.ts +5 -0
- package/dist/auto-import/index.d.ts.map +1 -0
- package/dist/auto-import/index.js +153 -0
- package/dist/auto-import/index.js.map +11 -0
- package/dist/auto-import/scanner.d.ts +9 -0
- package/dist/auto-import/scanner.d.ts.map +1 -0
- package/dist/auto-import/types.d.ts +20 -0
- package/dist/auto-import/types.d.ts.map +1 -0
- package/dist/cli/build.d.ts +2 -0
- package/dist/cli/build.d.ts.map +1 -0
- package/dist/cli/dev.d.ts +2 -0
- package/dist/cli/dev.d.ts.map +1 -0
- package/dist/cli/doctor.d.ts +2 -0
- package/dist/cli/doctor.d.ts.map +1 -0
- package/dist/cli/imports.d.ts +2 -0
- package/dist/cli/imports.d.ts.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/make.d.ts +4 -0
- package/dist/cli/make.d.ts.map +1 -0
- package/dist/cli/rakta.d.ts +3 -0
- package/dist/cli/rakta.d.ts.map +1 -0
- package/dist/cli/rakta.js +1511 -0
- package/dist/cli/rakta.js.map +33 -0
- package/dist/cli/routes.d.ts +2 -0
- package/dist/cli/routes.d.ts.map +1 -0
- package/dist/cli/rpcTypes.d.ts +2 -0
- package/dist/cli/rpcTypes.d.ts.map +1 -0
- package/dist/cli/seo.d.ts +2 -0
- package/dist/cli/seo.d.ts.map +1 -0
- package/dist/cli/start.d.ts +2 -0
- package/dist/cli/start.d.ts.map +1 -0
- package/dist/components/Click.d.ts +11 -0
- package/dist/components/Click.d.ts.map +1 -0
- package/dist/components/Picture.d.ts +22 -0
- package/dist/components/Picture.d.ts.map +1 -0
- package/dist/components/index.d.ts +5 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +1383 -0
- package/dist/components/index.js.map +15 -0
- package/dist/config/defineConfig.d.ts +64 -0
- package/dist/config/defineConfig.d.ts.map +1 -0
- package/dist/config/index.d.ts +4 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +104 -0
- package/dist/config/index.js.map +11 -0
- package/dist/config/loadConfig.d.ts +4 -0
- package/dist/config/loadConfig.d.ts.map +1 -0
- package/dist/forge/build.d.ts +7 -0
- package/dist/forge/build.d.ts.map +1 -0
- package/dist/forge/devServer.d.ts +7 -0
- package/dist/forge/devServer.d.ts.map +1 -0
- package/dist/forge/index.d.ts +6 -0
- package/dist/forge/index.d.ts.map +1 -0
- package/dist/forge/index.js +579 -0
- package/dist/forge/index.js.map +17 -0
- package/dist/forge/inspect.d.ts +9 -0
- package/dist/forge/inspect.d.ts.map +1 -0
- package/dist/forge/types.d.ts +55 -0
- package/dist/forge/types.d.ts.map +1 -0
- package/dist/http/errors.d.ts +17 -0
- package/dist/http/errors.d.ts.map +1 -0
- package/dist/http/index.d.ts +4 -0
- package/dist/http/index.d.ts.map +1 -0
- package/dist/http/index.js +154 -0
- package/dist/http/index.js.map +11 -0
- package/dist/http/panturaFetch.d.ts +33 -0
- package/dist/http/panturaFetch.d.ts.map +1 -0
- package/dist/http/types.d.ts +24 -0
- package/dist/http/types.d.ts.map +1 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3872 -0
- package/dist/index.js.map +50 -0
- package/dist/pwa/cache.d.ts +6 -0
- package/dist/pwa/cache.d.ts.map +1 -0
- package/dist/pwa/index.d.ts +5 -0
- package/dist/pwa/index.d.ts.map +1 -0
- package/dist/pwa/index.js +136 -0
- package/dist/pwa/index.js.map +12 -0
- package/dist/pwa/manifest.d.ts +11 -0
- package/dist/pwa/manifest.d.ts.map +1 -0
- package/dist/pwa/serviceWorker.d.ts +11 -0
- package/dist/pwa/serviceWorker.d.ts.map +1 -0
- package/dist/pwa/types.d.ts +45 -0
- package/dist/pwa/types.d.ts.map +1 -0
- package/dist/render/index.d.ts +5 -0
- package/dist/render/index.d.ts.map +1 -0
- package/dist/render/index.js +183 -0
- package/dist/render/index.js.map +11 -0
- package/dist/render/modes.d.ts +13 -0
- package/dist/render/modes.d.ts.map +1 -0
- package/dist/render/renderer.d.ts +15 -0
- package/dist/render/renderer.d.ts.map +1 -0
- package/dist/render/types.d.ts +72 -0
- package/dist/render/types.d.ts.map +1 -0
- package/dist/router/index.d.ts +5 -0
- package/dist/router/index.d.ts.map +1 -0
- package/dist/router/index.js +228 -0
- package/dist/router/index.js.map +12 -0
- package/dist/router/manifest.d.ts +6 -0
- package/dist/router/manifest.d.ts.map +1 -0
- package/dist/router/matcher.d.ts +5 -0
- package/dist/router/matcher.d.ts.map +1 -0
- package/dist/router/scanner.d.ts +6 -0
- package/dist/router/scanner.d.ts.map +1 -0
- package/dist/router/types.d.ts +45 -0
- package/dist/router/types.d.ts.map +1 -0
- package/dist/rpc/client.d.ts +24 -0
- package/dist/rpc/client.d.ts.map +1 -0
- package/dist/rpc/index.d.ts +6 -0
- package/dist/rpc/index.d.ts.map +1 -0
- package/dist/rpc/index.js +179 -0
- package/dist/rpc/index.js.map +13 -0
- package/dist/rpc/procedure.d.ts +28 -0
- package/dist/rpc/procedure.d.ts.map +1 -0
- package/dist/rpc/router.d.ts +12 -0
- package/dist/rpc/router.d.ts.map +1 -0
- package/dist/rpc/types.d.ts +48 -0
- package/dist/rpc/types.d.ts.map +1 -0
- package/dist/schema/array.d.ts +15 -0
- package/dist/schema/array.d.ts.map +1 -0
- package/dist/schema/boolean.d.ts +7 -0
- package/dist/schema/boolean.d.ts.map +1 -0
- package/dist/schema/errors.d.ts +21 -0
- package/dist/schema/errors.d.ts.map +1 -0
- package/dist/schema/index.d.ts +11 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/index.js +393 -0
- package/dist/schema/index.js.map +16 -0
- package/dist/schema/number.d.ts +17 -0
- package/dist/schema/number.d.ts.map +1 -0
- package/dist/schema/object.d.ts +19 -0
- package/dist/schema/object.d.ts.map +1 -0
- package/dist/schema/string.d.ts +18 -0
- package/dist/schema/string.d.ts.map +1 -0
- package/dist/schema/types.d.ts +27 -0
- package/dist/schema/types.d.ts.map +1 -0
- package/dist/seo/head.d.ts +8 -0
- package/dist/seo/head.d.ts.map +1 -0
- package/dist/seo/index.d.ts +9 -0
- package/dist/seo/index.d.ts.map +1 -0
- package/dist/seo/index.js +1578 -0
- package/dist/seo/index.js.map +17 -0
- package/dist/seo/metadata.d.ts +106 -0
- package/dist/seo/metadata.d.ts.map +1 -0
- package/dist/seo/robots.d.ts +14 -0
- package/dist/seo/robots.d.ts.map +1 -0
- package/dist/seo/sitemap.d.ts +27 -0
- package/dist/seo/sitemap.d.ts.map +1 -0
- package/dist/store/createStore.d.ts +18 -0
- package/dist/store/createStore.d.ts.map +1 -0
- package/dist/store/index.d.ts +3 -0
- package/dist/store/index.d.ts.map +1 -0
- package/dist/store/index.js +925 -0
- package/dist/store/index.js.map +12 -0
- package/dist/store/types.d.ts +14 -0
- package/dist/store/types.d.ts.map +1 -0
- package/dist/tide/adapter.d.ts +8 -0
- package/dist/tide/adapter.d.ts.map +1 -0
- package/dist/tide/index.d.ts +4 -0
- package/dist/tide/index.d.ts.map +1 -0
- package/dist/tide/index.js +477 -0
- package/dist/tide/index.js.map +16 -0
- package/dist/tide/runtime.d.ts +8 -0
- package/dist/tide/runtime.d.ts.map +1 -0
- package/dist/tide/types.d.ts +40 -0
- package/dist/tide/types.d.ts.map +1 -0
- package/package.json +128 -0
|
@@ -0,0 +1,579 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// src/forge/build.ts
|
|
3
|
+
import { mkdirSync } from "fs";
|
|
4
|
+
import { join as join2, resolve } from "path";
|
|
5
|
+
|
|
6
|
+
// src/router/manifest.ts
|
|
7
|
+
import { existsSync as existsSync2, readFileSync, writeFileSync } from "fs";
|
|
8
|
+
|
|
9
|
+
// src/router/scanner.ts
|
|
10
|
+
import { existsSync, readdirSync, statSync } from "fs";
|
|
11
|
+
import { join, relative } from "path";
|
|
12
|
+
var FILE_TO_KIND = {
|
|
13
|
+
"page.tsx": "page",
|
|
14
|
+
"page.ts": "page",
|
|
15
|
+
"page.jsx": "page",
|
|
16
|
+
"page.js": "page",
|
|
17
|
+
"layout.tsx": "layout",
|
|
18
|
+
"layout.ts": "layout",
|
|
19
|
+
"layout.jsx": "layout",
|
|
20
|
+
"layout.js": "layout",
|
|
21
|
+
"loading.tsx": "loading",
|
|
22
|
+
"loading.ts": "loading",
|
|
23
|
+
"loading.jsx": "loading",
|
|
24
|
+
"loading.js": "loading",
|
|
25
|
+
"notFound.tsx": "notFound",
|
|
26
|
+
"notFound.ts": "notFound",
|
|
27
|
+
"notFound.jsx": "notFound",
|
|
28
|
+
"notFound.js": "notFound",
|
|
29
|
+
"error.tsx": "error",
|
|
30
|
+
"error.ts": "error",
|
|
31
|
+
"error.jsx": "error",
|
|
32
|
+
"error.js": "error",
|
|
33
|
+
"route.ts": "api",
|
|
34
|
+
"route.js": "api"
|
|
35
|
+
};
|
|
36
|
+
function parseSegment(raw) {
|
|
37
|
+
const isDynamic = raw.startsWith("[") && raw.endsWith("]");
|
|
38
|
+
const paramName = isDynamic ? raw.slice(1, -1) : "";
|
|
39
|
+
return { raw, isDynamic, paramName };
|
|
40
|
+
}
|
|
41
|
+
function collectParamNames(segments) {
|
|
42
|
+
return segments.filter((segment) => segment.isDynamic && segment.paramName.length > 0).map((segment) => segment.paramName);
|
|
43
|
+
}
|
|
44
|
+
function segmentsToUrlPattern(segments) {
|
|
45
|
+
if (segments.length === 0)
|
|
46
|
+
return "/";
|
|
47
|
+
const parts = segments.map((segment) => segment.isDynamic && segment.paramName ? `:${segment.paramName}` : segment.raw);
|
|
48
|
+
return `/${parts.join("/")}`;
|
|
49
|
+
}
|
|
50
|
+
function scanDirectory(dirPath, appRoot, results) {
|
|
51
|
+
if (!existsSync(dirPath))
|
|
52
|
+
return;
|
|
53
|
+
const entries = readdirSync(dirPath);
|
|
54
|
+
for (const entryName of entries) {
|
|
55
|
+
const fullPath = join(dirPath, entryName);
|
|
56
|
+
const stats = statSync(fullPath);
|
|
57
|
+
if (stats.isDirectory()) {
|
|
58
|
+
scanDirectory(fullPath, appRoot, results);
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
if (!stats.isFile())
|
|
62
|
+
continue;
|
|
63
|
+
const kind = FILE_TO_KIND[entryName];
|
|
64
|
+
if (!kind)
|
|
65
|
+
continue;
|
|
66
|
+
const relativePath = relative(appRoot, fullPath).replace(/\\/g, "/");
|
|
67
|
+
const dirRelative = relative(appRoot, dirPath).replace(/\\/g, "/");
|
|
68
|
+
const rawSegments = dirRelative === "" ? [] : dirRelative.split("/");
|
|
69
|
+
const segments = rawSegments.map(parseSegment);
|
|
70
|
+
const urlPattern = segmentsToUrlPattern(segments);
|
|
71
|
+
const paramNames = collectParamNames(segments);
|
|
72
|
+
const isDynamic = paramNames.length > 0;
|
|
73
|
+
results.push({
|
|
74
|
+
filePath: relativePath,
|
|
75
|
+
urlPattern,
|
|
76
|
+
kind,
|
|
77
|
+
segments,
|
|
78
|
+
isDynamic,
|
|
79
|
+
paramNames
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function scanRoutes(options) {
|
|
84
|
+
const results = [];
|
|
85
|
+
scanDirectory(options.appDir, options.appDir, results);
|
|
86
|
+
results.sort((routeA, routeB) => {
|
|
87
|
+
if (routeA.isDynamic !== routeB.isDynamic) {
|
|
88
|
+
return routeA.isDynamic ? 1 : -1;
|
|
89
|
+
}
|
|
90
|
+
return routeA.urlPattern.localeCompare(routeB.urlPattern);
|
|
91
|
+
});
|
|
92
|
+
return results;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// src/router/manifest.ts
|
|
96
|
+
function generateManifest(appDir) {
|
|
97
|
+
const routes = scanRoutes({ appDir });
|
|
98
|
+
const manifest = {
|
|
99
|
+
version: "1",
|
|
100
|
+
generatedAt: new Date().toISOString(),
|
|
101
|
+
routes
|
|
102
|
+
};
|
|
103
|
+
return manifest;
|
|
104
|
+
}
|
|
105
|
+
function writeManifest(manifest, outputPath) {
|
|
106
|
+
writeFileSync(outputPath, JSON.stringify(manifest, null, 2), "utf-8");
|
|
107
|
+
}
|
|
108
|
+
function readManifest(manifestPath) {
|
|
109
|
+
if (!existsSync2(manifestPath))
|
|
110
|
+
return null;
|
|
111
|
+
const raw = readFileSync(manifestPath, "utf-8");
|
|
112
|
+
const parsed = JSON.parse(raw);
|
|
113
|
+
if (typeof parsed !== "object" || parsed === null || !("version" in parsed) || !("routes" in parsed)) {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
return parsed;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// src/forge/build.ts
|
|
120
|
+
async function buildProject(options) {
|
|
121
|
+
const startMs = Date.now();
|
|
122
|
+
const artifacts = [];
|
|
123
|
+
const errors = [];
|
|
124
|
+
mkdirSync(resolve(options.outDir), { recursive: true });
|
|
125
|
+
const manifest = generateManifest(options.appDir);
|
|
126
|
+
const manifestPath = join2(options.outDir, "route-manifest.json");
|
|
127
|
+
writeManifest(manifest, manifestPath);
|
|
128
|
+
const manifestContent = JSON.stringify(manifest);
|
|
129
|
+
artifacts.push({
|
|
130
|
+
outputPath: manifestPath,
|
|
131
|
+
sizeBytes: new TextEncoder().encode(manifestContent).byteLength,
|
|
132
|
+
kind: "manifest"
|
|
133
|
+
});
|
|
134
|
+
const buildResult = await Bun.build({
|
|
135
|
+
entrypoints: [options.entryPoint],
|
|
136
|
+
outdir: options.outDir,
|
|
137
|
+
target: options.target,
|
|
138
|
+
minify: options.minify,
|
|
139
|
+
sourcemap: options.sourcemap ? "external" : "none",
|
|
140
|
+
splitting: options.splitting,
|
|
141
|
+
naming: {
|
|
142
|
+
entry: "[name].[ext]",
|
|
143
|
+
chunk: "chunks/[name]-[hash].[ext]",
|
|
144
|
+
asset: "assets/[name]-[hash].[ext]"
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
if (!buildResult.success) {
|
|
148
|
+
for (const log of buildResult.logs) {
|
|
149
|
+
errors.push(log.message);
|
|
150
|
+
}
|
|
151
|
+
return {
|
|
152
|
+
success: false,
|
|
153
|
+
artifacts,
|
|
154
|
+
manifest,
|
|
155
|
+
buildMs: Date.now() - startMs,
|
|
156
|
+
errors
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
for (const output of buildResult.outputs) {
|
|
160
|
+
artifacts.push({
|
|
161
|
+
outputPath: output.path,
|
|
162
|
+
sizeBytes: output.size,
|
|
163
|
+
kind: output.path.endsWith(".css") ? "stylesheet" : "script"
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
return {
|
|
167
|
+
success: true,
|
|
168
|
+
artifacts,
|
|
169
|
+
manifest,
|
|
170
|
+
buildMs: Date.now() - startMs,
|
|
171
|
+
errors: []
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
// src/forge/devServer.ts
|
|
175
|
+
import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
|
|
176
|
+
import { join as join3 } from "path";
|
|
177
|
+
|
|
178
|
+
// src/render/modes.ts
|
|
179
|
+
var RENDER_MODE_DESCRIPTORS = {
|
|
180
|
+
csr: {
|
|
181
|
+
mode: "csr",
|
|
182
|
+
label: "Client-Side Rendering",
|
|
183
|
+
shortLabel: "CSR",
|
|
184
|
+
description: "React renders entirely in the browser. The server sends a minimal HTML shell with a JS bundle. No server required at runtime.",
|
|
185
|
+
serverRequired: false,
|
|
186
|
+
buildTimeGenerated: false,
|
|
187
|
+
clientHydration: true,
|
|
188
|
+
roadmap: false
|
|
189
|
+
},
|
|
190
|
+
ssr: {
|
|
191
|
+
mode: "ssr",
|
|
192
|
+
label: "Server-Side Rendering",
|
|
193
|
+
shortLabel: "SSR",
|
|
194
|
+
description: "React renders to HTML on the server per request. The client receives full HTML and then hydrates. Requires a running Node/Bun server.",
|
|
195
|
+
serverRequired: true,
|
|
196
|
+
buildTimeGenerated: false,
|
|
197
|
+
clientHydration: true,
|
|
198
|
+
roadmap: true
|
|
199
|
+
},
|
|
200
|
+
ssg: {
|
|
201
|
+
mode: "ssg",
|
|
202
|
+
label: "Static Site Generation",
|
|
203
|
+
shortLabel: "SSG",
|
|
204
|
+
description: "Pages are fully rendered at build time. Output is static HTML files. No server required at runtime.",
|
|
205
|
+
serverRequired: false,
|
|
206
|
+
buildTimeGenerated: true,
|
|
207
|
+
clientHydration: false,
|
|
208
|
+
roadmap: true
|
|
209
|
+
},
|
|
210
|
+
csg: {
|
|
211
|
+
mode: "csg",
|
|
212
|
+
label: "Client-Side Generation",
|
|
213
|
+
shortLabel: "CSG",
|
|
214
|
+
description: "A static shell is generated at build time, data is fetched and rendered on the client. Combines SSG speed with dynamic data.",
|
|
215
|
+
serverRequired: false,
|
|
216
|
+
buildTimeGenerated: true,
|
|
217
|
+
clientHydration: true,
|
|
218
|
+
roadmap: true
|
|
219
|
+
},
|
|
220
|
+
spa: {
|
|
221
|
+
mode: "spa",
|
|
222
|
+
label: "Single Page Application",
|
|
223
|
+
shortLabel: "SPA",
|
|
224
|
+
description: "A single HTML entry point is served for all routes. React handles all routing client-side. Equivalent to a standard Vite SPA.",
|
|
225
|
+
serverRequired: false,
|
|
226
|
+
buildTimeGenerated: false,
|
|
227
|
+
clientHydration: true,
|
|
228
|
+
roadmap: false
|
|
229
|
+
},
|
|
230
|
+
hybrid: {
|
|
231
|
+
mode: "hybrid",
|
|
232
|
+
label: "Hybrid Rendering",
|
|
233
|
+
shortLabel: "Hybrid",
|
|
234
|
+
description: "Different routes use different render modes. Configured via the `render.routes` map in rakta.config.ts. The top-level mode is the fallback.",
|
|
235
|
+
serverRequired: false,
|
|
236
|
+
buildTimeGenerated: false,
|
|
237
|
+
clientHydration: true,
|
|
238
|
+
roadmap: false
|
|
239
|
+
}
|
|
240
|
+
};
|
|
241
|
+
function pathMatchesPattern(pathname, pattern) {
|
|
242
|
+
if (pattern === pathname)
|
|
243
|
+
return true;
|
|
244
|
+
const patternParts = pattern.split("/");
|
|
245
|
+
const pathParts = pathname.split("/");
|
|
246
|
+
if (patternParts.length !== pathParts.length)
|
|
247
|
+
return false;
|
|
248
|
+
for (let i = 0;i < patternParts.length; i++) {
|
|
249
|
+
const pp = patternParts[i];
|
|
250
|
+
const path = pathParts[i];
|
|
251
|
+
if (pp === undefined || path === undefined)
|
|
252
|
+
return false;
|
|
253
|
+
if (pp.startsWith(":"))
|
|
254
|
+
continue;
|
|
255
|
+
if (pp !== path)
|
|
256
|
+
return false;
|
|
257
|
+
}
|
|
258
|
+
return true;
|
|
259
|
+
}
|
|
260
|
+
function resolveRouteMode(pathname, config) {
|
|
261
|
+
const patterns = Object.keys(config.routes).sort((a, b) => b.length - a.length);
|
|
262
|
+
for (const pattern of patterns) {
|
|
263
|
+
const overrideMode = config.routes[pattern];
|
|
264
|
+
if (overrideMode !== undefined && pathMatchesPattern(pathname, pattern)) {
|
|
265
|
+
return {
|
|
266
|
+
routePath: pathname,
|
|
267
|
+
mode: overrideMode,
|
|
268
|
+
source: "route-override"
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
return {
|
|
273
|
+
routePath: pathname,
|
|
274
|
+
mode: config.defaultMode,
|
|
275
|
+
source: "default"
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
function isRoadmapMode(mode) {
|
|
279
|
+
return RENDER_MODE_DESCRIPTORS[mode].roadmap;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// src/render/renderer.ts
|
|
283
|
+
function buildHtmlShell(options) {
|
|
284
|
+
return `
|
|
285
|
+
<!DOCTYPE html>
|
|
286
|
+
<html lang="${options.lang}">
|
|
287
|
+
<head>
|
|
288
|
+
<meta charset="UTF-8" />
|
|
289
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
290
|
+
<title>
|
|
291
|
+
${options.appName}
|
|
292
|
+
</title>
|
|
293
|
+
<link rel="stylesheet" href="${options.cssPath}" />
|
|
294
|
+
</head>
|
|
295
|
+
<body>
|
|
296
|
+
<div id="rakta-root"></div>
|
|
297
|
+
<script type="module" src="${options.scriptPath}"></script>
|
|
298
|
+
</body>
|
|
299
|
+
</html>`;
|
|
300
|
+
}
|
|
301
|
+
function makeSuccess(html, mode, renderMs, httpStatus = 200, fromCache = false) {
|
|
302
|
+
return {
|
|
303
|
+
kind: "success",
|
|
304
|
+
html,
|
|
305
|
+
mode,
|
|
306
|
+
httpStatus,
|
|
307
|
+
responseHeaders: { "Content-Type": "text/html; charset=utf-8" },
|
|
308
|
+
fromCache,
|
|
309
|
+
renderMs
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
function makeFailure(reason, mode, httpStatus = 500) {
|
|
313
|
+
return { kind: "failure", reason, mode, httpStatus };
|
|
314
|
+
}
|
|
315
|
+
async function render(context, options) {
|
|
316
|
+
const startMs = Date.now();
|
|
317
|
+
if (isRoadmapMode(context.mode)) {
|
|
318
|
+
console.warn(`[Rakta.js] Render mode "${context.mode}" is a roadmap feature (v0.2.0). ` + `Falling back to CSR for: ${context.routePath}`);
|
|
319
|
+
return makeSuccess(buildHtmlShell(options), "csr", Date.now() - startMs);
|
|
320
|
+
}
|
|
321
|
+
switch (context.mode) {
|
|
322
|
+
case "csr":
|
|
323
|
+
case "spa":
|
|
324
|
+
return makeSuccess(buildHtmlShell(options), context.mode, Date.now() - startMs);
|
|
325
|
+
case "hybrid":
|
|
326
|
+
return makeSuccess(buildHtmlShell(options), "csr", Date.now() - startMs);
|
|
327
|
+
case "ssr":
|
|
328
|
+
case "ssg":
|
|
329
|
+
case "csg":
|
|
330
|
+
return makeFailure(`Render mode "${context.mode}" is not yet implemented.`, context.mode, 501);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// src/router/matcher.ts
|
|
335
|
+
function escapeRegex(text) {
|
|
336
|
+
return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
337
|
+
}
|
|
338
|
+
function buildPatternRegex(segments) {
|
|
339
|
+
const paramNames = [];
|
|
340
|
+
const parts = segments.map((segment) => {
|
|
341
|
+
if (segment.isDynamic && segment.paramName) {
|
|
342
|
+
paramNames.push(segment.paramName);
|
|
343
|
+
return "([^/]+)";
|
|
344
|
+
}
|
|
345
|
+
return escapeRegex(segment.raw);
|
|
346
|
+
});
|
|
347
|
+
const pattern = parts.length === 0 ? "" : `/${parts.join("/")}`;
|
|
348
|
+
const regex = new RegExp(`^${pattern || "/"}$`);
|
|
349
|
+
return { regex, paramNames };
|
|
350
|
+
}
|
|
351
|
+
function matchRoute(pathname, routes) {
|
|
352
|
+
const normalized = pathname !== "/" && pathname.endsWith("/") ? pathname.slice(0, -1) : pathname;
|
|
353
|
+
for (const entry of routes) {
|
|
354
|
+
if (entry.kind !== "page" && entry.kind !== "api")
|
|
355
|
+
continue;
|
|
356
|
+
const { regex, paramNames } = buildPatternRegex(entry.segments);
|
|
357
|
+
const match = regex.exec(normalized);
|
|
358
|
+
if (!match)
|
|
359
|
+
continue;
|
|
360
|
+
const params = {};
|
|
361
|
+
paramNames.forEach((name, index) => {
|
|
362
|
+
const captured = match[index + 1];
|
|
363
|
+
if (captured !== undefined) {
|
|
364
|
+
params[name] = decodeURIComponent(captured);
|
|
365
|
+
}
|
|
366
|
+
});
|
|
367
|
+
return { entry, params };
|
|
368
|
+
}
|
|
369
|
+
return null;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// src/forge/devServer.ts
|
|
373
|
+
var DEFAULT_DEV_PORT = 3000;
|
|
374
|
+
var MIME_MAP = {
|
|
375
|
+
".html": "text/html; charset=utf-8",
|
|
376
|
+
".js": "application/javascript; charset=utf-8",
|
|
377
|
+
".mjs": "application/javascript; charset=utf-8",
|
|
378
|
+
".css": "text/css; charset=utf-8",
|
|
379
|
+
".json": "application/json; charset=utf-8",
|
|
380
|
+
".png": "image/png",
|
|
381
|
+
".jpg": "image/jpeg",
|
|
382
|
+
".jpeg": "image/jpeg",
|
|
383
|
+
".webp": "image/webp",
|
|
384
|
+
".svg": "image/svg+xml",
|
|
385
|
+
".ico": "image/x-icon",
|
|
386
|
+
".woff": "font/woff",
|
|
387
|
+
".woff2": "font/woff2",
|
|
388
|
+
".ttf": "font/ttf"
|
|
389
|
+
};
|
|
390
|
+
function resolveMime(filePath) {
|
|
391
|
+
const ext = filePath.slice(filePath.lastIndexOf(".")).toLowerCase();
|
|
392
|
+
return MIME_MAP[ext] ?? "application/octet-stream";
|
|
393
|
+
}
|
|
394
|
+
function resolveDevPort(port) {
|
|
395
|
+
return port > 0 ? port : DEFAULT_DEV_PORT;
|
|
396
|
+
}
|
|
397
|
+
function startDevServer(options) {
|
|
398
|
+
const manifest = generateManifest(options.appDir);
|
|
399
|
+
const resolvedPort = resolveDevPort(options.port);
|
|
400
|
+
const server = Bun.serve({
|
|
401
|
+
port: resolvedPort,
|
|
402
|
+
hostname: options.host,
|
|
403
|
+
async fetch(request) {
|
|
404
|
+
const url = new URL(request.url);
|
|
405
|
+
const { pathname } = url;
|
|
406
|
+
const publicPath = join3(options.publicDir, pathname);
|
|
407
|
+
if (existsSync3(publicPath) && !publicPath.endsWith("/")) {
|
|
408
|
+
return new Response(readFileSync2(publicPath), {
|
|
409
|
+
headers: { "Content-Type": resolveMime(pathname) }
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
const apiMatch = matchRoute(pathname, manifest.routes.filter((route) => route.kind === "api"));
|
|
413
|
+
if (apiMatch) {
|
|
414
|
+
const modulePath = join3(options.appDir, apiMatch.entry.filePath);
|
|
415
|
+
const routeModule = await import(modulePath);
|
|
416
|
+
const method = request.method.toUpperCase();
|
|
417
|
+
const handler = routeModule[method];
|
|
418
|
+
if (typeof handler !== "function") {
|
|
419
|
+
return new Response("Method not allowed", { status: 405 });
|
|
420
|
+
}
|
|
421
|
+
return await handler(request);
|
|
422
|
+
}
|
|
423
|
+
const resolved = resolveRouteMode(pathname, options.renderConfig);
|
|
424
|
+
const searchParams = {};
|
|
425
|
+
url.searchParams.forEach((value, key) => {
|
|
426
|
+
searchParams[key] = value;
|
|
427
|
+
});
|
|
428
|
+
const requestHeaders = {};
|
|
429
|
+
request.headers.forEach((value, key) => {
|
|
430
|
+
requestHeaders[key] = value;
|
|
431
|
+
});
|
|
432
|
+
const result = await render({
|
|
433
|
+
routePath: pathname,
|
|
434
|
+
mode: resolved.mode,
|
|
435
|
+
params: {},
|
|
436
|
+
searchParams,
|
|
437
|
+
requestHeaders,
|
|
438
|
+
timestampMs: Date.now()
|
|
439
|
+
}, {
|
|
440
|
+
appName: options.appName,
|
|
441
|
+
scriptPath: "/app.js",
|
|
442
|
+
cssPath: "/globals.css",
|
|
443
|
+
lang: "en"
|
|
444
|
+
});
|
|
445
|
+
if (result.kind === "failure") {
|
|
446
|
+
return new Response(result.reason, { status: result.httpStatus });
|
|
447
|
+
}
|
|
448
|
+
return new Response(result.html, {
|
|
449
|
+
status: result.httpStatus,
|
|
450
|
+
headers: result.responseHeaders
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
});
|
|
454
|
+
const serverPort = typeof server.port === "number" ? server.port : resolvedPort;
|
|
455
|
+
return {
|
|
456
|
+
port: serverPort,
|
|
457
|
+
host: options.host,
|
|
458
|
+
url: `http://${options.host}:${serverPort}`,
|
|
459
|
+
stop: () => server.stop()
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
// src/forge/inspect.ts
|
|
463
|
+
import { existsSync as existsSync4, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
|
|
464
|
+
import { join as join4 } from "path";
|
|
465
|
+
function detectArtifactKind(filename) {
|
|
466
|
+
if (filename === "route-manifest.json")
|
|
467
|
+
return "manifest";
|
|
468
|
+
if (filename.endsWith(".css"))
|
|
469
|
+
return "stylesheet";
|
|
470
|
+
if (filename.endsWith(".js") || filename.endsWith(".mjs"))
|
|
471
|
+
return "script";
|
|
472
|
+
return "asset";
|
|
473
|
+
}
|
|
474
|
+
function formatBytes(bytes) {
|
|
475
|
+
if (bytes < 1024)
|
|
476
|
+
return `${bytes} B`;
|
|
477
|
+
if (bytes < 1048576)
|
|
478
|
+
return `${(bytes / 1024).toFixed(1)} KB`;
|
|
479
|
+
return `${(bytes / 1048576).toFixed(2)} MB`;
|
|
480
|
+
}
|
|
481
|
+
function scanDirectory2(dirPath) {
|
|
482
|
+
if (!existsSync4(dirPath))
|
|
483
|
+
return [];
|
|
484
|
+
const collected = [];
|
|
485
|
+
function walk(current) {
|
|
486
|
+
const entries = readdirSync2(current, { withFileTypes: true });
|
|
487
|
+
for (const entry of entries) {
|
|
488
|
+
const full = join4(current, entry.name);
|
|
489
|
+
if (entry.isDirectory()) {
|
|
490
|
+
walk(full);
|
|
491
|
+
} else if (entry.isFile()) {
|
|
492
|
+
collected.push({
|
|
493
|
+
outputPath: full,
|
|
494
|
+
sizeBytes: statSync2(full).size,
|
|
495
|
+
kind: detectArtifactKind(entry.name)
|
|
496
|
+
});
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
walk(dirPath);
|
|
501
|
+
return collected;
|
|
502
|
+
}
|
|
503
|
+
function inspectBuild(options) {
|
|
504
|
+
const artifacts = scanDirectory2(options.outDir);
|
|
505
|
+
const manifestPath = join4(options.outDir, "route-manifest.json");
|
|
506
|
+
const manifest = readManifest(manifestPath);
|
|
507
|
+
const emptyManifest = {
|
|
508
|
+
version: "1",
|
|
509
|
+
generatedAt: new Date().toISOString(),
|
|
510
|
+
routes: []
|
|
511
|
+
};
|
|
512
|
+
const routeModes = (manifest ?? emptyManifest).routes.filter((r) => r.kind === "page" || r.kind === "api").map((r) => {
|
|
513
|
+
const resolved = resolveRouteMode(r.urlPattern, options.renderConfig);
|
|
514
|
+
return {
|
|
515
|
+
pattern: r.urlPattern,
|
|
516
|
+
mode: resolved.mode,
|
|
517
|
+
source: resolved.source
|
|
518
|
+
};
|
|
519
|
+
});
|
|
520
|
+
return {
|
|
521
|
+
buildDir: options.outDir,
|
|
522
|
+
artifacts,
|
|
523
|
+
manifest: manifest ?? emptyManifest,
|
|
524
|
+
routeModes,
|
|
525
|
+
totalSizeBytes: artifacts.reduce((sum, a) => sum + a.sizeBytes, 0),
|
|
526
|
+
inspectedAt: new Date().toISOString()
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
function printInspectReport(report) {
|
|
530
|
+
const sep = "\u2500".repeat(58);
|
|
531
|
+
console.log(`
|
|
532
|
+
|
|
533
|
+
Rakta.js Forge - Build Inspection
|
|
534
|
+
`);
|
|
535
|
+
console.log(`
|
|
536
|
+
${sep}
|
|
537
|
+
`);
|
|
538
|
+
console.log(`
|
|
539
|
+
Directory: ${report.buildDir}
|
|
540
|
+
`);
|
|
541
|
+
console.log(`
|
|
542
|
+
Inspected: ${report.inspectedAt}
|
|
543
|
+
`);
|
|
544
|
+
console.log(`
|
|
545
|
+
Total size: ${formatBytes(report.totalSizeBytes)}
|
|
546
|
+
|
|
547
|
+
`);
|
|
548
|
+
if (report.artifacts.length > 0) {
|
|
549
|
+
console.log("Artifacts:");
|
|
550
|
+
for (const artifact of report.artifacts) {
|
|
551
|
+
const rel = artifact.outputPath.replace(report.buildDir, ".").replace(/\\/g, "/");
|
|
552
|
+
console.log(`
|
|
553
|
+
[${artifact.kind.padEnd(10)}]
|
|
554
|
+
${rel.padEnd(38)}
|
|
555
|
+
${formatBytes(artifact.sizeBytes)}`);
|
|
556
|
+
}
|
|
557
|
+
console.log("");
|
|
558
|
+
}
|
|
559
|
+
if (report.routeModes.length > 0) {
|
|
560
|
+
console.log("Route Render Modes:");
|
|
561
|
+
for (const rm of report.routeModes) {
|
|
562
|
+
const src = rm.source === "route-override" ? "(override)" : "(default) ";
|
|
563
|
+
console.log(`
|
|
564
|
+
${rm.mode.toUpperCase().padEnd(8)}
|
|
565
|
+
${rm.pattern.padEnd(36)} ${src}`);
|
|
566
|
+
}
|
|
567
|
+
console.log("");
|
|
568
|
+
}
|
|
569
|
+
console.log(`${sep}
|
|
570
|
+
`);
|
|
571
|
+
}
|
|
572
|
+
export {
|
|
573
|
+
startDevServer,
|
|
574
|
+
printInspectReport,
|
|
575
|
+
inspectBuild,
|
|
576
|
+
buildProject
|
|
577
|
+
};
|
|
578
|
+
|
|
579
|
+
//# debugId=6749B66412BC6D2064756E2164756E21
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["..\\..\\src\\forge\\build.ts", "..\\..\\src\\router\\manifest.ts", "..\\..\\src\\router\\scanner.ts", "..\\..\\src\\forge\\devServer.ts", "..\\..\\src\\render\\modes.ts", "..\\..\\src\\render\\renderer.ts", "..\\..\\src\\router\\matcher.ts", "..\\..\\src\\forge\\inspect.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import { mkdirSync } from \"node:fs\";\nimport { join, resolve } from \"node:path\";\nimport { generateManifest, writeManifest } from \"../router/manifest\";\nimport type {\n\tForgeBuildArtifact,\n\tForgeBuildOptions,\n\tForgeBuildResult,\n} from \"./types\";\n\n/**\n * Runs the Rakta.js Forge build pipeline.\n * Uses Bun.build for bundling. Generates a route manifest alongside the bundle.\n */\nexport async function buildProject(\n\toptions: ForgeBuildOptions,\n): Promise<ForgeBuildResult> {\n\tconst startMs = Date.now();\n\tconst artifacts: ForgeBuildArtifact[] = [];\n\tconst errors: string[] = [];\n\n\tmkdirSync(resolve(options.outDir), { recursive: true });\n\n\t// Generate and write route manifest\n\tconst manifest = generateManifest(options.appDir);\n\tconst manifestPath = join(options.outDir, \"route-manifest.json\");\n\twriteManifest(manifest, manifestPath);\n\n\tconst manifestContent = JSON.stringify(manifest);\n\tartifacts.push({\n\t\toutputPath: manifestPath,\n\t\tsizeBytes: new TextEncoder().encode(manifestContent).byteLength,\n\t\tkind: \"manifest\",\n\t});\n\n\t// Build JavaScript bundle\n\tconst buildResult = await Bun.build({\n\t\tentrypoints: [options.entryPoint],\n\t\toutdir: options.outDir,\n\t\ttarget: options.target,\n\t\tminify: options.minify,\n\t\tsourcemap: options.sourcemap ? \"external\" : \"none\",\n\t\tsplitting: options.splitting,\n\t\tnaming: {\n\t\t\tentry: \"[name].[ext]\",\n\t\t\tchunk: \"chunks/[name]-[hash].[ext]\",\n\t\t\tasset: \"assets/[name]-[hash].[ext]\",\n\t\t},\n\t});\n\n\tif (!buildResult.success) {\n\t\tfor (const log of buildResult.logs) {\n\t\t\terrors.push(log.message);\n\t\t}\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\tartifacts,\n\t\t\tmanifest,\n\t\t\tbuildMs: Date.now() - startMs,\n\t\t\terrors,\n\t\t};\n\t}\n\n\tfor (const output of buildResult.outputs) {\n\t\tartifacts.push({\n\t\t\toutputPath: output.path,\n\t\t\tsizeBytes: output.size,\n\t\t\tkind: output.path.endsWith(\".css\") ? \"stylesheet\" : \"script\",\n\t\t});\n\t}\n\n\treturn {\n\t\tsuccess: true,\n\t\tartifacts,\n\t\tmanifest,\n\t\tbuildMs: Date.now() - startMs,\n\t\terrors: [],\n\t};\n}\n",
|
|
6
|
+
"import { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { scanRoutes } from \"./scanner\";\nimport type { RouteManifest } from \"./types\";\n\nexport function generateManifest(appDir: string): RouteManifest {\n\tconst routes = scanRoutes({ appDir });\n\n\tconst manifest: RouteManifest = {\n\t\tversion: \"1\",\n\t\tgeneratedAt: new Date().toISOString(),\n\t\troutes,\n\t};\n\n\treturn manifest;\n}\n\nexport function writeManifest(\n\tmanifest: RouteManifest,\n\toutputPath: string,\n): void {\n\twriteFileSync(outputPath, JSON.stringify(manifest, null, 2), \"utf-8\");\n}\n\nexport function readManifest(manifestPath: string): RouteManifest | null {\n\tif (!existsSync(manifestPath)) return null;\n\n\tconst raw = readFileSync(manifestPath, \"utf-8\");\n\n\tconst parsed: unknown = JSON.parse(raw);\n\tif (\n\t\ttypeof parsed !== \"object\" ||\n\t\tparsed === null ||\n\t\t!(\"version\" in parsed) ||\n\t\t!(\"routes\" in parsed)\n\t) {\n\t\treturn null;\n\t}\n\n\treturn parsed as RouteManifest;\n}\n\nexport function printManifest(manifest: RouteManifest): void {\n\tconst pageRoutes = manifest.routes.filter((route) => route.kind === \"page\");\n\tconst apiRoutes = manifest.routes.filter((route) => route.kind === \"api\");\n\tconst layoutRoutes = manifest.routes.filter(\n\t\t(route) => route.kind === \"layout\",\n\t);\n\tconst specialRoutes = manifest.routes.filter((route) =>\n\t\t[\"loading\", \"not-found\", \"error\"].includes(route.kind),\n\t);\n\n\tconst line = \"─\".repeat(56);\n\n\tconsole.log(`\\n Rakta.js Route Manifest`);\n\tconsole.log(` ${line}`);\n\tconsole.log(` Generated: ${manifest.generatedAt}`);\n\tconsole.log(` Total: ${manifest.routes.length} routes\\n`);\n\n\tif (pageRoutes.length > 0) {\n\t\tconsole.log(\" Pages:\");\n\t\tfor (const route of pageRoutes) {\n\t\t\tconst dynamic = route.isDynamic\n\t\t\t\t? ` [params: ${route.paramNames.join(\", \")}]`\n\t\t\t\t: \"\";\n\t\t\tconsole.log(` GET ${route.urlPattern}${dynamic}`);\n\t\t}\n\t\tconsole.log(\"\");\n\t}\n\n\tif (apiRoutes.length > 0) {\n\t\tconsole.log(\" API Routes:\");\n\t\tfor (const route of apiRoutes) {\n\t\t\tconst dynamic = route.isDynamic\n\t\t\t\t? ` [params: ${route.paramNames.join(\", \")}]`\n\t\t\t\t: \"\";\n\t\t\tconsole.log(` ANY ${route.urlPattern}${dynamic}`);\n\t\t}\n\t\tconsole.log(\"\");\n\t}\n\n\tif (layoutRoutes.length > 0) {\n\t\tconsole.log(\" Layouts:\");\n\t\tfor (const route of layoutRoutes) {\n\t\t\tconsole.log(\n\t\t\t\t` ${route.urlPattern === \"/\" ? \"root\" : route.urlPattern}`,\n\t\t\t);\n\t\t}\n\t\tconsole.log(\"\");\n\t}\n\n\tif (specialRoutes.length > 0) {\n\t\tconsole.log(\" Special:\");\n\t\tfor (const route of specialRoutes) {\n\t\t\tconsole.log(` [${route.kind}] ${route.filePath}`);\n\t\t}\n\t\tconsole.log(\"\");\n\t}\n\n\tconsole.log(` ${line}\\n`);\n}\n",
|
|
7
|
+
"import { existsSync, readdirSync, statSync } from \"node:fs\";\nimport { join, relative } from \"node:path\";\nimport type { RouteKind, RouteManifestEntry, RouteSegment } from \"./types.js\";\n\nconst FILE_TO_KIND: Record<string, RouteKind> = {\n\t\"page.tsx\": \"page\",\n\t\"page.ts\": \"page\",\n\t\"page.jsx\": \"page\",\n\t\"page.js\": \"page\",\n\t\"layout.tsx\": \"layout\",\n\t\"layout.ts\": \"layout\",\n\t\"layout.jsx\": \"layout\",\n\t\"layout.js\": \"layout\",\n\t\"loading.tsx\": \"loading\",\n\t\"loading.ts\": \"loading\",\n\t\"loading.jsx\": \"loading\",\n\t\"loading.js\": \"loading\",\n\t\"notFound.tsx\": \"notFound\",\n\t\"notFound.ts\": \"notFound\",\n\t\"notFound.jsx\": \"notFound\",\n\t\"notFound.js\": \"notFound\",\n\t\"error.tsx\": \"error\",\n\t\"error.ts\": \"error\",\n\t\"error.jsx\": \"error\",\n\t\"error.js\": \"error\",\n\t\"route.ts\": \"api\",\n\t\"route.js\": \"api\",\n};\n\nfunction parseSegment(raw: string): RouteSegment {\n\tconst isDynamic = raw.startsWith(\"[\") && raw.endsWith(\"]\");\n\tconst paramName = isDynamic ? raw.slice(1, -1) : \"\";\n\n\treturn { raw, isDynamic, paramName };\n}\n\nfunction collectParamNames(segments: RouteSegment[]): string[] {\n\treturn segments\n\t\t.filter((segment) => segment.isDynamic && segment.paramName.length > 0)\n\t\t.map((segment) => segment.paramName);\n}\n\nfunction segmentsToUrlPattern(segments: RouteSegment[]): string {\n\tif (segments.length === 0) return \"/\";\n\tconst parts = segments.map((segment) =>\n\t\tsegment.isDynamic && segment.paramName\n\t\t\t? `:${segment.paramName}`\n\t\t\t: segment.raw,\n\t);\n\treturn `/${parts.join(\"/\")}`;\n}\n\nfunction scanDirectory(\n\tdirPath: string,\n\tappRoot: string,\n\tresults: RouteManifestEntry[],\n): void {\n\tif (!existsSync(dirPath)) return;\n\n\tconst entries = readdirSync(dirPath);\n\n\tfor (const entryName of entries) {\n\t\tconst fullPath = join(dirPath, entryName);\n\t\tconst stats = statSync(fullPath);\n\n\t\tif (stats.isDirectory()) {\n\t\t\tscanDirectory(fullPath, appRoot, results);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!stats.isFile()) continue;\n\n\t\tconst kind = FILE_TO_KIND[entryName];\n\t\tif (!kind) continue;\n\n\t\t// Get path relative to app root, using forward slashes\n\t\tconst relativePath = relative(appRoot, fullPath).replace(/\\\\/g, \"/\");\n\n\t\t// Extract directory segments (all parts except the filename)\n\t\tconst dirRelative = relative(appRoot, dirPath).replace(/\\\\/g, \"/\");\n\t\tconst rawSegments = dirRelative === \"\" ? [] : dirRelative.split(\"/\");\n\n\t\tconst segments: RouteSegment[] = rawSegments.map(parseSegment);\n\t\tconst urlPattern = segmentsToUrlPattern(segments);\n\t\tconst paramNames = collectParamNames(segments);\n\t\tconst isDynamic = paramNames.length > 0;\n\n\t\tresults.push({\n\t\t\tfilePath: relativePath,\n\t\t\turlPattern,\n\t\t\tkind,\n\t\t\tsegments,\n\t\t\tisDynamic,\n\t\t\tparamNames,\n\t\t});\n\t}\n}\n\nexport interface ScanOptions {\n\tappDir: string;\n}\n\nexport function scanRoutes(options: ScanOptions): RouteManifestEntry[] {\n\tconst results: RouteManifestEntry[] = [];\n\tscanDirectory(options.appDir, options.appDir, results);\n\n\t// Sort: static routes before dynamic, shorter patterns first\n\tresults.sort((routeA, routeB) => {\n\t\tif (routeA.isDynamic !== routeB.isDynamic) {\n\t\t\treturn routeA.isDynamic ? 1 : -1;\n\t\t}\n\t\treturn routeA.urlPattern.localeCompare(routeB.urlPattern);\n\t});\n\n\treturn results;\n}\n",
|
|
8
|
+
"import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { resolveRouteMode } from \"../render/modes\";\nimport { render } from \"../render/renderer\";\nimport { generateManifest } from \"../router/manifest\";\nimport { matchRoute } from \"../router/matcher\";\nimport type { ForgeDevServerHandle, ForgeDevServerOptions } from \"./types\";\n\nconst DEFAULT_DEV_PORT = 3000;\n\nconst MIME_MAP: Readonly<Record<string, string>> = {\n\t\".html\": \"text/html; charset=utf-8\",\n\t\".js\": \"application/javascript; charset=utf-8\",\n\t\".mjs\": \"application/javascript; charset=utf-8\",\n\t\".css\": \"text/css; charset=utf-8\",\n\t\".json\": \"application/json; charset=utf-8\",\n\t\".png\": \"image/png\",\n\t\".jpg\": \"image/jpeg\",\n\t\".jpeg\": \"image/jpeg\",\n\t\".webp\": \"image/webp\",\n\t\".svg\": \"image/svg+xml\",\n\t\".ico\": \"image/x-icon\",\n\t\".woff\": \"font/woff\",\n\t\".woff2\": \"font/woff2\",\n\t\".ttf\": \"font/ttf\",\n};\n\nfunction resolveMime(filePath: string): string {\n\tconst ext = filePath.slice(filePath.lastIndexOf(\".\")).toLowerCase();\n\treturn MIME_MAP[ext] ?? \"application/octet-stream\";\n}\n\nfunction resolveDevPort(port: number): number {\n\treturn port > 0 ? port : DEFAULT_DEV_PORT;\n}\n\ninterface ApiRouteExports {\n\tGET?: (request: Request) => Promise<Response>;\n\tPOST?: (request: Request) => Promise<Response>;\n\tPUT?: (request: Request) => Promise<Response>;\n\tPATCH?: (request: Request) => Promise<Response>;\n\tDELETE?: (request: Request) => Promise<Response>;\n\tHEAD?: (request: Request) => Promise<Response>;\n\tOPTIONS?: (request: Request) => Promise<Response>;\n}\n\n/**\n * Starts the Rakta.js Forge development server.\n * Powered by Bun.serve. HMR is a roadmap feature (v0.2.0).\n */\nexport function startDevServer(\n\toptions: ForgeDevServerOptions,\n): ForgeDevServerHandle {\n\tconst manifest = generateManifest(options.appDir);\n\tconst resolvedPort = resolveDevPort(options.port);\n\n\tconst server = Bun.serve({\n\t\tport: resolvedPort,\n\t\thostname: options.host,\n\n\t\tasync fetch(request: Request): Promise<Response> {\n\t\t\tconst url = new URL(request.url);\n\t\t\tconst { pathname } = url;\n\n\t\t\t// Serve static files from public dir\n\t\t\tconst publicPath = join(options.publicDir, pathname);\n\t\t\tif (existsSync(publicPath) && !publicPath.endsWith(\"/\")) {\n\t\t\t\treturn new Response(readFileSync(publicPath), {\n\t\t\t\t\theaders: { \"Content-Type\": resolveMime(pathname) },\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Match API routes\n\t\t\tconst apiMatch = matchRoute(\n\t\t\t\tpathname,\n\t\t\t\tmanifest.routes.filter((route) => route.kind === \"api\"),\n\t\t\t);\n\n\t\t\tif (apiMatch) {\n\t\t\t\tconst modulePath = join(options.appDir, apiMatch.entry.filePath);\n\t\t\t\tconst routeModule = (await import(modulePath)) as ApiRouteExports;\n\t\t\t\tconst method = request.method.toUpperCase() as keyof ApiRouteExports;\n\t\t\t\tconst handler = routeModule[method];\n\n\t\t\t\tif (typeof handler !== \"function\") {\n\t\t\t\t\treturn new Response(\"Method not allowed\", { status: 405 });\n\t\t\t\t}\n\n\t\t\t\treturn await handler(request);\n\t\t\t}\n\n\t\t\t// Resolve render mode and serve HTML shell for page routes\n\t\t\tconst resolved = resolveRouteMode(pathname, options.renderConfig);\n\n\t\t\tconst searchParams: Record<string, string> = {};\n\t\t\turl.searchParams.forEach((value, key) => {\n\t\t\t\tsearchParams[key] = value;\n\t\t\t});\n\n\t\t\tconst requestHeaders: Record<string, string> = {};\n\t\t\trequest.headers.forEach((value, key) => {\n\t\t\t\trequestHeaders[key] = value;\n\t\t\t});\n\n\t\t\tconst result = await render(\n\t\t\t\t{\n\t\t\t\t\troutePath: pathname,\n\t\t\t\t\tmode: resolved.mode,\n\t\t\t\t\tparams: {},\n\t\t\t\t\tsearchParams,\n\t\t\t\t\trequestHeaders,\n\t\t\t\t\ttimestampMs: Date.now(),\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tappName: options.appName,\n\t\t\t\t\tscriptPath: \"/app.js\",\n\t\t\t\t\tcssPath: \"/globals.css\",\n\t\t\t\t\tlang: \"en\",\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (result.kind === \"failure\") {\n\t\t\t\treturn new Response(result.reason, { status: result.httpStatus });\n\t\t\t}\n\n\t\t\treturn new Response(result.html, {\n\t\t\t\tstatus: result.httpStatus,\n\t\t\t\theaders: result.responseHeaders,\n\t\t\t});\n\t\t},\n\t});\n\n\tconst serverPort =\n\t\ttypeof server.port === \"number\" ? server.port : resolvedPort;\n\n\treturn {\n\t\tport: serverPort,\n\t\thost: options.host,\n\t\turl: `http://${options.host}:${serverPort}`,\n\t\tstop: () => server.stop(),\n\t};\n}\n",
|
|
9
|
+
"import type {\n\tRenderConfig,\n\tRenderMode,\n\tRenderModeDescriptor,\n\tResolvedRouteMode,\n} from \"./types\";\n\nexport const RENDER_MODE_DESCRIPTORS: Readonly<\n\tRecord<RenderMode, RenderModeDescriptor>\n> = {\n\tcsr: {\n\t\tmode: \"csr\",\n\t\tlabel: \"Client-Side Rendering\",\n\t\tshortLabel: \"CSR\",\n\t\tdescription:\n\t\t\t\"React renders entirely in the browser. The server sends a minimal HTML shell with a JS bundle. No server required at runtime.\",\n\t\tserverRequired: false,\n\t\tbuildTimeGenerated: false,\n\t\tclientHydration: true,\n\t\troadmap: false,\n\t},\n\tssr: {\n\t\tmode: \"ssr\",\n\t\tlabel: \"Server-Side Rendering\",\n\t\tshortLabel: \"SSR\",\n\t\tdescription:\n\t\t\t\"React renders to HTML on the server per request. The client receives full HTML and then hydrates. Requires a running Node/Bun server.\",\n\t\tserverRequired: true,\n\t\tbuildTimeGenerated: false,\n\t\tclientHydration: true,\n\t\troadmap: true, // Roadmap: v0.2.0\n\t},\n\tssg: {\n\t\tmode: \"ssg\",\n\t\tlabel: \"Static Site Generation\",\n\t\tshortLabel: \"SSG\",\n\t\tdescription:\n\t\t\t\"Pages are fully rendered at build time. Output is static HTML files. No server required at runtime.\",\n\t\tserverRequired: false,\n\t\tbuildTimeGenerated: true,\n\t\tclientHydration: false,\n\t\troadmap: true, // Roadmap: v0.2.0\n\t},\n\tcsg: {\n\t\tmode: \"csg\",\n\t\tlabel: \"Client-Side Generation\",\n\t\tshortLabel: \"CSG\",\n\t\tdescription:\n\t\t\t\"A static shell is generated at build time, data is fetched and rendered on the client. Combines SSG speed with dynamic data.\",\n\t\tserverRequired: false,\n\t\tbuildTimeGenerated: true,\n\t\tclientHydration: true,\n\t\troadmap: true, // Roadmap: v0.2.0\n\t},\n\tspa: {\n\t\tmode: \"spa\",\n\t\tlabel: \"Single Page Application\",\n\t\tshortLabel: \"SPA\",\n\t\tdescription:\n\t\t\t\"A single HTML entry point is served for all routes. React handles all routing client-side. Equivalent to a standard Vite SPA.\",\n\t\tserverRequired: false,\n\t\tbuildTimeGenerated: false,\n\t\tclientHydration: true,\n\t\troadmap: false,\n\t},\n\thybrid: {\n\t\tmode: \"hybrid\",\n\t\tlabel: \"Hybrid Rendering\",\n\t\tshortLabel: \"Hybrid\",\n\t\tdescription:\n\t\t\t\"Different routes use different render modes. Configured via the `render.routes` map in rakta.config.ts. The top-level mode is the fallback.\",\n\t\tserverRequired: false,\n\t\tbuildTimeGenerated: false,\n\t\tclientHydration: true,\n\t\troadmap: false,\n\t},\n};\n\n/**\n * Returns true if the pathname matches a given route pattern.\n * Supports exact paths and simple :param segments (e.g. /blog/:slug).\n */\nfunction pathMatchesPattern(pathname: string, pattern: string): boolean {\n\tif (pattern === pathname) return true;\n\n\tconst patternParts = pattern.split(\"/\");\n\tconst pathParts = pathname.split(\"/\");\n\n\tif (patternParts.length !== pathParts.length) return false;\n\n\tfor (let i = 0; i < patternParts.length; i++) {\n\t\tconst pp = patternParts[i];\n\t\tconst path = pathParts[i];\n\t\tif (pp === undefined || path === undefined) return false;\n\t\tif (pp.startsWith(\":\")) continue; // dynamic segment — always matches\n\t\tif (pp !== path) return false;\n\t}\n\n\treturn true;\n}\n\n/**\n * Resolves the render mode for the given pathname using the provided config.\n * Route-specific overrides take priority. The most specific (longest) matching\n * pattern wins. Falls back to `config.defaultMode`.\n */\nexport function resolveRouteMode(\n\tpathname: string,\n\tconfig: RenderConfig,\n): ResolvedRouteMode {\n\tconst patterns = Object.keys(config.routes).sort(\n\t\t(a, b) => b.length - a.length, // longest pattern first (most specific)\n\t);\n\n\tfor (const pattern of patterns) {\n\t\tconst overrideMode = config.routes[pattern];\n\t\tif (overrideMode !== undefined && pathMatchesPattern(pathname, pattern)) {\n\t\t\treturn {\n\t\t\t\troutePath: pathname,\n\t\t\t\tmode: overrideMode,\n\t\t\t\tsource: \"route-override\",\n\t\t\t};\n\t\t}\n\t}\n\n\treturn {\n\t\troutePath: pathname,\n\t\tmode: config.defaultMode,\n\t\tsource: \"default\",\n\t};\n}\n\nexport function getModeDescriptor(mode: RenderMode): RenderModeDescriptor {\n\treturn RENDER_MODE_DESCRIPTORS[mode];\n}\n\nexport function isRoadmapMode(mode: RenderMode): boolean {\n\treturn RENDER_MODE_DESCRIPTORS[mode].roadmap;\n}\n\nexport function requiresServer(mode: RenderMode): boolean {\n\treturn RENDER_MODE_DESCRIPTORS[mode].serverRequired;\n}\n\nexport function isBuildTimeMode(mode: RenderMode): boolean {\n\treturn RENDER_MODE_DESCRIPTORS[mode].buildTimeGenerated;\n}\n",
|
|
10
|
+
"import { isRoadmapMode } from \"./modes\";\nimport type {\n\tRenderContext,\n\tRenderFailure,\n\tRenderMode,\n\tRenderResult,\n\tRenderSuccess,\n} from \"./types\";\n\nexport interface RendererOptions {\n\treadonly appName: string;\n\treadonly scriptPath: string;\n\treadonly cssPath: string;\n\treadonly lang: string;\n}\n\nfunction buildHtmlShell(options: RendererOptions): string {\n\treturn `\n <!DOCTYPE html>\n <html lang=\"${options.lang}\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <title>\n ${options.appName}\n </title>\n <link rel=\"stylesheet\" href=\"${options.cssPath}\" />\n </head>\n <body>\n <div id=\"rakta-root\"></div>\n <script type=\"module\" src=\"${options.scriptPath}\"></script>\n </body>\n </html>`;\n}\n\nfunction makeSuccess(\n\thtml: string,\n\tmode: RenderMode,\n\trenderMs: number,\n\thttpStatus: number = 200,\n\tfromCache: boolean = false,\n): RenderSuccess {\n\treturn {\n\t\tkind: \"success\",\n\t\thtml,\n\t\tmode,\n\t\thttpStatus,\n\t\tresponseHeaders: { \"Content-Type\": \"text/html; charset=utf-8\" },\n\t\tfromCache,\n\t\trenderMs,\n\t};\n}\n\nfunction makeFailure(\n\treason: string,\n\tmode: RenderMode,\n\thttpStatus: number = 500,\n): RenderFailure {\n\treturn { kind: \"failure\", reason, mode, httpStatus };\n}\n\n/**\n * Render a page using the resolved mode from the context.\n * Roadmap modes (ssr, ssg, csg) fall back to a CSR shell in v0.1.0.\n */\nexport async function render(\n\tcontext: RenderContext,\n\toptions: RendererOptions,\n): Promise<RenderResult> {\n\tconst startMs = Date.now();\n\n\t// Roadmap modes: fall back to CSR shell with a warning\n\tif (isRoadmapMode(context.mode)) {\n\t\tconsole.warn(\n\t\t\t`[Rakta.js] Render mode \"${context.mode}\" is a roadmap feature (v0.2.0). ` +\n\t\t\t\t`Falling back to CSR for: ${context.routePath}`,\n\t\t);\n\t\treturn makeSuccess(buildHtmlShell(options), \"csr\", Date.now() - startMs);\n\t}\n\n\tswitch (context.mode) {\n\t\tcase \"csr\":\n\t\tcase \"spa\":\n\t\t\treturn makeSuccess(\n\t\t\t\tbuildHtmlShell(options),\n\t\t\t\tcontext.mode,\n\t\t\t\tDate.now() - startMs,\n\t\t\t);\n\n\t\tcase \"hybrid\":\n\t\t\t// Hybrid resolution happens upstream in Tide. If it reaches the renderer\n\t\t\t// as hybrid, the route had no specific override - fall back to CSR.\n\t\t\treturn makeSuccess(buildHtmlShell(options), \"csr\", Date.now() - startMs);\n\n\t\tcase \"ssr\":\n\t\tcase \"ssg\":\n\t\tcase \"csg\":\n\t\t\t// These are already caught by isRoadmapMode above, but TypeScript\n\t\t\t// requires an exhaustive switch for the RenderMode union.\n\t\t\treturn makeFailure(\n\t\t\t\t`Render mode \"${context.mode}\" is not yet implemented.`,\n\t\t\t\tcontext.mode,\n\t\t\t\t501,\n\t\t\t);\n\t}\n}\n\nexport function renderNotFound(options: RendererOptions): RenderSuccess {\n\treturn makeSuccess(buildHtmlShell(options), \"csr\", 0, 404);\n}\n\nexport function renderServerError(\n\treason: string,\n\tmode: RenderMode,\n): RenderFailure {\n\treturn makeFailure(reason, mode, 500);\n}\n",
|
|
11
|
+
"import type {\n\tMatchedRoute,\n\tRouteManifestEntry,\n\tRouteSegment,\n} from \"./types.js\";\n\nfunction escapeRegex(text: string): string {\n\treturn text.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\nfunction buildPatternRegex(segments: RouteSegment[]): {\n\tregex: RegExp;\n\tparamNames: string[];\n} {\n\tconst paramNames: string[] = [];\n\n\tconst parts = segments.map((segment) => {\n\t\tif (segment.isDynamic && segment.paramName) {\n\t\t\tparamNames.push(segment.paramName);\n\t\t\t// Match any non-slash sequence for the param\n\t\t\treturn \"([^/]+)\";\n\t\t}\n\t\treturn escapeRegex(segment.raw);\n\t});\n\n\tconst pattern = parts.length === 0 ? \"\" : `/${parts.join(\"/\")}`;\n\tconst regex = new RegExp(`^${pattern || \"/\"}$`);\n\n\treturn { regex, paramNames };\n}\n\nexport function matchRoute(\n\tpathname: string,\n\troutes: RouteManifestEntry[],\n): MatchedRoute | null {\n\t// Normalize pathname: strip trailing slash unless root\n\tconst normalized =\n\t\tpathname !== \"/\" && pathname.endsWith(\"/\")\n\t\t\t? pathname.slice(0, -1)\n\t\t\t: pathname;\n\n\tfor (const entry of routes) {\n\t\t// Only match pages and api routes\n\t\tif (entry.kind !== \"page\" && entry.kind !== \"api\") continue;\n\n\t\tconst { regex, paramNames } = buildPatternRegex(entry.segments);\n\t\tconst match = regex.exec(normalized);\n\n\t\tif (!match) continue;\n\n\t\tconst params: Record<string, string> = {};\n\t\tparamNames.forEach((name, index) => {\n\t\t\tconst captured = match[index + 1];\n\t\t\tif (captured !== undefined) {\n\t\t\t\tparams[name] = decodeURIComponent(captured);\n\t\t\t}\n\t\t});\n\n\t\treturn { entry, params };\n\t}\n\n\treturn null;\n}\n\nexport function findLayoutsForPathname(\n\tpathname: string,\n\troutes: RouteManifestEntry[],\n): RouteManifestEntry[] {\n\tconst layoutRoutes = routes.filter((route) => route.kind === \"layout\");\n\n\treturn layoutRoutes.filter((layout) => {\n\t\tif (layout.urlPattern === \"/\") return true;\n\t\treturn (\n\t\t\tpathname === layout.urlPattern ||\n\t\t\tpathname.startsWith(`${layout.urlPattern}/`)\n\t\t);\n\t});\n}\n\nexport function findSpecialRoute(\n\tkind: \"loading\" | \"not-found\" | \"error\",\n\tpathname: string,\n\troutes: RouteManifestEntry[],\n): RouteManifestEntry | null {\n\tconst candidates = routes.filter((route) => route.kind === kind);\n\n\t// Find the most specific match (longest matching prefix)\n\tlet best: RouteManifestEntry | null = null;\n\tlet bestLength = -1;\n\n\tfor (const candidate of candidates) {\n\t\tconst prefix = candidate.urlPattern === \"/\" ? \"\" : candidate.urlPattern;\n\t\tif (pathname.startsWith(prefix) && prefix.length > bestLength) {\n\t\t\tbest = candidate;\n\t\t\tbestLength = prefix.length;\n\t\t}\n\t}\n\n\treturn best;\n}\n",
|
|
12
|
+
"import { existsSync, readdirSync, statSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { resolveRouteMode } from \"../render/modes\";\nimport type { RenderConfig } from \"../render/types\";\nimport { readManifest } from \"../router/manifest\";\nimport type {\n\tArtifactKind,\n\tForgeBuildArtifact,\n\tForgeInspectReport,\n\tForgeRouteModeEntry,\n} from \"./types\";\n\nexport interface InspectOptions {\n\treadonly outDir: string;\n\treadonly renderConfig: RenderConfig;\n}\n\nfunction detectArtifactKind(filename: string): ArtifactKind {\n\tif (filename === \"route-manifest.json\") return \"manifest\";\n\tif (filename.endsWith(\".css\")) return \"stylesheet\";\n\tif (filename.endsWith(\".js\") || filename.endsWith(\".mjs\")) return \"script\";\n\treturn \"asset\";\n}\n\nfunction formatBytes(bytes: number): string {\n\tif (bytes < 1024) return `${bytes} B`;\n\tif (bytes < 1_048_576) return `${(bytes / 1024).toFixed(1)} KB`;\n\treturn `${(bytes / 1_048_576).toFixed(2)} MB`;\n}\n\nfunction scanDirectory(dirPath: string): ForgeBuildArtifact[] {\n\tif (!existsSync(dirPath)) return [];\n\tconst collected: ForgeBuildArtifact[] = [];\n\n\tfunction walk(current: string): void {\n\t\tconst entries = readdirSync(current, { withFileTypes: true });\n\t\tfor (const entry of entries) {\n\t\t\tconst full = join(current, entry.name);\n\t\t\tif (entry.isDirectory()) {\n\t\t\t\twalk(full);\n\t\t\t} else if (entry.isFile()) {\n\t\t\t\tcollected.push({\n\t\t\t\t\toutputPath: full,\n\t\t\t\t\tsizeBytes: statSync(full).size,\n\t\t\t\t\tkind: detectArtifactKind(entry.name),\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\twalk(dirPath);\n\treturn collected;\n}\n\nexport function inspectBuild(options: InspectOptions): ForgeInspectReport {\n\tconst artifacts = scanDirectory(options.outDir);\n\tconst manifestPath = join(options.outDir, \"route-manifest.json\");\n\tconst manifest = readManifest(manifestPath);\n\n\tconst emptyManifest = {\n\t\tversion: \"1\" as const,\n\t\tgeneratedAt: new Date().toISOString(),\n\t\troutes: [],\n\t};\n\n\tconst routeModes: ForgeRouteModeEntry[] = (manifest ?? emptyManifest).routes\n\t\t.filter((r) => r.kind === \"page\" || r.kind === \"api\")\n\t\t.map((r) => {\n\t\t\tconst resolved = resolveRouteMode(r.urlPattern, options.renderConfig);\n\t\t\treturn {\n\t\t\t\tpattern: r.urlPattern,\n\t\t\t\tmode: resolved.mode,\n\t\t\t\tsource: resolved.source,\n\t\t\t};\n\t\t});\n\n\treturn {\n\t\tbuildDir: options.outDir,\n\t\tartifacts,\n\t\tmanifest: manifest ?? emptyManifest,\n\t\trouteModes,\n\t\ttotalSizeBytes: artifacts.reduce((sum, a) => sum + a.sizeBytes, 0),\n\t\tinspectedAt: new Date().toISOString(),\n\t};\n}\n\nexport function printInspectReport(report: ForgeInspectReport): void {\n\tconst sep = \"─\".repeat(58);\n\tconsole.log(`\n \\n Rakta.js Forge - Build Inspection\n `);\n\tconsole.log(`\n ${sep}\n `);\n\tconsole.log(`\n Directory: ${report.buildDir}\n `);\n\tconsole.log(`\n Inspected: ${report.inspectedAt}\n `);\n\tconsole.log(`\n Total size: ${formatBytes(report.totalSizeBytes)}\\n\n `);\n\n\tif (report.artifacts.length > 0) {\n\t\tconsole.log(\"Artifacts:\");\n\t\tfor (const artifact of report.artifacts) {\n\t\t\tconst rel = artifact.outputPath\n\t\t\t\t.replace(report.buildDir, \".\")\n\t\t\t\t.replace(/\\\\/g, \"/\");\n\t\t\tconsole.log(`\n [${artifact.kind.padEnd(10)}] \n ${rel.padEnd(38)} \n ${formatBytes(artifact.sizeBytes)}`);\n\t\t}\n\t\tconsole.log(\"\");\n\t}\n\n\tif (report.routeModes.length > 0) {\n\t\tconsole.log(\"Route Render Modes:\");\n\t\tfor (const rm of report.routeModes) {\n\t\t\tconst src = rm.source === \"route-override\" ? \"(override)\" : \"(default) \";\n\t\t\tconsole.log(`\n ${rm.mode.toUpperCase().padEnd(8)} \n ${rm.pattern.padEnd(36)} ${src}`);\n\t\t}\n\t\tconsole.log(\"\");\n\t}\n\n\tconsole.log(`${sep}\\n`);\n}\n"
|
|
13
|
+
],
|
|
14
|
+
"mappings": "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",
|
|
15
|
+
"debugId": "6749B66412BC6D2064756E2164756E21",
|
|
16
|
+
"names": []
|
|
17
|
+
}
|