@absolutejs/absolute 0.8.15 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/build/compileSvelte.d.ts +10 -0
- package/dist/build/compileVue.d.ts +5 -0
- package/dist/{src/build → build}/generateManifest.d.ts +1 -1
- package/dist/build/updateHTMLAssetPaths.d.ts +1 -0
- package/dist/core/build.d.ts +2 -0
- package/dist/{src/core → core}/index.d.ts +1 -0
- package/dist/core/lookup.d.ts +1 -0
- package/dist/core/pageHandlers.d.ts +14 -0
- package/dist/{src/index.d.ts → index.d.ts} +1 -1
- package/dist/index.js +546 -187
- package/dist/index.js.map +15 -11
- package/dist/types.d.ts +24 -0
- package/dist/utils/generateHeadElement.d.ts +17 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/stringModifiers.d.ts +2 -0
- package/eslint.config.mjs +38 -4
- package/package.json +8 -8
- package/tsconfig.build.json +20 -0
- package/dist/src/build/updateScriptTags.d.ts +0 -1
- package/dist/src/core/build.d.ts +0 -2
- package/dist/src/core/pageHandlers.d.ts +0 -10
- package/dist/src/svelte/compileSvelte.d.ts +0 -4
- package/dist/src/types.d.ts +0 -20
- package/dist/src/utils/index.d.ts +0 -2
- /package/dist/{src/build → build}/generateReactIndexes.d.ts +0 -0
- /package/dist/{src/build → build}/scanEntryPoints.d.ts +0 -0
- /package/dist/{src/constants.d.ts → constants.d.ts} +0 -0
- /package/dist/{src/plugins → plugins}/index.d.ts +0 -0
- /package/dist/{src/plugins → plugins}/networkingPlugin.d.ts +0 -0
- /package/dist/{src/plugins → plugins}/pageRouterPlugin.d.ts +0 -0
- /package/dist/{src/svelte → svelte}/renderToPipeableStream.d.ts +0 -0
- /package/dist/{src/svelte → svelte}/renderToReadableStream.d.ts +0 -0
- /package/dist/{src/svelte → svelte}/renderToString.d.ts +0 -0
- /package/dist/{src/utils → utils}/escapeScriptContent.d.ts +0 -0
- /package/dist/{src/utils → utils}/getDurationString.d.ts +0 -0
- /package/dist/{src/utils → utils}/networking.d.ts +0 -0
- /package/dist/{src/utils → utils}/validateSafePath.d.ts +0 -0
package/dist/index.js
CHANGED
|
@@ -11,49 +11,337 @@ var TWO_THIRDS = 2 / 3;
|
|
|
11
11
|
var DEFAULT_PORT = 3000;
|
|
12
12
|
var DEFAULT_CHUNK_SIZE = 16384;
|
|
13
13
|
// src/core/build.ts
|
|
14
|
-
import { rm as rm2, mkdir as
|
|
15
|
-
import { basename as
|
|
16
|
-
import { cwd, exit } from "process";
|
|
14
|
+
import { rm as rm2, mkdir as mkdir4, cp } from "fs/promises";
|
|
15
|
+
import { basename as basename4, join as join4, sep as sep3 } from "path";
|
|
16
|
+
import { cwd as cwd3, env as env2, exit } from "process";
|
|
17
17
|
var {$, build: bunBuild } = globalThis.Bun;
|
|
18
18
|
|
|
19
|
-
// src/build/
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
19
|
+
// src/build/compileSvelte.ts
|
|
20
|
+
import { mkdir, stat } from "fs/promises";
|
|
21
|
+
import {
|
|
22
|
+
dirname,
|
|
23
|
+
join,
|
|
24
|
+
basename,
|
|
25
|
+
extname,
|
|
26
|
+
resolve,
|
|
27
|
+
relative,
|
|
28
|
+
sep
|
|
29
|
+
} from "path";
|
|
30
|
+
import { cwd, env } from "process";
|
|
31
|
+
var {write, file, Transpiler } = globalThis.Bun;
|
|
32
|
+
import { compile, compileModule, preprocess } from "svelte/compiler";
|
|
33
|
+
var exists = async (filepath) => {
|
|
34
|
+
try {
|
|
35
|
+
await stat(filepath);
|
|
36
|
+
return true;
|
|
37
|
+
} catch {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
var resolveSvelte = async (spec, from) => {
|
|
42
|
+
const basePath = resolve(dirname(from), spec);
|
|
43
|
+
const explicit = /\.(svelte|svelte\.(?:ts|js))$/.test(basePath);
|
|
44
|
+
if (!explicit) {
|
|
45
|
+
const extensions = [".svelte", ".svelte.ts", ".svelte.js"];
|
|
46
|
+
const paths = extensions.map((ext) => `${basePath}${ext}`);
|
|
47
|
+
const checks = await Promise.all(paths.map(exists));
|
|
48
|
+
const match = paths.find((_, index) => checks[index]);
|
|
49
|
+
return match ?? null;
|
|
50
|
+
}
|
|
51
|
+
if (await exists(basePath))
|
|
52
|
+
return basePath;
|
|
53
|
+
if (!basePath.endsWith(".svelte"))
|
|
54
|
+
return null;
|
|
55
|
+
const tsPath = `${basePath}.ts`;
|
|
56
|
+
if (await exists(tsPath))
|
|
57
|
+
return tsPath;
|
|
58
|
+
const jsPath = `${basePath}.js`;
|
|
59
|
+
if (await exists(jsPath))
|
|
60
|
+
return jsPath;
|
|
61
|
+
return null;
|
|
62
|
+
};
|
|
63
|
+
var transpiler = new Transpiler({ loader: "ts", target: "browser" });
|
|
64
|
+
var projectRoot = cwd();
|
|
65
|
+
var compileSvelte = async (entryPoints, outRoot, cache = new Map) => {
|
|
66
|
+
const clientFolder = "client";
|
|
67
|
+
const indexFolder = "indexes";
|
|
68
|
+
const pagesFolder = "pages";
|
|
69
|
+
await Promise.all([clientFolder, indexFolder, pagesFolder].map((d) => mkdir(join(outRoot, d), { recursive: true })));
|
|
70
|
+
const dev = env.NODE_ENV === "development";
|
|
71
|
+
const build = async (src) => {
|
|
72
|
+
const memo = cache.get(src);
|
|
73
|
+
if (memo)
|
|
74
|
+
return memo;
|
|
75
|
+
const raw = await file(src).text();
|
|
76
|
+
const isModule = src.endsWith(".svelte.ts") || src.endsWith(".svelte.js");
|
|
77
|
+
const prepped = isModule ? raw : (await preprocess(raw, {})).code;
|
|
78
|
+
const transpiledCode = src.endsWith(".ts") || src.endsWith(".svelte.ts") ? transpiler.transformSync(prepped) : prepped;
|
|
79
|
+
const relDir = dirname(relative(projectRoot, src));
|
|
80
|
+
const baseName = basename(src).replace(/\.svelte(\.(ts|js))?$/, "");
|
|
81
|
+
const importPaths = Array.from(transpiledCode.matchAll(/from\s+['"]([^'"]+)['"]/g)).map((m) => m[1]).filter((p) => p !== undefined);
|
|
82
|
+
const resolveResults = await Promise.all(importPaths.map((p) => resolveSvelte(p, src)));
|
|
83
|
+
const childSources = resolveResults.filter((path) => path !== undefined);
|
|
84
|
+
await Promise.all(childSources.map((p) => build(p)));
|
|
85
|
+
const generate = (mode) => (isModule ? compileModule(transpiledCode, { dev, filename: src }).js.code : compile(transpiledCode, {
|
|
86
|
+
css: "injected",
|
|
87
|
+
dev,
|
|
88
|
+
filename: src,
|
|
89
|
+
generate: mode
|
|
90
|
+
}).js.code).replace(/\.svelte(?:\.(?:ts|js))?(['"])/g, ".js$1");
|
|
91
|
+
const ssrPath = join(outRoot, pagesFolder, relDir, `${baseName}.js`);
|
|
92
|
+
const clientPath = join(outRoot, clientFolder, relDir, `${baseName}.js`);
|
|
93
|
+
await Promise.all([
|
|
94
|
+
mkdir(dirname(ssrPath), { recursive: true }),
|
|
95
|
+
mkdir(dirname(clientPath), { recursive: true })
|
|
96
|
+
]);
|
|
97
|
+
if (isModule) {
|
|
98
|
+
const bundle = generate("client");
|
|
99
|
+
await Promise.all([
|
|
100
|
+
write(ssrPath, bundle),
|
|
101
|
+
write(clientPath, bundle)
|
|
102
|
+
]);
|
|
36
103
|
} else {
|
|
37
|
-
|
|
104
|
+
const serverBundle = generate("server");
|
|
105
|
+
const clientBundle = generate("client");
|
|
106
|
+
await Promise.all([
|
|
107
|
+
write(ssrPath, serverBundle),
|
|
108
|
+
write(clientPath, clientBundle)
|
|
109
|
+
]);
|
|
38
110
|
}
|
|
39
|
-
|
|
40
|
-
|
|
111
|
+
const built = { client: clientPath, ssr: ssrPath };
|
|
112
|
+
cache.set(src, built);
|
|
113
|
+
return built;
|
|
114
|
+
};
|
|
115
|
+
const roots = await Promise.all(entryPoints.map(build));
|
|
116
|
+
await Promise.all(roots.map(({ client }) => {
|
|
117
|
+
const relClientDir = dirname(relative(join(outRoot, clientFolder), client));
|
|
118
|
+
const name = basename(client, extname(client));
|
|
119
|
+
const indexDir = join(outRoot, indexFolder, relClientDir);
|
|
120
|
+
const importPathRaw = relative(indexDir, client).split(sep).join("/");
|
|
121
|
+
const importPath = importPathRaw.startsWith(".") ? importPathRaw : `./${importPathRaw}`;
|
|
122
|
+
const indexPath = join(indexDir, `${name}.js`);
|
|
123
|
+
const boot = `import C from "${importPath}";
|
|
124
|
+
import { hydrate } from "svelte";
|
|
125
|
+
hydrate(C,{target:document.body,props:window.__INITIAL_PROPS__??{}});`;
|
|
126
|
+
return mkdir(indexDir, { recursive: true }).then(() => write(indexPath, boot));
|
|
127
|
+
}));
|
|
128
|
+
return {
|
|
129
|
+
svelteClientPaths: roots.map(({ client }) => {
|
|
130
|
+
const rel = dirname(relative(join(outRoot, clientFolder), client));
|
|
131
|
+
return join(outRoot, indexFolder, rel, basename(client));
|
|
132
|
+
}),
|
|
133
|
+
svelteServerPaths: roots.map(({ ssr }) => ssr)
|
|
134
|
+
};
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
// src/build/compileVue.ts
|
|
138
|
+
import { mkdir as mkdir2 } from "fs/promises";
|
|
139
|
+
import { basename as basename2, dirname as dirname2, join as join2, relative as relative2, resolve as resolve2 } from "path";
|
|
140
|
+
import { cwd as cwd2 } from "process";
|
|
141
|
+
import {
|
|
142
|
+
parse,
|
|
143
|
+
compileScript,
|
|
144
|
+
compileTemplate,
|
|
145
|
+
compileStyle
|
|
146
|
+
} from "@vue/compiler-sfc";
|
|
147
|
+
var {file: file2, write: write2, Transpiler: Transpiler2 } = globalThis.Bun;
|
|
148
|
+
|
|
149
|
+
// src/utils/stringModifiers.ts
|
|
150
|
+
var normalizeSlug = (str) => str.trim().replace(/\s+/g, "-").replace(/[^A-Za-z0-9\-_]+/g, "").replace(/[-_]{2,}/g, "-");
|
|
151
|
+
var toPascal = (str) => normalizeSlug(str).split(/[-_]/).filter(Boolean).map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1).toLowerCase()).join("");
|
|
152
|
+
var toKebab = (str) => normalizeSlug(str).replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
|
|
153
|
+
|
|
154
|
+
// src/build/compileVue.ts
|
|
155
|
+
var transpiler2 = new Transpiler2({ loader: "ts", target: "browser" });
|
|
156
|
+
var projectRoot2 = cwd2();
|
|
157
|
+
var extractImports = (sourceCode) => Array.from(sourceCode.matchAll(/import\s+[\s\S]+?['"]([^'"]+)['"]/g)).map((match) => match[1]).filter((importPath) => importPath !== undefined);
|
|
158
|
+
var toJsFileName = (path) => {
|
|
159
|
+
if (path.endsWith(".vue")) {
|
|
160
|
+
return path.replace(/\.vue$/, ".js");
|
|
161
|
+
}
|
|
162
|
+
if (path.endsWith(".ts")) {
|
|
163
|
+
return path.replace(/\.ts$/, ".js");
|
|
164
|
+
}
|
|
165
|
+
return `${path}.js`;
|
|
166
|
+
};
|
|
167
|
+
var stripModuleExports = (sourceCode) => sourceCode.replace(/export\s+default/, "const script =").replace(/^export\s+/gm, "");
|
|
168
|
+
var buildVueFile = async (absolutePath, outputDirs, cache, isEntryPage = false) => {
|
|
169
|
+
if (cache.has(absolutePath))
|
|
170
|
+
return cache.get(absolutePath);
|
|
171
|
+
const relativePath = relative2(projectRoot2, absolutePath).replace(/\\/g, "/");
|
|
172
|
+
const relativePathWithoutExt = relativePath.replace(/\.vue$/, "");
|
|
173
|
+
const componentName = basename2(absolutePath, ".vue");
|
|
174
|
+
const kebabId = toKebab(componentName);
|
|
175
|
+
const sourceCode = await file2(absolutePath).text();
|
|
176
|
+
const { descriptor } = parse(sourceCode, { filename: absolutePath });
|
|
177
|
+
const originalSetupCode = descriptor.scriptSetup?.content ?? descriptor.script?.content ?? "";
|
|
178
|
+
const relativeImports = extractImports(originalSetupCode);
|
|
179
|
+
const childVueImports = relativeImports.filter((importPath) => importPath.startsWith(".") && importPath.endsWith(".vue"));
|
|
180
|
+
const tsHelperImports = relativeImports.filter((importPath) => importPath.startsWith(".") && !importPath.endsWith(".vue"));
|
|
181
|
+
const childBuildResults = await Promise.all(childVueImports.map((importPath) => buildVueFile(resolve2(dirname2(absolutePath), importPath), outputDirs, cache, false)));
|
|
182
|
+
const compiledScript = compileScript(descriptor, {
|
|
183
|
+
id: kebabId,
|
|
184
|
+
inlineTemplate: false
|
|
185
|
+
});
|
|
186
|
+
const transformedScript = transpiler2.transformSync(stripModuleExports(compiledScript.content)).replace(/(['"])(\.{1,2}\/[^'"]+)(['"])/g, (_, quote, importPath, endQuote) => quote + toJsFileName(importPath) + endQuote);
|
|
187
|
+
const renderBlock = (forServer) => compileTemplate({
|
|
188
|
+
compilerOptions: {
|
|
189
|
+
bindingMetadata: compiledScript.bindings,
|
|
190
|
+
prefixIdentifiers: true
|
|
191
|
+
},
|
|
192
|
+
filename: absolutePath,
|
|
193
|
+
id: kebabId,
|
|
194
|
+
scoped: descriptor.styles.some((s) => s.scoped),
|
|
195
|
+
source: descriptor.template?.content ?? "",
|
|
196
|
+
ssr: forServer,
|
|
197
|
+
ssrCssVars: descriptor.cssVars
|
|
198
|
+
}).code.replace(/(['"])(\.{1,2}\/[^'"]+)(['"])/g, (_, quote, importPath, endQuote) => quote + toJsFileName(importPath) + endQuote);
|
|
199
|
+
const ownCssCodes = descriptor.styles.map((styleBlock) => compileStyle({
|
|
200
|
+
filename: absolutePath,
|
|
201
|
+
id: kebabId,
|
|
202
|
+
scoped: styleBlock.scoped,
|
|
203
|
+
source: styleBlock.content,
|
|
204
|
+
trim: true
|
|
205
|
+
}).code);
|
|
206
|
+
const aggregatedCssCodes = [
|
|
207
|
+
...ownCssCodes,
|
|
208
|
+
...childBuildResults.flatMap((result) => result.cssCodes)
|
|
209
|
+
];
|
|
210
|
+
let emittedCssPaths = [];
|
|
211
|
+
if (isEntryPage && aggregatedCssCodes.length) {
|
|
212
|
+
const cssOutputPath = join2(outputDirs.css, `${toKebab(componentName)}.css`);
|
|
213
|
+
await mkdir2(dirname2(cssOutputPath), { recursive: true });
|
|
214
|
+
await write2(cssOutputPath, aggregatedCssCodes.join(`
|
|
215
|
+
`));
|
|
216
|
+
emittedCssPaths = [cssOutputPath];
|
|
217
|
+
}
|
|
218
|
+
const buildModule = (renderCode, renderFunctionName) => {
|
|
219
|
+
const vueHeader = 'import { defineComponent } from "vue";';
|
|
220
|
+
return [
|
|
221
|
+
transformedScript,
|
|
222
|
+
renderCode,
|
|
223
|
+
vueHeader,
|
|
224
|
+
`export default defineComponent({ ...script, ${renderFunctionName} });`
|
|
225
|
+
].join(`
|
|
226
|
+
`);
|
|
227
|
+
};
|
|
228
|
+
const clientModuleCode = buildModule(renderBlock(false), "render");
|
|
229
|
+
const serverModuleCode = buildModule(renderBlock(true), "ssrRender");
|
|
230
|
+
const clientOutPath = join2(outputDirs.client, `${relativePathWithoutExt}.js`);
|
|
231
|
+
const serverOutPath = join2(outputDirs.server, `${relativePathWithoutExt}.js`);
|
|
232
|
+
await mkdir2(dirname2(clientOutPath), { recursive: true });
|
|
233
|
+
await mkdir2(dirname2(serverOutPath), { recursive: true });
|
|
234
|
+
await write2(clientOutPath, clientModuleCode);
|
|
235
|
+
await write2(serverOutPath, serverModuleCode);
|
|
236
|
+
const buildResult = {
|
|
237
|
+
clientPath: clientOutPath,
|
|
238
|
+
cssCodes: aggregatedCssCodes,
|
|
239
|
+
cssPaths: emittedCssPaths,
|
|
240
|
+
serverPath: serverOutPath,
|
|
241
|
+
tsHelperPaths: [
|
|
242
|
+
...tsHelperImports.map((helper) => resolve2(dirname2(absolutePath), helper.endsWith(".ts") ? helper : `${helper}.ts`)),
|
|
243
|
+
...childBuildResults.flatMap((result) => result.tsHelperPaths)
|
|
244
|
+
]
|
|
245
|
+
};
|
|
246
|
+
cache.set(absolutePath, buildResult);
|
|
247
|
+
return buildResult;
|
|
248
|
+
};
|
|
249
|
+
var compileVue = async (pageEntryPoints, outputDirectory) => {
|
|
250
|
+
const clientDir = join2(outputDirectory, "client");
|
|
251
|
+
const indexDir = join2(outputDirectory, "indexes");
|
|
252
|
+
const pagesDir = join2(outputDirectory, "pages");
|
|
253
|
+
const stylesDir = join2(outputDirectory, "styles");
|
|
254
|
+
await Promise.all([
|
|
255
|
+
mkdir2(clientDir, { recursive: true }),
|
|
256
|
+
mkdir2(indexDir, { recursive: true }),
|
|
257
|
+
mkdir2(pagesDir, { recursive: true }),
|
|
258
|
+
mkdir2(stylesDir, { recursive: true })
|
|
259
|
+
]);
|
|
260
|
+
const buildCache = new Map;
|
|
261
|
+
const tsHelperSet = new Set;
|
|
262
|
+
const pageResults = await Promise.all(pageEntryPoints.map(async (pageEntry) => {
|
|
263
|
+
const buildResult = await buildVueFile(resolve2(pageEntry), { client: clientDir, css: stylesDir, server: pagesDir }, buildCache, true);
|
|
264
|
+
buildResult.tsHelperPaths.forEach((p) => tsHelperSet.add(p));
|
|
265
|
+
const relPath = relative2(projectRoot2, pageEntry).replace(/\.vue$/, "");
|
|
266
|
+
const indexPath = join2(indexDir, `${relPath}.js`);
|
|
267
|
+
const clientEntryPath = join2(clientDir, `${relPath}.js`);
|
|
268
|
+
await mkdir2(dirname2(indexPath), { recursive: true });
|
|
269
|
+
await write2(indexPath, [
|
|
270
|
+
`import Comp from "${relative2(dirname2(indexPath), clientEntryPath)}";`,
|
|
271
|
+
'import { createSSRApp } from "vue";',
|
|
272
|
+
"const props = window.__INITIAL_PROPS__ ?? {};",
|
|
273
|
+
'createSSRApp(Comp, props).mount("#root");'
|
|
274
|
+
].join(`
|
|
275
|
+
`));
|
|
276
|
+
return {
|
|
277
|
+
cssPaths: buildResult.cssPaths,
|
|
278
|
+
indexPath,
|
|
279
|
+
serverPath: buildResult.serverPath
|
|
280
|
+
};
|
|
281
|
+
}));
|
|
282
|
+
await Promise.all(Array.from(tsHelperSet).map(async (src) => {
|
|
283
|
+
const code = transpiler2.transformSync(await file2(src).text());
|
|
284
|
+
const rel = relative2(projectRoot2, src).replace(/\.ts$/, ".js");
|
|
285
|
+
const clientDest = join2(clientDir, rel);
|
|
286
|
+
const serverDest = join2(pagesDir, rel);
|
|
287
|
+
await Promise.all([
|
|
288
|
+
mkdir2(dirname2(clientDest), { recursive: true }),
|
|
289
|
+
mkdir2(dirname2(serverDest), { recursive: true })
|
|
290
|
+
]);
|
|
291
|
+
await Promise.all([
|
|
292
|
+
write2(clientDest, code),
|
|
293
|
+
write2(serverDest, code)
|
|
294
|
+
]);
|
|
295
|
+
}));
|
|
296
|
+
return {
|
|
297
|
+
vueCssPaths: pageResults.flatMap((pageResult) => pageResult.cssPaths),
|
|
298
|
+
vueIndexPaths: pageResults.map((pageResult) => pageResult.indexPath),
|
|
299
|
+
vueServerPaths: pageResults.map((pageResult) => pageResult.serverPath)
|
|
300
|
+
};
|
|
41
301
|
};
|
|
42
302
|
|
|
303
|
+
// src/build/generateManifest.ts
|
|
304
|
+
import { extname as extname2 } from "path";
|
|
305
|
+
var generateManifest = (outputs, buildPath) => outputs.reduce((manifest, artifact) => {
|
|
306
|
+
let relative3 = artifact.path.startsWith(buildPath) ? artifact.path.slice(buildPath.length) : artifact.path;
|
|
307
|
+
relative3 = relative3.replace(/^\/+/, "");
|
|
308
|
+
const segments = relative3.split("/");
|
|
309
|
+
const fileWithHash = segments.pop();
|
|
310
|
+
if (!fileWithHash)
|
|
311
|
+
return manifest;
|
|
312
|
+
const [baseName] = fileWithHash.split(`.${artifact.hash}.`);
|
|
313
|
+
if (!baseName)
|
|
314
|
+
return manifest;
|
|
315
|
+
const ext = extname2(fileWithHash);
|
|
316
|
+
if (ext === ".css") {
|
|
317
|
+
manifest[`${toPascal(baseName)}CSS`] = `/${relative3}`;
|
|
318
|
+
return manifest;
|
|
319
|
+
}
|
|
320
|
+
const folder = segments.length > 1 ? segments[1] : segments[0];
|
|
321
|
+
if (folder === "indexes") {
|
|
322
|
+
manifest[`${baseName}Index`] = `/${relative3}`;
|
|
323
|
+
} else if (folder === "pages") {
|
|
324
|
+
manifest[baseName] ??= artifact.path;
|
|
325
|
+
} else {
|
|
326
|
+
manifest[baseName] = `/${relative3}`;
|
|
327
|
+
}
|
|
328
|
+
return manifest;
|
|
329
|
+
}, {});
|
|
330
|
+
|
|
43
331
|
// src/build/generateReactIndexes.ts
|
|
44
|
-
import { mkdir, rm, writeFile } from "fs/promises";
|
|
45
|
-
import { basename, join } from "path";
|
|
332
|
+
import { mkdir as mkdir3, rm, writeFile } from "fs/promises";
|
|
333
|
+
import { basename as basename3, join as join3 } from "path";
|
|
46
334
|
var {Glob } = globalThis.Bun;
|
|
47
335
|
var generateReactIndexFiles = async (reactPagesDirectory, reactIndexesDirectory) => {
|
|
48
336
|
await rm(reactIndexesDirectory, { force: true, recursive: true });
|
|
49
|
-
await
|
|
337
|
+
await mkdir3(reactIndexesDirectory);
|
|
50
338
|
const pagesGlob = new Glob("*.*");
|
|
51
339
|
const files = [];
|
|
52
|
-
for await (const
|
|
53
|
-
files.push(
|
|
340
|
+
for await (const file3 of pagesGlob.scan({ cwd: reactPagesDirectory })) {
|
|
341
|
+
files.push(file3);
|
|
54
342
|
}
|
|
55
|
-
const promises = files.map(async (
|
|
56
|
-
const fileName =
|
|
343
|
+
const promises = files.map(async (file3) => {
|
|
344
|
+
const fileName = basename3(file3);
|
|
57
345
|
const [componentName] = fileName.split(".");
|
|
58
346
|
const content = [
|
|
59
347
|
`import { hydrateRoot } from 'react-dom/client';`,
|
|
@@ -71,7 +359,7 @@ var generateReactIndexFiles = async (reactPagesDirectory, reactIndexesDirectory)
|
|
|
71
359
|
`hydrateRoot(document, <${componentName} {...window.__INITIAL_PROPS__} />);`
|
|
72
360
|
].join(`
|
|
73
361
|
`);
|
|
74
|
-
return writeFile(
|
|
362
|
+
return writeFile(join3(reactIndexesDirectory, `${componentName}.tsx`), content);
|
|
75
363
|
});
|
|
76
364
|
await Promise.all(promises);
|
|
77
365
|
};
|
|
@@ -81,78 +369,32 @@ var {Glob: Glob2 } = globalThis.Bun;
|
|
|
81
369
|
var scanEntryPoints = async (dir, pattern) => {
|
|
82
370
|
const entryPaths = [];
|
|
83
371
|
const glob = new Glob2(pattern);
|
|
84
|
-
for await (const
|
|
85
|
-
entryPaths.push(
|
|
372
|
+
for await (const file3 of glob.scan({ absolute: true, cwd: dir })) {
|
|
373
|
+
entryPaths.push(file3);
|
|
86
374
|
}
|
|
87
375
|
return entryPaths;
|
|
88
376
|
};
|
|
89
377
|
|
|
90
|
-
// src/build/
|
|
378
|
+
// src/build/updateHTMLAssetPaths.ts
|
|
91
379
|
import { readFile, writeFile as writeFile2 } from "fs/promises";
|
|
92
|
-
var
|
|
380
|
+
var updateHTMLAssetPaths = async (manifest, htmlDir) => {
|
|
93
381
|
const htmlFiles = await scanEntryPoints(htmlDir, "*.html");
|
|
382
|
+
const assetRegex = /((?:<script[^>]+src=|<link[^>]*?rel=["']stylesheet["'][^>]*?href=)["'])(\/?(?:.*\/)?)([^./"']+)(?:\.[^."'/]+)?(\.(?:js|ts|css))(["'][^>]*>)/g;
|
|
94
383
|
const tasks = htmlFiles.map(async (filePath) => {
|
|
95
384
|
const original = await readFile(filePath, "utf8");
|
|
96
|
-
const updated =
|
|
97
|
-
const
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
|
|
385
|
+
const updated = original.replace(assetRegex, (match, prefix, _dir, name, ext, suffix) => {
|
|
386
|
+
const key = ext === ".css" ? `${toPascal(name)}CSS` : name;
|
|
387
|
+
const newPath = manifest[key];
|
|
388
|
+
if (newPath)
|
|
389
|
+
return `${prefix}${newPath}${suffix}`;
|
|
390
|
+
console.error(`error: no manifest entry for ${ext.slice(1)} "${name}" referenced in ${filePath}`);
|
|
391
|
+
return match;
|
|
392
|
+
});
|
|
101
393
|
await writeFile2(filePath, updated, "utf8");
|
|
102
394
|
});
|
|
103
395
|
await Promise.all(tasks);
|
|
104
396
|
};
|
|
105
397
|
|
|
106
|
-
// src/svelte/compileSvelte.ts
|
|
107
|
-
import { mkdir as mkdir2 } from "fs/promises";
|
|
108
|
-
import { basename as basename2, join as join2 } from "path";
|
|
109
|
-
import { env } from "process";
|
|
110
|
-
var {write, file } = globalThis.Bun;
|
|
111
|
-
import { compile, preprocess } from "svelte/compiler";
|
|
112
|
-
var compileSvelte = async (entryPoints, outputDirectory) => {
|
|
113
|
-
const pagesDir = join2(outputDirectory, "pages");
|
|
114
|
-
const clientDir = join2(outputDirectory, "client");
|
|
115
|
-
const indexesDir = join2(outputDirectory, "indexes");
|
|
116
|
-
await Promise.all([
|
|
117
|
-
mkdir2(clientDir, { recursive: true }),
|
|
118
|
-
mkdir2(indexesDir, { recursive: true })
|
|
119
|
-
]);
|
|
120
|
-
const isDev = env.NODE_ENV === "development";
|
|
121
|
-
const builds = await Promise.all(entryPoints.map(async (entry) => {
|
|
122
|
-
const source = await file(entry).text();
|
|
123
|
-
const { code: pre } = await preprocess(source, {});
|
|
124
|
-
const name = basename2(entry, ".svelte");
|
|
125
|
-
const { js: ssrJs } = compile(pre, {
|
|
126
|
-
css: "injected",
|
|
127
|
-
dev: isDev,
|
|
128
|
-
filename: entry,
|
|
129
|
-
generate: "server"
|
|
130
|
-
});
|
|
131
|
-
const ssrPath = join2(pagesDir, `${name}.js`);
|
|
132
|
-
const { js: clientJs } = compile(pre, {
|
|
133
|
-
css: "injected",
|
|
134
|
-
dev: isDev,
|
|
135
|
-
filename: entry,
|
|
136
|
-
generate: "client"
|
|
137
|
-
});
|
|
138
|
-
const clientComponentPath = join2(clientDir, `${name}.js`);
|
|
139
|
-
const bootstrap = `import Component from "../client/${name}.js";
|
|
140
|
-
import { hydrate } from "svelte";
|
|
141
|
-
hydrate(Component,{target:document.body,props:window.__INITIAL_PROPS__??{}});`;
|
|
142
|
-
const clientIndexPath = join2(indexesDir, `${name}.js`);
|
|
143
|
-
await Promise.all([
|
|
144
|
-
write(ssrPath, ssrJs.code),
|
|
145
|
-
write(clientComponentPath, clientJs.code),
|
|
146
|
-
write(clientIndexPath, bootstrap)
|
|
147
|
-
]);
|
|
148
|
-
return { clientIndexPath, ssrPath };
|
|
149
|
-
}));
|
|
150
|
-
return {
|
|
151
|
-
svelteClientPaths: builds.map(({ clientIndexPath }) => clientIndexPath),
|
|
152
|
-
svelteServerPaths: builds.map(({ ssrPath }) => ssrPath)
|
|
153
|
-
};
|
|
154
|
-
};
|
|
155
|
-
|
|
156
398
|
// src/utils/getDurationString.ts
|
|
157
399
|
var getDurationString = (duration) => {
|
|
158
400
|
let durationString;
|
|
@@ -167,152 +409,216 @@ var getDurationString = (duration) => {
|
|
|
167
409
|
};
|
|
168
410
|
|
|
169
411
|
// src/utils/validateSafePath.ts
|
|
170
|
-
import { resolve, relative, sep } from "path";
|
|
412
|
+
import { resolve as resolve3, relative as relative3, sep as sep2 } from "path";
|
|
171
413
|
var validateSafePath = (targetPath, baseDirectory) => {
|
|
172
|
-
const absoluteBase =
|
|
173
|
-
const absoluteTarget =
|
|
174
|
-
if (
|
|
414
|
+
const absoluteBase = resolve3(baseDirectory);
|
|
415
|
+
const absoluteTarget = resolve3(baseDirectory, targetPath);
|
|
416
|
+
if (relative3(absoluteBase, absoluteTarget).startsWith(`..${sep2}`)) {
|
|
175
417
|
throw new Error(`Unsafe path: ${targetPath}`);
|
|
176
418
|
}
|
|
177
419
|
return absoluteTarget;
|
|
178
420
|
};
|
|
179
421
|
|
|
180
422
|
// src/core/build.ts
|
|
423
|
+
var commonAncestor = (paths, fallback) => {
|
|
424
|
+
if (paths.length === 0)
|
|
425
|
+
return fallback;
|
|
426
|
+
const segmentsList = paths.map((p) => p.split(sep3));
|
|
427
|
+
const [first] = segmentsList;
|
|
428
|
+
if (!first)
|
|
429
|
+
return fallback;
|
|
430
|
+
const commonSegments = first.filter((segment, index) => segmentsList.every((pathSegs) => pathSegs[index] === segment));
|
|
431
|
+
return commonSegments.length ? commonSegments.join(sep3) : fallback;
|
|
432
|
+
};
|
|
433
|
+
var isDev = env2.NODE_ENV === "development";
|
|
434
|
+
var vueFeatureFlags = {
|
|
435
|
+
__VUE_OPTIONS_API__: "true",
|
|
436
|
+
__VUE_PROD_DEVTOOLS__: isDev ? "true" : "false",
|
|
437
|
+
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: isDev ? "true" : "false"
|
|
438
|
+
};
|
|
181
439
|
var build = async ({
|
|
182
440
|
buildDirectory = "build",
|
|
183
|
-
assetsDirectory,
|
|
441
|
+
assetsDirectory = "assets",
|
|
184
442
|
reactDirectory,
|
|
185
443
|
htmlDirectory,
|
|
186
444
|
htmxDirectory,
|
|
187
445
|
svelteDirectory,
|
|
446
|
+
vueDirectory,
|
|
188
447
|
tailwind,
|
|
189
448
|
options
|
|
190
449
|
}) => {
|
|
191
450
|
const buildStart = performance.now();
|
|
192
|
-
const
|
|
193
|
-
const buildPath = validateSafePath(buildDirectory,
|
|
194
|
-
const assetsPath = assetsDirectory && validateSafePath(assetsDirectory,
|
|
195
|
-
const
|
|
196
|
-
const
|
|
197
|
-
const
|
|
198
|
-
const
|
|
199
|
-
const
|
|
200
|
-
const
|
|
201
|
-
const
|
|
202
|
-
const
|
|
203
|
-
const
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
451
|
+
const projectRoot3 = cwd3();
|
|
452
|
+
const buildPath = validateSafePath(buildDirectory, projectRoot3);
|
|
453
|
+
const assetsPath = assetsDirectory && validateSafePath(assetsDirectory, projectRoot3);
|
|
454
|
+
const reactDir = reactDirectory && validateSafePath(reactDirectory, projectRoot3);
|
|
455
|
+
const htmlDir = htmlDirectory && validateSafePath(htmlDirectory, projectRoot3);
|
|
456
|
+
const htmxDir = htmxDirectory && validateSafePath(htmxDirectory, projectRoot3);
|
|
457
|
+
const svelteDir = svelteDirectory && validateSafePath(svelteDirectory, projectRoot3);
|
|
458
|
+
const vueDir = vueDirectory && validateSafePath(vueDirectory, projectRoot3);
|
|
459
|
+
const reactIndexesPath = reactDir && join4(reactDir, "indexes");
|
|
460
|
+
const reactPagesPath = reactDir && join4(reactDir, "pages");
|
|
461
|
+
const htmlPagesPath = htmlDir && join4(htmlDir, "pages");
|
|
462
|
+
const htmlScriptsPath = htmlDir && join4(htmlDir, "scripts");
|
|
463
|
+
const sveltePagesPath = svelteDir && join4(svelteDir, "pages");
|
|
464
|
+
const vuePagesPath = vueDir && join4(vueDir, "pages");
|
|
465
|
+
const frontends = [reactDir, htmlDir, htmxDir, svelteDir, vueDir].filter(Boolean);
|
|
466
|
+
const isSingle = frontends.length === 1;
|
|
467
|
+
let serverOutDir;
|
|
468
|
+
if (svelteDir)
|
|
469
|
+
serverOutDir = join4(buildPath, basename4(svelteDir), "pages");
|
|
470
|
+
else if (vueDir)
|
|
471
|
+
serverOutDir = join4(buildPath, basename4(vueDir), "pages");
|
|
472
|
+
let serverRoot;
|
|
473
|
+
if (svelteDir)
|
|
474
|
+
serverRoot = join4(svelteDir, "pages");
|
|
475
|
+
else if (vueDir)
|
|
476
|
+
serverRoot = join4(vueDir, "pages");
|
|
215
477
|
await rm2(buildPath, { force: true, recursive: true });
|
|
216
|
-
await
|
|
217
|
-
if (reactIndexesPath && reactPagesPath)
|
|
478
|
+
await mkdir4(buildPath);
|
|
479
|
+
if (reactIndexesPath && reactPagesPath)
|
|
218
480
|
await generateReactIndexFiles(reactPagesPath, reactIndexesPath);
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
await cp(assetsPath, join3(buildPath, "assets"), {
|
|
481
|
+
if (assetsPath)
|
|
482
|
+
await cp(assetsPath, join4(buildPath, "assets"), {
|
|
222
483
|
force: true,
|
|
223
484
|
recursive: true
|
|
224
485
|
});
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
await
|
|
228
|
-
await cp(htmxPath, join3(buildPath, "htmx"), {
|
|
486
|
+
if (htmxDir) {
|
|
487
|
+
await mkdir4(join4(buildPath, "htmx"));
|
|
488
|
+
await cp(htmxDir, join4(buildPath, "htmx"), {
|
|
229
489
|
force: true,
|
|
230
490
|
recursive: true
|
|
231
491
|
});
|
|
232
492
|
}
|
|
233
|
-
if (tailwind)
|
|
234
|
-
await $`bunx @tailwindcss/cli -i ${tailwind.input} -o ${
|
|
235
|
-
|
|
236
|
-
const
|
|
237
|
-
const
|
|
238
|
-
const
|
|
239
|
-
const
|
|
240
|
-
const
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
493
|
+
if (tailwind)
|
|
494
|
+
await $`bunx @tailwindcss/cli -i ${tailwind.input} -o ${join4(buildPath, tailwind.output)}`;
|
|
495
|
+
const reactEntries = reactIndexesPath ? await scanEntryPoints(reactIndexesPath, "*.tsx") : [];
|
|
496
|
+
const htmlEntries = htmlScriptsPath ? await scanEntryPoints(htmlScriptsPath, "*.{js,ts}") : [];
|
|
497
|
+
const svelteEntries = sveltePagesPath ? await scanEntryPoints(sveltePagesPath, "*.svelte") : [];
|
|
498
|
+
const vueEntries = vuePagesPath ? await scanEntryPoints(vuePagesPath, "*.vue") : [];
|
|
499
|
+
const htmlCssEntries = htmlDir ? await scanEntryPoints(join4(htmlDir, "styles"), "*.css") : [];
|
|
500
|
+
const reactCssEntries = reactDir ? await scanEntryPoints(join4(reactDir, "styles"), "*.css") : [];
|
|
501
|
+
const svelteCssEntries = svelteDir ? await scanEntryPoints(join4(svelteDir, "styles"), "*.css") : [];
|
|
502
|
+
const { svelteServerPaths, svelteClientPaths } = svelteDir ? await compileSvelte(svelteEntries, svelteDir) : { svelteClientPaths: [], svelteServerPaths: [] };
|
|
503
|
+
const { vueServerPaths, vueIndexPaths, vueCssPaths } = vueDir ? await compileVue(vueEntries, vueDir) : { vueCssPaths: [], vueIndexPaths: [], vueServerPaths: [] };
|
|
504
|
+
const serverEntryPoints = [...svelteServerPaths, ...vueServerPaths];
|
|
505
|
+
const clientEntryPoints = [
|
|
506
|
+
...reactEntries,
|
|
507
|
+
...svelteClientPaths,
|
|
508
|
+
...htmlEntries,
|
|
509
|
+
...vueIndexPaths
|
|
244
510
|
];
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
511
|
+
const cssEntryPoints = [
|
|
512
|
+
...vueCssPaths,
|
|
513
|
+
...reactCssEntries,
|
|
514
|
+
...svelteCssEntries,
|
|
515
|
+
...htmlCssEntries
|
|
516
|
+
];
|
|
517
|
+
if (serverEntryPoints.length === 0 && clientEntryPoints.length === 0) {
|
|
518
|
+
console.warn("No entry points found, manifest will be empty.");
|
|
519
|
+
return {};
|
|
520
|
+
}
|
|
521
|
+
let serverLogs = [];
|
|
522
|
+
let serverOutputs = [];
|
|
523
|
+
if (serverEntryPoints.length > 0) {
|
|
524
|
+
const { logs, outputs } = await bunBuild({
|
|
525
|
+
entrypoints: serverEntryPoints,
|
|
526
|
+
format: "esm",
|
|
527
|
+
naming: `[dir]/[name].[hash].[ext]`,
|
|
528
|
+
outdir: serverOutDir,
|
|
529
|
+
root: serverRoot,
|
|
530
|
+
target: "bun"
|
|
531
|
+
}).catch((err) => {
|
|
532
|
+
console.error("Server build failed:", err);
|
|
533
|
+
exit(1);
|
|
534
|
+
});
|
|
535
|
+
serverLogs = logs;
|
|
536
|
+
serverOutputs = outputs;
|
|
248
537
|
}
|
|
249
|
-
const { logs: serverLogs, outputs: serverOutputs } = await bunBuild({
|
|
250
|
-
entrypoints: serverEntryPoints,
|
|
251
|
-
format: "esm",
|
|
252
|
-
naming: `[dir]/[name].[hash].[ext]`,
|
|
253
|
-
outdir: serverOutDir,
|
|
254
|
-
root: serverRoot,
|
|
255
|
-
target: "bun"
|
|
256
|
-
}).catch((error) => {
|
|
257
|
-
console.error("Server build failed:", error);
|
|
258
|
-
exit(1);
|
|
259
|
-
});
|
|
260
538
|
let clientLogs = [];
|
|
261
539
|
let clientOutputs = [];
|
|
262
|
-
if (
|
|
540
|
+
if (clientEntryPoints.length > 0) {
|
|
541
|
+
const roots = [reactDir, svelteDir, htmlDir, vueDir].filter((dir) => Boolean(dir));
|
|
542
|
+
const clientRoot = isSingle ? roots[0] ?? projectRoot3 : commonAncestor(roots, projectRoot3);
|
|
263
543
|
const { logs, outputs } = await bunBuild({
|
|
264
|
-
|
|
544
|
+
define: vueDirectory ? vueFeatureFlags : undefined,
|
|
545
|
+
entrypoints: clientEntryPoints,
|
|
265
546
|
format: "esm",
|
|
266
547
|
naming: `[dir]/[name].[hash].[ext]`,
|
|
267
|
-
outdir:
|
|
268
|
-
root:
|
|
548
|
+
outdir: buildPath,
|
|
549
|
+
root: clientRoot,
|
|
269
550
|
target: "browser"
|
|
270
|
-
}).catch((
|
|
271
|
-
console.error("Client build failed:",
|
|
551
|
+
}).catch((err) => {
|
|
552
|
+
console.error("Client build failed:", err);
|
|
272
553
|
exit(1);
|
|
273
554
|
});
|
|
274
555
|
clientLogs = logs;
|
|
275
556
|
clientOutputs = outputs;
|
|
276
557
|
}
|
|
277
|
-
|
|
558
|
+
let cssLogs = [];
|
|
559
|
+
let cssOutputs = [];
|
|
560
|
+
if (cssEntryPoints.length > 0) {
|
|
561
|
+
const { logs, outputs } = await bunBuild({
|
|
562
|
+
entrypoints: cssEntryPoints,
|
|
563
|
+
naming: `[name].[hash].[ext]`,
|
|
564
|
+
outdir: join4(buildPath, basename4(assetsPath), "css"),
|
|
565
|
+
target: "browser"
|
|
566
|
+
}).catch((err) => {
|
|
567
|
+
console.error("CSS build failed:", err);
|
|
568
|
+
exit(1);
|
|
569
|
+
});
|
|
570
|
+
cssLogs = logs;
|
|
571
|
+
cssOutputs = outputs;
|
|
572
|
+
}
|
|
573
|
+
const allLogs = [...serverLogs, ...clientLogs, ...cssLogs];
|
|
574
|
+
for (const log of allLogs) {
|
|
278
575
|
if (log.level === "error")
|
|
279
576
|
console.error(log);
|
|
280
577
|
else if (log.level === "warning")
|
|
281
578
|
console.warn(log);
|
|
282
579
|
else
|
|
283
580
|
console.info(log);
|
|
284
|
-
}
|
|
285
|
-
const manifest = generateManifest([...serverOutputs, ...clientOutputs], buildPath
|
|
286
|
-
if (
|
|
287
|
-
const outputHtmlPages =
|
|
288
|
-
await
|
|
581
|
+
}
|
|
582
|
+
const manifest = generateManifest([...serverOutputs, ...clientOutputs, ...cssOutputs], buildPath);
|
|
583
|
+
if (htmlDir && htmlPagesPath) {
|
|
584
|
+
const outputHtmlPages = join4(buildPath, basename4(htmlDir), "pages");
|
|
585
|
+
await mkdir4(outputHtmlPages, { recursive: true });
|
|
289
586
|
await cp(htmlPagesPath, outputHtmlPages, {
|
|
290
587
|
force: true,
|
|
291
588
|
recursive: true
|
|
292
589
|
});
|
|
293
|
-
await
|
|
590
|
+
await updateHTMLAssetPaths(manifest, outputHtmlPages);
|
|
294
591
|
}
|
|
295
|
-
if (!options?.preserveIntermediateFiles &&
|
|
296
|
-
await rm2(
|
|
592
|
+
if (!options?.preserveIntermediateFiles && svelteDir) {
|
|
593
|
+
await rm2(join4(svelteDir, "indexes"), { force: true, recursive: true });
|
|
594
|
+
await rm2(join4(svelteDir, "client"), { force: true, recursive: true });
|
|
595
|
+
await Promise.all(svelteServerPaths.map((path) => rm2(path, { force: true })));
|
|
596
|
+
await rm2(join4(svelteDir, "pages", "example"), {
|
|
297
597
|
force: true,
|
|
298
598
|
recursive: true
|
|
299
599
|
});
|
|
300
|
-
|
|
600
|
+
}
|
|
601
|
+
if (!options?.preserveIntermediateFiles && vueDir) {
|
|
602
|
+
await rm2(join4(vueDir, "indexes"), { force: true, recursive: true });
|
|
603
|
+
await rm2(join4(vueDir, "client"), { force: true, recursive: true });
|
|
604
|
+
await rm2(join4(vueDir, "styles"), { force: true, recursive: true });
|
|
605
|
+
await Promise.all(vueServerPaths.map((path) => rm2(path, { force: true })));
|
|
606
|
+
await rm2(join4(vueDir, "pages", "example"), {
|
|
301
607
|
force: true,
|
|
302
608
|
recursive: true
|
|
303
609
|
});
|
|
304
|
-
await Promise.all(svelteServerPaths.map((filePath) => rm2(filePath, { force: true })));
|
|
305
610
|
}
|
|
306
|
-
if (!options?.preserveIntermediateFiles && reactIndexesPath)
|
|
611
|
+
if (!options?.preserveIntermediateFiles && reactIndexesPath)
|
|
307
612
|
await rm2(reactIndexesPath, { force: true, recursive: true });
|
|
308
|
-
}
|
|
309
613
|
console.log(`Build completed in ${getDurationString(performance.now() - buildStart)}`);
|
|
310
614
|
return manifest;
|
|
311
615
|
};
|
|
312
616
|
// src/core/pageHandlers.ts
|
|
313
|
-
var {file:
|
|
617
|
+
var {file: file3 } = globalThis.Bun;
|
|
314
618
|
import { createElement } from "react";
|
|
315
619
|
import { renderToReadableStream as renderReactToReadableStream } from "react-dom/server";
|
|
620
|
+
import { createSSRApp, h } from "vue";
|
|
621
|
+
import { renderToWebStream as renderVueToWebStream } from "vue/server-renderer";
|
|
316
622
|
|
|
317
623
|
// src/svelte/renderToReadableStream.ts
|
|
318
624
|
import { render } from "svelte/server";
|
|
@@ -326,7 +632,10 @@ var ESCAPE_LOOKUP = {
|
|
|
326
632
|
">": "\\u003E"
|
|
327
633
|
};
|
|
328
634
|
var ESCAPE_REGEX = /[&><\u2028\u2029]/g;
|
|
329
|
-
var escapeScriptContent = (content) => content.replace(ESCAPE_REGEX, (char) =>
|
|
635
|
+
var escapeScriptContent = (content) => content.replace(ESCAPE_REGEX, (char) => {
|
|
636
|
+
const escaped = ESCAPE_LOOKUP[char];
|
|
637
|
+
return escaped !== undefined ? escaped : char;
|
|
638
|
+
});
|
|
330
639
|
|
|
331
640
|
// src/svelte/renderToReadableStream.ts
|
|
332
641
|
var renderToReadableStream = async (component, props, {
|
|
@@ -382,26 +691,54 @@ var handleReactPageRequest = async (pageComponent, index, ...props) => {
|
|
|
382
691
|
headers: { "Content-Type": "text/html" }
|
|
383
692
|
});
|
|
384
693
|
};
|
|
385
|
-
var handleSveltePageRequest = async (
|
|
386
|
-
const componentPath = PageComponent.toString();
|
|
387
|
-
const pathSegments = componentPath.split("/");
|
|
388
|
-
const lastSegment = pathSegments[pathSegments.length - 1] ?? "";
|
|
389
|
-
const componentName = lastSegment.replace(/\.svelte$/, "");
|
|
390
|
-
const pagePath = manifest[componentName];
|
|
391
|
-
const indexPath = manifest[`${componentName}Index`];
|
|
694
|
+
var handleSveltePageRequest = async (_PageComponent, pagePath, indexPath, props) => {
|
|
392
695
|
const { default: ImportedPageComponent } = await import(pagePath);
|
|
393
696
|
const stream = await renderToReadableStream(ImportedPageComponent, props, {
|
|
394
|
-
bootstrapModules: [indexPath],
|
|
697
|
+
bootstrapModules: indexPath ? [indexPath] : [],
|
|
395
698
|
bootstrapScriptContent: `window.__INITIAL_PROPS__=${JSON.stringify(props)}`
|
|
396
699
|
});
|
|
397
700
|
return new Response(stream, {
|
|
398
701
|
headers: { "Content-Type": "text/html" }
|
|
399
702
|
});
|
|
400
703
|
};
|
|
401
|
-
var
|
|
704
|
+
var handleVuePageRequest = async (_PageComponent, pagePath, indexPath, headTag = "<head></head>", ...props) => {
|
|
705
|
+
const [maybeProps] = props;
|
|
706
|
+
const { default: ImportedPageComponent } = await import(pagePath);
|
|
707
|
+
const app = createSSRApp({
|
|
708
|
+
render: () => h(ImportedPageComponent, maybeProps ?? {})
|
|
709
|
+
});
|
|
710
|
+
const bodyStream = renderVueToWebStream(app);
|
|
711
|
+
const head = `<!DOCTYPE html><html>${headTag}<body><div id="root">`;
|
|
712
|
+
const tail = `</div><script>window.__INITIAL_PROPS__=${JSON.stringify(maybeProps ?? {})}</script><script type="module" src="${indexPath}"></script></body></html>`;
|
|
713
|
+
const stream = new ReadableStream({
|
|
714
|
+
start(controller) {
|
|
715
|
+
controller.enqueue(head);
|
|
716
|
+
const reader = bodyStream.getReader();
|
|
717
|
+
const pumpLoop = () => {
|
|
718
|
+
reader.read().then(({ done, value }) => done ? (controller.enqueue(tail), controller.close()) : (controller.enqueue(value), pumpLoop())).catch((err) => controller.error(err));
|
|
719
|
+
};
|
|
720
|
+
pumpLoop();
|
|
721
|
+
}
|
|
722
|
+
});
|
|
723
|
+
return new Response(stream, {
|
|
724
|
+
headers: { "Content-Type": "text/html" }
|
|
725
|
+
});
|
|
726
|
+
};
|
|
727
|
+
var handleHTMLPageRequest = (html) => file3(html);
|
|
728
|
+
var handlePageRequest = (PageComponent, ...props) => {
|
|
729
|
+
console.log("handlePageRequest coming soon.", PageComponent, props);
|
|
730
|
+
};
|
|
731
|
+
// src/core/lookup.ts
|
|
732
|
+
var asset = (manifest, name) => {
|
|
733
|
+
const assetPath = manifest[name];
|
|
734
|
+
if (assetPath === undefined) {
|
|
735
|
+
throw new Error(`Asset "${name}" not found in manifest.`);
|
|
736
|
+
}
|
|
737
|
+
return assetPath;
|
|
738
|
+
};
|
|
402
739
|
// src/plugins/networkingPlugin.ts
|
|
403
740
|
import { argv } from "process";
|
|
404
|
-
var {env:
|
|
741
|
+
var {env: env3 } = globalThis.Bun;
|
|
405
742
|
|
|
406
743
|
// src/utils/networking.ts
|
|
407
744
|
import os from "os";
|
|
@@ -416,8 +753,8 @@ var getLocalIPAddress = () => {
|
|
|
416
753
|
};
|
|
417
754
|
|
|
418
755
|
// src/plugins/networkingPlugin.ts
|
|
419
|
-
var host =
|
|
420
|
-
var port =
|
|
756
|
+
var host = env3.HOST ?? "localhost";
|
|
757
|
+
var port = env3.PORT ?? DEFAULT_PORT;
|
|
421
758
|
var localIP;
|
|
422
759
|
var args = argv;
|
|
423
760
|
var hostFlag = args.includes("--host");
|
|
@@ -440,15 +777,37 @@ var networkingPlugin = (app) => app.listen({
|
|
|
440
777
|
var pageRouterPlugin = () => {
|
|
441
778
|
console.log("Page Router Plugin Not Implemented Yet");
|
|
442
779
|
};
|
|
780
|
+
// src/utils/generateHeadElement.ts
|
|
781
|
+
var generateHeadElement = ({
|
|
782
|
+
cssPath,
|
|
783
|
+
title = "AbsoluteJS",
|
|
784
|
+
description = "A page created using AbsoluteJS",
|
|
785
|
+
font,
|
|
786
|
+
icon = "/assets/ico/favicon.ico"
|
|
787
|
+
} = {}) => `<head>
|
|
788
|
+
<meta charset="UTF-8">
|
|
789
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
790
|
+
<title>${title}</title>
|
|
791
|
+
<meta name="description" content="${description}">
|
|
792
|
+
<link rel="icon" href="${icon}" type="image/x-icon">
|
|
793
|
+
${font ? `<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
794
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
795
|
+
<link href="https://fonts.googleapis.com/css2?family=${font}:wght@100..900&display=swap" rel="stylesheet">` : ""}
|
|
796
|
+
${cssPath ? `<link rel="stylesheet" href="${cssPath}" type="text/css">` : ""}
|
|
797
|
+
</head>`;
|
|
443
798
|
export {
|
|
444
|
-
|
|
799
|
+
updateHTMLAssetPaths,
|
|
445
800
|
pageRouterPlugin,
|
|
446
801
|
networkingPlugin,
|
|
802
|
+
handleVuePageRequest,
|
|
447
803
|
handleSveltePageRequest,
|
|
448
804
|
handleReactPageRequest,
|
|
805
|
+
handlePageRequest,
|
|
449
806
|
handleHTMLPageRequest,
|
|
450
807
|
getLocalIPAddress,
|
|
808
|
+
generateHeadElement,
|
|
451
809
|
build,
|
|
810
|
+
asset,
|
|
452
811
|
TWO_THIRDS,
|
|
453
812
|
TIME_PRECISION,
|
|
454
813
|
SECONDS_IN_A_MINUTE,
|
|
@@ -461,5 +820,5 @@ export {
|
|
|
461
820
|
DEFAULT_CHUNK_SIZE
|
|
462
821
|
};
|
|
463
822
|
|
|
464
|
-
//# debugId=
|
|
823
|
+
//# debugId=919FA38EE8B07AC264756E2164756E21
|
|
465
824
|
//# sourceMappingURL=index.js.map
|