elegance-js 2.1.7 → 2.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/build.d.ts +2 -0
- package/dist/build.mjs +1726 -46
- package/dist/compile_docs.mjs +1731 -53
- package/dist/global.d.ts +4 -1
- package/dist/page_compiler.d.ts +1 -3
- package/dist/page_compiler.mjs +42 -468
- package/dist/server/server.mjs +1250 -1100
- package/package.json +1 -1
package/dist/compile_docs.mjs
CHANGED
|
@@ -1,13 +1,1240 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
+
var __esm = (fn, res) => function __init() {
|
|
4
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
5
|
+
};
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
3
10
|
|
|
4
|
-
// src/
|
|
11
|
+
// src/shared/serverElements.ts
|
|
12
|
+
var createBuildableElement, createChildrenlessBuildableElement, childrenlessElementTags, elementTags, elements, childrenlessElements, allElements;
|
|
13
|
+
var init_serverElements = __esm({
|
|
14
|
+
"src/shared/serverElements.ts"() {
|
|
15
|
+
"use strict";
|
|
16
|
+
createBuildableElement = (tag) => {
|
|
17
|
+
return (options3, ...children) => ({
|
|
18
|
+
tag,
|
|
19
|
+
options: options3 || {},
|
|
20
|
+
children
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
createChildrenlessBuildableElement = (tag) => {
|
|
24
|
+
return (options3) => ({
|
|
25
|
+
tag,
|
|
26
|
+
options: options3 || {},
|
|
27
|
+
children: null
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
childrenlessElementTags = [
|
|
31
|
+
"area",
|
|
32
|
+
"base",
|
|
33
|
+
"br",
|
|
34
|
+
"col",
|
|
35
|
+
"embed",
|
|
36
|
+
"hr",
|
|
37
|
+
"img",
|
|
38
|
+
"input",
|
|
39
|
+
"link",
|
|
40
|
+
"meta",
|
|
41
|
+
"source",
|
|
42
|
+
"track",
|
|
43
|
+
"path",
|
|
44
|
+
"rect"
|
|
45
|
+
];
|
|
46
|
+
elementTags = [
|
|
47
|
+
"a",
|
|
48
|
+
"address",
|
|
49
|
+
"article",
|
|
50
|
+
"aside",
|
|
51
|
+
"audio",
|
|
52
|
+
"blockquote",
|
|
53
|
+
"body",
|
|
54
|
+
"button",
|
|
55
|
+
"canvas",
|
|
56
|
+
"caption",
|
|
57
|
+
"colgroup",
|
|
58
|
+
"data",
|
|
59
|
+
"datalist",
|
|
60
|
+
"dd",
|
|
61
|
+
"del",
|
|
62
|
+
"details",
|
|
63
|
+
"dialog",
|
|
64
|
+
"div",
|
|
65
|
+
"dl",
|
|
66
|
+
"dt",
|
|
67
|
+
"fieldset",
|
|
68
|
+
"figcaption",
|
|
69
|
+
"figure",
|
|
70
|
+
"footer",
|
|
71
|
+
"form",
|
|
72
|
+
"h1",
|
|
73
|
+
"h2",
|
|
74
|
+
"h3",
|
|
75
|
+
"h4",
|
|
76
|
+
"h5",
|
|
77
|
+
"h6",
|
|
78
|
+
"head",
|
|
79
|
+
"header",
|
|
80
|
+
"hgroup",
|
|
81
|
+
"html",
|
|
82
|
+
"iframe",
|
|
83
|
+
"ins",
|
|
84
|
+
"label",
|
|
85
|
+
"legend",
|
|
86
|
+
"li",
|
|
87
|
+
"main",
|
|
88
|
+
"map",
|
|
89
|
+
"meter",
|
|
90
|
+
"nav",
|
|
91
|
+
"noscript",
|
|
92
|
+
"object",
|
|
93
|
+
"ol",
|
|
94
|
+
"optgroup",
|
|
95
|
+
"option",
|
|
96
|
+
"output",
|
|
97
|
+
"p",
|
|
98
|
+
"picture",
|
|
99
|
+
"pre",
|
|
100
|
+
"progress",
|
|
101
|
+
"q",
|
|
102
|
+
"section",
|
|
103
|
+
"select",
|
|
104
|
+
"summary",
|
|
105
|
+
"table",
|
|
106
|
+
"tbody",
|
|
107
|
+
"td",
|
|
108
|
+
"template",
|
|
109
|
+
"textarea",
|
|
110
|
+
"tfoot",
|
|
111
|
+
"th",
|
|
112
|
+
"thead",
|
|
113
|
+
"time",
|
|
114
|
+
"tr",
|
|
115
|
+
"ul",
|
|
116
|
+
"video",
|
|
117
|
+
"span",
|
|
118
|
+
"script",
|
|
119
|
+
"abbr",
|
|
120
|
+
"b",
|
|
121
|
+
"bdi",
|
|
122
|
+
"bdo",
|
|
123
|
+
"cite",
|
|
124
|
+
"code",
|
|
125
|
+
"dfn",
|
|
126
|
+
"em",
|
|
127
|
+
"i",
|
|
128
|
+
"kbd",
|
|
129
|
+
"mark",
|
|
130
|
+
"rp",
|
|
131
|
+
"rt",
|
|
132
|
+
"ruby",
|
|
133
|
+
"s",
|
|
134
|
+
"samp",
|
|
135
|
+
"small",
|
|
136
|
+
"strong",
|
|
137
|
+
"sub",
|
|
138
|
+
"sup",
|
|
139
|
+
"u",
|
|
140
|
+
"wbr",
|
|
141
|
+
"title",
|
|
142
|
+
"svg"
|
|
143
|
+
];
|
|
144
|
+
elements = {};
|
|
145
|
+
childrenlessElements = {};
|
|
146
|
+
for (const element of elementTags) {
|
|
147
|
+
elements[element] = createBuildableElement(element);
|
|
148
|
+
}
|
|
149
|
+
for (const element of childrenlessElementTags) {
|
|
150
|
+
childrenlessElements[element] = createChildrenlessBuildableElement(element);
|
|
151
|
+
}
|
|
152
|
+
allElements = {
|
|
153
|
+
...elements,
|
|
154
|
+
...childrenlessElements
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
// src/shared/bindServerElements.ts
|
|
160
|
+
var init_bindServerElements = __esm({
|
|
161
|
+
"src/shared/bindServerElements.ts"() {
|
|
162
|
+
"use strict";
|
|
163
|
+
init_serverElements();
|
|
164
|
+
Object.assign(globalThis, elements);
|
|
165
|
+
Object.assign(globalThis, childrenlessElements);
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
// src/server/render.ts
|
|
170
|
+
var renderRecursively, serverSideRenderPage;
|
|
171
|
+
var init_render = __esm({
|
|
172
|
+
"src/server/render.ts"() {
|
|
173
|
+
"use strict";
|
|
174
|
+
init_bindServerElements();
|
|
175
|
+
renderRecursively = (element) => {
|
|
176
|
+
let returnString = "";
|
|
177
|
+
if (typeof element === "boolean") return returnString;
|
|
178
|
+
else if (typeof element === "number" || typeof element === "string") {
|
|
179
|
+
return returnString + element;
|
|
180
|
+
} else if (Array.isArray(element)) {
|
|
181
|
+
return returnString + element.join(", ");
|
|
182
|
+
}
|
|
183
|
+
returnString += `<${element.tag}`;
|
|
184
|
+
if (typeof element.options === "object") {
|
|
185
|
+
const {
|
|
186
|
+
tag: elementTag,
|
|
187
|
+
options: elementOptions,
|
|
188
|
+
children: elementChildren
|
|
189
|
+
} = element.options;
|
|
190
|
+
if (elementTag !== void 0 && elementOptions !== void 0 && elementChildren !== void 0) {
|
|
191
|
+
const children = element.children;
|
|
192
|
+
element.children = [
|
|
193
|
+
element.options,
|
|
194
|
+
...children
|
|
195
|
+
];
|
|
196
|
+
element.options = {};
|
|
197
|
+
} else {
|
|
198
|
+
for (const [attrName, attrValue] of Object.entries(element.options)) {
|
|
199
|
+
if (typeof attrValue === "object") {
|
|
200
|
+
throw `Attr ${attrName}, for element ${element.tag} has obj type. Got: ${JSON.stringify(element, null, 2)}`;
|
|
201
|
+
}
|
|
202
|
+
returnString += ` ${attrName.toLowerCase()}="${attrValue}"`;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
} else if (typeof element.options !== "object" && element.options !== void 0) {
|
|
206
|
+
element.children = [element.options, ...element.children || []];
|
|
207
|
+
}
|
|
208
|
+
if (element.children === null) {
|
|
209
|
+
returnString += "/>";
|
|
210
|
+
return returnString;
|
|
211
|
+
}
|
|
212
|
+
returnString += ">";
|
|
213
|
+
for (const child2 of element.children) {
|
|
214
|
+
returnString += renderRecursively(child2);
|
|
215
|
+
}
|
|
216
|
+
returnString += `</${element.tag}>`;
|
|
217
|
+
return returnString;
|
|
218
|
+
};
|
|
219
|
+
serverSideRenderPage = async (page, pathname) => {
|
|
220
|
+
if (!page) {
|
|
221
|
+
throw `No Page Provided.`;
|
|
222
|
+
}
|
|
223
|
+
if (typeof page === "function") {
|
|
224
|
+
throw `Unbuilt page provided to ssr page.`;
|
|
225
|
+
}
|
|
226
|
+
const bodyHTML = renderRecursively(page);
|
|
227
|
+
return {
|
|
228
|
+
bodyHTML
|
|
229
|
+
};
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
// src/server/generateHTMLTemplate.ts
|
|
235
|
+
var generateHTMLTemplate;
|
|
236
|
+
var init_generateHTMLTemplate = __esm({
|
|
237
|
+
"src/server/generateHTMLTemplate.ts"() {
|
|
238
|
+
"use strict";
|
|
239
|
+
init_render();
|
|
240
|
+
generateHTMLTemplate = async ({
|
|
241
|
+
pageURL,
|
|
242
|
+
head: head2,
|
|
243
|
+
serverData = null,
|
|
244
|
+
addPageScriptTag = true,
|
|
245
|
+
name,
|
|
246
|
+
requiredClientModules = {},
|
|
247
|
+
environment: environment2
|
|
248
|
+
}) => {
|
|
249
|
+
let StartTemplate = `<meta name="viewport" content="width=device-width, initial-scale=1.0">`;
|
|
250
|
+
if (environment2 === "production") {
|
|
251
|
+
StartTemplate += `<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">`;
|
|
252
|
+
}
|
|
253
|
+
StartTemplate += '<meta charset="UTF-8">';
|
|
254
|
+
for (const [globalName] of Object.entries(requiredClientModules)) {
|
|
255
|
+
StartTemplate += `<script data-module="true" src="/shipped/${globalName}.js" defer="true"></script>`;
|
|
256
|
+
}
|
|
257
|
+
if (addPageScriptTag === true) {
|
|
258
|
+
const sanitized = pageURL === "" ? "/" : `/${pageURL}`;
|
|
259
|
+
StartTemplate += `<script data-page="true" type="module" data-pathname="${sanitized}" src="${sanitized.endsWith("/") ? sanitized : sanitized + "/"}${name}_data.js" defer="true"></script>`;
|
|
260
|
+
}
|
|
261
|
+
StartTemplate += `<script type="module" src="/client.js" defer="true"></script>`;
|
|
262
|
+
let builtHead;
|
|
263
|
+
if (head2.constructor.name === "AsyncFunction") {
|
|
264
|
+
builtHead = await head2();
|
|
265
|
+
} else {
|
|
266
|
+
builtHead = head2();
|
|
267
|
+
}
|
|
268
|
+
let HTMLTemplate = renderRecursively(builtHead);
|
|
269
|
+
if (serverData) {
|
|
270
|
+
HTMLTemplate += serverData;
|
|
271
|
+
}
|
|
272
|
+
return {
|
|
273
|
+
internals: StartTemplate,
|
|
274
|
+
builtMetadata: HTMLTemplate
|
|
275
|
+
};
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
// src/helpers/ObjectAttributeType.ts
|
|
281
|
+
var init_ObjectAttributeType = __esm({
|
|
282
|
+
"src/helpers/ObjectAttributeType.ts"() {
|
|
283
|
+
"use strict";
|
|
284
|
+
}
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
// src/internal/deprecate.ts
|
|
288
|
+
var init_deprecate = __esm({
|
|
289
|
+
"src/internal/deprecate.ts"() {
|
|
290
|
+
"use strict";
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
// src/server/loadHook.ts
|
|
295
|
+
var resetLoadHooks, getLoadHooks;
|
|
296
|
+
var init_loadHook = __esm({
|
|
297
|
+
"src/server/loadHook.ts"() {
|
|
298
|
+
"use strict";
|
|
299
|
+
init_deprecate();
|
|
300
|
+
resetLoadHooks = () => globalThis.__SERVER_CURRENT_LOADHOOKS__ = [];
|
|
301
|
+
getLoadHooks = () => globalThis.__SERVER_CURRENT_LOADHOOKS__;
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
// src/server/state.ts
|
|
306
|
+
var initializeState, getState, initializeObjectAttributes, getObjectAttributes;
|
|
307
|
+
var init_state = __esm({
|
|
308
|
+
"src/server/state.ts"() {
|
|
309
|
+
"use strict";
|
|
310
|
+
init_ObjectAttributeType();
|
|
311
|
+
init_loadHook();
|
|
312
|
+
if (!globalThis.__SERVER_CURRENT_STATE_ID__) {
|
|
313
|
+
globalThis.__SERVER_CURRENT_STATE_ID__ = 1;
|
|
314
|
+
}
|
|
315
|
+
initializeState = () => globalThis.__SERVER_CURRENT_STATE__ = [];
|
|
316
|
+
getState = () => {
|
|
317
|
+
return globalThis.__SERVER_CURRENT_STATE__;
|
|
318
|
+
};
|
|
319
|
+
initializeObjectAttributes = () => globalThis.__SERVER_CURRENT_OBJECT_ATTRIBUTES__ = [];
|
|
320
|
+
getObjectAttributes = () => {
|
|
321
|
+
return globalThis.__SERVER_CURRENT_OBJECT_ATTRIBUTES__;
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
// src/server/layout.ts
|
|
327
|
+
var resetLayouts;
|
|
328
|
+
var init_layout = __esm({
|
|
329
|
+
"src/server/layout.ts"() {
|
|
330
|
+
"use strict";
|
|
331
|
+
resetLayouts = () => globalThis.__SERVER_CURRENT_LAYOUTS__ = /* @__PURE__ */ new Map();
|
|
332
|
+
if (!globalThis.__SERVER_CURRENT_LAYOUT_ID__) globalThis.__SERVER_CURRENT_LAYOUT_ID__ = 1;
|
|
333
|
+
}
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
// src/page_compiler.ts
|
|
337
|
+
var page_compiler_exports = {};
|
|
338
|
+
__export(page_compiler_exports, {
|
|
339
|
+
buildDynamicPage: () => buildDynamicPage,
|
|
340
|
+
processPageElements: () => processPageElements
|
|
341
|
+
});
|
|
5
342
|
import fs from "fs";
|
|
6
343
|
import path from "path";
|
|
344
|
+
import { registerLoader, setArcTsConfig } from "ts-arc";
|
|
345
|
+
import esbuild from "esbuild";
|
|
7
346
|
import { fileURLToPath } from "url";
|
|
347
|
+
function buildTrace(stack, indent = 4) {
|
|
348
|
+
try {
|
|
349
|
+
if (!stack || stack.length === 0) return "[]";
|
|
350
|
+
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] };
|
|
351
|
+
traceObj._error = "This is the element where the error occurred";
|
|
352
|
+
for (let i = stack.length - 2; i >= 0; i--) {
|
|
353
|
+
const parent = stack[i];
|
|
354
|
+
const child2 = stack[i + 1];
|
|
355
|
+
if (!parent || typeof parent !== "object") {
|
|
356
|
+
traceObj = { value: parent, _errorChild: traceObj };
|
|
357
|
+
continue;
|
|
358
|
+
}
|
|
359
|
+
let parentClone;
|
|
360
|
+
try {
|
|
361
|
+
parentClone = JSON.parse(JSON.stringify(parent));
|
|
362
|
+
} catch {
|
|
363
|
+
parentClone = { value: parent };
|
|
364
|
+
}
|
|
365
|
+
let index = -1;
|
|
366
|
+
if (Array.isArray(parentClone.children)) {
|
|
367
|
+
index = parentClone.children.findIndex((c) => c === child2);
|
|
368
|
+
}
|
|
369
|
+
if (index !== -1 && parentClone.children) {
|
|
370
|
+
parentClone.children = parentClone.children.slice(0, index + 1);
|
|
371
|
+
parentClone.children[index] = traceObj;
|
|
372
|
+
} else {
|
|
373
|
+
parentClone._errorChild = traceObj;
|
|
374
|
+
}
|
|
375
|
+
traceObj = parentClone;
|
|
376
|
+
}
|
|
377
|
+
return JSON.stringify(traceObj, null, indent).replace(/^/gm, " ".repeat(indent));
|
|
378
|
+
} catch {
|
|
379
|
+
return "Could not build stack-trace.";
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
var __filename, __dirname, packageDir, clientPath, watcherPath, shippedModules, modulesToShip, yellow, black, bgYellow, bold, underline, white, log2, options, DIST_DIR, PAGE_MAP, LAYOUT_MAP, getAllSubdirectories, buildClient, elementKey, processOptionAsObjectAttribute, processPageElements, pageToHTML, generateClientPageData, generateLayout, builtLayouts, buildLayouts, buildLayout, fetchPageLayoutHTML, buildPages, buildPage, buildDynamicPage, shipModules, build;
|
|
383
|
+
var init_page_compiler = __esm({
|
|
384
|
+
"src/page_compiler.ts"() {
|
|
385
|
+
"use strict";
|
|
386
|
+
init_generateHTMLTemplate();
|
|
387
|
+
init_ObjectAttributeType();
|
|
388
|
+
init_render();
|
|
389
|
+
init_state();
|
|
390
|
+
init_loadHook();
|
|
391
|
+
init_layout();
|
|
392
|
+
init_render();
|
|
393
|
+
__filename = fileURLToPath(import.meta.url);
|
|
394
|
+
__dirname = path.dirname(__filename);
|
|
395
|
+
setArcTsConfig(__dirname);
|
|
396
|
+
registerLoader();
|
|
397
|
+
packageDir = process.env.PACKAGE_PATH;
|
|
398
|
+
if (packageDir === void 0) {
|
|
399
|
+
packageDir = path.resolve(__dirname, "..");
|
|
400
|
+
}
|
|
401
|
+
clientPath = path.resolve(packageDir, "./dist/client/client.mjs");
|
|
402
|
+
watcherPath = path.resolve(packageDir, "./dist/client/watcher.mjs");
|
|
403
|
+
shippedModules = /* @__PURE__ */ new Map();
|
|
404
|
+
modulesToShip = [];
|
|
405
|
+
yellow = (text) => {
|
|
406
|
+
return `\x1B[38;2;238;184;68m${text}`;
|
|
407
|
+
};
|
|
408
|
+
black = (text) => {
|
|
409
|
+
return `\x1B[38;2;0;0;0m${text}`;
|
|
410
|
+
};
|
|
411
|
+
bgYellow = (text) => {
|
|
412
|
+
return `\x1B[48;2;238;184;68m${text}`;
|
|
413
|
+
};
|
|
414
|
+
bold = (text) => {
|
|
415
|
+
return `\x1B[1m${text}`;
|
|
416
|
+
};
|
|
417
|
+
underline = (text) => {
|
|
418
|
+
return `\x1B[4m${text}`;
|
|
419
|
+
};
|
|
420
|
+
white = (text) => {
|
|
421
|
+
return `\x1B[38;2;255;247;229m${text}`;
|
|
422
|
+
};
|
|
423
|
+
log2 = (...text) => {
|
|
424
|
+
if (options.quiet) return;
|
|
425
|
+
return console.log(text.map((text2) => `${text2}\x1B[0m`).join(""));
|
|
426
|
+
};
|
|
427
|
+
options = JSON.parse(process.env.OPTIONS || "{}");
|
|
428
|
+
console.log(options);
|
|
429
|
+
DIST_DIR = process.env.DIST_DIR;
|
|
430
|
+
PAGE_MAP = /* @__PURE__ */ new Map();
|
|
431
|
+
LAYOUT_MAP = /* @__PURE__ */ new Map();
|
|
432
|
+
getAllSubdirectories = (dir, baseDir = dir) => {
|
|
433
|
+
let directories = [];
|
|
434
|
+
const items = fs.readdirSync(dir, { withFileTypes: true });
|
|
435
|
+
for (const item of items) {
|
|
436
|
+
if (item.isDirectory()) {
|
|
437
|
+
const fullPath = path.join(dir, item.name);
|
|
438
|
+
const relativePath = path.relative(baseDir, fullPath);
|
|
439
|
+
directories.push(relativePath);
|
|
440
|
+
directories = directories.concat(getAllSubdirectories(fullPath, baseDir));
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
return directories;
|
|
444
|
+
};
|
|
445
|
+
buildClient = async (DIST_DIR2) => {
|
|
446
|
+
let clientString = "window.__name = (func) => func; ";
|
|
447
|
+
clientString += fs.readFileSync(clientPath, "utf-8");
|
|
448
|
+
if (options.hotReload !== void 0) {
|
|
449
|
+
clientString += `const watchServerPort = ${options.hotReload.port}`;
|
|
450
|
+
clientString += fs.readFileSync(watcherPath, "utf-8");
|
|
451
|
+
}
|
|
452
|
+
const transformedClient = await esbuild.transform(clientString, {
|
|
453
|
+
minify: options.environment === "production",
|
|
454
|
+
drop: options.environment === "production" ? ["console", "debugger"] : void 0,
|
|
455
|
+
keepNames: false,
|
|
456
|
+
format: "iife",
|
|
457
|
+
platform: "node",
|
|
458
|
+
loader: "ts"
|
|
459
|
+
});
|
|
460
|
+
fs.writeFileSync(
|
|
461
|
+
path.join(DIST_DIR2, "/client.js"),
|
|
462
|
+
transformedClient.code
|
|
463
|
+
);
|
|
464
|
+
};
|
|
465
|
+
elementKey = 0;
|
|
466
|
+
processOptionAsObjectAttribute = (element, optionName, optionValue, objectAttributes) => {
|
|
467
|
+
const lcOptionName = optionName.toLowerCase();
|
|
468
|
+
const options3 = element.options;
|
|
469
|
+
let key = options3.key;
|
|
470
|
+
if (key == void 0) {
|
|
471
|
+
key = elementKey += 1;
|
|
472
|
+
options3.key = key;
|
|
473
|
+
}
|
|
474
|
+
if (!optionValue.type) {
|
|
475
|
+
throw `ObjectAttributeType is missing from object attribute. ${element.tag}: ${optionName}/${optionValue}`;
|
|
476
|
+
}
|
|
477
|
+
let optionFinal = lcOptionName;
|
|
478
|
+
switch (optionValue.type) {
|
|
479
|
+
case 1 /* STATE */:
|
|
480
|
+
const SOA = optionValue;
|
|
481
|
+
if (typeof SOA.value === "function") {
|
|
482
|
+
delete options3[optionName];
|
|
483
|
+
break;
|
|
484
|
+
}
|
|
485
|
+
if (lcOptionName === "innertext" || lcOptionName === "innerhtml") {
|
|
486
|
+
element.children = [SOA.value];
|
|
487
|
+
delete options3[optionName];
|
|
488
|
+
} else {
|
|
489
|
+
delete options3[optionName];
|
|
490
|
+
options3[lcOptionName] = SOA.value;
|
|
491
|
+
}
|
|
492
|
+
break;
|
|
493
|
+
case 2 /* OBSERVER */:
|
|
494
|
+
const OOA = optionValue;
|
|
495
|
+
const firstValue = OOA.update(...OOA.initialValues);
|
|
496
|
+
if (lcOptionName === "innertext" || lcOptionName === "innerhtml") {
|
|
497
|
+
element.children = [firstValue];
|
|
498
|
+
delete options3[optionName];
|
|
499
|
+
} else {
|
|
500
|
+
delete options3[optionName];
|
|
501
|
+
options3[lcOptionName] = firstValue;
|
|
502
|
+
}
|
|
503
|
+
optionFinal = optionName;
|
|
504
|
+
break;
|
|
505
|
+
case 4 /* REFERENCE */:
|
|
506
|
+
options3["ref"] = optionValue.value;
|
|
507
|
+
break;
|
|
508
|
+
}
|
|
509
|
+
objectAttributes.push({ ...optionValue, key, attribute: optionFinal });
|
|
510
|
+
};
|
|
511
|
+
processPageElements = (element, objectAttributes, recursionLevel, stack = []) => {
|
|
512
|
+
stack.push(element);
|
|
513
|
+
try {
|
|
514
|
+
if (typeof element === "boolean" || typeof element === "number" || Array.isArray(element)) {
|
|
515
|
+
stack.pop();
|
|
516
|
+
return element;
|
|
517
|
+
}
|
|
518
|
+
if (typeof element === "string") {
|
|
519
|
+
stack.pop();
|
|
520
|
+
return element;
|
|
521
|
+
}
|
|
522
|
+
const processElementOptionsAsChildAndReturn = () => {
|
|
523
|
+
try {
|
|
524
|
+
const children = element.children;
|
|
525
|
+
element.children = [
|
|
526
|
+
element.options,
|
|
527
|
+
...children
|
|
528
|
+
];
|
|
529
|
+
element.options = {};
|
|
530
|
+
for (let i = 0; i < children.length + 1; i++) {
|
|
531
|
+
const child2 = element.children[i];
|
|
532
|
+
const processedChild = processPageElements(child2, objectAttributes, recursionLevel + 1, stack);
|
|
533
|
+
element.children[i] = processedChild;
|
|
534
|
+
}
|
|
535
|
+
return {
|
|
536
|
+
...element,
|
|
537
|
+
options: {}
|
|
538
|
+
};
|
|
539
|
+
} catch (e) {
|
|
540
|
+
const errorString = `Could not process element options as a child. ${e}.`;
|
|
541
|
+
throw new Error(errorString);
|
|
542
|
+
}
|
|
543
|
+
};
|
|
544
|
+
if (typeof element.options !== "object") {
|
|
545
|
+
const result = processElementOptionsAsChildAndReturn();
|
|
546
|
+
stack.pop();
|
|
547
|
+
return result;
|
|
548
|
+
}
|
|
549
|
+
const {
|
|
550
|
+
tag: elementTag,
|
|
551
|
+
options: elementOptions,
|
|
552
|
+
children: elementChildren
|
|
553
|
+
} = element.options;
|
|
554
|
+
if (elementTag && elementOptions && elementChildren) {
|
|
555
|
+
const result = processElementOptionsAsChildAndReturn();
|
|
556
|
+
stack.pop();
|
|
557
|
+
return result;
|
|
558
|
+
}
|
|
559
|
+
const options3 = element.options;
|
|
560
|
+
for (const [optionName, optionValue] of Object.entries(options3)) {
|
|
561
|
+
const lcOptionName = optionName.toLowerCase();
|
|
562
|
+
if (typeof optionValue !== "object") {
|
|
563
|
+
if (lcOptionName === "innertext") {
|
|
564
|
+
delete options3[optionName];
|
|
565
|
+
if (element.children === null) {
|
|
566
|
+
throw `Cannot use innerText or innerHTML on childrenless elements.`;
|
|
567
|
+
}
|
|
568
|
+
element.children = [optionValue, ...element.children];
|
|
569
|
+
continue;
|
|
570
|
+
} else if (lcOptionName === "innerhtml") {
|
|
571
|
+
if (element.children === null) {
|
|
572
|
+
throw `Cannot use innerText or innerHTML on childrenless elements.`;
|
|
573
|
+
}
|
|
574
|
+
delete options3[optionName];
|
|
575
|
+
element.children = [optionValue];
|
|
576
|
+
continue;
|
|
577
|
+
}
|
|
578
|
+
continue;
|
|
579
|
+
}
|
|
580
|
+
;
|
|
581
|
+
processOptionAsObjectAttribute(element, optionName, optionValue, objectAttributes);
|
|
582
|
+
}
|
|
583
|
+
if (element.children) {
|
|
584
|
+
for (let i = 0; i < element.children.length; i++) {
|
|
585
|
+
const child2 = element.children[i];
|
|
586
|
+
const processedChild = processPageElements(child2, objectAttributes, recursionLevel + 1, stack);
|
|
587
|
+
element.children[i] = processedChild;
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
stack.pop();
|
|
591
|
+
return element;
|
|
592
|
+
} catch (e) {
|
|
593
|
+
const trace = buildTrace(stack);
|
|
594
|
+
if (recursionLevel === 0) {
|
|
595
|
+
throw new Error(`${e}
|
|
596
|
+
|
|
597
|
+
Trace:
|
|
598
|
+
${trace}`);
|
|
599
|
+
} else {
|
|
600
|
+
throw e;
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
};
|
|
604
|
+
pageToHTML = async (pageLocation, pageElements, metadata, DIST_DIR2, pageName, doWrite = true, requiredClientModules = {}, layout, pathname = "") => {
|
|
605
|
+
if (typeof pageElements === "string" || typeof pageElements === "boolean" || typeof pageElements === "number" || Array.isArray(pageElements)) {
|
|
606
|
+
throw new Error(`The root element of a page / layout must be a built element, not just a Child. Received: ${typeof pageElements}.`);
|
|
607
|
+
}
|
|
608
|
+
const objectAttributes = [];
|
|
609
|
+
const stack = [];
|
|
610
|
+
const processedPageElements = processPageElements(pageElements, objectAttributes, 0, stack);
|
|
611
|
+
const renderedPage = await serverSideRenderPage(
|
|
612
|
+
processedPageElements,
|
|
613
|
+
pageLocation
|
|
614
|
+
);
|
|
615
|
+
const { internals, builtMetadata } = await generateHTMLTemplate({
|
|
616
|
+
pageURL: pathname,
|
|
617
|
+
head: metadata,
|
|
618
|
+
addPageScriptTag: doWrite,
|
|
619
|
+
name: pageName,
|
|
620
|
+
requiredClientModules,
|
|
621
|
+
environment: options.environment
|
|
622
|
+
});
|
|
623
|
+
let extraBodyHTML = "";
|
|
624
|
+
if (doWrite === false) {
|
|
625
|
+
const state = getState();
|
|
626
|
+
const pageLoadHooks = getLoadHooks();
|
|
627
|
+
const userObjectAttributes = getObjectAttributes();
|
|
628
|
+
const {
|
|
629
|
+
result
|
|
630
|
+
} = await generateClientPageData(
|
|
631
|
+
pathname,
|
|
632
|
+
state || {},
|
|
633
|
+
[...objectAttributes, ...userObjectAttributes],
|
|
634
|
+
pageLoadHooks || [],
|
|
635
|
+
DIST_DIR2,
|
|
636
|
+
"page",
|
|
637
|
+
"pd",
|
|
638
|
+
false
|
|
639
|
+
);
|
|
640
|
+
const sanitized = pathname === "" ? "/" : `/${pathname}`;
|
|
641
|
+
extraBodyHTML = `<script data-hook="true" data-pathname="${sanitized}" type="text/plain">${result}</script>`;
|
|
642
|
+
extraBodyHTML += `<script>
|
|
643
|
+
const text = document.querySelector('[data-hook="true"][data-pathname="${sanitized}"][type="text/plain"').textContent;
|
|
644
|
+
const blob = new Blob([text], { type: 'text/javascript' });
|
|
645
|
+
const url = URL.createObjectURL(blob);
|
|
646
|
+
|
|
647
|
+
const script = document.createElement("script");
|
|
648
|
+
script.src = url;
|
|
649
|
+
script.type = "module";
|
|
650
|
+
script.setAttribute("data-page", "true");
|
|
651
|
+
script.setAttribute("data-pathname", "${sanitized}");
|
|
652
|
+
|
|
653
|
+
document.head.appendChild(script);
|
|
654
|
+
|
|
655
|
+
document.currentScript.remove();
|
|
656
|
+
</script>`;
|
|
657
|
+
extraBodyHTML = extraBodyHTML.replace(/\s+/g, " ").replace(/\s*([{}();,:])\s*/g, "$1").trim();
|
|
658
|
+
}
|
|
659
|
+
const headHTML = `<!DOCTYPE html>${layout.metadata.startHTML}${layout.scriptTag}${internals}${builtMetadata}${layout.metadata.endHTML}`;
|
|
660
|
+
const bodyHTML = `${layout.pageContent.startHTML}${renderedPage.bodyHTML}${extraBodyHTML}${layout.pageContent.endHTML}`;
|
|
661
|
+
const resultHTML = `${headHTML}${bodyHTML}`;
|
|
662
|
+
const htmlLocation = path.join(pageLocation, (pageName === "page" ? "index" : pageName) + ".html");
|
|
663
|
+
if (doWrite) {
|
|
664
|
+
const dirname2 = path.dirname(htmlLocation);
|
|
665
|
+
if (fs.existsSync(dirname2) === false) {
|
|
666
|
+
fs.mkdirSync(dirname2, { recursive: true });
|
|
667
|
+
}
|
|
668
|
+
fs.writeFileSync(
|
|
669
|
+
htmlLocation,
|
|
670
|
+
resultHTML,
|
|
671
|
+
{
|
|
672
|
+
encoding: "utf-8",
|
|
673
|
+
flag: "w"
|
|
674
|
+
}
|
|
675
|
+
);
|
|
676
|
+
return objectAttributes;
|
|
677
|
+
}
|
|
678
|
+
return resultHTML;
|
|
679
|
+
};
|
|
680
|
+
generateClientPageData = async (pageLocation, state, objectAttributes, pageLoadHooks, DIST_DIR2, pageName, globalVariableName = "pd", write = true) => {
|
|
681
|
+
let clientPageJSText = "";
|
|
682
|
+
{
|
|
683
|
+
clientPageJSText += `${globalThis.__SERVER_PAGE_DATA_BANNER__}`;
|
|
684
|
+
}
|
|
685
|
+
{
|
|
686
|
+
clientPageJSText += `export const data = {`;
|
|
687
|
+
if (state) {
|
|
688
|
+
clientPageJSText += `state:[`;
|
|
689
|
+
for (const subject of state) {
|
|
690
|
+
if (typeof subject.value === "string") {
|
|
691
|
+
const stringified = JSON.stringify(subject.value);
|
|
692
|
+
clientPageJSText += `{id:${subject.id},value:${stringified}},`;
|
|
693
|
+
} else if (typeof subject.value === "function") {
|
|
694
|
+
clientPageJSText += `{id:${subject.id},value:${subject.value.toString()}},`;
|
|
695
|
+
} else {
|
|
696
|
+
clientPageJSText += `{id:${subject.id},value:${JSON.stringify(subject.value)}},`;
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
clientPageJSText += `],`;
|
|
700
|
+
}
|
|
701
|
+
const stateObjectAttributes = objectAttributes.filter((oa) => oa.type === 1 /* STATE */);
|
|
702
|
+
if (stateObjectAttributes.length > 0) {
|
|
703
|
+
const processed = [...stateObjectAttributes].map((soa) => {
|
|
704
|
+
delete soa.type;
|
|
705
|
+
return soa;
|
|
706
|
+
});
|
|
707
|
+
clientPageJSText += `soa:${JSON.stringify(processed)},`;
|
|
708
|
+
}
|
|
709
|
+
const observerObjectAttributes = objectAttributes.filter((oa) => oa.type === 2 /* OBSERVER */);
|
|
710
|
+
if (observerObjectAttributes.length > 0) {
|
|
711
|
+
let observerObjectAttributeString = "ooa:[";
|
|
712
|
+
for (const observerObjectAttribute of observerObjectAttributes) {
|
|
713
|
+
const ooa = observerObjectAttribute;
|
|
714
|
+
observerObjectAttributeString += `{key:${ooa.key},attribute:"${ooa.attribute}",update:${ooa.update.toString()},`;
|
|
715
|
+
observerObjectAttributeString += `refs:[`;
|
|
716
|
+
for (const ref of ooa.refs) {
|
|
717
|
+
observerObjectAttributeString += `{id:${ref.id}},`;
|
|
718
|
+
}
|
|
719
|
+
observerObjectAttributeString += "]},";
|
|
720
|
+
}
|
|
721
|
+
observerObjectAttributeString += "],";
|
|
722
|
+
clientPageJSText += observerObjectAttributeString;
|
|
723
|
+
}
|
|
724
|
+
if (pageLoadHooks.length > 0) {
|
|
725
|
+
clientPageJSText += "lh:[";
|
|
726
|
+
for (const loadHook2 of pageLoadHooks) {
|
|
727
|
+
clientPageJSText += `{fn:${loadHook2.fn}},`;
|
|
728
|
+
}
|
|
729
|
+
clientPageJSText += "],";
|
|
730
|
+
}
|
|
731
|
+
clientPageJSText += `};`;
|
|
732
|
+
}
|
|
733
|
+
const pageDataPath = path.join(DIST_DIR2, pageLocation, `${pageName}_data.js`);
|
|
734
|
+
let sendHardReloadInstruction = false;
|
|
735
|
+
const transformedResult = await esbuild.transform(clientPageJSText, { minify: options.environment === "production" }).catch((error) => {
|
|
736
|
+
console.error("Failed to transform client page js!", error);
|
|
737
|
+
});
|
|
738
|
+
if (!transformedResult) return { sendHardReloadInstruction };
|
|
739
|
+
if (fs.existsSync(pageDataPath)) {
|
|
740
|
+
const content = fs.readFileSync(pageDataPath).toString();
|
|
741
|
+
if (content !== transformedResult.code) {
|
|
742
|
+
sendHardReloadInstruction = true;
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
if (write) fs.writeFileSync(pageDataPath, transformedResult.code, "utf-8");
|
|
746
|
+
return { sendHardReloadInstruction, result: transformedResult.code };
|
|
747
|
+
};
|
|
748
|
+
generateLayout = async (DIST_DIR2, filePath, directory, childIndicator, generateDynamic = false) => {
|
|
749
|
+
initializeState();
|
|
750
|
+
initializeObjectAttributes();
|
|
751
|
+
resetLoadHooks();
|
|
752
|
+
globalThis.__SERVER_PAGE_DATA_BANNER__ = "";
|
|
753
|
+
let layoutElements;
|
|
754
|
+
let metadataElements;
|
|
755
|
+
let modules = [];
|
|
756
|
+
let isDynamicLayout = false;
|
|
757
|
+
try {
|
|
758
|
+
const {
|
|
759
|
+
layout,
|
|
760
|
+
metadata,
|
|
761
|
+
isDynamic,
|
|
762
|
+
shippedModules: shippedModules2
|
|
763
|
+
} = await import("file://" + filePath);
|
|
764
|
+
if (shippedModules2 !== void 0) {
|
|
765
|
+
modules = shippedModules2;
|
|
766
|
+
}
|
|
767
|
+
layoutElements = layout;
|
|
768
|
+
metadataElements = metadata;
|
|
769
|
+
if (isDynamic === true) {
|
|
770
|
+
isDynamicLayout = isDynamic;
|
|
771
|
+
}
|
|
772
|
+
} catch (e) {
|
|
773
|
+
throw new Error(`Error in Page: ${directory === "" ? "/" : directory}layout.ts - ${e}`);
|
|
774
|
+
}
|
|
775
|
+
LAYOUT_MAP.set(directory === "" ? "/" : `/${directory}`, {
|
|
776
|
+
isDynamic: isDynamicLayout,
|
|
777
|
+
filePath
|
|
778
|
+
});
|
|
779
|
+
if (isDynamicLayout === true && generateDynamic === false) return false;
|
|
780
|
+
{
|
|
781
|
+
if (!layoutElements) {
|
|
782
|
+
throw new Error(`WARNING: ${filePath} should export a const layout, which is of type Layout: (child: Child) => AnyBuiltElement.`);
|
|
783
|
+
}
|
|
784
|
+
if (typeof layoutElements === "function") {
|
|
785
|
+
if (layoutElements.constructor.name === "AsyncFunction") {
|
|
786
|
+
layoutElements = await layoutElements(childIndicator);
|
|
787
|
+
} else {
|
|
788
|
+
layoutElements = layoutElements(childIndicator);
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
{
|
|
793
|
+
if (!metadataElements) {
|
|
794
|
+
throw new Error(`WARNING: ${filePath} should export a const metadata, which is of type LayoutMetadata: (child: Child) => AnyBuiltElement.`);
|
|
795
|
+
}
|
|
796
|
+
if (typeof metadataElements === "function") {
|
|
797
|
+
if (metadataElements.constructor.name === "AsyncFunction") {
|
|
798
|
+
metadataElements = await metadataElements(childIndicator);
|
|
799
|
+
} else {
|
|
800
|
+
metadataElements = metadataElements(childIndicator);
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
const state = getState();
|
|
805
|
+
const pageLoadHooks = getLoadHooks();
|
|
806
|
+
const objectAttributes = getObjectAttributes();
|
|
807
|
+
if (typeof layoutElements === "string" || typeof layoutElements === "boolean" || typeof layoutElements === "number" || Array.isArray(layoutElements)) {
|
|
808
|
+
throw new Error(`The root element of a page / layout must be a built element, not just a Child. Received: ${typeof layoutElements}.`);
|
|
809
|
+
}
|
|
810
|
+
const foundObjectAttributes = [];
|
|
811
|
+
const stack = [];
|
|
812
|
+
const processedPageElements = processPageElements(layoutElements, foundObjectAttributes, 0, stack);
|
|
813
|
+
const renderedPage = await serverSideRenderPage(
|
|
814
|
+
processedPageElements,
|
|
815
|
+
directory
|
|
816
|
+
);
|
|
817
|
+
const metadataHTML = metadataElements ? renderRecursively(metadataElements) : "";
|
|
818
|
+
await generateClientPageData(
|
|
819
|
+
directory,
|
|
820
|
+
state || {},
|
|
821
|
+
[...objectAttributes, ...foundObjectAttributes],
|
|
822
|
+
pageLoadHooks || [],
|
|
823
|
+
DIST_DIR2,
|
|
824
|
+
"layout",
|
|
825
|
+
"ld"
|
|
826
|
+
);
|
|
827
|
+
return { pageContentHTML: renderedPage.bodyHTML, metadataHTML };
|
|
828
|
+
};
|
|
829
|
+
builtLayouts = /* @__PURE__ */ new Map();
|
|
830
|
+
buildLayouts = async () => {
|
|
831
|
+
const pagesDirectory = path.resolve(options.pagesDirectory);
|
|
832
|
+
const subdirectories = [...getAllSubdirectories(pagesDirectory), ""];
|
|
833
|
+
let shouldClientHardReload = false;
|
|
834
|
+
for (const directory of subdirectories) {
|
|
835
|
+
const abs = path.resolve(path.join(pagesDirectory, directory));
|
|
836
|
+
const files = fs.readdirSync(abs, { withFileTypes: true }).filter((f) => f.name.endsWith(".ts"));
|
|
837
|
+
for (const file of files) {
|
|
838
|
+
const filePath = path.join(file.parentPath, file.name);
|
|
839
|
+
const name = file.name.slice(0, file.name.length - 3);
|
|
840
|
+
const isLayout = name === "layout";
|
|
841
|
+
if (isLayout == false) {
|
|
842
|
+
continue;
|
|
843
|
+
}
|
|
844
|
+
try {
|
|
845
|
+
const builtLayout = await buildLayout(filePath, directory);
|
|
846
|
+
if (!builtLayout) return { shouldClientHardReload: false };
|
|
847
|
+
builtLayouts.set(filePath, builtLayout);
|
|
848
|
+
} catch (e) {
|
|
849
|
+
console.error(e);
|
|
850
|
+
continue;
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
return { shouldClientHardReload };
|
|
855
|
+
};
|
|
856
|
+
buildLayout = async (filePath, directory, generateDynamic = false) => {
|
|
857
|
+
const id = globalThis.__SERVER_CURRENT_STATE_ID__ += 1;
|
|
858
|
+
const childIndicator = `<template layout-id="${id}"></template>`;
|
|
859
|
+
const result = await generateLayout(
|
|
860
|
+
DIST_DIR,
|
|
861
|
+
filePath,
|
|
862
|
+
directory,
|
|
863
|
+
childIndicator,
|
|
864
|
+
generateDynamic
|
|
865
|
+
);
|
|
866
|
+
if (result === false) return false;
|
|
867
|
+
const { pageContentHTML, metadataHTML } = result;
|
|
868
|
+
const splitAround = (str, sub) => {
|
|
869
|
+
const i = str.indexOf(sub);
|
|
870
|
+
if (i === -1) throw new Error("substring does not exist in parent string");
|
|
871
|
+
return {
|
|
872
|
+
startHTML: str.substring(0, i),
|
|
873
|
+
endHTML: str.substring(i + sub.length)
|
|
874
|
+
};
|
|
875
|
+
};
|
|
876
|
+
const splitAt = (str, sub) => {
|
|
877
|
+
const i = str.indexOf(sub) + sub.length;
|
|
878
|
+
if (i === -1) throw new Error("substring does not exist in parent string");
|
|
879
|
+
return {
|
|
880
|
+
startHTML: str.substring(0, i),
|
|
881
|
+
endHTML: str.substring(i)
|
|
882
|
+
};
|
|
883
|
+
};
|
|
884
|
+
const pathname = directory === "" ? "/" : directory;
|
|
885
|
+
return {
|
|
886
|
+
pageContent: splitAt(pageContentHTML, childIndicator),
|
|
887
|
+
metadata: splitAround(metadataHTML, childIndicator),
|
|
888
|
+
scriptTag: `<script data-layout="true" type="module" src="${pathname}layout_data.js" data-pathname="${pathname}" defer="true"></script>`
|
|
889
|
+
};
|
|
890
|
+
};
|
|
891
|
+
fetchPageLayoutHTML = async (dirname2) => {
|
|
892
|
+
const relative2 = path.relative(options.pagesDirectory, dirname2);
|
|
893
|
+
let split = relative2.split(path.sep).filter(Boolean);
|
|
894
|
+
split.push("/");
|
|
895
|
+
split.reverse();
|
|
896
|
+
let layouts = [];
|
|
897
|
+
for (const dir of split) {
|
|
898
|
+
if (LAYOUT_MAP.has(dir)) {
|
|
899
|
+
const filePath = path.join(path.resolve(options.pagesDirectory), dir, "layout.ts");
|
|
900
|
+
const layout = LAYOUT_MAP.get(dir);
|
|
901
|
+
if (layout.isDynamic) {
|
|
902
|
+
const builtLayout = await buildLayout(layout.filePath, dir, true);
|
|
903
|
+
if (!builtLayout) continue;
|
|
904
|
+
layouts.push(builtLayout);
|
|
905
|
+
} else {
|
|
906
|
+
layouts.push(builtLayouts.get(filePath));
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
const pageContent = {
|
|
911
|
+
startHTML: "",
|
|
912
|
+
endHTML: ""
|
|
913
|
+
};
|
|
914
|
+
const metadata = {
|
|
915
|
+
startHTML: "",
|
|
916
|
+
endHTML: ""
|
|
917
|
+
};
|
|
918
|
+
let scriptTags = "";
|
|
919
|
+
for (const layout of layouts) {
|
|
920
|
+
pageContent.startHTML += layout.pageContent.startHTML;
|
|
921
|
+
metadata.startHTML += layout.metadata.startHTML;
|
|
922
|
+
scriptTags += layout.scriptTag;
|
|
923
|
+
pageContent.endHTML += layout.pageContent.endHTML;
|
|
924
|
+
metadata.endHTML += layout.metadata.endHTML;
|
|
925
|
+
}
|
|
926
|
+
return { pageContent, metadata, scriptTag: scriptTags };
|
|
927
|
+
};
|
|
928
|
+
buildPages = async (DIST_DIR2) => {
|
|
929
|
+
resetLayouts();
|
|
930
|
+
const pagesDirectory = path.resolve(options.pagesDirectory);
|
|
931
|
+
const subdirectories = [...getAllSubdirectories(pagesDirectory), ""];
|
|
932
|
+
let shouldClientHardReload = false;
|
|
933
|
+
for (const directory of subdirectories) {
|
|
934
|
+
const abs = path.resolve(path.join(pagesDirectory, directory));
|
|
935
|
+
const files = fs.readdirSync(abs, { withFileTypes: true }).filter((f) => f.name.endsWith(".ts"));
|
|
936
|
+
for (const file of files) {
|
|
937
|
+
const filePath = path.join(file.parentPath, file.name);
|
|
938
|
+
const name = file.name.slice(0, file.name.length - 3);
|
|
939
|
+
const isPage = name === "page";
|
|
940
|
+
if (isPage == false) {
|
|
941
|
+
continue;
|
|
942
|
+
}
|
|
943
|
+
try {
|
|
944
|
+
const hardReloadForPage = await buildPage(DIST_DIR2, directory, filePath, name);
|
|
945
|
+
if (hardReloadForPage) {
|
|
946
|
+
shouldClientHardReload = true;
|
|
947
|
+
}
|
|
948
|
+
} catch (e) {
|
|
949
|
+
console.error(e);
|
|
950
|
+
continue;
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
return {
|
|
955
|
+
shouldClientHardReload
|
|
956
|
+
};
|
|
957
|
+
};
|
|
958
|
+
buildPage = async (DIST_DIR2, directory, filePath, name) => {
|
|
959
|
+
initializeState();
|
|
960
|
+
initializeObjectAttributes();
|
|
961
|
+
resetLoadHooks();
|
|
962
|
+
globalThis.__SERVER_PAGE_DATA_BANNER__ = "";
|
|
963
|
+
let pageElements;
|
|
964
|
+
let metadata;
|
|
965
|
+
let modules = {};
|
|
966
|
+
let pageIgnoresLayout = false;
|
|
967
|
+
let isDynamicPage = false;
|
|
968
|
+
try {
|
|
969
|
+
const {
|
|
970
|
+
page,
|
|
971
|
+
metadata: pageMetadata,
|
|
972
|
+
isDynamic,
|
|
973
|
+
shippedModules: shippedModules2,
|
|
974
|
+
ignoreLayout
|
|
975
|
+
} = await import("file://" + filePath);
|
|
976
|
+
if (shippedModules2 !== void 0) {
|
|
977
|
+
modules = shippedModules2;
|
|
978
|
+
}
|
|
979
|
+
if (ignoreLayout) {
|
|
980
|
+
pageIgnoresLayout = true;
|
|
981
|
+
}
|
|
982
|
+
pageElements = page;
|
|
983
|
+
metadata = pageMetadata;
|
|
984
|
+
if (isDynamic === true) {
|
|
985
|
+
isDynamicPage = isDynamic;
|
|
986
|
+
}
|
|
987
|
+
} catch (e) {
|
|
988
|
+
throw new Error(`Error in Page: ${directory}/${name}.ts - ${e}`);
|
|
989
|
+
}
|
|
990
|
+
PAGE_MAP.set(directory === "" ? "/" : `/${directory}`, {
|
|
991
|
+
isDynamic: isDynamicPage,
|
|
992
|
+
filePath
|
|
993
|
+
});
|
|
994
|
+
if (isDynamicPage) return false;
|
|
995
|
+
if (modules !== void 0) {
|
|
996
|
+
for (const [globalName, path4] of Object.entries(modules)) {
|
|
997
|
+
modulesToShip.push({ globalName, path: path4 });
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
if (!metadata || metadata && typeof metadata !== "function") {
|
|
1001
|
+
console.warn(`WARNING: ${filePath} does not export a metadata function.`);
|
|
1002
|
+
}
|
|
1003
|
+
if (!pageElements) {
|
|
1004
|
+
console.warn(`WARNING: ${filePath} should export a const page, which is of type () => BuiltElement<"body">.`);
|
|
1005
|
+
}
|
|
1006
|
+
const pageProps = {
|
|
1007
|
+
pageName: directory,
|
|
1008
|
+
middlewareData: {}
|
|
1009
|
+
};
|
|
1010
|
+
if (typeof pageElements === "function") {
|
|
1011
|
+
if (pageElements.constructor.name === "AsyncFunction") {
|
|
1012
|
+
pageElements = await pageElements(pageProps);
|
|
1013
|
+
} else {
|
|
1014
|
+
pageElements = pageElements(pageProps);
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
const state = getState();
|
|
1018
|
+
const pageLoadHooks = getLoadHooks();
|
|
1019
|
+
const objectAttributes = getObjectAttributes();
|
|
1020
|
+
const layout = await fetchPageLayoutHTML(path.dirname(filePath));
|
|
1021
|
+
const foundObjectAttributes = await pageToHTML(
|
|
1022
|
+
path.join(DIST_DIR2, directory),
|
|
1023
|
+
pageElements || body(),
|
|
1024
|
+
metadata ?? (() => head()),
|
|
1025
|
+
DIST_DIR2,
|
|
1026
|
+
name,
|
|
1027
|
+
true,
|
|
1028
|
+
modules,
|
|
1029
|
+
layout,
|
|
1030
|
+
directory
|
|
1031
|
+
);
|
|
1032
|
+
const {
|
|
1033
|
+
sendHardReloadInstruction
|
|
1034
|
+
} = await generateClientPageData(
|
|
1035
|
+
directory,
|
|
1036
|
+
state || {},
|
|
1037
|
+
[...objectAttributes, ...foundObjectAttributes],
|
|
1038
|
+
pageLoadHooks || [],
|
|
1039
|
+
DIST_DIR2,
|
|
1040
|
+
name
|
|
1041
|
+
);
|
|
1042
|
+
return sendHardReloadInstruction === true;
|
|
1043
|
+
};
|
|
1044
|
+
buildDynamicPage = async (DIST_DIR2, directory, pageInfo, req, res, middlewareData) => {
|
|
1045
|
+
directory = directory === "/" ? "" : directory;
|
|
1046
|
+
const filePath = pageInfo.filePath;
|
|
1047
|
+
initializeState();
|
|
1048
|
+
initializeObjectAttributes();
|
|
1049
|
+
resetLoadHooks();
|
|
1050
|
+
globalThis.__SERVER_PAGE_DATA_BANNER__ = "";
|
|
1051
|
+
let pageElements = async (props) => body();
|
|
1052
|
+
let metadata = async (props) => html();
|
|
1053
|
+
let modules = {};
|
|
1054
|
+
let pageIgnoresLayout = false;
|
|
1055
|
+
try {
|
|
1056
|
+
const {
|
|
1057
|
+
page,
|
|
1058
|
+
metadata: pageMetadata,
|
|
1059
|
+
shippedModules: shippedModules2,
|
|
1060
|
+
ignoreLayout,
|
|
1061
|
+
requestHook
|
|
1062
|
+
} = await import("file://" + filePath);
|
|
1063
|
+
if (requestHook) {
|
|
1064
|
+
const hook = requestHook;
|
|
1065
|
+
const doContinue = await hook(req, res);
|
|
1066
|
+
if (!doContinue) {
|
|
1067
|
+
return false;
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
if (shippedModules2 !== void 0) {
|
|
1071
|
+
modules = shippedModules2;
|
|
1072
|
+
}
|
|
1073
|
+
if (ignoreLayout) {
|
|
1074
|
+
pageIgnoresLayout = true;
|
|
1075
|
+
}
|
|
1076
|
+
pageElements = page;
|
|
1077
|
+
metadata = pageMetadata;
|
|
1078
|
+
} catch (e) {
|
|
1079
|
+
throw new Error(`Error in Page: ${directory}/page.ts - ${e}`);
|
|
1080
|
+
}
|
|
1081
|
+
if (modules !== void 0) {
|
|
1082
|
+
for (const [globalName, path4] of Object.entries(modules)) {
|
|
1083
|
+
modulesToShip.push({ globalName, path: path4 });
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
if (!metadata || metadata && typeof metadata !== "function") {
|
|
1087
|
+
console.warn(`WARNING: ${filePath} does not export a metadata function.`);
|
|
1088
|
+
}
|
|
1089
|
+
if (!pageElements) {
|
|
1090
|
+
console.warn(`WARNING: ${filePath} should export a const page, which is of type () => BuiltElement<"body">.`);
|
|
1091
|
+
}
|
|
1092
|
+
const pageProps = {
|
|
1093
|
+
pageName: directory,
|
|
1094
|
+
middlewareData
|
|
1095
|
+
};
|
|
1096
|
+
if (typeof pageElements === "function") {
|
|
1097
|
+
if (pageElements.constructor.name === "AsyncFunction") {
|
|
1098
|
+
pageElements = await pageElements(pageProps);
|
|
1099
|
+
} else {
|
|
1100
|
+
pageElements = pageElements(pageProps);
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
const layout = await fetchPageLayoutHTML(path.dirname(filePath));
|
|
1104
|
+
const resultHTML = await pageToHTML(
|
|
1105
|
+
path.join(DIST_DIR2, directory),
|
|
1106
|
+
pageElements,
|
|
1107
|
+
metadata,
|
|
1108
|
+
DIST_DIR2,
|
|
1109
|
+
"page",
|
|
1110
|
+
false,
|
|
1111
|
+
modules,
|
|
1112
|
+
layout,
|
|
1113
|
+
directory
|
|
1114
|
+
);
|
|
1115
|
+
await shipModules();
|
|
1116
|
+
return { resultHTML };
|
|
1117
|
+
};
|
|
1118
|
+
shipModules = async () => {
|
|
1119
|
+
for (const plugin of modulesToShip) {
|
|
1120
|
+
{
|
|
1121
|
+
if (shippedModules.has(plugin.globalName)) continue;
|
|
1122
|
+
shippedModules.set(plugin.globalName, true);
|
|
1123
|
+
}
|
|
1124
|
+
esbuild.build({
|
|
1125
|
+
entryPoints: [plugin.path],
|
|
1126
|
+
bundle: true,
|
|
1127
|
+
outfile: path.join(DIST_DIR, "shipped", plugin.globalName + ".js"),
|
|
1128
|
+
format: "iife",
|
|
1129
|
+
platform: "browser",
|
|
1130
|
+
globalName: plugin.globalName,
|
|
1131
|
+
minify: true,
|
|
1132
|
+
treeShaking: true
|
|
1133
|
+
});
|
|
1134
|
+
}
|
|
1135
|
+
modulesToShip = [];
|
|
1136
|
+
};
|
|
1137
|
+
build = async () => {
|
|
1138
|
+
if (options.quiet === true) {
|
|
1139
|
+
console.log = function() {
|
|
1140
|
+
};
|
|
1141
|
+
console.error = function() {
|
|
1142
|
+
};
|
|
1143
|
+
console.warn = function() {
|
|
1144
|
+
};
|
|
1145
|
+
}
|
|
1146
|
+
try {
|
|
1147
|
+
{
|
|
1148
|
+
log2(bold(yellow(" -- Elegance.JS -- ")));
|
|
1149
|
+
if (options.environment === "production") {
|
|
1150
|
+
log2(
|
|
1151
|
+
" - ",
|
|
1152
|
+
bgYellow(bold(black(" NOTE "))),
|
|
1153
|
+
" : ",
|
|
1154
|
+
white("In production mode, no "),
|
|
1155
|
+
underline("console.log() "),
|
|
1156
|
+
white("statements will be shown on the client, and all code will be minified.")
|
|
1157
|
+
);
|
|
1158
|
+
log2("");
|
|
1159
|
+
}
|
|
1160
|
+
}
|
|
1161
|
+
if (options.preCompile) {
|
|
1162
|
+
options.preCompile();
|
|
1163
|
+
}
|
|
1164
|
+
const start = performance.now();
|
|
1165
|
+
let shouldClientHardReload;
|
|
1166
|
+
{
|
|
1167
|
+
const { shouldClientHardReload: doReload } = await buildLayouts();
|
|
1168
|
+
if (doReload) shouldClientHardReload = true;
|
|
1169
|
+
}
|
|
1170
|
+
{
|
|
1171
|
+
const { shouldClientHardReload: doReload } = await buildPages(path.resolve(DIST_DIR));
|
|
1172
|
+
if (doReload) shouldClientHardReload = true;
|
|
1173
|
+
}
|
|
1174
|
+
await shipModules();
|
|
1175
|
+
const pagesBuilt = performance.now();
|
|
1176
|
+
await buildClient(DIST_DIR);
|
|
1177
|
+
const end = performance.now();
|
|
1178
|
+
if (options.publicDirectory) {
|
|
1179
|
+
log2("Recursively copying public directory.. this may take a while.");
|
|
1180
|
+
const src = path.relative(process.cwd(), options.publicDirectory.path);
|
|
1181
|
+
if (fs.existsSync(src) === false) {
|
|
1182
|
+
console.warn("WARNING: Public directory not found, an attempt will be made create it..");
|
|
1183
|
+
fs.mkdirSync(src, { recursive: true });
|
|
1184
|
+
}
|
|
1185
|
+
await fs.promises.cp(src, path.join(DIST_DIR), { recursive: true });
|
|
1186
|
+
}
|
|
1187
|
+
{
|
|
1188
|
+
log2(`Took ${Math.round(pagesBuilt - start)}ms to Build Pages.`);
|
|
1189
|
+
log2(`Took ${Math.round(end - pagesBuilt)}ms to Build Client.`);
|
|
1190
|
+
}
|
|
1191
|
+
process.send?.({ event: "message", data: "set-pages-and-layouts", content: JSON.stringify({ pageMap: Array.from(PAGE_MAP), layoutMap: Array.from(LAYOUT_MAP) }) });
|
|
1192
|
+
process.send?.({ event: "message", data: "compile-finish" });
|
|
1193
|
+
if (shouldClientHardReload) {
|
|
1194
|
+
process.send({ event: "message", data: "hard-reload" });
|
|
1195
|
+
} else {
|
|
1196
|
+
process.send({ event: "message", data: "soft-reload" });
|
|
1197
|
+
}
|
|
1198
|
+
} catch (e) {
|
|
1199
|
+
console.error("Build Failed! Received Error:");
|
|
1200
|
+
console.error(e);
|
|
1201
|
+
return false;
|
|
1202
|
+
}
|
|
1203
|
+
return true;
|
|
1204
|
+
};
|
|
1205
|
+
(async () => {
|
|
1206
|
+
if (process.env.DO_BUILD === "true") await build();
|
|
1207
|
+
})();
|
|
1208
|
+
}
|
|
1209
|
+
});
|
|
1210
|
+
|
|
1211
|
+
// src/compile_docs.ts
|
|
1212
|
+
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
1213
|
+
|
|
1214
|
+
// src/build.ts
|
|
1215
|
+
import fs3 from "fs";
|
|
1216
|
+
import path2 from "path";
|
|
1217
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
8
1218
|
import child_process from "node:child_process";
|
|
9
1219
|
import http from "http";
|
|
10
1220
|
|
|
1221
|
+
// src/server/server.ts
|
|
1222
|
+
import {
|
|
1223
|
+
createServer as createHttpServer
|
|
1224
|
+
} from "http";
|
|
1225
|
+
import {
|
|
1226
|
+
promises as fs2
|
|
1227
|
+
} from "fs";
|
|
1228
|
+
import {
|
|
1229
|
+
join,
|
|
1230
|
+
normalize,
|
|
1231
|
+
extname,
|
|
1232
|
+
dirname
|
|
1233
|
+
} from "path";
|
|
1234
|
+
import {
|
|
1235
|
+
pathToFileURL
|
|
1236
|
+
} from "url";
|
|
1237
|
+
|
|
11
1238
|
// src/log.ts
|
|
12
1239
|
var quiet = false;
|
|
13
1240
|
function setQuiet(value) {
|
|
@@ -44,18 +1271,445 @@ var log = {
|
|
|
44
1271
|
error: logError
|
|
45
1272
|
};
|
|
46
1273
|
|
|
1274
|
+
// src/server/server.ts
|
|
1275
|
+
import {
|
|
1276
|
+
gzip,
|
|
1277
|
+
deflate
|
|
1278
|
+
} from "zlib";
|
|
1279
|
+
import {
|
|
1280
|
+
promisify
|
|
1281
|
+
} from "util";
|
|
1282
|
+
var gzipAsync = promisify(gzip);
|
|
1283
|
+
var deflateAsync = promisify(deflate);
|
|
1284
|
+
var MIME_TYPES = {
|
|
1285
|
+
".html": "text/html; charset=utf-8",
|
|
1286
|
+
".css": "text/css; charset=utf-8",
|
|
1287
|
+
".js": "application/javascript; charset=utf-8",
|
|
1288
|
+
".json": "application/json; charset=utf-8",
|
|
1289
|
+
".png": "image/png",
|
|
1290
|
+
".jpg": "image/jpeg",
|
|
1291
|
+
".jpeg": "image/jpeg",
|
|
1292
|
+
".gif": "image/gif",
|
|
1293
|
+
".svg": "image/svg+xml",
|
|
1294
|
+
".ico": "image/x-icon",
|
|
1295
|
+
".txt": "text/plain; charset=utf-8"
|
|
1296
|
+
};
|
|
1297
|
+
function startServer({
|
|
1298
|
+
root,
|
|
1299
|
+
pagesDirectory,
|
|
1300
|
+
port = 3e3,
|
|
1301
|
+
host = "localhost",
|
|
1302
|
+
environment: environment2 = "production",
|
|
1303
|
+
DIST_DIR: DIST_DIR2
|
|
1304
|
+
}) {
|
|
1305
|
+
if (!root) throw new Error("Root directory must be specified.");
|
|
1306
|
+
if (!pagesDirectory) throw new Error("Pages directory must be specified.");
|
|
1307
|
+
root = normalize(root).replace(/[\\/]+$/, "");
|
|
1308
|
+
pagesDirectory = normalize(pagesDirectory).replace(/[\\/]+$/, "");
|
|
1309
|
+
const requestHandler = async (req, res) => {
|
|
1310
|
+
try {
|
|
1311
|
+
if (!req.url) {
|
|
1312
|
+
await sendResponse(req, res, 400, {
|
|
1313
|
+
"Content-Type": "text/plain; charset=utf-8"
|
|
1314
|
+
}, "Bad Request");
|
|
1315
|
+
return;
|
|
1316
|
+
}
|
|
1317
|
+
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
1318
|
+
res.setHeader("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS");
|
|
1319
|
+
res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
|
|
1320
|
+
if (req.method === "OPTIONS") {
|
|
1321
|
+
res.writeHead(204);
|
|
1322
|
+
res.end();
|
|
1323
|
+
if (environment2 === "development") {
|
|
1324
|
+
log.info(req.method, "::", req.url, "-", res.statusCode);
|
|
1325
|
+
}
|
|
1326
|
+
return;
|
|
1327
|
+
}
|
|
1328
|
+
const url = new URL(req.url, `http://${req.headers.host}`);
|
|
1329
|
+
if (url.pathname.startsWith("/api/")) {
|
|
1330
|
+
await handleApiRequest(pagesDirectory, url.pathname, req, res);
|
|
1331
|
+
} else if (PAGE_MAP2.has(url.pathname)) {
|
|
1332
|
+
await handlePageRequest(root, pagesDirectory, url.pathname, req, res, DIST_DIR2, PAGE_MAP2.get(url.pathname));
|
|
1333
|
+
} else {
|
|
1334
|
+
await handleStaticRequest(root, pagesDirectory, url.pathname, req, res, DIST_DIR2);
|
|
1335
|
+
}
|
|
1336
|
+
if (environment2 === "development") {
|
|
1337
|
+
log.info(req.method, "::", req.url, "-", res.statusCode);
|
|
1338
|
+
}
|
|
1339
|
+
} catch (err) {
|
|
1340
|
+
log.error(err);
|
|
1341
|
+
await sendResponse(req, res, 500, {
|
|
1342
|
+
"Content-Type": "text/plain; charset=utf-8"
|
|
1343
|
+
}, "Internal Server Error");
|
|
1344
|
+
}
|
|
1345
|
+
};
|
|
1346
|
+
function attemptListen(p) {
|
|
1347
|
+
const server = createHttpServer(requestHandler);
|
|
1348
|
+
server.on("error", (err) => {
|
|
1349
|
+
if (err.code === "EADDRINUSE") {
|
|
1350
|
+
attemptListen(p + 1);
|
|
1351
|
+
} else {
|
|
1352
|
+
console.error(err);
|
|
1353
|
+
}
|
|
1354
|
+
});
|
|
1355
|
+
server.listen(p, host, () => {
|
|
1356
|
+
log.info(`Server running at http://${host}:${p}/`);
|
|
1357
|
+
});
|
|
1358
|
+
return server;
|
|
1359
|
+
}
|
|
1360
|
+
return attemptListen(port);
|
|
1361
|
+
}
|
|
1362
|
+
async function getTargetInfo(root, pathname) {
|
|
1363
|
+
const originalPathname = pathname;
|
|
1364
|
+
const filePath = normalize(join(root, decodeURIComponent(pathname))).replace(/[\\/]+$/, "");
|
|
1365
|
+
if (!filePath.startsWith(root)) {
|
|
1366
|
+
throw new Error("Forbidden");
|
|
1367
|
+
}
|
|
1368
|
+
let stats;
|
|
1369
|
+
try {
|
|
1370
|
+
stats = await fs2.stat(filePath);
|
|
1371
|
+
} catch {
|
|
1372
|
+
}
|
|
1373
|
+
let targetDir;
|
|
1374
|
+
if (stats) {
|
|
1375
|
+
targetDir = stats.isDirectory() ? filePath : dirname(filePath);
|
|
1376
|
+
} else {
|
|
1377
|
+
targetDir = originalPathname.endsWith("/") ? filePath : dirname(filePath);
|
|
1378
|
+
}
|
|
1379
|
+
return {
|
|
1380
|
+
filePath,
|
|
1381
|
+
targetDir,
|
|
1382
|
+
stats
|
|
1383
|
+
};
|
|
1384
|
+
}
|
|
1385
|
+
function getMiddlewareDirs(base, parts) {
|
|
1386
|
+
const middlewareDirs = [];
|
|
1387
|
+
let current = base;
|
|
1388
|
+
middlewareDirs.push(current);
|
|
1389
|
+
for (const part of parts) {
|
|
1390
|
+
current = join(current, part);
|
|
1391
|
+
middlewareDirs.push(current);
|
|
1392
|
+
}
|
|
1393
|
+
return middlewareDirs;
|
|
1394
|
+
}
|
|
1395
|
+
async function collectMiddlewares(dirs) {
|
|
1396
|
+
const middlewares = [];
|
|
1397
|
+
for (const dir of dirs) {
|
|
1398
|
+
const mwPath = join(dir, "middleware.ts");
|
|
1399
|
+
let mwModule;
|
|
1400
|
+
try {
|
|
1401
|
+
await fs2.access(mwPath);
|
|
1402
|
+
const url = pathToFileURL(mwPath).href;
|
|
1403
|
+
mwModule = await import(url);
|
|
1404
|
+
} catch {
|
|
1405
|
+
continue;
|
|
1406
|
+
}
|
|
1407
|
+
const mwKeys = Object.keys(mwModule).sort();
|
|
1408
|
+
for (const key of mwKeys) {
|
|
1409
|
+
const f = mwModule[key];
|
|
1410
|
+
if (typeof f === "function" && !middlewares.some((existing) => existing === f)) {
|
|
1411
|
+
middlewares.push(f);
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
return middlewares;
|
|
1416
|
+
}
|
|
1417
|
+
async function handlePageRequest(root, pagesDirectory, pathname, req, res, DIST_DIR2, pageInfo) {
|
|
1418
|
+
try {
|
|
1419
|
+
const {
|
|
1420
|
+
filePath,
|
|
1421
|
+
targetDir,
|
|
1422
|
+
stats
|
|
1423
|
+
} = await getTargetInfo(root, pathname);
|
|
1424
|
+
const relDir = targetDir.slice(root.length).replace(/^[\/\\]+/, "");
|
|
1425
|
+
const parts = relDir.split(/[\\/]/).filter(Boolean);
|
|
1426
|
+
const middlewareDirs = getMiddlewareDirs(pagesDirectory, parts);
|
|
1427
|
+
const middlewares = await collectMiddlewares(middlewareDirs);
|
|
1428
|
+
const data = {};
|
|
1429
|
+
const isDynamic = pageInfo.isDynamic;
|
|
1430
|
+
const handlerPath = isDynamic ? pageInfo.filePath : join(filePath, "index.html");
|
|
1431
|
+
let hasHandler = false;
|
|
1432
|
+
try {
|
|
1433
|
+
await fs2.access(handlerPath);
|
|
1434
|
+
hasHandler = true;
|
|
1435
|
+
} catch {
|
|
1436
|
+
}
|
|
1437
|
+
const finalHandler = async (req2, res2) => {
|
|
1438
|
+
if (!hasHandler) {
|
|
1439
|
+
await respondWithErrorPage(root, pathname, 404, req2, res2);
|
|
1440
|
+
return;
|
|
1441
|
+
}
|
|
1442
|
+
if (isDynamic) {
|
|
1443
|
+
try {
|
|
1444
|
+
const {
|
|
1445
|
+
buildDynamicPage: buildDynamicPage2
|
|
1446
|
+
} = await Promise.resolve().then(() => (init_page_compiler(), page_compiler_exports));
|
|
1447
|
+
const result = await buildDynamicPage2(
|
|
1448
|
+
DIST_DIR2,
|
|
1449
|
+
pathname,
|
|
1450
|
+
pageInfo,
|
|
1451
|
+
req2,
|
|
1452
|
+
res2,
|
|
1453
|
+
data
|
|
1454
|
+
);
|
|
1455
|
+
if (result === false) {
|
|
1456
|
+
return;
|
|
1457
|
+
}
|
|
1458
|
+
const {
|
|
1459
|
+
resultHTML
|
|
1460
|
+
} = result;
|
|
1461
|
+
if (resultHTML === false) {
|
|
1462
|
+
return;
|
|
1463
|
+
}
|
|
1464
|
+
await sendResponse(req2, res2, 200, {
|
|
1465
|
+
"Content-Type": MIME_TYPES[".html"]
|
|
1466
|
+
}, resultHTML);
|
|
1467
|
+
} catch (err) {
|
|
1468
|
+
log.error("Error building dynamic page -", err);
|
|
1469
|
+
}
|
|
1470
|
+
} else {
|
|
1471
|
+
const ext = extname(handlerPath).toLowerCase();
|
|
1472
|
+
const contentType = MIME_TYPES[ext] || "application/octet-stream";
|
|
1473
|
+
const fileData = await fs2.readFile(handlerPath);
|
|
1474
|
+
await sendResponse(req2, res2, 200, {
|
|
1475
|
+
"Content-Type": contentType
|
|
1476
|
+
}, fileData);
|
|
1477
|
+
}
|
|
1478
|
+
};
|
|
1479
|
+
const composed = composeMiddlewares(middlewares, finalHandler, {
|
|
1480
|
+
isApi: false,
|
|
1481
|
+
root,
|
|
1482
|
+
pathname,
|
|
1483
|
+
data
|
|
1484
|
+
});
|
|
1485
|
+
await composed(req, res);
|
|
1486
|
+
} catch (err) {
|
|
1487
|
+
if (err.message === "Forbidden") {
|
|
1488
|
+
await sendResponse(req, res, 403, {
|
|
1489
|
+
"Content-Type": "text/plain; charset=utf-8"
|
|
1490
|
+
}, "Forbidden");
|
|
1491
|
+
} else {
|
|
1492
|
+
throw err;
|
|
1493
|
+
}
|
|
1494
|
+
}
|
|
1495
|
+
}
|
|
1496
|
+
async function handleStaticRequest(root, pagesDirectory, pathname, req, res, DIST_DIR2) {
|
|
1497
|
+
try {
|
|
1498
|
+
const {
|
|
1499
|
+
filePath,
|
|
1500
|
+
targetDir,
|
|
1501
|
+
stats
|
|
1502
|
+
} = await getTargetInfo(root, pathname);
|
|
1503
|
+
const relDir = targetDir.slice(root.length).replace(/^[\/\\]+/, "");
|
|
1504
|
+
const parts = relDir.split(/[\\/]/).filter(Boolean);
|
|
1505
|
+
const middlewareDirs = getMiddlewareDirs(pagesDirectory, parts);
|
|
1506
|
+
const middlewares = await collectMiddlewares(middlewareDirs);
|
|
1507
|
+
let handlerPath = filePath;
|
|
1508
|
+
if (stats && stats.isDirectory()) {
|
|
1509
|
+
handlerPath = join(filePath, "index.html");
|
|
1510
|
+
}
|
|
1511
|
+
let hasHandler = false;
|
|
1512
|
+
try {
|
|
1513
|
+
await fs2.access(handlerPath);
|
|
1514
|
+
hasHandler = true;
|
|
1515
|
+
} catch {
|
|
1516
|
+
}
|
|
1517
|
+
const finalHandler = async (req2, res2) => {
|
|
1518
|
+
if (!hasHandler) {
|
|
1519
|
+
await respondWithErrorPage(root, pathname, 404, req2, res2);
|
|
1520
|
+
return;
|
|
1521
|
+
}
|
|
1522
|
+
const ext = extname(handlerPath).toLowerCase();
|
|
1523
|
+
const contentType = MIME_TYPES[ext] || "application/octet-stream";
|
|
1524
|
+
const fileData = await fs2.readFile(handlerPath);
|
|
1525
|
+
await sendResponse(req2, res2, 200, {
|
|
1526
|
+
"Content-Type": contentType
|
|
1527
|
+
}, fileData);
|
|
1528
|
+
};
|
|
1529
|
+
const composed = composeMiddlewares(middlewares, finalHandler, {
|
|
1530
|
+
isApi: false,
|
|
1531
|
+
root,
|
|
1532
|
+
pathname
|
|
1533
|
+
});
|
|
1534
|
+
await composed(req, res);
|
|
1535
|
+
} catch (err) {
|
|
1536
|
+
if (err.message === "Forbidden") {
|
|
1537
|
+
await sendResponse(req, res, 403, {
|
|
1538
|
+
"Content-Type": "text/plain; charset=utf-8"
|
|
1539
|
+
}, "Forbidden");
|
|
1540
|
+
} else {
|
|
1541
|
+
throw err;
|
|
1542
|
+
}
|
|
1543
|
+
}
|
|
1544
|
+
}
|
|
1545
|
+
async function handleApiRequest(pagesDirectory, pathname, req, res) {
|
|
1546
|
+
const apiSubPath = pathname.slice("/api/".length);
|
|
1547
|
+
const parts = apiSubPath.split("/").filter(Boolean);
|
|
1548
|
+
const middlewareDirs = getMiddlewareDirs(join(pagesDirectory, "api"), parts);
|
|
1549
|
+
const middlewares = await collectMiddlewares(middlewareDirs);
|
|
1550
|
+
const routeDir = middlewareDirs[middlewareDirs.length - 1];
|
|
1551
|
+
const routePath = join(routeDir, "route.ts");
|
|
1552
|
+
let hasRoute = false;
|
|
1553
|
+
try {
|
|
1554
|
+
await fs2.access(routePath);
|
|
1555
|
+
hasRoute = true;
|
|
1556
|
+
} catch {
|
|
1557
|
+
}
|
|
1558
|
+
let fn = null;
|
|
1559
|
+
let module = null;
|
|
1560
|
+
if (hasRoute) {
|
|
1561
|
+
try {
|
|
1562
|
+
const moduleUrl = pathToFileURL(routePath).href;
|
|
1563
|
+
module = await import(moduleUrl);
|
|
1564
|
+
fn = module[req.method];
|
|
1565
|
+
} catch (err) {
|
|
1566
|
+
console.error(err);
|
|
1567
|
+
return respondWithJsonError(req, res, 500, "Internal Server Error");
|
|
1568
|
+
}
|
|
1569
|
+
}
|
|
1570
|
+
const finalHandler = async (req2, res2) => {
|
|
1571
|
+
if (!hasRoute) {
|
|
1572
|
+
return respondWithJsonError(req2, res2, 404, "Not Found");
|
|
1573
|
+
}
|
|
1574
|
+
if (typeof fn !== "function") {
|
|
1575
|
+
return respondWithJsonError(req2, res2, 405, "Method Not Allowed");
|
|
1576
|
+
}
|
|
1577
|
+
await fn(req2, res2);
|
|
1578
|
+
};
|
|
1579
|
+
const composed = composeMiddlewares(middlewares, finalHandler, {
|
|
1580
|
+
isApi: true
|
|
1581
|
+
});
|
|
1582
|
+
await composed(req, res);
|
|
1583
|
+
}
|
|
1584
|
+
function composeMiddlewares(mws, final, options3) {
|
|
1585
|
+
return async function(req, res) {
|
|
1586
|
+
let index = 0;
|
|
1587
|
+
async function dispatch(err) {
|
|
1588
|
+
if (err) {
|
|
1589
|
+
if (options3.isApi) {
|
|
1590
|
+
return respondWithJsonError(req, res, 500, err.message || "Internal Server Error");
|
|
1591
|
+
} else {
|
|
1592
|
+
return await respondWithErrorPage(options3.root, options3.pathname, 500, req, res);
|
|
1593
|
+
}
|
|
1594
|
+
}
|
|
1595
|
+
if (index >= mws.length) {
|
|
1596
|
+
return await final(req, res);
|
|
1597
|
+
}
|
|
1598
|
+
const thisMw = mws[index++];
|
|
1599
|
+
const next = (e) => dispatch(e);
|
|
1600
|
+
const onceNext = (nextFn) => {
|
|
1601
|
+
let called = false;
|
|
1602
|
+
return async (e) => {
|
|
1603
|
+
if (called) {
|
|
1604
|
+
log.warn("next() was called in a middleware more than once.");
|
|
1605
|
+
return;
|
|
1606
|
+
}
|
|
1607
|
+
called = true;
|
|
1608
|
+
await nextFn(e);
|
|
1609
|
+
};
|
|
1610
|
+
};
|
|
1611
|
+
try {
|
|
1612
|
+
await thisMw(req, res, onceNext(next), options3.data || {});
|
|
1613
|
+
} catch (error) {
|
|
1614
|
+
await dispatch(error);
|
|
1615
|
+
}
|
|
1616
|
+
}
|
|
1617
|
+
await dispatch();
|
|
1618
|
+
};
|
|
1619
|
+
}
|
|
1620
|
+
async function respondWithJsonError(req, res, code, message) {
|
|
1621
|
+
const body2 = JSON.stringify({
|
|
1622
|
+
error: message
|
|
1623
|
+
});
|
|
1624
|
+
await sendResponse(req, res, code, {
|
|
1625
|
+
"Content-Type": "application/json; charset=utf-8"
|
|
1626
|
+
}, body2);
|
|
1627
|
+
}
|
|
1628
|
+
async function respondWithErrorPage(root, pathname, code, req, res) {
|
|
1629
|
+
let currentPath = normalize(join(root, decodeURIComponent(pathname)));
|
|
1630
|
+
let tried = /* @__PURE__ */ new Set();
|
|
1631
|
+
let errorFilePath = null;
|
|
1632
|
+
while (currentPath.startsWith(root)) {
|
|
1633
|
+
const candidate = join(currentPath, `${code}.html`);
|
|
1634
|
+
if (!tried.has(candidate)) {
|
|
1635
|
+
try {
|
|
1636
|
+
await fs2.access(candidate);
|
|
1637
|
+
errorFilePath = candidate;
|
|
1638
|
+
break;
|
|
1639
|
+
} catch {
|
|
1640
|
+
}
|
|
1641
|
+
tried.add(candidate);
|
|
1642
|
+
}
|
|
1643
|
+
const parent = dirname(currentPath);
|
|
1644
|
+
if (parent === currentPath) break;
|
|
1645
|
+
currentPath = parent;
|
|
1646
|
+
}
|
|
1647
|
+
if (!errorFilePath) {
|
|
1648
|
+
const fallback = join(root, `${code}.html`);
|
|
1649
|
+
try {
|
|
1650
|
+
await fs2.access(fallback);
|
|
1651
|
+
errorFilePath = fallback;
|
|
1652
|
+
} catch {
|
|
1653
|
+
}
|
|
1654
|
+
}
|
|
1655
|
+
if (errorFilePath) {
|
|
1656
|
+
try {
|
|
1657
|
+
const html2 = await fs2.readFile(errorFilePath, "utf8");
|
|
1658
|
+
await sendResponse(req, res, code, {
|
|
1659
|
+
"Content-Type": "text/html; charset=utf-8"
|
|
1660
|
+
}, html2);
|
|
1661
|
+
return;
|
|
1662
|
+
} catch {
|
|
1663
|
+
}
|
|
1664
|
+
}
|
|
1665
|
+
await sendResponse(req, res, code, {
|
|
1666
|
+
"Content-Type": "text/plain; charset=utf-8"
|
|
1667
|
+
}, `${code} Error`);
|
|
1668
|
+
}
|
|
1669
|
+
function isCompressible(contentType) {
|
|
1670
|
+
if (!contentType) return false;
|
|
1671
|
+
return /text\/|javascript|json|xml|svg/.test(contentType);
|
|
1672
|
+
}
|
|
1673
|
+
async function sendResponse(req, res, status, headers, body2) {
|
|
1674
|
+
let bufferBody = typeof body2 === "string" ? Buffer.from(body2) : body2;
|
|
1675
|
+
const accept = req.headers["accept-encoding"] || "";
|
|
1676
|
+
let encoding = null;
|
|
1677
|
+
if (accept.match(/\bgzip\b/)) {
|
|
1678
|
+
encoding = "gzip";
|
|
1679
|
+
} else if (accept.match(/\bdeflate\b/)) {
|
|
1680
|
+
encoding = "deflate";
|
|
1681
|
+
}
|
|
1682
|
+
if (!encoding || !isCompressible(headers["Content-Type"] || "")) {
|
|
1683
|
+
res.writeHead(status, headers);
|
|
1684
|
+
res.end(bufferBody);
|
|
1685
|
+
return;
|
|
1686
|
+
}
|
|
1687
|
+
const compressor = encoding === "gzip" ? gzipAsync : deflateAsync;
|
|
1688
|
+
try {
|
|
1689
|
+
const compressed = await compressor(bufferBody);
|
|
1690
|
+
headers["Content-Encoding"] = encoding;
|
|
1691
|
+
headers["Vary"] = "Accept-Encoding";
|
|
1692
|
+
res.writeHead(status, headers);
|
|
1693
|
+
res.end(compressed);
|
|
1694
|
+
} catch (err) {
|
|
1695
|
+
log.error("Compression error:", err);
|
|
1696
|
+
res.writeHead(status, headers);
|
|
1697
|
+
res.end(bufferBody);
|
|
1698
|
+
}
|
|
1699
|
+
}
|
|
1700
|
+
|
|
47
1701
|
// src/build.ts
|
|
48
|
-
var
|
|
49
|
-
var
|
|
50
|
-
var
|
|
51
|
-
var builderPath =
|
|
52
|
-
var
|
|
1702
|
+
var __filename2 = fileURLToPath3(import.meta.url);
|
|
1703
|
+
var __dirname2 = path2.dirname(__filename2);
|
|
1704
|
+
var packageDir2 = path2.resolve(__dirname2, "..");
|
|
1705
|
+
var builderPath = path2.resolve(packageDir2, "./dist/page_compiler.mjs");
|
|
1706
|
+
var yellow2 = (text) => {
|
|
53
1707
|
return `\x1B[38;2;238;184;68m${text}`;
|
|
54
1708
|
};
|
|
55
|
-
var
|
|
1709
|
+
var bold2 = (text) => {
|
|
56
1710
|
return `\x1B[1m${text}`;
|
|
57
1711
|
};
|
|
58
|
-
var
|
|
1712
|
+
var white2 = (text) => {
|
|
59
1713
|
return `\x1B[38;2;255;247;229m${text}`;
|
|
60
1714
|
};
|
|
61
1715
|
var green = (text) => {
|
|
@@ -64,24 +1718,26 @@ var green = (text) => {
|
|
|
64
1718
|
var finishLog = (...text) => {
|
|
65
1719
|
log.info(text.map((text2) => `${text2}\x1B[0m`).join(""));
|
|
66
1720
|
};
|
|
67
|
-
var
|
|
68
|
-
var
|
|
1721
|
+
var PAGE_MAP2 = /* @__PURE__ */ new Map();
|
|
1722
|
+
var LAYOUT_MAP3 = /* @__PURE__ */ new Map();
|
|
1723
|
+
var options2 = process.env.OPTIONS;
|
|
1724
|
+
var getAllSubdirectories2 = (dir, baseDir = dir) => {
|
|
69
1725
|
let directories = [];
|
|
70
|
-
const items =
|
|
1726
|
+
const items = fs3.readdirSync(dir, { withFileTypes: true });
|
|
71
1727
|
for (const item of items) {
|
|
72
1728
|
if (item.isDirectory()) {
|
|
73
|
-
const fullPath =
|
|
74
|
-
const relativePath =
|
|
1729
|
+
const fullPath = path2.join(dir, item.name);
|
|
1730
|
+
const relativePath = path2.relative(baseDir, fullPath);
|
|
75
1731
|
directories.push(relativePath);
|
|
76
|
-
directories = directories.concat(
|
|
1732
|
+
directories = directories.concat(getAllSubdirectories2(fullPath, baseDir));
|
|
77
1733
|
}
|
|
78
1734
|
}
|
|
79
1735
|
return directories;
|
|
80
1736
|
};
|
|
81
1737
|
var child = void 0;
|
|
82
1738
|
var isBuilding = false;
|
|
83
|
-
var runBuild = (filepath,
|
|
84
|
-
const optionsString = JSON.stringify(
|
|
1739
|
+
var runBuild = (filepath, DIST_DIR2) => {
|
|
1740
|
+
const optionsString = JSON.stringify(options2);
|
|
85
1741
|
if (isBuilding) {
|
|
86
1742
|
return;
|
|
87
1743
|
}
|
|
@@ -91,8 +1747,16 @@ var runBuild = (filepath, DIST_DIR) => {
|
|
|
91
1747
|
}
|
|
92
1748
|
child = child_process.spawn("node", [filepath], {
|
|
93
1749
|
stdio: ["inherit", "inherit", "inherit", "ipc"],
|
|
94
|
-
env: {
|
|
1750
|
+
env: {
|
|
1751
|
+
...process.env,
|
|
1752
|
+
DIST_DIR: DIST_DIR2,
|
|
1753
|
+
OPTIONS: optionsString,
|
|
1754
|
+
PACKAGE_PATH: packageDir2,
|
|
1755
|
+
DO_BUILD: "true"
|
|
1756
|
+
}
|
|
95
1757
|
});
|
|
1758
|
+
process.env.OPTIONS = optionsString;
|
|
1759
|
+
process.env.DIST_DIR = DIST_DIR2;
|
|
96
1760
|
child.on("error", () => {
|
|
97
1761
|
log.error("Failed to start child process.");
|
|
98
1762
|
});
|
|
@@ -112,17 +1776,21 @@ var runBuild = (filepath, DIST_DIR) => {
|
|
|
112
1776
|
`);
|
|
113
1777
|
} else if (data === "compile-finish") {
|
|
114
1778
|
isBuilding = false;
|
|
115
|
-
if (
|
|
1779
|
+
if (options2.postCompile) {
|
|
116
1780
|
finishLog(
|
|
117
|
-
|
|
1781
|
+
white2("Calling post-compile hook..")
|
|
118
1782
|
);
|
|
119
|
-
|
|
1783
|
+
options2.postCompile();
|
|
120
1784
|
}
|
|
1785
|
+
} else if (data === "set-pages-and-layouts") {
|
|
1786
|
+
const { pageMap, layoutMap } = JSON.parse(message.content);
|
|
1787
|
+
PAGE_MAP2 = new Map(pageMap);
|
|
1788
|
+
LAYOUT_MAP3 = new Map(layoutMap);
|
|
121
1789
|
}
|
|
122
1790
|
});
|
|
123
1791
|
};
|
|
124
|
-
var
|
|
125
|
-
runBuild(builderPath,
|
|
1792
|
+
var build2 = (DIST_DIR2) => {
|
|
1793
|
+
runBuild(builderPath, DIST_DIR2);
|
|
126
1794
|
};
|
|
127
1795
|
var isTimedOut = false;
|
|
128
1796
|
var currentWatchers = [];
|
|
@@ -130,7 +1798,7 @@ var httpStream;
|
|
|
130
1798
|
var registerListener = async () => {
|
|
131
1799
|
const server = http.createServer((req, res) => {
|
|
132
1800
|
if (req.url === "/events") {
|
|
133
|
-
finishLog(
|
|
1801
|
+
finishLog(white2("Client listening for changes.."));
|
|
134
1802
|
res.writeHead(200, {
|
|
135
1803
|
"Content-Type": "text/event-stream",
|
|
136
1804
|
"Cache-Control": "no-cache",
|
|
@@ -151,30 +1819,40 @@ var registerListener = async () => {
|
|
|
151
1819
|
res.end("Not Found");
|
|
152
1820
|
}
|
|
153
1821
|
});
|
|
154
|
-
server.listen(
|
|
155
|
-
finishLog(
|
|
1822
|
+
server.listen(options2.hotReload.port, () => {
|
|
1823
|
+
finishLog(bold2(green("Hot-Reload server online!")));
|
|
156
1824
|
});
|
|
157
1825
|
};
|
|
158
1826
|
var compile = async (props) => {
|
|
159
|
-
|
|
160
|
-
setQuiet(
|
|
161
|
-
const watch =
|
|
162
|
-
const BUILD_FLAG =
|
|
163
|
-
if (!
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
1827
|
+
options2 = props;
|
|
1828
|
+
setQuiet(options2.quiet ?? false);
|
|
1829
|
+
const watch = options2.hotReload !== void 0;
|
|
1830
|
+
const BUILD_FLAG = path2.join(options2.outputDirectory, "ELEGANCE_BUILD_FLAG");
|
|
1831
|
+
if (!fs3.existsSync(options2.outputDirectory)) {
|
|
1832
|
+
fs3.mkdirSync(options2.outputDirectory, { recursive: true });
|
|
1833
|
+
fs3.writeFileSync(
|
|
1834
|
+
path2.join(BUILD_FLAG),
|
|
167
1835
|
"This file just marks this directory as one containing an Elegance Build.",
|
|
168
1836
|
"utf-8"
|
|
169
1837
|
);
|
|
170
1838
|
} else {
|
|
171
|
-
if (!
|
|
1839
|
+
if (!fs3.existsSync(BUILD_FLAG)) {
|
|
172
1840
|
throw `The output directory already exists, but is not an Elegance Build directory.`;
|
|
173
1841
|
}
|
|
174
1842
|
}
|
|
175
|
-
const
|
|
176
|
-
if (!
|
|
177
|
-
|
|
1843
|
+
const DIST_DIR2 = path2.join(props.outputDirectory, "dist");
|
|
1844
|
+
if (!fs3.existsSync(DIST_DIR2)) {
|
|
1845
|
+
fs3.mkdirSync(DIST_DIR2, { recursive: true });
|
|
1846
|
+
}
|
|
1847
|
+
if (options2.server != void 0 && options2.server.runServer == true) {
|
|
1848
|
+
startServer({
|
|
1849
|
+
root: options2.server.root ?? DIST_DIR2,
|
|
1850
|
+
environment: options2.environment,
|
|
1851
|
+
port: options2.server.port ?? 3e3,
|
|
1852
|
+
host: options2.server.host ?? "localhost",
|
|
1853
|
+
DIST_DIR: DIST_DIR2,
|
|
1854
|
+
pagesDirectory: options2.pagesDirectory
|
|
1855
|
+
});
|
|
178
1856
|
}
|
|
179
1857
|
if (watch) {
|
|
180
1858
|
await registerListener();
|
|
@@ -182,29 +1860,29 @@ var compile = async (props) => {
|
|
|
182
1860
|
watcher.close();
|
|
183
1861
|
}
|
|
184
1862
|
let extra = [];
|
|
185
|
-
if (
|
|
186
|
-
const dirs =
|
|
1863
|
+
if (options2.hotReload?.extraWatchDirectories) {
|
|
1864
|
+
const dirs = options2.hotReload?.extraWatchDirectories ?? [];
|
|
187
1865
|
if (dirs.length !== 0) {
|
|
188
1866
|
for (const dir of dirs) {
|
|
189
|
-
const subdirs =
|
|
1867
|
+
const subdirs = getAllSubdirectories2(dir).map((f) => path2.join(dir, f));
|
|
190
1868
|
extra.push(...subdirs);
|
|
191
1869
|
}
|
|
192
1870
|
}
|
|
193
1871
|
}
|
|
194
|
-
const pagesSubDirs =
|
|
195
|
-
const subdirectories = [...pagesSubDirs,
|
|
196
|
-
finishLog(
|
|
1872
|
+
const pagesSubDirs = getAllSubdirectories2(options2.pagesDirectory).map((f) => path2.join(options2.pagesDirectory, f));
|
|
1873
|
+
const subdirectories = [...pagesSubDirs, options2.pagesDirectory, ...extra];
|
|
1874
|
+
finishLog(yellow2("Hot-Reload Watching Subdirectories: "), ...subdirectories.join(", "));
|
|
197
1875
|
const watcherFn = async () => {
|
|
198
1876
|
if (isTimedOut) return;
|
|
199
1877
|
isTimedOut = true;
|
|
200
1878
|
process.stdout.write("\x1Bc");
|
|
201
1879
|
setTimeout(async () => {
|
|
202
|
-
|
|
1880
|
+
build2(DIST_DIR2);
|
|
203
1881
|
isTimedOut = false;
|
|
204
1882
|
}, 100);
|
|
205
1883
|
};
|
|
206
1884
|
for (const directory of subdirectories) {
|
|
207
|
-
const watcher =
|
|
1885
|
+
const watcher = fs3.watch(
|
|
208
1886
|
directory,
|
|
209
1887
|
{},
|
|
210
1888
|
watcherFn
|
|
@@ -212,16 +1890,16 @@ var compile = async (props) => {
|
|
|
212
1890
|
currentWatchers.push(watcher);
|
|
213
1891
|
}
|
|
214
1892
|
}
|
|
215
|
-
|
|
1893
|
+
build2(DIST_DIR2);
|
|
216
1894
|
};
|
|
217
1895
|
|
|
218
1896
|
// src/compile_docs.ts
|
|
219
1897
|
import { exec, execSync } from "child_process";
|
|
220
|
-
import
|
|
221
|
-
var
|
|
222
|
-
var PAGES_DIR =
|
|
223
|
-
var PUBLIC_DIR =
|
|
224
|
-
var OUTPUT_DIR =
|
|
1898
|
+
import path3 from "path";
|
|
1899
|
+
var __dirname3 = path3.dirname(fileURLToPath4(import.meta.url));
|
|
1900
|
+
var PAGES_DIR = path3.join(__dirname3, "../src/docs");
|
|
1901
|
+
var PUBLIC_DIR = path3.join(__dirname3, "../src/docs/public");
|
|
1902
|
+
var OUTPUT_DIR = path3.join(__dirname3, "../docs");
|
|
225
1903
|
var environmentArg = process.argv.find((arg) => arg.startsWith("--environment"));
|
|
226
1904
|
if (!environmentArg) environmentArg = "--environment='production'";
|
|
227
1905
|
var environment = environmentArg.split("=")[1];
|