elegance-js 2.1.23 → 2.1.26
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/client/effect.d.ts +27 -0
- package/dist/client/effect.js +37 -0
- package/dist/client/eventListener.d.ts +39 -0
- package/dist/client/eventListener.js +52 -0
- package/dist/client/loadHook.d.ts +34 -0
- package/dist/client/loadHook.js +52 -0
- package/dist/client/observer.d.ts +36 -0
- package/dist/client/observer.js +66 -0
- package/dist/client/runtime.d.ts +105 -0
- package/dist/client/runtime.js +620 -0
- package/dist/client/state.d.ts +40 -0
- package/dist/client/state.js +110 -0
- package/dist/compilation/compiler.d.ts +155 -0
- package/dist/compilation/compiler.js +1153 -0
- package/dist/components/ClientComponent.d.ts +22 -0
- package/dist/components/ClientComponent.js +55 -0
- package/dist/components/Link.d.ts +16 -1
- package/dist/components/Link.js +22 -0
- package/dist/components/Portal.d.ts +2 -0
- package/dist/components/Portal.js +2 -0
- package/dist/elements/element.d.ts +87 -0
- package/dist/elements/element.js +33 -0
- package/dist/elements/element_list.d.ts +7 -0
- package/dist/elements/element_list.js +65 -0
- package/dist/elements/raw.d.ts +14 -0
- package/dist/elements/raw.js +78 -0
- package/dist/elements/specific_props.d.ts +750 -0
- package/dist/global.d.ts +221 -327
- package/dist/index.d.ts +15 -3
- package/dist/index.js +11 -0
- package/dist/server/layout.d.ts +34 -3
- package/dist/server/layout.js +6 -0
- package/dist/server/log.d.ts +12 -0
- package/dist/server/log.js +64 -0
- package/dist/server/page.d.ts +32 -0
- package/dist/server/page.js +6 -0
- package/dist/server/runtime.d.ts +6 -0
- package/dist/server/runtime.js +72 -0
- package/dist/server/server.d.ts +103 -11
- package/dist/server/server.js +709 -0
- package/package.json +13 -13
- package/scripts/bootstrap.js +37 -273
- package/scripts/bootstrap_files/elegance.txt +40 -0
- package/scripts/bootstrap_files/index.txt +3 -0
- package/scripts/bootstrap_files/layout.txt +46 -0
- package/scripts/bootstrap_files/middleware.txt +18 -0
- package/scripts/bootstrap_files/page.txt +123 -0
- package/scripts/bootstrap_files/route.txt +6 -0
- package/scripts/elegance_dev.ts +40 -0
- package/scripts/elegance_prod.ts +40 -0
- package/scripts/elegance_static.ts +24 -0
- package/scripts/prod.js +9 -26
- package/scripts/run.js +13 -0
- package/scripts/static.js +13 -0
- package/dist/build.d.ts +0 -2
- package/dist/build.mjs +0 -202
- package/dist/client/client.d.ts +0 -1
- package/dist/client/client.mjs +0 -574
- package/dist/client/processPageElements.d.ts +0 -1
- package/dist/client/processPageElements.mjs +0 -117
- package/dist/client/render.d.ts +0 -1
- package/dist/client/render.mjs +0 -40
- package/dist/client/watcher.d.ts +0 -1
- package/dist/client/watcher.mjs +0 -26
- package/dist/compilation/compilation.d.ts +0 -139
- package/dist/compilation/compilation.mjs +0 -751
- package/dist/compilation/compiler_process.d.ts +0 -3
- package/dist/compilation/compiler_process.mjs +0 -102
- package/dist/compilation/dynamic_compiler.d.ts +0 -10
- package/dist/compilation/dynamic_compiler.mjs +0 -93
- package/dist/compile_docs.mjs +0 -34
- package/dist/components/Link.mjs +0 -65
- package/dist/global.mjs +0 -0
- package/dist/helpers/ObjectAttributeType.d.ts +0 -7
- package/dist/helpers/ObjectAttributeType.mjs +0 -11
- package/dist/helpers/camelToKebab.d.ts +0 -1
- package/dist/helpers/camelToKebab.mjs +0 -6
- package/dist/index.mjs +0 -3
- package/dist/internal/deprecate.d.ts +0 -1
- package/dist/internal/deprecate.mjs +0 -7
- package/dist/log.d.ts +0 -10
- package/dist/log.mjs +0 -38
- package/dist/server/generateHTMLTemplate.d.ts +0 -12
- package/dist/server/generateHTMLTemplate.mjs +0 -41
- package/dist/server/layout.mjs +0 -19
- package/dist/server/loadHook.d.ts +0 -30
- package/dist/server/loadHook.mjs +0 -50
- package/dist/server/observe.d.ts +0 -19
- package/dist/server/observe.mjs +0 -16
- package/dist/server/render.d.ts +0 -5
- package/dist/server/render.mjs +0 -61
- package/dist/server/server.mjs +0 -429
- package/dist/server/state.d.ts +0 -61
- package/dist/server/state.mjs +0 -146
- package/dist/shared/bindServerElements.mjs +0 -3
- package/dist/shared/serverElements.d.ts +0 -11
- package/dist/shared/serverElements.mjs +0 -164
- package/scripts/dev.js +0 -33
- package/scripts/export.js +0 -20
- package/scripts/ts-arc-dev.js +0 -9
- package/scripts/ts-arc-prod.js +0 -9
- /package/dist/{compile_docs.d.ts → elements/specific_props.js} +0 -0
- /package/dist/{shared/bindServerElements.d.ts → global.js} +0 -0
|
@@ -1,751 +0,0 @@
|
|
|
1
|
-
import fs from "fs";
|
|
2
|
-
import path from "path";
|
|
3
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
4
|
-
const __dirname = path.dirname(__filename);
|
|
5
|
-
import esbuild from "esbuild";
|
|
6
|
-
import { fileURLToPath } from "url";
|
|
7
|
-
import { generateHTMLTemplate } from "../server/generateHTMLTemplate";
|
|
8
|
-
import crypto from "crypto";
|
|
9
|
-
import { ObjectAttributeType } from "../helpers/ObjectAttributeType";
|
|
10
|
-
import { serverSideRenderPage } from "../server/render";
|
|
11
|
-
import { getState, initializeState, initializeObjectAttributes, getObjectAttributes } from "../server/state";
|
|
12
|
-
import { getLoadHooks, resetLoadHooks } from "../server/loadHook";
|
|
13
|
-
import { resetLayouts } from "../server/layout";
|
|
14
|
-
import { renderRecursively } from "../server/render";
|
|
15
|
-
let PAGE_MAP = /* @__PURE__ */ new Map();
|
|
16
|
-
let LAYOUT_MAP = /* @__PURE__ */ new Map();
|
|
17
|
-
function populateServerMaps(pageMap, layoutMap) {
|
|
18
|
-
LAYOUT_MAP = layoutMap;
|
|
19
|
-
PAGE_MAP = pageMap;
|
|
20
|
-
}
|
|
21
|
-
let options;
|
|
22
|
-
let DIST_DIR;
|
|
23
|
-
let elementKey = 0;
|
|
24
|
-
const shippedModules = /* @__PURE__ */ new Map();
|
|
25
|
-
let modulesToShip = [];
|
|
26
|
-
let packageDir = process.env.PACKAGE_PATH;
|
|
27
|
-
if (packageDir === void 0) {
|
|
28
|
-
packageDir = path.resolve(__dirname, "..");
|
|
29
|
-
}
|
|
30
|
-
const clientPath = path.resolve(packageDir, "./dist/client/client.mjs");
|
|
31
|
-
const watcherPath = path.resolve(packageDir, "./dist/client/watcher.mjs");
|
|
32
|
-
function setCompilationOptions(newOptions, distDir) {
|
|
33
|
-
options = newOptions;
|
|
34
|
-
DIST_DIR = distDir;
|
|
35
|
-
}
|
|
36
|
-
function getAllSubdirectories(dir, baseDir = dir) {
|
|
37
|
-
let directories = [];
|
|
38
|
-
const items = fs.readdirSync(dir, { withFileTypes: true });
|
|
39
|
-
for (const item of items) {
|
|
40
|
-
if (item.isDirectory()) {
|
|
41
|
-
const fullPath = path.join(dir, item.name);
|
|
42
|
-
const relativePath = path.relative(baseDir, fullPath);
|
|
43
|
-
directories.push(relativePath);
|
|
44
|
-
directories = directories.concat(getAllSubdirectories(fullPath, baseDir));
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
return directories;
|
|
48
|
-
}
|
|
49
|
-
;
|
|
50
|
-
async function buildClient(DIST_DIR2) {
|
|
51
|
-
let clientString = "window.__name = (func) => func; ";
|
|
52
|
-
clientString += fs.readFileSync(clientPath, "utf-8");
|
|
53
|
-
if (options.hotReload !== void 0) {
|
|
54
|
-
clientString += `const watchServerPort = ${options.hotReload.port};`;
|
|
55
|
-
clientString += fs.readFileSync(watcherPath, "utf-8");
|
|
56
|
-
}
|
|
57
|
-
const transformedClient = await esbuild.transform(clientString, {
|
|
58
|
-
minify: options.environment === "production",
|
|
59
|
-
drop: options.environment === "production" ? ["console", "debugger"] : void 0,
|
|
60
|
-
keepNames: false,
|
|
61
|
-
format: "iife",
|
|
62
|
-
platform: "node",
|
|
63
|
-
loader: "ts"
|
|
64
|
-
});
|
|
65
|
-
fs.writeFileSync(
|
|
66
|
-
path.join(DIST_DIR2, "/client.js"),
|
|
67
|
-
transformedClient.code
|
|
68
|
-
);
|
|
69
|
-
}
|
|
70
|
-
;
|
|
71
|
-
function processOptionAsObjectAttribute(element, optionName, optionValue, objectAttributes) {
|
|
72
|
-
const lcOptionName = optionName.toLowerCase();
|
|
73
|
-
const options2 = element.options;
|
|
74
|
-
let key = options2.key;
|
|
75
|
-
if (key == void 0) {
|
|
76
|
-
key = elementKey += 1;
|
|
77
|
-
options2.key = key;
|
|
78
|
-
}
|
|
79
|
-
if (!optionValue.type) {
|
|
80
|
-
throw `ObjectAttributeType is missing from object attribute. ${element.tag}: ${optionName}/${optionValue}`;
|
|
81
|
-
}
|
|
82
|
-
let optionFinal = lcOptionName;
|
|
83
|
-
switch (optionValue.type) {
|
|
84
|
-
case ObjectAttributeType.STATE:
|
|
85
|
-
const SOA = optionValue;
|
|
86
|
-
if (typeof SOA.value === "function") {
|
|
87
|
-
delete options2[optionName];
|
|
88
|
-
break;
|
|
89
|
-
}
|
|
90
|
-
if (lcOptionName === "innertext" || lcOptionName === "innerhtml") {
|
|
91
|
-
element.children = [SOA.value];
|
|
92
|
-
delete options2[optionName];
|
|
93
|
-
} else {
|
|
94
|
-
delete options2[optionName];
|
|
95
|
-
options2[lcOptionName] = SOA.value;
|
|
96
|
-
}
|
|
97
|
-
break;
|
|
98
|
-
case ObjectAttributeType.OBSERVER:
|
|
99
|
-
const OOA = optionValue;
|
|
100
|
-
const firstValue = OOA.update(...OOA.initialValues);
|
|
101
|
-
if (lcOptionName === "innertext" || lcOptionName === "innerhtml") {
|
|
102
|
-
element.children = [firstValue];
|
|
103
|
-
delete options2[optionName];
|
|
104
|
-
} else {
|
|
105
|
-
delete options2[optionName];
|
|
106
|
-
options2[lcOptionName] = firstValue;
|
|
107
|
-
}
|
|
108
|
-
optionFinal = optionName;
|
|
109
|
-
break;
|
|
110
|
-
case ObjectAttributeType.REFERENCE:
|
|
111
|
-
options2["ref"] = optionValue.value;
|
|
112
|
-
break;
|
|
113
|
-
}
|
|
114
|
-
objectAttributes.push({ ...optionValue, key, attribute: optionFinal });
|
|
115
|
-
}
|
|
116
|
-
;
|
|
117
|
-
function buildTrace(stack, indent = 4) {
|
|
118
|
-
try {
|
|
119
|
-
if (!stack || stack.length === 0) return "[]";
|
|
120
|
-
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] };
|
|
121
|
-
traceObj._error = "This is the element where the error occurred";
|
|
122
|
-
for (let i = stack.length - 2; i >= 0; i--) {
|
|
123
|
-
const parent = stack[i];
|
|
124
|
-
const child = stack[i + 1];
|
|
125
|
-
if (!parent || typeof parent !== "object") {
|
|
126
|
-
traceObj = { value: parent, _errorChild: traceObj };
|
|
127
|
-
continue;
|
|
128
|
-
}
|
|
129
|
-
let parentClone;
|
|
130
|
-
try {
|
|
131
|
-
parentClone = JSON.parse(JSON.stringify(parent));
|
|
132
|
-
} catch {
|
|
133
|
-
parentClone = { value: parent };
|
|
134
|
-
}
|
|
135
|
-
let index = -1;
|
|
136
|
-
if (Array.isArray(parentClone.children)) {
|
|
137
|
-
index = parentClone.children.findIndex((c) => c === child);
|
|
138
|
-
}
|
|
139
|
-
if (index !== -1 && parentClone.children) {
|
|
140
|
-
parentClone.children = parentClone.children.slice(0, index + 1);
|
|
141
|
-
parentClone.children[index] = traceObj;
|
|
142
|
-
} else {
|
|
143
|
-
parentClone._errorChild = traceObj;
|
|
144
|
-
}
|
|
145
|
-
traceObj = parentClone;
|
|
146
|
-
}
|
|
147
|
-
return JSON.stringify(traceObj, null, indent).replace(/^/gm, " ".repeat(indent));
|
|
148
|
-
} catch {
|
|
149
|
-
return "Could not build stack-trace.";
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
function processPageElements(element, objectAttributes, recursionLevel, stack = []) {
|
|
153
|
-
stack.push(element);
|
|
154
|
-
try {
|
|
155
|
-
if (typeof element === "boolean" || typeof element === "number" || Array.isArray(element)) {
|
|
156
|
-
stack.pop();
|
|
157
|
-
return element;
|
|
158
|
-
}
|
|
159
|
-
if (typeof element === "string") {
|
|
160
|
-
stack.pop();
|
|
161
|
-
return element;
|
|
162
|
-
}
|
|
163
|
-
const processElementOptionsAsChildAndReturn = () => {
|
|
164
|
-
try {
|
|
165
|
-
const children = element.children;
|
|
166
|
-
element.children = [
|
|
167
|
-
element.options,
|
|
168
|
-
...children
|
|
169
|
-
];
|
|
170
|
-
element.options = {};
|
|
171
|
-
for (let i = 0; i < children.length + 1; i++) {
|
|
172
|
-
const child = element.children[i];
|
|
173
|
-
const processedChild = processPageElements(child, objectAttributes, recursionLevel + 1, stack);
|
|
174
|
-
element.children[i] = processedChild;
|
|
175
|
-
}
|
|
176
|
-
return {
|
|
177
|
-
...element,
|
|
178
|
-
options: {}
|
|
179
|
-
};
|
|
180
|
-
} catch (e) {
|
|
181
|
-
const errorString = `Could not process element options as a child. ${e}.`;
|
|
182
|
-
throw new Error(errorString);
|
|
183
|
-
}
|
|
184
|
-
};
|
|
185
|
-
if (typeof element.options !== "object") {
|
|
186
|
-
const result = processElementOptionsAsChildAndReturn();
|
|
187
|
-
stack.pop();
|
|
188
|
-
return result;
|
|
189
|
-
}
|
|
190
|
-
const {
|
|
191
|
-
tag: elementTag,
|
|
192
|
-
options: elementOptions,
|
|
193
|
-
children: elementChildren
|
|
194
|
-
} = element.options;
|
|
195
|
-
if (elementTag && elementOptions && elementChildren) {
|
|
196
|
-
const result = processElementOptionsAsChildAndReturn();
|
|
197
|
-
stack.pop();
|
|
198
|
-
return result;
|
|
199
|
-
}
|
|
200
|
-
const options2 = element.options;
|
|
201
|
-
for (const [optionName, optionValue] of Object.entries(options2)) {
|
|
202
|
-
const lcOptionName = optionName.toLowerCase();
|
|
203
|
-
if (typeof optionValue !== "object") {
|
|
204
|
-
if (lcOptionName === "innertext") {
|
|
205
|
-
delete options2[optionName];
|
|
206
|
-
if (element.children === null) {
|
|
207
|
-
throw `Cannot use innerText or innerHTML on childrenless elements.`;
|
|
208
|
-
}
|
|
209
|
-
element.children = [optionValue, ...element.children];
|
|
210
|
-
continue;
|
|
211
|
-
} else if (lcOptionName === "innerhtml") {
|
|
212
|
-
if (element.children === null) {
|
|
213
|
-
throw `Cannot use innerText or innerHTML on childrenless elements.`;
|
|
214
|
-
}
|
|
215
|
-
delete options2[optionName];
|
|
216
|
-
element.children = [optionValue];
|
|
217
|
-
continue;
|
|
218
|
-
}
|
|
219
|
-
continue;
|
|
220
|
-
}
|
|
221
|
-
;
|
|
222
|
-
processOptionAsObjectAttribute(element, optionName, optionValue, objectAttributes);
|
|
223
|
-
}
|
|
224
|
-
if (element.children) {
|
|
225
|
-
for (let i = 0; i < element.children.length; i++) {
|
|
226
|
-
const child = element.children[i];
|
|
227
|
-
const processedChild = processPageElements(child, objectAttributes, recursionLevel + 1, stack);
|
|
228
|
-
element.children[i] = processedChild;
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
stack.pop();
|
|
232
|
-
return element;
|
|
233
|
-
} catch (e) {
|
|
234
|
-
const trace = buildTrace(stack);
|
|
235
|
-
if (recursionLevel === 0) {
|
|
236
|
-
throw new Error(`${e}
|
|
237
|
-
|
|
238
|
-
Trace:
|
|
239
|
-
${trace}`);
|
|
240
|
-
} else {
|
|
241
|
-
throw e;
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
;
|
|
246
|
-
async function pageToHTML(pageLocation, pageElements, metadata, DIST_DIR2, pageName, doWrite = true, requiredClientModules = {}, layout, pathname = "") {
|
|
247
|
-
if (typeof pageElements === "string" || typeof pageElements === "boolean" || typeof pageElements === "number" || Array.isArray(pageElements)) {
|
|
248
|
-
throw new Error(`The root element of a page / layout must be a built element, not just a Child. Received: ${typeof pageElements}.`);
|
|
249
|
-
}
|
|
250
|
-
const objectAttributes = [];
|
|
251
|
-
const stack = [];
|
|
252
|
-
const processedPageElements = processPageElements(pageElements, objectAttributes, 0, stack);
|
|
253
|
-
const renderedPage = await serverSideRenderPage(
|
|
254
|
-
processedPageElements,
|
|
255
|
-
pageLocation
|
|
256
|
-
);
|
|
257
|
-
const { internals, builtMetadata } = await generateHTMLTemplate({
|
|
258
|
-
pageURL: pathname,
|
|
259
|
-
head: metadata,
|
|
260
|
-
addPageScriptTag: doWrite,
|
|
261
|
-
name: pageName,
|
|
262
|
-
requiredClientModules,
|
|
263
|
-
environment: options.environment
|
|
264
|
-
});
|
|
265
|
-
let extraBodyHTML = "";
|
|
266
|
-
if (doWrite === false) {
|
|
267
|
-
const state = getState();
|
|
268
|
-
const pageLoadHooks = getLoadHooks();
|
|
269
|
-
const userObjectAttributes = getObjectAttributes();
|
|
270
|
-
const {
|
|
271
|
-
result
|
|
272
|
-
} = await generateClientPageData(
|
|
273
|
-
pathname,
|
|
274
|
-
state || {},
|
|
275
|
-
[...objectAttributes, ...userObjectAttributes],
|
|
276
|
-
pageLoadHooks || [],
|
|
277
|
-
DIST_DIR2,
|
|
278
|
-
"page",
|
|
279
|
-
"pd",
|
|
280
|
-
false
|
|
281
|
-
);
|
|
282
|
-
const sanitized = pathname === "" ? "/" : `/${pathname}`;
|
|
283
|
-
extraBodyHTML = `<script data-hook="true" data-pathname="${sanitized}" type="text/plain">${result}</script>`;
|
|
284
|
-
extraBodyHTML += `<script>
|
|
285
|
-
const text = document.querySelector('[data-hook="true"][data-pathname="${sanitized}"][type="text/plain"').textContent;
|
|
286
|
-
const blob = new Blob([text], { type: 'text/javascript' });
|
|
287
|
-
const url = URL.createObjectURL(blob);
|
|
288
|
-
|
|
289
|
-
const script = document.createElement("script");
|
|
290
|
-
script.src = url;
|
|
291
|
-
script.type = "module";
|
|
292
|
-
script.setAttribute("data-page", "true");
|
|
293
|
-
script.setAttribute("data-pathname", "${sanitized}");
|
|
294
|
-
|
|
295
|
-
document.head.appendChild(script);
|
|
296
|
-
|
|
297
|
-
document.currentScript.remove();
|
|
298
|
-
</script>`;
|
|
299
|
-
extraBodyHTML = extraBodyHTML.replace(/\s+/g, " ").replace(/\s*([{}();,:])\s*/g, "$1").trim();
|
|
300
|
-
}
|
|
301
|
-
const headHTML = `<!DOCTYPE html>${layout.metadata.startHTML}${layout.scriptTag}${internals}${builtMetadata}${layout.metadata.endHTML}`;
|
|
302
|
-
const bodyHTML = `${layout.pageContent.startHTML}${renderedPage.bodyHTML}${extraBodyHTML}${layout.pageContent.endHTML}`;
|
|
303
|
-
const resultHTML = `${headHTML}${bodyHTML}`;
|
|
304
|
-
const htmlLocation = path.join(pageLocation, (pageName === "page" ? "index" : pageName) + ".html");
|
|
305
|
-
if (doWrite) {
|
|
306
|
-
const dirname = path.dirname(htmlLocation);
|
|
307
|
-
if (fs.existsSync(dirname) === false) {
|
|
308
|
-
fs.mkdirSync(dirname, { recursive: true });
|
|
309
|
-
}
|
|
310
|
-
fs.writeFileSync(
|
|
311
|
-
htmlLocation,
|
|
312
|
-
resultHTML,
|
|
313
|
-
{
|
|
314
|
-
encoding: "utf-8",
|
|
315
|
-
flag: "w"
|
|
316
|
-
}
|
|
317
|
-
);
|
|
318
|
-
return objectAttributes;
|
|
319
|
-
}
|
|
320
|
-
return resultHTML;
|
|
321
|
-
}
|
|
322
|
-
;
|
|
323
|
-
async function generateClientPageData(pageLocation, state, objectAttributes, pageLoadHooks, DIST_DIR2, pageName, globalVariableName = "pd", write = true) {
|
|
324
|
-
let clientPageJSText = "";
|
|
325
|
-
{
|
|
326
|
-
clientPageJSText += `${globalThis.__SERVER_PAGE_DATA_BANNER__}`;
|
|
327
|
-
}
|
|
328
|
-
{
|
|
329
|
-
clientPageJSText += `export const data = {`;
|
|
330
|
-
if (state) {
|
|
331
|
-
clientPageJSText += `state:[`;
|
|
332
|
-
for (const subject of state) {
|
|
333
|
-
if (typeof subject.value === "string") {
|
|
334
|
-
const stringified = JSON.stringify(subject.value);
|
|
335
|
-
clientPageJSText += `{id:${subject.id},value:${stringified}},`;
|
|
336
|
-
} else if (typeof subject.value === "function") {
|
|
337
|
-
clientPageJSText += `{id:${subject.id},value:${subject.value.toString()}},`;
|
|
338
|
-
} else {
|
|
339
|
-
clientPageJSText += `{id:${subject.id},value:${JSON.stringify(subject.value)}},`;
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
clientPageJSText += `],`;
|
|
343
|
-
}
|
|
344
|
-
const stateObjectAttributes = objectAttributes.filter((oa) => oa.type === ObjectAttributeType.STATE);
|
|
345
|
-
if (stateObjectAttributes.length > 0) {
|
|
346
|
-
const processed = [...stateObjectAttributes].map((soa) => {
|
|
347
|
-
delete soa.type;
|
|
348
|
-
return soa;
|
|
349
|
-
});
|
|
350
|
-
clientPageJSText += `soa:${JSON.stringify(processed)},`;
|
|
351
|
-
}
|
|
352
|
-
const observerObjectAttributes = objectAttributes.filter((oa) => oa.type === ObjectAttributeType.OBSERVER);
|
|
353
|
-
if (observerObjectAttributes.length > 0) {
|
|
354
|
-
let observerObjectAttributeString = "ooa:[";
|
|
355
|
-
for (const observerObjectAttribute of observerObjectAttributes) {
|
|
356
|
-
const ooa = observerObjectAttribute;
|
|
357
|
-
observerObjectAttributeString += `{key:${ooa.key},attribute:"${ooa.attribute}",update:${ooa.update.toString()},`;
|
|
358
|
-
observerObjectAttributeString += `refs:[`;
|
|
359
|
-
for (const ref of ooa.refs) {
|
|
360
|
-
observerObjectAttributeString += `{id:${ref.id}},`;
|
|
361
|
-
}
|
|
362
|
-
observerObjectAttributeString += "]},";
|
|
363
|
-
}
|
|
364
|
-
observerObjectAttributeString += "],";
|
|
365
|
-
clientPageJSText += observerObjectAttributeString;
|
|
366
|
-
}
|
|
367
|
-
if (pageLoadHooks.length > 0) {
|
|
368
|
-
clientPageJSText += "lh:[";
|
|
369
|
-
for (const loadHook of pageLoadHooks) {
|
|
370
|
-
clientPageJSText += `{fn:${loadHook.fn}},`;
|
|
371
|
-
}
|
|
372
|
-
clientPageJSText += "],";
|
|
373
|
-
}
|
|
374
|
-
clientPageJSText += `};`;
|
|
375
|
-
}
|
|
376
|
-
const pageDataPath = path.join(DIST_DIR2, pageLocation, `${pageName}_data.js`);
|
|
377
|
-
let sendHardReloadInstruction = false;
|
|
378
|
-
const transformedResult = await esbuild.transform(clientPageJSText, { minify: options.environment === "production" }).catch((error) => {
|
|
379
|
-
console.error("Failed to transform client page js!", error);
|
|
380
|
-
});
|
|
381
|
-
if (!transformedResult) return { sendHardReloadInstruction };
|
|
382
|
-
if (fs.existsSync(pageDataPath)) {
|
|
383
|
-
const content = fs.readFileSync(pageDataPath).toString();
|
|
384
|
-
if (content !== transformedResult.code) {
|
|
385
|
-
sendHardReloadInstruction = true;
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
if (write) fs.writeFileSync(pageDataPath, transformedResult.code, "utf-8");
|
|
389
|
-
return { sendHardReloadInstruction, result: transformedResult.code };
|
|
390
|
-
}
|
|
391
|
-
;
|
|
392
|
-
async function generateLayout(DIST_DIR2, filePath, directory, childIndicator, generateDynamic = false) {
|
|
393
|
-
initializeState();
|
|
394
|
-
initializeObjectAttributes();
|
|
395
|
-
resetLoadHooks();
|
|
396
|
-
globalThis.__SERVER_PAGE_DATA_BANNER__ = "";
|
|
397
|
-
let layoutElements;
|
|
398
|
-
let metadataElements;
|
|
399
|
-
let modules = [];
|
|
400
|
-
let isDynamicLayout = false;
|
|
401
|
-
try {
|
|
402
|
-
const {
|
|
403
|
-
layout,
|
|
404
|
-
metadata,
|
|
405
|
-
isDynamic,
|
|
406
|
-
shippedModules: shippedModules2
|
|
407
|
-
} = await import("file://" + filePath);
|
|
408
|
-
if (shippedModules2 !== void 0) {
|
|
409
|
-
modules = shippedModules2;
|
|
410
|
-
}
|
|
411
|
-
layoutElements = layout;
|
|
412
|
-
metadataElements = metadata;
|
|
413
|
-
if (isDynamic === true) {
|
|
414
|
-
isDynamicLayout = isDynamic;
|
|
415
|
-
}
|
|
416
|
-
} catch (e) {
|
|
417
|
-
throw new Error(`Error in Page: ${directory === "" ? "/" : directory}layout.ts - ${e}`);
|
|
418
|
-
}
|
|
419
|
-
LAYOUT_MAP.set(directory === "" ? "/" : `/${directory}`, {
|
|
420
|
-
isDynamic: isDynamicLayout,
|
|
421
|
-
filePath
|
|
422
|
-
});
|
|
423
|
-
if (isDynamicLayout === true && generateDynamic === false) return false;
|
|
424
|
-
{
|
|
425
|
-
if (!layoutElements) {
|
|
426
|
-
throw new Error(`WARNING: ${filePath} should export a const layout, which is of type Layout: (child: Child) => AnyBuiltElement.`);
|
|
427
|
-
}
|
|
428
|
-
if (typeof layoutElements === "function") {
|
|
429
|
-
if (layoutElements.constructor.name === "AsyncFunction") {
|
|
430
|
-
layoutElements = await layoutElements(childIndicator);
|
|
431
|
-
} else {
|
|
432
|
-
layoutElements = layoutElements(childIndicator);
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
{
|
|
437
|
-
if (!metadataElements) {
|
|
438
|
-
throw new Error(`WARNING: ${filePath} should export a const metadata, which is of type LayoutMetadata: (child: Child) => AnyBuiltElement.`);
|
|
439
|
-
}
|
|
440
|
-
if (typeof metadataElements === "function") {
|
|
441
|
-
if (metadataElements.constructor.name === "AsyncFunction") {
|
|
442
|
-
metadataElements = await metadataElements(childIndicator);
|
|
443
|
-
} else {
|
|
444
|
-
metadataElements = metadataElements(childIndicator);
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
const state = getState();
|
|
449
|
-
const pageLoadHooks = getLoadHooks();
|
|
450
|
-
const objectAttributes = getObjectAttributes();
|
|
451
|
-
if (typeof layoutElements === "string" || typeof layoutElements === "boolean" || typeof layoutElements === "number" || Array.isArray(layoutElements)) {
|
|
452
|
-
throw new Error(`The root element of a page / layout must be a built element, not just a Child. Received: ${typeof layoutElements}.`);
|
|
453
|
-
}
|
|
454
|
-
const foundObjectAttributes = [];
|
|
455
|
-
const stack = [];
|
|
456
|
-
const processedPageElements = processPageElements(layoutElements, foundObjectAttributes, 0, stack);
|
|
457
|
-
const renderedPage = await serverSideRenderPage(
|
|
458
|
-
processedPageElements,
|
|
459
|
-
directory
|
|
460
|
-
);
|
|
461
|
-
const metadataHTML = metadataElements ? renderRecursively(metadataElements) : "";
|
|
462
|
-
await generateClientPageData(
|
|
463
|
-
directory,
|
|
464
|
-
state || {},
|
|
465
|
-
[...objectAttributes, ...foundObjectAttributes],
|
|
466
|
-
pageLoadHooks || [],
|
|
467
|
-
DIST_DIR2,
|
|
468
|
-
"layout",
|
|
469
|
-
"ld"
|
|
470
|
-
);
|
|
471
|
-
return { pageContentHTML: renderedPage.bodyHTML, metadataHTML };
|
|
472
|
-
}
|
|
473
|
-
;
|
|
474
|
-
const builtLayouts = /* @__PURE__ */ new Map();
|
|
475
|
-
async function buildLayouts() {
|
|
476
|
-
const pagesDirectory = path.resolve(options.pagesDirectory);
|
|
477
|
-
const subdirectories = [...getAllSubdirectories(pagesDirectory), ""];
|
|
478
|
-
let shouldClientHardReload = false;
|
|
479
|
-
for (const directory of subdirectories) {
|
|
480
|
-
const abs = path.resolve(path.join(pagesDirectory, directory));
|
|
481
|
-
const files = fs.readdirSync(abs, { withFileTypes: true }).filter((f) => f.name.endsWith(".ts"));
|
|
482
|
-
for (const file of files) {
|
|
483
|
-
const filePath = path.join(file.parentPath, file.name);
|
|
484
|
-
const name = file.name.slice(0, file.name.length - 3);
|
|
485
|
-
const isLayout = name === "layout";
|
|
486
|
-
if (isLayout == false) {
|
|
487
|
-
continue;
|
|
488
|
-
}
|
|
489
|
-
try {
|
|
490
|
-
const builtLayout = await buildLayout(filePath, directory);
|
|
491
|
-
if (!builtLayout) return { shouldClientHardReload: false };
|
|
492
|
-
builtLayouts.set(filePath, builtLayout);
|
|
493
|
-
} catch (e) {
|
|
494
|
-
console.error(e);
|
|
495
|
-
continue;
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
return { shouldClientHardReload };
|
|
500
|
-
}
|
|
501
|
-
function hashDirectory(directory) {
|
|
502
|
-
return crypto.createHash("md5").update(directory).digest("hex");
|
|
503
|
-
}
|
|
504
|
-
async function buildLayout(filePath, directory, generateDynamic = false) {
|
|
505
|
-
const id = hashDirectory(directory);
|
|
506
|
-
const childIndicator = `<template layout-id="${id}"></template>`;
|
|
507
|
-
const result = await generateLayout(
|
|
508
|
-
DIST_DIR,
|
|
509
|
-
filePath,
|
|
510
|
-
directory,
|
|
511
|
-
childIndicator,
|
|
512
|
-
generateDynamic
|
|
513
|
-
);
|
|
514
|
-
if (result === false) return false;
|
|
515
|
-
const { pageContentHTML, metadataHTML } = result;
|
|
516
|
-
function splitAround(str, sub) {
|
|
517
|
-
const i = str.indexOf(sub);
|
|
518
|
-
if (i === -1) {
|
|
519
|
-
throw new Error(`Whilst layout ${directory}, the splitter could not be found. Make sure to use the "child" prop passed into the layout.`);
|
|
520
|
-
}
|
|
521
|
-
return {
|
|
522
|
-
startHTML: str.substring(0, i),
|
|
523
|
-
endHTML: str.substring(i + sub.length)
|
|
524
|
-
};
|
|
525
|
-
}
|
|
526
|
-
function splitAt(str, sub) {
|
|
527
|
-
const i = str.indexOf(sub) + sub.length;
|
|
528
|
-
if (i === -1) {
|
|
529
|
-
throw new Error(`Whilst layout ${directory}, the splitter could not be found. Make sure to use the "child" prop passed into the layout's metadata.`);
|
|
530
|
-
}
|
|
531
|
-
return {
|
|
532
|
-
startHTML: str.substring(0, i),
|
|
533
|
-
endHTML: str.substring(i)
|
|
534
|
-
};
|
|
535
|
-
}
|
|
536
|
-
const pathname = directory === "" ? "/" : directory;
|
|
537
|
-
return {
|
|
538
|
-
pageContent: splitAt(pageContentHTML, childIndicator),
|
|
539
|
-
metadata: splitAround(metadataHTML, childIndicator),
|
|
540
|
-
scriptTag: `<script data-layout="true" type="module" src="${pathname}layout_data.js" data-pathname="${pathname}" defer="true"></script>`
|
|
541
|
-
};
|
|
542
|
-
}
|
|
543
|
-
;
|
|
544
|
-
async function fetchPageLayoutHTML(dirname) {
|
|
545
|
-
const relative = path.relative(options.pagesDirectory, dirname);
|
|
546
|
-
let split = relative.split(path.sep).filter(Boolean);
|
|
547
|
-
split.push("/");
|
|
548
|
-
split.reverse();
|
|
549
|
-
let layouts = [];
|
|
550
|
-
for (const dir of split) {
|
|
551
|
-
if (!LAYOUT_MAP.has(dir)) {
|
|
552
|
-
console.warn("A layout was not found within the layout map for a path:", dir, "This is normally not meant to be possible, so you might have royally screwed up.");
|
|
553
|
-
continue;
|
|
554
|
-
}
|
|
555
|
-
const filePath = path.join(path.resolve(options.pagesDirectory), dir, "layout.ts");
|
|
556
|
-
const layout = LAYOUT_MAP.get(dir);
|
|
557
|
-
if (layout.isDynamic) {
|
|
558
|
-
const builtLayout = await buildLayout(layout.filePath, dir, true);
|
|
559
|
-
if (!builtLayout) continue;
|
|
560
|
-
layouts.push(builtLayout);
|
|
561
|
-
} else {
|
|
562
|
-
if (!builtLayouts.has(filePath)) {
|
|
563
|
-
const builtLayout = await buildLayout(layout.filePath, dir, true);
|
|
564
|
-
if (!builtLayout) continue;
|
|
565
|
-
builtLayouts.set(filePath, builtLayout);
|
|
566
|
-
layouts.push(builtLayout);
|
|
567
|
-
} else {
|
|
568
|
-
layouts.push(builtLayouts.get(filePath));
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
const pageContent = {
|
|
573
|
-
startHTML: "",
|
|
574
|
-
endHTML: ""
|
|
575
|
-
};
|
|
576
|
-
const metadata = {
|
|
577
|
-
startHTML: "",
|
|
578
|
-
endHTML: ""
|
|
579
|
-
};
|
|
580
|
-
let scriptTags = "";
|
|
581
|
-
for (const layout of layouts) {
|
|
582
|
-
pageContent.startHTML += layout.pageContent.startHTML;
|
|
583
|
-
metadata.startHTML += layout.metadata.startHTML;
|
|
584
|
-
scriptTags += layout.scriptTag;
|
|
585
|
-
pageContent.endHTML += layout.pageContent.endHTML;
|
|
586
|
-
metadata.endHTML += layout.metadata.endHTML;
|
|
587
|
-
}
|
|
588
|
-
return { pageContent, metadata, scriptTag: scriptTags };
|
|
589
|
-
}
|
|
590
|
-
;
|
|
591
|
-
async function buildPages(DIST_DIR2) {
|
|
592
|
-
resetLayouts();
|
|
593
|
-
const pagesDirectory = path.resolve(options.pagesDirectory);
|
|
594
|
-
const subdirectories = [...getAllSubdirectories(pagesDirectory), ""];
|
|
595
|
-
let shouldClientHardReload = false;
|
|
596
|
-
for (const directory of subdirectories) {
|
|
597
|
-
const abs = path.resolve(path.join(pagesDirectory, directory));
|
|
598
|
-
const files = fs.readdirSync(abs, { withFileTypes: true }).filter((f) => f.name.endsWith(".ts"));
|
|
599
|
-
for (const file of files) {
|
|
600
|
-
const filePath = path.join(file.parentPath, file.name);
|
|
601
|
-
const name = file.name.slice(0, file.name.length - 3);
|
|
602
|
-
const isPage = name === "page";
|
|
603
|
-
if (isPage == false) {
|
|
604
|
-
continue;
|
|
605
|
-
}
|
|
606
|
-
try {
|
|
607
|
-
const hardReloadForPage = await buildPage(DIST_DIR2, directory, filePath, name);
|
|
608
|
-
if (hardReloadForPage) {
|
|
609
|
-
shouldClientHardReload = true;
|
|
610
|
-
}
|
|
611
|
-
} catch (e) {
|
|
612
|
-
console.error(e);
|
|
613
|
-
continue;
|
|
614
|
-
}
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
|
-
return {
|
|
618
|
-
shouldClientHardReload
|
|
619
|
-
};
|
|
620
|
-
}
|
|
621
|
-
;
|
|
622
|
-
async function buildPage(DIST_DIR2, directory, filePath, name) {
|
|
623
|
-
initializeState();
|
|
624
|
-
initializeObjectAttributes();
|
|
625
|
-
resetLoadHooks();
|
|
626
|
-
globalThis.__SERVER_PAGE_DATA_BANNER__ = "";
|
|
627
|
-
let pageElements;
|
|
628
|
-
let metadata;
|
|
629
|
-
let modules = {};
|
|
630
|
-
let pageIgnoresLayout = false;
|
|
631
|
-
let isDynamicPage = false;
|
|
632
|
-
try {
|
|
633
|
-
const {
|
|
634
|
-
page,
|
|
635
|
-
metadata: pageMetadata,
|
|
636
|
-
isDynamic,
|
|
637
|
-
shippedModules: shippedModules2,
|
|
638
|
-
ignoreLayout
|
|
639
|
-
} = await import("file://" + filePath);
|
|
640
|
-
if (shippedModules2 !== void 0) {
|
|
641
|
-
modules = shippedModules2;
|
|
642
|
-
}
|
|
643
|
-
if (ignoreLayout) {
|
|
644
|
-
pageIgnoresLayout = true;
|
|
645
|
-
}
|
|
646
|
-
pageElements = page;
|
|
647
|
-
metadata = pageMetadata;
|
|
648
|
-
if (isDynamic === true) {
|
|
649
|
-
isDynamicPage = isDynamic;
|
|
650
|
-
}
|
|
651
|
-
} catch (e) {
|
|
652
|
-
throw new Error(`Error in Page: ${directory}/${name}.ts - ${e}`);
|
|
653
|
-
}
|
|
654
|
-
PAGE_MAP.set(directory === "" ? "/" : `/${directory}`, {
|
|
655
|
-
isDynamic: isDynamicPage,
|
|
656
|
-
filePath
|
|
657
|
-
});
|
|
658
|
-
if (isDynamicPage) return false;
|
|
659
|
-
if (modules !== void 0) {
|
|
660
|
-
for (const [globalName, path2] of Object.entries(modules)) {
|
|
661
|
-
modulesToShip.push({ globalName, path: path2 });
|
|
662
|
-
}
|
|
663
|
-
}
|
|
664
|
-
if (!metadata || metadata && typeof metadata !== "function") {
|
|
665
|
-
console.warn(`WARNING: ${filePath} does not export a metadata function.`);
|
|
666
|
-
}
|
|
667
|
-
if (!pageElements) {
|
|
668
|
-
console.warn(`WARNING: ${filePath} should export a const page, which is of type () => BuiltElement<"body">.`);
|
|
669
|
-
}
|
|
670
|
-
const pageProps = {
|
|
671
|
-
pageName: directory,
|
|
672
|
-
middlewareData: {}
|
|
673
|
-
};
|
|
674
|
-
if (typeof pageElements === "function") {
|
|
675
|
-
if (pageElements.constructor.name === "AsyncFunction") {
|
|
676
|
-
pageElements = await pageElements(pageProps);
|
|
677
|
-
} else {
|
|
678
|
-
pageElements = pageElements(pageProps);
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
const state = getState();
|
|
682
|
-
const pageLoadHooks = getLoadHooks();
|
|
683
|
-
const objectAttributes = getObjectAttributes();
|
|
684
|
-
const layout = await fetchPageLayoutHTML(path.dirname(filePath));
|
|
685
|
-
const foundObjectAttributes = await pageToHTML(
|
|
686
|
-
path.join(DIST_DIR2, directory),
|
|
687
|
-
pageElements || body(),
|
|
688
|
-
metadata ?? (() => head()),
|
|
689
|
-
DIST_DIR2,
|
|
690
|
-
name,
|
|
691
|
-
true,
|
|
692
|
-
modules,
|
|
693
|
-
layout,
|
|
694
|
-
directory
|
|
695
|
-
);
|
|
696
|
-
const {
|
|
697
|
-
sendHardReloadInstruction
|
|
698
|
-
} = await generateClientPageData(
|
|
699
|
-
directory,
|
|
700
|
-
state || {},
|
|
701
|
-
[...objectAttributes, ...foundObjectAttributes],
|
|
702
|
-
pageLoadHooks || [],
|
|
703
|
-
DIST_DIR2,
|
|
704
|
-
name
|
|
705
|
-
);
|
|
706
|
-
return sendHardReloadInstruction === true;
|
|
707
|
-
}
|
|
708
|
-
;
|
|
709
|
-
async function shipModules() {
|
|
710
|
-
for (const plugin of modulesToShip) {
|
|
711
|
-
{
|
|
712
|
-
if (shippedModules.has(plugin.globalName)) continue;
|
|
713
|
-
shippedModules.set(plugin.globalName, true);
|
|
714
|
-
}
|
|
715
|
-
esbuild.build({
|
|
716
|
-
entryPoints: [plugin.path],
|
|
717
|
-
bundle: true,
|
|
718
|
-
outfile: path.join(DIST_DIR, "shipped", plugin.globalName + ".js"),
|
|
719
|
-
format: "iife",
|
|
720
|
-
platform: "browser",
|
|
721
|
-
globalName: plugin.globalName,
|
|
722
|
-
minify: true,
|
|
723
|
-
treeShaking: true
|
|
724
|
-
});
|
|
725
|
-
}
|
|
726
|
-
modulesToShip = [];
|
|
727
|
-
}
|
|
728
|
-
;
|
|
729
|
-
function retrievePageAndLayoutMaps() {
|
|
730
|
-
return { LAYOUT_MAP, PAGE_MAP };
|
|
731
|
-
}
|
|
732
|
-
export {
|
|
733
|
-
LAYOUT_MAP,
|
|
734
|
-
PAGE_MAP,
|
|
735
|
-
buildClient,
|
|
736
|
-
buildLayout,
|
|
737
|
-
buildLayouts,
|
|
738
|
-
buildPage,
|
|
739
|
-
buildPages,
|
|
740
|
-
fetchPageLayoutHTML,
|
|
741
|
-
generateClientPageData,
|
|
742
|
-
generateLayout,
|
|
743
|
-
getAllSubdirectories,
|
|
744
|
-
modulesToShip,
|
|
745
|
-
pageToHTML,
|
|
746
|
-
populateServerMaps,
|
|
747
|
-
processPageElements,
|
|
748
|
-
retrievePageAndLayoutMaps,
|
|
749
|
-
setCompilationOptions,
|
|
750
|
-
shipModules
|
|
751
|
-
};
|