litzjs 0.0.0
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/LICENSE +21 -0
- package/README.md +936 -0
- package/dist/bindings-B1P6pL93.js +21 -0
- package/dist/bindings-BDe-v5i6.mjs +10 -0
- package/dist/chunk-8l464Juk.js +28 -0
- package/dist/client.d.mts +35 -0
- package/dist/client.d.ts +35 -0
- package/dist/client.js +1633 -0
- package/dist/client.mjs +1625 -0
- package/dist/index.d.mts +559 -0
- package/dist/index.d.ts +559 -0
- package/dist/index.js +360 -0
- package/dist/index.mjs +344 -0
- package/dist/internal-transport-DR0r68ff.js +161 -0
- package/dist/internal-transport-dsMykcNK.mjs +114 -0
- package/dist/request-headers-DepZ5tjg.mjs +35 -0
- package/dist/request-headers-ZPR3TQs3.js +46 -0
- package/dist/server.d.mts +74 -0
- package/dist/server.d.ts +74 -0
- package/dist/server.js +316 -0
- package/dist/server.mjs +315 -0
- package/dist/vite.d.mts +10043 -0
- package/dist/vite.d.ts +10043 -0
- package/dist/vite.js +1481 -0
- package/dist/vite.mjs +1474 -0
- package/package.json +90 -0
package/dist/vite.js
ADDED
|
@@ -0,0 +1,1481 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_chunk = require("./chunk-8l464Juk.js");
|
|
3
|
+
const require_internal_transport = require("./internal-transport-DR0r68ff.js");
|
|
4
|
+
const require_request_headers = require("./request-headers-ZPR3TQs3.js");
|
|
5
|
+
let _vitejs_plugin_rsc = require("@vitejs/plugin-rsc");
|
|
6
|
+
_vitejs_plugin_rsc = require_chunk.__toESM(_vitejs_plugin_rsc);
|
|
7
|
+
let node_child_process = require("node:child_process");
|
|
8
|
+
let node_fs = require("node:fs");
|
|
9
|
+
let node_fs_promises = require("node:fs/promises");
|
|
10
|
+
let node_path = require("node:path");
|
|
11
|
+
node_path = require_chunk.__toESM(node_path);
|
|
12
|
+
let tinyglobby = require("tinyglobby");
|
|
13
|
+
let typescript = require("typescript");
|
|
14
|
+
typescript = require_chunk.__toESM(typescript);
|
|
15
|
+
//#region src/client-projection.ts
|
|
16
|
+
function createClientModuleProjection(filePath, source) {
|
|
17
|
+
const scriptKind = filePath.endsWith(".tsx") ? typescript.default.ScriptKind.TSX : typescript.default.ScriptKind.TS;
|
|
18
|
+
const sourceFile = typescript.default.createSourceFile(filePath, source, typescript.default.ScriptTarget.Latest, true, scriptKind);
|
|
19
|
+
const compilerOptions = {
|
|
20
|
+
target: typescript.default.ScriptTarget.ESNext,
|
|
21
|
+
module: typescript.default.ModuleKind.ESNext,
|
|
22
|
+
jsx: typescript.default.JsxEmit.Preserve,
|
|
23
|
+
moduleResolution: typescript.default.ModuleResolutionKind.Bundler,
|
|
24
|
+
allowJs: true
|
|
25
|
+
};
|
|
26
|
+
const host = typescript.default.createCompilerHost(compilerOptions, true);
|
|
27
|
+
const originalGetSourceFile = host.getSourceFile.bind(host);
|
|
28
|
+
host.getSourceFile = (fileName, languageVersion, onError, shouldCreateNewSourceFile) => {
|
|
29
|
+
if (node_path.default.resolve(fileName) === node_path.default.resolve(filePath)) return sourceFile;
|
|
30
|
+
return originalGetSourceFile(fileName, languageVersion, onError, shouldCreateNewSourceFile);
|
|
31
|
+
};
|
|
32
|
+
host.readFile = (fileName) => {
|
|
33
|
+
if (node_path.default.resolve(fileName) === node_path.default.resolve(filePath)) return source;
|
|
34
|
+
return (0, node_fs.readFileSync)(fileName, "utf8");
|
|
35
|
+
};
|
|
36
|
+
host.fileExists = (fileName) => {
|
|
37
|
+
if (node_path.default.resolve(fileName) === node_path.default.resolve(filePath)) return true;
|
|
38
|
+
return typescript.default.sys.fileExists(fileName);
|
|
39
|
+
};
|
|
40
|
+
const checker = typescript.default.createProgram([filePath], compilerOptions, host).getTypeChecker();
|
|
41
|
+
const topLevelDeclarations = collectTopLevelDeclarations(sourceFile);
|
|
42
|
+
const importStatements = sourceFile.statements.filter(typescript.default.isImportDeclaration);
|
|
43
|
+
const topLevelNames = new Set(topLevelDeclarations.keys());
|
|
44
|
+
const importBindings = collectImportBindings(importStatements);
|
|
45
|
+
const rootStatement = findProjectionRootStatement(sourceFile);
|
|
46
|
+
if (!rootStatement) return null;
|
|
47
|
+
const requiredStatements = new Set([rootStatement]);
|
|
48
|
+
const referencedImports = /* @__PURE__ */ new Set();
|
|
49
|
+
const queue = [rootStatement];
|
|
50
|
+
while (queue.length > 0) {
|
|
51
|
+
const statement = queue.pop();
|
|
52
|
+
if (!statement) continue;
|
|
53
|
+
const referencedNames = collectReferencedNames(statement, checker, topLevelNames, importBindings, shouldSkipProjectionSubtree);
|
|
54
|
+
for (const importName of referencedNames.imports) referencedImports.add(importName);
|
|
55
|
+
for (const declarationName of referencedNames.locals) {
|
|
56
|
+
const declarationStatement = topLevelDeclarations.get(declarationName);
|
|
57
|
+
if (!declarationStatement || requiredStatements.has(declarationStatement)) continue;
|
|
58
|
+
requiredStatements.add(declarationStatement);
|
|
59
|
+
queue.push(declarationStatement);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
const printedImports = importStatements.map((statement) => projectImportStatement(statement, referencedImports)).filter((statement) => statement !== null);
|
|
63
|
+
const projectionStatements = sourceFile.statements.filter((statement) => requiredStatements.has(statement));
|
|
64
|
+
const needsPlaceholder = projectionStatements.some((statement) => projectionNeedsPlaceholder(statement));
|
|
65
|
+
const transformedStatements = projectionStatements.map((statement) => transformProjectionStatement(statement));
|
|
66
|
+
const printer = typescript.default.createPrinter({ newLine: typescript.default.NewLineKind.LineFeed });
|
|
67
|
+
const placeholder = needsPlaceholder ? [typescript.default.factory.createVariableStatement(void 0, typescript.default.factory.createVariableDeclarationList([typescript.default.factory.createVariableDeclaration(typescript.default.factory.createIdentifier("__litz_server_placeholder__"), void 0, void 0, typescript.default.factory.createObjectLiteralExpression())], typescript.default.NodeFlags.Const))] : [];
|
|
68
|
+
return `${[
|
|
69
|
+
...printedImports,
|
|
70
|
+
...placeholder,
|
|
71
|
+
...transformedStatements
|
|
72
|
+
].map((statement) => printer.printNode(typescript.default.EmitHint.Unspecified, statement, sourceFile)).join("\n\n")}\n`;
|
|
73
|
+
}
|
|
74
|
+
function findProjectionRootStatement(sourceFile) {
|
|
75
|
+
for (const statement of sourceFile.statements) {
|
|
76
|
+
if (!typescript.default.isVariableStatement(statement)) continue;
|
|
77
|
+
if (!statement.modifiers?.some((modifier) => modifier.kind === typescript.default.SyntaxKind.ExportKeyword)) continue;
|
|
78
|
+
const declaration = statement.declarationList.declarations[0];
|
|
79
|
+
if (!declaration || !typescript.default.isIdentifier(declaration.name) || !declaration.initializer) continue;
|
|
80
|
+
const exportName = declaration.name.text;
|
|
81
|
+
if (exportName !== "route" && exportName !== "layout" && exportName !== "resource" && exportName !== "api") continue;
|
|
82
|
+
return statement;
|
|
83
|
+
}
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
function collectTopLevelDeclarations(sourceFile) {
|
|
87
|
+
const declarations = /* @__PURE__ */ new Map();
|
|
88
|
+
for (const statement of sourceFile.statements) {
|
|
89
|
+
if (typescript.default.isFunctionDeclaration(statement) && statement.name) {
|
|
90
|
+
declarations.set(statement.name.text, statement);
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
if (typescript.default.isClassDeclaration(statement) && statement.name) {
|
|
94
|
+
declarations.set(statement.name.text, statement);
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
if (typescript.default.isVariableStatement(statement)) {
|
|
98
|
+
for (const declaration of statement.declarationList.declarations) if (typescript.default.isIdentifier(declaration.name)) declarations.set(declaration.name.text, statement);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return declarations;
|
|
102
|
+
}
|
|
103
|
+
function collectImportBindings(imports) {
|
|
104
|
+
const bindings = /* @__PURE__ */ new Set();
|
|
105
|
+
for (const statement of imports) {
|
|
106
|
+
if (!statement.importClause) continue;
|
|
107
|
+
if (statement.importClause.name) bindings.add(statement.importClause.name.text);
|
|
108
|
+
const namedBindings = statement.importClause.namedBindings;
|
|
109
|
+
if (!namedBindings) continue;
|
|
110
|
+
if (typescript.default.isNamespaceImport(namedBindings)) {
|
|
111
|
+
bindings.add(namedBindings.name.text);
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
for (const element of namedBindings.elements) bindings.add(element.name.text);
|
|
115
|
+
}
|
|
116
|
+
return bindings;
|
|
117
|
+
}
|
|
118
|
+
function collectReferencedNames(statement, checker, topLevelNames, importBindings, shouldSkipSubtree) {
|
|
119
|
+
const locals = /* @__PURE__ */ new Set();
|
|
120
|
+
const imports = /* @__PURE__ */ new Set();
|
|
121
|
+
const sourceFile = statement.getSourceFile();
|
|
122
|
+
function visit(node) {
|
|
123
|
+
if (shouldSkipSubtree(node)) return;
|
|
124
|
+
if (typescript.default.isTypeNode(node)) return;
|
|
125
|
+
if (typescript.default.isIdentifier(node)) {
|
|
126
|
+
if (isIgnoredIdentifierReference(node)) return;
|
|
127
|
+
const declarations = checker.getSymbolAtLocation(node)?.declarations ?? [];
|
|
128
|
+
const declaration = declarations[0];
|
|
129
|
+
if (importBindings.has(node.text)) {
|
|
130
|
+
if (!declaration) {
|
|
131
|
+
imports.add(node.text);
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
if (isImportBindingDeclaration(declaration)) {
|
|
135
|
+
imports.add(node.text);
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
if (declarations.every((candidate) => candidate.getSourceFile() !== sourceFile)) {
|
|
139
|
+
imports.add(node.text);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
if (!declaration) return;
|
|
144
|
+
if (isImportBindingDeclaration(declaration)) {
|
|
145
|
+
if (importBindings.has(node.text)) imports.add(node.text);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
if (declaration.getSourceFile() !== statement.getSourceFile()) {
|
|
149
|
+
if (importBindings.has(node.text)) imports.add(node.text);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
if (topLevelNames.has(node.text)) locals.add(node.text);
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
typescript.default.forEachChild(node, visit);
|
|
156
|
+
}
|
|
157
|
+
visit(statement);
|
|
158
|
+
return {
|
|
159
|
+
locals,
|
|
160
|
+
imports
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
function isIgnoredIdentifierReference(node) {
|
|
164
|
+
const parent = node.parent;
|
|
165
|
+
if (typescript.default.isPropertyAccessExpression(parent) && parent.name === node) return true;
|
|
166
|
+
if (typescript.default.isPropertyAssignment(parent) && parent.name === node) return true;
|
|
167
|
+
if (typescript.default.isShorthandPropertyAssignment(parent)) return false;
|
|
168
|
+
if (typescript.default.isImportClause(parent) || typescript.default.isImportSpecifier(parent) || typescript.default.isNamespaceImport(parent)) return true;
|
|
169
|
+
if (typescript.default.isVariableDeclaration(parent) || typescript.default.isFunctionDeclaration(parent) || typescript.default.isParameter(parent) || typescript.default.isBindingElement(parent) || typescript.default.isClassDeclaration(parent)) return parent.name === node;
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
function shouldSkipProjectionSubtree(node) {
|
|
173
|
+
if (typescript.default.isCallExpression(node) && typescript.default.isIdentifier(node.expression) && node.expression.text === "server") return true;
|
|
174
|
+
if ((typescript.default.isPropertyAssignment(node) || typescript.default.isMethodDeclaration(node) || typescript.default.isShorthandPropertyAssignment(node)) && isServerOnlyProjectionProperty(node)) return true;
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
177
|
+
function projectImportStatement(statement, referencedImports) {
|
|
178
|
+
if (!statement.importClause) return statement;
|
|
179
|
+
const defaultImport = statement.importClause.name && referencedImports.has(statement.importClause.name.text) ? statement.importClause.name : void 0;
|
|
180
|
+
const namedBindings = statement.importClause.namedBindings;
|
|
181
|
+
let nextNamedBindings;
|
|
182
|
+
if (namedBindings) if (typescript.default.isNamespaceImport(namedBindings)) {
|
|
183
|
+
if (referencedImports.has(namedBindings.name.text)) nextNamedBindings = namedBindings;
|
|
184
|
+
} else {
|
|
185
|
+
const elements = namedBindings.elements.filter((element) => referencedImports.has(element.name.text));
|
|
186
|
+
if (elements.length > 0) nextNamedBindings = typescript.default.factory.updateNamedImports(namedBindings, elements);
|
|
187
|
+
}
|
|
188
|
+
if (!defaultImport && !nextNamedBindings) return null;
|
|
189
|
+
return typescript.default.factory.updateImportDeclaration(statement, statement.modifiers, typescript.default.factory.updateImportClause(statement.importClause, statement.importClause.isTypeOnly, defaultImport, nextNamedBindings), statement.moduleSpecifier, statement.attributes);
|
|
190
|
+
}
|
|
191
|
+
function projectionNeedsPlaceholder(statement) {
|
|
192
|
+
let required = false;
|
|
193
|
+
function visit(node) {
|
|
194
|
+
if (required) return;
|
|
195
|
+
if (typescript.default.isCallExpression(node) && typescript.default.isIdentifier(node.expression) && (node.expression.text === "server" || node.expression.text === "defineApiRoute")) {
|
|
196
|
+
required = true;
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
typescript.default.forEachChild(node, visit);
|
|
200
|
+
}
|
|
201
|
+
visit(statement);
|
|
202
|
+
return required;
|
|
203
|
+
}
|
|
204
|
+
function transformProjectionStatement(statement) {
|
|
205
|
+
const result = typescript.default.transform(statement, [(context) => {
|
|
206
|
+
const visit = (node) => {
|
|
207
|
+
if (typescript.default.isCallExpression(node) && typescript.default.isIdentifier(node.expression)) {
|
|
208
|
+
if (node.expression.text === "server") return typescript.default.factory.createIdentifier("__litz_server_placeholder__");
|
|
209
|
+
if ((node.expression.text === "defineRoute" || node.expression.text === "defineLayout" || node.expression.text === "defineResource") && node.arguments[1] && typescript.default.isObjectLiteralExpression(node.arguments[1])) {
|
|
210
|
+
const pathArgument = node.arguments[0] ?? typescript.default.factory.createStringLiteral("");
|
|
211
|
+
const properties = node.arguments[1].properties.map((property) => {
|
|
212
|
+
if (typescript.default.isShorthandPropertyAssignment(property)) {
|
|
213
|
+
const name = property.name.text;
|
|
214
|
+
if (name === "loader" || name === "action") return typescript.default.factory.createPropertyAssignment(property.name, typescript.default.factory.createIdentifier("__litz_server_placeholder__"));
|
|
215
|
+
if (name === "middleware") return typescript.default.factory.createPropertyAssignment(property.name, typescript.default.factory.createArrayLiteralExpression());
|
|
216
|
+
return property;
|
|
217
|
+
}
|
|
218
|
+
if (!typescript.default.isPropertyAssignment(property)) return property;
|
|
219
|
+
const name = getObjectPropertyName(property.name);
|
|
220
|
+
if (name === "loader" || name === "action") return typescript.default.factory.updatePropertyAssignment(property, property.name, typescript.default.factory.createIdentifier("__litz_server_placeholder__"));
|
|
221
|
+
if (name === "middleware") return typescript.default.factory.updatePropertyAssignment(property, property.name, typescript.default.factory.createArrayLiteralExpression());
|
|
222
|
+
return typescript.default.visitEachChild(property, visit, context);
|
|
223
|
+
});
|
|
224
|
+
return typescript.default.factory.updateCallExpression(node, node.expression, node.typeArguments, [pathArgument, typescript.default.factory.updateObjectLiteralExpression(node.arguments[1], properties)]);
|
|
225
|
+
}
|
|
226
|
+
if (node.expression.text === "defineApiRoute" && node.arguments[1] && typescript.default.isObjectLiteralExpression(node.arguments[1])) {
|
|
227
|
+
const pathArgument = node.arguments[0] ?? typescript.default.factory.createStringLiteral("");
|
|
228
|
+
const properties = node.arguments[1].properties.map((property) => {
|
|
229
|
+
if (typescript.default.isPropertyAssignment(property)) return typescript.default.factory.updatePropertyAssignment(property, property.name, typescript.default.factory.createIdentifier("__litz_server_placeholder__"));
|
|
230
|
+
if (typescript.default.isMethodDeclaration(property)) return typescript.default.factory.createPropertyAssignment(property.name, typescript.default.factory.createIdentifier("__litz_server_placeholder__"));
|
|
231
|
+
if (typescript.default.isShorthandPropertyAssignment(property)) return typescript.default.factory.createPropertyAssignment(property.name, typescript.default.factory.createIdentifier("__litz_server_placeholder__"));
|
|
232
|
+
return property;
|
|
233
|
+
});
|
|
234
|
+
return typescript.default.factory.updateCallExpression(node, node.expression, node.typeArguments, [pathArgument, typescript.default.factory.updateObjectLiteralExpression(node.arguments[1], properties)]);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return typescript.default.visitEachChild(node, visit, context);
|
|
238
|
+
};
|
|
239
|
+
return (node) => typescript.default.visitNode(node, visit);
|
|
240
|
+
}]);
|
|
241
|
+
const [transformed] = result.transformed;
|
|
242
|
+
result.dispose();
|
|
243
|
+
return transformed ?? statement;
|
|
244
|
+
}
|
|
245
|
+
function getObjectPropertyName(name) {
|
|
246
|
+
if (typescript.default.isIdentifier(name) || typescript.default.isStringLiteral(name) || typescript.default.isNumericLiteral(name)) return name.text;
|
|
247
|
+
return null;
|
|
248
|
+
}
|
|
249
|
+
function isImportBindingDeclaration(declaration) {
|
|
250
|
+
return typescript.default.isImportClause(declaration) || typescript.default.isImportSpecifier(declaration) || typescript.default.isNamespaceImport(declaration) || typescript.default.isImportEqualsDeclaration(declaration);
|
|
251
|
+
}
|
|
252
|
+
function isServerOnlyProjectionProperty(node) {
|
|
253
|
+
const parent = node.parent;
|
|
254
|
+
if (!typescript.default.isObjectLiteralExpression(parent)) return false;
|
|
255
|
+
const call = parent.parent;
|
|
256
|
+
if (!typescript.default.isCallExpression(call) || !typescript.default.isIdentifier(call.expression)) return false;
|
|
257
|
+
const propertyName = typescript.default.isShorthandPropertyAssignment(node) ? node.name.text : getObjectPropertyName(node.name);
|
|
258
|
+
if (!propertyName) return false;
|
|
259
|
+
if (call.expression.text === "defineRoute" || call.expression.text === "defineLayout" || call.expression.text === "defineResource") return propertyName === "loader" || propertyName === "action" || propertyName === "middleware";
|
|
260
|
+
if (call.expression.text === "defineApiRoute") return true;
|
|
261
|
+
return false;
|
|
262
|
+
}
|
|
263
|
+
//#endregion
|
|
264
|
+
//#region src/vite.ts
|
|
265
|
+
const ROUTE_MANIFEST_ID = "virtual:litzjs:route-manifest";
|
|
266
|
+
const RESOLVED_ROUTE_MANIFEST_ID = "\0virtual:litzjs:route-manifest";
|
|
267
|
+
const RESOURCE_MANIFEST_ID = "virtual:litzjs:resource-manifest";
|
|
268
|
+
const RESOLVED_RESOURCE_MANIFEST_ID = "\0virtual:litzjs:resource-manifest";
|
|
269
|
+
const SERVER_MANIFEST_ID = "virtual:litzjs:server-manifest";
|
|
270
|
+
const RESOLVED_SERVER_MANIFEST_ID = "\0virtual:litzjs:server-manifest";
|
|
271
|
+
const LITZ_RSC_ENTRY_ID = "virtual:litzjs:rsc-entry";
|
|
272
|
+
const RESOLVED_LITZ_RSC_ENTRY_ID = "\0virtual:litzjs:rsc-entry";
|
|
273
|
+
const LITZ_BROWSER_ENTRY_ID = "virtual:litzjs:browser-entry";
|
|
274
|
+
const RESOLVED_LITZ_BROWSER_ENTRY_ID = "\0virtual:litzjs:browser-entry";
|
|
275
|
+
const LITZ_RSC_RENDERER_ID = "virtual:litzjs:rsc-renderer";
|
|
276
|
+
const RESOLVED_LITZ_RSC_RENDERER_ID = "\0virtual:litzjs:rsc-renderer";
|
|
277
|
+
function litz(options = {}) {
|
|
278
|
+
let root = process.cwd();
|
|
279
|
+
let browserEntryPath = "src/main.tsx";
|
|
280
|
+
let serverEntryPath = null;
|
|
281
|
+
let serverEntryFilePath = null;
|
|
282
|
+
let outputRootDir = node_path.default.resolve(root, "dist");
|
|
283
|
+
let clientOutDir = node_path.default.resolve(root, "dist/client");
|
|
284
|
+
let serverOutDir = node_path.default.resolve(root, "dist/server");
|
|
285
|
+
let serverRscOutDir = node_path.default.resolve(root, "dist/server/_rsc");
|
|
286
|
+
let routeManifest = [];
|
|
287
|
+
let layoutManifest = [];
|
|
288
|
+
let resourceManifest = [];
|
|
289
|
+
let apiManifest = [];
|
|
290
|
+
let clientProjectedFiles = /* @__PURE__ */ new Set();
|
|
291
|
+
let hasFinalizedServerArtifacts = false;
|
|
292
|
+
let hasRegisteredExitFinalizer = false;
|
|
293
|
+
const routePatterns = options.routes ?? [
|
|
294
|
+
"src/routes/**/*.{ts,tsx}",
|
|
295
|
+
"!src/routes/api/**/*.{ts,tsx}",
|
|
296
|
+
"!src/routes/resources/**/*.{ts,tsx}"
|
|
297
|
+
];
|
|
298
|
+
const resourcePatterns = options.resources ?? ["src/routes/resources/**/*.{ts,tsx}"];
|
|
299
|
+
const apiPatterns = options.api ?? ["src/routes/api/**/*.{ts,tsx}"];
|
|
300
|
+
const rscPlugins = (0, _vitejs_plugin_rsc.default)({
|
|
301
|
+
entries: {
|
|
302
|
+
client: LITZ_BROWSER_ENTRY_ID,
|
|
303
|
+
rsc: LITZ_RSC_ENTRY_ID
|
|
304
|
+
},
|
|
305
|
+
serverHandler: false
|
|
306
|
+
});
|
|
307
|
+
const litzPlugin = {
|
|
308
|
+
name: "litzjs/vite",
|
|
309
|
+
config(userConfig) {
|
|
310
|
+
const baseOutDir = userConfig.build?.outDir ?? "dist";
|
|
311
|
+
return { environments: {
|
|
312
|
+
client: { build: {
|
|
313
|
+
outDir: node_path.default.join(baseOutDir, "client"),
|
|
314
|
+
manifest: true
|
|
315
|
+
} },
|
|
316
|
+
rsc: { build: { outDir: node_path.default.join(baseOutDir, "server", "_rsc") } },
|
|
317
|
+
ssr: { build: { outDir: node_path.default.join(baseOutDir, "server", "_ssr") } }
|
|
318
|
+
} };
|
|
319
|
+
},
|
|
320
|
+
async configResolved(config) {
|
|
321
|
+
root = config.root;
|
|
322
|
+
outputRootDir = node_path.default.resolve(root, config.build.outDir || "dist");
|
|
323
|
+
clientOutDir = node_path.default.resolve(root, config.environments.client?.build.outDir || node_path.default.join("dist", "client"));
|
|
324
|
+
serverOutDir = node_path.default.resolve(root, node_path.default.join(config.build.outDir || "dist", "server"));
|
|
325
|
+
serverRscOutDir = node_path.default.resolve(root, config.environments.rsc?.build.outDir || node_path.default.join("dist", "server", "_rsc"));
|
|
326
|
+
browserEntryPath = await discoverBrowserEntry(root);
|
|
327
|
+
serverEntryPath = await discoverServerEntry(root, options.server);
|
|
328
|
+
serverEntryFilePath = serverEntryPath ? node_path.default.resolve(root, serverEntryPath) : null;
|
|
329
|
+
({routeManifest, layoutManifest, resourceManifest, apiManifest} = await discoverAllManifests(root, routePatterns, resourcePatterns, apiPatterns));
|
|
330
|
+
clientProjectedFiles = createClientProjectedFileSet(root, routeManifest, layoutManifest, resourceManifest, apiManifest);
|
|
331
|
+
},
|
|
332
|
+
resolveId(id) {
|
|
333
|
+
if (id === ROUTE_MANIFEST_ID) return RESOLVED_ROUTE_MANIFEST_ID;
|
|
334
|
+
if (id === RESOURCE_MANIFEST_ID) return RESOLVED_RESOURCE_MANIFEST_ID;
|
|
335
|
+
if (id === SERVER_MANIFEST_ID) return RESOLVED_SERVER_MANIFEST_ID;
|
|
336
|
+
if (id === LITZ_RSC_ENTRY_ID) return RESOLVED_LITZ_RSC_ENTRY_ID;
|
|
337
|
+
if (id === LITZ_BROWSER_ENTRY_ID) return RESOLVED_LITZ_BROWSER_ENTRY_ID;
|
|
338
|
+
if (id === LITZ_RSC_RENDERER_ID) return RESOLVED_LITZ_RSC_RENDERER_ID;
|
|
339
|
+
return null;
|
|
340
|
+
},
|
|
341
|
+
load(id) {
|
|
342
|
+
if (id === RESOLVED_ROUTE_MANIFEST_ID) return createRouteManifestModule(routeManifest, root, this.environment.name === "client");
|
|
343
|
+
if (id === RESOLVED_RESOURCE_MANIFEST_ID) return createResourceManifestModule(resourceManifest);
|
|
344
|
+
if (id === RESOLVED_SERVER_MANIFEST_ID) return createServerManifestModule(routeManifest, resourceManifest, apiManifest);
|
|
345
|
+
if (id === RESOLVED_LITZ_RSC_ENTRY_ID) {
|
|
346
|
+
if (serverEntryPath) return `export { default } from ${JSON.stringify(toProjectImportSpecifier(serverEntryPath))};`;
|
|
347
|
+
return `
|
|
348
|
+
import { createServer } from "litzjs/server";
|
|
349
|
+
import { serverManifest } from ${JSON.stringify(SERVER_MANIFEST_ID)};
|
|
350
|
+
|
|
351
|
+
export default createServer({
|
|
352
|
+
manifest: serverManifest,
|
|
353
|
+
createContext() {
|
|
354
|
+
return undefined;
|
|
355
|
+
},
|
|
356
|
+
});
|
|
357
|
+
`;
|
|
358
|
+
}
|
|
359
|
+
if (id === RESOLVED_LITZ_BROWSER_ENTRY_ID) return `import ${JSON.stringify(toImportSpecifier(root, browserEntryPath))};`;
|
|
360
|
+
if (id === RESOLVED_LITZ_RSC_RENDERER_ID) return `
|
|
361
|
+
import { renderToReadableStream } from "@vitejs/plugin-rsc/rsc";
|
|
362
|
+
|
|
363
|
+
export async function renderView(node, metadata = {}) {
|
|
364
|
+
const stream = renderToReadableStream(node);
|
|
365
|
+
return new Response(stream, {
|
|
366
|
+
status: metadata.status ?? 200,
|
|
367
|
+
headers: {
|
|
368
|
+
"content-type": "text/x-component",
|
|
369
|
+
"x-litzjs-kind": "view",
|
|
370
|
+
"x-litzjs-status": String(metadata.status ?? 200),
|
|
371
|
+
"x-litzjs-view-id": metadata.viewId ?? "litzjs#view",
|
|
372
|
+
"x-litzjs-revalidate": Array.isArray(metadata.revalidate) ? metadata.revalidate.join(",") : ""
|
|
373
|
+
}
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
`;
|
|
377
|
+
return null;
|
|
378
|
+
},
|
|
379
|
+
configureServer(server) {
|
|
380
|
+
const refreshManifests = async (changedFile) => {
|
|
381
|
+
if (changedFile && !/\.(ts|tsx)$/.test(changedFile)) return;
|
|
382
|
+
const next = await discoverAllManifests(root, routePatterns, resourcePatterns, apiPatterns);
|
|
383
|
+
const changed = JSON.stringify(routeManifest) !== JSON.stringify(next.routeManifest) || JSON.stringify(layoutManifest) !== JSON.stringify(next.layoutManifest) || JSON.stringify(resourceManifest) !== JSON.stringify(next.resourceManifest) || JSON.stringify(apiManifest) !== JSON.stringify(next.apiManifest);
|
|
384
|
+
routeManifest = next.routeManifest;
|
|
385
|
+
layoutManifest = next.layoutManifest;
|
|
386
|
+
resourceManifest = next.resourceManifest;
|
|
387
|
+
apiManifest = next.apiManifest;
|
|
388
|
+
clientProjectedFiles = createClientProjectedFileSet(root, routeManifest, layoutManifest, resourceManifest, apiManifest);
|
|
389
|
+
if (!changed) return;
|
|
390
|
+
invalidateVirtualModule(server, RESOLVED_ROUTE_MANIFEST_ID);
|
|
391
|
+
invalidateVirtualModule(server, RESOLVED_RESOURCE_MANIFEST_ID);
|
|
392
|
+
server.ws.send({ type: "full-reload" });
|
|
393
|
+
};
|
|
394
|
+
const onFsChange = (file) => {
|
|
395
|
+
refreshManifests(file);
|
|
396
|
+
};
|
|
397
|
+
server.watcher.on("add", onFsChange);
|
|
398
|
+
server.watcher.on("change", onFsChange);
|
|
399
|
+
server.watcher.on("unlink", onFsChange);
|
|
400
|
+
server.middlewares.use((request, response, next) => {
|
|
401
|
+
handleLitzResourceRequest(server, resourceManifest, request, response, next);
|
|
402
|
+
});
|
|
403
|
+
server.middlewares.use((request, response, next) => {
|
|
404
|
+
handleLitzRouteRequest(server, routeManifest, request, response, next);
|
|
405
|
+
});
|
|
406
|
+
server.middlewares.use((request, response, next) => {
|
|
407
|
+
handleLitzApiRequest(server, apiManifest, request, response, next);
|
|
408
|
+
});
|
|
409
|
+
server.middlewares.use((request, response, next) => {
|
|
410
|
+
handleLitzDocumentRequest(server, request, response, next);
|
|
411
|
+
});
|
|
412
|
+
},
|
|
413
|
+
async handleHotUpdate(context) {
|
|
414
|
+
if (!/\.(ts|tsx)$/.test(context.file)) return;
|
|
415
|
+
return context.modules;
|
|
416
|
+
},
|
|
417
|
+
async transform(code, id) {
|
|
418
|
+
const cleanId = normalizeViteModuleId(id);
|
|
419
|
+
if (this.environment.name === "rsc" && serverEntryFilePath && cleanId === serverEntryFilePath) {
|
|
420
|
+
const transformed = injectServerManifestIntoServerEntry(cleanId, code);
|
|
421
|
+
if (!transformed) return null;
|
|
422
|
+
return {
|
|
423
|
+
code: transformed,
|
|
424
|
+
map: null
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
if (this.environment.name !== "client") return null;
|
|
428
|
+
if (!clientProjectedFiles.has(cleanId)) return null;
|
|
429
|
+
const projected = createClientModuleProjection(cleanId, code);
|
|
430
|
+
if (!projected) return null;
|
|
431
|
+
return {
|
|
432
|
+
code: projected,
|
|
433
|
+
map: null
|
|
434
|
+
};
|
|
435
|
+
},
|
|
436
|
+
async closeBundle() {
|
|
437
|
+
await Promise.all([writeProductionIndexHtml(root, clientOutDir), removeLegacyBuildArtifacts(outputRootDir)]);
|
|
438
|
+
if (hasFinalizedServerArtifacts) return;
|
|
439
|
+
if (!hasRegisteredExitFinalizer) {
|
|
440
|
+
hasRegisteredExitFinalizer = true;
|
|
441
|
+
process.once("exit", () => {
|
|
442
|
+
if (hasFinalizedServerArtifacts) return;
|
|
443
|
+
hasFinalizedServerArtifacts = finalizeServerArtifacts(serverOutDir, serverRscOutDir, clientOutDir, !serverEntryPath);
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
hasFinalizedServerArtifacts = finalizeServerArtifacts(serverOutDir, serverRscOutDir, clientOutDir, !serverEntryPath);
|
|
447
|
+
}
|
|
448
|
+
};
|
|
449
|
+
return [...rscPlugins, litzPlugin];
|
|
450
|
+
}
|
|
451
|
+
async function discoverAllManifests(root, routePatterns, resourcePatterns, apiPatterns) {
|
|
452
|
+
const [nextRouteManifest, nextLayoutManifest, nextResourceManifest, nextApiManifest] = await Promise.all([
|
|
453
|
+
discoverRoutes(root, routePatterns),
|
|
454
|
+
discoverLayouts(root, routePatterns),
|
|
455
|
+
discoverResources(root, resourcePatterns),
|
|
456
|
+
discoverApiRoutes(root, apiPatterns)
|
|
457
|
+
]);
|
|
458
|
+
return {
|
|
459
|
+
routeManifest: require_internal_transport.sortByPathSpecificity(nextRouteManifest),
|
|
460
|
+
layoutManifest: nextLayoutManifest,
|
|
461
|
+
resourceManifest: nextResourceManifest,
|
|
462
|
+
apiManifest: require_internal_transport.sortByPathSpecificity(nextApiManifest)
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
async function discoverBrowserEntry(root) {
|
|
466
|
+
const indexHtmlPath = node_path.default.join(root, "index.html");
|
|
467
|
+
try {
|
|
468
|
+
const scriptSrc = (await (0, node_fs_promises.readFile)(indexHtmlPath, "utf8")).match(/<script[^>]+type=["']module["'][^>]+src=["']([^"']+)["'][^>]*><\/script>/i)?.[1];
|
|
469
|
+
if (!scriptSrc) return "src/main.tsx";
|
|
470
|
+
return scriptSrc.startsWith("/") ? scriptSrc.slice(1) : scriptSrc;
|
|
471
|
+
} catch {
|
|
472
|
+
return "src/main.tsx";
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
async function discoverServerEntry(root, configuredPath) {
|
|
476
|
+
const candidates = configuredPath ? [configuredPath] : ["src/server.ts", "src/server/index.ts"];
|
|
477
|
+
for (const candidate of candidates) {
|
|
478
|
+
const absolutePath = node_path.default.resolve(root, candidate);
|
|
479
|
+
if (typescript.default.sys.fileExists(absolutePath)) return normalizeRelativePath(root, absolutePath);
|
|
480
|
+
}
|
|
481
|
+
return null;
|
|
482
|
+
}
|
|
483
|
+
async function discoverRoutes(root, patterns) {
|
|
484
|
+
const files = await (0, tinyglobby.glob)(patterns, {
|
|
485
|
+
cwd: root,
|
|
486
|
+
absolute: true
|
|
487
|
+
});
|
|
488
|
+
return (await Promise.all(files.map(async (file) => discoverRouteFromFile(root, file)))).filter((entry) => entry !== null);
|
|
489
|
+
}
|
|
490
|
+
async function discoverLayouts(root, patterns) {
|
|
491
|
+
const files = await (0, tinyglobby.glob)(patterns, {
|
|
492
|
+
cwd: root,
|
|
493
|
+
absolute: true
|
|
494
|
+
});
|
|
495
|
+
return (await Promise.all(files.map(async (file) => discoverLayoutFromFile(root, file)))).filter((entry) => entry !== null);
|
|
496
|
+
}
|
|
497
|
+
async function discoverRouteFromFile(root, file) {
|
|
498
|
+
const match = (await (0, node_fs_promises.readFile)(file, "utf8")).match(/export\s+const\s+route\s*=\s*defineRoute(?:<[\s\S]*?>)?\(\s*["'`]([^"'`]+)["'`]/);
|
|
499
|
+
if (!match) return null;
|
|
500
|
+
const routePath = match[1];
|
|
501
|
+
if (!routePath) return null;
|
|
502
|
+
return {
|
|
503
|
+
id: routePath,
|
|
504
|
+
path: routePath,
|
|
505
|
+
modulePath: normalizeRelativePath(root, file)
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
async function discoverLayoutFromFile(root, file) {
|
|
509
|
+
const match = (await (0, node_fs_promises.readFile)(file, "utf8")).match(/export\s+const\s+layout\s*=\s*defineLayout(?:<[\s\S]*?>)?\(\s*["'`]([^"'`]+)["'`]/);
|
|
510
|
+
if (!match) return null;
|
|
511
|
+
const layoutPath = match[1];
|
|
512
|
+
if (!layoutPath) return null;
|
|
513
|
+
return {
|
|
514
|
+
id: layoutPath,
|
|
515
|
+
path: layoutPath,
|
|
516
|
+
modulePath: normalizeRelativePath(root, file)
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
async function discoverResources(root, patterns) {
|
|
520
|
+
const files = await (0, tinyglobby.glob)(patterns, {
|
|
521
|
+
cwd: root,
|
|
522
|
+
absolute: true
|
|
523
|
+
});
|
|
524
|
+
return (await Promise.all(files.map(async (file) => discoverResourceFromFile(root, file)))).filter((entry) => entry !== null);
|
|
525
|
+
}
|
|
526
|
+
async function discoverResourceFromFile(root, file) {
|
|
527
|
+
const source = await (0, node_fs_promises.readFile)(file, "utf8");
|
|
528
|
+
const pathMatch = source.match(/export\s+const\s+resource\s*=\s*defineResource(?:<[\s\S]*?>)?\(\s*["'`]([^"'`]+)["'`]/);
|
|
529
|
+
if (!pathMatch) return null;
|
|
530
|
+
const resourcePath = pathMatch[1];
|
|
531
|
+
if (!resourcePath) return null;
|
|
532
|
+
return {
|
|
533
|
+
path: resourcePath,
|
|
534
|
+
modulePath: normalizeRelativePath(root, file),
|
|
535
|
+
hasLoader: /\bloader\s*:/.test(source),
|
|
536
|
+
hasAction: /\baction\s*:/.test(source),
|
|
537
|
+
hasComponent: /\bcomponent\s*:/.test(source)
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
async function discoverApiRoutes(root, patterns) {
|
|
541
|
+
const files = await (0, tinyglobby.glob)(patterns, {
|
|
542
|
+
cwd: root,
|
|
543
|
+
absolute: true
|
|
544
|
+
});
|
|
545
|
+
return (await Promise.all(files.map(async (file) => discoverApiRouteFromFile(root, file)))).filter((entry) => entry !== null);
|
|
546
|
+
}
|
|
547
|
+
async function discoverApiRouteFromFile(root, file) {
|
|
548
|
+
const match = (await (0, node_fs_promises.readFile)(file, "utf8")).match(/export\s+const\s+api\s*=\s*defineApiRoute(?:<[\s\S]*?>)?\(\s*["'`]([^"'`]+)["'`]/);
|
|
549
|
+
if (!match) return null;
|
|
550
|
+
const apiPath = match[1];
|
|
551
|
+
if (!apiPath) return null;
|
|
552
|
+
return {
|
|
553
|
+
path: apiPath,
|
|
554
|
+
modulePath: normalizeRelativePath(root, file)
|
|
555
|
+
};
|
|
556
|
+
}
|
|
557
|
+
function createRouteManifestModule(manifest, root, lazy) {
|
|
558
|
+
if (!lazy) {
|
|
559
|
+
const imports = [];
|
|
560
|
+
const lines = manifest.map((route, index) => {
|
|
561
|
+
const importName = `routeModule${index}`;
|
|
562
|
+
imports.push(`import * as ${importName} from ${JSON.stringify(toProjectImportSpecifier(route.modulePath))};`);
|
|
563
|
+
return [
|
|
564
|
+
` {`,
|
|
565
|
+
` id: ${JSON.stringify(route.id)},`,
|
|
566
|
+
` path: ${JSON.stringify(route.path)},`,
|
|
567
|
+
` load: async () => ({ route: ${importName}.route })`,
|
|
568
|
+
` }${index === manifest.length - 1 ? "" : ","}`
|
|
569
|
+
].join("\n");
|
|
570
|
+
});
|
|
571
|
+
return [
|
|
572
|
+
...imports,
|
|
573
|
+
"",
|
|
574
|
+
`export const routeManifest = [`,
|
|
575
|
+
lines.join("\n"),
|
|
576
|
+
`];`
|
|
577
|
+
].join("\n");
|
|
578
|
+
}
|
|
579
|
+
return [
|
|
580
|
+
`export const routeManifest = [`,
|
|
581
|
+
manifest.map((route, index) => {
|
|
582
|
+
const importPath = toImportSpecifier(root, route.modulePath);
|
|
583
|
+
return [
|
|
584
|
+
` {`,
|
|
585
|
+
` id: ${JSON.stringify(route.id)},`,
|
|
586
|
+
` path: ${JSON.stringify(route.path)},`,
|
|
587
|
+
` load: () => import(${JSON.stringify(importPath)})`,
|
|
588
|
+
` }${index === manifest.length - 1 ? "" : ","}`
|
|
589
|
+
].join("\n");
|
|
590
|
+
}).join("\n"),
|
|
591
|
+
`];`
|
|
592
|
+
].join("\n");
|
|
593
|
+
}
|
|
594
|
+
function createClientProjectedFileSet(root, routes, layouts, resources, apiRoutes) {
|
|
595
|
+
return new Set([
|
|
596
|
+
...routes,
|
|
597
|
+
...layouts,
|
|
598
|
+
...resources,
|
|
599
|
+
...apiRoutes
|
|
600
|
+
].map((entry) => node_path.default.resolve(root, entry.modulePath)));
|
|
601
|
+
}
|
|
602
|
+
function injectServerManifestIntoServerEntry(filePath, source) {
|
|
603
|
+
const scriptKind = filePath.endsWith(".tsx") ? typescript.default.ScriptKind.TSX : typescript.default.ScriptKind.TS;
|
|
604
|
+
const sourceFile = typescript.default.createSourceFile(filePath, source, typescript.default.ScriptTarget.Latest, true, scriptKind);
|
|
605
|
+
const createServerImportNames = /* @__PURE__ */ new Set();
|
|
606
|
+
for (const statement of sourceFile.statements) {
|
|
607
|
+
if (!typescript.default.isImportDeclaration(statement) || !typescript.default.isStringLiteral(statement.moduleSpecifier)) continue;
|
|
608
|
+
if (statement.moduleSpecifier.text !== "litzjs/server") continue;
|
|
609
|
+
const namedBindings = statement.importClause?.namedBindings;
|
|
610
|
+
if (!namedBindings || !typescript.default.isNamedImports(namedBindings)) continue;
|
|
611
|
+
for (const element of namedBindings.elements) if ((element.propertyName?.text ?? element.name.text) === "createServer") createServerImportNames.add(element.name.text);
|
|
612
|
+
}
|
|
613
|
+
if (createServerImportNames.size === 0) return null;
|
|
614
|
+
const result = typescript.default.transform(sourceFile, [(context) => {
|
|
615
|
+
const visit = (node) => {
|
|
616
|
+
if (typescript.default.isCallExpression(node) && typescript.default.isIdentifier(node.expression) && createServerImportNames.has(node.expression.text)) return typescript.default.factory.updateCallExpression(node, node.expression, node.typeArguments, [typescript.default.factory.createCallExpression(typescript.default.factory.createIdentifier("__litzjsMergeServerOptions"), void 0, [node.arguments[0] ?? typescript.default.factory.createIdentifier("undefined")])]);
|
|
617
|
+
return typescript.default.visitEachChild(node, visit, context);
|
|
618
|
+
};
|
|
619
|
+
return (node) => typescript.default.visitEachChild(node, visit, context);
|
|
620
|
+
}]);
|
|
621
|
+
const transformedSource = result.transformed[0];
|
|
622
|
+
result.dispose();
|
|
623
|
+
const importStatement = typescript.default.factory.createImportDeclaration(void 0, typescript.default.factory.createImportClause(false, void 0, typescript.default.factory.createNamedImports([typescript.default.factory.createImportSpecifier(false, typescript.default.factory.createIdentifier("serverManifest"), typescript.default.factory.createIdentifier("__litzjsServerManifest"))])), typescript.default.factory.createStringLiteral(SERVER_MANIFEST_ID), void 0);
|
|
624
|
+
const helperStatement = typescript.default.factory.createVariableStatement(void 0, typescript.default.factory.createVariableDeclarationList([typescript.default.factory.createVariableDeclaration(typescript.default.factory.createIdentifier("__litzjsMergeServerOptions"), void 0, void 0, typescript.default.factory.createArrowFunction(void 0, void 0, [typescript.default.factory.createParameterDeclaration(void 0, void 0, typescript.default.factory.createIdentifier("options"))], void 0, typescript.default.factory.createToken(typescript.default.SyntaxKind.EqualsGreaterThanToken), typescript.default.factory.createParenthesizedExpression(typescript.default.factory.createObjectLiteralExpression([typescript.default.factory.createPropertyAssignment(typescript.default.factory.createIdentifier("manifest"), typescript.default.factory.createIdentifier("__litzjsServerManifest")), typescript.default.factory.createSpreadAssignment(typescript.default.factory.createBinaryExpression(typescript.default.factory.createIdentifier("options"), typescript.default.factory.createToken(typescript.default.SyntaxKind.QuestionQuestionToken), typescript.default.factory.createObjectLiteralExpression()))], true))))], typescript.default.NodeFlags.Const));
|
|
625
|
+
const printer = typescript.default.createPrinter({ newLine: typescript.default.NewLineKind.LineFeed });
|
|
626
|
+
return [
|
|
627
|
+
printer.printNode(typescript.default.EmitHint.Unspecified, importStatement, transformedSource),
|
|
628
|
+
printer.printNode(typescript.default.EmitHint.Unspecified, helperStatement, transformedSource),
|
|
629
|
+
...transformedSource.statements.map((statement) => printer.printNode(typescript.default.EmitHint.Unspecified, statement, transformedSource)),
|
|
630
|
+
""
|
|
631
|
+
].join("\n\n");
|
|
632
|
+
}
|
|
633
|
+
function normalizeViteModuleId(id) {
|
|
634
|
+
return node_path.default.resolve(id.replace(/[?#].*$/, ""));
|
|
635
|
+
}
|
|
636
|
+
function createResourceManifestModule(manifest) {
|
|
637
|
+
return `export const resourceManifest = ${JSON.stringify(manifest, null, 2)};`;
|
|
638
|
+
}
|
|
639
|
+
function createServerManifestModule(routes, resources, apiRoutes) {
|
|
640
|
+
const imports = [];
|
|
641
|
+
const routeEntries = routes.map((entry, index) => {
|
|
642
|
+
const name = `routeModule${index}`;
|
|
643
|
+
imports.push(`import * as ${name} from ${JSON.stringify(toProjectImportSpecifier(entry.modulePath))};`);
|
|
644
|
+
return `{ id: ${JSON.stringify(entry.id)}, path: ${JSON.stringify(entry.path)}, route: ${name}.route }`;
|
|
645
|
+
});
|
|
646
|
+
const resourceEntries = resources.map((entry, index) => {
|
|
647
|
+
const name = `resourceModule${index}`;
|
|
648
|
+
imports.push(`import * as ${name} from ${JSON.stringify(toProjectImportSpecifier(entry.modulePath))};`);
|
|
649
|
+
return `{ path: ${JSON.stringify(entry.path)}, resource: ${name}.resource }`;
|
|
650
|
+
});
|
|
651
|
+
const apiEntries = apiRoutes.map((entry, index) => {
|
|
652
|
+
const name = `apiModule${index}`;
|
|
653
|
+
imports.push(`import * as ${name} from ${JSON.stringify(toProjectImportSpecifier(entry.modulePath))};`);
|
|
654
|
+
return `{ path: ${JSON.stringify(entry.path)}, api: ${name}.api }`;
|
|
655
|
+
});
|
|
656
|
+
return [
|
|
657
|
+
...imports,
|
|
658
|
+
"",
|
|
659
|
+
"export const serverManifest = {",
|
|
660
|
+
` routes: [${routeEntries.join(", ")}],`,
|
|
661
|
+
` resources: [${resourceEntries.join(", ")}],`,
|
|
662
|
+
` apiRoutes: [${apiEntries.join(", ")}],`,
|
|
663
|
+
"};"
|
|
664
|
+
].join("\n");
|
|
665
|
+
}
|
|
666
|
+
function invalidateVirtualModule(server, id) {
|
|
667
|
+
const module = server.moduleGraph.getModuleById(id);
|
|
668
|
+
if (module) server.moduleGraph.invalidateModule(module);
|
|
669
|
+
}
|
|
670
|
+
function normalizeRelativePath(root, file) {
|
|
671
|
+
return node_path.default.relative(root, file).split(node_path.default.sep).join("/");
|
|
672
|
+
}
|
|
673
|
+
function toImportSpecifier(root, relativeModulePath) {
|
|
674
|
+
return `/@fs/${node_path.default.resolve(root, relativeModulePath).split(node_path.default.sep).join("/")}`;
|
|
675
|
+
}
|
|
676
|
+
function toProjectImportSpecifier(relativeModulePath) {
|
|
677
|
+
return `/${relativeModulePath}`;
|
|
678
|
+
}
|
|
679
|
+
async function handleLitzResourceRequest(server, manifest, request, response, next) {
|
|
680
|
+
if (!request.url?.startsWith("/_litzjs/resource")) {
|
|
681
|
+
next();
|
|
682
|
+
return;
|
|
683
|
+
}
|
|
684
|
+
if (request.method !== "POST") {
|
|
685
|
+
response.statusCode = 405;
|
|
686
|
+
response.end("Method Not Allowed");
|
|
687
|
+
return;
|
|
688
|
+
}
|
|
689
|
+
try {
|
|
690
|
+
const internalRequest = await createNodeRequest(request);
|
|
691
|
+
const body = await require_request_headers.parseInternalRequestBody(internalRequest);
|
|
692
|
+
const resourcePath = body.path;
|
|
693
|
+
const operation = body.operation ?? "loader";
|
|
694
|
+
const entry = manifest.find((resource) => resource.path === resourcePath);
|
|
695
|
+
if (!resourcePath || !entry) {
|
|
696
|
+
sendLitzJson(response, 404, {
|
|
697
|
+
kind: "error",
|
|
698
|
+
message: "Resource not found."
|
|
699
|
+
});
|
|
700
|
+
return;
|
|
701
|
+
}
|
|
702
|
+
const resource = (await loadLitzServerModule(server, toImportSpecifier(server.config.root, entry.modulePath))).resource;
|
|
703
|
+
if (!resource) {
|
|
704
|
+
sendLitzJson(response, 500, {
|
|
705
|
+
kind: "fault",
|
|
706
|
+
message: "Resource module did not export resource."
|
|
707
|
+
});
|
|
708
|
+
return;
|
|
709
|
+
}
|
|
710
|
+
const handler = operation === "action" ? resource.action : resource.loader;
|
|
711
|
+
if (!handler) {
|
|
712
|
+
sendLitzJson(response, 405, {
|
|
713
|
+
kind: "error",
|
|
714
|
+
message: `Resource does not define a ${operation}.`
|
|
715
|
+
});
|
|
716
|
+
return;
|
|
717
|
+
}
|
|
718
|
+
const normalizedRequest = normalizeInternalResourceRequest(internalRequest, resourcePath, body.request, body.payload);
|
|
719
|
+
const signal = new AbortController().signal;
|
|
720
|
+
await sendServerResult(server, response, await runDevMiddlewareChain({
|
|
721
|
+
middleware: resource.middleware ?? [],
|
|
722
|
+
request: normalizedRequest.request,
|
|
723
|
+
params: normalizedRequest.params,
|
|
724
|
+
signal,
|
|
725
|
+
context: void 0,
|
|
726
|
+
execute(nextContext) {
|
|
727
|
+
return handler({
|
|
728
|
+
request: normalizedRequest.request,
|
|
729
|
+
params: normalizedRequest.params,
|
|
730
|
+
signal,
|
|
731
|
+
context: nextContext
|
|
732
|
+
});
|
|
733
|
+
}
|
|
734
|
+
}), `${entry.path}#${operation}`);
|
|
735
|
+
} catch (error) {
|
|
736
|
+
server.ssrFixStacktrace(error);
|
|
737
|
+
sendLitzJson(response, 500, {
|
|
738
|
+
kind: "fault",
|
|
739
|
+
message: error instanceof Error ? error.message : "Resource request failed."
|
|
740
|
+
});
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
async function handleLitzRouteRequest(server, manifest, request, response, next) {
|
|
744
|
+
if (!request.url?.startsWith("/_litzjs/route") && !request.url?.startsWith("/_litzjs/action")) {
|
|
745
|
+
next();
|
|
746
|
+
return;
|
|
747
|
+
}
|
|
748
|
+
if (request.method !== "POST") {
|
|
749
|
+
response.statusCode = 405;
|
|
750
|
+
response.end("Method Not Allowed");
|
|
751
|
+
return;
|
|
752
|
+
}
|
|
753
|
+
try {
|
|
754
|
+
const internalRequest = await createNodeRequest(request);
|
|
755
|
+
const body = await require_request_headers.parseInternalRequestBody(internalRequest);
|
|
756
|
+
const routePath = body.path;
|
|
757
|
+
const targetId = body.target;
|
|
758
|
+
const operation = body.operation ?? (request.url.startsWith("/_litzjs/action") ? "action" : "loader");
|
|
759
|
+
const entry = manifest.find((route) => route.path === routePath);
|
|
760
|
+
if (!routePath || !entry) {
|
|
761
|
+
sendLitzJson(response, 404, {
|
|
762
|
+
kind: "error",
|
|
763
|
+
message: "Route not found."
|
|
764
|
+
});
|
|
765
|
+
return;
|
|
766
|
+
}
|
|
767
|
+
const route = (await loadLitzServerModule(server, toImportSpecifier(server.config.root, entry.modulePath))).route;
|
|
768
|
+
if (!route) {
|
|
769
|
+
sendLitzJson(response, 500, {
|
|
770
|
+
kind: "fault",
|
|
771
|
+
message: "Route module did not export route."
|
|
772
|
+
});
|
|
773
|
+
return;
|
|
774
|
+
}
|
|
775
|
+
const chain = getDevRouteMatchChain({
|
|
776
|
+
id: entry.id,
|
|
777
|
+
path: entry.path,
|
|
778
|
+
route
|
|
779
|
+
});
|
|
780
|
+
const target = operation === "action" ? chain[chain.length - 1] : findDevTargetRouteMatch(chain, targetId ?? routePath);
|
|
781
|
+
if (!target) {
|
|
782
|
+
sendLitzJson(response, 404, {
|
|
783
|
+
kind: "error",
|
|
784
|
+
message: "Route target not found."
|
|
785
|
+
});
|
|
786
|
+
return;
|
|
787
|
+
}
|
|
788
|
+
const targetIndex = chain.findIndex((candidate) => candidate.id === target.id);
|
|
789
|
+
const handler = operation === "action" ? route.action ?? route.options?.action : target.loader;
|
|
790
|
+
if (!handler) {
|
|
791
|
+
sendLitzJson(response, 405, {
|
|
792
|
+
kind: "error",
|
|
793
|
+
message: `Route does not define a ${operation}.`
|
|
794
|
+
});
|
|
795
|
+
return;
|
|
796
|
+
}
|
|
797
|
+
const normalizedRequest = normalizeInternalResourceRequest(internalRequest, routePath, body.request, body.payload);
|
|
798
|
+
const signal = new AbortController().signal;
|
|
799
|
+
await sendServerResult(server, response, await runDevMiddlewareChain({
|
|
800
|
+
middleware: chain.slice(0, targetIndex + 1).flatMap((candidate) => candidate.middleware),
|
|
801
|
+
request: normalizedRequest.request,
|
|
802
|
+
params: operation === "action" ? normalizedRequest.params : require_internal_transport.extractRouteLikeParams(target.path, new URL(normalizedRequest.request.url).pathname) ?? normalizedRequest.params,
|
|
803
|
+
signal,
|
|
804
|
+
context: void 0,
|
|
805
|
+
execute(nextContext) {
|
|
806
|
+
const params = operation === "action" ? normalizedRequest.params : require_internal_transport.extractRouteLikeParams(target.path, new URL(normalizedRequest.request.url).pathname) ?? normalizedRequest.params;
|
|
807
|
+
return handler({
|
|
808
|
+
request: normalizedRequest.request,
|
|
809
|
+
params,
|
|
810
|
+
signal,
|
|
811
|
+
context: nextContext
|
|
812
|
+
});
|
|
813
|
+
}
|
|
814
|
+
}), `${target.id}#${operation}`);
|
|
815
|
+
} catch (error) {
|
|
816
|
+
server.ssrFixStacktrace(error);
|
|
817
|
+
sendLitzJson(response, 500, {
|
|
818
|
+
kind: "fault",
|
|
819
|
+
message: error instanceof Error ? error.message : "Route request failed."
|
|
820
|
+
});
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
async function handleLitzDocumentRequest(server, request, response, next) {
|
|
824
|
+
const url = request.url ?? "/";
|
|
825
|
+
if (request.method !== "GET" && request.method !== "HEAD") {
|
|
826
|
+
next();
|
|
827
|
+
return;
|
|
828
|
+
}
|
|
829
|
+
if (url.startsWith("/_litzjs/") || url.startsWith("/@") || url.startsWith("/node_modules/")) {
|
|
830
|
+
next();
|
|
831
|
+
return;
|
|
832
|
+
}
|
|
833
|
+
if (node_path.default.extname(url)) {
|
|
834
|
+
next();
|
|
835
|
+
return;
|
|
836
|
+
}
|
|
837
|
+
const accept = request.headers.accept ?? "";
|
|
838
|
+
if (!accept.includes("text/html") && !accept.includes("*/*")) {
|
|
839
|
+
next();
|
|
840
|
+
return;
|
|
841
|
+
}
|
|
842
|
+
try {
|
|
843
|
+
const template = await (0, node_fs_promises.readFile)(node_path.default.join(server.config.root, "index.html"), "utf8");
|
|
844
|
+
const html = await server.transformIndexHtml(url, template);
|
|
845
|
+
response.statusCode = 200;
|
|
846
|
+
response.setHeader("content-type", "text/html; charset=utf-8");
|
|
847
|
+
response.end(html);
|
|
848
|
+
} catch (error) {
|
|
849
|
+
server.ssrFixStacktrace(error);
|
|
850
|
+
next(error);
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
async function handleLitzApiRequest(server, manifest, request, response, next) {
|
|
854
|
+
const requestUrl = request.url ? new URL(request.url, "http://litzjs.local") : null;
|
|
855
|
+
if (!requestUrl) {
|
|
856
|
+
next();
|
|
857
|
+
return;
|
|
858
|
+
}
|
|
859
|
+
const matched = manifest.find((entry) => matchPathPattern(entry.path, requestUrl.pathname));
|
|
860
|
+
if (!matched) {
|
|
861
|
+
next();
|
|
862
|
+
return;
|
|
863
|
+
}
|
|
864
|
+
try {
|
|
865
|
+
const api = (await server.ssrLoadModule(toImportSpecifier(server.config.root, matched.modulePath))).api;
|
|
866
|
+
const method = (request.method ?? "GET").toUpperCase();
|
|
867
|
+
const handler = api?.methods?.[method] ?? api?.methods?.ALL;
|
|
868
|
+
const matchedParams = require_internal_transport.matchPathname(matched.path, requestUrl.pathname);
|
|
869
|
+
if (!handler) {
|
|
870
|
+
response.statusCode = 405;
|
|
871
|
+
response.end("Method Not Allowed");
|
|
872
|
+
return;
|
|
873
|
+
}
|
|
874
|
+
const apiRequest = await createNodeRequest(request, requestUrl);
|
|
875
|
+
const signal = new AbortController().signal;
|
|
876
|
+
await writeFetchResponseToNode(response, await runDevMiddlewareChain({
|
|
877
|
+
middleware: api?.middleware ?? [],
|
|
878
|
+
request: apiRequest,
|
|
879
|
+
params: matchedParams ?? {},
|
|
880
|
+
signal,
|
|
881
|
+
context: void 0,
|
|
882
|
+
execute(nextContext) {
|
|
883
|
+
return handler({
|
|
884
|
+
request: apiRequest,
|
|
885
|
+
params: matchedParams ?? {},
|
|
886
|
+
signal,
|
|
887
|
+
context: nextContext
|
|
888
|
+
});
|
|
889
|
+
}
|
|
890
|
+
}));
|
|
891
|
+
} catch (error) {
|
|
892
|
+
server.ssrFixStacktrace(error);
|
|
893
|
+
response.statusCode = 500;
|
|
894
|
+
response.end(error instanceof Error ? error.message : "API route failed.");
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
async function readRequestBuffer(request) {
|
|
898
|
+
const chunks = [];
|
|
899
|
+
for await (const chunk of request) chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
900
|
+
return Buffer.concat(chunks);
|
|
901
|
+
}
|
|
902
|
+
async function createNodeRequest(request, url = createIncomingRequestUrl(request)) {
|
|
903
|
+
const headers = new Headers();
|
|
904
|
+
for (const [key, value] of Object.entries(request.headers)) if (Array.isArray(value)) for (const item of value) headers.append(key, item);
|
|
905
|
+
else if (typeof value === "string") headers.set(key, value);
|
|
906
|
+
const body = request.method === "GET" || request.method === "HEAD" ? void 0 : await readRequestBuffer(request);
|
|
907
|
+
return new Request(url, {
|
|
908
|
+
method: request.method,
|
|
909
|
+
headers,
|
|
910
|
+
body: body ? new Uint8Array(body) : void 0
|
|
911
|
+
});
|
|
912
|
+
}
|
|
913
|
+
function createIncomingRequestUrl(request) {
|
|
914
|
+
const host = getForwardedRequestValue(request.headers["x-forwarded-host"]) ?? request.headers.host;
|
|
915
|
+
const socket = request.socket;
|
|
916
|
+
const protocol = getForwardedRequestValue(request.headers["x-forwarded-proto"]) ?? (socket.encrypted ? "https" : "http");
|
|
917
|
+
return new URL(request.url ?? "/", `${protocol}://${host ?? "litzjs.local"}`);
|
|
918
|
+
}
|
|
919
|
+
function getForwardedRequestValue(value) {
|
|
920
|
+
const raw = Array.isArray(value) ? value[0] : value;
|
|
921
|
+
if (!raw) return;
|
|
922
|
+
return raw.split(",").map((entry) => entry.trim()).find(Boolean);
|
|
923
|
+
}
|
|
924
|
+
function normalizeInternalResourceRequest(originalRequest, resourcePath, requestData, payload) {
|
|
925
|
+
const params = requestData?.params ?? {};
|
|
926
|
+
const search = new URLSearchParams(requestData?.search ?? {});
|
|
927
|
+
const url = new URL(originalRequest.url);
|
|
928
|
+
url.pathname = interpolatePath(resourcePath, params);
|
|
929
|
+
url.search = search.toString();
|
|
930
|
+
url.hash = "";
|
|
931
|
+
let body;
|
|
932
|
+
if (payload) {
|
|
933
|
+
body = new FormData();
|
|
934
|
+
for (const [key, value] of payload.entries) body.append(key, value);
|
|
935
|
+
}
|
|
936
|
+
return {
|
|
937
|
+
request: new Request(url, {
|
|
938
|
+
method: body ? "POST" : "GET",
|
|
939
|
+
headers: require_request_headers.createInternalHandlerHeaders(originalRequest.headers),
|
|
940
|
+
body
|
|
941
|
+
}),
|
|
942
|
+
params
|
|
943
|
+
};
|
|
944
|
+
}
|
|
945
|
+
async function sendServerResult(server, response, result, viewId = "litzjs#view") {
|
|
946
|
+
if (!result || typeof result !== "object" || !("kind" in result)) {
|
|
947
|
+
sendLitzJson(response, 500, {
|
|
948
|
+
kind: "fault",
|
|
949
|
+
message: "Handler returned an unknown result."
|
|
950
|
+
});
|
|
951
|
+
return;
|
|
952
|
+
}
|
|
953
|
+
const serverResult = result;
|
|
954
|
+
applyHeaders(response, serverResult.headers);
|
|
955
|
+
applyRevalidateHeader(response, serverResult.revalidate);
|
|
956
|
+
switch (serverResult.kind) {
|
|
957
|
+
case "data":
|
|
958
|
+
sendLitzJson(response, serverResult.status ?? 200, {
|
|
959
|
+
kind: "data",
|
|
960
|
+
data: serverResult.data,
|
|
961
|
+
revalidate: serverResult.revalidate ?? []
|
|
962
|
+
});
|
|
963
|
+
return;
|
|
964
|
+
case "invalid":
|
|
965
|
+
sendLitzJson(response, serverResult.status ?? 422, {
|
|
966
|
+
kind: "invalid",
|
|
967
|
+
fields: serverResult.fields,
|
|
968
|
+
formError: serverResult.formError,
|
|
969
|
+
data: serverResult.data
|
|
970
|
+
});
|
|
971
|
+
return;
|
|
972
|
+
case "redirect":
|
|
973
|
+
sendLitzJson(response, serverResult.status ?? 303, {
|
|
974
|
+
kind: "redirect",
|
|
975
|
+
location: serverResult.location,
|
|
976
|
+
replace: serverResult.replace ?? false,
|
|
977
|
+
revalidate: serverResult.revalidate ?? []
|
|
978
|
+
});
|
|
979
|
+
return;
|
|
980
|
+
case "error":
|
|
981
|
+
sendLitzJson(response, serverResult.status ?? 500, {
|
|
982
|
+
kind: "error",
|
|
983
|
+
message: serverResult.message ?? "Error",
|
|
984
|
+
code: serverResult.code,
|
|
985
|
+
data: serverResult.data
|
|
986
|
+
});
|
|
987
|
+
return;
|
|
988
|
+
case "fault":
|
|
989
|
+
sendLitzJson(response, serverResult.status ?? 500, {
|
|
990
|
+
kind: "fault",
|
|
991
|
+
message: serverResult.message ?? "Fault",
|
|
992
|
+
digest: serverResult.digest
|
|
993
|
+
});
|
|
994
|
+
return;
|
|
995
|
+
case "view":
|
|
996
|
+
await writeFetchResponseToNode(response, await (await loadRscRenderer(server)).renderView(serverResult.node, {
|
|
997
|
+
status: serverResult.status ?? 200,
|
|
998
|
+
viewId,
|
|
999
|
+
revalidate: serverResult.revalidate ?? []
|
|
1000
|
+
}));
|
|
1001
|
+
return;
|
|
1002
|
+
default: sendLitzJson(response, 500, {
|
|
1003
|
+
kind: "fault",
|
|
1004
|
+
message: `Unsupported result kind "${serverResult.kind}".`
|
|
1005
|
+
});
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
async function loadLitzServerModule(server, id) {
|
|
1009
|
+
const environment = getRscEnvironment(server);
|
|
1010
|
+
const resolved = await environment.pluginContainer.resolveId(id);
|
|
1011
|
+
if (!resolved) throw new Error(`Failed to resolve Litz server module "${id}".`);
|
|
1012
|
+
return environment.runner.import(resolved.id);
|
|
1013
|
+
}
|
|
1014
|
+
async function loadRscRenderer(server) {
|
|
1015
|
+
return loadLitzServerModule(server, LITZ_RSC_RENDERER_ID);
|
|
1016
|
+
}
|
|
1017
|
+
function getRscEnvironment(server) {
|
|
1018
|
+
return server.environments.rsc;
|
|
1019
|
+
}
|
|
1020
|
+
function sendLitzJson(response, status, body) {
|
|
1021
|
+
response.statusCode = status;
|
|
1022
|
+
response.setHeader("content-type", "application/vnd.litzjs.result+json");
|
|
1023
|
+
response.end(JSON.stringify(body));
|
|
1024
|
+
}
|
|
1025
|
+
function applyHeaders(response, headers) {
|
|
1026
|
+
if (!headers) return;
|
|
1027
|
+
new Headers(headers).forEach((value, key) => {
|
|
1028
|
+
response.setHeader(key, value);
|
|
1029
|
+
});
|
|
1030
|
+
}
|
|
1031
|
+
function applyRevalidateHeader(response, revalidate) {
|
|
1032
|
+
if (!revalidate?.length) return;
|
|
1033
|
+
response.setHeader("x-litzjs-revalidate", revalidate.join(","));
|
|
1034
|
+
}
|
|
1035
|
+
async function writeFetchResponseToNode(response, fetchResponse) {
|
|
1036
|
+
response.statusCode = fetchResponse.status;
|
|
1037
|
+
fetchResponse.headers.forEach((value, key) => {
|
|
1038
|
+
response.setHeader(key, value);
|
|
1039
|
+
});
|
|
1040
|
+
if (!fetchResponse.body) {
|
|
1041
|
+
response.end();
|
|
1042
|
+
return;
|
|
1043
|
+
}
|
|
1044
|
+
const reader = fetchResponse.body.getReader();
|
|
1045
|
+
while (true) {
|
|
1046
|
+
const chunk = await reader.read();
|
|
1047
|
+
if (chunk.done) break;
|
|
1048
|
+
response.write(Buffer.from(chunk.value));
|
|
1049
|
+
}
|
|
1050
|
+
response.end();
|
|
1051
|
+
}
|
|
1052
|
+
function interpolatePath(pathPattern, params) {
|
|
1053
|
+
return pathPattern.replace(/:([A-Za-z0-9_]+)/g, (_, key) => {
|
|
1054
|
+
const value = params[key];
|
|
1055
|
+
if (value === void 0) throw new Error(`Missing required resource param "${key}" for path "${pathPattern}".`);
|
|
1056
|
+
return encodeURIComponent(value);
|
|
1057
|
+
});
|
|
1058
|
+
}
|
|
1059
|
+
function matchPathPattern(pathPattern, pathname) {
|
|
1060
|
+
return require_internal_transport.matchPathname(pathPattern, pathname) !== null;
|
|
1061
|
+
}
|
|
1062
|
+
function getDevRouteMatchChain(entry) {
|
|
1063
|
+
return [...collectDevLayouts(entry.route.options?.layout).map((layout) => ({
|
|
1064
|
+
id: layout.id,
|
|
1065
|
+
path: layout.path,
|
|
1066
|
+
loader: layout.options?.loader,
|
|
1067
|
+
middleware: layout.options?.middleware ?? []
|
|
1068
|
+
})), {
|
|
1069
|
+
id: entry.id,
|
|
1070
|
+
path: entry.path,
|
|
1071
|
+
loader: entry.route.loader ?? entry.route.options?.loader,
|
|
1072
|
+
middleware: entry.route.options?.middleware ?? []
|
|
1073
|
+
}];
|
|
1074
|
+
}
|
|
1075
|
+
function collectDevLayouts(layout) {
|
|
1076
|
+
if (!layout) return [];
|
|
1077
|
+
return [...isDevLayout(layout.options?.layout) ? collectDevLayouts(layout.options?.layout) : [], layout];
|
|
1078
|
+
}
|
|
1079
|
+
function isDevLayout(value) {
|
|
1080
|
+
return typeof value === "object" && value !== null && "id" in value && "path" in value && typeof value.id === "string" && typeof value.path === "string";
|
|
1081
|
+
}
|
|
1082
|
+
function findDevTargetRouteMatch(chain, targetId) {
|
|
1083
|
+
return chain.find((entry) => entry.id === targetId);
|
|
1084
|
+
}
|
|
1085
|
+
async function runDevMiddlewareChain(options) {
|
|
1086
|
+
const dispatch = async (index, context) => {
|
|
1087
|
+
const middleware = options.middleware[index];
|
|
1088
|
+
if (!middleware) return options.execute(context);
|
|
1089
|
+
let called = false;
|
|
1090
|
+
return middleware({
|
|
1091
|
+
request: options.request,
|
|
1092
|
+
params: options.params,
|
|
1093
|
+
signal: options.signal,
|
|
1094
|
+
context
|
|
1095
|
+
}, async (overrides) => {
|
|
1096
|
+
if (called) throw new Error("Litz middleware next() called multiple times.");
|
|
1097
|
+
called = true;
|
|
1098
|
+
const nextContext = overrides && Object.prototype.hasOwnProperty.call(overrides, "context") ? overrides.context : context;
|
|
1099
|
+
return dispatch(index + 1, nextContext);
|
|
1100
|
+
});
|
|
1101
|
+
};
|
|
1102
|
+
return dispatch(0, options.context);
|
|
1103
|
+
}
|
|
1104
|
+
async function writeProductionIndexHtml(root, clientOutDir) {
|
|
1105
|
+
const sourceHtmlPath = node_path.default.join(root, "index.html");
|
|
1106
|
+
const clientManifestPath = node_path.default.join(clientOutDir, ".vite", "manifest.json");
|
|
1107
|
+
let sourceHtml;
|
|
1108
|
+
let manifest;
|
|
1109
|
+
try {
|
|
1110
|
+
[sourceHtml, manifest] = await Promise.all([(0, node_fs_promises.readFile)(sourceHtmlPath, "utf8"), readJson(clientManifestPath)]);
|
|
1111
|
+
} catch {
|
|
1112
|
+
return;
|
|
1113
|
+
}
|
|
1114
|
+
const entry = Object.values(manifest).find((item) => item.isEntry) ?? Object.values(manifest).find((item) => Boolean(item.file));
|
|
1115
|
+
if (!entry) return;
|
|
1116
|
+
const headTags = (entry.css ?? []).map((cssFile) => ` <link rel="stylesheet" href="/${cssFile}">`).join("\n");
|
|
1117
|
+
const scriptTag = ` <script type="module" src="/${entry.file}"><\/script>`;
|
|
1118
|
+
let html = sourceHtml.replace(/<script[^>]+type=["']module["'][^>]+src=["'][^"']+["'][^>]*><\/script>\s*/gi, "");
|
|
1119
|
+
if (headTags) html = html.replace("</head>", `${headTags}\n </head>`);
|
|
1120
|
+
html = html.replace("</body>", `${scriptTag}\n </body>`);
|
|
1121
|
+
await (0, node_fs_promises.mkdir)(clientOutDir, { recursive: true });
|
|
1122
|
+
await (0, node_fs_promises.writeFile)(node_path.default.join(clientOutDir, "index.html"), html, "utf8");
|
|
1123
|
+
}
|
|
1124
|
+
async function readJson(filePath) {
|
|
1125
|
+
return JSON.parse(await (0, node_fs_promises.readFile)(filePath, "utf8"));
|
|
1126
|
+
}
|
|
1127
|
+
async function removeLegacyBuildArtifacts(outputRootDir) {
|
|
1128
|
+
await Promise.all([
|
|
1129
|
+
(0, node_fs_promises.rm)(node_path.default.join(outputRootDir, "index.html"), { force: true }),
|
|
1130
|
+
(0, node_fs_promises.rm)(node_path.default.join(outputRootDir, "rsc"), {
|
|
1131
|
+
force: true,
|
|
1132
|
+
recursive: true
|
|
1133
|
+
}),
|
|
1134
|
+
(0, node_fs_promises.rm)(node_path.default.join(outputRootDir, "ssr"), {
|
|
1135
|
+
force: true,
|
|
1136
|
+
recursive: true
|
|
1137
|
+
})
|
|
1138
|
+
]);
|
|
1139
|
+
}
|
|
1140
|
+
function finalizeServerArtifacts(serverOutDir, serverRscOutDir, clientOutDir, inlineClientAssets) {
|
|
1141
|
+
const rscIndexPath = node_path.default.join(serverRscOutDir, "index.mjs");
|
|
1142
|
+
const rscAssetsManifestPath = node_path.default.join(serverRscOutDir, "__vite_rsc_assets_manifest.js");
|
|
1143
|
+
let rscEntrySource;
|
|
1144
|
+
let rscAssetsManifestSource;
|
|
1145
|
+
let documentHtml = "";
|
|
1146
|
+
let clientAssets = [];
|
|
1147
|
+
try {
|
|
1148
|
+
[rscEntrySource, rscAssetsManifestSource] = [(0, node_fs.readFileSync)(rscIndexPath, "utf8"), (0, node_fs.readFileSync)(rscAssetsManifestPath, "utf8")];
|
|
1149
|
+
if (inlineClientAssets) {
|
|
1150
|
+
documentHtml = (0, node_fs.readFileSync)(node_path.default.join(clientOutDir, "index.html"), "utf8");
|
|
1151
|
+
clientAssets = collectEmbeddedClientAssets(clientOutDir);
|
|
1152
|
+
}
|
|
1153
|
+
} catch {
|
|
1154
|
+
return false;
|
|
1155
|
+
}
|
|
1156
|
+
const manifestBindingSource = rscAssetsManifestSource.replace(/^export default\s+/, "const assetsManifest = ");
|
|
1157
|
+
const asyncLocalStorageShimSource = [
|
|
1158
|
+
"class __LitzAsyncLocalStorage {",
|
|
1159
|
+
" run(store, callback, ...args) {",
|
|
1160
|
+
" const previousStore = this.store;",
|
|
1161
|
+
" this.store = store;",
|
|
1162
|
+
" try {",
|
|
1163
|
+
" return callback(...args);",
|
|
1164
|
+
" } finally {",
|
|
1165
|
+
" this.store = previousStore;",
|
|
1166
|
+
" }",
|
|
1167
|
+
" }",
|
|
1168
|
+
"",
|
|
1169
|
+
" getStore() {",
|
|
1170
|
+
" return this.store;",
|
|
1171
|
+
" }",
|
|
1172
|
+
"",
|
|
1173
|
+
" enterWith(store) {",
|
|
1174
|
+
" this.store = store;",
|
|
1175
|
+
" }",
|
|
1176
|
+
"}",
|
|
1177
|
+
"",
|
|
1178
|
+
"globalThis.AsyncLocalStorage ??= __LitzAsyncLocalStorage;"
|
|
1179
|
+
].join("\n");
|
|
1180
|
+
const inlinedServerSource = rscEntrySource.replace("import assetsManifest from \"./__vite_rsc_assets_manifest.js\";", manifestBindingSource).replace(/import \* as __viteRscAsyncHooks from "node:async_hooks";\s*/g, "").replace(/const __viteRscAsyncHooks = require\("node:async_hooks"\);\s*/g, "").replace(/globalThis\.AsyncLocalStorage = __viteRscAsyncHooks\.AsyncLocalStorage;/g, asyncLocalStorageShimSource);
|
|
1181
|
+
const bundledWrapperSource = bundleServerWrapper(serverRscOutDir, inlineClientAssets ? createInlineAssetServerWrapper(inlinedServerSource, documentHtml, clientAssets) : createServerModuleWrapper(inlinedServerSource));
|
|
1182
|
+
if (!bundledWrapperSource) return false;
|
|
1183
|
+
(0, node_fs.mkdirSync)(serverOutDir, { recursive: true });
|
|
1184
|
+
(0, node_fs.writeFileSync)(node_path.default.join(serverOutDir, "index.js"), bundledWrapperSource, "utf8");
|
|
1185
|
+
(0, node_fs.rmSync)(serverRscOutDir, {
|
|
1186
|
+
force: true,
|
|
1187
|
+
recursive: true
|
|
1188
|
+
});
|
|
1189
|
+
(0, node_fs.rmSync)(node_path.default.join(serverOutDir, "_ssr"), {
|
|
1190
|
+
force: true,
|
|
1191
|
+
recursive: true
|
|
1192
|
+
});
|
|
1193
|
+
return true;
|
|
1194
|
+
}
|
|
1195
|
+
function createServerModuleWrapper(serverModuleSource) {
|
|
1196
|
+
const { source, handlerName } = transformServerModuleSource(serverModuleSource);
|
|
1197
|
+
return [
|
|
1198
|
+
source,
|
|
1199
|
+
"",
|
|
1200
|
+
`export default ${handlerName};`,
|
|
1201
|
+
""
|
|
1202
|
+
].join("\n");
|
|
1203
|
+
}
|
|
1204
|
+
function transformServerModuleSource(serverModuleSource) {
|
|
1205
|
+
const handlerName = "__litzjsServerHandler";
|
|
1206
|
+
const sourceFile = typescript.default.createSourceFile("server/index.js", serverModuleSource, typescript.default.ScriptTarget.Latest, true, typescript.default.ScriptKind.JS);
|
|
1207
|
+
const transformedStatements = [];
|
|
1208
|
+
let defaultBinding = null;
|
|
1209
|
+
let handlerDeclared = false;
|
|
1210
|
+
const setDefaultBinding = (expression) => {
|
|
1211
|
+
if (defaultBinding) throw new Error("Expected a single default export in the bundled Litz server module.");
|
|
1212
|
+
defaultBinding = expression;
|
|
1213
|
+
};
|
|
1214
|
+
const createHandlerDeclaration = (expression) => typescript.default.factory.createVariableStatement(void 0, typescript.default.factory.createVariableDeclarationList([typescript.default.factory.createVariableDeclaration(typescript.default.factory.createIdentifier(handlerName), void 0, void 0, expression)], typescript.default.NodeFlags.Const));
|
|
1215
|
+
const stripExportModifiers = (modifiers) => modifiers?.filter((modifier) => modifier.kind !== typescript.default.SyntaxKind.DefaultKeyword && modifier.kind !== typescript.default.SyntaxKind.ExportKeyword) ?? [];
|
|
1216
|
+
for (const statement of sourceFile.statements) {
|
|
1217
|
+
if (typescript.default.isExportDeclaration(statement) && statement.exportClause && typescript.default.isNamedExports(statement.exportClause)) {
|
|
1218
|
+
const remainingElements = [];
|
|
1219
|
+
for (const element of statement.exportClause.elements) {
|
|
1220
|
+
if (element.name.text === "default" && !statement.moduleSpecifier) {
|
|
1221
|
+
setDefaultBinding(typescript.default.factory.createIdentifier(element.propertyName?.text ?? element.name.text));
|
|
1222
|
+
continue;
|
|
1223
|
+
}
|
|
1224
|
+
remainingElements.push(element);
|
|
1225
|
+
}
|
|
1226
|
+
if (remainingElements.length === statement.exportClause.elements.length) {
|
|
1227
|
+
transformedStatements.push(statement);
|
|
1228
|
+
continue;
|
|
1229
|
+
}
|
|
1230
|
+
if (remainingElements.length > 0) transformedStatements.push(typescript.default.factory.updateExportDeclaration(statement, statement.modifiers, statement.isTypeOnly, typescript.default.factory.updateNamedExports(statement.exportClause, remainingElements), statement.moduleSpecifier, statement.attributes));
|
|
1231
|
+
continue;
|
|
1232
|
+
}
|
|
1233
|
+
if (typescript.default.isExportAssignment(statement) && !statement.isExportEquals) {
|
|
1234
|
+
transformedStatements.push(createHandlerDeclaration(statement.expression));
|
|
1235
|
+
handlerDeclared = true;
|
|
1236
|
+
continue;
|
|
1237
|
+
}
|
|
1238
|
+
if (typescript.default.isFunctionDeclaration(statement)) {
|
|
1239
|
+
const modifiers = stripExportModifiers(statement.modifiers);
|
|
1240
|
+
if (!(statement.modifiers?.some((modifier) => modifier.kind === typescript.default.SyntaxKind.ExportKeyword) && statement.modifiers?.some((modifier) => modifier.kind === typescript.default.SyntaxKind.DefaultKeyword))) {
|
|
1241
|
+
transformedStatements.push(statement);
|
|
1242
|
+
continue;
|
|
1243
|
+
}
|
|
1244
|
+
if (statement.name) {
|
|
1245
|
+
transformedStatements.push(typescript.default.factory.updateFunctionDeclaration(statement, modifiers, statement.asteriskToken, statement.name, statement.typeParameters, statement.parameters, statement.type, statement.body ?? typescript.default.factory.createBlock([], false)));
|
|
1246
|
+
setDefaultBinding(typescript.default.factory.createIdentifier(statement.name.text));
|
|
1247
|
+
continue;
|
|
1248
|
+
}
|
|
1249
|
+
transformedStatements.push(createHandlerDeclaration(typescript.default.factory.createFunctionExpression(modifiers, statement.asteriskToken, void 0, statement.typeParameters, statement.parameters, statement.type, statement.body ?? typescript.default.factory.createBlock([], false))));
|
|
1250
|
+
handlerDeclared = true;
|
|
1251
|
+
continue;
|
|
1252
|
+
}
|
|
1253
|
+
if (typescript.default.isClassDeclaration(statement)) {
|
|
1254
|
+
const modifiers = stripExportModifiers(statement.modifiers);
|
|
1255
|
+
if (!(statement.modifiers?.some((modifier) => modifier.kind === typescript.default.SyntaxKind.ExportKeyword) && statement.modifiers?.some((modifier) => modifier.kind === typescript.default.SyntaxKind.DefaultKeyword))) {
|
|
1256
|
+
transformedStatements.push(statement);
|
|
1257
|
+
continue;
|
|
1258
|
+
}
|
|
1259
|
+
if (statement.name) {
|
|
1260
|
+
transformedStatements.push(typescript.default.factory.updateClassDeclaration(statement, modifiers, statement.name, statement.typeParameters, statement.heritageClauses, statement.members));
|
|
1261
|
+
setDefaultBinding(typescript.default.factory.createIdentifier(statement.name.text));
|
|
1262
|
+
continue;
|
|
1263
|
+
}
|
|
1264
|
+
transformedStatements.push(createHandlerDeclaration(typescript.default.factory.createClassExpression(modifiers, void 0, statement.typeParameters, statement.heritageClauses, statement.members)));
|
|
1265
|
+
handlerDeclared = true;
|
|
1266
|
+
continue;
|
|
1267
|
+
}
|
|
1268
|
+
transformedStatements.push(statement);
|
|
1269
|
+
}
|
|
1270
|
+
if (!handlerDeclared) {
|
|
1271
|
+
if (!defaultBinding) throw new Error("Unable to locate the default export in the bundled Litz server module.");
|
|
1272
|
+
transformedStatements.push(createHandlerDeclaration(defaultBinding));
|
|
1273
|
+
}
|
|
1274
|
+
const printer = typescript.default.createPrinter({ newLine: typescript.default.NewLineKind.LineFeed });
|
|
1275
|
+
const transformedSourceFile = typescript.default.factory.updateSourceFile(sourceFile, transformedStatements);
|
|
1276
|
+
return {
|
|
1277
|
+
source: printer.printFile(transformedSourceFile),
|
|
1278
|
+
handlerName
|
|
1279
|
+
};
|
|
1280
|
+
}
|
|
1281
|
+
function createInlineAssetServerWrapper(serverModuleSource, documentHtml, clientAssets) {
|
|
1282
|
+
const serializedClientAssets = JSON.stringify(clientAssets);
|
|
1283
|
+
const serializedDocumentHtml = JSON.stringify(documentHtml);
|
|
1284
|
+
const { source, handlerName } = transformServerModuleSource(serverModuleSource);
|
|
1285
|
+
return [
|
|
1286
|
+
`const LITZ_DOCUMENT_HTML = ${serializedDocumentHtml};`,
|
|
1287
|
+
`const LITZ_CLIENT_ASSETS = new Map(${serializedClientAssets}.map((asset) => [asset.path, asset]));`,
|
|
1288
|
+
"",
|
|
1289
|
+
source,
|
|
1290
|
+
"",
|
|
1291
|
+
"function __litzjsDecodeBase64(value) {",
|
|
1292
|
+
" if (typeof atob !== 'function') {",
|
|
1293
|
+
" throw new Error('Base64 asset decoding requires global atob.');",
|
|
1294
|
+
" }",
|
|
1295
|
+
"",
|
|
1296
|
+
" const binary = atob(value);",
|
|
1297
|
+
" const bytes = new Uint8Array(binary.length);",
|
|
1298
|
+
"",
|
|
1299
|
+
" for (let index = 0; index < binary.length; index += 1) {",
|
|
1300
|
+
" bytes[index] = binary.charCodeAt(index);",
|
|
1301
|
+
" }",
|
|
1302
|
+
"",
|
|
1303
|
+
" return bytes;",
|
|
1304
|
+
"}",
|
|
1305
|
+
"",
|
|
1306
|
+
"function __litzjsCreateStaticAssetResponse(asset, request) {",
|
|
1307
|
+
" const body = request.method === 'HEAD'",
|
|
1308
|
+
" ? null",
|
|
1309
|
+
" : asset.encoding === 'base64'",
|
|
1310
|
+
" ? __litzjsDecodeBase64(asset.body)",
|
|
1311
|
+
" : asset.body;",
|
|
1312
|
+
"",
|
|
1313
|
+
" return new Response(body, {",
|
|
1314
|
+
" status: 200,",
|
|
1315
|
+
" headers: asset.headers,",
|
|
1316
|
+
" });",
|
|
1317
|
+
"}",
|
|
1318
|
+
"",
|
|
1319
|
+
"function __litzjsShouldServeDocument(request, pathname) {",
|
|
1320
|
+
" if (pathname.startsWith('/_litz/') || pathname.startsWith('/api/')) {",
|
|
1321
|
+
" return false;",
|
|
1322
|
+
" }",
|
|
1323
|
+
"",
|
|
1324
|
+
" const lastSegment = pathname.split('/').at(-1) ?? '';",
|
|
1325
|
+
"",
|
|
1326
|
+
" if (lastSegment.includes('.')) {",
|
|
1327
|
+
" return pathname === '/index.html';",
|
|
1328
|
+
" }",
|
|
1329
|
+
"",
|
|
1330
|
+
" const accept = request.headers.get('accept') ?? '';",
|
|
1331
|
+
" return accept.includes('text/html') || accept.includes('*/*');",
|
|
1332
|
+
"}",
|
|
1333
|
+
"",
|
|
1334
|
+
"async function handle(request) {",
|
|
1335
|
+
" const url = new URL(request.url);",
|
|
1336
|
+
" const asset = LITZ_CLIENT_ASSETS.get(url.pathname);",
|
|
1337
|
+
"",
|
|
1338
|
+
" if ((request.method === 'GET' || request.method === 'HEAD') && asset) {",
|
|
1339
|
+
" return __litzjsCreateStaticAssetResponse(asset, request);",
|
|
1340
|
+
" }",
|
|
1341
|
+
"",
|
|
1342
|
+
" if ((request.method === 'GET' || request.method === 'HEAD') && __litzjsShouldServeDocument(request, url.pathname)) {",
|
|
1343
|
+
" return new Response(request.method === 'HEAD' ? null : LITZ_DOCUMENT_HTML, {",
|
|
1344
|
+
" status: 200,",
|
|
1345
|
+
" headers: {",
|
|
1346
|
+
" 'content-type': 'text/html; charset=utf-8',",
|
|
1347
|
+
" },",
|
|
1348
|
+
" });",
|
|
1349
|
+
" }",
|
|
1350
|
+
"",
|
|
1351
|
+
` return ${handlerName}.fetch(request);`,
|
|
1352
|
+
"}",
|
|
1353
|
+
"",
|
|
1354
|
+
"export default { fetch: handle };",
|
|
1355
|
+
""
|
|
1356
|
+
].join("\n");
|
|
1357
|
+
}
|
|
1358
|
+
function bundleServerWrapper(serverRscOutDir, wrapperSource) {
|
|
1359
|
+
const wrapperEntryPath = node_path.default.join(serverRscOutDir, "__litzjs_wrapped_server_entry.mjs");
|
|
1360
|
+
const bundleOutDir = node_path.default.join(serverRscOutDir, "__litzjs_bundle_out");
|
|
1361
|
+
const bundleScript = `
|
|
1362
|
+
const entryPath = process.env.LITZ_SERVER_ENTRY_PATH;
|
|
1363
|
+
const outDir = process.env.LITZ_SERVER_OUT_DIR;
|
|
1364
|
+
|
|
1365
|
+
if (!entryPath || !outDir) {
|
|
1366
|
+
throw new Error("Missing Litz server bundle paths.");
|
|
1367
|
+
}
|
|
1368
|
+
|
|
1369
|
+
(async () => {
|
|
1370
|
+
const { build } = await import("vite");
|
|
1371
|
+
|
|
1372
|
+
await build({
|
|
1373
|
+
appType: "custom",
|
|
1374
|
+
configFile: false,
|
|
1375
|
+
publicDir: false,
|
|
1376
|
+
logLevel: "silent",
|
|
1377
|
+
build: {
|
|
1378
|
+
ssr: entryPath,
|
|
1379
|
+
copyPublicDir: false,
|
|
1380
|
+
emptyOutDir: false,
|
|
1381
|
+
minify: false,
|
|
1382
|
+
outDir,
|
|
1383
|
+
target: "esnext",
|
|
1384
|
+
write: true,
|
|
1385
|
+
rollupOptions: {
|
|
1386
|
+
output: {
|
|
1387
|
+
entryFileNames: "index.js",
|
|
1388
|
+
format: "es",
|
|
1389
|
+
inlineDynamicImports: true,
|
|
1390
|
+
},
|
|
1391
|
+
},
|
|
1392
|
+
},
|
|
1393
|
+
});
|
|
1394
|
+
})().catch((error) => {
|
|
1395
|
+
console.error(error);
|
|
1396
|
+
process.exit(1);
|
|
1397
|
+
});
|
|
1398
|
+
`;
|
|
1399
|
+
(0, node_fs.writeFileSync)(wrapperEntryPath, wrapperSource, "utf8");
|
|
1400
|
+
(0, node_fs.rmSync)(bundleOutDir, {
|
|
1401
|
+
force: true,
|
|
1402
|
+
recursive: true
|
|
1403
|
+
});
|
|
1404
|
+
(0, node_fs.mkdirSync)(bundleOutDir, { recursive: true });
|
|
1405
|
+
const result = (0, node_child_process.spawnSync)(process.execPath, ["-e", bundleScript], {
|
|
1406
|
+
cwd: serverRscOutDir,
|
|
1407
|
+
encoding: "utf8",
|
|
1408
|
+
env: {
|
|
1409
|
+
...process.env,
|
|
1410
|
+
LITZ_SERVER_ENTRY_PATH: wrapperEntryPath,
|
|
1411
|
+
LITZ_SERVER_OUT_DIR: bundleOutDir
|
|
1412
|
+
}
|
|
1413
|
+
});
|
|
1414
|
+
try {
|
|
1415
|
+
if (result.status !== 0) {
|
|
1416
|
+
const stderr = result.stderr.trim();
|
|
1417
|
+
const stdout = result.stdout.trim();
|
|
1418
|
+
const failureMessage = stderr || stdout || "Failed to bundle the production Litz server.";
|
|
1419
|
+
throw new Error(failureMessage);
|
|
1420
|
+
}
|
|
1421
|
+
return (0, node_fs.readFileSync)(node_path.default.join(bundleOutDir, "index.js"), "utf8");
|
|
1422
|
+
} finally {
|
|
1423
|
+
(0, node_fs.rmSync)(wrapperEntryPath, { force: true });
|
|
1424
|
+
(0, node_fs.rmSync)(bundleOutDir, {
|
|
1425
|
+
force: true,
|
|
1426
|
+
recursive: true
|
|
1427
|
+
});
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
function collectEmbeddedClientAssets(clientOutDir) {
|
|
1431
|
+
const assets = [];
|
|
1432
|
+
walkClientAssets(clientOutDir, clientOutDir, assets);
|
|
1433
|
+
return assets;
|
|
1434
|
+
}
|
|
1435
|
+
function walkClientAssets(rootDir, currentDir, assets) {
|
|
1436
|
+
for (const entry of (0, node_fs.readdirSync)(currentDir, { withFileTypes: true })) {
|
|
1437
|
+
const fullPath = node_path.default.join(currentDir, entry.name);
|
|
1438
|
+
const relativePath = node_path.default.relative(rootDir, fullPath).split(node_path.default.sep).join("/");
|
|
1439
|
+
if (relativePath === ".vite" || relativePath.startsWith(".vite/")) continue;
|
|
1440
|
+
if (entry.isDirectory()) {
|
|
1441
|
+
walkClientAssets(rootDir, fullPath, assets);
|
|
1442
|
+
continue;
|
|
1443
|
+
}
|
|
1444
|
+
if (relativePath === "index.html") continue;
|
|
1445
|
+
const buffer = (0, node_fs.readFileSync)(fullPath);
|
|
1446
|
+
const encoding = isUtf8Asset(relativePath) ? "utf8" : "base64";
|
|
1447
|
+
assets.push({
|
|
1448
|
+
path: `/${relativePath}`,
|
|
1449
|
+
headers: { "content-type": getContentType(relativePath) },
|
|
1450
|
+
body: encoding === "utf8" ? buffer.toString("utf8") : buffer.toString("base64"),
|
|
1451
|
+
encoding
|
|
1452
|
+
});
|
|
1453
|
+
}
|
|
1454
|
+
}
|
|
1455
|
+
function isUtf8Asset(filePath) {
|
|
1456
|
+
const extension = node_path.default.extname(filePath).toLowerCase();
|
|
1457
|
+
return extension === ".js" || extension === ".mjs" || extension === ".css" || extension === ".html" || extension === ".json" || extension === ".svg" || extension === ".txt" || extension === ".map";
|
|
1458
|
+
}
|
|
1459
|
+
function getContentType(filePath) {
|
|
1460
|
+
switch (node_path.default.extname(filePath).toLowerCase()) {
|
|
1461
|
+
case ".html": return "text/html; charset=utf-8";
|
|
1462
|
+
case ".js":
|
|
1463
|
+
case ".mjs": return "text/javascript; charset=utf-8";
|
|
1464
|
+
case ".css": return "text/css; charset=utf-8";
|
|
1465
|
+
case ".json":
|
|
1466
|
+
case ".map": return "application/json; charset=utf-8";
|
|
1467
|
+
case ".svg": return "image/svg+xml";
|
|
1468
|
+
case ".png": return "image/png";
|
|
1469
|
+
case ".jpg":
|
|
1470
|
+
case ".jpeg": return "image/jpeg";
|
|
1471
|
+
case ".webp": return "image/webp";
|
|
1472
|
+
case ".woff": return "font/woff";
|
|
1473
|
+
case ".woff2": return "font/woff2";
|
|
1474
|
+
case ".txt": return "text/plain; charset=utf-8";
|
|
1475
|
+
default: return "application/octet-stream";
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
//#endregion
|
|
1479
|
+
exports.discoverServerEntry = discoverServerEntry;
|
|
1480
|
+
exports.litz = litz;
|
|
1481
|
+
exports.transformServerModuleSource = transformServerModuleSource;
|