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,729 +1,56 @@
1
- // src/page_compiler.ts
2
- import fs2 from "fs";
1
+ import fs from "fs";
3
2
  import path from "path";
3
+ const __filename = fileURLToPath(import.meta.url);
4
+ const __dirname = path.dirname(__filename);
4
5
  import { registerLoader, setArcTsConfig } from "ts-arc";
5
- import esbuild from "esbuild";
6
- import { fileURLToPath as fileURLToPath2 } from "url";
7
-
8
- // src/shared/serverElements.ts
9
- var createBuildableElement = (tag) => {
10
- return (options2, ...children) => ({
11
- tag,
12
- options: options2 || {},
13
- children
14
- });
15
- };
16
- var createChildrenlessBuildableElement = (tag) => {
17
- return (options2) => ({
18
- tag,
19
- options: options2 || {},
20
- children: null
21
- });
22
- };
23
- var childrenlessElementTags = [
24
- "area",
25
- "base",
26
- "br",
27
- "col",
28
- "embed",
29
- "hr",
30
- "img",
31
- "input",
32
- "link",
33
- "meta",
34
- "source",
35
- "track",
36
- "path",
37
- "rect"
38
- ];
39
- var elementTags = [
40
- "a",
41
- "address",
42
- "article",
43
- "aside",
44
- "audio",
45
- "blockquote",
46
- "body",
47
- "button",
48
- "canvas",
49
- "caption",
50
- "colgroup",
51
- "data",
52
- "datalist",
53
- "dd",
54
- "del",
55
- "details",
56
- "dialog",
57
- "div",
58
- "dl",
59
- "dt",
60
- "fieldset",
61
- "figcaption",
62
- "figure",
63
- "footer",
64
- "form",
65
- "h1",
66
- "h2",
67
- "h3",
68
- "h4",
69
- "h5",
70
- "h6",
71
- "head",
72
- "header",
73
- "hgroup",
74
- "html",
75
- "iframe",
76
- "ins",
77
- "label",
78
- "legend",
79
- "li",
80
- "main",
81
- "map",
82
- "meter",
83
- "nav",
84
- "noscript",
85
- "object",
86
- "ol",
87
- "optgroup",
88
- "option",
89
- "output",
90
- "p",
91
- "picture",
92
- "pre",
93
- "progress",
94
- "q",
95
- "section",
96
- "select",
97
- "summary",
98
- "table",
99
- "tbody",
100
- "td",
101
- "template",
102
- "textarea",
103
- "tfoot",
104
- "th",
105
- "thead",
106
- "time",
107
- "tr",
108
- "ul",
109
- "video",
110
- "span",
111
- "script",
112
- "abbr",
113
- "b",
114
- "bdi",
115
- "bdo",
116
- "cite",
117
- "code",
118
- "dfn",
119
- "em",
120
- "i",
121
- "kbd",
122
- "mark",
123
- "rp",
124
- "rt",
125
- "ruby",
126
- "s",
127
- "samp",
128
- "small",
129
- "strong",
130
- "sub",
131
- "sup",
132
- "u",
133
- "wbr",
134
- "title",
135
- "svg"
136
- ];
137
- var elements = {};
138
- var childrenlessElements = {};
139
- for (const element of elementTags) {
140
- elements[element] = createBuildableElement(element);
141
- }
142
- for (const element of childrenlessElementTags) {
143
- childrenlessElements[element] = createChildrenlessBuildableElement(element);
144
- }
145
- var allElements = {
146
- ...elements,
147
- ...childrenlessElements
148
- };
149
-
150
- // src/shared/bindServerElements.ts
151
- Object.assign(globalThis, elements);
152
- Object.assign(globalThis, childrenlessElements);
153
-
154
- // src/server/render.ts
155
- var renderRecursively = (element) => {
156
- let returnString = "";
157
- if (typeof element === "boolean") return returnString;
158
- else if (typeof element === "number" || typeof element === "string") {
159
- return returnString + element;
160
- } else if (Array.isArray(element)) {
161
- return returnString + element.join(", ");
162
- }
163
- returnString += `<${element.tag}`;
164
- if (typeof element.options === "object") {
165
- const {
166
- tag: elementTag,
167
- options: elementOptions,
168
- children: elementChildren
169
- } = element.options;
170
- if (elementTag !== void 0 && elementOptions !== void 0 && elementChildren !== void 0) {
171
- const children = element.children;
172
- element.children = [
173
- element.options,
174
- ...children
175
- ];
176
- element.options = {};
177
- } else {
178
- for (const [attrName, attrValue] of Object.entries(element.options)) {
179
- if (typeof attrValue === "object") {
180
- throw `Attr ${attrName}, for element ${element.tag} has obj type. Got: ${JSON.stringify(element, null, 2)}`;
181
- }
182
- returnString += ` ${attrName.toLowerCase()}="${attrValue}"`;
183
- }
184
- }
185
- } else if (typeof element.options !== "object" && element.options !== void 0) {
186
- element.children = [element.options, ...element.children || []];
187
- }
188
- if (element.children === null) {
189
- returnString += "/>";
190
- return returnString;
191
- }
192
- returnString += ">";
193
- for (const child of element.children) {
194
- returnString += renderRecursively(child);
195
- }
196
- returnString += `</${element.tag}>`;
197
- return returnString;
198
- };
199
- var serverSideRenderPage = async (page, pathname) => {
200
- if (!page) {
201
- throw `No Page Provided.`;
202
- }
203
- if (typeof page === "function") {
204
- throw `Unbuilt page provided to ssr page.`;
205
- }
206
- const bodyHTML = renderRecursively(page);
207
- return {
208
- bodyHTML
209
- };
210
- };
211
-
212
- // src/server/generateHTMLTemplate.ts
213
- var generateHTMLTemplate = async ({
214
- pageURL,
215
- head: head2,
216
- serverData = null,
217
- addPageScriptTag = true,
218
- name,
219
- requiredClientModules = {},
220
- environment
221
- }) => {
222
- let StartTemplate = `<meta name="viewport" content="width=device-width, initial-scale=1.0">`;
223
- if (environment === "production") {
224
- StartTemplate += `<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">`;
225
- }
226
- StartTemplate += '<meta charset="UTF-8">';
227
- for (const [globalName] of Object.entries(requiredClientModules)) {
228
- StartTemplate += `<script data-module="true" src="/shipped/${globalName}.js" defer="true"></script>`;
229
- }
230
- if (addPageScriptTag === true) {
231
- const sanitized = pageURL === "" ? "/" : `/${pageURL}`;
232
- StartTemplate += `<script data-page="true" type="module" data-pathname="${sanitized}" src="${sanitized.endsWith("/") ? sanitized : sanitized + "/"}${name}_data.js" defer="true"></script>`;
233
- }
234
- StartTemplate += `<script type="module" src="/client.js" defer="true"></script>`;
235
- let builtHead;
236
- if (head2.constructor.name === "AsyncFunction") {
237
- builtHead = await head2();
238
- } else {
239
- builtHead = head2();
240
- }
241
- let HTMLTemplate = renderRecursively(builtHead);
242
- if (serverData) {
243
- HTMLTemplate += serverData;
244
- }
245
- return {
246
- internals: StartTemplate,
247
- builtMetadata: HTMLTemplate
248
- };
249
- };
250
-
251
- // src/server/server.ts
252
- import { createServer as createHttpServer } from "http";
253
- import { promises as fs } from "fs";
254
- import { join, normalize, extname, dirname } from "path";
255
- import { pathToFileURL } from "url";
256
-
257
- // src/log.ts
258
- var quiet = false;
259
- function getTimestamp() {
260
- const now = /* @__PURE__ */ new Date();
261
- return now.toLocaleString(void 0, {
262
- year: "2-digit",
263
- month: "2-digit",
264
- day: "2-digit",
265
- hour: "2-digit",
266
- minute: "2-digit",
267
- second: "2-digit"
268
- });
269
- }
270
- function color(text, code) {
271
- return `\x1B[${code}m${text}\x1B[0m`;
272
- }
273
- function logInfo(...args) {
274
- if (quiet) return;
275
- console.info(`Elegance.JS: ${getTimestamp()} ${color("[INFO]:", 34)}`, ...args);
276
- }
277
- function logWarn(...args) {
278
- if (quiet) return;
279
- console.warn(`Elegance.JS: ${getTimestamp()} ${color("[WARN]:", 33)}`, ...args);
280
- }
281
- function logError(...args) {
282
- console.error(`Elegance.JS: ${getTimestamp()} ${color("[ERROR]:", 31)}`, ...args);
283
- }
284
- var log = {
285
- info: logInfo,
286
- warn: logWarn,
287
- error: logError
288
- };
289
-
290
- // src/server/server.ts
291
- import { gzip, deflate } from "zlib";
292
- import { promisify } from "util";
293
- var gzipAsync = promisify(gzip);
294
- var deflateAsync = promisify(deflate);
295
- var MIME_TYPES = {
296
- ".html": "text/html; charset=utf-8",
297
- ".css": "text/css; charset=utf-8",
298
- ".js": "application/javascript; charset=utf-8",
299
- ".json": "application/json; charset=utf-8",
300
- ".png": "image/png",
301
- ".jpg": "image/jpeg",
302
- ".jpeg": "image/jpeg",
303
- ".gif": "image/gif",
304
- ".svg": "image/svg+xml",
305
- ".ico": "image/x-icon",
306
- ".txt": "text/plain; charset=utf-8"
307
- };
308
- function startServer({
309
- root,
310
- pagesDirectory,
311
- port = 3e3,
312
- host = "localhost",
313
- environment = "production",
314
- DIST_DIR: DIST_DIR2
315
- }) {
316
- if (!root) throw new Error("Root directory must be specified.");
317
- if (!pagesDirectory) throw new Error("Pages directory must be specified.");
318
- root = normalize(root).replace(/[\\/]+$/, "");
319
- pagesDirectory = normalize(pagesDirectory).replace(/[\\/]+$/, "");
320
- const requestHandler = async (req, res) => {
321
- try {
322
- if (!req.url) {
323
- await sendResponse(req, res, 400, { "Content-Type": "text/plain; charset=utf-8" }, "Bad Request");
324
- return;
325
- }
326
- res.setHeader("Access-Control-Allow-Origin", "*");
327
- res.setHeader("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS");
328
- res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
329
- if (req.method === "OPTIONS") {
330
- res.writeHead(204);
331
- res.end();
332
- if (environment === "development") {
333
- log.info(req.method, "::", req.url, "-", res.statusCode);
334
- }
335
- return;
336
- }
337
- const url = new URL(req.url, `http://${req.headers.host}`);
338
- if (url.pathname.startsWith("/api/")) {
339
- await handleApiRequest(pagesDirectory, url.pathname, req, res);
340
- } else if (PAGE_MAP.has(url.pathname)) {
341
- await handlePageRequest(root, pagesDirectory, url.pathname, req, res, DIST_DIR2, PAGE_MAP.get(url.pathname));
342
- } else {
343
- await handleStaticRequest(root, pagesDirectory, url.pathname, req, res, DIST_DIR2);
344
- }
345
- if (environment === "development") {
346
- log.info(req.method, "::", req.url, "-", res.statusCode);
347
- }
348
- } catch (err) {
349
- log.error(err);
350
- await sendResponse(req, res, 500, { "Content-Type": "text/plain; charset=utf-8" }, "Internal Server Error");
351
- }
352
- };
353
- function attemptListen(p) {
354
- const server = createHttpServer(requestHandler);
355
- server.on("error", (err) => {
356
- if (err.code === "EADDRINUSE") {
357
- attemptListen(p + 1);
358
- } else {
359
- console.error(err);
360
- }
361
- });
362
- server.listen(p, host, () => {
363
- log.info(`Server running at http://${host}:${p}/`);
364
- });
365
- return server;
366
- }
367
- return attemptListen(port);
368
- }
369
- async function getTargetInfo(root, pathname) {
370
- const originalPathname = pathname;
371
- const filePath = normalize(join(root, decodeURIComponent(pathname))).replace(/[\\/]+$/, "");
372
- if (!filePath.startsWith(root)) {
373
- throw new Error("Forbidden");
374
- }
375
- let stats;
376
- try {
377
- stats = await fs.stat(filePath);
378
- } catch {
379
- }
380
- let targetDir;
381
- if (stats) {
382
- targetDir = stats.isDirectory() ? filePath : dirname(filePath);
383
- } else {
384
- targetDir = originalPathname.endsWith("/") ? filePath : dirname(filePath);
385
- }
386
- return { filePath, targetDir, stats };
387
- }
388
- function getMiddlewareDirs(base, parts) {
389
- const middlewareDirs = [];
390
- let current = base;
391
- middlewareDirs.push(current);
392
- for (const part of parts) {
393
- current = join(current, part);
394
- middlewareDirs.push(current);
395
- }
396
- return middlewareDirs;
397
- }
398
- async function collectMiddlewares(dirs) {
399
- const middlewares = [];
400
- for (const dir of dirs) {
401
- const mwPath = join(dir, "middleware.ts");
402
- let mwModule;
403
- try {
404
- await fs.access(mwPath);
405
- const url = pathToFileURL(mwPath).href;
406
- mwModule = await import(url);
407
- } catch {
408
- continue;
409
- }
410
- const mwKeys = Object.keys(mwModule).sort();
411
- for (const key of mwKeys) {
412
- const f = mwModule[key];
413
- if (typeof f === "function" && !middlewares.some((existing) => existing === f)) {
414
- middlewares.push(f);
415
- }
416
- }
417
- }
418
- return middlewares;
419
- }
420
- async function handlePageRequest(root, pagesDirectory, pathname, req, res, DIST_DIR2, pageInfo) {
421
- try {
422
- const { filePath, targetDir, stats } = await getTargetInfo(root, pathname);
423
- const relDir = targetDir.slice(root.length).replace(/^[\/\\]+/, "");
424
- const parts = relDir.split(/[\\/]/).filter(Boolean);
425
- const middlewareDirs = getMiddlewareDirs(pagesDirectory, parts);
426
- const middlewares = await collectMiddlewares(middlewareDirs);
427
- let isDynamic = pageInfo.isDynamic;
428
- const handlerPath = isDynamic ? pageInfo.filePath : join(filePath, "index.html");
429
- let hasHandler = false;
430
- try {
431
- await fs.access(handlerPath);
432
- hasHandler = true;
433
- } catch {
434
- }
435
- const finalHandler = async (req2, res2) => {
436
- if (!hasHandler) {
437
- await respondWithErrorPage(root, pathname, 404, req2, res2);
438
- return;
439
- }
440
- if (isDynamic) {
441
- try {
442
- const result = await buildDynamicPage(
443
- DIST_DIR2,
444
- pathname,
445
- pageInfo,
446
- req2,
447
- res2
448
- );
449
- if (result === false) {
450
- return;
451
- }
452
- const { resultHTML } = result;
453
- if (resultHTML === false) {
454
- return;
455
- }
456
- await sendResponse(req2, res2, 200, { "Content-Type": MIME_TYPES[".html"] }, resultHTML);
457
- } catch (err) {
458
- log.error("Error building dynamic page -", err);
459
- }
460
- } else {
461
- const ext = extname(handlerPath).toLowerCase();
462
- const contentType = MIME_TYPES[ext] || "application/octet-stream";
463
- const data = await fs.readFile(handlerPath);
464
- await sendResponse(req2, res2, 200, { "Content-Type": contentType }, data);
465
- }
466
- };
467
- const composed = composeMiddlewares(middlewares, finalHandler, { isApi: false, root, pathname });
468
- await composed(req, res);
469
- } catch (err) {
470
- if (err.message === "Forbidden") {
471
- await sendResponse(req, res, 403, { "Content-Type": "text/plain; charset=utf-8" }, "Forbidden");
472
- } else {
473
- throw err;
474
- }
475
- }
476
- }
477
- async function handleStaticRequest(root, pagesDirectory, pathname, req, res, DIST_DIR2) {
478
- try {
479
- const { filePath, targetDir, stats } = await getTargetInfo(root, pathname);
480
- const relDir = targetDir.slice(root.length).replace(/^[\/\\]+/, "");
481
- const parts = relDir.split(/[\\/]/).filter(Boolean);
482
- const middlewareDirs = getMiddlewareDirs(pagesDirectory, parts);
483
- const middlewares = await collectMiddlewares(middlewareDirs);
484
- let handlerPath = filePath;
485
- if (stats && stats.isDirectory()) {
486
- handlerPath = join(filePath, "index.html");
487
- } else {
488
- handlerPath = filePath;
489
- }
490
- let hasHandler = false;
491
- try {
492
- await fs.access(handlerPath);
493
- hasHandler = true;
494
- } catch {
495
- }
496
- const finalHandler = async (req2, res2) => {
497
- if (!hasHandler) {
498
- await respondWithErrorPage(root, pathname, 404, req2, res2);
499
- return;
500
- }
501
- const ext = extname(handlerPath).toLowerCase();
502
- const contentType = MIME_TYPES[ext] || "application/octet-stream";
503
- const data = await fs.readFile(handlerPath);
504
- await sendResponse(req2, res2, 200, { "Content-Type": contentType }, data);
505
- };
506
- const composed = composeMiddlewares(middlewares, finalHandler, { isApi: false, root, pathname });
507
- await composed(req, res);
508
- } catch (err) {
509
- if (err.message === "Forbidden") {
510
- await sendResponse(req, res, 403, { "Content-Type": "text/plain; charset=utf-8" }, "Forbidden");
511
- } else {
512
- throw err;
513
- }
514
- }
515
- }
516
- async function handleApiRequest(pagesDirectory, pathname, req, res) {
517
- const apiSubPath = pathname.slice("/api/".length);
518
- const parts = apiSubPath.split("/").filter(Boolean);
519
- const middlewareDirs = getMiddlewareDirs(join(pagesDirectory, "api"), parts);
520
- const middlewares = await collectMiddlewares(middlewareDirs);
521
- const routeDir = middlewareDirs[middlewareDirs.length - 1];
522
- const routePath = join(routeDir, "route.ts");
523
- let hasRoute = false;
524
- try {
525
- await fs.access(routePath);
526
- hasRoute = true;
527
- } catch {
528
- }
529
- let fn = null;
530
- let module = null;
531
- if (hasRoute) {
532
- try {
533
- const moduleUrl = pathToFileURL(routePath).href;
534
- module = await import(moduleUrl);
535
- fn = module[req.method];
536
- } catch (err) {
537
- console.error(err);
538
- return respondWithJsonError(req, res, 500, "Internal Server Error");
539
- }
540
- }
541
- const finalHandler = async (req2, res2) => {
542
- if (!hasRoute) {
543
- return respondWithJsonError(req2, res2, 404, "Not Found");
544
- }
545
- if (typeof fn !== "function") {
546
- return respondWithJsonError(req2, res2, 405, "Method Not Allowed");
547
- }
548
- await fn(req2, res2);
549
- };
550
- const composed = composeMiddlewares(middlewares, finalHandler, { isApi: true });
551
- await composed(req, res);
552
- }
553
- function composeMiddlewares(mws, final, options2) {
554
- return async function(req, res) {
555
- let index = 0;
556
- async function dispatch(err) {
557
- if (err) {
558
- if (options2.isApi) {
559
- return respondWithJsonError(req, res, 500, err.message || "Internal Server Error");
560
- } else {
561
- return await respondWithErrorPage(options2.root, options2.pathname, 500, req, res);
562
- }
563
- }
564
- if (index >= mws.length) {
565
- return await final(req, res);
566
- }
567
- const thisMw = mws[index++];
568
- const next = (e) => dispatch(e);
569
- const onceNext = (nextFn) => {
570
- let called = false;
571
- return async (e) => {
572
- if (called) {
573
- log.warn("next() was called in a middleware more than once.");
574
- return;
575
- }
576
- called = true;
577
- await nextFn(e);
578
- };
579
- };
580
- try {
581
- await thisMw(req, res, onceNext(next));
582
- } catch (error) {
583
- await dispatch(error);
584
- }
585
- }
586
- await dispatch();
587
- };
588
- }
589
- async function respondWithJsonError(req, res, code, message) {
590
- const body2 = JSON.stringify({ error: message });
591
- await sendResponse(req, res, code, { "Content-Type": "application/json; charset=utf-8" }, body2);
592
- }
593
- async function respondWithErrorPage(root, pathname, code, req, res) {
594
- let currentPath = normalize(join(root, decodeURIComponent(pathname)));
595
- let tried = /* @__PURE__ */ new Set();
596
- let errorFilePath = null;
597
- while (currentPath.startsWith(root)) {
598
- const candidate = join(currentPath, `${code}.html`);
599
- if (!tried.has(candidate)) {
600
- try {
601
- await fs.access(candidate);
602
- errorFilePath = candidate;
603
- break;
604
- } catch {
605
- }
606
- tried.add(candidate);
607
- }
608
- const parent = dirname(currentPath);
609
- if (parent === currentPath) break;
610
- currentPath = parent;
611
- }
612
- if (!errorFilePath) {
613
- const fallback = join(root, `${code}.html`);
614
- try {
615
- await fs.access(fallback);
616
- errorFilePath = fallback;
617
- } catch {
618
- }
619
- }
620
- if (errorFilePath) {
621
- try {
622
- const html2 = await fs.readFile(errorFilePath, "utf8");
623
- await sendResponse(req, res, code, { "Content-Type": "text/html; charset=utf-8" }, html2);
624
- return;
625
- } catch {
626
- }
627
- }
628
- await sendResponse(req, res, code, { "Content-Type": "text/plain; charset=utf-8" }, `${code} Error`);
629
- }
630
- function isCompressible(contentType) {
631
- if (!contentType) return false;
632
- return /text\/|javascript|json|xml|svg/.test(contentType);
633
- }
634
- async function sendResponse(req, res, status, headers, body2) {
635
- if (typeof body2 === "string") {
636
- body2 = Buffer.from(body2);
637
- }
638
- const accept = req.headers["accept-encoding"] || "";
639
- let encoding = null;
640
- if (accept.match(/\bgzip\b/)) {
641
- encoding = "gzip";
642
- } else if (accept.match(/\bdeflate\b/)) {
643
- encoding = "deflate";
644
- }
645
- if (!encoding || !isCompressible(headers["Content-Type"] || "")) {
646
- res.writeHead(status, headers);
647
- res.end(body2);
648
- return;
649
- }
650
- const compressor = encoding === "gzip" ? gzipAsync : deflateAsync;
651
- try {
652
- const compressed = await compressor(body2);
653
- headers["Content-Encoding"] = encoding;
654
- headers["Vary"] = "Accept-Encoding";
655
- res.writeHead(status, headers);
656
- res.end(compressed);
657
- } catch (err) {
658
- log.error("Compression error:", err);
659
- res.writeHead(status, headers);
660
- res.end(body2);
661
- }
662
- }
663
-
664
- // src/server/loadHook.ts
665
- var resetLoadHooks = () => globalThis.__SERVER_CURRENT_LOADHOOKS__ = [];
666
- var getLoadHooks = () => globalThis.__SERVER_CURRENT_LOADHOOKS__;
667
-
668
- // src/server/state.ts
669
- if (!globalThis.__SERVER_CURRENT_STATE_ID__) {
670
- globalThis.__SERVER_CURRENT_STATE_ID__ = 1;
671
- }
672
- var initializeState = () => globalThis.__SERVER_CURRENT_STATE__ = [];
673
- var getState = () => {
674
- return globalThis.__SERVER_CURRENT_STATE__;
675
- };
676
- var initializeObjectAttributes = () => globalThis.__SERVER_CURRENT_OBJECT_ATTRIBUTES__ = [];
677
- var getObjectAttributes = () => {
678
- return globalThis.__SERVER_CURRENT_OBJECT_ATTRIBUTES__;
679
- };
680
-
681
- // src/server/layout.ts
682
- var resetLayouts = () => globalThis.__SERVER_CURRENT_LAYOUTS__ = /* @__PURE__ */ new Map();
683
- if (!globalThis.__SERVER_CURRENT_LAYOUT_ID__) globalThis.__SERVER_CURRENT_LAYOUT_ID__ = 1;
684
-
685
- // src/page_compiler.ts
686
- var __filename = fileURLToPath2(import.meta.url);
687
- var __dirname = path.dirname(__filename);
688
6
  setArcTsConfig(__dirname);
