elegance-js 2.1.37 → 3.0.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.
Files changed (138) hide show
  1. package/bin/bootstrap.js +18 -0
  2. package/bin/run.js +2 -0
  3. package/dist/build/common.d.ts +147 -0
  4. package/dist/build/common.d.ts.map +1 -0
  5. package/dist/build/common.js +599 -0
  6. package/dist/build/dev.d.ts +2 -0
  7. package/dist/build/dev.d.ts.map +1 -0
  8. package/dist/build/dev.js +234 -0
  9. package/dist/build/prod.d.ts +2 -0
  10. package/dist/build/prod.d.ts.map +1 -0
  11. package/dist/build/prod.js +212 -0
  12. package/dist/build/render.d.ts +29 -0
  13. package/dist/build/render.d.ts.map +1 -0
  14. package/dist/build/render.js +234 -0
  15. package/dist/client.d.ts +13 -0
  16. package/dist/client.d.ts.map +1 -0
  17. package/dist/client.js +677 -0
  18. package/dist/config.d.ts +7 -0
  19. package/dist/config.d.ts.map +1 -0
  20. package/dist/config.js +80 -0
  21. package/dist/constants.d.ts +10 -0
  22. package/dist/constants.d.ts.map +1 -0
  23. package/dist/constants.js +20 -0
  24. package/dist/elements.d.ts +2 -0
  25. package/dist/elements.d.ts.map +1 -0
  26. package/dist/elements.js +14 -0
  27. package/dist/error.d.ts +20 -0
  28. package/dist/error.d.ts.map +1 -0
  29. package/dist/error.js +123 -0
  30. package/dist/globals.d.ts +6 -0
  31. package/dist/globals.d.ts.map +1 -0
  32. package/dist/globals.js +106 -0
  33. package/dist/logger.d.ts +32 -0
  34. package/dist/logger.d.ts.map +1 -0
  35. package/dist/logger.js +72 -0
  36. package/dist/page-tools.d.ts +19 -0
  37. package/dist/page-tools.d.ts.map +1 -0
  38. package/dist/page-tools.js +141 -0
  39. package/dist/processing/oxc.d.ts +17 -0
  40. package/dist/processing/oxc.d.ts.map +1 -0
  41. package/dist/processing/oxc.js +938 -0
  42. package/dist/processing/taglist.d.ts +2 -0
  43. package/dist/processing/taglist.d.ts.map +1 -0
  44. package/dist/processing/taglist.js +215 -0
  45. package/dist/processing/tsx.d.ts +2 -0
  46. package/dist/processing/tsx.d.ts.map +1 -0
  47. package/dist/processing/tsx.js +131 -0
  48. package/dist/run.d.ts +3 -0
  49. package/dist/run.d.ts.map +1 -0
  50. package/dist/run.js +147 -0
  51. package/dist/server/dev.d.ts +2 -0
  52. package/dist/server/dev.d.ts.map +1 -0
  53. package/dist/server/dev.js +10 -0
  54. package/dist/server/prod.d.ts +2 -0
  55. package/dist/server/prod.d.ts.map +1 -0
  56. package/dist/server/prod.js +42 -0
  57. package/dist/server/security.d.ts +64 -0
  58. package/dist/server/security.d.ts.map +1 -0
  59. package/dist/server/security.js +120 -0
  60. package/dist/server/server.d.ts +73 -99
  61. package/dist/server/server.d.ts.map +1 -0
  62. package/dist/server/server.js +830 -680
  63. package/dist/types/component.d.ts +85 -0
  64. package/dist/types/component.d.ts.map +1 -0
  65. package/dist/types/component.js +0 -0
  66. package/dist/types/config.d.ts +12 -0
  67. package/dist/types/config.d.ts.map +1 -0
  68. package/dist/types/config.js +0 -0
  69. package/dist/types/elements.d.ts +412 -0
  70. package/dist/types/elements.d.ts.map +1 -0
  71. package/dist/types/elements.js +0 -0
  72. package/dist/types/index.d.ts +9 -0
  73. package/dist/types/index.d.ts.map +1 -0
  74. package/dist/types/index.js +5 -0
  75. package/dist/types/jsx.d.ts +976 -0
  76. package/dist/types/jsx.d.ts.map +1 -0
  77. package/dist/types/jsx.js +0 -0
  78. package/dist/types/server-actions.d.ts +60 -0
  79. package/dist/types/server-actions.d.ts.map +1 -0
  80. package/dist/types/server-actions.js +0 -0
  81. package/dist/user-utils.d.ts +23 -0
  82. package/dist/user-utils.d.ts.map +1 -0
  83. package/dist/user-utils.js +61 -0
  84. package/package.json +47 -28
  85. package/README.md +0 -4
  86. package/dist/client/effect.d.ts +0 -27
  87. package/dist/client/effect.js +0 -37
  88. package/dist/client/eventListener.d.ts +0 -39
  89. package/dist/client/eventListener.js +0 -52
  90. package/dist/client/loadHook.d.ts +0 -34
  91. package/dist/client/loadHook.js +0 -52
  92. package/dist/client/observer.d.ts +0 -36
  93. package/dist/client/observer.js +0 -66
  94. package/dist/client/runtime.d.ts +0 -105
  95. package/dist/client/runtime.js +0 -624
  96. package/dist/client/state.d.ts +0 -40
  97. package/dist/client/state.js +0 -110
  98. package/dist/compilation/compiler.d.ts +0 -163
  99. package/dist/compilation/compiler.js +0 -1164
  100. package/dist/components/ClientComponent.d.ts +0 -22
  101. package/dist/components/ClientComponent.js +0 -55
  102. package/dist/components/Link.d.ts +0 -16
  103. package/dist/components/Link.js +0 -21
  104. package/dist/components/Portal.d.ts +0 -2
  105. package/dist/components/Portal.js +0 -2
  106. package/dist/elements/element.d.ts +0 -87
  107. package/dist/elements/element.js +0 -33
  108. package/dist/elements/element_list.d.ts +0 -7
  109. package/dist/elements/element_list.js +0 -65
  110. package/dist/elements/raw.d.ts +0 -14
  111. package/dist/elements/raw.js +0 -78
  112. package/dist/elements/specific_props.d.ts +0 -750
  113. package/dist/elements/specific_props.js +0 -1
  114. package/dist/global.d.ts +0 -229
  115. package/dist/global.js +0 -1
  116. package/dist/index.d.ts +0 -16
  117. package/dist/index.js +0 -12
  118. package/dist/server/layout.d.ts +0 -34
  119. package/dist/server/layout.js +0 -6
  120. package/dist/server/log.d.ts +0 -12
  121. package/dist/server/log.js +0 -64
  122. package/dist/server/page.d.ts +0 -32
  123. package/dist/server/page.js +0 -6
  124. package/dist/server/runtime.d.ts +0 -6
  125. package/dist/server/runtime.js +0 -92
  126. package/scripts/bootstrap.js +0 -95
  127. package/scripts/bootstrap_files/elegance.txt +0 -40
  128. package/scripts/bootstrap_files/index.txt +0 -3
  129. package/scripts/bootstrap_files/layout.txt +0 -46
  130. package/scripts/bootstrap_files/middleware.txt +0 -18
  131. package/scripts/bootstrap_files/page.txt +0 -123
  132. package/scripts/bootstrap_files/route.txt +0 -6
  133. package/scripts/elegance_dev.ts +0 -42
  134. package/scripts/elegance_prod.ts +0 -42
  135. package/scripts/elegance_static.ts +0 -26
  136. package/scripts/prod.js +0 -13
  137. package/scripts/run.js +0 -13
  138. package/scripts/static.js +0 -13
