@blinkk/root 1.0.0-beta.6 → 1.0.0-beta.61
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/bin/root.js +4 -0
- package/dist/chunk-6F72PDTR.js +1289 -0
- package/dist/chunk-6F72PDTR.js.map +1 -0
- package/dist/{chunk-WVRC46JG.js → chunk-DXD5LKU3.js} +18 -18
- package/dist/chunk-DXD5LKU3.js.map +1 -0
- package/dist/{chunk-WTSNW7BB.js → chunk-HQXIHYDN.js} +1 -1
- package/dist/chunk-HQXIHYDN.js.map +1 -0
- package/dist/{chunk-DTEQ2AIW.js → chunk-QKBMWK5B.js} +1 -1
- package/dist/chunk-QKBMWK5B.js.map +1 -0
- package/dist/chunk-QMEBIZAR.js +183 -0
- package/dist/chunk-QMEBIZAR.js.map +1 -0
- package/dist/{chunk-LTSJAEBG.js → chunk-SDT4J6VY.js} +18 -6
- package/dist/chunk-SDT4J6VY.js.map +1 -0
- package/dist/cli.d.ts +14 -4
- package/dist/cli.js +12 -1101
- package/dist/cli.js.map +1 -1
- package/dist/core.d.ts +10 -7
- package/dist/core.js +14 -13
- package/dist/core.js.map +1 -1
- package/dist/functions.d.ts +14 -0
- package/dist/functions.js +30 -0
- package/dist/functions.js.map +1 -0
- package/dist/middleware.d.ts +34 -0
- package/dist/middleware.js +17 -0
- package/dist/middleware.js.map +1 -0
- package/dist/node.d.ts +1 -1
- package/dist/node.js +2 -2
- package/dist/render.d.ts +1 -1
- package/dist/render.js +429 -228
- package/dist/render.js.map +1 -1
- package/dist/{types-47b9b530.d.ts → types-ca13e626.d.ts} +161 -34
- package/package.json +40 -4
- package/dist/chunk-DTEQ2AIW.js.map +0 -1
- package/dist/chunk-LTSJAEBG.js.map +0 -1
- package/dist/chunk-WTSNW7BB.js.map +0 -1
- package/dist/chunk-WVRC46JG.js.map +0 -1
|
@@ -0,0 +1,1289 @@
|
|
|
1
|
+
import {
|
|
2
|
+
rootProjectMiddleware,
|
|
3
|
+
sessionMiddleware,
|
|
4
|
+
trailingSlashMiddleware
|
|
5
|
+
} from "./chunk-QMEBIZAR.js";
|
|
6
|
+
import {
|
|
7
|
+
copyGlob,
|
|
8
|
+
createViteServer,
|
|
9
|
+
dirExists,
|
|
10
|
+
directoryContains,
|
|
11
|
+
fileExists,
|
|
12
|
+
isDirectory,
|
|
13
|
+
isJsFile,
|
|
14
|
+
loadJson,
|
|
15
|
+
loadRootConfig,
|
|
16
|
+
makeDir,
|
|
17
|
+
rmDir,
|
|
18
|
+
writeFile
|
|
19
|
+
} from "./chunk-SDT4J6VY.js";
|
|
20
|
+
import {
|
|
21
|
+
configureServerPlugins,
|
|
22
|
+
getVitePlugins
|
|
23
|
+
} from "./chunk-QKBMWK5B.js";
|
|
24
|
+
import {
|
|
25
|
+
htmlMinify,
|
|
26
|
+
htmlPretty,
|
|
27
|
+
isValidTagName,
|
|
28
|
+
parseTagNames
|
|
29
|
+
} from "./chunk-DXD5LKU3.js";
|
|
30
|
+
|
|
31
|
+
// src/cli/commands/build.ts
|
|
32
|
+
import path3 from "node:path";
|
|
33
|
+
import { fileURLToPath } from "node:url";
|
|
34
|
+
import fsExtra from "fs-extra";
|
|
35
|
+
import { dim, cyan } from "kleur/colors";
|
|
36
|
+
import glob2 from "tiny-glob";
|
|
37
|
+
import { build as viteBuild } from "vite";
|
|
38
|
+
|
|
39
|
+
// src/node/element-graph.ts
|
|
40
|
+
import fs from "node:fs";
|
|
41
|
+
import path from "node:path";
|
|
42
|
+
import glob from "tiny-glob";
|
|
43
|
+
import { searchForWorkspaceRoot } from "vite";
|
|
44
|
+
var ElementGraph = class {
|
|
45
|
+
constructor(sourceFiles) {
|
|
46
|
+
this.sourceFiles = {};
|
|
47
|
+
this.deps = {};
|
|
48
|
+
this.sourceFiles = sourceFiles;
|
|
49
|
+
}
|
|
50
|
+
toJson() {
|
|
51
|
+
for (const tagName in this.sourceFiles) {
|
|
52
|
+
this.deps[tagName] ??= this.parseDepsFromSource(tagName);
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
sourceFiles: this.sourceFiles,
|
|
56
|
+
deps: this.deps
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
static fromJson(data) {
|
|
60
|
+
const graph = new ElementGraph(data.sourceFiles);
|
|
61
|
+
graph.deps = data.deps;
|
|
62
|
+
return graph;
|
|
63
|
+
}
|
|
64
|
+
getDeps(tagName, visited) {
|
|
65
|
+
visited ??= /* @__PURE__ */ new Set();
|
|
66
|
+
if (visited.has(tagName)) {
|
|
67
|
+
return [];
|
|
68
|
+
}
|
|
69
|
+
visited.add(tagName);
|
|
70
|
+
this.deps[tagName] ??= this.parseDepsFromSource(tagName);
|
|
71
|
+
const deps = new Set(this.deps[tagName]);
|
|
72
|
+
for (const depTagName of this.deps[tagName]) {
|
|
73
|
+
for (const childDep of this.getDeps(depTagName, visited)) {
|
|
74
|
+
deps.add(childDep);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return Array.from(deps);
|
|
78
|
+
}
|
|
79
|
+
parseDepsFromSource(tagName) {
|
|
80
|
+
const srcFile = this.sourceFiles[tagName];
|
|
81
|
+
if (!srcFile) {
|
|
82
|
+
throw new Error(`could not find file path for tagName <${tagName}>`);
|
|
83
|
+
}
|
|
84
|
+
const src = fs.readFileSync(srcFile.filePath, "utf-8");
|
|
85
|
+
const tagNames = parseTagNames(src);
|
|
86
|
+
const deps = /* @__PURE__ */ new Set();
|
|
87
|
+
for (const depTagName of tagNames) {
|
|
88
|
+
if (depTagName !== tagName && depTagName in this.sourceFiles) {
|
|
89
|
+
deps.add(depTagName);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return Array.from(deps);
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
async function getElements(rootConfig) {
|
|
96
|
+
var _a;
|
|
97
|
+
const rootDir = rootConfig.rootDir;
|
|
98
|
+
const elementsDirs = getElementsDirs(rootConfig);
|
|
99
|
+
const excludePatterns = ((_a = rootConfig.elements) == null ? void 0 : _a.exclude) || [];
|
|
100
|
+
const excludeElement = (moduleId) => {
|
|
101
|
+
return excludePatterns.some((pattern) => Boolean(moduleId.match(pattern)));
|
|
102
|
+
};
|
|
103
|
+
const elementFilePaths = {};
|
|
104
|
+
for (const dirPath of elementsDirs) {
|
|
105
|
+
if (await isDirectory(dirPath)) {
|
|
106
|
+
const files = await glob("**/*", { cwd: dirPath });
|
|
107
|
+
files.forEach((file) => {
|
|
108
|
+
const parts = path.parse(file);
|
|
109
|
+
if (isJsFile(parts.base) && isValidTagName(parts.name)) {
|
|
110
|
+
const tagName = parts.name;
|
|
111
|
+
const filePath = path.join(dirPath, file);
|
|
112
|
+
const relPath = path.relative(rootDir, filePath);
|
|
113
|
+
if (!excludeElement(relPath)) {
|
|
114
|
+
elementFilePaths[tagName] = { filePath, relPath };
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
const graph = new ElementGraph(elementFilePaths);
|
|
121
|
+
return graph;
|
|
122
|
+
}
|
|
123
|
+
function getElementsDirs(rootConfig) {
|
|
124
|
+
var _a;
|
|
125
|
+
const rootDir = rootConfig.rootDir;
|
|
126
|
+
const workspaceRoot = searchForWorkspaceRoot(rootDir);
|
|
127
|
+
const elementsDirs = [path.join(rootDir, "elements")];
|
|
128
|
+
const elementsInclude = ((_a = rootConfig.elements) == null ? void 0 : _a.include) || [];
|
|
129
|
+
for (const dirPath of elementsInclude) {
|
|
130
|
+
const elementsDir = path.resolve(rootDir, dirPath);
|
|
131
|
+
if (!directoryContains(rootDir, elementsDir)) {
|
|
132
|
+
throw new Error(
|
|
133
|
+
`the elements dir (${dirPath}) should be within the project's workspace (${workspaceRoot})`
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
elementsDirs.push(elementsDir);
|
|
137
|
+
}
|
|
138
|
+
return elementsDirs;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// src/render/asset-map/build-asset-map.ts
|
|
142
|
+
import fs2 from "node:fs";
|
|
143
|
+
import path2 from "node:path";
|
|
144
|
+
var BuildAssetMap = class {
|
|
145
|
+
constructor(rootConfig) {
|
|
146
|
+
this.rootConfig = rootConfig;
|
|
147
|
+
this.srcToAsset = /* @__PURE__ */ new Map();
|
|
148
|
+
}
|
|
149
|
+
async get(src) {
|
|
150
|
+
const asset = this.srcToAsset.get(src);
|
|
151
|
+
if (asset) {
|
|
152
|
+
return asset;
|
|
153
|
+
}
|
|
154
|
+
const realSrc = realPathRelativeTo(this.rootConfig.rootDir, src);
|
|
155
|
+
if (realSrc !== src) {
|
|
156
|
+
const asset2 = this.srcToAsset.get(realSrc);
|
|
157
|
+
if (asset2) {
|
|
158
|
+
return asset2;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
console.log(`could not find build asset: ${src}`);
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
add(asset) {
|
|
165
|
+
this.srcToAsset.set(asset.src, asset);
|
|
166
|
+
}
|
|
167
|
+
toJson() {
|
|
168
|
+
const result = {};
|
|
169
|
+
for (const src of this.srcToAsset.keys()) {
|
|
170
|
+
result[src] = this.srcToAsset.get(src).toJson();
|
|
171
|
+
}
|
|
172
|
+
return result;
|
|
173
|
+
}
|
|
174
|
+
static fromViteManifest(rootConfig, clientManifest, elementsGraph) {
|
|
175
|
+
const assetMap = new BuildAssetMap(rootConfig);
|
|
176
|
+
const elementFiles = /* @__PURE__ */ new Set();
|
|
177
|
+
Object.values(elementsGraph.sourceFiles).forEach((elementSource) => {
|
|
178
|
+
elementFiles.add(elementSource.relPath);
|
|
179
|
+
const realSrc = realPathRelativeTo(
|
|
180
|
+
rootConfig.rootDir,
|
|
181
|
+
elementSource.relPath
|
|
182
|
+
);
|
|
183
|
+
if (realSrc !== elementSource.filePath) {
|
|
184
|
+
elementFiles.add(realSrc);
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
Object.keys(clientManifest).forEach((manifestKey) => {
|
|
188
|
+
const src = manifestKey;
|
|
189
|
+
const manifestChunk = clientManifest[manifestKey];
|
|
190
|
+
const isElement = elementFiles.has(src);
|
|
191
|
+
const assetUrl = src.startsWith("routes/") && isJsFile(src) ? "" : `/${manifestChunk.file}`;
|
|
192
|
+
const assetData = {
|
|
193
|
+
src,
|
|
194
|
+
assetUrl,
|
|
195
|
+
importedModules: manifestChunk.imports || [],
|
|
196
|
+
importedCss: (manifestChunk.css || []).map((relPath) => `/${relPath}`),
|
|
197
|
+
isElement
|
|
198
|
+
};
|
|
199
|
+
assetMap.add(new BuildAsset(assetMap, assetData));
|
|
200
|
+
});
|
|
201
|
+
return assetMap;
|
|
202
|
+
}
|
|
203
|
+
static fromRootManifest(rootConfig, rootManifest) {
|
|
204
|
+
const assetMap = new BuildAssetMap(rootConfig);
|
|
205
|
+
Object.keys(rootManifest).forEach((moduleId) => {
|
|
206
|
+
const assetData = rootManifest[moduleId];
|
|
207
|
+
assetMap.add(new BuildAsset(assetMap, assetData));
|
|
208
|
+
});
|
|
209
|
+
return assetMap;
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
function realPathRelativeTo(rootDir, src) {
|
|
213
|
+
const fullPath = path2.resolve(rootDir, src);
|
|
214
|
+
if (!fs2.existsSync(fullPath)) {
|
|
215
|
+
return src;
|
|
216
|
+
}
|
|
217
|
+
const realpath = fs2.realpathSync(path2.resolve(rootDir, src));
|
|
218
|
+
return path2.relative(rootDir, realpath);
|
|
219
|
+
}
|
|
220
|
+
var BuildAsset = class {
|
|
221
|
+
constructor(assetMap, assetData) {
|
|
222
|
+
this.assetMap = assetMap;
|
|
223
|
+
this.src = assetData.src;
|
|
224
|
+
this.assetUrl = assetData.assetUrl;
|
|
225
|
+
this.importedModules = assetData.importedModules;
|
|
226
|
+
this.importedCss = assetData.importedCss;
|
|
227
|
+
this.isElement = assetData.isElement;
|
|
228
|
+
}
|
|
229
|
+
async getCssDeps() {
|
|
230
|
+
const visited = /* @__PURE__ */ new Set();
|
|
231
|
+
const deps = /* @__PURE__ */ new Set();
|
|
232
|
+
await this.collectCss(this, deps, visited);
|
|
233
|
+
return Array.from(deps);
|
|
234
|
+
}
|
|
235
|
+
async getJsDeps() {
|
|
236
|
+
const visited = /* @__PURE__ */ new Set();
|
|
237
|
+
const deps = /* @__PURE__ */ new Set();
|
|
238
|
+
await this.collectJs(this, deps, visited);
|
|
239
|
+
return Array.from(deps);
|
|
240
|
+
}
|
|
241
|
+
async collectJs(asset, urls, visited) {
|
|
242
|
+
if (!asset) {
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
if (!asset.src) {
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
if (visited.has(asset.src)) {
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
visited.add(asset.src);
|
|
252
|
+
if (asset.isElement) {
|
|
253
|
+
urls.add(asset.assetUrl);
|
|
254
|
+
}
|
|
255
|
+
await Promise.all(
|
|
256
|
+
asset.importedModules.map(async (src) => {
|
|
257
|
+
const importedAsset = await this.assetMap.get(src);
|
|
258
|
+
this.collectJs(importedAsset, urls, visited);
|
|
259
|
+
})
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
async collectCss(asset, urls, visited) {
|
|
263
|
+
if (!asset) {
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
if (!asset.src) {
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
if (visited.has(asset.src)) {
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
visited.add(asset.src);
|
|
273
|
+
if (asset.importedCss) {
|
|
274
|
+
asset.importedCss.forEach((cssUrl) => urls.add(cssUrl));
|
|
275
|
+
}
|
|
276
|
+
await Promise.all(
|
|
277
|
+
asset.importedModules.map(async (moduleId) => {
|
|
278
|
+
const importedAsset = await this.assetMap.get(moduleId);
|
|
279
|
+
this.collectCss(importedAsset, urls, visited);
|
|
280
|
+
})
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
toJson() {
|
|
284
|
+
return {
|
|
285
|
+
src: this.src,
|
|
286
|
+
assetUrl: this.assetUrl,
|
|
287
|
+
importedModules: this.importedModules,
|
|
288
|
+
importedCss: this.importedCss,
|
|
289
|
+
isElement: this.isElement
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
// src/utils/batch.ts
|
|
295
|
+
async function batchAsyncCalls(data, batchSize, asyncFunction) {
|
|
296
|
+
const result = [];
|
|
297
|
+
const batches = Math.ceil(data.length / batchSize);
|
|
298
|
+
for (let i = 0; i < batches; i++) {
|
|
299
|
+
const batch = data.slice(i * batchSize, (i + 1) * batchSize);
|
|
300
|
+
const batchResults = await Promise.all(batch.map(asyncFunction));
|
|
301
|
+
result.push(...batchResults);
|
|
302
|
+
}
|
|
303
|
+
return result;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// src/cli/commands/build.ts
|
|
307
|
+
var __dirname = path3.dirname(fileURLToPath(import.meta.url));
|
|
308
|
+
async function build(rootProjectDir, options) {
|
|
309
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
310
|
+
const mode = (options == null ? void 0 : options.mode) || "production";
|
|
311
|
+
process.env.NODE_ENV = mode;
|
|
312
|
+
const rootDir = path3.resolve(rootProjectDir || process.cwd());
|
|
313
|
+
const rootConfig = await loadRootConfig(rootDir, { command: "build" });
|
|
314
|
+
const distDir = path3.join(rootDir, "dist");
|
|
315
|
+
const ssrOnly = (options == null ? void 0 : options.ssrOnly) || false;
|
|
316
|
+
console.log();
|
|
317
|
+
console.log(`${dim("\u2503")} project: ${rootDir}`);
|
|
318
|
+
console.log(`${dim("\u2503")} output: ${distDir}/html`);
|
|
319
|
+
console.log(`${dim("\u2503")} mode: ${mode}`);
|
|
320
|
+
console.log();
|
|
321
|
+
await rmDir(distDir);
|
|
322
|
+
await makeDir(distDir);
|
|
323
|
+
const routeFiles = [];
|
|
324
|
+
if (await isDirectory(path3.join(rootDir, "routes"))) {
|
|
325
|
+
const pageFiles = await glob2("routes/**/*", { cwd: rootDir });
|
|
326
|
+
pageFiles.forEach((file) => {
|
|
327
|
+
const parts = path3.parse(file);
|
|
328
|
+
if (!parts.name.startsWith("_") && isJsFile(parts.base)) {
|
|
329
|
+
routeFiles.push(path3.resolve(rootDir, file));
|
|
330
|
+
}
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
const elementGraph = await getElements(rootConfig);
|
|
334
|
+
const elements = Object.values(elementGraph.sourceFiles).map((sourceFile) => {
|
|
335
|
+
return sourceFile.filePath;
|
|
336
|
+
});
|
|
337
|
+
const bundleScripts = [];
|
|
338
|
+
if (await isDirectory(path3.join(rootDir, "bundles"))) {
|
|
339
|
+
const bundleFiles = await glob2("bundles/*", { cwd: rootDir });
|
|
340
|
+
bundleFiles.forEach((file) => {
|
|
341
|
+
const parts = path3.parse(file);
|
|
342
|
+
if (isJsFile(parts.base)) {
|
|
343
|
+
bundleScripts.push(path3.resolve(rootDir, file));
|
|
344
|
+
}
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
const rootPlugins = rootConfig.plugins || [];
|
|
348
|
+
const viteConfig = rootConfig.vite || {};
|
|
349
|
+
const vitePlugins = [
|
|
350
|
+
...viteConfig.plugins || [],
|
|
351
|
+
...getVitePlugins(rootPlugins)
|
|
352
|
+
];
|
|
353
|
+
const baseConfig = {
|
|
354
|
+
...viteConfig,
|
|
355
|
+
root: rootDir,
|
|
356
|
+
mode,
|
|
357
|
+
esbuild: {
|
|
358
|
+
...viteConfig.esbuild,
|
|
359
|
+
jsx: "automatic",
|
|
360
|
+
jsxImportSource: "preact",
|
|
361
|
+
treeShaking: true
|
|
362
|
+
},
|
|
363
|
+
plugins: vitePlugins
|
|
364
|
+
};
|
|
365
|
+
const ssrInput = {
|
|
366
|
+
render: path3.resolve(__dirname, "./render.js")
|
|
367
|
+
};
|
|
368
|
+
rootPlugins.forEach((plugin) => {
|
|
369
|
+
if (plugin.ssrInput) {
|
|
370
|
+
Object.assign(ssrInput, plugin.ssrInput());
|
|
371
|
+
}
|
|
372
|
+
});
|
|
373
|
+
const noExternalConfig = (_a = viteConfig.ssr) == null ? void 0 : _a.noExternal;
|
|
374
|
+
const noExternal = [];
|
|
375
|
+
if (noExternalConfig) {
|
|
376
|
+
if (Array.isArray(noExternalConfig)) {
|
|
377
|
+
noExternal.push(...noExternalConfig);
|
|
378
|
+
} else {
|
|
379
|
+
noExternal.push(noExternalConfig);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
await viteBuild({
|
|
383
|
+
...baseConfig,
|
|
384
|
+
publicDir: false,
|
|
385
|
+
build: {
|
|
386
|
+
...viteConfig == null ? void 0 : viteConfig.build,
|
|
387
|
+
rollupOptions: {
|
|
388
|
+
...(_b = viteConfig == null ? void 0 : viteConfig.build) == null ? void 0 : _b.rollupOptions,
|
|
389
|
+
input: ssrInput,
|
|
390
|
+
output: {
|
|
391
|
+
format: "esm",
|
|
392
|
+
chunkFileNames: "chunks/[hash].min.js",
|
|
393
|
+
assetFileNames: "assets/[name].[hash][extname]",
|
|
394
|
+
sanitizeFileName
|
|
395
|
+
}
|
|
396
|
+
},
|
|
397
|
+
outDir: path3.join(distDir, "server"),
|
|
398
|
+
ssr: true,
|
|
399
|
+
ssrManifest: false,
|
|
400
|
+
cssCodeSplit: true,
|
|
401
|
+
target: "esnext",
|
|
402
|
+
minify: false,
|
|
403
|
+
modulePreload: { polyfill: false },
|
|
404
|
+
reportCompressedSize: false
|
|
405
|
+
},
|
|
406
|
+
ssr: {
|
|
407
|
+
...viteConfig.ssr,
|
|
408
|
+
target: "node",
|
|
409
|
+
noExternal: ["@blinkk/root", ...noExternal]
|
|
410
|
+
}
|
|
411
|
+
});
|
|
412
|
+
await viteBuild({
|
|
413
|
+
...baseConfig,
|
|
414
|
+
publicDir: false,
|
|
415
|
+
build: {
|
|
416
|
+
...viteConfig == null ? void 0 : viteConfig.build,
|
|
417
|
+
rollupOptions: {
|
|
418
|
+
...(_c = viteConfig == null ? void 0 : viteConfig.build) == null ? void 0 : _c.rollupOptions,
|
|
419
|
+
input: [...routeFiles],
|
|
420
|
+
output: {
|
|
421
|
+
format: "esm",
|
|
422
|
+
entryFileNames: "assets/[name].[hash].min.js",
|
|
423
|
+
assetFileNames: "assets/[name].[hash][extname]",
|
|
424
|
+
chunkFileNames: "chunks/[hash].min.js",
|
|
425
|
+
sanitizeFileName,
|
|
426
|
+
...(_e = (_d = viteConfig == null ? void 0 : viteConfig.build) == null ? void 0 : _d.rollupOptions) == null ? void 0 : _e.output
|
|
427
|
+
}
|
|
428
|
+
},
|
|
429
|
+
outDir: path3.join(distDir, "routes"),
|
|
430
|
+
ssr: false,
|
|
431
|
+
ssrManifest: false,
|
|
432
|
+
manifest: true,
|
|
433
|
+
cssCodeSplit: true,
|
|
434
|
+
target: "esnext",
|
|
435
|
+
minify: true,
|
|
436
|
+
modulePreload: { polyfill: false },
|
|
437
|
+
reportCompressedSize: false
|
|
438
|
+
}
|
|
439
|
+
});
|
|
440
|
+
const clientInput = [...elements, ...bundleScripts];
|
|
441
|
+
if (clientInput.length > 0) {
|
|
442
|
+
await viteBuild({
|
|
443
|
+
...baseConfig,
|
|
444
|
+
publicDir: false,
|
|
445
|
+
build: {
|
|
446
|
+
...viteConfig == null ? void 0 : viteConfig.build,
|
|
447
|
+
rollupOptions: {
|
|
448
|
+
...(_f = viteConfig == null ? void 0 : viteConfig.build) == null ? void 0 : _f.rollupOptions,
|
|
449
|
+
input: [...elements, ...bundleScripts],
|
|
450
|
+
output: {
|
|
451
|
+
format: "esm",
|
|
452
|
+
entryFileNames: "assets/[name].[hash].min.js",
|
|
453
|
+
assetFileNames: "assets/[name].[hash][extname]",
|
|
454
|
+
chunkFileNames: "chunks/[hash].min.js",
|
|
455
|
+
sanitizeFileName,
|
|
456
|
+
...(_h = (_g = viteConfig == null ? void 0 : viteConfig.build) == null ? void 0 : _g.rollupOptions) == null ? void 0 : _h.output
|
|
457
|
+
}
|
|
458
|
+
},
|
|
459
|
+
outDir: path3.join(distDir, "client"),
|
|
460
|
+
ssr: false,
|
|
461
|
+
ssrManifest: false,
|
|
462
|
+
manifest: true,
|
|
463
|
+
cssCodeSplit: true,
|
|
464
|
+
target: "esnext",
|
|
465
|
+
minify: true,
|
|
466
|
+
modulePreload: { polyfill: false },
|
|
467
|
+
reportCompressedSize: false
|
|
468
|
+
}
|
|
469
|
+
});
|
|
470
|
+
} else {
|
|
471
|
+
await writeFile(path3.join(distDir, "client/manifest.json"), "{}");
|
|
472
|
+
}
|
|
473
|
+
await copyGlob(
|
|
474
|
+
"**/*.css",
|
|
475
|
+
path3.join(distDir, "routes"),
|
|
476
|
+
path3.join(distDir, "client")
|
|
477
|
+
);
|
|
478
|
+
const routesManifest = await loadJson(
|
|
479
|
+
path3.join(distDir, "routes/manifest.json")
|
|
480
|
+
);
|
|
481
|
+
const clientManifest = await loadJson(
|
|
482
|
+
path3.join(distDir, "client/manifest.json")
|
|
483
|
+
);
|
|
484
|
+
function collectRouteCss(asset, cssDeps, visited) {
|
|
485
|
+
if (!asset || !asset.file || visited.has(asset.file)) {
|
|
486
|
+
return;
|
|
487
|
+
}
|
|
488
|
+
visited.add(asset.file);
|
|
489
|
+
if (asset.css) {
|
|
490
|
+
asset.css.forEach((dep) => cssDeps.add(dep));
|
|
491
|
+
}
|
|
492
|
+
if (asset.imports) {
|
|
493
|
+
asset.imports.forEach((manifestKey) => {
|
|
494
|
+
collectRouteCss(routesManifest[manifestKey], cssDeps, visited);
|
|
495
|
+
});
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
Object.keys(routesManifest).forEach((manifestKey) => {
|
|
499
|
+
const asset = routesManifest[manifestKey];
|
|
500
|
+
if (asset.isEntry) {
|
|
501
|
+
const visited = /* @__PURE__ */ new Set();
|
|
502
|
+
const cssDeps = /* @__PURE__ */ new Set();
|
|
503
|
+
collectRouteCss(asset, cssDeps, visited);
|
|
504
|
+
asset.css = Array.from(cssDeps);
|
|
505
|
+
asset.imports = [];
|
|
506
|
+
clientManifest[manifestKey] = asset;
|
|
507
|
+
} else if (asset.file.endsWith(".css")) {
|
|
508
|
+
clientManifest[manifestKey] = asset;
|
|
509
|
+
}
|
|
510
|
+
});
|
|
511
|
+
const assetMap = BuildAssetMap.fromViteManifest(
|
|
512
|
+
rootConfig,
|
|
513
|
+
clientManifest,
|
|
514
|
+
elementGraph
|
|
515
|
+
);
|
|
516
|
+
const rootManifest = assetMap.toJson();
|
|
517
|
+
await writeFile(
|
|
518
|
+
path3.join(distDir, "client/root-manifest.json"),
|
|
519
|
+
JSON.stringify(rootManifest, null, 2)
|
|
520
|
+
);
|
|
521
|
+
const elementGraphJson = elementGraph.toJson();
|
|
522
|
+
await writeFile(
|
|
523
|
+
path3.join(distDir, "client/root-element-graph.json"),
|
|
524
|
+
JSON.stringify(elementGraphJson, null, 2)
|
|
525
|
+
);
|
|
526
|
+
const buildDir = path3.join(distDir, "html");
|
|
527
|
+
const publicDir = path3.join(rootDir, "public");
|
|
528
|
+
if (fsExtra.existsSync(path3.join(rootDir, "public"))) {
|
|
529
|
+
fsExtra.copySync(publicDir, buildDir, { dereference: true });
|
|
530
|
+
} else {
|
|
531
|
+
await makeDir(buildDir);
|
|
532
|
+
}
|
|
533
|
+
console.log("\njs/css output:");
|
|
534
|
+
await Promise.all(
|
|
535
|
+
Object.keys(rootManifest).map(async (src) => {
|
|
536
|
+
if (isRouteFile(src)) {
|
|
537
|
+
return;
|
|
538
|
+
}
|
|
539
|
+
const assetData = rootManifest[src];
|
|
540
|
+
if (!assetData.assetUrl) {
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
543
|
+
const assetRelPath = assetData.assetUrl.slice(1);
|
|
544
|
+
const assetFrom = path3.join(distDir, "client", assetRelPath);
|
|
545
|
+
const assetTo = path3.join(buildDir, assetRelPath);
|
|
546
|
+
if (!await fileExists(assetFrom)) {
|
|
547
|
+
console.log(`${assetFrom} does not exist`);
|
|
548
|
+
return;
|
|
549
|
+
}
|
|
550
|
+
await fsExtra.copy(assetFrom, assetTo);
|
|
551
|
+
printFileOutput(fileSize(assetTo), "dist/html/", assetRelPath);
|
|
552
|
+
})
|
|
553
|
+
);
|
|
554
|
+
if (!ssrOnly) {
|
|
555
|
+
const render = await import(path3.join(distDir, "server/render.js"));
|
|
556
|
+
const renderer = new render.Renderer(rootConfig, { assetMap, elementGraph });
|
|
557
|
+
const sitemap = await renderer.getSitemap();
|
|
558
|
+
console.log("\nhtml output:");
|
|
559
|
+
const batchSize = Number((options == null ? void 0 : options.concurrency) || 10);
|
|
560
|
+
await batchAsyncCalls(Object.keys(sitemap), batchSize, async (urlPath) => {
|
|
561
|
+
const { route, params } = sitemap[urlPath];
|
|
562
|
+
try {
|
|
563
|
+
const data = await renderer.renderRoute(route, {
|
|
564
|
+
routeParams: params
|
|
565
|
+
});
|
|
566
|
+
if (data.notFound) {
|
|
567
|
+
return;
|
|
568
|
+
}
|
|
569
|
+
let outFilePath = path3.join(urlPath.slice(1), "index.html");
|
|
570
|
+
if (outFilePath.endsWith("404/index.html")) {
|
|
571
|
+
outFilePath = outFilePath.replace("404/index.html", "404.html");
|
|
572
|
+
}
|
|
573
|
+
const outPath = path3.join(buildDir, outFilePath);
|
|
574
|
+
let html = data.html || "";
|
|
575
|
+
if (rootConfig.prettyHtml !== false) {
|
|
576
|
+
html = await htmlPretty(html, rootConfig.prettyHtmlOptions);
|
|
577
|
+
}
|
|
578
|
+
if (rootConfig.minifyHtml !== false) {
|
|
579
|
+
html = await htmlMinify(html, rootConfig.minifyHtmlOptions);
|
|
580
|
+
}
|
|
581
|
+
await writeFile(outPath, html);
|
|
582
|
+
printFileOutput(fileSize(outPath), "dist/html/", outFilePath);
|
|
583
|
+
} catch (e) {
|
|
584
|
+
logBuildError({ route, params, urlPath }, e);
|
|
585
|
+
throw new Error(
|
|
586
|
+
`BuildError: ${urlPath} (${route.src}) failed to build.`
|
|
587
|
+
);
|
|
588
|
+
}
|
|
589
|
+
});
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
function isRouteFile(filepath) {
|
|
593
|
+
return filepath.startsWith("routes") && isJsFile(filepath);
|
|
594
|
+
}
|
|
595
|
+
function fileSize(filepath) {
|
|
596
|
+
const stats = fsExtra.statSync(filepath);
|
|
597
|
+
const bytes = stats.size;
|
|
598
|
+
const k = 1024;
|
|
599
|
+
if (bytes < k) {
|
|
600
|
+
return (bytes / k).toFixed(2) + " kB";
|
|
601
|
+
}
|
|
602
|
+
const units = ["B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
|
|
603
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
604
|
+
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + units[i];
|
|
605
|
+
}
|
|
606
|
+
function printFileOutput(fileSize2, outputDir, outputFile) {
|
|
607
|
+
const indent = " ".repeat(2);
|
|
608
|
+
const paddedSize = fileSize2.padStart(9, " ");
|
|
609
|
+
console.log(
|
|
610
|
+
`${indent}${dim(paddedSize)} ${dim(outputDir)}${cyan(outputFile)}`
|
|
611
|
+
);
|
|
612
|
+
}
|
|
613
|
+
function sanitizeFileName(name) {
|
|
614
|
+
return name.replaceAll("...", "").replaceAll("_", "").replaceAll("[", "").replaceAll("]", "").replace(/[^\x00-\x7F]/g, "").replace(/\x00/g, "").toLowerCase();
|
|
615
|
+
}
|
|
616
|
+
function logBuildError(ctx, e) {
|
|
617
|
+
const { route, params, urlPath } = ctx;
|
|
618
|
+
const errorString = String(e.stack || e);
|
|
619
|
+
console.error();
|
|
620
|
+
if (Object.keys(params).length > 0) {
|
|
621
|
+
console.error(
|
|
622
|
+
`An error occurred building ${urlPath} (${route.src}) with params:
|
|
623
|
+
${formatParams(params)}
|
|
624
|
+
|
|
625
|
+
The error was:
|
|
626
|
+
${errorString}
|
|
627
|
+
`.trim()
|
|
628
|
+
);
|
|
629
|
+
} else {
|
|
630
|
+
console.error(
|
|
631
|
+
`An error occurred building ${urlPath} (${route.src})
|
|
632
|
+
|
|
633
|
+
The error was:
|
|
634
|
+
${errorString}`
|
|
635
|
+
);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
function formatParams(params) {
|
|
639
|
+
return Object.entries(params).map(([key, value]) => {
|
|
640
|
+
return ` ${key}: ${value}`;
|
|
641
|
+
}).join("\n");
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
// src/cli/commands/dev.ts
|
|
645
|
+
import path5 from "node:path";
|
|
646
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
647
|
+
import cookieParser from "cookie-parser";
|
|
648
|
+
import { default as express } from "express";
|
|
649
|
+
import { dim as dim2 } from "kleur/colors";
|
|
650
|
+
import sirv from "sirv";
|
|
651
|
+
import glob3 from "tiny-glob";
|
|
652
|
+
|
|
653
|
+
// src/middleware/hooks.ts
|
|
654
|
+
function hooksMiddleware() {
|
|
655
|
+
return (req, res, next) => {
|
|
656
|
+
req.hooks = new Hooks();
|
|
657
|
+
next();
|
|
658
|
+
};
|
|
659
|
+
}
|
|
660
|
+
var Hooks = class {
|
|
661
|
+
constructor() {
|
|
662
|
+
this.callbacks = {};
|
|
663
|
+
}
|
|
664
|
+
add(name, cb) {
|
|
665
|
+
this.callbacks[name] ??= [];
|
|
666
|
+
this.callbacks[name].push(cb);
|
|
667
|
+
}
|
|
668
|
+
trigger(name, ...args) {
|
|
669
|
+
const callbacks = this.callbacks[name] || [];
|
|
670
|
+
callbacks.forEach((cb) => {
|
|
671
|
+
cb(...args);
|
|
672
|
+
});
|
|
673
|
+
}
|
|
674
|
+
};
|
|
675
|
+
|
|
676
|
+
// src/render/asset-map/dev-asset-map.ts
|
|
677
|
+
import path4 from "node:path";
|
|
678
|
+
import { searchForWorkspaceRoot as searchForWorkspaceRoot2 } from "vite";
|
|
679
|
+
var DevServerAssetMap = class {
|
|
680
|
+
constructor(rootConfig, moduleGraph) {
|
|
681
|
+
this.rootConfig = rootConfig;
|
|
682
|
+
this.moduleGraph = moduleGraph;
|
|
683
|
+
}
|
|
684
|
+
async get(src) {
|
|
685
|
+
const file = path4.resolve(this.rootConfig.rootDir, src);
|
|
686
|
+
const viteModules = this.moduleGraph.getModulesByFile(file);
|
|
687
|
+
if (viteModules && viteModules.size > 0) {
|
|
688
|
+
const [viteModule] = viteModules;
|
|
689
|
+
return new DevServerAsset(src, {
|
|
690
|
+
assetMap: this,
|
|
691
|
+
viteModule
|
|
692
|
+
});
|
|
693
|
+
}
|
|
694
|
+
if (file.startsWith(this.rootConfig.rootDir)) {
|
|
695
|
+
const assetUrl = file.slice(this.rootConfig.rootDir.length);
|
|
696
|
+
return {
|
|
697
|
+
src,
|
|
698
|
+
assetUrl,
|
|
699
|
+
getCssDeps: async () => [],
|
|
700
|
+
getJsDeps: async () => [assetUrl]
|
|
701
|
+
};
|
|
702
|
+
}
|
|
703
|
+
const workspaceRoot = searchForWorkspaceRoot2(this.rootConfig.rootDir);
|
|
704
|
+
if (await directoryContains(workspaceRoot, file)) {
|
|
705
|
+
const assetUrl = `/@fs/${file}`;
|
|
706
|
+
return {
|
|
707
|
+
src,
|
|
708
|
+
assetUrl,
|
|
709
|
+
getCssDeps: async () => [],
|
|
710
|
+
getJsDeps: async () => [assetUrl]
|
|
711
|
+
};
|
|
712
|
+
}
|
|
713
|
+
console.log(`could not find asset in asset map: ${src}`);
|
|
714
|
+
return null;
|
|
715
|
+
}
|
|
716
|
+
filePathToSrc(file) {
|
|
717
|
+
return path4.relative(this.rootConfig.rootDir, file);
|
|
718
|
+
}
|
|
719
|
+
};
|
|
720
|
+
var DevServerAsset = class {
|
|
721
|
+
constructor(src, options) {
|
|
722
|
+
this.src = src;
|
|
723
|
+
this.assetMap = options.assetMap;
|
|
724
|
+
this.viteModule = options.viteModule;
|
|
725
|
+
this.moduleId = this.viteModule.id;
|
|
726
|
+
this.assetUrl = this.viteModule.url;
|
|
727
|
+
}
|
|
728
|
+
async getCssDeps() {
|
|
729
|
+
const visited = /* @__PURE__ */ new Set();
|
|
730
|
+
const deps = /* @__PURE__ */ new Set();
|
|
731
|
+
this.collectCss(this, deps, visited);
|
|
732
|
+
return Array.from(deps);
|
|
733
|
+
}
|
|
734
|
+
async getJsDeps() {
|
|
735
|
+
const visited = /* @__PURE__ */ new Set();
|
|
736
|
+
const deps = /* @__PURE__ */ new Set();
|
|
737
|
+
this.collectJs(this, deps, visited);
|
|
738
|
+
return Array.from(deps);
|
|
739
|
+
}
|
|
740
|
+
getImportedModules() {
|
|
741
|
+
return this.viteModule.importedModules;
|
|
742
|
+
}
|
|
743
|
+
collectJs(asset, urls, visited) {
|
|
744
|
+
if (!asset) {
|
|
745
|
+
return;
|
|
746
|
+
}
|
|
747
|
+
if (!asset.moduleId) {
|
|
748
|
+
return;
|
|
749
|
+
}
|
|
750
|
+
if (visited.has(asset.moduleId)) {
|
|
751
|
+
return;
|
|
752
|
+
}
|
|
753
|
+
visited.add(asset.moduleId);
|
|
754
|
+
const parts = path4.parse(asset.assetUrl);
|
|
755
|
+
if ([".js", ".jsx", ".ts", ".tsx"].includes(parts.ext) && asset.moduleId.includes("/elements/")) {
|
|
756
|
+
urls.add(asset.assetUrl);
|
|
757
|
+
}
|
|
758
|
+
asset.getImportedModules().forEach((viteModule) => {
|
|
759
|
+
if (viteModule.file) {
|
|
760
|
+
const src = this.assetMap.filePathToSrc(viteModule.file);
|
|
761
|
+
const importedAsset = new DevServerAsset(src, {
|
|
762
|
+
assetMap: this.assetMap,
|
|
763
|
+
viteModule
|
|
764
|
+
});
|
|
765
|
+
this.collectJs(importedAsset, urls, visited);
|
|
766
|
+
}
|
|
767
|
+
});
|
|
768
|
+
}
|
|
769
|
+
collectCss(asset, urls, visited) {
|
|
770
|
+
if (!asset) {
|
|
771
|
+
return;
|
|
772
|
+
}
|
|
773
|
+
if (!asset.assetUrl) {
|
|
774
|
+
return;
|
|
775
|
+
}
|
|
776
|
+
if (visited.has(asset.assetUrl)) {
|
|
777
|
+
return;
|
|
778
|
+
}
|
|
779
|
+
visited.add(asset.assetUrl);
|
|
780
|
+
if (asset.src.endsWith(".scss")) {
|
|
781
|
+
const parts = path4.parse(asset.src);
|
|
782
|
+
if (!parts.name.startsWith("_")) {
|
|
783
|
+
urls.add(asset.assetUrl);
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
asset.getImportedModules().forEach((viteModule) => {
|
|
787
|
+
if (viteModule.file) {
|
|
788
|
+
const src = this.assetMap.filePathToSrc(viteModule.file);
|
|
789
|
+
const importedAsset = new DevServerAsset(src, {
|
|
790
|
+
assetMap: this.assetMap,
|
|
791
|
+
viteModule
|
|
792
|
+
});
|
|
793
|
+
this.collectCss(importedAsset, urls, visited);
|
|
794
|
+
}
|
|
795
|
+
});
|
|
796
|
+
}
|
|
797
|
+
};
|
|
798
|
+
|
|
799
|
+
// src/utils/ports.ts
|
|
800
|
+
import { createServer } from "node:net";
|
|
801
|
+
function isPortOpen(port) {
|
|
802
|
+
return new Promise((resolve, reject) => {
|
|
803
|
+
const server = createServer();
|
|
804
|
+
server.on("error", (err) => {
|
|
805
|
+
if (err.code === "EADDRINUSE") {
|
|
806
|
+
resolve(false);
|
|
807
|
+
return;
|
|
808
|
+
}
|
|
809
|
+
reject(err);
|
|
810
|
+
});
|
|
811
|
+
server.on("close", () => {
|
|
812
|
+
resolve(true);
|
|
813
|
+
});
|
|
814
|
+
server.listen(port, () => {
|
|
815
|
+
server.close((err) => {
|
|
816
|
+
if (err) {
|
|
817
|
+
console.log(`error closing server: ${err}`);
|
|
818
|
+
reject(err);
|
|
819
|
+
}
|
|
820
|
+
});
|
|
821
|
+
});
|
|
822
|
+
});
|
|
823
|
+
}
|
|
824
|
+
async function findOpenPort(min, max) {
|
|
825
|
+
let port = min;
|
|
826
|
+
while (port <= max) {
|
|
827
|
+
const isOpen = await isPortOpen(port);
|
|
828
|
+
if (isOpen) {
|
|
829
|
+
return port;
|
|
830
|
+
}
|
|
831
|
+
port += 1;
|
|
832
|
+
}
|
|
833
|
+
throw new Error(`no ports open between ${min} and ${max}`);
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
// src/utils/rand.ts
|
|
837
|
+
function randString(len) {
|
|
838
|
+
const result = [];
|
|
839
|
+
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
840
|
+
for (let i = 0; i < len; i++) {
|
|
841
|
+
const rand = Math.floor(Math.random() * chars.length);
|
|
842
|
+
result.push(chars.charAt(rand));
|
|
843
|
+
}
|
|
844
|
+
return result.join("");
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
// src/cli/commands/dev.ts
|
|
848
|
+
var __dirname2 = path5.dirname(fileURLToPath2(import.meta.url));
|
|
849
|
+
async function dev(rootProjectDir, options) {
|
|
850
|
+
process.env.NODE_ENV = "development";
|
|
851
|
+
const rootDir = path5.resolve(rootProjectDir || process.cwd());
|
|
852
|
+
const defaultPort = parseInt(process.env.PORT || "4007");
|
|
853
|
+
const host = (options == null ? void 0 : options.host) || "localhost";
|
|
854
|
+
const port = await findOpenPort(defaultPort, defaultPort + 10);
|
|
855
|
+
console.log();
|
|
856
|
+
console.log(`${dim2("\u2503")} project: ${rootDir}`);
|
|
857
|
+
console.log(`${dim2("\u2503")} server: http://${host}:${port}`);
|
|
858
|
+
console.log(`${dim2("\u2503")} mode: development`);
|
|
859
|
+
console.log();
|
|
860
|
+
const server = await createDevServer({ rootDir, port });
|
|
861
|
+
server.listen(port, host);
|
|
862
|
+
}
|
|
863
|
+
async function createDevServer(options) {
|
|
864
|
+
var _a;
|
|
865
|
+
const rootDir = path5.resolve((options == null ? void 0 : options.rootDir) || process.cwd());
|
|
866
|
+
const rootConfig = await loadRootConfig(rootDir, { command: "dev" });
|
|
867
|
+
const port = options == null ? void 0 : options.port;
|
|
868
|
+
const server = express();
|
|
869
|
+
server.disable("x-powered-by");
|
|
870
|
+
server.use(rootProjectMiddleware({ rootConfig }));
|
|
871
|
+
server.use(await viteServerMiddleware({ rootConfig, port }));
|
|
872
|
+
server.use(hooksMiddleware());
|
|
873
|
+
const sessionCookieSecret = ((_a = rootConfig.server) == null ? void 0 : _a.sessionCookieSecret) || randString(36);
|
|
874
|
+
server.use(cookieParser(sessionCookieSecret));
|
|
875
|
+
server.use(sessionMiddleware());
|
|
876
|
+
const plugins = rootConfig.plugins || [];
|
|
877
|
+
await configureServerPlugins(
|
|
878
|
+
server,
|
|
879
|
+
async () => {
|
|
880
|
+
var _a2;
|
|
881
|
+
const userMiddlewares = ((_a2 = rootConfig.server) == null ? void 0 : _a2.middlewares) || [];
|
|
882
|
+
for (const middleware of userMiddlewares) {
|
|
883
|
+
server.use(middleware);
|
|
884
|
+
}
|
|
885
|
+
const publicDir = path5.join(rootDir, "public");
|
|
886
|
+
if (await dirExists(publicDir)) {
|
|
887
|
+
server.use(sirv(publicDir, { dev: false }));
|
|
888
|
+
}
|
|
889
|
+
server.use(trailingSlashMiddleware({ rootConfig }));
|
|
890
|
+
server.use(rootDevServerMiddleware());
|
|
891
|
+
server.use(rootDevServer404Middleware());
|
|
892
|
+
server.use(rootDevServer500Middleware());
|
|
893
|
+
},
|
|
894
|
+
plugins,
|
|
895
|
+
{ type: "dev", rootConfig }
|
|
896
|
+
);
|
|
897
|
+
return server;
|
|
898
|
+
}
|
|
899
|
+
async function viteServerMiddleware(options) {
|
|
900
|
+
const rootConfig = options.rootConfig;
|
|
901
|
+
const rootDir = rootConfig.rootDir;
|
|
902
|
+
let elementGraph = await getElements(rootConfig);
|
|
903
|
+
const elements = Object.values(elementGraph.sourceFiles).map((sourceFile) => {
|
|
904
|
+
return sourceFile.relPath;
|
|
905
|
+
});
|
|
906
|
+
const bundleScripts = [];
|
|
907
|
+
if (await isDirectory(path5.join(rootDir, "bundles"))) {
|
|
908
|
+
const bundleFiles = await glob3("bundles/*", { cwd: rootDir });
|
|
909
|
+
bundleFiles.forEach((file) => {
|
|
910
|
+
const parts = path5.parse(file);
|
|
911
|
+
if (isJsFile(parts.base)) {
|
|
912
|
+
bundleScripts.push(file);
|
|
913
|
+
}
|
|
914
|
+
});
|
|
915
|
+
}
|
|
916
|
+
const optimizeDeps = [...elements, ...bundleScripts];
|
|
917
|
+
const viteServer = await createViteServer(rootConfig, {
|
|
918
|
+
port: options.port,
|
|
919
|
+
optimizeDeps
|
|
920
|
+
});
|
|
921
|
+
function isInElementsDir(changedFilePath) {
|
|
922
|
+
const filePath = path5.resolve(changedFilePath);
|
|
923
|
+
const elementsDirs = getElementsDirs(rootConfig);
|
|
924
|
+
return elementsDirs.some((dirPath) => filePath.startsWith(dirPath));
|
|
925
|
+
}
|
|
926
|
+
viteServer.watcher.on("add", async (filePath) => {
|
|
927
|
+
if (isInElementsDir(filePath)) {
|
|
928
|
+
elementGraph = await getElements(rootConfig);
|
|
929
|
+
console.log(`element added: ${filePath}`);
|
|
930
|
+
}
|
|
931
|
+
});
|
|
932
|
+
viteServer.watcher.on("unlink", async (filePath) => {
|
|
933
|
+
if (isInElementsDir(filePath)) {
|
|
934
|
+
elementGraph = await getElements(rootConfig);
|
|
935
|
+
console.log(`element deleted: ${filePath}`);
|
|
936
|
+
}
|
|
937
|
+
});
|
|
938
|
+
return async (req, res, next) => {
|
|
939
|
+
try {
|
|
940
|
+
req.viteServer = viteServer;
|
|
941
|
+
const renderModulePath = path5.resolve(__dirname2, "./render.js");
|
|
942
|
+
const render = await viteServer.ssrLoadModule(
|
|
943
|
+
renderModulePath
|
|
944
|
+
);
|
|
945
|
+
const assetMap = new DevServerAssetMap(
|
|
946
|
+
rootConfig,
|
|
947
|
+
viteServer.moduleGraph
|
|
948
|
+
);
|
|
949
|
+
req.renderer = new render.Renderer(rootConfig, { assetMap, elementGraph });
|
|
950
|
+
viteServer.middlewares(req, res, next);
|
|
951
|
+
} catch (e) {
|
|
952
|
+
next(e);
|
|
953
|
+
}
|
|
954
|
+
};
|
|
955
|
+
}
|
|
956
|
+
function rootDevServerMiddleware() {
|
|
957
|
+
return async (req, res, next) => {
|
|
958
|
+
const renderer = req.renderer;
|
|
959
|
+
const viteServer = req.viteServer;
|
|
960
|
+
try {
|
|
961
|
+
await renderer.handle(req, res, next);
|
|
962
|
+
} catch (err) {
|
|
963
|
+
viteServer.ssrFixStacktrace(err);
|
|
964
|
+
next(err);
|
|
965
|
+
}
|
|
966
|
+
};
|
|
967
|
+
}
|
|
968
|
+
function rootDevServer404Middleware() {
|
|
969
|
+
return async (req, res) => {
|
|
970
|
+
console.error(`\u2753 404 ${req.originalUrl}`);
|
|
971
|
+
if (req.renderer) {
|
|
972
|
+
const url = req.path;
|
|
973
|
+
const ext = path5.extname(url);
|
|
974
|
+
if (!ext) {
|
|
975
|
+
const renderer = req.renderer;
|
|
976
|
+
const data = await renderer.renderDevServer404(req);
|
|
977
|
+
const html = data.html || "";
|
|
978
|
+
res.status(404).set({ "Content-Type": "text/html" }).end(html);
|
|
979
|
+
return;
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
res.status(404).set({ "Content-Type": "text/plain" }).end("404");
|
|
983
|
+
};
|
|
984
|
+
}
|
|
985
|
+
function rootDevServer500Middleware() {
|
|
986
|
+
return async (err, req, res, next) => {
|
|
987
|
+
console.error(`\u2757 500 ${req.originalUrl}`);
|
|
988
|
+
console.error(String(err.stack || err));
|
|
989
|
+
if (req.renderer) {
|
|
990
|
+
const url = req.path;
|
|
991
|
+
const ext = path5.extname(url);
|
|
992
|
+
if (!ext) {
|
|
993
|
+
const renderer = req.renderer;
|
|
994
|
+
const data = await renderer.renderDevServer500(req, err);
|
|
995
|
+
const html = data.html || "";
|
|
996
|
+
res.status(500).set({ "Content-Type": "text/html" }).end(html);
|
|
997
|
+
return;
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
next(err);
|
|
1001
|
+
};
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
// src/cli/commands/preview.ts
|
|
1005
|
+
import path6 from "node:path";
|
|
1006
|
+
import compression from "compression";
|
|
1007
|
+
import cookieParser2 from "cookie-parser";
|
|
1008
|
+
import { default as express2 } from "express";
|
|
1009
|
+
import { dim as dim3 } from "kleur/colors";
|
|
1010
|
+
import sirv2 from "sirv";
|
|
1011
|
+
async function preview(rootProjectDir, options) {
|
|
1012
|
+
process.env.NODE_ENV = "development";
|
|
1013
|
+
const rootDir = path6.resolve(rootProjectDir || process.cwd());
|
|
1014
|
+
const server = await createPreviewServer({ rootDir });
|
|
1015
|
+
const port = parseInt(process.env.PORT || "4007");
|
|
1016
|
+
const host = (options == null ? void 0 : options.host) || "localhost";
|
|
1017
|
+
console.log();
|
|
1018
|
+
console.log(`${dim3("\u2503")} project: ${rootDir}`);
|
|
1019
|
+
console.log(`${dim3("\u2503")} server: http://${host}:${port}`);
|
|
1020
|
+
console.log(`${dim3("\u2503")} mode: preview`);
|
|
1021
|
+
console.log();
|
|
1022
|
+
server.listen(port, host);
|
|
1023
|
+
}
|
|
1024
|
+
async function createPreviewServer(options) {
|
|
1025
|
+
var _a;
|
|
1026
|
+
const rootDir = options.rootDir;
|
|
1027
|
+
const rootConfig = await loadRootConfig(rootDir, { command: "preview" });
|
|
1028
|
+
const distDir = path6.join(rootDir, "dist");
|
|
1029
|
+
const server = express2();
|
|
1030
|
+
server.disable("x-powered-by");
|
|
1031
|
+
server.use(compression());
|
|
1032
|
+
server.use(rootProjectMiddleware({ rootConfig }));
|
|
1033
|
+
server.use(await rootPreviewRendererMiddleware({ rootConfig, distDir }));
|
|
1034
|
+
server.use(hooksMiddleware());
|
|
1035
|
+
const sessionCookieSecret = ((_a = rootConfig.server) == null ? void 0 : _a.sessionCookieSecret) || randString(36);
|
|
1036
|
+
server.use(cookieParser2(sessionCookieSecret));
|
|
1037
|
+
server.use(sessionMiddleware());
|
|
1038
|
+
const plugins = rootConfig.plugins || [];
|
|
1039
|
+
configureServerPlugins(
|
|
1040
|
+
server,
|
|
1041
|
+
async () => {
|
|
1042
|
+
var _a2;
|
|
1043
|
+
const userMiddlewares = ((_a2 = rootConfig.server) == null ? void 0 : _a2.middlewares) || [];
|
|
1044
|
+
userMiddlewares.forEach((middleware) => {
|
|
1045
|
+
server.use(middleware);
|
|
1046
|
+
});
|
|
1047
|
+
const publicDir = path6.join(distDir, "html");
|
|
1048
|
+
server.use(sirv2(publicDir, { dev: false }));
|
|
1049
|
+
server.use(trailingSlashMiddleware({ rootConfig }));
|
|
1050
|
+
server.use(rootPreviewServerMiddleware());
|
|
1051
|
+
server.use(rootPreviewServer404Middleware());
|
|
1052
|
+
server.use(rootPreviewServer500Middleware());
|
|
1053
|
+
},
|
|
1054
|
+
plugins,
|
|
1055
|
+
{ type: "preview", rootConfig }
|
|
1056
|
+
);
|
|
1057
|
+
return server;
|
|
1058
|
+
}
|
|
1059
|
+
async function rootPreviewRendererMiddleware(options) {
|
|
1060
|
+
const { distDir, rootConfig } = options;
|
|
1061
|
+
const render = await import(path6.join(distDir, "server/render.js"));
|
|
1062
|
+
const manifestPath = path6.join(distDir, "client/root-manifest.json");
|
|
1063
|
+
if (!await fileExists(manifestPath)) {
|
|
1064
|
+
throw new Error(
|
|
1065
|
+
`could not find ${manifestPath}. run \`root build\` before \`root preview\`.`
|
|
1066
|
+
);
|
|
1067
|
+
}
|
|
1068
|
+
const elementGraphJsonPath = path6.join(
|
|
1069
|
+
distDir,
|
|
1070
|
+
"client/root-element-graph.json"
|
|
1071
|
+
);
|
|
1072
|
+
if (!await fileExists(elementGraphJsonPath)) {
|
|
1073
|
+
throw new Error(
|
|
1074
|
+
`could not find ${elementGraphJsonPath}. run \`root build\` before \`root start\`.`
|
|
1075
|
+
);
|
|
1076
|
+
}
|
|
1077
|
+
const rootManifest = await loadJson(manifestPath);
|
|
1078
|
+
const assetMap = BuildAssetMap.fromRootManifest(rootConfig, rootManifest);
|
|
1079
|
+
const elementGraphJson = await loadJson(elementGraphJsonPath);
|
|
1080
|
+
const elementGraph = ElementGraph.fromJson(elementGraphJson);
|
|
1081
|
+
const renderer = new render.Renderer(rootConfig, { assetMap, elementGraph });
|
|
1082
|
+
return async (req, _, next) => {
|
|
1083
|
+
req.renderer = renderer;
|
|
1084
|
+
next();
|
|
1085
|
+
};
|
|
1086
|
+
}
|
|
1087
|
+
function rootPreviewServerMiddleware() {
|
|
1088
|
+
return async (req, res, next) => {
|
|
1089
|
+
const renderer = req.renderer;
|
|
1090
|
+
try {
|
|
1091
|
+
await renderer.handle(req, res, next);
|
|
1092
|
+
} catch (e) {
|
|
1093
|
+
try {
|
|
1094
|
+
console.error(`error rendering ${req.originalUrl}`);
|
|
1095
|
+
console.error(e.stack || e);
|
|
1096
|
+
const { html } = await renderer.renderError(e);
|
|
1097
|
+
res.status(500).set({ "Content-Type": "text/html" }).end(html);
|
|
1098
|
+
} catch (e2) {
|
|
1099
|
+
console.error("failed to render custom error");
|
|
1100
|
+
console.error(e2);
|
|
1101
|
+
next(e);
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
};
|
|
1105
|
+
}
|
|
1106
|
+
function rootPreviewServer404Middleware() {
|
|
1107
|
+
return async (req, res) => {
|
|
1108
|
+
console.error(`\u2753 404 ${req.originalUrl}`);
|
|
1109
|
+
if (req.renderer) {
|
|
1110
|
+
const url = req.path;
|
|
1111
|
+
const ext = path6.extname(url);
|
|
1112
|
+
if (!ext) {
|
|
1113
|
+
const renderer = req.renderer;
|
|
1114
|
+
const data = await renderer.render404({ currentPath: url });
|
|
1115
|
+
const html = data.html || "";
|
|
1116
|
+
res.status(404).set({ "Content-Type": "text/html" }).end(html);
|
|
1117
|
+
return;
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1120
|
+
res.status(404).set({ "Content-Type": "text/plain" }).end("404");
|
|
1121
|
+
};
|
|
1122
|
+
}
|
|
1123
|
+
function rootPreviewServer500Middleware() {
|
|
1124
|
+
return async (err, req, res, next) => {
|
|
1125
|
+
console.error(`\u2757 500 ${req.originalUrl}`);
|
|
1126
|
+
console.error(String(err.stack || err));
|
|
1127
|
+
if (req.renderer) {
|
|
1128
|
+
const url = req.path;
|
|
1129
|
+
const ext = path6.extname(url);
|
|
1130
|
+
if (!ext) {
|
|
1131
|
+
const renderer = req.renderer;
|
|
1132
|
+
const data = await renderer.renderDevServer500(req, err);
|
|
1133
|
+
const html = data.html || "";
|
|
1134
|
+
res.status(500).set({ "Content-Type": "text/html" }).end(html);
|
|
1135
|
+
return;
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
next(err);
|
|
1139
|
+
};
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
// src/cli/commands/start.ts
|
|
1143
|
+
import path7 from "node:path";
|
|
1144
|
+
import compression2 from "compression";
|
|
1145
|
+
import cookieParser3 from "cookie-parser";
|
|
1146
|
+
import { default as express3 } from "express";
|
|
1147
|
+
import { dim as dim4 } from "kleur/colors";
|
|
1148
|
+
import sirv3 from "sirv";
|
|
1149
|
+
async function start(rootProjectDir, options) {
|
|
1150
|
+
process.env.NODE_ENV = "production";
|
|
1151
|
+
const rootDir = path7.resolve(rootProjectDir || process.cwd());
|
|
1152
|
+
const server = await createProdServer({ rootDir });
|
|
1153
|
+
const port = parseInt(process.env.PORT || "4007");
|
|
1154
|
+
const host = (options == null ? void 0 : options.host) || "localhost";
|
|
1155
|
+
console.log();
|
|
1156
|
+
console.log(`${dim4("\u2503")} project: ${rootDir}`);
|
|
1157
|
+
console.log(`${dim4("\u2503")} server: http://${host}:${port}`);
|
|
1158
|
+
console.log(`${dim4("\u2503")} mode: production`);
|
|
1159
|
+
console.log();
|
|
1160
|
+
server.listen(port, host);
|
|
1161
|
+
}
|
|
1162
|
+
async function createProdServer(options) {
|
|
1163
|
+
var _a;
|
|
1164
|
+
const rootDir = options.rootDir;
|
|
1165
|
+
const rootConfig = await loadRootConfig(rootDir, { command: "start" });
|
|
1166
|
+
const distDir = path7.join(rootDir, "dist");
|
|
1167
|
+
const server = express3();
|
|
1168
|
+
server.disable("x-powered-by");
|
|
1169
|
+
server.use(compression2());
|
|
1170
|
+
server.use(rootProjectMiddleware({ rootConfig }));
|
|
1171
|
+
server.use(await rootProdRendererMiddleware({ rootConfig, distDir }));
|
|
1172
|
+
server.use(hooksMiddleware());
|
|
1173
|
+
const sessionCookieSecret = ((_a = rootConfig.server) == null ? void 0 : _a.sessionCookieSecret) || randString(36);
|
|
1174
|
+
server.use(cookieParser3(sessionCookieSecret));
|
|
1175
|
+
server.use(sessionMiddleware());
|
|
1176
|
+
const plugins = rootConfig.plugins || [];
|
|
1177
|
+
configureServerPlugins(
|
|
1178
|
+
server,
|
|
1179
|
+
async () => {
|
|
1180
|
+
var _a2;
|
|
1181
|
+
const userMiddlewares = ((_a2 = rootConfig.server) == null ? void 0 : _a2.middlewares) || [];
|
|
1182
|
+
userMiddlewares.forEach((middleware) => {
|
|
1183
|
+
server.use(middleware);
|
|
1184
|
+
});
|
|
1185
|
+
const publicDir = path7.join(distDir, "html");
|
|
1186
|
+
server.use(sirv3(publicDir, { dev: false }));
|
|
1187
|
+
server.use(trailingSlashMiddleware({ rootConfig }));
|
|
1188
|
+
server.use(rootProdServerMiddleware());
|
|
1189
|
+
server.use(rootProdServer404Middleware());
|
|
1190
|
+
server.use(rootProdServer500Middleware());
|
|
1191
|
+
},
|
|
1192
|
+
plugins,
|
|
1193
|
+
{ type: "prod", rootConfig }
|
|
1194
|
+
);
|
|
1195
|
+
return server;
|
|
1196
|
+
}
|
|
1197
|
+
async function rootProdRendererMiddleware(options) {
|
|
1198
|
+
const { distDir, rootConfig } = options;
|
|
1199
|
+
const render = await import(path7.join(distDir, "server/render.js"));
|
|
1200
|
+
const manifestPath = path7.join(distDir, "client/root-manifest.json");
|
|
1201
|
+
if (!await fileExists(manifestPath)) {
|
|
1202
|
+
throw new Error(
|
|
1203
|
+
`could not find ${manifestPath}. run \`root build\` before \`root start\`.`
|
|
1204
|
+
);
|
|
1205
|
+
}
|
|
1206
|
+
const elementGraphJsonPath = path7.join(
|
|
1207
|
+
distDir,
|
|
1208
|
+
"client/root-element-graph.json"
|
|
1209
|
+
);
|
|
1210
|
+
if (!await fileExists(elementGraphJsonPath)) {
|
|
1211
|
+
throw new Error(
|
|
1212
|
+
`could not find ${elementGraphJsonPath}. run \`root build\` before \`root start\`.`
|
|
1213
|
+
);
|
|
1214
|
+
}
|
|
1215
|
+
const rootManifest = await loadJson(manifestPath);
|
|
1216
|
+
const assetMap = BuildAssetMap.fromRootManifest(rootConfig, rootManifest);
|
|
1217
|
+
const elementGraphJson = await loadJson(elementGraphJsonPath);
|
|
1218
|
+
const elementGraph = ElementGraph.fromJson(elementGraphJson);
|
|
1219
|
+
const renderer = new render.Renderer(rootConfig, { assetMap, elementGraph });
|
|
1220
|
+
return async (req, _, next) => {
|
|
1221
|
+
req.renderer = renderer;
|
|
1222
|
+
next();
|
|
1223
|
+
};
|
|
1224
|
+
}
|
|
1225
|
+
function rootProdServerMiddleware() {
|
|
1226
|
+
return async (req, res, next) => {
|
|
1227
|
+
const renderer = req.renderer;
|
|
1228
|
+
try {
|
|
1229
|
+
await renderer.handle(req, res, next);
|
|
1230
|
+
} catch (e) {
|
|
1231
|
+
try {
|
|
1232
|
+
console.error(`error rendering ${req.originalUrl}`);
|
|
1233
|
+
console.error(e.stack || e);
|
|
1234
|
+
const { html } = await renderer.renderError(e);
|
|
1235
|
+
res.status(500).set({ "Content-Type": "text/html" }).end(html);
|
|
1236
|
+
} catch (e2) {
|
|
1237
|
+
console.error("failed to render custom error");
|
|
1238
|
+
console.error(e2);
|
|
1239
|
+
next(e);
|
|
1240
|
+
}
|
|
1241
|
+
}
|
|
1242
|
+
};
|
|
1243
|
+
}
|
|
1244
|
+
function rootProdServer404Middleware() {
|
|
1245
|
+
return async (req, res) => {
|
|
1246
|
+
console.error(`\u2753 404 ${req.originalUrl}`);
|
|
1247
|
+
if (req.renderer) {
|
|
1248
|
+
const url = req.path;
|
|
1249
|
+
const ext = path7.extname(url);
|
|
1250
|
+
if (!ext) {
|
|
1251
|
+
const renderer = req.renderer;
|
|
1252
|
+
const data = await renderer.render404({ currentPath: url });
|
|
1253
|
+
const html = data.html || "";
|
|
1254
|
+
res.status(404).set({ "Content-Type": "text/html" }).end(html);
|
|
1255
|
+
return;
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
res.status(404).set({ "Content-Type": "text/plain" }).end("404");
|
|
1259
|
+
};
|
|
1260
|
+
}
|
|
1261
|
+
function rootProdServer500Middleware() {
|
|
1262
|
+
return async (err, req, res, next) => {
|
|
1263
|
+
console.error(`\u2757 500 ${req.originalUrl}`);
|
|
1264
|
+
console.error(String(err.stack || err));
|
|
1265
|
+
if (req.renderer) {
|
|
1266
|
+
const url = req.path;
|
|
1267
|
+
const ext = path7.extname(url);
|
|
1268
|
+
if (!ext) {
|
|
1269
|
+
const renderer = req.renderer;
|
|
1270
|
+
const data = await renderer.renderError(err);
|
|
1271
|
+
const html = data.html || "";
|
|
1272
|
+
res.status(500).set({ "Content-Type": "text/html" }).end(html);
|
|
1273
|
+
return;
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
next(err);
|
|
1277
|
+
};
|
|
1278
|
+
}
|
|
1279
|
+
|
|
1280
|
+
export {
|
|
1281
|
+
build,
|
|
1282
|
+
dev,
|
|
1283
|
+
createDevServer,
|
|
1284
|
+
preview,
|
|
1285
|
+
createPreviewServer,
|
|
1286
|
+
start,
|
|
1287
|
+
createProdServer
|
|
1288
|
+
};
|
|
1289
|
+
//# sourceMappingURL=chunk-6F72PDTR.js.map
|