689
7
  registerLoader();
690
- var packageDir = process.env.PACKAGE_PATH;
8
+ import esbuild from "esbuild";
9
+ import { fileURLToPath } from "url";
10
+ import { generateHTMLTemplate } from "./server/generateHTMLTemplate";
11
+ import { ObjectAttributeType } from "./helpers/ObjectAttributeType";
12
+ import { serverSideRenderPage } from "./server/render";
13
+ import { getState, initializeState, initializeObjectAttributes, getObjectAttributes } from "./server/state";
14
+ import { getLoadHooks, resetLoadHooks } from "./server/loadHook";
15
+ import { resetLayouts } from "./server/layout";
16
+ import { renderRecursively } from "./server/render";
17
+ let packageDir = process.env.PACKAGE_PATH;
691
18
  if (packageDir === void 0) {
692
19
  packageDir = path.resolve(__dirname, "..");
693
20
  }
694
- var clientPath = path.resolve(packageDir, "./dist/client/client.mjs");
695
- var watcherPath = path.resolve(packageDir, "./dist/client/watcher.mjs");
696
- var shippedModules = /* @__PURE__ */ new Map();
697
- var modulesToShip = [];
698
- var yellow = (text) => {
21
+ const clientPath = path.resolve(packageDir, "./dist/client/client.mjs");
22
+ const watcherPath = path.resolve(packageDir, "./dist/client/watcher.mjs");
23
+ const shippedModules = /* @__PURE__ */ new Map();
24
+ let modulesToShip = [];
25
+ const yellow = (text) => {
699
26
  return `\x1B[38;2;238;184;68m${text}`;
700
27
  };
701
- var black = (text) => {
28
+ const black = (text) => {
702
29
  return `\x1B[38;2;0;0;0m${text}`;
703
30
  };
704
- var bgYellow = (text) => {
31
+ const bgYellow = (text) => {
705
32
  return `\x1B[48;2;238;184;68m${text}`;
706
33
  };
707
- var bold = (text) => {
34
+ const bold = (text) => {
708
35
  return `\x1B[1m${text}`;
709
36
  };
710
- var underline = (text) => {
37
+ const underline = (text) => {
711
38
  return `\x1B[4m${text}`;
712
39
  };
713
- var white = (text) => {
40
+ const white = (text) => {
714
41
  return `\x1B[38;2;255;247;229m${text}`;
715
42
  };
716
- var log2 = (...text) => {
43
+ const log = (...text) => {
717
44
  if (options.quiet) return;
718
45
  return console.log(text.map((text2) => `${text2}\x1B[0m`).join(""));
719
46
  };
720
- var options = JSON.parse(process.env.OPTIONS);
721
- var DIST_DIR = process.env.DIST_DIR;
722
- var PAGE_MAP = /* @__PURE__ */ new Map();
723
- var LAYOUT_MAP2 = /* @__PURE__ */ new Map();
724
- var getAllSubdirectories = (dir, baseDir = dir) => {
47
+ let options = JSON.parse(process.env.OPTIONS || "{}");
48
+ const DIST_DIR = process.env.DIST_DIR;
49
+ const PAGE_MAP = /* @__PURE__ */ new Map();
50
+ const LAYOUT_MAP = /* @__PURE__ */ new Map();
51
+ const getAllSubdirectories = (dir, baseDir = dir) => {
725
52
  let directories = [];
726
- const items = fs2.readdirSync(dir, { withFileTypes: true });
53
+ const items = fs.readdirSync(dir, { withFileTypes: true });
727
54
  for (const item of items) {
728
55
  if (item.isDirectory()) {
729
56
  const fullPath = path.join(dir, item.name);
@@ -734,12 +61,12 @@ var getAllSubdirectories = (dir, baseDir = dir) => {
734
61
  }
735
62
  return directories;
736
63
  };
737
- var buildClient = async (DIST_DIR2) => {
64
+ const buildClient = async (DIST_DIR2) => {
738
65
  let clientString = "window.__name = (func) => func; ";
739
- clientString += fs2.readFileSync(clientPath, "utf-8");
66
+ clientString += fs.readFileSync(clientPath, "utf-8");
740
67
  if (options.hotReload !== void 0) {
741
68
  clientString += `const watchServerPort = ${options.hotReload.port}`;
742
- clientString += fs2.readFileSync(watcherPath, "utf-8");
69
+ clientString += fs.readFileSync(watcherPath, "utf-8");
743
70
  }
744
71
  const transformedClient = await esbuild.transform(clientString, {
745
72
  minify: options.environment === "production",
@@ -749,13 +76,13 @@ var buildClient = async (DIST_DIR2) => {
749
76
  platform: "node",
750
77
  loader: "ts"
751
78
  });
752
- fs2.writeFileSync(
79
+ fs.writeFileSync(
753
80
  path.join(DIST_DIR2, "/client.js"),
754
81
  transformedClient.code
755
82
  );
756
83
  };
757
- var elementKey = 0;
758
- var processOptionAsObjectAttribute = (element, optionName, optionValue, objectAttributes) => {
84
+ let elementKey = 0;
85
+ const processOptionAsObjectAttribute = (element, optionName, optionValue, objectAttributes) => {
759
86
  const lcOptionName = optionName.toLowerCase();
760
87
  const options2 = element.options;
761
88
  let key = options2.key;
@@ -768,7 +95,7 @@ var processOptionAsObjectAttribute = (element, optionName, optionValue, objectAt
768
95
  }
769
96
  let optionFinal = lcOptionName;
770
97
  switch (optionValue.type) {
771
- case 1 /* STATE */:
98
+ case ObjectAttributeType.STATE:
772
99
  const SOA = optionValue;
773
100
  if (typeof SOA.value === "function") {
774
101
  delete options2[optionName];
@@ -782,7 +109,7 @@ var processOptionAsObjectAttribute = (element, optionName, optionValue, objectAt
782
109
  options2[lcOptionName] = SOA.value;
783
110
  }
784
111
  break;
785
- case 2 /* OBSERVER */:
112
+ case ObjectAttributeType.OBSERVER:
786
113
  const OOA = optionValue;
787
114
  const firstValue = OOA.update(...OOA.initialValues);
788
115
  if (lcOptionName === "innertext" || lcOptionName === "innerhtml") {
@@ -794,7 +121,7 @@ var processOptionAsObjectAttribute = (element, optionName, optionValue, objectAt
794
121
  }
795
122
  optionFinal = optionName;
796
123
  break;
797
- case 4 /* REFERENCE */:
124
+ case ObjectAttributeType.REFERENCE:
798
125
  options2["ref"] = optionValue.value;
799
126
  break;
800
127
  }
@@ -835,7 +162,7 @@ function buildTrace(stack, indent = 4) {
835
162
  return "Could not build stack-trace.";
836
163
  }
837
164
  }
838
- var processPageElements = (element, objectAttributes, recursionLevel, stack = []) => {
165
+ const processPageElements = (element, objectAttributes, recursionLevel, stack = []) => {
839
166
  stack.push(element);
840
167
  try {
841
168
  if (typeof element === "boolean" || typeof element === "number" || Array.isArray(element)) {
@@ -928,7 +255,7 @@ ${trace}`);
928
255
  }
929
256
  }
930
257
  };
931
- var pageToHTML = async (pageLocation, pageElements, metadata, DIST_DIR2, pageName, doWrite = true, requiredClientModules = {}, layout, pathname = "") => {
258
+ const pageToHTML = async (pageLocation, pageElements, metadata, DIST_DIR2, pageName, doWrite = true, requiredClientModules = {}, layout, pathname = "") => {
932
259
  if (typeof pageElements === "string" || typeof pageElements === "boolean" || typeof pageElements === "number" || Array.isArray(pageElements)) {
933
260
  throw new Error(`The root element of a page / layout must be a built element, not just a Child. Received: ${typeof pageElements}.`);
934
261
  }
@@ -988,11 +315,11 @@ var pageToHTML = async (pageLocation, pageElements, metadata, DIST_DIR2, pageNam
988
315
  const resultHTML = `${headHTML}${bodyHTML}`;
989
316
  const htmlLocation = path.join(pageLocation, (pageName === "page" ? "index" : pageName) + ".html");
990
317
  if (doWrite) {
991
- const dirname2 = path.dirname(htmlLocation);
992
- if (fs2.existsSync(dirname2) === false) {
993
- fs2.mkdirSync(dirname2, { recursive: true });
318
+ const dirname = path.dirname(htmlLocation);
319
+ if (fs.existsSync(dirname) === false) {
320
+ fs.mkdirSync(dirname, { recursive: true });
994
321
  }
995
- fs2.writeFileSync(
322
+ fs.writeFileSync(
996
323
  htmlLocation,
997
324
  resultHTML,
998
325
  {
@@ -1004,7 +331,7 @@ var pageToHTML = async (pageLocation, pageElements, metadata, DIST_DIR2, pageNam
1004
331
  }
1005
332
  return resultHTML;
1006
333
  };
1007
- var generateClientPageData = async (pageLocation, state, objectAttributes, pageLoadHooks, DIST_DIR2, pageName, globalVariableName = "pd", write = true) => {
334
+ const generateClientPageData = async (pageLocation, state, objectAttributes, pageLoadHooks, DIST_DIR2, pageName, globalVariableName = "pd", write = true) => {
1008
335
  let clientPageJSText = "";
1009
336
  {
1010
337
  clientPageJSText += `${globalThis.__SERVER_PAGE_DATA_BANNER__}`;
@@ -1025,7 +352,7 @@ var generateClientPageData = async (pageLocation, state, objectAttributes, pageL
1025
352
  }
1026
353
  clientPageJSText += `],`;
1027
354
  }
1028
- const stateObjectAttributes = objectAttributes.filter((oa) => oa.type === 1 /* STATE */);
355
+ const stateObjectAttributes = objectAttributes.filter((oa) => oa.type === ObjectAttributeType.STATE);
1029
356
  if (stateObjectAttributes.length > 0) {
1030
357
  const processed = [...stateObjectAttributes].map((soa) => {
1031
358
  delete soa.type;
@@ -1033,7 +360,7 @@ var generateClientPageData = async (pageLocation, state, objectAttributes, pageL
1033
360
  });
1034
361
  clientPageJSText += `soa:${JSON.stringify(processed)},`;
1035
362
  }
1036
- const observerObjectAttributes = objectAttributes.filter((oa) => oa.type === 2 /* OBSERVER */);
363
+ const observerObjectAttributes = objectAttributes.filter((oa) => oa.type === ObjectAttributeType.OBSERVER);
1037
364
  if (observerObjectAttributes.length > 0) {
1038
365
  let observerObjectAttributeString = "ooa:[";
1039
366
  for (const observerObjectAttribute of observerObjectAttributes) {
@@ -1050,8 +377,8 @@ var generateClientPageData = async (pageLocation, state, objectAttributes, pageL
1050
377
  }
1051
378
  if (pageLoadHooks.length > 0) {
1052
379
  clientPageJSText += "lh:[";
1053
- for (const loadHook2 of pageLoadHooks) {
1054
- clientPageJSText += `{fn:${loadHook2.fn}},`;
380
+ for (const loadHook of pageLoadHooks) {
381
+ clientPageJSText += `{fn:${loadHook.fn}},`;
1055
382
  }
1056
383
  clientPageJSText += "],";
1057
384
  }
@@ -1063,16 +390,16 @@ var generateClientPageData = async (pageLocation, state, objectAttributes, pageL
1063
390
  console.error("Failed to transform client page js!", error);
1064
391
  });
1065
392
  if (!transformedResult) return { sendHardReloadInstruction };
1066
- if (fs2.existsSync(pageDataPath)) {
1067
- const content = fs2.readFileSync(pageDataPath).toString();
393
+ if (fs.existsSync(pageDataPath)) {
394
+ const content = fs.readFileSync(pageDataPath).toString();
1068
395
  if (content !== transformedResult.code) {
1069
396
  sendHardReloadInstruction = true;
1070
397
  }
1071
398
  }
1072
- if (write) fs2.writeFileSync(pageDataPath, transformedResult.code, "utf-8");
399
+ if (write) fs.writeFileSync(pageDataPath, transformedResult.code, "utf-8");
1073
400
  return { sendHardReloadInstruction, result: transformedResult.code };
1074
401
  };
1075
- var generateLayout = async (DIST_DIR2, filePath, directory, childIndicator, generateDynamic = false) => {
402
+ const generateLayout = async (DIST_DIR2, filePath, directory, childIndicator, generateDynamic = false) => {
1076
403
  initializeState();
1077
404
  initializeObjectAttributes();
1078
405
  resetLoadHooks();
@@ -1099,7 +426,7 @@ var generateLayout = async (DIST_DIR2, filePath, directory, childIndicator, gene
1099
426
  } catch (e) {
1100
427
  throw new Error(`Error in Page: ${directory === "" ? "/" : directory}layout.ts - ${e}`);
1101
428
  }
1102
- LAYOUT_MAP2.set(directory === "" ? "/" : `/${directory}`, {
429
+ LAYOUT_MAP.set(directory === "" ? "/" : `/${directory}`, {
1103
430
  isDynamic: isDynamicLayout,
1104
431
  filePath
1105
432
  });
@@ -1153,14 +480,14 @@ var generateLayout = async (DIST_DIR2, filePath, directory, childIndicator, gene
1153
480
  );
1154
481
  return { pageContentHTML: renderedPage.bodyHTML, metadataHTML };
1155
482
  };
1156
- var builtLayouts = /* @__PURE__ */ new Map();
1157
- var buildLayouts = async () => {
483
+ const builtLayouts = /* @__PURE__ */ new Map();
484
+ const buildLayouts = async () => {
1158
485
  const pagesDirectory = path.resolve(options.pagesDirectory);
1159
486
  const subdirectories = [...getAllSubdirectories(pagesDirectory), ""];
1160
487
  let shouldClientHardReload = false;
1161
488
  for (const directory of subdirectories) {
1162
489
  const abs = path.resolve(path.join(pagesDirectory, directory));
1163
- const files = fs2.readdirSync(abs, { withFileTypes: true }).filter((f) => f.name.endsWith(".ts"));
490
+ const files = fs.readdirSync(abs, { withFileTypes: true }).filter((f) => f.name.endsWith(".ts"));
1164
491
  for (const file of files) {
1165
492
  const filePath = path.join(file.parentPath, file.name);
1166
493
  const name = file.name.slice(0, file.name.length - 3);
@@ -1180,7 +507,7 @@ var buildLayouts = async () => {
1180
507
  }
1181
508
  return { shouldClientHardReload };
1182
509
  };
1183
- var buildLayout = async (filePath, directory, generateDynamic = false) => {
510
+ const buildLayout = async (filePath, directory, generateDynamic = false) => {
1184
511
  const id = globalThis.__SERVER_CURRENT_STATE_ID__ += 1;
1185
512
  const childIndicator = `<template layout-id="${id}"></template>`;
1186
513
  const result = await generateLayout(
@@ -1215,16 +542,16 @@ var buildLayout = async (filePath, directory, generateDynamic = false) => {
1215
542
  scriptTag: `<script data-layout="true" type="module" src="${pathname}layout_data.js" data-pathname="${pathname}" defer="true"></script>`
1216
543
  };
1217
544
  };
1218
- var fetchPageLayoutHTML = async (dirname2) => {
1219
- const relative2 = path.relative(options.pagesDirectory, dirname2);
1220
- let split = relative2.split(path.sep).filter(Boolean);
545
+ const fetchPageLayoutHTML = async (dirname) => {
546
+ const relative = path.relative(options.pagesDirectory, dirname);
547
+ let split = relative.split(path.sep).filter(Boolean);
1221
548
  split.push("/");
1222
549
  split.reverse();
1223
550
  let layouts = [];
1224
551
  for (const dir of split) {
1225
- if (LAYOUT_MAP2.has(dir)) {
552
+ if (LAYOUT_MAP.has(dir)) {
1226
553
  const filePath = path.join(path.resolve(options.pagesDirectory), dir, "layout.ts");
1227
- const layout = LAYOUT_MAP2.get(dir);
554
+ const layout = LAYOUT_MAP.get(dir);
1228
555
  if (layout.isDynamic) {
1229
556
  const builtLayout = await buildLayout(layout.filePath, dir, true);
1230
557
  if (!builtLayout) continue;
@@ -1252,14 +579,14 @@ var fetchPageLayoutHTML = async (dirname2) => {
1252
579
  }
1253
580
  return { pageContent, metadata, scriptTag: scriptTags };
1254
581
  };
1255
- var buildPages = async (DIST_DIR2) => {
582
+ const buildPages = async (DIST_DIR2) => {
1256
583
  resetLayouts();
1257
584
  const pagesDirectory = path.resolve(options.pagesDirectory);
1258
585
  const subdirectories = [...getAllSubdirectories(pagesDirectory), ""];
1259
586
  let shouldClientHardReload = false;
1260
587
  for (const directory of subdirectories) {
1261
588
  const abs = path.resolve(path.join(pagesDirectory, directory));
1262
- const files = fs2.readdirSync(abs, { withFileTypes: true }).filter((f) => f.name.endsWith(".ts"));
589
+ const files = fs.readdirSync(abs, { withFileTypes: true }).filter((f) => f.name.endsWith(".ts"));
1263
590
  for (const file of files) {
1264
591
  const filePath = path.join(file.parentPath, file.name);
1265
592
  const name = file.name.slice(0, file.name.length - 3);
@@ -1282,7 +609,7 @@ var buildPages = async (DIST_DIR2) => {
1282
609
  shouldClientHardReload
1283
610
  };
1284
611
  };
1285
- var buildPage = async (DIST_DIR2, directory, filePath, name) => {
612
+ const buildPage = async (DIST_DIR2, directory, filePath, name) => {
1286
613
  initializeState();
1287
614
  initializeObjectAttributes();
1288
615
  resetLoadHooks();
@@ -1331,7 +658,8 @@ var buildPage = async (DIST_DIR2, directory, filePath, name) => {
1331
658
  console.warn(`WARNING: ${filePath} should export a const page, which is of type () => BuiltElement<"body">.`);
1332
659
  }
1333
660
  const pageProps = {
1334
- pageName: directory
661
+ pageName: directory,
662
+ middlewareData: {}
1335
663
  };
1336
664
  if (typeof pageElements === "function") {
1337
665
  if (pageElements.constructor.name === "AsyncFunction") {
@@ -1367,7 +695,7 @@ var buildPage = async (DIST_DIR2, directory, filePath, name) => {
1367
695
  );
1368
696
  return sendHardReloadInstruction === true;
1369
697
  };
1370
- var buildDynamicPage = async (DIST_DIR2, directory, pageInfo, req, res) => {
698
+ const buildDynamicPage = async (DIST_DIR2, directory, pageInfo, req, res, middlewareData) => {
1371
699
  directory = directory === "/" ? "" : directory;
1372
700
  const filePath = pageInfo.filePath;
1373
701
  initializeState();
@@ -1378,12 +706,10 @@ var buildDynamicPage = async (DIST_DIR2, directory, pageInfo, req, res) => {
1378
706
  let metadata = async (props) => html();
1379
707
  let modules = {};
1380
708
  let pageIgnoresLayout = false;
1381
- let isDynamicPage = false;
1382
709
  try {
1383
710
  const {
1384
711
  page,
1385
712
  metadata: pageMetadata,
1386
- isDynamic,
1387
713
  shippedModules: shippedModules2,
1388
714
  ignoreLayout,
1389
715
  requestHook
@@ -1403,9 +729,6 @@ var buildDynamicPage = async (DIST_DIR2, directory, pageInfo, req, res) => {
1403
729
  }
1404
730
  pageElements = page;
1405
731
  metadata = pageMetadata;
1406
- if (isDynamic === true) {
1407
- isDynamicPage = isDynamic;
1408
- }
1409
732
  } catch (e) {
1410
733
  throw new Error(`Error in Page: ${directory}/page.ts - ${e}`);
1411
734
  }
@@ -1421,7 +744,8 @@ var buildDynamicPage = async (DIST_DIR2, directory, pageInfo, req, res) => {
1421
744
  console.warn(`WARNING: ${filePath} should export a const page, which is of type () => BuiltElement<"body">.`);
1422
745
  }
1423
746
  const pageProps = {
1424
- pageName: directory
747
+ pageName: directory,
748
+ middlewareData
1425
749
  };
1426
750
  if (typeof pageElements === "function") {
1427
751
  if (pageElements.constructor.name === "AsyncFunction") {
@@ -1445,7 +769,7 @@ var buildDynamicPage = async (DIST_DIR2, directory, pageInfo, req, res) => {
1445
769
  await shipModules();
1446
770
  return { resultHTML };
1447
771
  };
1448
- var shipModules = async () => {
772
+ const shipModules = async () => {
1449
773
  for (const plugin of modulesToShip) {
1450
774
  {
1451
775
  if (shippedModules.has(plugin.globalName)) continue;
@@ -1464,20 +788,12 @@ var shipModules = async () => {
1464
788
  }
1465
789
  modulesToShip = [];
1466
790
  };
1467
- var build = async () => {
1468
- if (options.quiet === true) {
1469
- console.log = function() {
1470
- };
1471
- console.error = function() {
1472
- };
1473
- console.warn = function() {
1474
- };
1475
- }
791
+ const build = async () => {
1476
792
  try {
1477
793
  {
1478
- log2(bold(yellow(" -- Elegance.JS -- ")));
794
+ log(bold(yellow(" -- Elegance.JS -- ")));
1479
795
  if (options.environment === "production") {
1480
- log2(
796
+ log(
1481
797
  " - ",
1482
798
  bgYellow(bold(black(" NOTE "))),
1483
799
  " : ",
@@ -1485,7 +801,7 @@ var build = async () => {
1485
801
  underline("console.log() "),
1486
802
  white("statements will be shown on the client, and all code will be minified.")
1487
803
  );
1488
- log2("");
804
+ log("");
1489
805
  }
1490
806
  }
1491
807
  if (options.preCompile) {
@@ -1506,28 +822,19 @@ var build = async () => {
1506
822
  await buildClient(DIST_DIR);
1507
823
  const end = performance.now();
1508
824
  if (options.publicDirectory) {
1509
- log2("Recursively copying public directory.. this may take a while.");
825
+ log("Recursively copying public directory.. this may take a while.");
1510
826
  const src = path.relative(process.cwd(), options.publicDirectory.path);
1511
- if (fs2.existsSync(src) === false) {
827
+ if (fs.existsSync(src) === false) {
1512
828
  console.warn("WARNING: Public directory not found, an attempt will be made create it..");
1513
- fs2.mkdirSync(src, { recursive: true });
829
+ fs.mkdirSync(src, { recursive: true });
1514
830
  }
1515
- await fs2.promises.cp(src, path.join(DIST_DIR), { recursive: true });
831
+ await fs.promises.cp(src, path.join(DIST_DIR), { recursive: true });
1516
832
  }
1517
833
  {
1518
- log2(`Took ${Math.round(pagesBuilt - start)}ms to Build Pages.`);
1519
- log2(`Took ${Math.round(end - pagesBuilt)}ms to Build Client.`);
1520
- }
1521
- if (options.server != void 0 && options.server.runServer == true) {
1522
- startServer({
1523
- root: options.server.root ?? DIST_DIR,
1524
- environment: options.environment,
1525
- port: options.server.port ?? 3e3,
1526
- host: options.server.host ?? "localhost",
1527
- DIST_DIR,
1528
- pagesDirectory: options.pagesDirectory
1529
- });
834
+ log(`Took ${Math.round(pagesBuilt - start)}ms to Build Pages.`);
835
+ log(`Took ${Math.round(end - pagesBuilt)}ms to Build Client.`);
1530
836
  }
837
+ process.send?.({ event: "message", data: "set-pages-and-layouts", content: JSON.stringify({ pageMap: Array.from(PAGE_MAP), layoutMap: Array.from(LAYOUT_MAP) }) });
1531
838
  process.send?.({ event: "message", data: "compile-finish" });
1532
839
  if (shouldClientHardReload) {
1533
840
  process.send({ event: "message", data: "hard-reload" });
@@ -1542,11 +849,9 @@ var build = async () => {
1542
849
  return true;
1543
850
  };
1544
851
  (async () => {
1545
- await build();
852
+ if (process.env.DO_BUILD === "true") await build();
1546
853
  })();
1547
854
  export {
1548
- LAYOUT_MAP2 as LAYOUT_MAP,
1549
- PAGE_MAP,
1550
855
  buildDynamicPage,
1551
856
  processPageElements
1552
857
  };