elegance-js 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/README.md +4 -0
  2. package/dist/build.d.ts +22 -0
  3. package/dist/build.mjs +1060 -0
  4. package/dist/client/client.d.ts +1 -0
  5. package/dist/client/client.mjs +272 -0
  6. package/dist/client/watcher.d.ts +1 -0
  7. package/dist/client/watcher.mjs +26 -0
  8. package/dist/compile_docs.d.ts +1 -0
  9. package/dist/compile_docs.mjs +1087 -0
  10. package/dist/components/Breakpoint.d.ts +3 -0
  11. package/dist/components/Breakpoint.mjs +17 -0
  12. package/dist/components/Link.d.ts +1 -0
  13. package/dist/components/Link.mjs +116 -0
  14. package/dist/docs/components/Header.d.ts +1 -0
  15. package/dist/docs/components/Header.mjs +219 -0
  16. package/dist/docs/components/RootLayout.d.ts +1 -0
  17. package/dist/docs/components/RootLayout.mjs +10 -0
  18. package/dist/docs/docs/basics/page.d.ts +2 -0
  19. package/dist/docs/docs/basics/page.mjs +1174 -0
  20. package/dist/docs/docs/compilations/page.d.ts +2 -0
  21. package/dist/docs/docs/compilations/page.mjs +15 -0
  22. package/dist/docs/docs/components/CodeBlock.d.ts +2 -0
  23. package/dist/docs/docs/components/CodeBlock.mjs +316 -0
  24. package/dist/docs/docs/components/DocsLayout.d.ts +1 -0
  25. package/dist/docs/docs/components/DocsLayout.mjs +465 -0
  26. package/dist/docs/docs/components/Header.d.ts +1 -0
  27. package/dist/docs/docs/components/Header.mjs +163 -0
  28. package/dist/docs/docs/components/Mono.d.ts +1 -0
  29. package/dist/docs/docs/components/Mono.mjs +7 -0
  30. package/dist/docs/docs/components/PageHeading.d.ts +1 -0
  31. package/dist/docs/docs/components/PageHeading.mjs +9 -0
  32. package/dist/docs/docs/components/Paragraph.d.ts +1 -0
  33. package/dist/docs/docs/components/Paragraph.mjs +10 -0
  34. package/dist/docs/docs/components/Separator.d.ts +1 -0
  35. package/dist/docs/docs/components/Separator.mjs +7 -0
  36. package/dist/docs/docs/components/SubHeading.d.ts +1 -0
  37. package/dist/docs/docs/components/SubHeading.mjs +8 -0
  38. package/dist/docs/docs/components/SubSeparator.d.ts +1 -0
  39. package/dist/docs/docs/components/SubSeparator.mjs +7 -0
  40. package/dist/docs/docs/components/Subtext.d.ts +1 -0
  41. package/dist/docs/docs/components/Subtext.mjs +8 -0
  42. package/dist/docs/docs/concepts/page.d.ts +2 -0
  43. package/dist/docs/docs/concepts/page.mjs +892 -0
  44. package/dist/docs/docs/page-files/page.d.ts +2 -0
  45. package/dist/docs/docs/page-files/page.mjs +1144 -0
  46. package/dist/docs/docs/page.d.ts +2 -0
  47. package/dist/docs/docs/page.mjs +49 -0
  48. package/dist/docs/docs/route.d.ts +2 -0
  49. package/dist/docs/docs/route.mjs +8 -0
  50. package/dist/docs/docs/running/page.d.ts +2 -0
  51. package/dist/docs/docs/running/page.mjs +7 -0
  52. package/dist/docs/nullpage/page.d.ts +2 -0
  53. package/dist/docs/nullpage/page.mjs +52 -0
  54. package/dist/docs/page.d.ts +2 -0
  55. package/dist/docs/page.mjs +405 -0
  56. package/dist/docs/utils/MEGALEXER.d.ts +1 -0
  57. package/dist/docs/utils/MEGALEXER.mjs +171 -0
  58. package/dist/global.d.ts +290 -0
  59. package/dist/global.mjs +0 -0
  60. package/dist/helpers/ObjectAttributeType.d.ts +7 -0
  61. package/dist/helpers/ObjectAttributeType.mjs +12 -0
  62. package/dist/helpers/camelToKebab.d.ts +1 -0
  63. package/dist/helpers/camelToKebab.mjs +7 -0
  64. package/dist/index.d.ts +0 -0
  65. package/dist/index.mjs +0 -0
  66. package/dist/server/createReference.d.ts +6 -0
  67. package/dist/server/createReference.mjs +18 -0
  68. package/dist/server/createState.d.ts +47 -0
  69. package/dist/server/createState.mjs +50 -0
  70. package/dist/server/generateHTMLTemplate.d.ts +7 -0
  71. package/dist/server/generateHTMLTemplate.mjs +222 -0
  72. package/dist/server/layout.d.ts +3 -0
  73. package/dist/server/layout.mjs +17 -0
  74. package/dist/server/loadHook.d.ts +29 -0
  75. package/dist/server/loadHook.mjs +28 -0
  76. package/dist/server/observe.d.ts +19 -0
  77. package/dist/server/observe.mjs +16 -0
  78. package/dist/server/pageShimmer.d.ts +2 -0
  79. package/dist/server/pageShimmer.mjs +5 -0
  80. package/dist/server/render.d.ts +5 -0
  81. package/dist/server/render.mjs +210 -0
  82. package/dist/server/server.d.ts +9 -0
  83. package/dist/server/server.mjs +184 -0
  84. package/dist/shared/bindServerElements.d.ts +1 -0
  85. package/dist/shared/bindServerElements.mjs +145 -0
  86. package/dist/shared/serverElements.d.ts +11 -0
  87. package/dist/shared/serverElements.mjs +165 -0
  88. package/dist/types/Metadata.d.ts +19 -0
  89. package/dist/types/Metadata.mjs +15 -0
  90. package/package.json +38 -0
  91. package/scripts/dev.js +25 -0
  92. package/scripts/export.js +20 -0
  93. package/scripts/prod.js +21 -0