@@ -0,0 +1,599 @@
1
+ import esbuild from "esbuild";
2
+ import {
3
+ sanitize,
4
+ eleganceTsxPlugin,
5
+ collectLayouts,
6
+ composeRenderFn,
7
+ gatherMetaFromModules
8
+ } from "../page-tools.js";
9
+ import { transformBundle, transformChunk, generateLayoutBundle } from "../processing/oxc.js";
10
+ import { hookGlobals } from "../globals.js";
11
+ hookGlobals();
12
+ import {
13
+ readFile,
14
+ mkdir,
15
+ writeFile,
16
+ copyFile,
17
+ cp,
18
+ stat as fsStat,
19
+ unlink,
20
+ readdir,
21
+ rm
22
+ } from "node:fs/promises";
23
+ import { existsSync } from "node:fs";
24
+ import { createHash } from "node:crypto";
25
+ import { join, dirname, resolve, relative, basename } from "node:path";
26
+ import { DIST_DIR, CACHE_DIR, PAGES_DIR } from "../constants.js";
27
+ import { isRichError, printError, richError } from "../error.js";
28
+ import { AsyncLocalStorage } from "node:async_hooks";
29
+ const SINGLE_PARAM_RE = /\[([^\]]+)\]/;
30
+ const PARAM_STRIP_RE = /^\.{3}/;
31
+ const EXPORT_RE = /\bexport\b/;
32
+ const IS_DEV = process.env.ELEGANCE_DEV_MODE === "dev";
33
+ const importContext = new AsyncLocalStorage();
34
+ async function importModule(path) {
35
+ const store = {
36
+ preBuildHooks: [],
37
+ postBuildHooks: [],
38
+ buildCallbacks: [],
39
+ publishFiles: [],
40
+ atomSeeds: []
41
+ };
42
+ const module = await importContext.run(store, async () => await import(path));
43
+ return { module, ...store };
44
+ }
45
+ const importedModules = /* @__PURE__ */ new Map();
46
+ async function importCompiledModule(sourceFile, filePath) {
47
+ const contents = await readFile(filePath);
48
+ if (importedModules.has(sourceFile)) {
49
+ return importedModules.get(sourceFile);
50
+ }
51
+ const tmpDir = join(process.cwd(), ".temp");
52
+ await mkdir(tmpDir, { recursive: true });
53
+ const tmpPath = join(tmpDir, `${Date.now() + Math.random() * 1e3}.mjs`);
54
+ await writeFile(tmpPath, contents);
55
+ try {
56
+ return await importModule(`copycat://${resolve(sourceFile)}?real=${resolve(tmpPath)}`);
57
+ } catch (err) {
58
+ if (isRichError(err)) throw err;
59
+ throw richError({
60
+ title: "Failed to Import Module",
61
+ cause: err,
62
+ doShowStack: true
63
+ });
64
+ } finally {
65
+ await unlink(tmpPath);
66
+ }
67
+ }
68
+ function pageCacheKey(pathname) {
69
+ return `route_${sanitize(pathname.replace(/^\//, "")) || "index"}`;
70
+ }
71
+ function layoutFileCacheKey(layoutPath) {
72
+ let s = sanitize(relative(PAGES_DIR, layoutPath).replace(/\.tsx?$/, ""));
73
+ if (s.endsWith("_layout")) s = s.slice(0, -7);
74
+ return `layout_${s}`;
75
+ }
76
+ function statusCodeCacheKey(filePath) {
77
+ return `statusCode_${sanitize(relative(PAGES_DIR, filePath).replace(/\.tsx?$/, ""))}`;
78
+ }
79
+ function serverMjsPath(key) {
80
+ return join(CACHE_DIR, `${key}.server.mjs`);
81
+ }
82
+ function preClientMjsPath(key) {
83
+ return join(CACHE_DIR, `${key}.pre_client.mjs`);
84
+ }
85
+ function clientMjsPath(key) {
86
+ return join(CACHE_DIR, `${key}.client.mjs`);
87
+ }
88
+ function chunkClientPath(key) {
89
+ return join(DIST_DIR, "chunks", `${key}.client.mjs`);
90
+ }
91
+ async function runBuildHooks(compiled, stage) {
92
+ if (stage === "pre") {
93
+ const buildCallbacks = compiled.buildCallbacks.splice(0);
94
+ try {
95
+ await Promise.all(buildCallbacks.map((cb) => cb()));
96
+ } catch (err) {
97
+ if (isRichError(err)) throw err;
98
+ throw richError({ title: "Build Hook Failed to Run", cause: err, origin: compiled.pathname, doShowStack: true });
99
+ }
100
+ try {
101
+ await Promise.all(compiled.preBuildHooks.map((cb) => cb()));
102
+ } catch (err) {
103
+ if (isRichError(err)) throw err;
104
+ throw richError({ title: "Build Hook Failed to Run", cause: err, origin: compiled.pathname, doShowStack: true });
105
+ }
106
+ return;
107
+ }
108
+ try {
109
+ await Promise.all(compiled.postBuildHooks.map((cb) => cb()));
110
+ } catch (err) {
111
+ if (isRichError(err)) throw err;
112
+ throw richError({ title: "Build Hook Failed to Run", cause: err, origin: compiled.pathname, doShowStack: true });
113
+ }
114
+ await Promise.all(
115
+ compiled.publishFiles.map(async ({ input, target }) => {
116
+ const dest = join(DIST_DIR, target);
117
+ await mkdir(dirname(dest), { recursive: true });
118
+ try {
119
+ await copyFile(input, dest);
120
+ } catch (err) {
121
+ const error = richError({
122
+ title: "Failed to Publish File",
123
+ cause: `A post-build hook attempted to call publishFile() on a file that did not exist during the build.
124
+ File: ${input}`,
125
+ origin: compiled.pathname,
126
+ doShowStack: false
127
+ });
128
+ printError(error);
129
+ throw err;
130
+ }
131
+ })
132
+ );
133
+ }
134
+ function minifyHtml(html) {
135
+ return html.replace(/\s+/g, " ").replace(/> </g, "><").trim();
136
+ }
137
+ async function minifyCode(code) {
138
+ const result = await esbuild.transform(code, { minify: true, loader: "js" });
139
+ return result.code;
140
+ }
141
+ function getSlugParamName(pattern) {
142
+ const match = SINGLE_PARAM_RE.exec(pattern);
143
+ if (!match) return "slug";
144
+ return match[1].replace(PARAM_STRIP_RE, "");
145
+ }
146
+ async function fileHasExports(filePath) {
147
+ try {
148
+ const content = await readFile(filePath, "utf-8");
149
+ return EXPORT_RE.test(content);
150
+ } catch (err) {
151
+ const error = richError({
152
+ title: "Internal Error",
153
+ cause: "Elegance attempted to check if a file had exports, but ran into an unexpected error.",
154
+ hint: "If the error persists, please report it.",
155
+ origin: filePath,
156
+ doShowStack: true
157
+ });
158
+ console.error(error);
159
+ printError(error);
160
+ throw err;
161
+ }
162
+ }
163
+ async function computeFileHash(filePath) {
164
+ const content = await readFile(filePath);
165
+ return createHash("sha1").update(content).digest("hex");
166
+ }
167
+ async function loadIncrementalState() {
168
+ const path = join(CACHE_DIR, "incremental.json");
169
+ try {
170
+ return JSON.parse(await readFile(path, "utf-8"));
171
+ } catch {
172
+ return { fileHashes: {}, clientCodeHashes: {} };
173
+ }
174
+ }
175
+ async function saveIncrementalState(state) {
176
+ const path = join(CACHE_DIR, "incremental.json");
177
+ await mkdir(CACHE_DIR, { recursive: true });
178
+ await writeFile(path, JSON.stringify(state));
179
+ }
180
+ async function copyPublicDir(publicDir) {
181
+ if (!existsSync(publicDir)) return;
182
+ await cp(publicDir, DIST_DIR, { recursive: true });
183
+ }
184
+ async function copyPublicDirIncremental(publicDir) {
185
+ if (!existsSync(publicDir)) return;
186
+ const dirEnsured = /* @__PURE__ */ new Map();
187
+ const ensureDir = (dir) => {
188
+ let p = dirEnsured.get(dir);
189
+ if (!p) dirEnsured.set(dir, p = mkdir(dir, { recursive: true }));
190
+ return p;
191
+ };
192
+ async function walk(srcDir, destDir) {
193
+ let entries;
194
+ try {
195
+ entries = await readdir(srcDir, { withFileTypes: true });
196
+ } catch {
197
+ return;
198
+ }
199
+ await Promise.all(entries.map(async (e) => {
200
+ const src = join(srcDir, e.name);
201
+ const dest = join(destDir, e.name);
202
+ if (e.isDirectory()) {
203
+ await walk(src, dest);
204
+ return;
205
+ }
206
+ try {
207
+ const [ss, ds] = await Promise.all([fsStat(src), fsStat(dest)]);
208
+ if (ds.mtimeMs >= ss.mtimeMs && ds.size === ss.size) return;
209
+ } catch {
210
+ }
211
+ await ensureDir(destDir);
212
+ await copyFile(src, dest);
213
+ }));
214
+ }
215
+ await walk(publicDir, DIST_DIR);
216
+ }
217
+ async function buildClientRuntime(minify) {
218
+ await esbuild.build({
219
+ entryPoints: [join(import.meta.dirname, "..", "client.js")],
220
+ bundle: true,
221
+ outfile: join(DIST_DIR, "client.js"),
222
+ minify,
223
+ format: "esm",
224
+ platform: "browser",
225
+ target: "es2020",
226
+ treeShaking: true,
227
+ loader: { ".ts": "ts", ".tsx": "ts" },
228
+ plugins: [eleganceTsxPlugin]
229
+ });
230
+ }
231
+ const ROUTE_ESBUILD_BASE = {
232
+ bundle: true,
233
+ write: false,
234
+ format: "esm",
235
+ target: `node${process.versions.node}`,
236
+ legalComments: "inline",
237
+ packages: "external",
238
+ external: ["../../../v11/user-utils"],
239
+ loader: { ".ts": "ts", ".tsx": "ts" },
240
+ plugins: [eleganceTsxPlugin],
241
+ minify: false,
242
+ treeShaking: false
243
+ };
244
+ async function walkPagesDir(dir, onDir) {
245
+ let entries;
246
+ try {
247
+ entries = await readdir(dir, { withFileTypes: true });
248
+ } catch {
249
+ return;
250
+ }
251
+ const subdirs = entries.filter((e) => e.isDirectory() && !e.name.startsWith(".") && !e.name.startsWith("_")).map((e) => join(dir, e.name));
252
+ await Promise.all(subdirs.map((sub) => walkPagesDir(sub, onDir)));
253
+ await onDir(dir);
254
+ }
255
+ async function discoverApiRoutes(pagesDir) {
256
+ const entries = [];
257
+ await walkPagesDir(pagesDir, async (dir) => {
258
+ const candidate = join(dir, "route.ts");
259
+ if (existsSync(candidate)) {
260
+ const pathname = dir === pagesDir ? "/" : dir.slice(pagesDir.length);
261
+ entries.push({ pathname, file: candidate });
262
+ }
263
+ });
264
+ return entries;
265
+ }
266
+ async function discoverMiddlewares(pagesDir) {
267
+ const entries = [];
268
+ await walkPagesDir(pagesDir, async (dir) => {
269
+ const candidate = join(dir, "middleware.ts");
270
+ if (existsSync(candidate)) entries.push({ file: candidate });
271
+ });
272
+ return entries;
273
+ }
274
+ async function compileServerFiles(files, stamp, label) {
275
+ if (files.size === 0) return /* @__PURE__ */ new Map();
276
+ const tmpDir = join(process.cwd(), ".temp", `${label}_${stamp}`);
277
+ await mkdir(tmpDir, { recursive: true });
278
+ try {
279
+ await esbuild.build({
280
+ ...ROUTE_ESBUILD_BASE,
281
+ entryPoints: Object.fromEntries(files),
282
+ write: true,
283
+ outdir: tmpDir,
284
+ splitting: false,
285
+ minify: false
286
+ });
287
+ const result = /* @__PURE__ */ new Map();
288
+ await Promise.all([...files.keys()].map(async (key) => {
289
+ const raw = await readFile(join(tmpDir, `${key}.js`), "utf-8");
290
+ const { serverCode, preClientCode } = transformBundle(raw, files.get(key));
291
+ result.set(key, { serverCode, preClientCode });
292
+ }));
293
+ return result;
294
+ } finally {
295
+ await rm(tmpDir, { recursive: true, force: true }).catch(() => {
296
+ });
297
+ }
298
+ }
299
+ async function findAndCacheStatusCodePages() {
300
+ const candidates = [];
301
+ async function walk(dir) {
302
+ let dirents;
303
+ try {
304
+ dirents = await readdir(dir, { withFileTypes: true });
305
+ } catch {
306
+ return;
307
+ }
308
+ await Promise.all(
309
+ dirents.filter((ent) => ent.isDirectory()).map((ent) => walk(join(dir, ent.name)))
310
+ );
311
+ for (const ent of dirents) {
312
+ if (!ent.isDirectory() && /^\d{3}\.tsx?$/.test(ent.name))
313
+ candidates.push({ full: join(dir, ent.name), dir });
314
+ }
315
+ }
316
+ await walk(PAGES_DIR);
317
+ if (candidates.length === 0) return [];
318
+ await mkdir(CACHE_DIR, { recursive: true });
319
+ const settled = await Promise.allSettled(
320
+ candidates.map(async ({ full, dir }) => {
321
+ const layouts = await collectLayouts(dir, PAGES_DIR);
322
+ const layoutKeys = layouts.map(layoutFileCacheKey);
323
+ const cacheKey = statusCodeCacheKey(full);
324
+ const stamp = Date.now();
325
+ const allFiles = /* @__PURE__ */ new Map();
326
+ allFiles.set(cacheKey, full);
327
+ for (let i = 0; i < layouts.length; i++) {
328
+ allFiles.set(layoutKeys[i], layouts[i]);
329
+ }
330
+ const compiled = await compileServerFiles(allFiles, stamp, `sc_${cacheKey}`);
331
+ await Promise.all(
332
+ [...compiled.entries()].map(
333
+ ([k, { serverCode }]) => writeFile(serverMjsPath(k), serverCode)
334
+ )
335
+ );
336
+ await Promise.all(
337
+ layoutKeys.map(async (lk, i) => {
338
+ if (existsSync(clientMjsPath(lk))) return;
339
+ const { preClientCode } = compiled.get(lk) ?? {};
340
+ if (!preClientCode) return;
341
+ let bundle = generateLayoutBundle(preClientCode, layouts[i]);
342
+ if (!IS_DEV) bundle = await minifyCode(bundle);
343
+ await Promise.all([
344
+ writeFile(clientMjsPath(lk), bundle),
345
+ writeFile(chunkClientPath(lk), bundle)
346
+ ]);
347
+ })
348
+ );
349
+ const { preClientCode: pagePreClient } = compiled.get(cacheKey);
350
+ await writeFile(
351
+ preClientMjsPath(cacheKey),
352
+ IS_DEV ? pagePreClient : await minifyCode(pagePreClient)
353
+ );
354
+ return {
355
+ pageFile: full,
356
+ layouts,
357
+ layoutCacheKeys: layoutKeys,
358
+ cacheKey
359
+ };
360
+ })
361
+ );
362
+ const entries = [];
363
+ for (let i = 0; i < settled.length; i++) {
364
+ const result = settled[i];
365
+ if (result.status === "fulfilled") {
366
+ entries.push(result.value);
367
+ } else {
368
+ const { full } = candidates[i];
369
+ const error = richError({
370
+ title: "Compilation Error",
371
+ cause: "A status code page threw an error whilst it was being compiled. (full error below).",
372
+ origin: full,
373
+ doShowStack: false
374
+ });
375
+ console.error(error);
376
+ printError(error);
377
+ }
378
+ }
379
+ return entries;
380
+ }
381
+ async function transpileAllRoutes(routes, minify, skipServerKeys = /* @__PURE__ */ new Set()) {
382
+ if (routes.length === 0) return /* @__PURE__ */ new Map();
383
+ const stamp = Date.now();
384
+ const clientTmpOut = join(process.cwd(), ".temp", `client_out_${stamp}`);
385
+ const serverTmpOut = join(process.cwd(), ".temp", `server_out_${stamp}`);
386
+ const chunksDir = join(DIST_DIR, "chunks");
387
+ const keyToRoute = /* @__PURE__ */ new Map();
388
+ const keyToLayoutPath = /* @__PURE__ */ new Map();
389
+ const clientEntryPoints = {};
390
+ const allServerFiles = /* @__PURE__ */ new Map();
391
+ for (const route of routes) {
392
+ const key = pageCacheKey(route.pathname);
393
+ clientEntryPoints[key] = route.pageFile;
394
+ keyToRoute.set(key, route);
395
+ if (!skipServerKeys.has(key))
396
+ allServerFiles.set(key, route.pageFile);
397
+ for (const layoutPath of route.layouts) {
398
+ const lk = layoutFileCacheKey(layoutPath);
399
+ if (!keyToLayoutPath.has(lk)) {
400
+ clientEntryPoints[lk] = layoutPath;
401
+ keyToLayoutPath.set(lk, layoutPath);
402
+ }
403
+ if (!skipServerKeys.has(lk))
404
+ allServerFiles.set(lk, layoutPath);
405
+ }
406
+ }
407
+ const hasServerWork = allServerFiles.size > 0;
408
+ await Promise.all([
409
+ mkdir(clientTmpOut, { recursive: true }),
410
+ mkdir(chunksDir, { recursive: true }),
411
+ mkdir(CACHE_DIR, { recursive: true }),
412
+ hasServerWork ? mkdir(serverTmpOut, { recursive: true }) : Promise.resolve()
413
+ ]);
414
+ const serverBuildProm = hasServerWork ? esbuild.build({
415
+ ...ROUTE_ESBUILD_BASE,
416
+ entryPoints: Object.fromEntries(allServerFiles),
417
+ write: true,
418
+ outdir: serverTmpOut,
419
+ splitting: false,
420
+ minify: false
421
+ }).then(() => void 0) : Promise.resolve();
422
+ await esbuild.build({
423
+ ...ROUTE_ESBUILD_BASE,
424
+ entryPoints: clientEntryPoints,
425
+ write: true,
426
+ outdir: clientTmpOut,
427
+ splitting: true,
428
+ minify: false
429
+ });
430
+ const clientOutputs = await readdir(clientTmpOut);
431
+ const entryStems = /* @__PURE__ */ new Set([...keyToRoute.keys(), ...keyToLayoutPath.keys()]);
432
+ const chunkFiles = clientOutputs.filter(
433
+ (f) => f.endsWith(".js") && !entryStems.has(basename(f, ".js"))
434
+ );
435
+ const chunkUrlMap = /* @__PURE__ */ new Map();
436
+ await Promise.all(chunkFiles.map(async (chunkFile) => {
437
+ const raw = await readFile(join(clientTmpOut, chunkFile), "utf-8");
438
+ const processed = transformChunk(raw, chunkFile);
439
+ chunkUrlMap.set(`./${chunkFile}`, `/chunks/${chunkFile}`);
440
+ await writeFile(join(chunksDir, chunkFile), processed);
441
+ }));
442
+ let replaceChunkUrls;
443
+ if (chunkUrlMap.size > 0) {
444
+ const escapedKeys = [...chunkUrlMap.keys()].map(
445
+ (k) => k.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
446
+ );
447
+ const chunkRe = new RegExp(escapedKeys.join("|"), "g");
448
+ replaceChunkUrls = (code) => code.replace(chunkRe, (m) => chunkUrlMap.get(m));
449
+ } else {
450
+ replaceChunkUrls = (code) => code;
451
+ }
452
+ await serverBuildProm;
453
+ if (hasServerWork) {
454
+ await Promise.all([...allServerFiles.entries()].map(async ([key, filePath]) => {
455
+ const raw = await readFile(join(serverTmpOut, `${key}.js`), "utf-8");
456
+ const { serverCode } = transformBundle(raw, filePath);
457
+ await writeFile(serverMjsPath(key), serverCode);
458
+ }));
459
+ }
460
+ await Promise.all([...keyToLayoutPath.entries()].map(async ([lk, layoutPath]) => {
461
+ const raw = await readFile(join(clientTmpOut, `${lk}.js`), "utf-8");
462
+ const { preClientCode: rawPre } = transformBundle(raw, layoutPath);
463
+ const preClientCode = replaceChunkUrls(rawPre);
464
+ let layoutBundle = generateLayoutBundle(preClientCode, layoutPath);
465
+ if (minify) layoutBundle = await minifyCode(layoutBundle);
466
+ await Promise.all([
467
+ writeFile(clientMjsPath(lk), layoutBundle),
468
+ writeFile(chunkClientPath(lk), layoutBundle)
469
+ ]);
470
+ }));
471
+ const results = /* @__PURE__ */ new Map();
472
+ await Promise.all([...keyToRoute.entries()].map(async ([key, route]) => {
473
+ const [clientRaw, rawServerCode] = await Promise.all([
474
+ readFile(join(clientTmpOut, `${key}.js`), "utf-8"),
475
+ readFile(serverMjsPath(key), "utf-8")
476
+ ]);
477
+ const { preClientCode: rawPreClientCode } = transformBundle(clientRaw, route.pageFile);
478
+ let preClientCode = replaceChunkUrls(rawPreClientCode);
479
+ const sharedChunkPaths = chunkFiles.filter((f) => clientRaw.includes(`./${f}`)).map((f) => `/chunks/${f}`);
480
+ await writeFile(preClientMjsPath(key), preClientCode);
481
+ results.set(route.pathname, {
482
+ pathname: route.pathname,
483
+ pageFile: route.pageFile,
484
+ layouts: route.layouts,
485
+ serverCode: rawServerCode,
486
+ preClientCode,
487
+ sharedChunkPaths
488
+ });
489
+ }));
490
+ await Promise.all([
491
+ rm(clientTmpOut, { recursive: true, force: true }).catch(() => {
492
+ }),
493
+ rm(serverTmpOut, { recursive: true, force: true }).catch(() => {
494
+ })
495
+ ]);
496
+ return results;
497
+ }
498
+ async function loadLayoutFromCache(pathname, cacheKey) {
499
+ try {
500
+ const { module, buildCallbacks, postBuildHooks, preBuildHooks, publishFiles, atomSeeds } = await importModule(`copycat://${resolve(pathname)}?real=${serverMjsPath(cacheKey)}`);
501
+ if (typeof module.default !== "function") {
502
+ throw richError({
503
+ title: "Invalid Layout",
504
+ cause: "Could not get default export. For a layout to be valid, it must export a function that resolved into a VirtualNode",
505
+ hint: "Did you forget the *export* keyword?",
506
+ doShowStack: false
507
+ });
508
+ }
509
+ if (module.meta && typeof module.meta !== "function") {
510
+ throw richError({
511
+ title: "Invalid Layout",
512
+ cause: 'Meta export is not of type "function"',
513
+ hint: "The 'meta' export of a layout should be a function that resolves into an array of VirtualNodes.",
514
+ doShowStack: false
515
+ });
516
+ }
517
+ return {
518
+ default: module.default,
519
+ metadata: module.metadata ? module.metadata : () => [],
520
+ pathname,
521
+ buildCallbacks,
522
+ postBuildHooks,
523
+ preBuildHooks,
524
+ publishFiles,
525
+ atomSeeds
526
+ };
527
+ } catch (err) {
528
+ if (isRichError(err)) throw err;
529
+ throw richError({
530
+ title: "Failed to Import Layout",
531
+ cause: err,
532
+ origin: pathname,
533
+ doShowStack: true
534
+ });
535
+ }
536
+ }
537
+ async function loadRouteFromCache(entry) {
538
+ const { module, preBuildHooks, buildCallbacks, postBuildHooks, publishFiles, atomSeeds } = await importCompiledModule(entry.pageFile, serverMjsPath(entry.cacheKey));
539
+ if (typeof module.default !== "function") {
540
+ throw richError({
541
+ title: "Invalid Page",
542
+ cause: "Could not find default export.",
543
+ hint: "Did you forget the *default* keyword?",
544
+ doShowStack: false
545
+ });
546
+ }
547
+ const layoutModules = await Promise.all(
548
+ entry.layouts.map(
549
+ (layoutPath, i) => loadLayoutFromCache(layoutPath, entry.layoutCacheKeys[i])
550
+ )
551
+ );
552
+ for (const layout of layoutModules) {
553
+ preBuildHooks.push(...layout.preBuildHooks);
554
+ postBuildHooks.push(...layout.postBuildHooks);
555
+ buildCallbacks.push(...layout.buildCallbacks);
556
+ publishFiles.push(...layout.publishFiles);
557
+ atomSeeds.push(...layout.atomSeeds);
558
+ }
559
+ return {
560
+ default: composeRenderFn(module, layoutModules),
561
+ metadata: async (params) => gatherMetaFromModules(module, layoutModules, params ?? {}),
562
+ getEnumeratedRoutes: module.getEnumeratedRoutes,
563
+ pathname: entry.pathname,
564
+ preBuildHooks,
565
+ buildCallbacks,
566
+ postBuildHooks,
567
+ publishFiles,
568
+ atomSeeds
569
+ };
570
+ }
571
+ export {
572
+ ROUTE_ESBUILD_BASE,
573
+ buildClientRuntime,
574
+ chunkClientPath,
575
+ clientMjsPath,
576
+ computeFileHash,
577
+ copyPublicDir,
578
+ copyPublicDirIncremental,
579
+ discoverApiRoutes,
580
+ discoverMiddlewares,
581
+ fileHasExports,
582
+ findAndCacheStatusCodePages,
583
+ getSlugParamName,
584
+ importContext,
585
+ importModule,
586
+ layoutFileCacheKey,
587
+ loadIncrementalState,
588
+ loadLayoutFromCache,
589
+ loadRouteFromCache,
590
+ minifyCode,
591
+ minifyHtml,
592
+ pageCacheKey,
593
+ preClientMjsPath,
594
+ runBuildHooks,
595
+ saveIncrementalState,
596
+ serverMjsPath,
597
+ statusCodeCacheKey,
598
+ transpileAllRoutes
599
+ };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=dev.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/build/dev.ts"],"names":[],"mappings":""}