xpine 0.0.19 → 0.0.21
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.js +236 -111
- package/dist/src/scripts/xpine-build.js +200 -100
- package/dist/src/scripts/xpine-dev.js +207 -107
- package/package.json +1 -2
package/dist/index.js
CHANGED
|
@@ -6,11 +6,10 @@ import EventEmitter from "events";
|
|
|
6
6
|
import chokidar from "chokidar";
|
|
7
7
|
|
|
8
8
|
// src/scripts/build.ts
|
|
9
|
-
import
|
|
10
|
-
import
|
|
9
|
+
import path5 from "path";
|
|
10
|
+
import fs5 from "fs-extra";
|
|
11
11
|
import { build } from "esbuild";
|
|
12
|
-
import
|
|
13
|
-
import ts2 from "typescript";
|
|
12
|
+
import ts3 from "typescript";
|
|
14
13
|
|
|
15
14
|
// src/build/typescript-builder.ts
|
|
16
15
|
import ts from "typescript";
|
|
@@ -114,17 +113,6 @@ function removeClientScriptInTSXFile(pathName, source) {
|
|
|
114
113
|
clientDataStart
|
|
115
114
|
};
|
|
116
115
|
}
|
|
117
|
-
function createStaticFile(pathName, source) {
|
|
118
|
-
source.forEachChild((child) => {
|
|
119
|
-
if (child.kind === ts.SyntaxKind.ExpressionStatement) {
|
|
120
|
-
const text = child.getText(source);
|
|
121
|
-
const cleanedText = text.replace(/["';]/g, "");
|
|
122
|
-
if (cleanedText === "xpine-static") {
|
|
123
|
-
console.log("make this file static", pathName);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
});
|
|
127
|
-
}
|
|
128
116
|
|
|
129
117
|
// src/scripts/build.ts
|
|
130
118
|
import { globSync } from "glob";
|
|
@@ -181,6 +169,9 @@ var configDefaults = {
|
|
|
181
169
|
get pagesDir() {
|
|
182
170
|
return path2.join(this.srcDir, "./pages");
|
|
183
171
|
},
|
|
172
|
+
get distPagesDir() {
|
|
173
|
+
return path2.join(this.distDir, "./pages");
|
|
174
|
+
},
|
|
184
175
|
get publicDir() {
|
|
185
176
|
return path2.join(this.srcDir, "./public");
|
|
186
177
|
},
|
|
@@ -216,11 +207,117 @@ var plugin = (opts = {}) => {
|
|
|
216
207
|
plugin.postcss = true;
|
|
217
208
|
var remove_layers_default = plugin;
|
|
218
209
|
|
|
210
|
+
// src/build/esbuild/transformTSXFiles.ts
|
|
211
|
+
import fs2 from "fs-extra";
|
|
212
|
+
import ts2 from "typescript";
|
|
213
|
+
import path3 from "path";
|
|
214
|
+
|
|
215
|
+
// src/util/regex.ts
|
|
216
|
+
var regex_default = {
|
|
217
|
+
dotTsx: /.tsx/,
|
|
218
|
+
hasLetters: /[A-Za-z0-9]/g,
|
|
219
|
+
configFile: /\+config\.[tj]s/g,
|
|
220
|
+
dynamicRoutes: /(\[)(.*?)(\])/g,
|
|
221
|
+
isDynamicRoute: /\[(.*)\]/g,
|
|
222
|
+
endsWithTSX: /\.tsx$/,
|
|
223
|
+
endsWithJSX: /\.jsx$/
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
// src/build/esbuild/transformTSXFiles.ts
|
|
227
|
+
function transformTSXFiles(componentData, pageConfigFiles) {
|
|
228
|
+
return {
|
|
229
|
+
name: "transform-tsx-files",
|
|
230
|
+
setup(build2) {
|
|
231
|
+
build2.onLoad({ filter: regex_default.dotTsx }, (args) => {
|
|
232
|
+
const configFile = getConfigFile(args.path, pageConfigFiles);
|
|
233
|
+
const content = fs2.readFileSync(args.path, "utf-8");
|
|
234
|
+
const source = ts2.createSourceFile(
|
|
235
|
+
args.path,
|
|
236
|
+
content,
|
|
237
|
+
ts2.ScriptTarget.Latest
|
|
238
|
+
);
|
|
239
|
+
const cleanedContent = removeClientScriptInTSXFile(args.path, source);
|
|
240
|
+
const htmlImportStart = "import { html } from 'xpine';\n";
|
|
241
|
+
const newContent = `${htmlImportStart}${cleanedContent.content}`;
|
|
242
|
+
componentData.push({
|
|
243
|
+
...args,
|
|
244
|
+
contents: `${htmlImportStart}${cleanedContent.fullContent}`,
|
|
245
|
+
clientContent: cleanedContent.clientContent,
|
|
246
|
+
configFile
|
|
247
|
+
});
|
|
248
|
+
return {
|
|
249
|
+
contents: newContent,
|
|
250
|
+
loader: "tsx"
|
|
251
|
+
};
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
function getConfigFile(pathName, pageConfigFiles) {
|
|
257
|
+
const configs = [];
|
|
258
|
+
for (const configFile of pageConfigFiles) {
|
|
259
|
+
const result = path3.relative(pathName, configFile)?.replace(regex_default.configFile, "");
|
|
260
|
+
const hasLetters = result.match(regex_default.hasLetters);
|
|
261
|
+
if (!hasLetters) configs.push(configFile);
|
|
262
|
+
}
|
|
263
|
+
const configToUse = configs.sort((a, b) => b.length - a.length)?.[0];
|
|
264
|
+
return configToUse;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// src/build/esbuild/addDotJS.ts
|
|
268
|
+
import fs3 from "fs-extra";
|
|
269
|
+
import path4 from "path";
|
|
270
|
+
import builtinModules from "builtin-modules";
|
|
271
|
+
function addDotJS(allPackages2, extensions2, isDev) {
|
|
272
|
+
const allPackagesIncludingNode = allPackages2.concat(builtinModules);
|
|
273
|
+
return {
|
|
274
|
+
name: "add-dot-js",
|
|
275
|
+
setup(build2) {
|
|
276
|
+
build2.onResolve({ filter: /.*/ }, (args) => {
|
|
277
|
+
const hasAtSign = args.path.startsWith("@");
|
|
278
|
+
const isPackage = hasAtSign ? allPackagesIncludingNode.includes(args.path) : allPackagesIncludingNode.includes(args.path.split("/").shift());
|
|
279
|
+
if (args.importer && !isPackage) {
|
|
280
|
+
const calculatedDir = path4.join(args.resolveDir, args.path);
|
|
281
|
+
let existsAsFile = false;
|
|
282
|
+
for (const extension of extensions2) {
|
|
283
|
+
const asFile = calculatedDir + extension;
|
|
284
|
+
const exists = fs3.existsSync(asFile);
|
|
285
|
+
if (exists) existsAsFile = true;
|
|
286
|
+
}
|
|
287
|
+
let outputPath = args.path + (existsAsFile ? "" : "/index") + ".js";
|
|
288
|
+
outputPath = args.path.endsWith(".js") || args.path.endsWith(".mjs") ? args.path : outputPath;
|
|
289
|
+
return { path: outputPath + (isDev ? `?cache=${Date.now()}` : ""), external: true };
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// src/build/esbuild/getDataFiles.ts
|
|
297
|
+
import fs4 from "fs-extra";
|
|
298
|
+
function getDataFiles(dataFiles) {
|
|
299
|
+
return {
|
|
300
|
+
name: "get-data-files",
|
|
301
|
+
setup(build2) {
|
|
302
|
+
build2.onLoad({ filter: /\.data\.(js|mjs|ts)$/ }, (args) => {
|
|
303
|
+
const contents = fs4.readFileSync(args.path, "utf-8");
|
|
304
|
+
dataFiles.push({
|
|
305
|
+
...args,
|
|
306
|
+
contents
|
|
307
|
+
});
|
|
308
|
+
return {
|
|
309
|
+
contents,
|
|
310
|
+
loader: "ts"
|
|
311
|
+
};
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
|
|
219
317
|
// src/scripts/build.ts
|
|
220
318
|
var extensions = [".ts", ".tsx"];
|
|
221
|
-
var packageJson = JSON.parse(
|
|
319
|
+
var packageJson = JSON.parse(fs5.readFileSync(config.packageJsonPath, "utf-8"));
|
|
222
320
|
var allPackages = Object.keys(packageJson.devDependencies).concat(Object.keys(packageJson.dependencies));
|
|
223
|
-
var allPackagesIncludingNode = allPackages.concat(builtinModules);
|
|
224
321
|
var xpineDistDir = getXPineDistDir();
|
|
225
322
|
async function buildApp(isDev = false) {
|
|
226
323
|
try {
|
|
@@ -228,9 +325,10 @@ async function buildApp(isDev = false) {
|
|
|
228
325
|
const { componentData, dataFiles } = await buildAppFiles(srcDirFiles, isDev);
|
|
229
326
|
const alpineDataFile = await buildAlpineDataFile(componentData, dataFiles);
|
|
230
327
|
await buildClientSideFiles([alpineDataFile], isDev);
|
|
231
|
-
|
|
328
|
+
fs5.removeSync(config.distTempFolder);
|
|
232
329
|
await buildCSS();
|
|
233
330
|
await buildPublicFolderSymlinks();
|
|
331
|
+
if (!isDev) await buildStaticFiles(componentData);
|
|
234
332
|
} catch (err) {
|
|
235
333
|
console.error("Build failed");
|
|
236
334
|
console.error(err);
|
|
@@ -239,8 +337,12 @@ async function buildApp(isDev = false) {
|
|
|
239
337
|
async function buildAppFiles(files, isDev) {
|
|
240
338
|
const componentData = [];
|
|
241
339
|
const dataFiles = [];
|
|
340
|
+
const pageConfigFiles = files.filter((file) => {
|
|
341
|
+
const fileName = file.split("/").at(-1).split(".").shift();
|
|
342
|
+
return fileName === "+config";
|
|
343
|
+
});
|
|
242
344
|
const backendFiles = files.filter((file) => extensions.find((ext) => file.endsWith(ext))).filter((file) => !file.startsWith(config.publicDir));
|
|
243
|
-
|
|
345
|
+
fs5.ensureDirSync(config.distDir);
|
|
244
346
|
await build({
|
|
245
347
|
entryPoints: backendFiles,
|
|
246
348
|
format: "esm",
|
|
@@ -252,69 +354,9 @@ async function buildAppFiles(files, isDev) {
|
|
|
252
354
|
jsx: "transform",
|
|
253
355
|
minify: !isDev,
|
|
254
356
|
plugins: [
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
build2.onResolve({ filter: /.*/ }, (args) => {
|
|
259
|
-
const hasAtSign = args.path.startsWith("@");
|
|
260
|
-
const isPackage = hasAtSign ? allPackagesIncludingNode.includes(args.path) : allPackagesIncludingNode.includes(args.path.split("/").shift());
|
|
261
|
-
if (args.importer && !isPackage) {
|
|
262
|
-
const calculatedDir = path3.join(args.resolveDir, args.path);
|
|
263
|
-
let existsAsFile = false;
|
|
264
|
-
for (const extension of extensions) {
|
|
265
|
-
const asFile = calculatedDir + extension;
|
|
266
|
-
const exists = fs2.existsSync(asFile);
|
|
267
|
-
if (exists) existsAsFile = true;
|
|
268
|
-
}
|
|
269
|
-
let outputPath = args.path + (existsAsFile ? "" : "/index") + ".js";
|
|
270
|
-
outputPath = args.path.endsWith(".js") || args.path.endsWith(".mjs") ? args.path : outputPath;
|
|
271
|
-
return { path: outputPath + (isDev ? `?cache=${Date.now()}` : ""), external: true };
|
|
272
|
-
}
|
|
273
|
-
});
|
|
274
|
-
}
|
|
275
|
-
},
|
|
276
|
-
{
|
|
277
|
-
name: "insert-html-banner-and-remove-client-scripts",
|
|
278
|
-
setup(build2) {
|
|
279
|
-
build2.onLoad({ filter: /.tsx/ }, (args) => {
|
|
280
|
-
const content = fs2.readFileSync(args.path, "utf-8");
|
|
281
|
-
const source = ts2.createSourceFile(
|
|
282
|
-
args.path,
|
|
283
|
-
content,
|
|
284
|
-
ts2.ScriptTarget.Latest
|
|
285
|
-
);
|
|
286
|
-
const cleanedContent = removeClientScriptInTSXFile(args.path, source);
|
|
287
|
-
createStaticFile(args.path, source);
|
|
288
|
-
const htmlImportStart = "import { html } from 'xpine';\n";
|
|
289
|
-
const newContent = `${htmlImportStart}${cleanedContent.content}`;
|
|
290
|
-
componentData.push({
|
|
291
|
-
...args,
|
|
292
|
-
contents: `${htmlImportStart}${cleanedContent.fullContent}`,
|
|
293
|
-
clientContent: cleanedContent.clientContent
|
|
294
|
-
});
|
|
295
|
-
return {
|
|
296
|
-
contents: newContent,
|
|
297
|
-
loader: "tsx"
|
|
298
|
-
};
|
|
299
|
-
});
|
|
300
|
-
}
|
|
301
|
-
},
|
|
302
|
-
{
|
|
303
|
-
name: "get-data-files",
|
|
304
|
-
setup(build2) {
|
|
305
|
-
build2.onLoad({ filter: /\.data\.(js|mjs|ts)$/ }, (args) => {
|
|
306
|
-
const contents = fs2.readFileSync(args.path, "utf-8");
|
|
307
|
-
dataFiles.push({
|
|
308
|
-
...args,
|
|
309
|
-
contents
|
|
310
|
-
});
|
|
311
|
-
return {
|
|
312
|
-
contents,
|
|
313
|
-
loader: "ts"
|
|
314
|
-
};
|
|
315
|
-
});
|
|
316
|
-
}
|
|
317
|
-
}
|
|
357
|
+
addDotJS(allPackages, extensions, isDev),
|
|
358
|
+
transformTSXFiles(componentData, pageConfigFiles),
|
|
359
|
+
getDataFiles(dataFiles)
|
|
318
360
|
]
|
|
319
361
|
});
|
|
320
362
|
await logSize(config.distDir, "app");
|
|
@@ -324,8 +366,8 @@ async function buildAppFiles(files, isDev) {
|
|
|
324
366
|
};
|
|
325
367
|
}
|
|
326
368
|
async function buildClientSideFiles(alpineDataFiles = [], isDev) {
|
|
327
|
-
const tempFilePath =
|
|
328
|
-
|
|
369
|
+
const tempFilePath = path5.join(config.distTempFolder, "./app.ts");
|
|
370
|
+
fs5.ensureFileSync(tempFilePath);
|
|
329
371
|
const pagesScriptsGlob = config.publicDir + "/scripts/pages/**/*.{js,ts}";
|
|
330
372
|
const clientFiles = globSync(
|
|
331
373
|
config.publicDir + "/**/*.{js,ts}",
|
|
@@ -354,15 +396,15 @@ async function buildClientSideFiles(alpineDataFiles = [], isDev) {
|
|
|
354
396
|
await logSize(config.distPublicDir, "client");
|
|
355
397
|
}
|
|
356
398
|
function writeDevServerClientSideCode(tempFilePath) {
|
|
357
|
-
const devServerPath =
|
|
358
|
-
const content =
|
|
359
|
-
|
|
399
|
+
const devServerPath = path5.join(xpineDistDir, "./src/static/dev-server.js");
|
|
400
|
+
const content = fs5.readFileSync(devServerPath, "utf-8");
|
|
401
|
+
fs5.appendFileSync(tempFilePath, `
|
|
360
402
|
` + content);
|
|
361
403
|
}
|
|
362
404
|
function writeSpaClientSideCode(tempFilePath) {
|
|
363
|
-
const spaPath =
|
|
364
|
-
const content =
|
|
365
|
-
|
|
405
|
+
const spaPath = path5.join(xpineDistDir, "./src/static/spa.js");
|
|
406
|
+
const content = fs5.readFileSync(spaPath, "utf-8");
|
|
407
|
+
fs5.appendFileSync(tempFilePath, `
|
|
366
408
|
` + content);
|
|
367
409
|
}
|
|
368
410
|
async function buildAlpineDataFile(componentData, dataFiles) {
|
|
@@ -382,10 +424,10 @@ async function buildAlpineDataFile(componentData, dataFiles) {
|
|
|
382
424
|
};
|
|
383
425
|
const componentsAndDataFiles = componentData.concat(dataFiles);
|
|
384
426
|
for (const component of componentsAndDataFiles) {
|
|
385
|
-
const sourceFile =
|
|
427
|
+
const sourceFile = ts3.createSourceFile(
|
|
386
428
|
component.path,
|
|
387
429
|
component.contents,
|
|
388
|
-
|
|
430
|
+
ts3.ScriptTarget.Latest
|
|
389
431
|
);
|
|
390
432
|
const dataFunctionResult = findDataAttributesAndFunctions(sourceFile, sourceFile);
|
|
391
433
|
dataFunctionResults.foundDataAttributes.push(...dataFunctionResult.foundDataAttributes);
|
|
@@ -407,18 +449,18 @@ async function buildAlpineDataFile(componentData, dataFiles) {
|
|
|
407
449
|
output.code.push(`Alpine.data('${dataFunction.name}', ${dataFunction.name});`);
|
|
408
450
|
}
|
|
409
451
|
const result = output.imports.join("\n") + "\n" + output.code.join("\n") + "\n" + output.end.join("\n");
|
|
410
|
-
|
|
411
|
-
|
|
452
|
+
fs5.ensureFileSync(config.alpineDataPath);
|
|
453
|
+
fs5.writeFileSync(config.alpineDataPath, result);
|
|
412
454
|
return config.alpineDataPath;
|
|
413
455
|
}
|
|
414
456
|
async function buildCSS() {
|
|
415
457
|
const cssFiles = globSync(config.srcDir + "/**/*.css");
|
|
416
458
|
for (const file of cssFiles) {
|
|
417
|
-
const fileContents =
|
|
459
|
+
const fileContents = fs5.readFileSync(file, "utf-8");
|
|
418
460
|
const result = await postcss([tailwindPostcss(), remove_layers_default()]).process(fileContents, { from: file });
|
|
419
461
|
const newPath = file.replace(config.srcDir, config.distDir);
|
|
420
|
-
|
|
421
|
-
|
|
462
|
+
fs5.ensureFileSync(newPath);
|
|
463
|
+
fs5.writeFileSync(newPath, result.css);
|
|
422
464
|
}
|
|
423
465
|
logSize(config.distPublicDir, "css");
|
|
424
466
|
}
|
|
@@ -432,8 +474,8 @@ async function buildPublicFolderSymlinks() {
|
|
|
432
474
|
const splitNewPath = newPath.split("/");
|
|
433
475
|
splitNewPath.pop();
|
|
434
476
|
const newDir = splitNewPath.join("/");
|
|
435
|
-
|
|
436
|
-
|
|
477
|
+
fs5.ensureDirSync(newDir);
|
|
478
|
+
fs5.symlinkSync(file, newPath);
|
|
437
479
|
} catch {
|
|
438
480
|
}
|
|
439
481
|
}
|
|
@@ -444,7 +486,7 @@ async function logSize(pathName, type, validExtensions = [".js", ".css"]) {
|
|
|
444
486
|
if (!validExtensions.find((ext) => file.endsWith(ext))) return false;
|
|
445
487
|
return {
|
|
446
488
|
file,
|
|
447
|
-
size:
|
|
489
|
+
size: fs5.statSync(file).size / (1024 * 1e3)
|
|
448
490
|
};
|
|
449
491
|
}).filter(Boolean);
|
|
450
492
|
const totalSize = fileSizes.reduce((total, current) => {
|
|
@@ -452,17 +494,75 @@ async function logSize(pathName, type, validExtensions = [".js", ".css"]) {
|
|
|
452
494
|
}, 0);
|
|
453
495
|
console.info(`[${totalSize.toFixed(3)} MB] Built ${type}`);
|
|
454
496
|
}
|
|
497
|
+
async function buildStaticFiles(componentData) {
|
|
498
|
+
const componentsWithConfigs = componentData.filter((item) => item.configFile);
|
|
499
|
+
for (const component of componentsWithConfigs) {
|
|
500
|
+
const config2 = (await import(sourcePathToDistPath(component.configFile) + `?cache=${Date.now()}`)).default;
|
|
501
|
+
const shouldBeStatic = config2?.staticPaths;
|
|
502
|
+
if (shouldBeStatic) {
|
|
503
|
+
let componentFileName = component.path.split("/").pop().replace(regex_default.endsWithJSX, "").replace(regex_default.endsWithTSX, "");
|
|
504
|
+
const isDynamicRoute = component.path.match(regex_default.isDynamicRoute);
|
|
505
|
+
if (isDynamicRoute) {
|
|
506
|
+
componentFileName = component.path.split("/").filter((dir) => dir.match(regex_default.isDynamicRoute)).join("/").replace(regex_default.endsWithJSX, "").replace(regex_default.endsWithTSX, "");
|
|
507
|
+
}
|
|
508
|
+
const builtComponentPath = sourcePathToDistPath(component.path);
|
|
509
|
+
const componentDynamicPaths = getComponentDynamicPaths(componentFileName);
|
|
510
|
+
const componentFn = (await import(builtComponentPath + `?cache=${Date.now()}`)).default;
|
|
511
|
+
const outputPath = componentDynamicPaths?.length ? componentDynamicPaths.reduce((total, current) => {
|
|
512
|
+
return total.replace(`/[${current}]`, "");
|
|
513
|
+
}, path5.dirname(builtComponentPath)) : path5.dirname(builtComponentPath);
|
|
514
|
+
if (typeof shouldBeStatic === "boolean") {
|
|
515
|
+
try {
|
|
516
|
+
const staticComponentOutput = await componentFn();
|
|
517
|
+
fs5.writeFileSync(path5.join(outputPath, "./index.html"), staticComponentOutput);
|
|
518
|
+
} catch (err) {
|
|
519
|
+
console.error(err);
|
|
520
|
+
console.log("Could not build static component", component.path);
|
|
521
|
+
}
|
|
522
|
+
} else if (typeof shouldBeStatic === "function") {
|
|
523
|
+
const dynamicPaths = await shouldBeStatic();
|
|
524
|
+
for (const dynamicPath of dynamicPaths) {
|
|
525
|
+
try {
|
|
526
|
+
const staticComponentOutput = await componentFn({
|
|
527
|
+
params: {
|
|
528
|
+
...componentDynamicPaths?.length ? dynamicPath : {}
|
|
529
|
+
}
|
|
530
|
+
});
|
|
531
|
+
const updatedOutDir = path5.join(outputPath, `./${componentDynamicPaths.map((key) => dynamicPath[key]).join("/")}`);
|
|
532
|
+
fs5.ensureDirSync(updatedOutDir);
|
|
533
|
+
fs5.writeFileSync(path5.join(updatedOutDir, `./index.html`), staticComponentOutput);
|
|
534
|
+
} catch (err) {
|
|
535
|
+
console.log("Could not build static component", component.path);
|
|
536
|
+
console.error(err);
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
function sourcePathToDistPath(sourcePath) {
|
|
544
|
+
return sourcePath.replace(config.srcDir, config.distDir).replace(/\.ts$/, ".js").replace(/\.tsx$/, ".js");
|
|
545
|
+
}
|
|
546
|
+
function getComponentDynamicPaths(componentPath) {
|
|
547
|
+
const matches = [...componentPath.matchAll(regex_default.dynamicRoutes)];
|
|
548
|
+
if (!matches?.length) return null;
|
|
549
|
+
const output = [];
|
|
550
|
+
for (const match of matches) {
|
|
551
|
+
output.push(match[2]);
|
|
552
|
+
}
|
|
553
|
+
return output;
|
|
554
|
+
}
|
|
455
555
|
|
|
456
556
|
// src/runDevServer.ts
|
|
457
|
-
import
|
|
557
|
+
import path7 from "path";
|
|
458
558
|
|
|
459
559
|
// src/util/env.ts
|
|
460
560
|
import dotenv from "dotenv";
|
|
461
|
-
import
|
|
561
|
+
import path6 from "path";
|
|
462
562
|
import { GetSecretValueCommand, SecretsManagerClient } from "@aws-sdk/client-secrets-manager";
|
|
463
563
|
async function setupEnv() {
|
|
464
564
|
if (process.env.HAS_SETUP_ENV) return;
|
|
465
|
-
dotenv.config({ path:
|
|
565
|
+
dotenv.config({ path: path6.join(config.rootDir, `./.env.${process.env.STAGE || "dev"}`) });
|
|
466
566
|
await loadSecretsManagerSecrets();
|
|
467
567
|
process.env.HAS_SETUP_ENV = "true";
|
|
468
568
|
}
|
|
@@ -491,16 +591,16 @@ async function loadSecretsManagerSecrets() {
|
|
|
491
591
|
await setupEnv();
|
|
492
592
|
async function runDevServer() {
|
|
493
593
|
process.env.NODE_ENV = "development";
|
|
494
|
-
const startServer = (await import(config.serverDistAppPath + `?cache=${Date.now()}`)).default;
|
|
495
594
|
await buildApp(true);
|
|
595
|
+
const startServer = (await import(config.serverDistAppPath + `?cache=${Date.now()}`)).default;
|
|
496
596
|
let appServer = await startServer();
|
|
497
597
|
const watcher = chokidar.watch(config.srcDir, {
|
|
498
598
|
ignoreInitial: true,
|
|
499
599
|
// Ignore map and prisma files
|
|
500
|
-
ignored: (pathName) => pathName.endsWith(".map") || pathName.startsWith(
|
|
600
|
+
ignored: (pathName) => pathName.endsWith(".map") || pathName.startsWith(path7.join(config.serverDir, "./prisma"))
|
|
501
601
|
});
|
|
502
|
-
watcher.on("all", async (event,
|
|
503
|
-
const shouldReloadServer =
|
|
602
|
+
watcher.on("all", async (event, path9) => {
|
|
603
|
+
const shouldReloadServer = path9.startsWith(config.serverDir) && !path9.startsWith(config.runDir) || ["add", "unlink"].includes(event) && path9.startsWith(config.pagesDir);
|
|
504
604
|
if (shouldReloadServer) {
|
|
505
605
|
await appServer.server.close();
|
|
506
606
|
await buildApp(true);
|
|
@@ -574,29 +674,34 @@ function getTokenFromRequest(req) {
|
|
|
574
674
|
|
|
575
675
|
// src/express.ts
|
|
576
676
|
import requestIP from "request-ip";
|
|
677
|
+
import fs6 from "fs-extra";
|
|
678
|
+
import path8 from "path";
|
|
577
679
|
var doctypeHTML = "<!DOCTYPE html>";
|
|
578
680
|
async function createRouter() {
|
|
579
681
|
const methods = ["get", "post", "put", "patch", "delete"];
|
|
580
682
|
const router = express2.Router();
|
|
581
683
|
const routes = globSync2(config.pagesDir + "/**/*.{tsx,ts}");
|
|
582
684
|
const routeMap = routes.map((route) => {
|
|
685
|
+
const routeFormatted = route.split(config.pagesDir).pop().replace(".tsx", "").replace(".js", "").replace(".ts", "");
|
|
686
|
+
if (routeFormatted.endsWith("+config")) return;
|
|
687
|
+
const routeFormattedWithIndex = routeFormatted.replace(/\/index$/g, "");
|
|
583
688
|
return {
|
|
584
|
-
route:
|
|
689
|
+
route: routeFormattedWithIndex,
|
|
585
690
|
path: route.replace(config.srcDir, config.distDir).replace(".tsx", ".js").replace(".ts", ".js"),
|
|
586
691
|
originalRoute: route
|
|
587
692
|
};
|
|
588
|
-
});
|
|
693
|
+
}).filter(Boolean);
|
|
589
694
|
const routeResults = [];
|
|
590
695
|
for (const route of routeMap) {
|
|
591
696
|
const isJSX = route.originalRoute.endsWith(".tsx") || route.originalRoute.endsWith(".jsx");
|
|
592
697
|
const routeItem = process.env.NODE_ENV === "development" ? null : (await import(route.path)).default;
|
|
593
698
|
const slugRoute = route.route.toLowerCase().replace(/[ ]/g, "");
|
|
594
699
|
const foundMethod = methods.find((method) => slugRoute.endsWith(`.${method}`));
|
|
595
|
-
const isDynamicRoute = slugRoute.match(
|
|
700
|
+
const isDynamicRoute = slugRoute.match(regex_default.isDynamicRoute);
|
|
596
701
|
let formattedRouteItem = slugRoute;
|
|
597
702
|
if (foundMethod) formattedRouteItem = formattedRouteItem.split(".").shift();
|
|
598
703
|
if (isDynamicRoute) {
|
|
599
|
-
const result = [...formattedRouteItem.matchAll(
|
|
704
|
+
const result = [...formattedRouteItem.matchAll(regex_default.dynamicRoutes)];
|
|
600
705
|
for (const match of result) {
|
|
601
706
|
formattedRouteItem = formattedRouteItem.replace(match[0], ":" + match[2]);
|
|
602
707
|
}
|
|
@@ -608,6 +713,11 @@ async function createRouter() {
|
|
|
608
713
|
});
|
|
609
714
|
router[foundMethod || "get"](formattedRouteItem, async (req, res) => {
|
|
610
715
|
try {
|
|
716
|
+
const staticPath = routeHasStaticPath(formattedRouteItem, req.params);
|
|
717
|
+
if (staticPath && process.env.NODE_ENV !== "development") {
|
|
718
|
+
res.sendFile(staticPath);
|
|
719
|
+
return;
|
|
720
|
+
}
|
|
611
721
|
if (routeItem) {
|
|
612
722
|
if (isJSX) {
|
|
613
723
|
res.send(doctypeHTML + await routeItem(req, res));
|
|
@@ -669,6 +779,17 @@ async function createXPineRouter(app, beforeErrorRoute) {
|
|
|
669
779
|
}
|
|
670
780
|
});
|
|
671
781
|
}
|
|
782
|
+
function routeHasStaticPath(route, params) {
|
|
783
|
+
const paramEntries = Object.entries(params);
|
|
784
|
+
let routeToStaticPath = route;
|
|
785
|
+
for (const [key, value] of paramEntries) {
|
|
786
|
+
routeToStaticPath = routeToStaticPath.replace(`:${key}`, value);
|
|
787
|
+
}
|
|
788
|
+
routeToStaticPath += "/index.html";
|
|
789
|
+
const outputPath = path8.join(config.distPagesDir, routeToStaticPath);
|
|
790
|
+
if (fs6.existsSync(outputPath)) return outputPath;
|
|
791
|
+
return false;
|
|
792
|
+
}
|
|
672
793
|
|
|
673
794
|
// src/util/html.ts
|
|
674
795
|
var html = class {
|
|
@@ -700,15 +821,19 @@ export {
|
|
|
700
821
|
buildApp,
|
|
701
822
|
buildCSS,
|
|
702
823
|
buildPublicFolderSymlinks,
|
|
824
|
+
buildStaticFiles,
|
|
703
825
|
config,
|
|
704
826
|
createRouter,
|
|
705
827
|
createXPineRouter,
|
|
706
828
|
fromRoot,
|
|
829
|
+
getComponentDynamicPaths,
|
|
707
830
|
getTokenFromRequest,
|
|
708
831
|
html,
|
|
709
832
|
logSize,
|
|
833
|
+
routeHasStaticPath,
|
|
710
834
|
runDevServer,
|
|
711
835
|
setupEnv,
|
|
712
836
|
signUser,
|
|
837
|
+
sourcePathToDistPath,
|
|
713
838
|
verifyUser
|
|
714
839
|
};
|