package/dist/build.mjs ADDED
@@ -0,0 +1,1060 @@
1
+ // src/build.ts
2
+ import fs2 from "fs";
3
+ import path from "path";
4
+ import esbuild from "esbuild";
5
+ import { fileURLToPath } from "url";
6
+
7
+ // src/shared/serverElements.ts
8
+ var createBuildableElement = (tag) => {
9
+ return (options2, ...children) => ({
10
+ tag,
11
+ options: options2 || {},
12
+ children
13
+ });
14
+ };
15
+ var createChildrenlessBuildableElement = (tag) => {
16
+ return (options2) => ({
17
+ tag,
18
+ options: options2 || {},
19
+ children: null
20
+ });
21
+ };
22
+ var childrenlessElementTags = [
23
+ "area",
24
+ "base",
25
+ "br",
26
+ "col",
27
+ "embed",
28
+ "hr",
29
+ "img",
30
+ "input",
31
+ "link",
32
+ "meta",
33
+ "source",
34
+ "track",
35
+ "path",
36
+ "rect"
37
+ ];
38
+ var elementTags = [
39
+ "a",
40
+ "address",
41
+ "article",
42
+ "aside",
43
+ "audio",
44
+ "blockquote",
45
+ "body",
46
+ "button",
47
+ "canvas",
48
+ "caption",
49
+ "colgroup",
50
+ "data",
51
+ "datalist",
52
+ "dd",
53
+ "del",
54
+ "details",
55
+ "dialog",
56
+ "div",
57
+ "dl",
58
+ "dt",
59
+ "fieldset",
60
+ "figcaption",
61
+ "figure",
62
+ "footer",
63
+ "form",
64
+ "h1",
65
+ "h2",
66
+ "h3",
67
+ "h4",
68
+ "h5",
69
+ "h6",
70
+ "head",
71
+ "header",
72
+ "hgroup",
73
+ "html",
74
+ "iframe",
75
+ "ins",
76
+ "label",
77
+ "legend",
78
+ "li",
79
+ "main",
80
+ "map",
81
+ "meter",
82
+ "nav",
83
+ "noscript",
84
+ "object",
85
+ "ol",
86
+ "optgroup",
87
+ "option",
88
+ "output",
89
+ "p",
90
+ "picture",
91
+ "pre",
92
+ "progress",
93
+ "q",
94
+ "section",
95
+ "select",
96
+ "summary",
97
+ "table",
98
+ "tbody",
99
+ "td",
100
+ "template",
101
+ "textarea",
102
+ "tfoot",
103
+ "th",
104
+ "thead",
105
+ "time",
106
+ "tr",
107
+ "ul",
108
+ "video",
109
+ "span",
110
+ "script",
111
+ "abbr",
112
+ "b",
113
+ "bdi",
114
+ "bdo",
115
+ "cite",
116
+ "code",
117
+ "dfn",
118
+ "em",
119
+ "i",
120
+ "kbd",
121
+ "mark",
122
+ "rp",
123
+ "rt",
124
+ "ruby",
125
+ "s",
126
+ "samp",
127
+ "small",
128
+ "strong",
129
+ "sub",
130
+ "sup",
131
+ "u",
132
+ "wbr",
133
+ "title",
134
+ "svg"
135
+ ];
136
+ var elements = {};
137
+ var childrenlessElements = {};
138
+ for (const element of elementTags) {
139
+ elements[element] = createBuildableElement(element);
140
+ }
141
+ for (const element of childrenlessElementTags) {
142
+ childrenlessElements[element] = createChildrenlessBuildableElement(element);
143
+ }
144
+ var allElements = {
145
+ ...elements,
146
+ ...childrenlessElements
147
+ };
148
+
149
+ // src/shared/bindServerElements.ts
150
+ Object.assign(globalThis, elements);
151
+ Object.assign(globalThis, childrenlessElements);
152
+
153
+ // src/server/render.ts
154
+ var renderRecursively = (element) => {
155
+ let returnString = "";
156
+ if (typeof element === "boolean") return returnString;
157
+ else if (typeof element === "number" || typeof element === "string") {
158
+ return returnString + element;
159
+ } else if (Array.isArray(element)) {
160
+ return returnString + element.join(", ");
161
+ }
162
+ returnString += `<${element.tag}`;
163
+ const {
164
+ tag: elementTag,
165
+ options: elementOptions,
166
+ children: elementChildren
167
+ } = element.options;
168
+ if (elementTag && elementOptions && elementChildren) {
169
+ const children = element.children;
170
+ element.children = [
171
+ element.options,
172
+ ...children
173
+ ];
174
+ element.options = {};
175
+ for (let i = 0; i < children.length + 1; i++) {
176
+ const child = element.children[i];
177
+ returnString += renderRecursively(child);
178
+ }
179
+ returnString += `</${element.tag}>`;
180
+ return returnString;
181
+ }
182
+ if (typeof element.options === "object") {
183
+ for (const [attrName, attrValue] of Object.entries(element.options)) {
184
+ if (typeof attrValue === "object") {
185
+ throw `Attr ${attrName}, for element ${element.tag} has obj type. Got: ${JSON.stringify(element)}`;
186
+ }
187
+ returnString += ` ${attrName.toLowerCase()}="${attrValue}"`;
188
+ }
189
+ }
190
+ if (element.children === null) {
191
+ returnString += "/>";
192
+ return returnString;
193
+ }
194
+ returnString += ">";
195
+ for (const child of element.children) {
196
+ returnString += renderRecursively(child);
197
+ }
198
+ returnString += `</${element.tag}>`;
199
+ return returnString;
200
+ };
201
+ var serverSideRenderPage = async (page, pathname) => {
202
+ if (!page) {
203
+ throw `No Page Provided.`;
204
+ }
205
+ if (typeof page === "function") {
206
+ throw `Unbuilt page provided to ssr page.`;
207
+ }
208
+ const bodyHTML = renderRecursively(page);
209
+ return {
210
+ bodyHTML
211
+ };
212
+ };
213
+
214
+ // src/server/generateHTMLTemplate.ts
215
+ var generateHTMLTemplate = ({
216
+ pageURL,
217
+ head: head2,
218
+ serverData = null,
219
+ addPageScriptTag = true,
220
+ name
221
+ }) => {
222
+ let HTMLTemplate = `<head><meta name="viewport" content="width=device-width, initial-scale=1.0">`;
223
+ HTMLTemplate += '<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests"><meta charset="UTF-8">';
224
+ if (addPageScriptTag === true) {
225
+ HTMLTemplate += `<script data-tag="true" type="module" src="${pageURL === "" ? "" : "/"}${pageURL}/${name}_data.js" defer="true"></script>`;
226
+ }
227
+ HTMLTemplate += `<script stype="module" src="/client.js" defer="true"></script>`;
228
+ const builtHead = head2();
229
+ for (const child of builtHead.children) {
230
+ HTMLTemplate += renderRecursively(child);
231
+ }
232
+ if (serverData) {
233
+ HTMLTemplate += serverData;
234
+ }
235
+ HTMLTemplate += "</head>";
236
+ return HTMLTemplate;
237
+ };
238
+
239
+ // src/build.ts
240
+ import http from "http";
241
+
242
+ // src/server/createState.ts
243
+ if (!globalThis.__SERVER_CURRENT_STATE_ID__) {
244
+ globalThis.__SERVER_CURRENT_STATE_ID__ = 0;
245
+ }
246
+ var currentId = globalThis.__SERVER_CURRENT_STATE_ID__;
247
+ var initializeState = () => globalThis.__SERVER_CURRENT_STATE__ = [];
248
+ var getState = () => {
249
+ return globalThis.__SERVER_CURRENT_STATE__;
250
+ };
251
+
252
+ // src/server/loadHook.ts
253
+ var resetLoadHooks = () => globalThis.__SERVER_CURRENT_LOADHOOKS__ = [];
254
+ var getLoadHooks = () => globalThis.__SERVER_CURRENT_LOADHOOKS__;
255
+
256
+ // src/server/layout.ts
257
+ var resetLayouts = () => globalThis.__SERVER_CURRENT_LAYOUTS__ = /* @__PURE__ */ new Map();
258
+ if (!globalThis.__SERVER_CURRENT_LAYOUT_ID__) globalThis.__SERVER_CURRENT_LAYOUT_ID__ = 1;
259
+ var layoutId = globalThis.__SERVER_CURRENT_LAYOUT_ID__;
260
+
261
+ // src/server/server.ts
262
+ import { createServer as createHttpServer } from "http";
263
+ import { promises as fs } from "fs";
264
+ import { join, normalize, extname, dirname } from "path";
265
+ import { pathToFileURL } from "url";
266
+ var MIME_TYPES = {
267
+ ".html": "text/html; charset=utf-8",
268
+ ".css": "text/css; charset=utf-8",
269
+ ".js": "application/javascript; charset=utf-8",
270
+ ".json": "application/json; charset=utf-8",
271
+ ".png": "image/png",
272
+ ".jpg": "image/jpeg",
273
+ ".jpeg": "image/jpeg",
274
+ ".gif": "image/gif",
275
+ ".svg": "image/svg+xml",
276
+ ".ico": "image/x-icon",
277
+ ".txt": "text/plain; charset=utf-8"
278
+ };
279
+ function startServer({ root, port = 3e3, host = "0.0.0.0", environment = "production" }) {
280
+ if (!root) throw new Error("Root directory must be specified.");
281
+ const requestHandler = async (req, res) => {
282
+ try {
283
+ if (!req.url) {
284
+ res.writeHead(400, { "Content-Type": "text/plain; charset=utf-8" });
285
+ res.end("Bad Request");
286
+ return;
287
+ }
288
+ res.setHeader("Access-Control-Allow-Origin", "*");
289
+ res.setHeader("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS");
290
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
291
+ if (req.method === "OPTIONS") {
292
+ res.writeHead(204);
293
+ res.end();
294
+ if (environment === "development") {
295
+ console.log(req.method, "::", req.url, "-", res.statusCode);
296
+ }
297
+ return;
298
+ }
299
+ const url = new URL(req.url, `https://${req.headers.host}`);
300
+ if (url.pathname.startsWith("/api/")) {
301
+ await handleApiRequest(root, url.pathname, req, res);
302
+ } else {
303
+ await handleStaticRequest(root, url.pathname, res);
304
+ }
305
+ if (environment === "development") {
306
+ console.log(req.method, "::", req.url, "-", res.statusCode);
307
+ }
308
+ } catch (err) {
309
+ console.error(err);
310
+ res.writeHead(500, { "Content-Type": "text/plain; charset=utf-8" });
311
+ res.end("Internal Server Error");
312
+ }
313
+ };
314
+ let server = createHttpServer(requestHandler);
315
+ server.listen(port, host, () => {
316
+ console.log(`Server running at https://${host}:${port}/`);
317
+ });
318
+ return server;
319
+ }
320
+ async function handleStaticRequest(root, pathname, res) {
321
+ let filePath = normalize(join(root, decodeURIComponent(pathname)));
322
+ root = normalize(root);
323
+ if (!filePath.startsWith(root)) {
324
+ res.writeHead(403, { "Content-Type": "text/plain; charset=utf-8" });
325
+ res.end("Forbidden");
326
+ return;
327
+ }
328
+ try {
329
+ const stats = await fs.stat(filePath);
330
+ if (stats.isDirectory()) {
331
+ filePath = join(filePath, "index.html");
332
+ }
333
+ } catch {
334
+ }
335
+ try {
336
+ const ext = extname(filePath).toLowerCase();
337
+ const contentType = MIME_TYPES[ext] || "application/octet-stream";
338
+ const data = await fs.readFile(filePath);
339
+ res.writeHead(200, { "Content-Type": contentType });
340
+ res.end(data);
341
+ } catch {
342
+ await respondWithErrorPage(root, pathname, 404, res);
343
+ }
344
+ }
345
+ async function handleApiRequest(root, pathname, req, res) {
346
+ const routePath = join(root, pathname, "route.js");
347
+ try {
348
+ await fs.access(routePath);
349
+ } catch {
350
+ res.writeHead(404, { "Content-Type": "application/json; charset=utf-8" });
351
+ res.end(JSON.stringify({ error: "Not found" }));
352
+ return;
353
+ }
354
+ try {
355
+ const moduleUrl = pathToFileURL(routePath).href;
356
+ const { GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE, CONNECT } = await import(moduleUrl);
357
+ let fn;
358
+ switch (req.method) {
359
+ case "GET":
360
+ fn = GET;
361
+ break;
362
+ case "HEAD":
363
+ fn = HEAD;
364
+ break;
365
+ case "POST":
366
+ fn = POST;
367
+ break;
368
+ case "PUT":
369
+ fn = PUT;
370
+ break;
371
+ case "PATCH":
372
+ fn = PATCH;
373
+ break;
374
+ case "DELETE":
375
+ fn = DELETE;
376
+ break;
377
+ case "OPTIONS":
378
+ fn = OPTIONS;
379
+ break;
380
+ case "TRACE":
381
+ fn = TRACE;
382
+ break;
383
+ case "CONNECT":
384
+ fn = CONNECT;
385
+ break;
386
+ default:
387
+ fn = null;
388
+ return;
389
+ }
390
+ if (fn === null) {
391
+ res.writeHead(404, { "Content-Type": "application/json; charset=utf-8" });
392
+ res.end(JSON.stringify({ error: "Unsupported method for route." }));
393
+ return;
394
+ }
395
+ if (typeof fn !== "function") {
396
+ throw new Error('API route module must export a "route" function.');
397
+ }
398
+ await fn(req, res);
399
+ } catch {
400
+ await respondWithErrorPage(root, pathname, 404, res);
401
+ }
402
+ }
403
+ async function respondWithErrorPage(root, pathname, code, res) {
404
+ let currentPath = normalize(join(root, decodeURIComponent(pathname)));
405
+ let tried = /* @__PURE__ */ new Set();
406
+ let errorFilePath = null;
407
+ while (currentPath.startsWith(root)) {
408
+ const candidate = join(currentPath, `${code}.html`);
409
+ if (!tried.has(candidate)) {
410
+ try {
411
+ await fs.access(candidate);
412
+ errorFilePath = candidate;
413
+ break;
414
+ } catch {
415
+ }
416
+ tried.add(candidate);
417
+ }
418
+ const parent = dirname(currentPath);
419
+ if (parent === currentPath) break;
420
+ currentPath = parent;
421
+ }
422
+ if (!errorFilePath) {
423
+ const fallback = join(root, `${code}.html`);
424
+ try {
425
+ await fs.access(fallback);
426
+ errorFilePath = fallback;
427
+ } catch {
428
+ }
429
+ }
430
+ if (errorFilePath) {
431
+ try {
432
+ const html = await fs.readFile(errorFilePath);
433
+ res.writeHead(code, { "Content-Type": "text/html; charset=utf-8" });
434
+ res.end(html);
435
+ return;
436
+ } catch {
437
+ }
438
+ }
439
+ res.writeHead(code, { "Content-Type": "text/plain; charset=utf-8" });
440
+ res.end(`${code} Error`);
441
+ }
442
+
443
+ // src/build.ts
444
+ var __filename = fileURLToPath(import.meta.url);
445
+ var __dirname = path.dirname(__filename);
446
+ var packageDir = path.resolve(__dirname, "..");
447
+ var clientPath = path.resolve(packageDir, "./src/client/client.ts");
448
+ var watcherPath = path.resolve(packageDir, "./src/client/watcher.ts");
449
+ var yellow = (text) => {
450
+ return `\x1B[38;2;238;184;68m${text}`;
451
+ };
452
+ var black = (text) => {
453
+ return `\x1B[38;2;0;0;0m${text}`;
454
+ };
455
+ var bgYellow = (text) => {
456
+ return `\x1B[48;2;238;184;68m${text}`;
457
+ };
458
+ var bold = (text) => {
459
+ return `\x1B[1m${text}`;
460
+ };
461
+ var underline = (text) => {
462
+ return `\x1B[4m${text}`;
463
+ };
464
+ var white = (text) => {
465
+ return `\x1B[38;2;255;247;229m${text}`;
466
+ };
467
+ var green = (text) => {
468
+ return `\x1B[38;2;65;224;108m${text}`;
469
+ };
470
+ var log = (...text) => {
471
+ return console.log(text.map((text2) => `${text2}\x1B[0m`).join(""));
472
+ };
473
+ var getAllSubdirectories = (dir, baseDir = dir) => {
474
+ let directories = [];
475
+ const items = fs2.readdirSync(dir, { withFileTypes: true });
476
+ for (const item of items) {
477
+ if (item.isDirectory()) {
478
+ const fullPath = path.join(dir, item.name);
479
+ const relativePath = path.relative(baseDir, fullPath);
480
+ directories.push(relativePath);
481
+ directories = directories.concat(getAllSubdirectories(fullPath, baseDir));
482
+ }
483
+ }
484
+ return directories;
485
+ };
486
+ var getProjectFiles = (pagesDirectory) => {
487
+ const pageFiles = [];
488
+ const apiFiles = [];
489
+ const subdirectories = [...getAllSubdirectories(pagesDirectory), ""];
490
+ for (const subdirectory of subdirectories) {
491
+ const absoluteDirectoryPath = path.join(pagesDirectory, subdirectory);
492
+ const subdirectoryFiles = fs2.readdirSync(absoluteDirectoryPath, { withFileTypes: true }).filter((f) => f.name.endsWith(".js") || f.name.endsWith(".ts"));
493
+ for (const file of subdirectoryFiles) {
494
+ if (file.name === "route.ts") {
495
+ apiFiles.push(file);
496
+ continue;
497
+ } else if (file.name === "page.ts") {
498
+ pageFiles.push(file);
499
+ continue;
500
+ }
501
+ const name = file.name.slice(0, file.name.length - 3);
502
+ const numberName = parseInt(name);
503
+ if (isNaN(numberName) === false) {
504
+ if (numberName >= 400 && numberName <= 599) {
505
+ pageFiles.push(file);
506
+ continue;
507
+ }
508
+ }
509
+ }
510
+ }
511
+ return {
512
+ pageFiles,
513
+ apiFiles
514
+ };
515
+ };
516
+ var buildClient = async (DIST_DIR) => {
517
+ let clientString = "window.__name = (func) => func; ";
518
+ clientString += fs2.readFileSync(clientPath, "utf-8");
519
+ if (options.hotReload !== void 0) {
520
+ clientString += `const watchServerPort = ${options.hotReload.port}`;
521
+ clientString += fs2.readFileSync(watcherPath, "utf-8");
522
+ }
523
+ const transformedClient = await esbuild.transform(clientString, {
524
+ minify: options.environment === "production",
525
+ drop: options.environment === "production" ? ["console", "debugger"] : void 0,
526
+ keepNames: false,
527
+ format: "iife",
528
+ platform: "node",
529
+ loader: "ts"
530
+ });
531
+ fs2.writeFileSync(
532
+ path.join(DIST_DIR, "/client.js"),
533
+ transformedClient.code
534
+ );
535
+ };
536
+ var elementKey = 0;
537
+ var processOptionAsObjectAttribute = (element, optionName, optionValue, objectAttributes) => {
538
+ const lcOptionName = optionName.toLowerCase();
539
+ const options2 = element.options;
540
+ let key = options2.key;
541
+ if (key == void 0) {
542
+ key = elementKey += 1;
543
+ options2.key = key;
544
+ }
545
+ if (!optionValue.type) {
546
+ throw `ObjectAttributeType is missing from object attribute. ${element.tag}: ${optionName}/${optionValue}`;
547
+ }
548
+ let optionFinal = lcOptionName;
549
+ switch (optionValue.type) {
550
+ case 1 /* STATE */:
551
+ const SOA = optionValue;
552
+ if (typeof SOA.value === "function") {
553
+ delete options2[optionName];
554
+ break;
555
+ }
556
+ if (lcOptionName === "innertext" || lcOptionName === "innerhtml") {
557
+ element.children = [SOA.value];
558
+ delete options2[optionName];
559
+ } else {
560
+ delete options2[optionName];
561
+ options2[lcOptionName] = SOA.value;
562
+ }
563
+ break;
564
+ case 2 /* OBSERVER */:
565
+ const OOA = optionValue;
566
+ const firstValue = OOA.update(...OOA.initialValues);
567
+ if (lcOptionName === "innertext" || lcOptionName === "innerhtml") {
568
+ element.children = [firstValue];
569
+ delete options2[optionName];
570
+ } else {
571
+ delete options2[optionName];
572
+ options2[lcOptionName] = firstValue;
573
+ }
574
+ optionFinal = optionName;
575
+ break;
576
+ case 4 /* REFERENCE */:
577
+ options2["ref"] = optionValue.value;
578
+ break;
579
+ }
580
+ objectAttributes.push({ ...optionValue, key, attribute: optionFinal });
581
+ };
582
+ var processPageElements = (element, objectAttributes, parent) => {
583
+ if (typeof element === "boolean" || typeof element === "number" || Array.isArray(element)) return element;
584
+ if (typeof element === "string") {
585
+ return element;
586
+ }
587
+ const processElementOptionsAsChildAndReturn = () => {
588
+ const children = element.children;
589
+ element.children = [
590
+ element.options,
591
+ ...children
592
+ ];
593
+ element.options = {};
594
+ for (let i = 0; i < children.length + 1; i++) {
595
+ const child = element.children[i];
596
+ const processedChild = processPageElements(child, objectAttributes, element);
597
+ element.children[i] = processedChild;
598
+ }
599
+ return {
600
+ ...element,
601
+ options: {}
602
+ };
603
+ };
604
+ if (typeof element.options !== "object") {
605
+ return processElementOptionsAsChildAndReturn();
606
+ }
607
+ const {
608
+ tag: elementTag,
609
+ options: elementOptions,
610
+ children: elementChildren
611
+ } = element.options;
612
+ if (elementTag && elementOptions && elementChildren) {
613
+ return processElementOptionsAsChildAndReturn();
614
+ }
615
+ const options2 = element.options;
616
+ for (const [optionName, optionValue] of Object.entries(options2)) {
617
+ const lcOptionName = optionName.toLowerCase();
618
+ if (typeof optionValue !== "object") {
619
+ if (lcOptionName === "innertext") {
620
+ delete options2[optionName];
621
+ if (element.children === null) {
622
+ throw `Cannot use innerText or innerHTML on childrenless elements.`;
623
+ }
624
+ element.children = [optionValue, ...element.children];
625
+ continue;
626
+ } else if (lcOptionName === "innerhtml") {
627
+ if (element.children === null) {
628
+ throw `Cannot use innerText or innerHTML on childrenless elements.`;
629
+ }
630
+ delete options2[optionName];
631
+ element.children = [optionValue];
632
+ continue;
633
+ }
634
+ continue;
635
+ }
636
+ ;
637
+ processOptionAsObjectAttribute(element, optionName, optionValue, objectAttributes);
638
+ }
639
+ if (element.children) {
640
+ for (let i = 0; i < element.children.length; i++) {
641
+ const child = element.children[i];
642
+ const processedChild = processPageElements(child, objectAttributes, element);
643
+ element.children[i] = processedChild;
644
+ }
645
+ }
646
+ return element;
647
+ };
648
+ var generateSuitablePageElements = async (pageLocation, pageElements, metadata, DIST_DIR, pageName) => {
649
+ if (typeof pageElements === "string" || typeof pageElements === "boolean" || typeof pageElements === "number" || Array.isArray(pageElements)) {
650
+ return [];
651
+ }
652
+ const objectAttributes = [];
653
+ const processedPageElements = processPageElements(pageElements, objectAttributes, []);
654
+ elementKey = 0;
655
+ const renderedPage = await serverSideRenderPage(
656
+ processedPageElements,
657
+ pageLocation
658
+ );
659
+ const template = generateHTMLTemplate({
660
+ pageURL: path.relative(DIST_DIR, pageLocation),
661
+ head: metadata,
662
+ addPageScriptTag: true,
663
+ name: pageName
664
+ });
665
+ const resultHTML = `<!DOCTYPE html><html>${template}${renderedPage.bodyHTML}</html>`;
666
+ const htmlLocation = path.join(pageLocation, (pageName === "page" ? "index" : pageName) + ".html");
667
+ fs2.writeFileSync(
668
+ htmlLocation,
669
+ resultHTML,
670
+ {
671
+ encoding: "utf-8",
672
+ flag: "w"
673
+ }
674
+ );
675
+ return objectAttributes;
676
+ };
677
+ var generateClientPageData = async (pageLocation, state, objectAttributes, pageLoadHooks, DIST_DIR, pageName) => {
678
+ const pageDiff = path.relative(DIST_DIR, pageLocation);
679
+ let clientPageJSText = `let url="${pageDiff === "" ? "/" : `/${pageDiff}`}";`;
680
+ {
681
+ clientPageJSText += `export const data = {`;
682
+ if (state) {
683
+ const nonBoundState = state.filter((subj) => subj.bind === void 0);
684
+ clientPageJSText += `state:[`;
685
+ for (const subject of nonBoundState) {
686
+ if (typeof subject.value === "string") {
687
+ const stringified = JSON.stringify(subject.value);
688
+ clientPageJSText += `{id:${subject.id},value:${stringified}},`;
689
+ } else if (typeof subject.value === "function") {
690
+ clientPageJSText += `{id:${subject.id},value:${subject.value.toString()}},`;
691
+ } else {
692
+ clientPageJSText += `{id:${subject.id},value:${JSON.stringify(subject.value)}},`;
693
+ }
694
+ }
695
+ clientPageJSText += `],`;
696
+ const formattedBoundState = {};
697
+ const stateBinds = state.map((subj) => subj.bind).filter((bind) => bind !== void 0);
698
+ for (const bind of stateBinds) {
699
+ formattedBoundState[bind] = [];
700
+ }
701
+ ;
702
+ const boundState = state.filter((subj) => subj.bind !== void 0);
703
+ for (const subject of boundState) {
704
+ const bindingState = formattedBoundState[subject.bind];
705
+ delete subject.bind;
706
+ bindingState.push(subject);
707
+ }
708
+ const bindSubjectPairing = Object.entries(formattedBoundState);
709
+ if (bindSubjectPairing.length > 0) {
710
+ clientPageJSText += "binds:{";
711
+ for (const [bind, subjects] of bindSubjectPairing) {
712
+ clientPageJSText += `${bind}:[`;
713
+ for (const subject of subjects) {
714
+ if (typeof subject.value === "string") {
715
+ clientPageJSText += `{id:${subject.id},value:${JSON.stringify(subject.value)}},`;
716
+ } else {
717
+ clientPageJSText += `{id:${subject.id},value:${JSON.stringify(subject.value)}},`;
718
+ }
719
+ }
720
+ clientPageJSText += "]";
721
+ }
722
+ clientPageJSText += "},";
723
+ }
724
+ }
725
+ const stateObjectAttributes = objectAttributes.filter((oa) => oa.type === 1 /* STATE */);
726
+ if (stateObjectAttributes.length > 0) {
727
+ const processed = [...stateObjectAttributes].map((soa) => {
728
+ delete soa.type;
729
+ return soa;
730
+ });
731
+ clientPageJSText += `soa:${JSON.stringify(processed)},`;
732
+ }
733
+ const observerObjectAttributes = objectAttributes.filter((oa) => oa.type === 2 /* OBSERVER */);
734
+ if (observerObjectAttributes.length > 0) {
735
+ let observerObjectAttributeString = "ooa:[";
736
+ for (const observerObjectAttribute of observerObjectAttributes) {
737
+ const ooa = observerObjectAttribute;
738
+ observerObjectAttributeString += `{key:${ooa.key},attribute:"${ooa.attribute}",update:${ooa.update.toString()},`;
739
+ observerObjectAttributeString += `refs:[`;
740
+ for (const ref of ooa.refs) {
741
+ observerObjectAttributeString += `{id:${ref.id}`;
742
+ if (ref.bind !== void 0) observerObjectAttributeString += `,bind:${ref.bind}`;
743
+ observerObjectAttributeString += "},";
744
+ }
745
+ observerObjectAttributeString += "]},";
746
+ }
747
+ observerObjectAttributeString += "],";
748
+ clientPageJSText += observerObjectAttributeString;
749
+ }
750
+ if (pageLoadHooks.length > 0) {
751
+ clientPageJSText += "lh:[";
752
+ for (const loadHook of pageLoadHooks) {
753
+ const key = loadHook.bind;
754
+ clientPageJSText += `{fn:${loadHook.fn},bind:"${key || ""}"},`;
755
+ }
756
+ clientPageJSText += "],";
757
+ }
758
+ clientPageJSText += `};`;
759
+ }
760
+ clientPageJSText += "if(!globalThis.pd) { globalThis.pd = {}; globalThis.pd[url] = data}";
761
+ const pageDataPath = path.join(pageLocation, `${pageName}_data.js`);
762
+ let sendHardReloadInstruction = false;
763
+ const transformedResult = await esbuild.transform(clientPageJSText, { minify: true }).catch((error) => {
764
+ console.error("Failed to transform client page js!", error);
765
+ });
766
+ if (!transformedResult) return { sendHardReloadInstruction };
767
+ fs2.writeFileSync(pageDataPath, transformedResult.code, "utf-8");
768
+ return { sendHardReloadInstruction };
769
+ };
770
+ var buildPages = async (DIST_DIR) => {
771
+ resetLayouts();
772
+ const subdirectories = [...getAllSubdirectories(DIST_DIR), ""];
773
+ let shouldClientHardReload = false;
774
+ for (const directory of subdirectories) {
775
+ const abs = path.resolve(path.join(DIST_DIR, directory));
776
+ const files = fs2.readdirSync(abs, { withFileTypes: true }).filter((f) => f.name.endsWith(".js"));
777
+ for (const file of files) {
778
+ const filePath = path.join(file.parentPath, file.name);
779
+ const name = file.name.slice(0, file.name.length - 3);
780
+ const tempPath = file.parentPath + "/" + Date.now().toString() + ".mjs";
781
+ await fs2.promises.copyFile(filePath, tempPath);
782
+ const bytes = fs2.readFileSync(tempPath);
783
+ const isPage = bytes.toString().startsWith("//__ELEGANCE_JS_PAGE_MARKER__");
784
+ if (isPage == false) {
785
+ fs2.rmSync(tempPath, { force: true });
786
+ continue;
787
+ }
788
+ fs2.rmSync(filePath, { force: true });
789
+ initializeState();
790
+ resetLoadHooks();
791
+ let pageElements;
792
+ let metadata;
793
+ try {
794
+ const {
795
+ page,
796
+ metadata: pageMetadata
797
+ } = await import("file://" + tempPath);
798
+ pageElements = page;
799
+ metadata = pageMetadata;
800
+ } catch (e) {
801
+ fs2.rmSync(tempPath, { force: true });
802
+ throw `Error in Page: ${directory === "" ? "/" : directory}${file.name} - ${e}`;
803
+ }
804
+ fs2.rmSync(tempPath, { force: true });
805
+ if (!metadata || metadata && typeof metadata !== "function") {
806
+ console.warn(`WARNING: ${filePath} does not export a metadata function. This is *highly* recommended.`);
807
+ }
808
+ if (!pageElements) {
809
+ console.warn(`WARNING: ${filePath} should export a const page, which is of type BuiltElement<"body">.`);
810
+ }
811
+ if (typeof pageElements === "function") {
812
+ pageElements = pageElements();
813
+ }
814
+ const state = getState();
815
+ const pageLoadHooks = getLoadHooks();
816
+ const objectAttributes = await generateSuitablePageElements(
817
+ file.parentPath,
818
+ pageElements || body(),
819
+ metadata ?? (() => head()),
820
+ DIST_DIR,
821
+ name
822
+ );
823
+ const {
824
+ sendHardReloadInstruction
825
+ } = await generateClientPageData(
826
+ file.parentPath,
827
+ state || {},
828
+ objectAttributes,
829
+ pageLoadHooks || [],
830
+ DIST_DIR,
831
+ name
832
+ );
833
+ if (sendHardReloadInstruction === true) shouldClientHardReload = true;
834
+ }
835
+ }
836
+ return {
837
+ shouldClientHardReload
838
+ };
839
+ };
840
+ var isTimedOut = false;
841
+ var httpStream;
842
+ var currentWatchers = [];
843
+ var registerListener = async () => {
844
+ const server = http.createServer((req, res) => {
845
+ if (req.url === "/events") {
846
+ log(white("Client listening for changes.."));
847
+ res.writeHead(200, {
848
+ "Content-Type": "text/event-stream",
849
+ "Cache-Control": "no-cache",
850
+ "Connection": "keep-alive",
851
+ "Transfer-Encoding": "chunked",
852
+ "X-Accel-Buffering": "no",
853
+ "Content-Encoding": "none",
854
+ "Access-Control-Allow-Origin": "*",
855
+ "Access-Control-Allow-Methods": "*",
856
+ "Access-Control-Allow-Headers": "*"
857
+ });
858
+ httpStream = res;
859
+ httpStream.write(`data: ping
860
+
861
+ `);
862
+ } else {
863
+ res.writeHead(404, { "Content-Type": "text/plain" });
864
+ res.end("Not Found");
865
+ }
866
+ });
867
+ server.listen(options.hotReload.port, () => {
868
+ log(bold(green("Hot-Reload server online!")));
869
+ });
870
+ };
871
+ var build = async (DIST_DIR) => {
872
+ try {
873
+ {
874
+ log(bold(yellow(" -- Elegance.JS -- ")));
875
+ log(white(`Beginning build at ${(/* @__PURE__ */ new Date()).toLocaleTimeString()}..`));
876
+ log("");
877
+ if (options.environment === "production") {
878
+ log(
879
+ " - ",
880
+ bgYellow(bold(black(" NOTE "))),
881
+ " : ",
882
+ white("In production mode, no "),
883
+ underline("console.log() "),
884
+ white("statements will be shown on the client, and all code will be minified.")
885
+ );
886
+ log("");
887
+ }
888
+ }
889
+ if (options.preCompile) {
890
+ log(
891
+ white("Calling pre-compile hook..")
892
+ );
893
+ options.preCompile();
894
+ }
895
+ const { pageFiles, apiFiles } = getProjectFiles(options.pagesDirectory);
896
+ {
897
+ const existingCompiledPages = [...getAllSubdirectories(DIST_DIR), ""];
898
+ for (const page of existingCompiledPages) {
899
+ const pageFile = pageFiles.find((dir) => path.relative(options.pagesDirectory, dir?.parentPath ?? "") === page);
900
+ const apiFile = apiFiles.find((dir) => path.relative(options.pagesDirectory, dir?.parentPath ?? "") === page);
901
+ if (!pageFile && !apiFile) {
902
+ const dir = path.join(DIST_DIR, page);
903
+ if (fs2.existsSync(dir) === false) {
904
+ continue;
905
+ }
906
+ fs2.rmdirSync(dir, { recursive: true });
907
+ console.log("Deleted old file, ", pageFile);
908
+ }
909
+ }
910
+ }
911
+ const start = performance.now();
912
+ {
913
+ await esbuild.build({
914
+ entryPoints: [
915
+ ...pageFiles.map((page) => path.join(page.parentPath, page.name))
916
+ ],
917
+ minify: options.environment === "production",
918
+ drop: options.environment === "production" ? ["console", "debugger"] : void 0,
919
+ bundle: true,
920
+ outdir: DIST_DIR,
921
+ loader: {
922
+ ".js": "js",
923
+ ".ts": "ts"
924
+ },
925
+ format: "esm",
926
+ platform: "node",
927
+ keepNames: false,
928
+ banner: {
929
+ js: "//__ELEGANCE_JS_PAGE_MARKER__"
930
+ }
931
+ });
932
+ await esbuild.build({
933
+ entryPoints: [
934
+ ...apiFiles.map((route) => path.join(route.parentPath, route.name))
935
+ ],
936
+ minify: options.environment === "production",
937
+ drop: options.environment === "production" ? ["console", "debugger"] : void 0,
938
+ bundle: false,
939
+ outbase: path.join(options.pagesDirectory, "/api"),
940
+ outdir: path.join(DIST_DIR, "/api"),
941
+ loader: {
942
+ ".js": "js",
943
+ ".ts": "ts"
944
+ },
945
+ format: "esm",
946
+ platform: "node",
947
+ keepNames: false
948
+ });
949
+ }
950
+ const pagesTranspiled = performance.now();
951
+ const {
952
+ shouldClientHardReload
953
+ } = await buildPages(DIST_DIR);
954
+ const pagesBuilt = performance.now();
955
+ await buildClient(DIST_DIR);
956
+ const end = performance.now();
957
+ if (options.publicDirectory) {
958
+ console.log("Recursively copying public directory.. this may take a while.");
959
+ const src = path.relative(process.cwd(), options.publicDirectory.path);
960
+ await fs2.promises.cp(src, path.join(DIST_DIR), { recursive: true });
961
+ }
962
+ {
963
+ log(`${Math.round(pagesTranspiled - start)}ms to Transpile Pages`);
964
+ log(`${Math.round(pagesBuilt - pagesTranspiled)}ms to Build Pages`);
965
+ log(`${Math.round(end - pagesBuilt)}ms to Build Client`);
966
+ log(green(bold(`Compiled ${pageFiles.length} pages in ${Math.ceil(end - start)}ms!`)));
967
+ for (const pageFile of pageFiles) {
968
+ console.log(
969
+ "- /" + path.relative(options.pagesDirectory, pageFile.parentPath),
970
+ "(Page)"
971
+ );
972
+ }
973
+ for (const apiFile of apiFiles) {
974
+ "- /" + path.relative(options.pagesDirectory, apiFile.parentPath), "(API Route)";
975
+ }
976
+ }
977
+ if (options.postCompile) {
978
+ log(
979
+ white("Calling post-compile hook..")
980
+ );
981
+ options.postCompile();
982
+ }
983
+ if (shouldClientHardReload) {
984
+ console.log("Sending hard reload..");
985
+ httpStream?.write(`data: hard-reload
986
+
987
+ `);
988
+ } else {
989
+ console.log("Sending soft reload..");
990
+ httpStream?.write(`data: reload
991
+
992
+ `);
993
+ }
994
+ } catch (e) {
995
+ console.error("Build Failed! Received Error:");
996
+ console.error(e);
997
+ return false;
998
+ }
999
+ return true;
1000
+ };
1001
+ var options;
1002
+ var compile = async (props) => {
1003
+ options = props;
1004
+ const watch = options.hotReload !== void 0;
1005
+ const BUILD_FLAG = path.join(options.outputDirectory, "ELEGANCE_BUILD_FLAG");
1006
+ if (!fs2.existsSync(options.outputDirectory)) {
1007
+ fs2.mkdirSync(options.outputDirectory);
1008
+ fs2.writeFileSync(
1009
+ path.join(BUILD_FLAG),
1010
+ "This file just marks this directory as one containing an Elegance Build.",
1011
+ "utf-8"
1012
+ );
1013
+ } else {
1014
+ if (!fs2.existsSync(BUILD_FLAG)) {
1015
+ throw `The output directory already exists, but is not an Elegance Build directory.`;
1016
+ }
1017
+ }
1018
+ const DIST_DIR = path.join(props.outputDirectory, "dist");
1019
+ if (!fs2.existsSync(DIST_DIR)) {
1020
+ fs2.mkdirSync(DIST_DIR);
1021
+ }
1022
+ if (props.server != void 0 && props.server.runServer == true) {
1023
+ startServer({
1024
+ root: props.server.root ?? DIST_DIR,
1025
+ environment: props.environment,
1026
+ port: props.server.port ?? 3e3
1027
+ });
1028
+ }
1029
+ if (watch) {
1030
+ await registerListener();
1031
+ for (const watcher of currentWatchers) {
1032
+ watcher.close();
1033
+ }
1034
+ const subdirectories = [...getAllSubdirectories(options.pagesDirectory), ""];
1035
+ log(yellow("Hot-Reload Watching Subdirectories: "), ...subdirectories.join(", "));
1036
+ const watcherFn = async () => {
1037
+ if (isTimedOut) return;
1038
+ isTimedOut = true;
1039
+ process.stdout.write("\x1Bc");
1040
+ setTimeout(async () => {
1041
+ await build(DIST_DIR);
1042
+ isTimedOut = false;
1043
+ }, 100);
1044
+ };
1045
+ for (const directory of subdirectories) {
1046
+ const fullPath = path.join(options.pagesDirectory, directory);
1047
+ const watcher = fs2.watch(
1048
+ fullPath,
1049
+ {},
1050
+ watcherFn
1051
+ );
1052
+ currentWatchers.push(watcher);
1053
+ }
1054
+ }
1055
+ const success = await build(DIST_DIR);
1056
+ if (!success) return;
1057
+ };
1058
+ export {
1059
+ compile
1060
+ };