xpine 0.0.26 → 0.0.27
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/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +291 -111
- package/dist/src/build/esbuild/transformTSXFiles.d.ts.map +1 -1
- package/dist/src/build/typescript-builder.d.ts +7 -0
- package/dist/src/build/typescript-builder.d.ts.map +1 -1
- package/dist/src/context.d.ts +18 -0
- package/dist/src/context.d.ts.map +1 -0
- package/dist/src/express.d.ts.map +1 -1
- package/dist/src/scripts/build.d.ts +13 -2
- package/dist/src/scripts/build.d.ts.map +1 -1
- package/dist/src/scripts/xpine-build.js +265 -111
- package/dist/src/scripts/xpine-dev.js +250 -97
- package/dist/src/util/hooks/onInit.d.ts +3 -0
- package/dist/src/util/hooks/onInit.d.ts.map +1 -0
- package/dist/src/util/paths.d.ts +2 -0
- package/dist/src/util/paths.d.ts.map +1 -0
- package/dist/src/util/require.d.ts +0 -1
- package/dist/src/util/require.d.ts.map +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -1
- package/types.ts +3 -1
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -9,12 +9,146 @@ import chokidar from "chokidar";
|
|
|
9
9
|
import path5 from "path";
|
|
10
10
|
import fs5 from "fs-extra";
|
|
11
11
|
import { build } from "esbuild";
|
|
12
|
-
import ts3 from "typescript";
|
|
13
12
|
|
|
14
13
|
// src/build/typescript-builder.ts
|
|
15
14
|
import ts from "typescript";
|
|
16
15
|
import fs from "fs-extra";
|
|
16
|
+
import path2 from "path";
|
|
17
|
+
|
|
18
|
+
// src/util/get-config.ts
|
|
17
19
|
import path from "path";
|
|
20
|
+
|
|
21
|
+
// src/util/require.ts
|
|
22
|
+
import { createRequire } from "module";
|
|
23
|
+
var require_default = createRequire(import.meta.url);
|
|
24
|
+
|
|
25
|
+
// src/util/get-config.ts
|
|
26
|
+
var rootDir = process.cwd();
|
|
27
|
+
function fromRoot(pathName) {
|
|
28
|
+
if (!pathName) return rootDir;
|
|
29
|
+
return path.join(rootDir, pathName);
|
|
30
|
+
}
|
|
31
|
+
var userConfig = require_default(path.join(process.cwd(), "./xpine.config.mjs")).default;
|
|
32
|
+
var configDefaults = {
|
|
33
|
+
rootDir: fromRoot(),
|
|
34
|
+
srcDir: fromRoot("./src"),
|
|
35
|
+
distDir: fromRoot("./dist"),
|
|
36
|
+
packageJsonPath: fromRoot("package.json"),
|
|
37
|
+
// We need to use getters here in the event someone wants to change folders, such as the dist folder
|
|
38
|
+
get distPublicDir() {
|
|
39
|
+
return path.join(this.distDir, "./public");
|
|
40
|
+
},
|
|
41
|
+
get distPublicScriptsDir() {
|
|
42
|
+
return path.join(this.distPublicDir, "./scripts");
|
|
43
|
+
},
|
|
44
|
+
get distTempFolder() {
|
|
45
|
+
return path.join(this.distDir, "./temp");
|
|
46
|
+
},
|
|
47
|
+
get clientJSBundlePath() {
|
|
48
|
+
return path.join(this.distPublicScriptsDir, "./app.js");
|
|
49
|
+
},
|
|
50
|
+
get alpineDataPath() {
|
|
51
|
+
return path.join(this.distTempFolder, "./alpine-data.ts");
|
|
52
|
+
},
|
|
53
|
+
get serverDistDir() {
|
|
54
|
+
return path.join(this.distDir, "./server");
|
|
55
|
+
},
|
|
56
|
+
get serverDistAppPath() {
|
|
57
|
+
return path.join(this.serverDistDir, "./app.js");
|
|
58
|
+
},
|
|
59
|
+
// Important dirs/paths
|
|
60
|
+
get pagesDir() {
|
|
61
|
+
return path.join(this.srcDir, "./pages");
|
|
62
|
+
},
|
|
63
|
+
get distPagesDir() {
|
|
64
|
+
return path.join(this.distDir, "./pages");
|
|
65
|
+
},
|
|
66
|
+
get publicDir() {
|
|
67
|
+
return path.join(this.srcDir, "./public");
|
|
68
|
+
},
|
|
69
|
+
get serverDir() {
|
|
70
|
+
return path.join(this.srcDir, "./server");
|
|
71
|
+
},
|
|
72
|
+
get runDir() {
|
|
73
|
+
return path.join(this.serverDir, "./run");
|
|
74
|
+
},
|
|
75
|
+
get serverAppPath() {
|
|
76
|
+
return path.join(this.serverDir, "./app.ts");
|
|
77
|
+
},
|
|
78
|
+
get globalCSSFile() {
|
|
79
|
+
return path.join(this.publicDir, "./styles/global.css");
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
var config = {
|
|
83
|
+
...configDefaults,
|
|
84
|
+
...userConfig
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
// src/context.ts
|
|
88
|
+
function createContext(value) {
|
|
89
|
+
let stateValue = value;
|
|
90
|
+
let arrayQueue = {};
|
|
91
|
+
return {
|
|
92
|
+
get(id) {
|
|
93
|
+
const val = stateValue[id];
|
|
94
|
+
if (Array.isArray(val)) return val.filter((item) => item !== void 0);
|
|
95
|
+
return val;
|
|
96
|
+
},
|
|
97
|
+
set(id, callback, defaultValue) {
|
|
98
|
+
if (!stateValue[id]) stateValue[id] = defaultValue ?? null;
|
|
99
|
+
stateValue[id] = callback(stateValue[id]);
|
|
100
|
+
},
|
|
101
|
+
clear() {
|
|
102
|
+
stateValue = {};
|
|
103
|
+
},
|
|
104
|
+
getAll() {
|
|
105
|
+
return stateValue;
|
|
106
|
+
},
|
|
107
|
+
getArrayQueue() {
|
|
108
|
+
return arrayQueue;
|
|
109
|
+
},
|
|
110
|
+
addToArray(id, value2, position) {
|
|
111
|
+
const output = {
|
|
112
|
+
id,
|
|
113
|
+
value: addToContextArray(value2, position),
|
|
114
|
+
position
|
|
115
|
+
};
|
|
116
|
+
if (!arrayQueue[id]) {
|
|
117
|
+
arrayQueue[id] = [output];
|
|
118
|
+
} else {
|
|
119
|
+
arrayQueue[id].push(output);
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
runArrayQueue() {
|
|
123
|
+
Object.keys(arrayQueue).forEach((key) => {
|
|
124
|
+
arrayQueue[key].sort((a, b) => {
|
|
125
|
+
return (a?.position ?? Infinity) - (b.position ?? Infinity);
|
|
126
|
+
});
|
|
127
|
+
for (const item of arrayQueue[key]) {
|
|
128
|
+
this.set(key, item.value, []);
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
arrayQueue = {};
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
var context = createContext({});
|
|
136
|
+
function addToContextArray(newValue, position) {
|
|
137
|
+
return function(currentValue) {
|
|
138
|
+
if (!currentValue) return [newValue];
|
|
139
|
+
if (typeof position === "number") {
|
|
140
|
+
if (position > currentValue?.length) {
|
|
141
|
+
const output = [...currentValue, ...new Array(position + 1 - currentValue.length)];
|
|
142
|
+
return output.toSpliced(position, 0, newValue);
|
|
143
|
+
}
|
|
144
|
+
if (currentValue?.[position] === void 0) return currentValue.toSpliced(position, 1, newValue);
|
|
145
|
+
return currentValue.toSpliced(position, 0, newValue);
|
|
146
|
+
}
|
|
147
|
+
return [...currentValue, newValue];
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// src/build/typescript-builder.ts
|
|
18
152
|
function findDataAttributesAndFunctions(node, sourceFile, foundDataAttributes = [], foundFunctions = []) {
|
|
19
153
|
if (node.kind === ts.SyntaxKind.JsxAttribute) {
|
|
20
154
|
const attribute = getAttributeValuePair(node, sourceFile);
|
|
@@ -86,18 +220,7 @@ function removeClientScriptInTSXFile(pathName, source) {
|
|
|
86
220
|
}
|
|
87
221
|
if (child.kind === ts.SyntaxKind.ImportDeclaration && child.pos >= clientDataStart) {
|
|
88
222
|
const text = child.getText(source);
|
|
89
|
-
|
|
90
|
-
if (child2.kind === ts.SyntaxKind.StringLiteral) {
|
|
91
|
-
const text2 = child2.getText(source);
|
|
92
|
-
const importPath = text2.replace(/[\"\']/g, "");
|
|
93
|
-
const isRelativeImport = importPath.startsWith(".") || importPath.startsWith("/");
|
|
94
|
-
if (!isRelativeImport) return;
|
|
95
|
-
clientImportsToReplace.push({
|
|
96
|
-
old: importPath,
|
|
97
|
-
new: path.join(path.dirname(pathName), importPath)
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
});
|
|
223
|
+
clientImportsToReplace.push(...getImportsToAbsolutePaths(child, source, pathName));
|
|
101
224
|
clientImportsToHoist.push(text);
|
|
102
225
|
}
|
|
103
226
|
});
|
|
@@ -113,18 +236,58 @@ function removeClientScriptInTSXFile(pathName, source) {
|
|
|
113
236
|
clientDataStart
|
|
114
237
|
};
|
|
115
238
|
}
|
|
239
|
+
function getImportsToAbsolutePaths(child, source, pathName) {
|
|
240
|
+
const output = [];
|
|
241
|
+
child.forEachChild((child2) => {
|
|
242
|
+
if (child2.kind === ts.SyntaxKind.StringLiteral) {
|
|
243
|
+
const text = child2.getText(source);
|
|
244
|
+
const importPath = text.replace(/[\"\']/g, "");
|
|
245
|
+
const isRelativeImport = importPath.startsWith(".") || importPath.startsWith("/");
|
|
246
|
+
if (!isRelativeImport) return;
|
|
247
|
+
output.push({
|
|
248
|
+
old: importPath,
|
|
249
|
+
new: path2.join(path2.dirname(pathName), importPath)
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
return output;
|
|
254
|
+
}
|
|
255
|
+
function getXpineOnLoadFunction(pathName, source, onLoadFileResult) {
|
|
256
|
+
const value = {
|
|
257
|
+
imports: "",
|
|
258
|
+
fn: ""
|
|
259
|
+
};
|
|
260
|
+
source.forEachChild((child) => {
|
|
261
|
+
if (child.kind == ts.SyntaxKind.ImportDeclaration) {
|
|
262
|
+
let importText = child.getText(source);
|
|
263
|
+
const importOutput = getImportsToAbsolutePaths(child, source, pathName);
|
|
264
|
+
for (const importItem of importOutput) {
|
|
265
|
+
importText = importText.replace(importItem.old, importItem.new);
|
|
266
|
+
}
|
|
267
|
+
value.imports = importText + "\n" + value.imports;
|
|
268
|
+
}
|
|
269
|
+
if ([ts.SyntaxKind.FirstStatement, ts.SyntaxKind.FunctionDeclaration].includes(child.kind)) {
|
|
270
|
+
let text = child.getText(source);
|
|
271
|
+
if (text.includes("xpineOnLoad")) {
|
|
272
|
+
const body = child?.body?.getText(source) || "";
|
|
273
|
+
value.fn = value.fn + "\n" + body ? `(function() ${body})();` : "";
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
return value;
|
|
278
|
+
}
|
|
279
|
+
async function triggerXPineOnLoad(noCache = false) {
|
|
280
|
+
context.clear();
|
|
281
|
+
const xpineOnLoad = (await import(path2.join(config.distDir, `./__xpineOnLoad.js${noCache ? `?cache=${Date.now()}` : ""}`)))?.default;
|
|
282
|
+
if (xpineOnLoad) await xpineOnLoad();
|
|
283
|
+
}
|
|
116
284
|
|
|
117
285
|
// src/scripts/build.ts
|
|
118
286
|
import { globSync } from "glob";
|
|
119
287
|
import postcss from "postcss";
|
|
120
288
|
import tailwindPostcss from "@tailwindcss/postcss";
|
|
121
289
|
|
|
122
|
-
// src/util/
|
|
123
|
-
import path2 from "path";
|
|
124
|
-
|
|
125
|
-
// src/util/require.ts
|
|
126
|
-
import { createRequire } from "module";
|
|
127
|
-
var require_default = createRequire(import.meta.url);
|
|
290
|
+
// src/util/paths.ts
|
|
128
291
|
function getXPineDistDir() {
|
|
129
292
|
const dir = import.meta.dirname;
|
|
130
293
|
const splitDir = dir.split("/xpine/dist");
|
|
@@ -135,68 +298,6 @@ function getXPineDistDir() {
|
|
|
135
298
|
return splitDir[0] + "/xpine/dist";
|
|
136
299
|
}
|
|
137
300
|
|
|
138
|
-
// src/util/get-config.ts
|
|
139
|
-
var rootDir = process.cwd();
|
|
140
|
-
function fromRoot(pathName) {
|
|
141
|
-
if (!pathName) return rootDir;
|
|
142
|
-
return path2.join(rootDir, pathName);
|
|
143
|
-
}
|
|
144
|
-
var userConfig = require_default(path2.join(process.cwd(), "./xpine.config.mjs")).default;
|
|
145
|
-
var configDefaults = {
|
|
146
|
-
rootDir: fromRoot(),
|
|
147
|
-
srcDir: fromRoot("./src"),
|
|
148
|
-
distDir: fromRoot("./dist"),
|
|
149
|
-
packageJsonPath: fromRoot("package.json"),
|
|
150
|
-
// We need to use getters here in the event someone wants to change folders, such as the dist folder
|
|
151
|
-
get distPublicDir() {
|
|
152
|
-
return path2.join(this.distDir, "./public");
|
|
153
|
-
},
|
|
154
|
-
get distPublicScriptsDir() {
|
|
155
|
-
return path2.join(this.distPublicDir, "./scripts");
|
|
156
|
-
},
|
|
157
|
-
get distTempFolder() {
|
|
158
|
-
return path2.join(this.distDir, "./temp");
|
|
159
|
-
},
|
|
160
|
-
get clientJSBundlePath() {
|
|
161
|
-
return path2.join(this.distPublicScriptsDir, "./app.js");
|
|
162
|
-
},
|
|
163
|
-
get alpineDataPath() {
|
|
164
|
-
return path2.join(this.distTempFolder, "./alpine-data.ts");
|
|
165
|
-
},
|
|
166
|
-
get serverDistDir() {
|
|
167
|
-
return path2.join(this.distDir, "./server");
|
|
168
|
-
},
|
|
169
|
-
get serverDistAppPath() {
|
|
170
|
-
return path2.join(this.serverDistDir, "./app.js");
|
|
171
|
-
},
|
|
172
|
-
// Important dirs/paths
|
|
173
|
-
get pagesDir() {
|
|
174
|
-
return path2.join(this.srcDir, "./pages");
|
|
175
|
-
},
|
|
176
|
-
get distPagesDir() {
|
|
177
|
-
return path2.join(this.distDir, "./pages");
|
|
178
|
-
},
|
|
179
|
-
get publicDir() {
|
|
180
|
-
return path2.join(this.srcDir, "./public");
|
|
181
|
-
},
|
|
182
|
-
get serverDir() {
|
|
183
|
-
return path2.join(this.srcDir, "./server");
|
|
184
|
-
},
|
|
185
|
-
get runDir() {
|
|
186
|
-
return path2.join(this.serverDir, "./run");
|
|
187
|
-
},
|
|
188
|
-
get serverAppPath() {
|
|
189
|
-
return path2.join(this.serverDir, "./app.ts");
|
|
190
|
-
},
|
|
191
|
-
get globalCSSFile() {
|
|
192
|
-
return path2.join(this.publicDir, "./styles/global.css");
|
|
193
|
-
}
|
|
194
|
-
};
|
|
195
|
-
var config = {
|
|
196
|
-
...configDefaults,
|
|
197
|
-
...userConfig
|
|
198
|
-
};
|
|
199
|
-
|
|
200
301
|
// src/util/postcss/remove-layers.ts
|
|
201
302
|
var plugin = (opts = {}) => {
|
|
202
303
|
return {
|
|
@@ -270,13 +371,16 @@ function transformTSXFiles(componentData, pageConfigFiles) {
|
|
|
270
371
|
ts2.ScriptTarget.Latest
|
|
271
372
|
);
|
|
272
373
|
const cleanedContent = removeClientScriptInTSXFile(args.path, source);
|
|
273
|
-
const htmlImportStart =
|
|
274
|
-
|
|
374
|
+
const htmlImportStart = [
|
|
375
|
+
"import { html } from 'xpine';"
|
|
376
|
+
];
|
|
377
|
+
const newContent = `${htmlImportStart.join("\n")}${cleanedContent.content}`;
|
|
275
378
|
componentData.push({
|
|
276
379
|
...args,
|
|
277
380
|
contents: `${htmlImportStart}${cleanedContent.fullContent}`,
|
|
278
381
|
clientContent: cleanedContent.clientContent,
|
|
279
|
-
configFiles: isAConfigFile(args?.path) ? null : getConfigFiles(args.path, pageConfigFiles)
|
|
382
|
+
configFiles: isAConfigFile(args?.path) ? null : getConfigFiles(args.path, pageConfigFiles),
|
|
383
|
+
source
|
|
280
384
|
});
|
|
281
385
|
return {
|
|
282
386
|
contents: newContent,
|
|
@@ -346,7 +450,10 @@ var extensions = [".ts", ".tsx"];
|
|
|
346
450
|
var packageJson = JSON.parse(fs5.readFileSync(config.packageJsonPath, "utf-8"));
|
|
347
451
|
var allPackages = Object.keys(packageJson.devDependencies).concat(Object.keys(packageJson.dependencies));
|
|
348
452
|
var xpineDistDir = getXPineDistDir();
|
|
349
|
-
async function buildApp(
|
|
453
|
+
async function buildApp(args) {
|
|
454
|
+
const isDev = args?.isDev || false;
|
|
455
|
+
const removePreviousBuild = args?.removePreviousBuild || false;
|
|
456
|
+
const disableTailwind = args?.disableTailwind || false;
|
|
350
457
|
try {
|
|
351
458
|
if (removePreviousBuild) fs5.removeSync(config.distDir);
|
|
352
459
|
const srcDirFiles = globSync(config.srcDir + "/**/*.{js,ts,tsx,jsx}");
|
|
@@ -354,9 +461,12 @@ async function buildApp(isDev = false, removePreviousBuild = false) {
|
|
|
354
461
|
const alpineDataFile = await buildAlpineDataFile(componentData, dataFiles);
|
|
355
462
|
await buildClientSideFiles([alpineDataFile], isDev);
|
|
356
463
|
fs5.removeSync(config.distTempFolder);
|
|
357
|
-
await buildCSS();
|
|
464
|
+
await buildCSS(disableTailwind);
|
|
358
465
|
await buildPublicFolderSymlinks();
|
|
466
|
+
await buildOnLoadFile(componentData, isDev);
|
|
467
|
+
if (!isDev) await triggerXPineOnLoad();
|
|
359
468
|
if (!isDev) await buildFilesWithConfigs(componentData);
|
|
469
|
+
if (!isDev) context.clear();
|
|
360
470
|
} catch (err) {
|
|
361
471
|
console.error("Build failed");
|
|
362
472
|
console.error(err);
|
|
@@ -450,12 +560,7 @@ async function buildAlpineDataFile(componentData, dataFiles) {
|
|
|
450
560
|
};
|
|
451
561
|
const componentsAndDataFiles = componentData.concat(dataFiles);
|
|
452
562
|
for (const component of componentsAndDataFiles) {
|
|
453
|
-
const
|
|
454
|
-
component.path,
|
|
455
|
-
component.contents,
|
|
456
|
-
ts3.ScriptTarget.Latest
|
|
457
|
-
);
|
|
458
|
-
const dataFunctionResult = findDataAttributesAndFunctions(sourceFile, sourceFile);
|
|
563
|
+
const dataFunctionResult = findDataAttributesAndFunctions(component.source, component.source);
|
|
459
564
|
dataFunctionResults.foundDataAttributes.push(...dataFunctionResult.foundDataAttributes);
|
|
460
565
|
const foundFunctionsWithPath = dataFunctionResult.foundFunctions.map((item) => {
|
|
461
566
|
return {
|
|
@@ -479,11 +584,11 @@ async function buildAlpineDataFile(componentData, dataFiles) {
|
|
|
479
584
|
fs5.writeFileSync(config.alpineDataPath, result);
|
|
480
585
|
return config.alpineDataPath;
|
|
481
586
|
}
|
|
482
|
-
async function buildCSS() {
|
|
587
|
+
async function buildCSS(disableTailwind) {
|
|
483
588
|
const cssFiles = globSync(config.srcDir + "/**/*.css");
|
|
484
589
|
for (const file of cssFiles) {
|
|
485
590
|
const fileContents = fs5.readFileSync(file, "utf-8");
|
|
486
|
-
const result = await postcss([tailwindPostcss(), remove_layers_default()]).process(fileContents, { from: file });
|
|
591
|
+
const result = disableTailwind ? fileContents : await postcss([tailwindPostcss(), remove_layers_default()]).process(fileContents, { from: file });
|
|
487
592
|
const newPath = file.replace(config.srcDir, config.distDir);
|
|
488
593
|
fs5.ensureFileSync(newPath);
|
|
489
594
|
fs5.writeFileSync(newPath, result.css);
|
|
@@ -545,6 +650,7 @@ async function buildStaticFiles(config2, component, componentImport, builtCompon
|
|
|
545
650
|
}
|
|
546
651
|
const componentDynamicPaths = getComponentDynamicPaths(componentFileName);
|
|
547
652
|
const componentFn = componentImport.default;
|
|
653
|
+
if (componentImport?.onInit) await componentImport.onInit();
|
|
548
654
|
const outputPath = componentDynamicPaths?.length ? componentDynamicPaths.reduce((total, current) => {
|
|
549
655
|
return total.replace(`/[${current}]`, "");
|
|
550
656
|
}, path5.dirname(builtComponentPath)) : path5.dirname(builtComponentPath);
|
|
@@ -594,6 +700,53 @@ function getComponentDynamicPaths(componentPath) {
|
|
|
594
700
|
}
|
|
595
701
|
return output;
|
|
596
702
|
}
|
|
703
|
+
async function buildOnLoadFile(componentData, isDev) {
|
|
704
|
+
const onLoadFiles = [];
|
|
705
|
+
const onLoadFileResult = {
|
|
706
|
+
imports: "",
|
|
707
|
+
fn: ""
|
|
708
|
+
};
|
|
709
|
+
for (const component of componentData) {
|
|
710
|
+
if (component.contents.includes("xpineOnLoad")) {
|
|
711
|
+
onLoadFiles.push({
|
|
712
|
+
path: sourcePathToDistPath(component.path),
|
|
713
|
+
source: component.source
|
|
714
|
+
});
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
onLoadFiles.sort((a, b) => {
|
|
718
|
+
return a.path.localeCompare(b.path);
|
|
719
|
+
});
|
|
720
|
+
for (const file of onLoadFiles) {
|
|
721
|
+
const result = getXpineOnLoadFunction(file.path, file.source, onLoadFileResult);
|
|
722
|
+
onLoadFileResult.fn += result.fn;
|
|
723
|
+
onLoadFileResult.imports += result.imports;
|
|
724
|
+
}
|
|
725
|
+
const output = `
|
|
726
|
+
${onLoadFileResult.imports}
|
|
727
|
+
import { context } from "xpine";
|
|
728
|
+
export default async function triggerOnLoad() {
|
|
729
|
+
${onLoadFileResult.fn}
|
|
730
|
+
context.runArrayQueue();
|
|
731
|
+
}
|
|
732
|
+
`;
|
|
733
|
+
const onLoadFilePath = path5.join(config.distDir, "./__xpineOnLoad.ts");
|
|
734
|
+
fs5.writeFileSync(onLoadFilePath, output);
|
|
735
|
+
await build({
|
|
736
|
+
entryPoints: [onLoadFilePath],
|
|
737
|
+
format: "esm",
|
|
738
|
+
platform: "node",
|
|
739
|
+
outdir: config.distDir,
|
|
740
|
+
bundle: true,
|
|
741
|
+
sourcemap: isDev ? "inline" : false,
|
|
742
|
+
external: allPackages,
|
|
743
|
+
jsx: "transform",
|
|
744
|
+
minify: !isDev,
|
|
745
|
+
plugins: [
|
|
746
|
+
addDotJS(allPackages, extensions, isDev)
|
|
747
|
+
]
|
|
748
|
+
});
|
|
749
|
+
}
|
|
597
750
|
|
|
598
751
|
// src/runDevServer.ts
|
|
599
752
|
import path7 from "path";
|
|
@@ -634,7 +787,7 @@ await setupEnv();
|
|
|
634
787
|
async function runDevServer() {
|
|
635
788
|
process.env.NODE_ENV = "development";
|
|
636
789
|
const rebuildEmitter = createRebuildEmitter();
|
|
637
|
-
await buildApp(true);
|
|
790
|
+
await buildApp({ isDev: true });
|
|
638
791
|
const startServer = (await import(config.serverDistAppPath + `?cache=${Date.now()}`)).default;
|
|
639
792
|
let appServer = await startServer();
|
|
640
793
|
const watcher = chokidar.watch(config.srcDir, {
|
|
@@ -649,14 +802,14 @@ async function runDevServer() {
|
|
|
649
802
|
rebuildEmitter.emit("rebuild-server");
|
|
650
803
|
return;
|
|
651
804
|
}
|
|
652
|
-
await buildApp(true);
|
|
805
|
+
await buildApp({ isDev: true });
|
|
653
806
|
refreshEmitter.emit("refresh");
|
|
654
807
|
});
|
|
655
808
|
rebuildEmitter.on("done", async () => {
|
|
656
809
|
await rebuildServer();
|
|
657
810
|
});
|
|
658
811
|
async function rebuildServer() {
|
|
659
|
-
await buildApp(true);
|
|
812
|
+
await buildApp({ isDev: true });
|
|
660
813
|
const startServer2 = (await import(config.serverDistAppPath + `?cache=${Date.now()}`)).default;
|
|
661
814
|
appServer = await startServer2();
|
|
662
815
|
}
|
|
@@ -756,12 +909,19 @@ function getTokenFromRequest(req) {
|
|
|
756
909
|
import requestIP from "request-ip";
|
|
757
910
|
import fs6 from "fs-extra";
|
|
758
911
|
import path8 from "path";
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
912
|
+
import EventEmitter2 from "events";
|
|
913
|
+
var OnInitEmitter = class extends EventEmitter2 {
|
|
914
|
+
};
|
|
915
|
+
var onInitEmitter = new OnInitEmitter();
|
|
916
|
+
onInitEmitter.on("triggerOnInit", async (paths) => {
|
|
917
|
+
for (const routePath of paths) {
|
|
918
|
+
const pathImport = await import(routePath.path + `?cache=${Date.now()}`);
|
|
919
|
+
if (pathImport?.config?.onInit) await pathImport.config.onInit();
|
|
920
|
+
}
|
|
921
|
+
});
|
|
922
|
+
function getAllBuiltRoutes() {
|
|
763
923
|
const routes = globSync2(config.pagesDir + "/**/*.{tsx,ts}");
|
|
764
|
-
|
|
924
|
+
return routes.map((route) => {
|
|
765
925
|
const routeFormatted = route.split(config.pagesDir).pop().replace(".tsx", "").replace(".js", "").replace(".ts", "");
|
|
766
926
|
if (routeFormatted.endsWith("+config")) return;
|
|
767
927
|
const routeFormattedWithIndex = routeFormatted.replace(/\/index$/g, "");
|
|
@@ -771,8 +931,15 @@ async function createRouter() {
|
|
|
771
931
|
originalRoute: route
|
|
772
932
|
};
|
|
773
933
|
}).filter(Boolean);
|
|
934
|
+
}
|
|
935
|
+
async function createRouter() {
|
|
936
|
+
const isDev = process.env.NODE_ENV === "development";
|
|
937
|
+
const methods = ["get", "post", "put", "patch", "delete"];
|
|
938
|
+
const router = express2.Router();
|
|
939
|
+
const routeMap = getAllBuiltRoutes();
|
|
774
940
|
const routeResults = [];
|
|
775
941
|
const configFiles = globSync2(config.pagesDir + "/**/+config.{tsx,ts}");
|
|
942
|
+
await triggerXPineOnLoad();
|
|
776
943
|
for (const route of routeMap) {
|
|
777
944
|
const isJSX = route.originalRoute.endsWith(".tsx") || route.originalRoute.endsWith(".jsx");
|
|
778
945
|
const slugRoute = route.route.replace(/[ ]/g, "");
|
|
@@ -786,15 +953,21 @@ async function createRouter() {
|
|
|
786
953
|
formattedRouteItem = formattedRouteItem.replace(match[0], ":" + match[2]);
|
|
787
954
|
}
|
|
788
955
|
}
|
|
789
|
-
const componentImport =
|
|
790
|
-
const componentFn = componentImport?.default;
|
|
956
|
+
const componentImport = await import(route.path);
|
|
957
|
+
const componentFn = isDev ? null : componentImport?.default;
|
|
958
|
+
if (componentImport?.config?.onInit) {
|
|
959
|
+
await componentImport.config?.onInit();
|
|
960
|
+
}
|
|
961
|
+
let config2 = {};
|
|
791
962
|
const configFilePaths = getConfigFiles(route.originalRoute, configFiles);
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
963
|
+
if (!isDev) {
|
|
964
|
+
config2 = configFilePaths && await getCompleteConfig(configFilePaths, Date.now());
|
|
965
|
+
if (componentImport?.config) {
|
|
966
|
+
config2 = {
|
|
967
|
+
...config2,
|
|
968
|
+
...componentImport.config
|
|
969
|
+
};
|
|
970
|
+
}
|
|
798
971
|
}
|
|
799
972
|
routeResults.push({
|
|
800
973
|
formattedRouteItem,
|
|
@@ -819,8 +992,10 @@ async function createRouter() {
|
|
|
819
992
|
}
|
|
820
993
|
return;
|
|
821
994
|
}
|
|
995
|
+
await triggerXPineOnLoad(true);
|
|
822
996
|
const componentImportDev = await import(route.path + `?cache=${Date.now()}`);
|
|
823
997
|
const componentFnDev = componentImportDev.default;
|
|
998
|
+
onInitEmitter.emit("triggerOnInit", getAllBuiltRoutes());
|
|
824
999
|
if (isJSX) {
|
|
825
1000
|
let config3 = configFilePaths && await getCompleteConfig(configFilePaths, Date.now());
|
|
826
1001
|
if (componentImportDev?.config) {
|
|
@@ -830,8 +1005,9 @@ async function createRouter() {
|
|
|
830
1005
|
};
|
|
831
1006
|
}
|
|
832
1007
|
const data = config3?.data ? await config3.data(req) : null;
|
|
833
|
-
const originalResult = await componentFnDev({ req, res, data });
|
|
1008
|
+
const originalResult = await componentFnDev({ req, res, data, config: config3 });
|
|
834
1009
|
const output = config3?.wrapper ? await config3.wrapper({ req, children: originalResult, config: config3, data }) : originalResult;
|
|
1010
|
+
context.clear();
|
|
835
1011
|
res.send(doctypeHTML + output);
|
|
836
1012
|
} else {
|
|
837
1013
|
await componentFnDev(req, res);
|
|
@@ -922,12 +1098,16 @@ function JSXRuntime() {
|
|
|
922
1098
|
}
|
|
923
1099
|
export {
|
|
924
1100
|
JSXRuntime,
|
|
1101
|
+
addToContextArray,
|
|
925
1102
|
buildApp,
|
|
926
1103
|
buildCSS,
|
|
927
1104
|
buildFilesWithConfigs,
|
|
1105
|
+
buildOnLoadFile,
|
|
928
1106
|
buildPublicFolderSymlinks,
|
|
929
1107
|
buildStaticFiles,
|
|
930
1108
|
config,
|
|
1109
|
+
context,
|
|
1110
|
+
createContext,
|
|
931
1111
|
createRouter,
|
|
932
1112
|
createXPineRouter,
|
|
933
1113
|
fromRoot,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transformTSXFiles.d.ts","sourceRoot":"","sources":["../../../../src/build/esbuild/transformTSXFiles.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C,MAAM,CAAC,OAAO,UAAU,iBAAiB,CAAC,aAAa,EAAE,aAAa,EAAE,EAAE,eAAe,EAAE,MAAM,EAAE;;;
|
|
1
|
+
{"version":3,"file":"transformTSXFiles.d.ts","sourceRoot":"","sources":["../../../../src/build/esbuild/transformTSXFiles.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C,MAAM,CAAC,OAAO,UAAU,iBAAiB,CAAC,aAAa,EAAE,aAAa,EAAE,EAAE,eAAe,EAAE,MAAM,EAAE;;;EA8BlG"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import ts from 'typescript';
|
|
2
|
+
import { OnLoadFileResult } from '../scripts/build';
|
|
2
3
|
type ImportDeclaration = {
|
|
3
4
|
node: ts.Node;
|
|
4
5
|
importPath: string;
|
|
@@ -25,6 +26,12 @@ export declare function removeClientScriptInTSXFile(pathName: string, source: ts
|
|
|
25
26
|
clientDataStart: number;
|
|
26
27
|
};
|
|
27
28
|
export declare function createStaticFile(pathName: string, source: ts.SourceFile): void;
|
|
29
|
+
export declare function getImportsToAbsolutePaths(child: ts.Node, source: ts.SourceFile, pathName: string): any[];
|
|
28
30
|
export declare function printRecursiveFrom(node: ts.Node, indentLevel: number, sourceFile: ts.SourceFile): void;
|
|
31
|
+
export declare function getXpineOnLoadFunction(pathName: string, source: ts.SourceFile, onLoadFileResult: OnLoadFileResult): {
|
|
32
|
+
imports: string;
|
|
33
|
+
fn: string;
|
|
34
|
+
};
|
|
35
|
+
export declare function triggerXPineOnLoad(noCache?: boolean): Promise<void>;
|
|
29
36
|
export {};
|
|
30
37
|
//# sourceMappingURL=typescript-builder.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"typescript-builder.d.ts","sourceRoot":"","sources":["../../../src/build/typescript-builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"typescript-builder.d.ts","sourceRoot":"","sources":["../../../src/build/typescript-builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAG5B,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAIpD,KAAK,iBAAiB,GAAG;IACvB,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB,CAAA;AAGD,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,CAAC,UAAU,EAAE,kBAAkB,GAAE,iBAAiB,EAAO,uBAiB/H;AAED,wBAAgB,yBAAyB,CAAC,cAAc,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,UAO3H;AAED,KAAK,mBAAmB,GAAG;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,EAAE,OAAO,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;CACpB,CAAA;AAED,wBAAgB,8BAA8B,CAC5C,IAAI,EAAE,EAAE,CAAC,IAAI,EACb,UAAU,EAAE,EAAE,CAAC,UAAU,EACzB,mBAAmB,GAAE,MAAM,EAAO,EAClC,cAAc,GAAE,mBAAmB,EAAO;;;EA0B3C;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,CAAC,UAAU,GAAG,MAAM,EAAE,CAMxF;AAED,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,CAAC,UAAU,GAAG,mBAAmB,CAkBzG;AAGD,wBAAgB,8BAA8B,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,aAAa,EAAE,MAAM,QAO1F;AAED,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,UAAU;;;;;;EAmClF;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,UAAU,QAUvE;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,UAAU,EAAE,QAAQ,EAAE,MAAM,SAgBhG;AAED,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,CAAC,UAAU,QAU9D;AAED,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,UAAU,EAAE,gBAAgB,EAAE,gBAAgB;;;EA0BjH;AAED,wBAAsB,kBAAkB,CAAC,OAAO,GAAE,OAAe,iBAMhE"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type SetContext<Type> = (currentContext: Type) => Type;
|
|
2
|
+
export type State<StateProps> = {
|
|
3
|
+
get: (id: string) => StateProps;
|
|
4
|
+
set: (id: string, callback: SetContext<StateProps>, defaultValue?: any) => void;
|
|
5
|
+
clear: () => void;
|
|
6
|
+
getAll: () => any;
|
|
7
|
+
addToArray: (id: string, value: any, position?: number) => void;
|
|
8
|
+
getArrayQueue: () => any;
|
|
9
|
+
runArrayQueue: () => void;
|
|
10
|
+
};
|
|
11
|
+
type ContextType<Type> = {
|
|
12
|
+
[key: string]: Type;
|
|
13
|
+
};
|
|
14
|
+
export declare function createContext(value: ContextType<any>): State<any>;
|
|
15
|
+
export declare const context: State<any>;
|
|
16
|
+
export declare function addToContextArray(newValue: any, position?: number): (currentValue: any) => any;
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/context.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,CAAC,IAAI,IAAI,CAAC,cAAc,EAAE,IAAI,KAAK,IAAI,CAAC;AAE9D,MAAM,MAAM,KAAK,CAAC,UAAU,IAAI;IAC9B,GAAG,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,UAAU,CAAC;IAChC,GAAG,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,CAAC,UAAU,CAAC,EAAE,YAAY,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC;IAChF,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,MAAM,EAAE,MAAM,GAAG,CAAC;IAClB,UAAU,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAChE,aAAa,EAAE,MAAM,GAAG,CAAC;IACzB,aAAa,EAAE,MAAM,IAAI,CAAC;CAC3B,CAAA;AAED,KAAK,WAAW,CAAC,IAAI,IAAI;IACvB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB,CAAA;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CA8CjE;AAED,eAAO,MAAM,OAAO,YAAoB,CAAC;AAEzC,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,GAAG,EAAE,QAAQ,CAAC,EAAE,MAAM,kBACjC,GAAG,SAYnC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"express.d.ts","sourceRoot":"","sources":["../../src/express.ts"],"names":[],"mappings":"AAAA,OAAgB,EAAgB,OAAO,EAAqB,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"express.d.ts","sourceRoot":"","sources":["../../src/express.ts"],"names":[],"mappings":"AAAA,OAAgB,EAAgB,OAAO,EAAqB,MAAM,SAAS,CAAC;AAyC5E,wBAAsB,YAAY;;;GA8GjC;AAiBD,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,GAAG,EAAE,gBAAgB,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,iBA6B1F;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,GAAG,MAAM,GAAG,KAAK,CAWnG"}
|
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
import { ConfigFile, ComponentData } from '../../types';
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
type BuildAppArgs = {
|
|
3
|
+
isDev?: boolean;
|
|
4
|
+
removePreviousBuild?: boolean;
|
|
5
|
+
disableTailwind?: boolean;
|
|
6
|
+
};
|
|
7
|
+
export declare function buildApp(args: BuildAppArgs): Promise<void>;
|
|
8
|
+
export declare function buildCSS(disableTailwind?: boolean): Promise<void>;
|
|
4
9
|
export declare function buildPublicFolderSymlinks(): Promise<void>;
|
|
5
10
|
export declare function logSize(pathName: string, type: 'app' | 'client' | 'css', validExtensions?: string[]): Promise<void>;
|
|
6
11
|
export declare function buildFilesWithConfigs(componentData: ComponentData[]): Promise<void>;
|
|
7
12
|
export declare function buildStaticFiles(config: ConfigFile, component: ComponentData, componentImport: any, builtComponentPath: string): Promise<void>;
|
|
8
13
|
export declare function getComponentDynamicPaths(componentPath: string): string[];
|
|
14
|
+
export type OnLoadFileResult = {
|
|
15
|
+
imports: string;
|
|
16
|
+
fn: string;
|
|
17
|
+
};
|
|
18
|
+
export declare function buildOnLoadFile(componentData: ComponentData[], isDev?: boolean): Promise<void>;
|
|
19
|
+
export {};
|
|
9
20
|
//# sourceMappingURL=build.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../../src/scripts/build.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../../src/scripts/build.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAE,UAAU,EAA2B,aAAa,EAAE,MAAM,aAAa,CAAC;AAUjF,KAAK,YAAY,GAAG;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,CAAA;AAED,wBAAsB,QAAQ,CAAC,IAAI,EAAE,YAAY,iBAsBhD;AAsID,wBAAsB,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,iBAavD;AAGD,wBAAsB,yBAAyB,kBAgB9C;AAED,wBAAsB,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,GAAG,QAAQ,GAAG,KAAK,EAAE,eAAe,WAAkB,iBAahH;AAED,wBAAsB,qBAAqB,CAAC,aAAa,EAAE,aAAa,EAAE,iBAezE;AAED,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,eAAe,EAAE,GAAG,EAAE,kBAAkB,EAAE,MAAM,iBAgEpI;AAED,wBAAgB,wBAAwB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,EAAE,CAQxE;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;CACZ,CAAA;AAGD,wBAAsB,eAAe,CAAC,aAAa,EAAE,aAAa,EAAE,EAAE,KAAK,CAAC,EAAE,OAAO,iBAoDpF"}
|