elegance-js 2.0.19 → 2.1.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.
- package/dist/build.mjs +23 -974
- package/dist/client/client.mjs +20 -13
- package/dist/compile_docs.mjs +29 -980
- package/dist/global.d.ts +18 -5
- package/dist/index.mjs +9 -6
- package/dist/page_compiler.d.ts +5 -0
- package/dist/page_compiler.mjs +658 -109
- package/dist/server/generateHTMLTemplate.d.ts +1 -1
- package/dist/server/generateHTMLTemplate.mjs +5 -4
- package/dist/server/server.mjs +874 -317
- package/dist/server/state.d.ts +17 -0
- package/dist/server/state.mjs +9 -6
- package/package.json +2 -2
- package/dist/components/Breakpoint.d.ts +0 -3
- package/dist/components/Breakpoint.mjs +0 -20
- package/dist/dynamic_page.d.ts +0 -2
- package/dist/dynamic_page.mjs +0 -591
- package/dist/server/createReference.d.ts +0 -6
- package/dist/server/createReference.mjs +0 -18
- package/dist/server/createState.d.ts +0 -64
- package/dist/server/createState.mjs +0 -65
- package/dist/server/packModule.d.ts +0 -4
- package/dist/server/packModule.mjs +0 -30
package/dist/compile_docs.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// src/compile_docs.ts
|
|
2
|
-
import { fileURLToPath as
|
|
2
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
3
3
|
|
|
4
4
|
// src/build.ts
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import { fileURLToPath
|
|
5
|
+
import fs from "fs";
|
|
6
|
+
import path from "path";
|
|
7
|
+
import { fileURLToPath } from "url";
|
|
8
8
|
import child_process from "node:child_process";
|
|
9
9
|
import http from "http";
|
|
10
10
|
|
|
@@ -44,950 +44,11 @@ var log = {
|
|
|
44
44
|
error: logError
|
|
45
45
|
};
|
|
46
46
|
|
|
47
|
-
// src/dynamic_page.ts
|
|
48
|
-
import fs from "fs";
|
|
49
|
-
import path from "path";
|
|
50
|
-
import esbuild from "esbuild";
|
|
51
|
-
import { fileURLToPath } from "url";
|
|
52
|
-
|
|
53
|
-
// src/shared/serverElements.ts
|
|
54
|
-
var createBuildableElement = (tag) => {
|
|
55
|
-
return (options2, ...children) => ({
|
|
56
|
-
tag,
|
|
57
|
-
options: options2 || {},
|
|
58
|
-
children
|
|
59
|
-
});
|
|
60
|
-
};
|
|
61
|
-
var createChildrenlessBuildableElement = (tag) => {
|
|
62
|
-
return (options2) => ({
|
|
63
|
-
tag,
|
|
64
|
-
options: options2 || {},
|
|
65
|
-
children: null
|
|
66
|
-
});
|
|
67
|
-
};
|
|
68
|
-
var childrenlessElementTags = [
|
|
69
|
-
"area",
|
|
70
|
-
"base",
|
|
71
|
-
"br",
|
|
72
|
-
"col",
|
|
73
|
-
"embed",
|
|
74
|
-
"hr",
|
|
75
|
-
"img",
|
|
76
|
-
"input",
|
|
77
|
-
"link",
|
|
78
|
-
"meta",
|
|
79
|
-
"source",
|
|
80
|
-
"track",
|
|
81
|
-
"path",
|
|
82
|
-
"rect"
|
|
83
|
-
];
|
|
84
|
-
var elementTags = [
|
|
85
|
-
"a",
|
|
86
|
-
"address",
|
|
87
|
-
"article",
|
|
88
|
-
"aside",
|
|
89
|
-
"audio",
|
|
90
|
-
"blockquote",
|
|
91
|
-
"body",
|
|
92
|
-
"button",
|
|
93
|
-
"canvas",
|
|
94
|
-
"caption",
|
|
95
|
-
"colgroup",
|
|
96
|
-
"data",
|
|
97
|
-
"datalist",
|
|
98
|
-
"dd",
|
|
99
|
-
"del",
|
|
100
|
-
"details",
|
|
101
|
-
"dialog",
|
|
102
|
-
"div",
|
|
103
|
-
"dl",
|
|
104
|
-
"dt",
|
|
105
|
-
"fieldset",
|
|
106
|
-
"figcaption",
|
|
107
|
-
"figure",
|
|
108
|
-
"footer",
|
|
109
|
-
"form",
|
|
110
|
-
"h1",
|
|
111
|
-
"h2",
|
|
112
|
-
"h3",
|
|
113
|
-
"h4",
|
|
114
|
-
"h5",
|
|
115
|
-
"h6",
|
|
116
|
-
"head",
|
|
117
|
-
"header",
|
|
118
|
-
"hgroup",
|
|
119
|
-
"html",
|
|
120
|
-
"iframe",
|
|
121
|
-
"ins",
|
|
122
|
-
"label",
|
|
123
|
-
"legend",
|
|
124
|
-
"li",
|
|
125
|
-
"main",
|
|
126
|
-
"map",
|
|
127
|
-
"meter",
|
|
128
|
-
"nav",
|
|
129
|
-
"noscript",
|
|
130
|
-
"object",
|
|
131
|
-
"ol",
|
|
132
|
-
"optgroup",
|
|
133
|
-
"option",
|
|
134
|
-
"output",
|
|
135
|
-
"p",
|
|
136
|
-
"picture",
|
|
137
|
-
"pre",
|
|
138
|
-
"progress",
|
|
139
|
-
"q",
|
|
140
|
-
"section",
|
|
141
|
-
"select",
|
|
142
|
-
"summary",
|
|
143
|
-
"table",
|
|
144
|
-
"tbody",
|
|
145
|
-
"td",
|
|
146
|
-
"template",
|
|
147
|
-
"textarea",
|
|
148
|
-
"tfoot",
|
|
149
|
-
"th",
|
|
150
|
-
"thead",
|
|
151
|
-
"time",
|
|
152
|
-
"tr",
|
|
153
|
-
"ul",
|
|
154
|
-
"video",
|
|
155
|
-
"span",
|
|
156
|
-
"script",
|
|
157
|
-
"abbr",
|
|
158
|
-
"b",
|
|
159
|
-
"bdi",
|
|
160
|
-
"bdo",
|
|
161
|
-
"cite",
|
|
162
|
-
"code",
|
|
163
|
-
"dfn",
|
|
164
|
-
"em",
|
|
165
|
-
"i",
|
|
166
|
-
"kbd",
|
|
167
|
-
"mark",
|
|
168
|
-
"rp",
|
|
169
|
-
"rt",
|
|
170
|
-
"ruby",
|
|
171
|
-
"s",
|
|
172
|
-
"samp",
|
|
173
|
-
"small",
|
|
174
|
-
"strong",
|
|
175
|
-
"sub",
|
|
176
|
-
"sup",
|
|
177
|
-
"u",
|
|
178
|
-
"wbr",
|
|
179
|
-
"title",
|
|
180
|
-
"svg"
|
|
181
|
-
];
|
|
182
|
-
var elements = {};
|
|
183
|
-
var childrenlessElements = {};
|
|
184
|
-
for (const element of elementTags) {
|
|
185
|
-
elements[element] = createBuildableElement(element);
|
|
186
|
-
}
|
|
187
|
-
for (const element of childrenlessElementTags) {
|
|
188
|
-
childrenlessElements[element] = createChildrenlessBuildableElement(element);
|
|
189
|
-
}
|
|
190
|
-
var allElements = {
|
|
191
|
-
...elements,
|
|
192
|
-
...childrenlessElements
|
|
193
|
-
};
|
|
194
|
-
|
|
195
|
-
// src/shared/bindServerElements.ts
|
|
196
|
-
Object.assign(globalThis, elements);
|
|
197
|
-
Object.assign(globalThis, childrenlessElements);
|
|
198
|
-
|
|
199
|
-
// src/server/render.ts
|
|
200
|
-
var renderRecursively = (element) => {
|
|
201
|
-
let returnString = "";
|
|
202
|
-
if (typeof element === "boolean") return returnString;
|
|
203
|
-
else if (typeof element === "number" || typeof element === "string") {
|
|
204
|
-
return returnString + element;
|
|
205
|
-
} else if (Array.isArray(element)) {
|
|
206
|
-
return returnString + element.join(", ");
|
|
207
|
-
}
|
|
208
|
-
returnString += `<${element.tag}`;
|
|
209
|
-
if (typeof element.options === "object") {
|
|
210
|
-
const {
|
|
211
|
-
tag: elementTag,
|
|
212
|
-
options: elementOptions,
|
|
213
|
-
children: elementChildren
|
|
214
|
-
} = element.options;
|
|
215
|
-
if (elementTag !== void 0 && elementOptions !== void 0 && elementChildren !== void 0) {
|
|
216
|
-
const children = element.children;
|
|
217
|
-
element.children = [
|
|
218
|
-
element.options,
|
|
219
|
-
...children
|
|
220
|
-
];
|
|
221
|
-
element.options = {};
|
|
222
|
-
} else {
|
|
223
|
-
for (const [attrName, attrValue] of Object.entries(element.options)) {
|
|
224
|
-
if (typeof attrValue === "object") {
|
|
225
|
-
throw `Attr ${attrName}, for element ${element.tag} has obj type. Got: ${JSON.stringify(element, null, 2)}`;
|
|
226
|
-
}
|
|
227
|
-
returnString += ` ${attrName.toLowerCase()}="${attrValue}"`;
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
} else if (typeof element.options !== "object" && element.options !== void 0) {
|
|
231
|
-
element.children = [element.options, ...element.children || []];
|
|
232
|
-
}
|
|
233
|
-
if (element.children === null) {
|
|
234
|
-
returnString += "/>";
|
|
235
|
-
return returnString;
|
|
236
|
-
}
|
|
237
|
-
returnString += ">";
|
|
238
|
-
for (const child2 of element.children) {
|
|
239
|
-
returnString += renderRecursively(child2);
|
|
240
|
-
}
|
|
241
|
-
returnString += `</${element.tag}>`;
|
|
242
|
-
return returnString;
|
|
243
|
-
};
|
|
244
|
-
var serverSideRenderPage = async (page, pathname) => {
|
|
245
|
-
if (!page) {
|
|
246
|
-
throw `No Page Provided.`;
|
|
247
|
-
}
|
|
248
|
-
if (typeof page === "function") {
|
|
249
|
-
throw `Unbuilt page provided to ssr page.`;
|
|
250
|
-
}
|
|
251
|
-
const bodyHTML = renderRecursively(page);
|
|
252
|
-
return {
|
|
253
|
-
bodyHTML
|
|
254
|
-
};
|
|
255
|
-
};
|
|
256
|
-
|
|
257
|
-
// src/server/generateHTMLTemplate.ts
|
|
258
|
-
var generateHTMLTemplate = async ({
|
|
259
|
-
pageURL,
|
|
260
|
-
head: head2,
|
|
261
|
-
serverData = null,
|
|
262
|
-
addPageScriptTag = true,
|
|
263
|
-
name,
|
|
264
|
-
requiredClientModules = [],
|
|
265
|
-
environment: environment2
|
|
266
|
-
}) => {
|
|
267
|
-
let StartTemplate = `<meta name="viewport" content="width=device-width, initial-scale=1.0">`;
|
|
268
|
-
if (environment2 === "production") {
|
|
269
|
-
StartTemplate += `<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">`;
|
|
270
|
-
}
|
|
271
|
-
StartTemplate += '<meta charset="UTF-8">';
|
|
272
|
-
for (const module of requiredClientModules) {
|
|
273
|
-
StartTemplate += `<script data-module="true" src="/shipped/${module}.js" defer="true"></script>`;
|
|
274
|
-
}
|
|
275
|
-
if (addPageScriptTag === true) {
|
|
276
|
-
StartTemplate += `<script data-page="true" type="module" src="${pageURL === "" ? "" : "/"}${pageURL}/${name}_data.js" defer="true"></script>`;
|
|
277
|
-
}
|
|
278
|
-
StartTemplate += `<script type="module" src="/client.js" defer="true"></script>`;
|
|
279
|
-
let builtHead;
|
|
280
|
-
if (head2.constructor.name === "AsyncFunction") {
|
|
281
|
-
builtHead = await head2();
|
|
282
|
-
} else {
|
|
283
|
-
builtHead = head2();
|
|
284
|
-
}
|
|
285
|
-
let HTMLTemplate = renderRecursively(builtHead);
|
|
286
|
-
if (serverData) {
|
|
287
|
-
HTMLTemplate += serverData;
|
|
288
|
-
}
|
|
289
|
-
return {
|
|
290
|
-
internals: StartTemplate,
|
|
291
|
-
builtMetadata: HTMLTemplate
|
|
292
|
-
};
|
|
293
|
-
};
|
|
294
|
-
|
|
295
|
-
// src/server/createState.ts
|
|
296
|
-
if (!globalThis.__SERVER_CURRENT_STATE_ID__) {
|
|
297
|
-
globalThis.__SERVER_CURRENT_STATE_ID__ = 1;
|
|
298
|
-
}
|
|
299
|
-
var initializeState = () => {
|
|
300
|
-
globalThis.__SERVER_CURRENT_STATE__ = [];
|
|
301
|
-
};
|
|
302
|
-
var getState = () => {
|
|
303
|
-
return globalThis.__SERVER_CURRENT_STATE__;
|
|
304
|
-
};
|
|
305
|
-
var initializeObjectAttributes = () => globalThis.__SERVER_CURRENT_OBJECT_ATTRIBUTES__ = [];
|
|
306
|
-
var getObjectAttributes = () => {
|
|
307
|
-
return globalThis.__SERVER_CURRENT_OBJECT_ATTRIBUTES__;
|
|
308
|
-
};
|
|
309
|
-
|
|
310
|
-
// src/server/loadHook.ts
|
|
311
|
-
var resetLoadHooks = () => globalThis.__SERVER_CURRENT_LOADHOOKS__ = [];
|
|
312
|
-
var getLoadHooks = () => globalThis.__SERVER_CURRENT_LOADHOOKS__;
|
|
313
|
-
|
|
314
|
-
// src/dynamic_page.ts
|
|
315
|
-
var packageDir = process.env.PACKAGE_PATH;
|
|
316
|
-
if (packageDir === void 0) {
|
|
317
|
-
const __filename2 = fileURLToPath(import.meta.url);
|
|
318
|
-
const __dirname3 = path.dirname(__filename2);
|
|
319
|
-
packageDir = path.resolve(__dirname3, "..");
|
|
320
|
-
}
|
|
321
|
-
var elementKey = 0;
|
|
322
|
-
var processOptionAsObjectAttribute = (element, optionName, optionValue, objectAttributes) => {
|
|
323
|
-
const lcOptionName = optionName.toLowerCase();
|
|
324
|
-
const options2 = element.options;
|
|
325
|
-
let key = options2.key;
|
|
326
|
-
if (key == void 0) {
|
|
327
|
-
key = elementKey += 1;
|
|
328
|
-
options2.key = key;
|
|
329
|
-
}
|
|
330
|
-
if (!optionValue.type) {
|
|
331
|
-
throw `ObjectAttributeType is missing from object attribute. ${element.tag}: ${optionName}/${optionValue}`;
|
|
332
|
-
}
|
|
333
|
-
let optionFinal = lcOptionName;
|
|
334
|
-
switch (optionValue.type) {
|
|
335
|
-
case 1 /* STATE */:
|
|
336
|
-
const SOA = optionValue;
|
|
337
|
-
if (typeof SOA.value === "function") {
|
|
338
|
-
delete options2[optionName];
|
|
339
|
-
break;
|
|
340
|
-
}
|
|
341
|
-
if (lcOptionName === "innertext" || lcOptionName === "innerhtml") {
|
|
342
|
-
element.children = [SOA.value];
|
|
343
|
-
delete options2[optionName];
|
|
344
|
-
} else {
|
|
345
|
-
delete options2[optionName];
|
|
346
|
-
options2[lcOptionName] = SOA.value;
|
|
347
|
-
}
|
|
348
|
-
break;
|
|
349
|
-
case 2 /* OBSERVER */:
|
|
350
|
-
const OOA = optionValue;
|
|
351
|
-
const firstValue = OOA.update(...OOA.initialValues);
|
|
352
|
-
if (lcOptionName === "innertext" || lcOptionName === "innerhtml") {
|
|
353
|
-
element.children = [firstValue];
|
|
354
|
-
delete options2[optionName];
|
|
355
|
-
} else {
|
|
356
|
-
delete options2[optionName];
|
|
357
|
-
options2[lcOptionName] = firstValue;
|
|
358
|
-
}
|
|
359
|
-
optionFinal = optionName;
|
|
360
|
-
break;
|
|
361
|
-
case 4 /* REFERENCE */:
|
|
362
|
-
options2["ref"] = optionValue.value;
|
|
363
|
-
break;
|
|
364
|
-
}
|
|
365
|
-
objectAttributes.push({ ...optionValue, key, attribute: optionFinal });
|
|
366
|
-
};
|
|
367
|
-
var processPageElements = async (element, objectAttributes, parent) => {
|
|
368
|
-
if (typeof element === "boolean" || typeof element === "number" || Array.isArray(element)) return element;
|
|
369
|
-
if (typeof element === "string") {
|
|
370
|
-
return element;
|
|
371
|
-
}
|
|
372
|
-
const processElementOptionsAsChildAndReturn = async () => {
|
|
373
|
-
const children = element.children;
|
|
374
|
-
element.children = [
|
|
375
|
-
element.options,
|
|
376
|
-
...children
|
|
377
|
-
];
|
|
378
|
-
element.options = {};
|
|
379
|
-
for (let i = 0; i < children.length + 1; i++) {
|
|
380
|
-
const child2 = element.children[i];
|
|
381
|
-
const processedChild = await processPageElements(child2, objectAttributes, element);
|
|
382
|
-
element.children[i] = processedChild;
|
|
383
|
-
}
|
|
384
|
-
return {
|
|
385
|
-
...element,
|
|
386
|
-
options: {}
|
|
387
|
-
};
|
|
388
|
-
};
|
|
389
|
-
if (typeof element.options !== "object") {
|
|
390
|
-
return await processElementOptionsAsChildAndReturn();
|
|
391
|
-
}
|
|
392
|
-
const {
|
|
393
|
-
tag: elementTag,
|
|
394
|
-
options: elementOptions,
|
|
395
|
-
children: elementChildren
|
|
396
|
-
} = element.options;
|
|
397
|
-
if (elementTag && elementOptions && elementChildren) {
|
|
398
|
-
return await processElementOptionsAsChildAndReturn();
|
|
399
|
-
}
|
|
400
|
-
const options2 = element.options;
|
|
401
|
-
for (const [optionName, optionValue] of Object.entries(options2)) {
|
|
402
|
-
const lcOptionName = optionName.toLowerCase();
|
|
403
|
-
if (typeof optionValue !== "object") {
|
|
404
|
-
if (lcOptionName === "innertext") {
|
|
405
|
-
delete options2[optionName];
|
|
406
|
-
if (element.children === null) {
|
|
407
|
-
throw `Cannot use innerText or innerHTML on childrenless elements.`;
|
|
408
|
-
}
|
|
409
|
-
element.children = [optionValue, ...element.children];
|
|
410
|
-
continue;
|
|
411
|
-
} else if (lcOptionName === "innerhtml") {
|
|
412
|
-
if (element.children === null) {
|
|
413
|
-
throw `Cannot use innerText or innerHTML on childrenless elements.`;
|
|
414
|
-
}
|
|
415
|
-
delete options2[optionName];
|
|
416
|
-
element.children = [optionValue];
|
|
417
|
-
continue;
|
|
418
|
-
}
|
|
419
|
-
continue;
|
|
420
|
-
}
|
|
421
|
-
;
|
|
422
|
-
processOptionAsObjectAttribute(element, optionName, optionValue, objectAttributes);
|
|
423
|
-
}
|
|
424
|
-
if (element.children) {
|
|
425
|
-
for (let i = 0; i < element.children.length; i++) {
|
|
426
|
-
const child2 = element.children[i];
|
|
427
|
-
const processedChild = await processPageElements(child2, objectAttributes, element);
|
|
428
|
-
element.children[i] = processedChild;
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
return element;
|
|
432
|
-
};
|
|
433
|
-
var generateSuitablePageElements = async (pageLocation, pageElements, metadata, DIST_DIR, pageName, requiredClientModules) => {
|
|
434
|
-
if (typeof pageElements === "string" || typeof pageElements === "boolean" || typeof pageElements === "number" || Array.isArray(pageElements)) {
|
|
435
|
-
return [];
|
|
436
|
-
}
|
|
437
|
-
const objectAttributes = [];
|
|
438
|
-
const processedPageElements = await processPageElements(pageElements, objectAttributes, []);
|
|
439
|
-
elementKey = 0;
|
|
440
|
-
const renderedPage = await serverSideRenderPage(
|
|
441
|
-
processedPageElements,
|
|
442
|
-
pageLocation
|
|
443
|
-
);
|
|
444
|
-
const template = await generateHTMLTemplate({
|
|
445
|
-
pageURL: path.relative(DIST_DIR, pageLocation),
|
|
446
|
-
head: metadata,
|
|
447
|
-
addPageScriptTag: true,
|
|
448
|
-
name: pageName,
|
|
449
|
-
requiredClientModules,
|
|
450
|
-
environment: "production"
|
|
451
|
-
});
|
|
452
|
-
const resultHTML = `<!DOCTYPE html>${template}${renderedPage.bodyHTML}`;
|
|
453
|
-
return {
|
|
454
|
-
objectAttributes,
|
|
455
|
-
resultHTML
|
|
456
|
-
};
|
|
457
|
-
};
|
|
458
|
-
var generateClientPageData = async (pageLocation, state, objectAttributes, pageLoadHooks, DIST_DIR, pageName) => {
|
|
459
|
-
const pageDiff = path.relative(DIST_DIR, pageLocation);
|
|
460
|
-
let clientPageJSText = `${globalThis.__SERVER_PAGE_DATA_BANNER__}
|
|
461
|
-
/*ELEGANCE_JS*/
|
|
462
|
-
let url="${pageDiff === "" ? "/" : `/${pageDiff}`}";`;
|
|
463
|
-
{
|
|
464
|
-
clientPageJSText += `export const data = {`;
|
|
465
|
-
if (state) {
|
|
466
|
-
const nonBoundState = state.filter((subj) => subj.bind === void 0);
|
|
467
|
-
clientPageJSText += `state:[`;
|
|
468
|
-
for (const subject of nonBoundState) {
|
|
469
|
-
if (typeof subject.value === "string") {
|
|
470
|
-
const stringified = JSON.stringify(subject.value);
|
|
471
|
-
clientPageJSText += `{id:${subject.id},value:${stringified}},`;
|
|
472
|
-
} else if (typeof subject.value === "function") {
|
|
473
|
-
clientPageJSText += `{id:${subject.id},value:${subject.value.toString()}},`;
|
|
474
|
-
} else {
|
|
475
|
-
clientPageJSText += `{id:${subject.id},value:${JSON.stringify(subject.value)}},`;
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
clientPageJSText += `],`;
|
|
479
|
-
const formattedBoundState = {};
|
|
480
|
-
const stateBinds = state.map((subj) => subj.bind).filter((bind) => bind !== void 0);
|
|
481
|
-
for (const bind of stateBinds) {
|
|
482
|
-
formattedBoundState[bind] = [];
|
|
483
|
-
}
|
|
484
|
-
;
|
|
485
|
-
const boundState = state.filter((subj) => subj.bind !== void 0);
|
|
486
|
-
for (const subject of boundState) {
|
|
487
|
-
const bindingState = formattedBoundState[subject.bind];
|
|
488
|
-
delete subject.bind;
|
|
489
|
-
bindingState.push(subject);
|
|
490
|
-
}
|
|
491
|
-
const bindSubjectPairing = Object.entries(formattedBoundState);
|
|
492
|
-
if (bindSubjectPairing.length > 0) {
|
|
493
|
-
clientPageJSText += "binds:{";
|
|
494
|
-
for (const [bind, subjects] of bindSubjectPairing) {
|
|
495
|
-
clientPageJSText += `${bind}:[`;
|
|
496
|
-
for (const subject of subjects) {
|
|
497
|
-
if (typeof subject.value === "string") {
|
|
498
|
-
clientPageJSText += `{id:${subject.id},value:${JSON.stringify(subject.value)}},`;
|
|
499
|
-
} else {
|
|
500
|
-
clientPageJSText += `{id:${subject.id},value:${JSON.stringify(subject.value)}},`;
|
|
501
|
-
}
|
|
502
|
-
}
|
|
503
|
-
clientPageJSText += "]";
|
|
504
|
-
}
|
|
505
|
-
clientPageJSText += "},";
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
const stateObjectAttributes = objectAttributes.filter((oa) => oa.type === 1 /* STATE */);
|
|
509
|
-
if (stateObjectAttributes.length > 0) {
|
|
510
|
-
const processed = [...stateObjectAttributes].map((soa) => {
|
|
511
|
-
delete soa.type;
|
|
512
|
-
return soa;
|
|
513
|
-
});
|
|
514
|
-
clientPageJSText += `soa:${JSON.stringify(processed)},`;
|
|
515
|
-
}
|
|
516
|
-
const observerObjectAttributes = objectAttributes.filter((oa) => oa.type === 2 /* OBSERVER */);
|
|
517
|
-
if (observerObjectAttributes.length > 0) {
|
|
518
|
-
let observerObjectAttributeString = "ooa:[";
|
|
519
|
-
for (const observerObjectAttribute of observerObjectAttributes) {
|
|
520
|
-
const ooa = observerObjectAttribute;
|
|
521
|
-
observerObjectAttributeString += `{key:${ooa.key},attribute:"${ooa.attribute}",update:${ooa.update.toString()},`;
|
|
522
|
-
observerObjectAttributeString += `refs:[`;
|
|
523
|
-
for (const ref of ooa.refs) {
|
|
524
|
-
observerObjectAttributeString += `{id:${ref.id}`;
|
|
525
|
-
if (ref.bind !== void 0) observerObjectAttributeString += `,bind:${ref.bind}`;
|
|
526
|
-
observerObjectAttributeString += "},";
|
|
527
|
-
}
|
|
528
|
-
observerObjectAttributeString += "]},";
|
|
529
|
-
}
|
|
530
|
-
observerObjectAttributeString += "],";
|
|
531
|
-
clientPageJSText += observerObjectAttributeString;
|
|
532
|
-
}
|
|
533
|
-
if (pageLoadHooks.length > 0) {
|
|
534
|
-
clientPageJSText += "lh:[";
|
|
535
|
-
for (const loadHook of pageLoadHooks) {
|
|
536
|
-
const key = loadHook.bind;
|
|
537
|
-
clientPageJSText += `{fn:${loadHook.fn},bind:"${key || ""}"},`;
|
|
538
|
-
}
|
|
539
|
-
clientPageJSText += "],";
|
|
540
|
-
}
|
|
541
|
-
clientPageJSText += `};`;
|
|
542
|
-
}
|
|
543
|
-
clientPageJSText += "if(!globalThis.pd) { globalThis.pd = {}; globalThis.pd[url] = data}";
|
|
544
|
-
const pageDataPath = path.join(pageLocation, `${pageName}_data.js`);
|
|
545
|
-
let sendHardReloadInstruction = false;
|
|
546
|
-
const transformedResult = await esbuild.transform(clientPageJSText, { minify: true }).catch((error) => {
|
|
547
|
-
console.error("Failed to transform client page js!", error);
|
|
548
|
-
});
|
|
549
|
-
if (!transformedResult) return { sendHardReloadInstruction };
|
|
550
|
-
fs.writeFileSync(pageDataPath, transformedResult.code, "utf-8");
|
|
551
|
-
return { sendHardReloadInstruction };
|
|
552
|
-
};
|
|
553
|
-
var buildDynamicPage = async (filePath, DIST_DIR, req, res) => {
|
|
554
|
-
let pageElements;
|
|
555
|
-
let metadata;
|
|
556
|
-
initializeState();
|
|
557
|
-
initializeObjectAttributes();
|
|
558
|
-
resetLoadHooks();
|
|
559
|
-
globalThis.__SERVER_PAGE_DATA_BANNER__ = "";
|
|
560
|
-
globalThis.__SERVER_CURRENT_STATE_ID__ = 1;
|
|
561
|
-
let modules = [];
|
|
562
|
-
try {
|
|
563
|
-
const {
|
|
564
|
-
construct
|
|
565
|
-
} = await import("file://" + filePath);
|
|
566
|
-
const {
|
|
567
|
-
page,
|
|
568
|
-
metadata: pageMetadata,
|
|
569
|
-
isDynamicPage,
|
|
570
|
-
requestHook,
|
|
571
|
-
requiredClientModules
|
|
572
|
-
} = construct();
|
|
573
|
-
if (requiredClientModules !== void 0) {
|
|
574
|
-
modules = requiredClientModules;
|
|
575
|
-
}
|
|
576
|
-
if (typeof requestHook === "function") {
|
|
577
|
-
if (requestHook.constructor.name === "AsyncFunction") {
|
|
578
|
-
const doProcessRequest = await requestHook(req, res);
|
|
579
|
-
if (doProcessRequest !== void 0 == doProcessRequest === false) {
|
|
580
|
-
return false;
|
|
581
|
-
}
|
|
582
|
-
} else {
|
|
583
|
-
const doProcessRequest = requestHook(req, res);
|
|
584
|
-
if (doProcessRequest !== void 0 == doProcessRequest === false) {
|
|
585
|
-
return false;
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
}
|
|
589
|
-
pageElements = page;
|
|
590
|
-
metadata = pageMetadata;
|
|
591
|
-
if (isDynamicPage === false) {
|
|
592
|
-
throw new Error("Cannot dynamically render a non-dynamic page.");
|
|
593
|
-
}
|
|
594
|
-
} catch (e) {
|
|
595
|
-
throw `${filePath} - ${e}
|
|
596
|
-
${e?.stack ?? "No stack."}
|
|
597
|
-
|
|
598
|
-
`;
|
|
599
|
-
}
|
|
600
|
-
if (!metadata || metadata && typeof metadata !== "function") {
|
|
601
|
-
console.warn(`WARNING: Dynamic ${filePath} does not export a metadata function. This is *highly* recommended.`);
|
|
602
|
-
}
|
|
603
|
-
if (!pageElements) {
|
|
604
|
-
console.warn(`WARNING: Dynamic ${filePath} should export a const page, which is of type BuiltElement<"body">.`);
|
|
605
|
-
}
|
|
606
|
-
if (typeof pageElements === "function") {
|
|
607
|
-
if (pageElements.constructor.name === "AsyncFunction") {
|
|
608
|
-
pageElements = await pageElements();
|
|
609
|
-
} else {
|
|
610
|
-
pageElements = pageElements();
|
|
611
|
-
}
|
|
612
|
-
}
|
|
613
|
-
const state = getState();
|
|
614
|
-
const pageLoadHooks = getLoadHooks();
|
|
615
|
-
const objectAttributes = getObjectAttributes();
|
|
616
|
-
const foundObjectAttributes = await generateSuitablePageElements(
|
|
617
|
-
path.dirname(filePath),
|
|
618
|
-
pageElements || body(),
|
|
619
|
-
metadata ?? (() => head()),
|
|
620
|
-
DIST_DIR,
|
|
621
|
-
"page",
|
|
622
|
-
modules
|
|
623
|
-
);
|
|
624
|
-
await generateClientPageData(
|
|
625
|
-
path.dirname(filePath),
|
|
626
|
-
state || {},
|
|
627
|
-
[...objectAttributes, ...foundObjectAttributes.objectAttributes],
|
|
628
|
-
pageLoadHooks || [],
|
|
629
|
-
DIST_DIR,
|
|
630
|
-
"page"
|
|
631
|
-
);
|
|
632
|
-
return foundObjectAttributes.resultHTML;
|
|
633
|
-
};
|
|
634
|
-
|
|
635
|
-
// src/server/server.ts
|
|
636
|
-
import { createServer as createHttpServer } from "http";
|
|
637
|
-
import { promises as fs2 } from "fs";
|
|
638
|
-
import { join, normalize, extname, dirname, resolve } from "path";
|
|
639
|
-
import { pathToFileURL } from "url";
|
|
640
|
-
import { gzip, deflate } from "zlib";
|
|
641
|
-
import { promisify } from "util";
|
|
642
|
-
var gzipAsync = promisify(gzip);
|
|
643
|
-
var deflateAsync = promisify(deflate);
|
|
644
|
-
var MIME_TYPES = {
|
|
645
|
-
".html": "text/html; charset=utf-8",
|
|
646
|
-
".css": "text/css; charset=utf-8",
|
|
647
|
-
".js": "application/javascript; charset=utf-8",
|
|
648
|
-
".json": "application/json; charset=utf-8",
|
|
649
|
-
".png": "image/png",
|
|
650
|
-
".jpg": "image/jpeg",
|
|
651
|
-
".jpeg": "image/jpeg",
|
|
652
|
-
".gif": "image/gif",
|
|
653
|
-
".svg": "image/svg+xml",
|
|
654
|
-
".ico": "image/x-icon",
|
|
655
|
-
".txt": "text/plain; charset=utf-8"
|
|
656
|
-
};
|
|
657
|
-
function startServer({
|
|
658
|
-
root,
|
|
659
|
-
port = 3e3,
|
|
660
|
-
host = "localhost",
|
|
661
|
-
environment: environment2 = "production",
|
|
662
|
-
DIST_DIR
|
|
663
|
-
}) {
|
|
664
|
-
if (!root) throw new Error("Root directory must be specified.");
|
|
665
|
-
root = normalize(root).replace(/[\\/]+$/, "");
|
|
666
|
-
const requestHandler = async (req, res) => {
|
|
667
|
-
try {
|
|
668
|
-
if (!req.url) {
|
|
669
|
-
await sendResponse(req, res, 400, { "Content-Type": "text/plain; charset=utf-8" }, "Bad Request");
|
|
670
|
-
return;
|
|
671
|
-
}
|
|
672
|
-
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
673
|
-
res.setHeader("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS");
|
|
674
|
-
res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
|
|
675
|
-
if (req.method === "OPTIONS") {
|
|
676
|
-
res.writeHead(204);
|
|
677
|
-
res.end();
|
|
678
|
-
if (environment2 === "development") {
|
|
679
|
-
log.info(req.method, "::", req.url, "-", res.statusCode);
|
|
680
|
-
}
|
|
681
|
-
return;
|
|
682
|
-
}
|
|
683
|
-
const url = new URL(req.url, `http://${req.headers.host}`);
|
|
684
|
-
if (url.pathname.startsWith("/api/")) {
|
|
685
|
-
await handleApiRequest(root, url.pathname, req, res);
|
|
686
|
-
} else {
|
|
687
|
-
await handleStaticRequest(root, url.pathname, req, res, DIST_DIR);
|
|
688
|
-
}
|
|
689
|
-
if (environment2 === "development") {
|
|
690
|
-
log.info(req.method, "::", req.url, "-", res.statusCode);
|
|
691
|
-
}
|
|
692
|
-
} catch (err) {
|
|
693
|
-
log.error(err);
|
|
694
|
-
await sendResponse(req, res, 500, { "Content-Type": "text/plain; charset=utf-8" }, "Internal Server Error");
|
|
695
|
-
}
|
|
696
|
-
};
|
|
697
|
-
function attemptListen(p) {
|
|
698
|
-
const server = createHttpServer(requestHandler);
|
|
699
|
-
server.on("error", (err) => {
|
|
700
|
-
if (err.code === "EADDRINUSE") {
|
|
701
|
-
attemptListen(p + 1);
|
|
702
|
-
} else {
|
|
703
|
-
console.error(err);
|
|
704
|
-
}
|
|
705
|
-
});
|
|
706
|
-
server.listen(p, host, () => {
|
|
707
|
-
log.info(`Server running at http://${host}:${p}/`);
|
|
708
|
-
});
|
|
709
|
-
return server;
|
|
710
|
-
}
|
|
711
|
-
return attemptListen(port);
|
|
712
|
-
}
|
|
713
|
-
async function handleStaticRequest(root, pathname, req, res, DIST_DIR) {
|
|
714
|
-
const originalPathname = pathname;
|
|
715
|
-
let filePath = normalize(join(root, decodeURIComponent(pathname))).replace(/[\\/]+$/, "");
|
|
716
|
-
if (!filePath.startsWith(root)) {
|
|
717
|
-
await sendResponse(req, res, 403, { "Content-Type": "text/plain; charset=utf-8" }, "Forbidden");
|
|
718
|
-
return;
|
|
719
|
-
}
|
|
720
|
-
let stats;
|
|
721
|
-
try {
|
|
722
|
-
stats = await fs2.stat(filePath);
|
|
723
|
-
} catch {
|
|
724
|
-
}
|
|
725
|
-
let pageDir;
|
|
726
|
-
if (stats) {
|
|
727
|
-
if (stats.isDirectory()) {
|
|
728
|
-
pageDir = filePath;
|
|
729
|
-
} else {
|
|
730
|
-
pageDir = dirname(filePath);
|
|
731
|
-
}
|
|
732
|
-
} else {
|
|
733
|
-
if (originalPathname.endsWith("/")) {
|
|
734
|
-
pageDir = filePath;
|
|
735
|
-
} else {
|
|
736
|
-
pageDir = dirname(filePath);
|
|
737
|
-
}
|
|
738
|
-
}
|
|
739
|
-
const relDir = pageDir.slice(root.length).replace(/^[\/\\]+/, "");
|
|
740
|
-
const parts = relDir.split(/[\\/]/).filter(Boolean);
|
|
741
|
-
const middlewareDirs = [];
|
|
742
|
-
let current = root;
|
|
743
|
-
middlewareDirs.push(current);
|
|
744
|
-
for (const part of parts) {
|
|
745
|
-
current = join(current, part);
|
|
746
|
-
middlewareDirs.push(current);
|
|
747
|
-
}
|
|
748
|
-
const middlewares = [];
|
|
749
|
-
for (const dir of middlewareDirs) {
|
|
750
|
-
const mwPath = join(dir, "middleware.mjs");
|
|
751
|
-
let mwModule;
|
|
752
|
-
try {
|
|
753
|
-
await fs2.access(mwPath);
|
|
754
|
-
const url = pathToFileURL(mwPath).href;
|
|
755
|
-
mwModule = await import(url);
|
|
756
|
-
} catch {
|
|
757
|
-
continue;
|
|
758
|
-
}
|
|
759
|
-
const mwKeys = Object.keys(mwModule).sort();
|
|
760
|
-
for (const key of mwKeys) {
|
|
761
|
-
const f = mwModule[key];
|
|
762
|
-
if (typeof f === "function" && !middlewares.some((existing) => existing === f)) {
|
|
763
|
-
middlewares.push(f);
|
|
764
|
-
}
|
|
765
|
-
}
|
|
766
|
-
}
|
|
767
|
-
let isDynamic = false;
|
|
768
|
-
let handlerPath = filePath;
|
|
769
|
-
if (stats && stats.isDirectory()) {
|
|
770
|
-
const pageMjsPath = join(filePath, "page.mjs");
|
|
771
|
-
try {
|
|
772
|
-
await fs2.access(pageMjsPath);
|
|
773
|
-
handlerPath = pageMjsPath;
|
|
774
|
-
isDynamic = true;
|
|
775
|
-
} catch {
|
|
776
|
-
handlerPath = join(filePath, "index.html");
|
|
777
|
-
isDynamic = false;
|
|
778
|
-
}
|
|
779
|
-
} else {
|
|
780
|
-
handlerPath = filePath;
|
|
781
|
-
isDynamic = false;
|
|
782
|
-
}
|
|
783
|
-
let hasHandler = false;
|
|
784
|
-
try {
|
|
785
|
-
await fs2.access(handlerPath);
|
|
786
|
-
hasHandler = true;
|
|
787
|
-
} catch {
|
|
788
|
-
}
|
|
789
|
-
const finalHandler = async (req2, res2) => {
|
|
790
|
-
if (!hasHandler) {
|
|
791
|
-
await respondWithErrorPage(root, pathname, 404, req2, res2);
|
|
792
|
-
return;
|
|
793
|
-
}
|
|
794
|
-
if (isDynamic) {
|
|
795
|
-
try {
|
|
796
|
-
const resultHTML = await buildDynamicPage(resolve(handlerPath), DIST_DIR, req2, res2);
|
|
797
|
-
if (resultHTML === false) {
|
|
798
|
-
return;
|
|
799
|
-
}
|
|
800
|
-
await sendResponse(req2, res2, 200, { "Content-Type": MIME_TYPES[".html"] }, resultHTML);
|
|
801
|
-
} catch (err) {
|
|
802
|
-
log.error("Error building dynamic page -", err);
|
|
803
|
-
}
|
|
804
|
-
} else {
|
|
805
|
-
const ext = extname(handlerPath).toLowerCase();
|
|
806
|
-
const contentType = MIME_TYPES[ext] || "application/octet-stream";
|
|
807
|
-
const data = await fs2.readFile(handlerPath);
|
|
808
|
-
await sendResponse(req2, res2, 200, { "Content-Type": contentType }, data);
|
|
809
|
-
}
|
|
810
|
-
};
|
|
811
|
-
const composed = composeMiddlewares(middlewares, finalHandler, { isApi: false, root, pathname });
|
|
812
|
-
await composed(req, res);
|
|
813
|
-
}
|
|
814
|
-
async function handleApiRequest(root, pathname, req, res) {
|
|
815
|
-
const apiSubPath = pathname.slice("/api/".length);
|
|
816
|
-
const parts = apiSubPath.split("/").filter(Boolean);
|
|
817
|
-
const routeDir = join(root, pathname);
|
|
818
|
-
const routePath = join(routeDir, "route.mjs");
|
|
819
|
-
let hasRoute = false;
|
|
820
|
-
try {
|
|
821
|
-
await fs2.access(routePath);
|
|
822
|
-
hasRoute = true;
|
|
823
|
-
} catch {
|
|
824
|
-
}
|
|
825
|
-
let fn = null;
|
|
826
|
-
let module = null;
|
|
827
|
-
if (hasRoute) {
|
|
828
|
-
try {
|
|
829
|
-
const moduleUrl = pathToFileURL(routePath).href;
|
|
830
|
-
module = await import(moduleUrl);
|
|
831
|
-
fn = module[req.method];
|
|
832
|
-
} catch (err) {
|
|
833
|
-
console.error(err);
|
|
834
|
-
return respondWithJsonError(req, res, 500, "Internal Server Error");
|
|
835
|
-
}
|
|
836
|
-
}
|
|
837
|
-
const middlewareDirs = [];
|
|
838
|
-
let current = join(root, "api");
|
|
839
|
-
middlewareDirs.push(current);
|
|
840
|
-
for (const part of parts) {
|
|
841
|
-
current = join(current, part);
|
|
842
|
-
middlewareDirs.push(current);
|
|
843
|
-
}
|
|
844
|
-
const middlewares = [];
|
|
845
|
-
for (const dir of middlewareDirs) {
|
|
846
|
-
const mwPath = join(dir, "middleware.mjs");
|
|
847
|
-
let mwModule;
|
|
848
|
-
try {
|
|
849
|
-
await fs2.access(mwPath);
|
|
850
|
-
const url = pathToFileURL(mwPath).href;
|
|
851
|
-
mwModule = await import(url);
|
|
852
|
-
} catch {
|
|
853
|
-
continue;
|
|
854
|
-
}
|
|
855
|
-
const mwKeys = Object.keys(mwModule).sort();
|
|
856
|
-
for (const key of mwKeys) {
|
|
857
|
-
const f = mwModule[key];
|
|
858
|
-
if (typeof f === "function" && !middlewares.some((existing) => existing === f)) {
|
|
859
|
-
middlewares.push(f);
|
|
860
|
-
}
|
|
861
|
-
}
|
|
862
|
-
}
|
|
863
|
-
const finalHandler = async (req2, res2) => {
|
|
864
|
-
if (!hasRoute) {
|
|
865
|
-
return respondWithJsonError(req2, res2, 404, "Not Found");
|
|
866
|
-
}
|
|
867
|
-
if (typeof fn !== "function") {
|
|
868
|
-
return respondWithJsonError(req2, res2, 405, "Method Not Allowed");
|
|
869
|
-
}
|
|
870
|
-
await fn(req2, res2);
|
|
871
|
-
};
|
|
872
|
-
const composed = composeMiddlewares(middlewares, finalHandler, { isApi: true });
|
|
873
|
-
await composed(req, res);
|
|
874
|
-
}
|
|
875
|
-
function composeMiddlewares(mws, final, options2) {
|
|
876
|
-
return async function(req, res) {
|
|
877
|
-
let index = 0;
|
|
878
|
-
async function dispatch(err) {
|
|
879
|
-
if (err) {
|
|
880
|
-
if (options2.isApi) {
|
|
881
|
-
return respondWithJsonError(req, res, 500, err.message || "Internal Server Error");
|
|
882
|
-
} else {
|
|
883
|
-
return await respondWithErrorPage(options2.root, options2.pathname, 500, req, res);
|
|
884
|
-
}
|
|
885
|
-
}
|
|
886
|
-
if (index >= mws.length) {
|
|
887
|
-
return await final(req, res);
|
|
888
|
-
}
|
|
889
|
-
const thisMw = mws[index++];
|
|
890
|
-
const next = (e) => dispatch(e);
|
|
891
|
-
const onceNext = (nextFn) => {
|
|
892
|
-
let called = false;
|
|
893
|
-
return async (e) => {
|
|
894
|
-
if (called) {
|
|
895
|
-
log.warn("next() was called in a middleware more than once.");
|
|
896
|
-
return;
|
|
897
|
-
}
|
|
898
|
-
called = true;
|
|
899
|
-
await nextFn(e);
|
|
900
|
-
};
|
|
901
|
-
};
|
|
902
|
-
try {
|
|
903
|
-
await thisMw(req, res, onceNext(next));
|
|
904
|
-
} catch (error) {
|
|
905
|
-
await dispatch(error);
|
|
906
|
-
}
|
|
907
|
-
}
|
|
908
|
-
await dispatch();
|
|
909
|
-
};
|
|
910
|
-
}
|
|
911
|
-
async function respondWithJsonError(req, res, code, message) {
|
|
912
|
-
const body2 = JSON.stringify({ error: message });
|
|
913
|
-
await sendResponse(req, res, code, { "Content-Type": "application/json; charset=utf-8" }, body2);
|
|
914
|
-
}
|
|
915
|
-
async function respondWithErrorPage(root, pathname, code, req, res) {
|
|
916
|
-
let currentPath = normalize(join(root, decodeURIComponent(pathname)));
|
|
917
|
-
let tried = /* @__PURE__ */ new Set();
|
|
918
|
-
let errorFilePath = null;
|
|
919
|
-
while (currentPath.startsWith(root)) {
|
|
920
|
-
const candidate = join(currentPath, `${code}.html`);
|
|
921
|
-
if (!tried.has(candidate)) {
|
|
922
|
-
try {
|
|
923
|
-
await fs2.access(candidate);
|
|
924
|
-
errorFilePath = candidate;
|
|
925
|
-
break;
|
|
926
|
-
} catch {
|
|
927
|
-
}
|
|
928
|
-
tried.add(candidate);
|
|
929
|
-
}
|
|
930
|
-
const parent = dirname(currentPath);
|
|
931
|
-
if (parent === currentPath) break;
|
|
932
|
-
currentPath = parent;
|
|
933
|
-
}
|
|
934
|
-
if (!errorFilePath) {
|
|
935
|
-
const fallback = join(root, `${code}.html`);
|
|
936
|
-
try {
|
|
937
|
-
await fs2.access(fallback);
|
|
938
|
-
errorFilePath = fallback;
|
|
939
|
-
} catch {
|
|
940
|
-
}
|
|
941
|
-
}
|
|
942
|
-
if (errorFilePath) {
|
|
943
|
-
try {
|
|
944
|
-
const html = await fs2.readFile(errorFilePath, "utf8");
|
|
945
|
-
await sendResponse(req, res, code, { "Content-Type": "text/html; charset=utf-8" }, html);
|
|
946
|
-
return;
|
|
947
|
-
} catch {
|
|
948
|
-
}
|
|
949
|
-
}
|
|
950
|
-
await sendResponse(req, res, code, { "Content-Type": "text/plain; charset=utf-8" }, `${code} Error`);
|
|
951
|
-
}
|
|
952
|
-
function isCompressible(contentType) {
|
|
953
|
-
if (!contentType) return false;
|
|
954
|
-
return /text\/|javascript|json|xml|svg/.test(contentType);
|
|
955
|
-
}
|
|
956
|
-
async function sendResponse(req, res, status, headers, body2) {
|
|
957
|
-
if (typeof body2 === "string") {
|
|
958
|
-
body2 = Buffer.from(body2);
|
|
959
|
-
}
|
|
960
|
-
const accept = req.headers["accept-encoding"] || "";
|
|
961
|
-
let encoding = null;
|
|
962
|
-
if (accept.match(/\bgzip\b/)) {
|
|
963
|
-
encoding = "gzip";
|
|
964
|
-
} else if (accept.match(/\bdeflate\b/)) {
|
|
965
|
-
encoding = "deflate";
|
|
966
|
-
}
|
|
967
|
-
if (!encoding || !isCompressible(headers["Content-Type"] || "")) {
|
|
968
|
-
res.writeHead(status, headers);
|
|
969
|
-
res.end(body2);
|
|
970
|
-
return;
|
|
971
|
-
}
|
|
972
|
-
const compressor = encoding === "gzip" ? gzipAsync : deflateAsync;
|
|
973
|
-
try {
|
|
974
|
-
const compressed = await compressor(body2);
|
|
975
|
-
headers["Content-Encoding"] = encoding;
|
|
976
|
-
headers["Vary"] = "Accept-Encoding";
|
|
977
|
-
res.writeHead(status, headers);
|
|
978
|
-
res.end(compressed);
|
|
979
|
-
} catch (err) {
|
|
980
|
-
log.error("Compression error:", err);
|
|
981
|
-
res.writeHead(status, headers);
|
|
982
|
-
res.end(body2);
|
|
983
|
-
}
|
|
984
|
-
}
|
|
985
|
-
|
|
986
47
|
// src/build.ts
|
|
987
|
-
var __filename =
|
|
988
|
-
var __dirname =
|
|
989
|
-
var
|
|
990
|
-
var builderPath =
|
|
48
|
+
var __filename = fileURLToPath(import.meta.url);
|
|
49
|
+
var __dirname = path.dirname(__filename);
|
|
50
|
+
var packageDir = path.resolve(__dirname, "..");
|
|
51
|
+
var builderPath = path.resolve(packageDir, "./dist/page_compiler.mjs");
|
|
991
52
|
var yellow = (text) => {
|
|
992
53
|
return `\x1B[38;2;238;184;68m${text}`;
|
|
993
54
|
};
|
|
@@ -1006,11 +67,11 @@ var finishLog = (...text) => {
|
|
|
1006
67
|
var options = process.env.OPTIONS;
|
|
1007
68
|
var getAllSubdirectories = (dir, baseDir = dir) => {
|
|
1008
69
|
let directories = [];
|
|
1009
|
-
const items =
|
|
70
|
+
const items = fs.readdirSync(dir, { withFileTypes: true });
|
|
1010
71
|
for (const item of items) {
|
|
1011
72
|
if (item.isDirectory()) {
|
|
1012
|
-
const fullPath =
|
|
1013
|
-
const relativePath =
|
|
73
|
+
const fullPath = path.join(dir, item.name);
|
|
74
|
+
const relativePath = path.relative(baseDir, fullPath);
|
|
1014
75
|
directories.push(relativePath);
|
|
1015
76
|
directories = directories.concat(getAllSubdirectories(fullPath, baseDir));
|
|
1016
77
|
}
|
|
@@ -1030,7 +91,7 @@ var runBuild = (filepath, DIST_DIR) => {
|
|
|
1030
91
|
}
|
|
1031
92
|
child = child_process.spawn("node", [filepath], {
|
|
1032
93
|
stdio: ["inherit", "inherit", "inherit", "ipc"],
|
|
1033
|
-
env: { ...process.env, DIST_DIR, OPTIONS: optionsString, PACKAGE_PATH:
|
|
94
|
+
env: { ...process.env, DIST_DIR, OPTIONS: optionsString, PACKAGE_PATH: packageDir }
|
|
1034
95
|
});
|
|
1035
96
|
child.on("error", () => {
|
|
1036
97
|
log.error("Failed to start child process.");
|
|
@@ -1057,9 +118,6 @@ var runBuild = (filepath, DIST_DIR) => {
|
|
|
1057
118
|
);
|
|
1058
119
|
options.postCompile();
|
|
1059
120
|
}
|
|
1060
|
-
} else if (data === "set-layouts") {
|
|
1061
|
-
globalThis.__SERVER_CURRENT_LAYOUTS__ = new Map(JSON.parse(message.layouts));
|
|
1062
|
-
globalThis.__SERVER_CURRENT_LAYOUT_ID__ = parseInt(message.currentLayoutId);
|
|
1063
121
|
}
|
|
1064
122
|
});
|
|
1065
123
|
};
|
|
@@ -1101,31 +159,22 @@ var compile = async (props) => {
|
|
|
1101
159
|
options = props;
|
|
1102
160
|
setQuiet(options.quiet ?? false);
|
|
1103
161
|
const watch = options.hotReload !== void 0;
|
|
1104
|
-
const BUILD_FLAG =
|
|
1105
|
-
if (!
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
162
|
+
const BUILD_FLAG = path.join(options.outputDirectory, "ELEGANCE_BUILD_FLAG");
|
|
163
|
+
if (!fs.existsSync(options.outputDirectory)) {
|
|
164
|
+
fs.mkdirSync(options.outputDirectory, { recursive: true });
|
|
165
|
+
fs.writeFileSync(
|
|
166
|
+
path.join(BUILD_FLAG),
|
|
1109
167
|
"This file just marks this directory as one containing an Elegance Build.",
|
|
1110
168
|
"utf-8"
|
|
1111
169
|
);
|
|
1112
170
|
} else {
|
|
1113
|
-
if (!
|
|
171
|
+
if (!fs.existsSync(BUILD_FLAG)) {
|
|
1114
172
|
throw `The output directory already exists, but is not an Elegance Build directory.`;
|
|
1115
173
|
}
|
|
1116
174
|
}
|
|
1117
|
-
const DIST_DIR =
|
|
1118
|
-
if (!
|
|
1119
|
-
|
|
1120
|
-
}
|
|
1121
|
-
if (props.server != void 0 && props.server.runServer == true) {
|
|
1122
|
-
startServer({
|
|
1123
|
-
root: props.server.root ?? DIST_DIR,
|
|
1124
|
-
environment: props.environment,
|
|
1125
|
-
port: props.server.port ?? 3e3,
|
|
1126
|
-
host: props.server.host ?? "localhost",
|
|
1127
|
-
DIST_DIR
|
|
1128
|
-
});
|
|
175
|
+
const DIST_DIR = path.join(props.outputDirectory, "dist");
|
|
176
|
+
if (!fs.existsSync(DIST_DIR)) {
|
|
177
|
+
fs.mkdirSync(DIST_DIR, { recursive: true });
|
|
1129
178
|
}
|
|
1130
179
|
if (watch) {
|
|
1131
180
|
await registerListener();
|
|
@@ -1137,12 +186,12 @@ var compile = async (props) => {
|
|
|
1137
186
|
const dirs = options.hotReload?.extraWatchDirectories ?? [];
|
|
1138
187
|
if (dirs.length !== 0) {
|
|
1139
188
|
for (const dir of dirs) {
|
|
1140
|
-
const subdirs = getAllSubdirectories(dir).map((f) =>
|
|
189
|
+
const subdirs = getAllSubdirectories(dir).map((f) => path.join(dir, f));
|
|
1141
190
|
extra.push(...subdirs);
|
|
1142
191
|
}
|
|
1143
192
|
}
|
|
1144
193
|
}
|
|
1145
|
-
const pagesSubDirs = getAllSubdirectories(options.pagesDirectory).map((f) =>
|
|
194
|
+
const pagesSubDirs = getAllSubdirectories(options.pagesDirectory).map((f) => path.join(options.pagesDirectory, f));
|
|
1146
195
|
const subdirectories = [...pagesSubDirs, options.pagesDirectory, ...extra];
|
|
1147
196
|
finishLog(yellow("Hot-Reload Watching Subdirectories: "), ...subdirectories.join(", "));
|
|
1148
197
|
const watcherFn = async () => {
|
|
@@ -1155,7 +204,7 @@ var compile = async (props) => {
|
|
|
1155
204
|
}, 100);
|
|
1156
205
|
};
|
|
1157
206
|
for (const directory of subdirectories) {
|
|
1158
|
-
const watcher =
|
|
207
|
+
const watcher = fs.watch(
|
|
1159
208
|
directory,
|
|
1160
209
|
{},
|
|
1161
210
|
watcherFn
|
|
@@ -1168,11 +217,11 @@ var compile = async (props) => {
|
|
|
1168
217
|
|
|
1169
218
|
// src/compile_docs.ts
|
|
1170
219
|
import { exec, execSync } from "child_process";
|
|
1171
|
-
import
|
|
1172
|
-
var __dirname2 =
|
|
1173
|
-
var PAGES_DIR =
|
|
1174
|
-
var PUBLIC_DIR =
|
|
1175
|
-
var OUTPUT_DIR =
|
|
220
|
+
import path2 from "path";
|
|
221
|
+
var __dirname2 = path2.dirname(fileURLToPath2(import.meta.url));
|
|
222
|
+
var PAGES_DIR = path2.join(__dirname2, "../src/docs");
|
|
223
|
+
var PUBLIC_DIR = path2.join(__dirname2, "../src/docs/public");
|
|
224
|
+
var OUTPUT_DIR = path2.join(__dirname2, "../docs");
|
|
1176
225
|
var environmentArg = process.argv.find((arg) => arg.startsWith("--environment"));
|
|
1177
226
|
if (!environmentArg) environmentArg = "--environment='production'";
|
|
1178
227
|
var environment = environmentArg.split("=")[1];
|