elegance-js 2.1.7 → 2.1.10

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.
@@ -1,1184 +1,34 @@
1
- // src/server/server.ts
2
- import { createServer as createHttpServer } from "http";
3
- import { promises as fs2 } from "fs";
4
- import { join, normalize, extname, dirname } from "path";
5
- import { pathToFileURL } from "url";
6
-
7
- // src/log.ts
8
- var quiet = false;
9
- function getTimestamp() {
10
- const now = /* @__PURE__ */ new Date();
11
- return now.toLocaleString(void 0, {
12
- year: "2-digit",
13
- month: "2-digit",
14
- day: "2-digit",
15
- hour: "2-digit",
16
- minute: "2-digit",
17
- second: "2-digit"
18
- });
19
- }
20
- function color(text, code) {
21
- return `\x1B[${code}m${text}\x1B[0m`;
22
- }
23
- function logInfo(...args) {
24
- if (quiet) return;
25
- console.info(`Elegance.JS: ${getTimestamp()} ${color("[INFO]:", 34)}`, ...args);
26
- }
27
- function logWarn(...args) {
28
- if (quiet) return;
29
- console.warn(`Elegance.JS: ${getTimestamp()} ${color("[WARN]:", 33)}`, ...args);
30
- }
31
- function logError(...args) {
32
- console.error(`Elegance.JS: ${getTimestamp()} ${color("[ERROR]:", 31)}`, ...args);
33
- }
34
- var log = {
35
- info: logInfo,
36
- warn: logWarn,
37
- error: logError
38
- };
39
-
40
- // src/server/server.ts
41
- import { gzip, deflate } from "zlib";
42
- import { promisify } from "util";
43
-
44
- // src/page_compiler.ts
45
- import fs from "fs";
46
- import path from "path";
47
- import { registerLoader, setArcTsConfig } from "ts-arc";
48
- import esbuild from "esbuild";
49
- import { fileURLToPath } from "url";
50
-
51
- // src/shared/serverElements.ts
52
- var createBuildableElement = (tag) => {
53
- return (options2, ...children) => ({
54
- tag,
55
- options: options2 || {},
56
- children
57
- });
58
- };
59
- var createChildrenlessBuildableElement = (tag) => {
60
- return (options2) => ({
61
- tag,
62
- options: options2 || {},
63
- children: null
64
- });
65
- };
66
- var childrenlessElementTags = [
67
- "area",
68
- "base",
69
- "br",
70
- "col",
71
- "embed",
72
- "hr",
73
- "img",
74
- "input",
75
- "link",
76
- "meta",
77
- "source",
78
- "track",
79
- "path",
80
- "rect"
81
- ];
82
- var elementTags = [
83
- "a",
84
- "address",
85
- "article",
86
- "aside",
87
- "audio",
88
- "blockquote",
89
- "body",
90
- "button",
91
- "canvas",
92
- "caption",
93
- "colgroup",
94
- "data",
95
- "datalist",
96
- "dd",
97
- "del",
98
- "details",
99
- "dialog",
100
- "div",
101
- "dl",
102
- "dt",
103
- "fieldset",
104
- "figcaption",
105
- "figure",
106
- "footer",
107
- "form",
108
- "h1",
109
- "h2",
110
- "h3",
111
- "h4",
112
- "h5",
113
- "h6",
114
- "head",
115
- "header",
116
- "hgroup",
117
- "html",
118
- "iframe",
119
- "ins",
120
- "label",
121
- "legend",
122
- "li",
123
- "main",
124
- "map",
125
- "meter",
126
- "nav",
127
- "noscript",
128
- "object",
129
- "ol",
130
- "optgroup",
131
- "option",
132
- "output",
133
- "p",
134
- "picture",
135
- "pre",
136
- "progress",
137
- "q",
138
- "section",
139
- "select",
140
- "summary",
141
- "table",
142
- "tbody",
143
- "td",
144
- "template",
145
- "textarea",
146
- "tfoot",
147
- "th",
148
- "thead",
149
- "time",
150
- "tr",
151
- "ul",
152
- "video",
153
- "span",
154
- "script",
155
- "abbr",
156
- "b",
157
- "bdi",
158
- "bdo",
159
- "cite",
160
- "code",
161
- "dfn",
162
- "em",
163
- "i",
164
- "kbd",
165
- "mark",
166
- "rp",
167
- "rt",
168
- "ruby",
169
- "s",
170
- "samp",
171
- "small",
172
- "strong",
173
- "sub",
174
- "sup",
175
- "u",
176
- "wbr",
177
- "title",
178
- "svg"
179
- ];
180
- var elements = {};
181
- var childrenlessElements = {};
182
- for (const element of elementTags) {
183
- elements[element] = createBuildableElement(element);
184
- }
185
- for (const element of childrenlessElementTags) {
186
- childrenlessElements[element] = createChildrenlessBuildableElement(element);
187
- }
188
- var allElements = {
189
- ...elements,
190
- ...childrenlessElements
191
- };
192
-
193
- // src/shared/bindServerElements.ts
194
- Object.assign(globalThis, elements);
195
- Object.assign(globalThis, childrenlessElements);
196
-
197
- // src/server/render.ts
198
- var renderRecursively = (element) => {
199
- let returnString = "";
200
- if (typeof element === "boolean") return returnString;
201
- else if (typeof element === "number" || typeof element === "string") {
202
- return returnString + element;
203
- } else if (Array.isArray(element)) {
204
- return returnString + element.join(", ");
205
- }
206
- returnString += `<${element.tag}`;
207
- if (typeof element.options === "object") {
208
- const {
209
- tag: elementTag,
210
- options: elementOptions,
211
- children: elementChildren
212
- } = element.options;
213
- if (elementTag !== void 0 && elementOptions !== void 0 && elementChildren !== void 0) {
214
- const children = element.children;
215
- element.children = [
216
- element.options,
217
- ...children
218
- ];
219
- element.options = {};
220
- } else {
221
- for (const [attrName, attrValue] of Object.entries(element.options)) {
222
- if (typeof attrValue === "object") {
223
- throw `Attr ${attrName}, for element ${element.tag} has obj type. Got: ${JSON.stringify(element, null, 2)}`;
224
- }
225
- returnString += ` ${attrName.toLowerCase()}="${attrValue}"`;
226
- }
227
- }
228
- } else if (typeof element.options !== "object" && element.options !== void 0) {
229
- element.children = [element.options, ...element.children || []];
230
- }
231
- if (element.children === null) {
232
- returnString += "/>";
233
- return returnString;
234
- }
235
- returnString += ">";
236
- for (const child of element.children) {
237
- returnString += renderRecursively(child);
238
- }
239
- returnString += `</${element.tag}>`;
240
- return returnString;
241
- };
242
- var serverSideRenderPage = async (page, pathname) => {
243
- if (!page) {
244
- throw `No Page Provided.`;
245
- }
246
- if (typeof page === "function") {
247
- throw `Unbuilt page provided to ssr page.`;
248
- }
249
- const bodyHTML = renderRecursively(page);
250
- return {
251
- bodyHTML
252
- };
253
- };
254
-
255
- // src/server/generateHTMLTemplate.ts
256
- var generateHTMLTemplate = async ({
257
- pageURL,
258
- head: head2,
259
- serverData = null,
260
- addPageScriptTag = true,
261
- name,
262
- requiredClientModules = {},
263
- environment
264
- }) => {
265
- let StartTemplate = `<meta name="viewport" content="width=device-width, initial-scale=1.0">`;
266
- if (environment === "production") {
267
- StartTemplate += `<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">`;
268
- }
269
- StartTemplate += '<meta charset="UTF-8">';
270
- for (const [globalName] of Object.entries(requiredClientModules)) {
271
- StartTemplate += `<script data-module="true" src="/shipped/${globalName}.js" defer="true"></script>`;
272
- }
273
- if (addPageScriptTag === true) {
274
- const sanitized = pageURL === "" ? "/" : `/${pageURL}`;
275
- StartTemplate += `<script data-page="true" type="module" data-pathname="${sanitized}" src="${sanitized.endsWith("/") ? sanitized : sanitized + "/"}${name}_data.js" defer="true"></script>`;
276
- }
277
- StartTemplate += `<script type="module" src="/client.js" defer="true"></script>`;
278
- let builtHead;
279
- if (head2.constructor.name === "AsyncFunction") {
280
- builtHead = await head2();
281
- } else {
282
- builtHead = head2();
283
- }
284
- let HTMLTemplate = renderRecursively(builtHead);
285
- if (serverData) {
286
- HTMLTemplate += serverData;
287
- }
288
- return {
289
- internals: StartTemplate,
290
- builtMetadata: HTMLTemplate
291
- };
292
- };
293
-
294
- // src/server/loadHook.ts
295
- var resetLoadHooks = () => globalThis.__SERVER_CURRENT_LOADHOOKS__ = [];
296
- var getLoadHooks = () => globalThis.__SERVER_CURRENT_LOADHOOKS__;
297
-
298
- // src/server/state.ts
299
- if (!globalThis.__SERVER_CURRENT_STATE_ID__) {
300
- globalThis.__SERVER_CURRENT_STATE_ID__ = 1;
301
- }
302
- var initializeState = () => globalThis.__SERVER_CURRENT_STATE__ = [];
303
- var getState = () => {
304
- return globalThis.__SERVER_CURRENT_STATE__;
305
- };
306
- var initializeObjectAttributes = () => globalThis.__SERVER_CURRENT_OBJECT_ATTRIBUTES__ = [];
307
- var getObjectAttributes = () => {
308
- return globalThis.__SERVER_CURRENT_OBJECT_ATTRIBUTES__;
309
- };
310
-
311
- // src/server/layout.ts
312
- var resetLayouts = () => globalThis.__SERVER_CURRENT_LAYOUTS__ = /* @__PURE__ */ new Map();
313
- if (!globalThis.__SERVER_CURRENT_LAYOUT_ID__) globalThis.__SERVER_CURRENT_LAYOUT_ID__ = 1;
314
-
315
- // src/page_compiler.ts
316
- var __filename = fileURLToPath(import.meta.url);
317
- var __dirname = path.dirname(__filename);
318
- setArcTsConfig(__dirname);
319
- registerLoader();
320
- var packageDir = process.env.PACKAGE_PATH;
321
- if (packageDir === void 0) {
322
- packageDir = path.resolve(__dirname, "..");
323
- }
324
- var clientPath = path.resolve(packageDir, "./dist/client/client.mjs");
325
- var watcherPath = path.resolve(packageDir, "./dist/client/watcher.mjs");
326
- var shippedModules = /* @__PURE__ */ new Map();
327
- var modulesToShip = [];
328
- var yellow = (text) => {
329
- return `\x1B[38;2;238;184;68m${text}`;
330
- };
331
- var black = (text) => {
332
- return `\x1B[38;2;0;0;0m${text}`;
333
- };
334
- var bgYellow = (text) => {
335
- return `\x1B[48;2;238;184;68m${text}`;
336
- };
337
- var bold = (text) => {
338
- return `\x1B[1m${text}`;
339
- };
340
- var underline = (text) => {
341
- return `\x1B[4m${text}`;
342
- };
343
- var white = (text) => {
344
- return `\x1B[38;2;255;247;229m${text}`;
345
- };
346
- var log2 = (...text) => {
347
- if (options.quiet) return;
348
- return console.log(text.map((text2) => `${text2}\x1B[0m`).join(""));
349
- };
350
- var options = JSON.parse(process.env.OPTIONS);
351
- var DIST_DIR = process.env.DIST_DIR;
352
- var PAGE_MAP = /* @__PURE__ */ new Map();
353
- var LAYOUT_MAP = /* @__PURE__ */ new Map();
354
- var getAllSubdirectories = (dir, baseDir = dir) => {
355
- let directories = [];
356
- const items = fs.readdirSync(dir, { withFileTypes: true });
357
- for (const item of items) {
358
- if (item.isDirectory()) {
359
- const fullPath = path.join(dir, item.name);
360
- const relativePath = path.relative(baseDir, fullPath);
361
- directories.push(relativePath);
362
- directories = directories.concat(getAllSubdirectories(fullPath, baseDir));
363
- }
364
- }
365
- return directories;
366
- };
367
- var buildClient = async (DIST_DIR2) => {
368
- let clientString = "window.__name = (func) => func; ";
369
- clientString += fs.readFileSync(clientPath, "utf-8");
370
- if (options.hotReload !== void 0) {
371
- clientString += `const watchServerPort = ${options.hotReload.port}`;
372
- clientString += fs.readFileSync(watcherPath, "utf-8");
373
- }
374
- const transformedClient = await esbuild.transform(clientString, {
375
- minify: options.environment === "production",
376
- drop: options.environment === "production" ? ["console", "debugger"] : void 0,
377
- keepNames: false,
378
- format: "iife",
379
- platform: "node",
380
- loader: "ts"
381
- });
382
- fs.writeFileSync(
383
- path.join(DIST_DIR2, "/client.js"),
384
- transformedClient.code
385
- );
386
- };
387
- var elementKey = 0;
388
- var processOptionAsObjectAttribute = (element, optionName, optionValue, objectAttributes) => {
389
- const lcOptionName = optionName.toLowerCase();
390
- const options2 = element.options;
391
- let key = options2.key;
392
- if (key == void 0) {
393
- key = elementKey += 1;
394
- options2.key = key;
395
- }
396
- if (!optionValue.type) {
397
- throw `ObjectAttributeType is missing from object attribute. ${element.tag}: ${optionName}/${optionValue}`;
398
- }
399
- let optionFinal = lcOptionName;
400
- switch (optionValue.type) {
401
- case 1 /* STATE */:
402
- const SOA = optionValue;
403
- if (typeof SOA.value === "function") {
404
- delete options2[optionName];
405
- break;
406
- }
407
- if (lcOptionName === "innertext" || lcOptionName === "innerhtml") {
408
- element.children = [SOA.value];
409
- delete options2[optionName];
410
- } else {
411
- delete options2[optionName];
412
- options2[lcOptionName] = SOA.value;
413
- }
414
- break;
415
- case 2 /* OBSERVER */:
416
- const OOA = optionValue;
417
- const firstValue = OOA.update(...OOA.initialValues);
418
- if (lcOptionName === "innertext" || lcOptionName === "innerhtml") {
419
- element.children = [firstValue];
420
- delete options2[optionName];
421
- } else {
422
- delete options2[optionName];
423
- options2[lcOptionName] = firstValue;
424
- }
425
- optionFinal = optionName;
426
- break;
427
- case 4 /* REFERENCE */:
428
- options2["ref"] = optionValue.value;
429
- break;
430
- }
431
- objectAttributes.push({ ...optionValue, key, attribute: optionFinal });
432
- };
433
- function buildTrace(stack, indent = 4) {
434
- try {
435
- if (!stack || stack.length === 0) return "[]";
436
- let traceObj = stack[stack.length - 1] && typeof stack[stack.length - 1] === "object" ? JSON.parse(JSON.stringify(stack[stack.length - 1])) : { value: stack[stack.length - 1] };
437
- traceObj._error = "This is the element where the error occurred";
438
- for (let i = stack.length - 2; i >= 0; i--) {
439
- const parent = stack[i];
440
- const child = stack[i + 1];
441
- if (!parent || typeof parent !== "object") {
442
- traceObj = { value: parent, _errorChild: traceObj };
443
- continue;
444
- }
445
- let parentClone;
446
- try {
447
- parentClone = JSON.parse(JSON.stringify(parent));
448
- } catch {
449
- parentClone = { value: parent };
450
- }
451
- let index = -1;
452
- if (Array.isArray(parentClone.children)) {
453
- index = parentClone.children.findIndex((c) => c === child);
454
- }
455
- if (index !== -1 && parentClone.children) {
456
- parentClone.children = parentClone.children.slice(0, index + 1);
457
- parentClone.children[index] = traceObj;
458
- } else {
459
- parentClone._errorChild = traceObj;
460
- }
461
- traceObj = parentClone;
462
- }
463
- return JSON.stringify(traceObj, null, indent).replace(/^/gm, " ".repeat(indent));
464
- } catch {
465
- return "Could not build stack-trace.";
466
- }
467
- }
468
- var processPageElements = (element, objectAttributes, recursionLevel, stack = []) => {
469
- stack.push(element);
470
- try {
471
- if (typeof element === "boolean" || typeof element === "number" || Array.isArray(element)) {
472
- stack.pop();
473
- return element;
474
- }
475
- if (typeof element === "string") {
476
- stack.pop();
477
- return element;
478
- }
479
- const processElementOptionsAsChildAndReturn = () => {
480
- try {
481
- const children = element.children;
482
- element.children = [
483
- element.options,
484
- ...children
485
- ];
486
- element.options = {};
487
- for (let i = 0; i < children.length + 1; i++) {
488
- const child = element.children[i];
489
- const processedChild = processPageElements(child, objectAttributes, recursionLevel + 1, stack);
490
- element.children[i] = processedChild;
491
- }
492
- return {
493
- ...element,
494
- options: {}
495
- };
496
- } catch (e) {
497
- const errorString = `Could not process element options as a child. ${e}.`;
498
- throw new Error(errorString);
499
- }
500
- };
501
- if (typeof element.options !== "object") {
502
- const result = processElementOptionsAsChildAndReturn();
503
- stack.pop();
504
- return result;
505
- }
506
- const {
507
- tag: elementTag,
508
- options: elementOptions,
509
- children: elementChildren
510
- } = element.options;
511
- if (elementTag && elementOptions && elementChildren) {
512
- const result = processElementOptionsAsChildAndReturn();
513
- stack.pop();
514
- return result;
515
- }
516
- const options2 = element.options;
517
- for (const [optionName, optionValue] of Object.entries(options2)) {
518
- const lcOptionName = optionName.toLowerCase();
519
- if (typeof optionValue !== "object") {
520
- if (lcOptionName === "innertext") {
521
- delete options2[optionName];
522
- if (element.children === null) {
523
- throw `Cannot use innerText or innerHTML on childrenless elements.`;
524
- }
525
- element.children = [optionValue, ...element.children];
526
- continue;
527
- } else if (lcOptionName === "innerhtml") {
528
- if (element.children === null) {
529
- throw `Cannot use innerText or innerHTML on childrenless elements.`;
530
- }
531
- delete options2[optionName];
532
- element.children = [optionValue];
533
- continue;
534
- }
535
- continue;
536
- }
537
- ;
538
- processOptionAsObjectAttribute(element, optionName, optionValue, objectAttributes);
539
- }
540
- if (element.children) {
541
- for (let i = 0; i < element.children.length; i++) {
542
- const child = element.children[i];
543
- const processedChild = processPageElements(child, objectAttributes, recursionLevel + 1, stack);
544
- element.children[i] = processedChild;
545
- }
546
- }
547
- stack.pop();
548
- return element;
549
- } catch (e) {
550
- const trace = buildTrace(stack);
551
- if (recursionLevel === 0) {
552
- throw new Error(`${e}
553
-
554
- Trace:
555
- ${trace}`);
556
- } else {
557
- throw e;
558
- }
559
- }
560
- };
561
- var pageToHTML = async (pageLocation, pageElements, metadata, DIST_DIR2, pageName, doWrite = true, requiredClientModules = {}, layout, pathname = "") => {
562
- if (typeof pageElements === "string" || typeof pageElements === "boolean" || typeof pageElements === "number" || Array.isArray(pageElements)) {
563
- throw new Error(`The root element of a page / layout must be a built element, not just a Child. Received: ${typeof pageElements}.`);
564
- }
565
- const objectAttributes = [];
566
- const stack = [];
567
- const processedPageElements = processPageElements(pageElements, objectAttributes, 0, stack);
568
- const renderedPage = await serverSideRenderPage(
569
- processedPageElements,
570
- pageLocation
571
- );
572
- const { internals, builtMetadata } = await generateHTMLTemplate({
573
- pageURL: pathname,
574
- head: metadata,
575
- addPageScriptTag: doWrite,
576
- name: pageName,
577
- requiredClientModules,
578
- environment: options.environment
579
- });
580
- let extraBodyHTML = "";
581
- if (doWrite === false) {
582
- const state = getState();
583
- const pageLoadHooks = getLoadHooks();
584
- const userObjectAttributes = getObjectAttributes();
585
- const {
586
- result
587
- } = await generateClientPageData(
588
- pathname,
589
- state || {},
590
- [...objectAttributes, ...userObjectAttributes],
591
- pageLoadHooks || [],
592
- DIST_DIR2,
593
- "page",
594
- "pd",
595
- false
596
- );
597
- const sanitized = pathname === "" ? "/" : `/${pathname}`;
598
- extraBodyHTML = `<script data-hook="true" data-pathname="${sanitized}" type="text/plain">${result}</script>`;
599
- extraBodyHTML += `<script>
600
- const text = document.querySelector('[data-hook="true"][data-pathname="${sanitized}"][type="text/plain"').textContent;
601
- const blob = new Blob([text], { type: 'text/javascript' });
602
- const url = URL.createObjectURL(blob);
603
-
604
- const script = document.createElement("script");
605
- script.src = url;
606
- script.type = "module";
607
- script.setAttribute("data-page", "true");
608
- script.setAttribute("data-pathname", "${sanitized}");
609
-
610
- document.head.appendChild(script);
611
-
612
- document.currentScript.remove();
613
- </script>`;
614
- extraBodyHTML = extraBodyHTML.replace(/\s+/g, " ").replace(/\s*([{}();,:])\s*/g, "$1").trim();
615
- }
616
- const headHTML = `<!DOCTYPE html>${layout.metadata.startHTML}${layout.scriptTag}${internals}${builtMetadata}${layout.metadata.endHTML}`;
617
- const bodyHTML = `${layout.pageContent.startHTML}${renderedPage.bodyHTML}${extraBodyHTML}${layout.pageContent.endHTML}`;
618
- const resultHTML = `${headHTML}${bodyHTML}`;
619
- const htmlLocation = path.join(pageLocation, (pageName === "page" ? "index" : pageName) + ".html");
620
- if (doWrite) {
621
- const dirname2 = path.dirname(htmlLocation);
622
- if (fs.existsSync(dirname2) === false) {
623
- fs.mkdirSync(dirname2, { recursive: true });
624
- }
625
- fs.writeFileSync(
626
- htmlLocation,
627
- resultHTML,
628
- {
629
- encoding: "utf-8",
630
- flag: "w"
631
- }
632
- );
633
- return objectAttributes;
634
- }
635
- return resultHTML;
636
- };
637
- var generateClientPageData = async (pageLocation, state, objectAttributes, pageLoadHooks, DIST_DIR2, pageName, globalVariableName = "pd", write = true) => {
638
- let clientPageJSText = "";
639
- {
640
- clientPageJSText += `${globalThis.__SERVER_PAGE_DATA_BANNER__}`;
641
- }
642
- {
643
- clientPageJSText += `export const data = {`;
644
- if (state) {
645
- clientPageJSText += `state:[`;
646
- for (const subject of state) {
647
- if (typeof subject.value === "string") {
648
- const stringified = JSON.stringify(subject.value);
649
- clientPageJSText += `{id:${subject.id},value:${stringified}},`;
650
- } else if (typeof subject.value === "function") {
651
- clientPageJSText += `{id:${subject.id},value:${subject.value.toString()}},`;
652
- } else {
653
- clientPageJSText += `{id:${subject.id},value:${JSON.stringify(subject.value)}},`;
654
- }
655
- }
656
- clientPageJSText += `],`;
657
- }
658
- const stateObjectAttributes = objectAttributes.filter((oa) => oa.type === 1 /* STATE */);
659
- if (stateObjectAttributes.length > 0) {
660
- const processed = [...stateObjectAttributes].map((soa) => {
661
- delete soa.type;
662
- return soa;
663
- });
664
- clientPageJSText += `soa:${JSON.stringify(processed)},`;
665
- }
666
- const observerObjectAttributes = objectAttributes.filter((oa) => oa.type === 2 /* OBSERVER */);
667
- if (observerObjectAttributes.length > 0) {
668
- let observerObjectAttributeString = "ooa:[";
669
- for (const observerObjectAttribute of observerObjectAttributes) {
670
- const ooa = observerObjectAttribute;
671
- observerObjectAttributeString += `{key:${ooa.key},attribute:"${ooa.attribute}",update:${ooa.update.toString()},`;
672
- observerObjectAttributeString += `refs:[`;
673
- for (const ref of ooa.refs) {
674
- observerObjectAttributeString += `{id:${ref.id}},`;
675
- }
676
- observerObjectAttributeString += "]},";
677
- }
678
- observerObjectAttributeString += "],";
679
- clientPageJSText += observerObjectAttributeString;
680
- }
681
- if (pageLoadHooks.length > 0) {
682
- clientPageJSText += "lh:[";
683
- for (const loadHook2 of pageLoadHooks) {
684
- clientPageJSText += `{fn:${loadHook2.fn}},`;
685
- }
686
- clientPageJSText += "],";
687
- }
688
- clientPageJSText += `};`;
689
- }
690
- const pageDataPath = path.join(DIST_DIR2, pageLocation, `${pageName}_data.js`);
691
- let sendHardReloadInstruction = false;
692
- const transformedResult = await esbuild.transform(clientPageJSText, { minify: options.environment === "production" }).catch((error) => {
693
- console.error("Failed to transform client page js!", error);
694
- });
695
- if (!transformedResult) return { sendHardReloadInstruction };
696
- if (fs.existsSync(pageDataPath)) {
697
- const content = fs.readFileSync(pageDataPath).toString();
698
- if (content !== transformedResult.code) {
699
- sendHardReloadInstruction = true;
700
- }
701
- }
702
- if (write) fs.writeFileSync(pageDataPath, transformedResult.code, "utf-8");
703
- return { sendHardReloadInstruction, result: transformedResult.code };
704
- };
705
- var generateLayout = async (DIST_DIR2, filePath, directory, childIndicator, generateDynamic = false) => {
706
- initializeState();
707
- initializeObjectAttributes();
708
- resetLoadHooks();
709
- globalThis.__SERVER_PAGE_DATA_BANNER__ = "";
710
- let layoutElements;
711
- let metadataElements;
712
- let modules = [];
713
- let isDynamicLayout = false;
714
- try {
715
- const {
716
- layout,
717
- metadata,
718
- isDynamic,
719
- shippedModules: shippedModules2
720
- } = await import("file://" + filePath);
721
- if (shippedModules2 !== void 0) {
722
- modules = shippedModules2;
723
- }
724
- layoutElements = layout;
725
- metadataElements = metadata;
726
- if (isDynamic === true) {
727
- isDynamicLayout = isDynamic;
728
- }
729
- } catch (e) {
730
- throw new Error(`Error in Page: ${directory === "" ? "/" : directory}layout.ts - ${e}`);
731
- }
732
- LAYOUT_MAP.set(directory === "" ? "/" : `/${directory}`, {
733
- isDynamic: isDynamicLayout,
734
- filePath
735
- });
736
- if (isDynamicLayout === true && generateDynamic === false) return false;
737
- {
738
- if (!layoutElements) {
739
- throw new Error(`WARNING: ${filePath} should export a const layout, which is of type Layout: (child: Child) => AnyBuiltElement.`);
740
- }
741
- if (typeof layoutElements === "function") {
742
- if (layoutElements.constructor.name === "AsyncFunction") {
743
- layoutElements = await layoutElements(childIndicator);
744
- } else {
745
- layoutElements = layoutElements(childIndicator);
746
- }
747
- }
748
- }
749
- {
750
- if (!metadataElements) {
751
- throw new Error(`WARNING: ${filePath} should export a const metadata, which is of type LayoutMetadata: (child: Child) => AnyBuiltElement.`);
752
- }
753
- if (typeof metadataElements === "function") {
754
- if (metadataElements.constructor.name === "AsyncFunction") {
755
- metadataElements = await metadataElements(childIndicator);
756
- } else {
757
- metadataElements = metadataElements(childIndicator);
758
- }
759
- }
760
- }
761
- const state = getState();
762
- const pageLoadHooks = getLoadHooks();
763
- const objectAttributes = getObjectAttributes();
764
- if (typeof layoutElements === "string" || typeof layoutElements === "boolean" || typeof layoutElements === "number" || Array.isArray(layoutElements)) {
765
- throw new Error(`The root element of a page / layout must be a built element, not just a Child. Received: ${typeof layoutElements}.`);
766
- }
767
- const foundObjectAttributes = [];
768
- const stack = [];
769
- const processedPageElements = processPageElements(layoutElements, foundObjectAttributes, 0, stack);
770
- const renderedPage = await serverSideRenderPage(
771
- processedPageElements,
772
- directory
773
- );
774
- const metadataHTML = metadataElements ? renderRecursively(metadataElements) : "";
775
- await generateClientPageData(
776
- directory,
777
- state || {},
778
- [...objectAttributes, ...foundObjectAttributes],
779
- pageLoadHooks || [],
780
- DIST_DIR2,
781
- "layout",
782
- "ld"
783
- );
784
- return { pageContentHTML: renderedPage.bodyHTML, metadataHTML };
785
- };
786
- var builtLayouts = /* @__PURE__ */ new Map();
787
- var buildLayouts = async () => {
788
- const pagesDirectory = path.resolve(options.pagesDirectory);
789
- const subdirectories = [...getAllSubdirectories(pagesDirectory), ""];
790
- let shouldClientHardReload = false;
791
- for (const directory of subdirectories) {
792
- const abs = path.resolve(path.join(pagesDirectory, directory));
793
- const files = fs.readdirSync(abs, { withFileTypes: true }).filter((f) => f.name.endsWith(".ts"));
794
- for (const file of files) {
795
- const filePath = path.join(file.parentPath, file.name);
796
- const name = file.name.slice(0, file.name.length - 3);
797
- const isLayout = name === "layout";
798
- if (isLayout == false) {
799
- continue;
800
- }
801
- try {
802
- const builtLayout = await buildLayout(filePath, directory);
803
- if (!builtLayout) return { shouldClientHardReload: false };
804
- builtLayouts.set(filePath, builtLayout);
805
- } catch (e) {
806
- console.error(e);
807
- continue;
808
- }
809
- }
810
- }
811
- return { shouldClientHardReload };
812
- };
813
- var buildLayout = async (filePath, directory, generateDynamic = false) => {
814
- const id = globalThis.__SERVER_CURRENT_STATE_ID__ += 1;
815
- const childIndicator = `<template layout-id="${id}"></template>`;
816
- const result = await generateLayout(
817
- DIST_DIR,
818
- filePath,
819
- directory,
820
- childIndicator,
821
- generateDynamic
822
- );
823
- if (result === false) return false;
824
- const { pageContentHTML, metadataHTML } = result;
825
- const splitAround = (str, sub) => {
826
- const i = str.indexOf(sub);
827
- if (i === -1) throw new Error("substring does not exist in parent string");
828
- return {
829
- startHTML: str.substring(0, i),
830
- endHTML: str.substring(i + sub.length)
831
- };
832
- };
833
- const splitAt = (str, sub) => {
834
- const i = str.indexOf(sub) + sub.length;
835
- if (i === -1) throw new Error("substring does not exist in parent string");
836
- return {
837
- startHTML: str.substring(0, i),
838
- endHTML: str.substring(i)
839
- };
840
- };
841
- const pathname = directory === "" ? "/" : directory;
842
- return {
843
- pageContent: splitAt(pageContentHTML, childIndicator),
844
- metadata: splitAround(metadataHTML, childIndicator),
845
- scriptTag: `<script data-layout="true" type="module" src="${pathname}layout_data.js" data-pathname="${pathname}" defer="true"></script>`
846
- };
847
- };
848
- var fetchPageLayoutHTML = async (dirname2) => {
849
- const relative2 = path.relative(options.pagesDirectory, dirname2);
850
- let split = relative2.split(path.sep).filter(Boolean);
851
- split.push("/");
852
- split.reverse();
853
- let layouts = [];
854
- for (const dir of split) {
855
- if (LAYOUT_MAP.has(dir)) {
856
- const filePath = path.join(path.resolve(options.pagesDirectory), dir, "layout.ts");
857
- const layout = LAYOUT_MAP.get(dir);
858
- if (layout.isDynamic) {
859
- const builtLayout = await buildLayout(layout.filePath, dir, true);
860
- if (!builtLayout) continue;
861
- layouts.push(builtLayout);
862
- } else {
863
- layouts.push(builtLayouts.get(filePath));
864
- }
865
- }
866
- }
867
- const pageContent = {
868
- startHTML: "",
869
- endHTML: ""
870
- };
871
- const metadata = {
872
- startHTML: "",
873
- endHTML: ""
874
- };
875
- let scriptTags = "";
876
- for (const layout of layouts) {
877
- pageContent.startHTML += layout.pageContent.startHTML;
878
- metadata.startHTML += layout.metadata.startHTML;
879
- scriptTags += layout.scriptTag;
880
- pageContent.endHTML += layout.pageContent.endHTML;
881
- metadata.endHTML += layout.metadata.endHTML;
882
- }
883
- return { pageContent, metadata, scriptTag: scriptTags };
884
- };
885
- var buildPages = async (DIST_DIR2) => {
886
- resetLayouts();
887
- const pagesDirectory = path.resolve(options.pagesDirectory);
888
- const subdirectories = [...getAllSubdirectories(pagesDirectory), ""];
889
- let shouldClientHardReload = false;
890
- for (const directory of subdirectories) {
891
- const abs = path.resolve(path.join(pagesDirectory, directory));
892
- const files = fs.readdirSync(abs, { withFileTypes: true }).filter((f) => f.name.endsWith(".ts"));
893
- for (const file of files) {
894
- const filePath = path.join(file.parentPath, file.name);
895
- const name = file.name.slice(0, file.name.length - 3);
896
- const isPage = name === "page";
897
- if (isPage == false) {
898
- continue;
899
- }
900
- try {
901
- const hardReloadForPage = await buildPage(DIST_DIR2, directory, filePath, name);
902
- if (hardReloadForPage) {
903
- shouldClientHardReload = true;
904
- }
905
- } catch (e) {
906
- console.error(e);
907
- continue;
908
- }
909
- }
910
- }
911
- return {
912
- shouldClientHardReload
913
- };
914
- };
915
- var buildPage = async (DIST_DIR2, directory, filePath, name) => {
916
- initializeState();
917
- initializeObjectAttributes();
918
- resetLoadHooks();
919
- globalThis.__SERVER_PAGE_DATA_BANNER__ = "";
920
- let pageElements;
921
- let metadata;
922
- let modules = {};
923
- let pageIgnoresLayout = false;
924
- let isDynamicPage = false;
925
- try {
926
- const {
927
- page,
928
- metadata: pageMetadata,
929
- isDynamic,
930
- shippedModules: shippedModules2,
931
- ignoreLayout
932
- } = await import("file://" + filePath);
933
- if (shippedModules2 !== void 0) {
934
- modules = shippedModules2;
935
- }
936
- if (ignoreLayout) {
937
- pageIgnoresLayout = true;
938
- }
939
- pageElements = page;
940
- metadata = pageMetadata;
941
- if (isDynamic === true) {
942
- isDynamicPage = isDynamic;
943
- }
944
- } catch (e) {
945
- throw new Error(`Error in Page: ${directory}/${name}.ts - ${e}`);
946
- }
947
- PAGE_MAP.set(directory === "" ? "/" : `/${directory}`, {
948
- isDynamic: isDynamicPage,
949
- filePath
950
- });
951
- if (isDynamicPage) return false;
952
- if (modules !== void 0) {
953
- for (const [globalName, path2] of Object.entries(modules)) {
954
- modulesToShip.push({ globalName, path: path2 });
955
- }
956
- }
957
- if (!metadata || metadata && typeof metadata !== "function") {
958
- console.warn(`WARNING: ${filePath} does not export a metadata function.`);
959
- }
960
- if (!pageElements) {
961
- console.warn(`WARNING: ${filePath} should export a const page, which is of type () => BuiltElement<"body">.`);
962
- }
963
- const pageProps = {
964
- pageName: directory
965
- };
966
- if (typeof pageElements === "function") {
967
- if (pageElements.constructor.name === "AsyncFunction") {
968
- pageElements = await pageElements(pageProps);
969
- } else {
970
- pageElements = pageElements(pageProps);
971
- }
972
- }
973
- const state = getState();
974
- const pageLoadHooks = getLoadHooks();
975
- const objectAttributes = getObjectAttributes();
976
- const layout = await fetchPageLayoutHTML(path.dirname(filePath));
977
- const foundObjectAttributes = await pageToHTML(
978
- path.join(DIST_DIR2, directory),
979
- pageElements || body(),
980
- metadata ?? (() => head()),
981
- DIST_DIR2,
982
- name,
983
- true,
984
- modules,
985
- layout,
986
- directory
987
- );
988
- const {
989
- sendHardReloadInstruction
990
- } = await generateClientPageData(
991
- directory,
992
- state || {},
993
- [...objectAttributes, ...foundObjectAttributes],
994
- pageLoadHooks || [],
995
- DIST_DIR2,
996
- name
997
- );
998
- return sendHardReloadInstruction === true;
999
- };
1000
- var buildDynamicPage = async (DIST_DIR2, directory, pageInfo, req, res) => {
1001
- directory = directory === "/" ? "" : directory;
1002
- const filePath = pageInfo.filePath;
1003
- initializeState();
1004
- initializeObjectAttributes();
1005
- resetLoadHooks();
1006
- globalThis.__SERVER_PAGE_DATA_BANNER__ = "";
1007
- let pageElements = async (props) => body();
1008
- let metadata = async (props) => html();
1009
- let modules = {};
1010
- let pageIgnoresLayout = false;
1011
- let isDynamicPage = false;
1012
- try {
1013
- const {
1014
- page,
1015
- metadata: pageMetadata,
1016
- isDynamic,
1017
- shippedModules: shippedModules2,
1018
- ignoreLayout,
1019
- requestHook
1020
- } = await import("file://" + filePath);
1021
- if (requestHook) {
1022
- const hook = requestHook;
1023
- const doContinue = await hook(req, res);
1024
- if (!doContinue) {
1025
- return false;
1026
- }
1027
- }
1028
- if (shippedModules2 !== void 0) {
1029
- modules = shippedModules2;
1030
- }
1031
- if (ignoreLayout) {
1032
- pageIgnoresLayout = true;
1033
- }
1034
- pageElements = page;
1035
- metadata = pageMetadata;
1036
- if (isDynamic === true) {
1037
- isDynamicPage = isDynamic;
1038
- }
1039
- } catch (e) {
1040
- throw new Error(`Error in Page: ${directory}/page.ts - ${e}`);
1041
- }
1042
- if (modules !== void 0) {
1043
- for (const [globalName, path2] of Object.entries(modules)) {
1044
- modulesToShip.push({ globalName, path: path2 });
1045
- }
1046
- }
1047
- if (!metadata || metadata && typeof metadata !== "function") {
1048
- console.warn(`WARNING: ${filePath} does not export a metadata function.`);
1049
- }
1050
- if (!pageElements) {
1051
- console.warn(`WARNING: ${filePath} should export a const page, which is of type () => BuiltElement<"body">.`);
1052
- }
1053
- const pageProps = {
1054
- pageName: directory
1055
- };
1056
- if (typeof pageElements === "function") {
1057
- if (pageElements.constructor.name === "AsyncFunction") {
1058
- pageElements = await pageElements(pageProps);
1059
- } else {
1060
- pageElements = pageElements(pageProps);
1061
- }
1062
- }
1063
- const layout = await fetchPageLayoutHTML(path.dirname(filePath));
1064
- const resultHTML = await pageToHTML(
1065
- path.join(DIST_DIR2, directory),
1066
- pageElements,
1067
- metadata,
1068
- DIST_DIR2,
1069
- "page",
1070
- false,
1071
- modules,
1072
- layout,
1073
- directory
1074
- );
1075
- await shipModules();
1076
- return { resultHTML };
1077
- };
1078
- var shipModules = async () => {
1079
- for (const plugin of modulesToShip) {
1080
- {
1081
- if (shippedModules.has(plugin.globalName)) continue;
1082
- shippedModules.set(plugin.globalName, true);
1083
- }
1084
- esbuild.build({
1085
- entryPoints: [plugin.path],
1086
- bundle: true,
1087
- outfile: path.join(DIST_DIR, "shipped", plugin.globalName + ".js"),
1088
- format: "iife",
1089
- platform: "browser",
1090
- globalName: plugin.globalName,
1091
- minify: true,
1092
- treeShaking: true
1093
- });
1094
- }
1095
- modulesToShip = [];
1096
- };
1097
- var build = async () => {
1098
- if (options.quiet === true) {
1099
- console.log = function() {
1100
- };
1101
- console.error = function() {
1102
- };
1103
- console.warn = function() {
1104
- };
1105
- }
1106
- try {
1107
- {
1108
- log2(bold(yellow(" -- Elegance.JS -- ")));
1109
- if (options.environment === "production") {
1110
- log2(
1111
- " - ",
1112
- bgYellow(bold(black(" NOTE "))),
1113
- " : ",
1114
- white("In production mode, no "),
1115
- underline("console.log() "),
1116
- white("statements will be shown on the client, and all code will be minified.")
1117
- );
1118
- log2("");
1119
- }
1120
- }
1121
- if (options.preCompile) {
1122
- options.preCompile();
1123
- }
1124
- const start = performance.now();
1125
- let shouldClientHardReload;
1126
- {
1127
- const { shouldClientHardReload: doReload } = await buildLayouts();
1128
- if (doReload) shouldClientHardReload = true;
1129
- }
1130
- {
1131
- const { shouldClientHardReload: doReload } = await buildPages(path.resolve(DIST_DIR));
1132
- if (doReload) shouldClientHardReload = true;
1133
- }
1134
- await shipModules();
1135
- const pagesBuilt = performance.now();
1136
- await buildClient(DIST_DIR);
1137
- const end = performance.now();
1138
- if (options.publicDirectory) {
1139
- log2("Recursively copying public directory.. this may take a while.");
1140
- const src = path.relative(process.cwd(), options.publicDirectory.path);
1141
- if (fs.existsSync(src) === false) {
1142
- console.warn("WARNING: Public directory not found, an attempt will be made create it..");
1143
- fs.mkdirSync(src, { recursive: true });
1144
- }
1145
- await fs.promises.cp(src, path.join(DIST_DIR), { recursive: true });
1146
- }
1147
- {
1148
- log2(`Took ${Math.round(pagesBuilt - start)}ms to Build Pages.`);
1149
- log2(`Took ${Math.round(end - pagesBuilt)}ms to Build Client.`);
1150
- }
1151
- if (options.server != void 0 && options.server.runServer == true) {
1152
- startServer({
1153
- root: options.server.root ?? DIST_DIR,
1154
- environment: options.environment,
1155
- port: options.server.port ?? 3e3,
1156
- host: options.server.host ?? "localhost",
1157
- DIST_DIR,
1158
- pagesDirectory: options.pagesDirectory
1159
- });
1160
- }
1161
- process.send?.({ event: "message", data: "compile-finish" });
1162
- if (shouldClientHardReload) {
1163
- process.send({ event: "message", data: "hard-reload" });
1164
- } else {
1165
- process.send({ event: "message", data: "soft-reload" });
1166
- }
1167
- } catch (e) {
1168
- console.error("Build Failed! Received Error:");
1169
- console.error(e);
1170
- return false;
1171
- }
1172
- return true;
1173
- };
1174
- (async () => {
1175
- await build();
1176
- })();
1177
-
1178
- // src/server/server.ts
1179
- var gzipAsync = promisify(gzip);
1180
- var deflateAsync = promisify(deflate);
1181
- var MIME_TYPES = {
1
+ import {
2
+ createServer as createHttpServer
3
+ } from "http";
4
+ import {
5
+ promises as fs
6
+ } from "fs";
7
+ import {
8
+ join,
9
+ normalize,
10
+ extname,
11
+ dirname
12
+ } from "path";
13
+ import {
14
+ pathToFileURL
15
+ } from "url";
16
+ import {
17
+ log
18
+ } from "../log";
19
+ import {
20
+ gzip,
21
+ deflate
22
+ } from "zlib";
23
+ import {
24
+ promisify
25
+ } from "util";
26
+ import {
27
+ PAGE_MAP
28
+ } from "../build";
29
+ const gzipAsync = promisify(gzip);
30
+ const deflateAsync = promisify(deflate);
31
+ const MIME_TYPES = {
1182
32
  ".html": "text/html; charset=utf-8",
1183
33
  ".css": "text/css; charset=utf-8",
1184
34
  ".js": "application/javascript; charset=utf-8",
@@ -1197,7 +47,7 @@ function startServer({
1197
47
  port = 3e3,
1198
48
  host = "localhost",
1199
49
  environment = "production",
1200
- DIST_DIR: DIST_DIR2
50
+ DIST_DIR
1201
51
  }) {
1202
52
  if (!root) throw new Error("Root directory must be specified.");
1203
53
  if (!pagesDirectory) throw new Error("Pages directory must be specified.");
@@ -1206,7 +56,9 @@ function startServer({
1206
56
  const requestHandler = async (req, res) => {
1207
57
  try {
1208
58
  if (!req.url) {
1209
- await sendResponse(req, res, 400, { "Content-Type": "text/plain; charset=utf-8" }, "Bad Request");
59
+ await sendResponse(req, res, 400, {
60
+ "Content-Type": "text/plain; charset=utf-8"
61
+ }, "Bad Request");
1210
62
  return;
1211
63
  }
1212
64
  res.setHeader("Access-Control-Allow-Origin", "*");
@@ -1224,16 +76,18 @@ function startServer({
1224
76
  if (url.pathname.startsWith("/api/")) {
1225
77
  await handleApiRequest(pagesDirectory, url.pathname, req, res);
1226
78
  } else if (PAGE_MAP.has(url.pathname)) {
1227
- await handlePageRequest(root, pagesDirectory, url.pathname, req, res, DIST_DIR2, PAGE_MAP.get(url.pathname));
79
+ await handlePageRequest(root, pagesDirectory, url.pathname, req, res, DIST_DIR, PAGE_MAP.get(url.pathname));
1228
80
  } else {
1229
- await handleStaticRequest(root, pagesDirectory, url.pathname, req, res, DIST_DIR2);
81
+ await handleStaticRequest(root, pagesDirectory, url.pathname, req, res, DIST_DIR);
1230
82
  }
1231
83
  if (environment === "development") {
1232
84
  log.info(req.method, "::", req.url, "-", res.statusCode);
1233
85
  }
1234
86
  } catch (err) {
1235
87
  log.error(err);
1236
- await sendResponse(req, res, 500, { "Content-Type": "text/plain; charset=utf-8" }, "Internal Server Error");
88
+ await sendResponse(req, res, 500, {
89
+ "Content-Type": "text/plain; charset=utf-8"
90
+ }, "Internal Server Error");
1237
91
  }
1238
92
  };
1239
93
  function attemptListen(p) {
@@ -1260,7 +114,7 @@ async function getTargetInfo(root, pathname) {
1260
114
  }
1261
115
  let stats;
1262
116
  try {
1263
- stats = await fs2.stat(filePath);
117
+ stats = await fs.stat(filePath);
1264
118
  } catch {
1265
119
  }
1266
120
  let targetDir;
@@ -1269,7 +123,11 @@ async function getTargetInfo(root, pathname) {
1269
123
  } else {
1270
124
  targetDir = originalPathname.endsWith("/") ? filePath : dirname(filePath);
1271
125
  }
1272
- return { filePath, targetDir, stats };
126
+ return {
127
+ filePath,
128
+ targetDir,
129
+ stats
130
+ };
1273
131
  }
1274
132
  function getMiddlewareDirs(base, parts) {
1275
133
  const middlewareDirs = [];
@@ -1287,7 +145,7 @@ async function collectMiddlewares(dirs) {
1287
145
  const mwPath = join(dir, "middleware.ts");
1288
146
  let mwModule;
1289
147
  try {
1290
- await fs2.access(mwPath);
148
+ await fs.access(mwPath);
1291
149
  const url = pathToFileURL(mwPath).href;
1292
150
  mwModule = await import(url);
1293
151
  } catch {
@@ -1303,18 +161,23 @@ async function collectMiddlewares(dirs) {
1303
161
  }
1304
162
  return middlewares;
1305
163
  }
1306
- async function handlePageRequest(root, pagesDirectory, pathname, req, res, DIST_DIR2, pageInfo) {
164
+ async function handlePageRequest(root, pagesDirectory, pathname, req, res, DIST_DIR, pageInfo) {
1307
165
  try {
1308
- const { filePath, targetDir, stats } = await getTargetInfo(root, pathname);
166
+ const {
167
+ filePath,
168
+ targetDir,
169
+ stats
170
+ } = await getTargetInfo(root, pathname);
1309
171
  const relDir = targetDir.slice(root.length).replace(/^[\/\\]+/, "");
1310
172
  const parts = relDir.split(/[\\/]/).filter(Boolean);
1311
173
  const middlewareDirs = getMiddlewareDirs(pagesDirectory, parts);
1312
174
  const middlewares = await collectMiddlewares(middlewareDirs);
1313
- let isDynamic = pageInfo.isDynamic;
175
+ const data = {};
176
+ const isDynamic = pageInfo.isDynamic;
1314
177
  const handlerPath = isDynamic ? pageInfo.filePath : join(filePath, "index.html");
1315
178
  let hasHandler = false;
1316
179
  try {
1317
- await fs2.access(handlerPath);
180
+ await fs.access(handlerPath);
1318
181
  hasHandler = true;
1319
182
  } catch {
1320
183
  }
@@ -1325,44 +188,65 @@ async function handlePageRequest(root, pagesDirectory, pathname, req, res, DIST_
1325
188
  }
1326
189
  if (isDynamic) {
1327
190
  try {
191
+ const {
192
+ buildDynamicPage
193
+ } = await import("../page_compiler");
1328
194
  const result = await buildDynamicPage(
1329
- DIST_DIR2,
195
+ DIST_DIR,
1330
196
  pathname,
1331
197
  pageInfo,
1332
198
  req2,
1333
- res2
199
+ res2,
200
+ data
1334
201
  );
1335
202
  if (result === false) {
1336
203
  return;
1337
204
  }
1338
- const { resultHTML } = result;
205
+ const {
206
+ resultHTML
207
+ } = result;
1339
208
  if (resultHTML === false) {
1340
209
  return;
1341
210
  }
1342
- await sendResponse(req2, res2, 200, { "Content-Type": MIME_TYPES[".html"] }, resultHTML);
211
+ await sendResponse(req2, res2, 200, {
212
+ "Content-Type": MIME_TYPES[".html"]
213
+ }, resultHTML);
1343
214
  } catch (err) {
1344
215
  log.error("Error building dynamic page -", err);
1345
216
  }
1346
217
  } else {
1347
218
  const ext = extname(handlerPath).toLowerCase();
1348
219
  const contentType = MIME_TYPES[ext] || "application/octet-stream";
1349
- const data = await fs2.readFile(handlerPath);
1350
- await sendResponse(req2, res2, 200, { "Content-Type": contentType }, data);
220
+ const fileData = await fs.readFile(handlerPath);
221
+ await sendResponse(req2, res2, 200, {
222
+ "Content-Type": contentType
223
+ }, fileData);
1351
224
  }
1352
225
  };
1353
- const composed = composeMiddlewares(middlewares, finalHandler, { isApi: false, root, pathname });
226
+ const composed = composeMiddlewares(middlewares, finalHandler, {
227
+ isApi: false,
228
+ root,
229
+ pathname,
230
+ data
231
+ });
1354
232
  await composed(req, res);
1355
233
  } catch (err) {
1356
234
  if (err.message === "Forbidden") {
1357
- await sendResponse(req, res, 403, { "Content-Type": "text/plain; charset=utf-8" }, "Forbidden");
235
+ await sendResponse(req, res, 403, {
236
+ "Content-Type": "text/plain; charset=utf-8"
237
+ }, "Forbidden");
1358
238
  } else {
1359
239
  throw err;
1360
240
  }
1361
241
  }
1362
242
  }
1363
- async function handleStaticRequest(root, pagesDirectory, pathname, req, res, DIST_DIR2) {
243
+ async function handleStaticRequest(root, pagesDirectory, pathname, req, res, DIST_DIR) {
1364
244
  try {
1365
- const { filePath, targetDir, stats } = await getTargetInfo(root, pathname);
245
+ const {
246
+ filePath,
247
+ targetDir,
248
+ stats
249
+ } = await getTargetInfo(root, pathname);
1366
250
  const relDir = targetDir.slice(root.length).replace(/^[\/\\]+/, "");
1367
251
  const parts = relDir.split(/[\\/]/).filter(Boolean);
1368
252
  const middlewareDirs = getMiddlewareDirs(pagesDirectory, parts);
@@ -1370,12 +254,10 @@ async function handleStaticRequest(root, pagesDirectory, pathname, req, res, DIS
1370
254
  let handlerPath = filePath;
1371
255
  if (stats && stats.isDirectory()) {
1372
256
  handlerPath = join(filePath, "index.html");
1373
- } else {
1374
- handlerPath = filePath;
1375
257
  }
1376
258
  let hasHandler = false;
1377
259
  try {
1378
- await fs2.access(handlerPath);
260
+ await fs.access(handlerPath);
1379
261
  hasHandler = true;
1380
262
  } catch {
1381
263
  }
@@ -1386,14 +268,22 @@ async function handleStaticRequest(root, pagesDirectory, pathname, req, res, DIS
1386
268
  }
1387
269
  const ext = extname(handlerPath).toLowerCase();
1388
270
  const contentType = MIME_TYPES[ext] || "application/octet-stream";
1389
- const data = await fs2.readFile(handlerPath);
1390
- await sendResponse(req2, res2, 200, { "Content-Type": contentType }, data);
271
+ const fileData = await fs.readFile(handlerPath);
272
+ await sendResponse(req2, res2, 200, {
273
+ "Content-Type": contentType
274
+ }, fileData);
1391
275
  };
1392
- const composed = composeMiddlewares(middlewares, finalHandler, { isApi: false, root, pathname });
276
+ const composed = composeMiddlewares(middlewares, finalHandler, {
277
+ isApi: false,
278
+ root,
279
+ pathname
280
+ });
1393
281
  await composed(req, res);
1394
282
  } catch (err) {
1395
283
  if (err.message === "Forbidden") {
1396
- await sendResponse(req, res, 403, { "Content-Type": "text/plain; charset=utf-8" }, "Forbidden");
284
+ await sendResponse(req, res, 403, {
285
+ "Content-Type": "text/plain; charset=utf-8"
286
+ }, "Forbidden");
1397
287
  } else {
1398
288
  throw err;
1399
289
  }
@@ -1408,7 +298,7 @@ async function handleApiRequest(pagesDirectory, pathname, req, res) {
1408
298
  const routePath = join(routeDir, "route.ts");
1409
299
  let hasRoute = false;
1410
300
  try {
1411
- await fs2.access(routePath);
301
+ await fs.access(routePath);
1412
302
  hasRoute = true;
1413
303
  } catch {
1414
304
  }
@@ -1433,18 +323,20 @@ async function handleApiRequest(pagesDirectory, pathname, req, res) {
1433
323
  }
1434
324
  await fn(req2, res2);
1435
325
  };
1436
- const composed = composeMiddlewares(middlewares, finalHandler, { isApi: true });
326
+ const composed = composeMiddlewares(middlewares, finalHandler, {
327
+ isApi: true
328
+ });
1437
329
  await composed(req, res);
1438
330
  }
1439
- function composeMiddlewares(mws, final, options2) {
331
+ function composeMiddlewares(mws, final, options) {
1440
332
  return async function(req, res) {
1441
333
  let index = 0;
1442
334
  async function dispatch(err) {
1443
335
  if (err) {
1444
- if (options2.isApi) {
336
+ if (options.isApi) {
1445
337
  return respondWithJsonError(req, res, 500, err.message || "Internal Server Error");
1446
338
  } else {
1447
- return await respondWithErrorPage(options2.root, options2.pathname, 500, req, res);
339
+ return await respondWithErrorPage(options.root, options.pathname, 500, req, res);
1448
340
  }
1449
341
  }
1450
342
  if (index >= mws.length) {
@@ -1464,7 +356,7 @@ function composeMiddlewares(mws, final, options2) {
1464
356
  };
1465
357
  };
1466
358
  try {
1467
- await thisMw(req, res, onceNext(next));
359
+ await thisMw(req, res, onceNext(next), options.data || {});
1468
360
  } catch (error) {
1469
361
  await dispatch(error);
1470
362
  }
@@ -1473,8 +365,12 @@ function composeMiddlewares(mws, final, options2) {
1473
365
  };
1474
366
  }
1475
367
  async function respondWithJsonError(req, res, code, message) {
1476
- const body2 = JSON.stringify({ error: message });
1477
- await sendResponse(req, res, code, { "Content-Type": "application/json; charset=utf-8" }, body2);
368
+ const body = JSON.stringify({
369
+ error: message
370
+ });
371
+ await sendResponse(req, res, code, {
372
+ "Content-Type": "application/json; charset=utf-8"
373
+ }, body);
1478
374
  }
1479
375
  async function respondWithErrorPage(root, pathname, code, req, res) {
1480
376
  let currentPath = normalize(join(root, decodeURIComponent(pathname)));
@@ -1484,7 +380,7 @@ async function respondWithErrorPage(root, pathname, code, req, res) {
1484
380
  const candidate = join(currentPath, `${code}.html`);
1485
381
  if (!tried.has(candidate)) {
1486
382
  try {
1487
- await fs2.access(candidate);
383
+ await fs.access(candidate);
1488
384
  errorFilePath = candidate;
1489
385
  break;
1490
386
  } catch {
@@ -1498,29 +394,31 @@ async function respondWithErrorPage(root, pathname, code, req, res) {
1498
394
  if (!errorFilePath) {
1499
395
  const fallback = join(root, `${code}.html`);
1500
396
  try {
1501
- await fs2.access(fallback);
397
+ await fs.access(fallback);
1502
398
  errorFilePath = fallback;
1503
399
  } catch {
1504
400
  }
1505
401
  }
1506
402
  if (errorFilePath) {
1507
403
  try {
1508
- const html2 = await fs2.readFile(errorFilePath, "utf8");
1509
- await sendResponse(req, res, code, { "Content-Type": "text/html; charset=utf-8" }, html2);
404
+ const html = await fs.readFile(errorFilePath, "utf8");
405
+ await sendResponse(req, res, code, {
406
+ "Content-Type": "text/html; charset=utf-8"
407
+ }, html);
1510
408
  return;
1511
409
  } catch {
1512
410
  }
1513
411
  }
1514
- await sendResponse(req, res, code, { "Content-Type": "text/plain; charset=utf-8" }, `${code} Error`);
412
+ await sendResponse(req, res, code, {
413
+ "Content-Type": "text/plain; charset=utf-8"
414
+ }, `${code} Error`);
1515
415
  }
1516
416
  function isCompressible(contentType) {
1517
417
  if (!contentType) return false;
1518
418
  return /text\/|javascript|json|xml|svg/.test(contentType);
1519
419
  }
1520
- async function sendResponse(req, res, status, headers, body2) {
1521
- if (typeof body2 === "string") {
1522
- body2 = Buffer.from(body2);
1523
- }
420
+ async function sendResponse(req, res, status, headers, body) {
421
+ let bufferBody = typeof body === "string" ? Buffer.from(body) : body;
1524
422
  const accept = req.headers["accept-encoding"] || "";
1525
423
  let encoding = null;
1526
424
  if (accept.match(/\bgzip\b/)) {
@@ -1530,12 +428,12 @@ async function sendResponse(req, res, status, headers, body2) {
1530
428
  }
1531
429
  if (!encoding || !isCompressible(headers["Content-Type"] || "")) {
1532
430
  res.writeHead(status, headers);
1533
- res.end(body2);
431
+ res.end(bufferBody);
1534
432
  return;
1535
433
  }
1536
434
  const compressor = encoding === "gzip" ? gzipAsync : deflateAsync;
1537
435
  try {
1538
- const compressed = await compressor(body2);
436
+ const compressed = await compressor(bufferBody);
1539
437
  headers["Content-Encoding"] = encoding;
1540
438
  headers["Vary"] = "Accept-Encoding";
1541
439
  res.writeHead(status, headers);
@@ -1543,7 +441,7 @@ async function sendResponse(req, res, status, headers, body2) {
1543
441
  } catch (err) {
1544
442
  log.error("Compression error:", err);
1545
443
  res.writeHead(status, headers);
1546
- res.end(body2);
444
+ res.end(bufferBody);
1547
445
  }
1548
446
  }
1549
447
  export {