@pracht/vite-plugin 0.2.3 → 0.2.4

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/README.md CHANGED
@@ -29,7 +29,7 @@ export default defineConfig({
29
29
 
30
30
  ## Peer Dependencies
31
31
 
32
- - `vite@^7.0.0 || ^8.0.0`
32
+ - `vite@^8.0.0`
33
33
 
34
34
  Target-specific Vite plugins (e.g. `@cloudflare/vite-plugin`) are pulled in by
35
35
  the adapter package you install (`@pracht/adapter-cloudflare`,
package/dist/index.d.mts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { Plugin } from "vite";
2
+ import { RenderMode } from "@pracht/core";
2
3
 
3
4
  //#region src/index.d.ts
4
5
  declare const PRACHT_CLIENT_MODULE_ID = "virtual:pracht/client";
@@ -36,7 +37,6 @@ interface PrachtAdapter {
36
37
  */
37
38
  ownsDevServer?: boolean;
38
39
  }
39
- type RenderMode = "spa" | "ssr" | "ssg" | "isg";
40
40
  interface PrachtPluginOptions {
41
41
  appFile?: string;
42
42
  routesDir?: string;
@@ -60,4 +60,4 @@ declare function createPrachtServerModuleSource(options?: PrachtPluginOptions, b
60
60
  }): string;
61
61
  declare function createPrachtRegistryModuleSource(options?: PrachtPluginOptions): string;
62
62
  //#endregion
63
- export { PRACHT_CLIENT_MODULE_ID, PRACHT_SERVER_MODULE_ID, PrachtAdapter, PrachtPluginOptions, RenderMode, createPrachtClientModuleSource, createPrachtRegistryModuleSource, createPrachtServerModuleSource, pracht };
63
+ export { PRACHT_CLIENT_MODULE_ID, PRACHT_SERVER_MODULE_ID, PrachtAdapter, PrachtPluginOptions, type RenderMode, createPrachtClientModuleSource, createPrachtRegistryModuleSource, createPrachtServerModuleSource, pracht };
package/dist/index.mjs CHANGED
@@ -1,7 +1,909 @@
1
1
  import { generatePagesManifestSource, scanPagesDirectory } from "./pages-router.mjs";
2
+ import preact from "@preact/preset-vite";
2
3
  import { existsSync, readFileSync } from "node:fs";
3
4
  import { resolve } from "node:path";
4
- import preact from "@preact/preset-vite";
5
+ import { parseAst } from "vite";
6
+ //#region src/client-module-scope-analysis.ts
7
+ const JSX_COMPONENT_RE = /^[A-Z]/;
8
+ const SKIPPED_KEYS = new Set([
9
+ "attributes",
10
+ "decorators",
11
+ "end",
12
+ "exportKind",
13
+ "importKind",
14
+ "optional",
15
+ "phase",
16
+ "raw",
17
+ "returnType",
18
+ "start",
19
+ "superTypeArguments",
20
+ "type",
21
+ "typeAnnotation",
22
+ "typeArguments",
23
+ "typeParameters",
24
+ "value"
25
+ ]);
26
+ function analyzeRetainedStatements(statements, options = {}) {
27
+ const programScope = createScope("program", null, null);
28
+ for (const name of options.knownTopLevelNames ?? []) declareBinding(programScope, name, "placeholder", null);
29
+ const scopesByNode = /* @__PURE__ */ new WeakMap();
30
+ declareProgramScopes(statements, programScope, scopesByNode);
31
+ const result = {
32
+ programScope,
33
+ referencedTopLevelNames: /* @__PURE__ */ new Set(),
34
+ references: []
35
+ };
36
+ const excludedNames = new Set(options.excludedNames);
37
+ for (const statement of statements) collectStatementReferences(statement.node, programScope, scopesByNode, result, excludedNames);
38
+ return result;
39
+ }
40
+ function createScope(type, parent, node) {
41
+ return {
42
+ bindings: /* @__PURE__ */ new Map(),
43
+ node,
44
+ parent,
45
+ type
46
+ };
47
+ }
48
+ function declareProgramScopes(statements, programScope, scopesByNode) {
49
+ for (const statement of statements) declareTopLevelStatement(statement.node, programScope);
50
+ for (const statement of statements) declareNodeScopes(statement.node, programScope, scopesByNode);
51
+ }
52
+ function declareTopLevelStatement(statement, programScope) {
53
+ if (statement.type === "ImportDeclaration") {
54
+ if (statement.importKind === "type") return;
55
+ for (const specifier of statement.specifiers) {
56
+ if (specifier.type === "ImportSpecifier" && specifier.importKind === "type") continue;
57
+ const localName = getIdentifierName$1(specifier.local);
58
+ if (localName) declareBinding(programScope, localName, "import", specifier);
59
+ }
60
+ return;
61
+ }
62
+ const declaration = getStatementDeclaration$1(statement);
63
+ if (!declaration) return;
64
+ declareDeclarationBindings(programScope, declaration);
65
+ }
66
+ function declareNodeScopes(node, currentScope, scopesByNode) {
67
+ if (!node) return;
68
+ if (node.type.startsWith("TS")) {
69
+ declareTsRuntimeChildren(node, currentScope, scopesByNode);
70
+ return;
71
+ }
72
+ switch (node.type) {
73
+ case "ImportDeclaration": return;
74
+ case "ArrowFunctionExpression":
75
+ case "FunctionDeclaration":
76
+ case "FunctionExpression": {
77
+ const functionScope = createScope("function", currentScope, node);
78
+ scopesByNode.set(node, functionScope);
79
+ declareFunctionBindings(node, functionScope);
80
+ for (const param of node.params) declareNodeScopes(param, functionScope, scopesByNode);
81
+ declareNodeScopes(node.body, functionScope, scopesByNode);
82
+ return;
83
+ }
84
+ case "BlockStatement": {
85
+ const blockScope = createScope("block", currentScope, node);
86
+ scopesByNode.set(node, blockScope);
87
+ declareBlockBindings(node.body, blockScope);
88
+ for (const statement of node.body) declareNodeScopes(statement, blockScope, scopesByNode);
89
+ return;
90
+ }
91
+ case "CatchClause": {
92
+ const catchScope = createScope("catch", currentScope, node);
93
+ scopesByNode.set(node, catchScope);
94
+ declareCatchBindings(node, catchScope);
95
+ if (node.param) declareNodeScopes(node.param, catchScope, scopesByNode);
96
+ declareNodeScopes(node.body, catchScope, scopesByNode);
97
+ return;
98
+ }
99
+ case "ForStatement": {
100
+ const init = node.init;
101
+ if (init?.type === "VariableDeclaration" && init.kind !== "var") {
102
+ const loopScope = createScope("for", currentScope, node);
103
+ scopesByNode.set(node, loopScope);
104
+ declareDeclarationBindings(loopScope, init);
105
+ declareNodeScopes(init, loopScope, scopesByNode);
106
+ declareNodeScopes(node.test, loopScope, scopesByNode);
107
+ declareNodeScopes(node.update, loopScope, scopesByNode);
108
+ declareNodeScopes(node.body, loopScope, scopesByNode);
109
+ return;
110
+ }
111
+ declareNodeScopes(init, currentScope, scopesByNode);
112
+ declareNodeScopes(node.test, currentScope, scopesByNode);
113
+ declareNodeScopes(node.update, currentScope, scopesByNode);
114
+ declareNodeScopes(node.body, currentScope, scopesByNode);
115
+ return;
116
+ }
117
+ case "ForInStatement":
118
+ case "ForOfStatement": {
119
+ const left = node.left;
120
+ if (left?.type === "VariableDeclaration" && left.kind !== "var") {
121
+ const loopScope = createScope("for", currentScope, node);
122
+ scopesByNode.set(node, loopScope);
123
+ declareDeclarationBindings(loopScope, left);
124
+ declareNodeScopes(left, loopScope, scopesByNode);
125
+ declareNodeScopes(node.right, loopScope, scopesByNode);
126
+ declareNodeScopes(node.body, loopScope, scopesByNode);
127
+ return;
128
+ }
129
+ declareNodeScopes(left, currentScope, scopesByNode);
130
+ declareNodeScopes(node.right, currentScope, scopesByNode);
131
+ declareNodeScopes(node.body, currentScope, scopesByNode);
132
+ return;
133
+ }
134
+ case "SwitchStatement": {
135
+ declareNodeScopes(node.discriminant, currentScope, scopesByNode);
136
+ const switchScope = createScope("switch", currentScope, node);
137
+ scopesByNode.set(node, switchScope);
138
+ declareSwitchBindings(node.cases, switchScope);
139
+ for (const switchCase of node.cases) declareNodeScopes(switchCase, switchScope, scopesByNode);
140
+ return;
141
+ }
142
+ case "ClassDeclaration":
143
+ case "ClassExpression": {
144
+ declareNodeScopes(node.superClass, currentScope, scopesByNode);
145
+ const classScope = createScope("class", currentScope, node);
146
+ scopesByNode.set(node, classScope);
147
+ const name = getIdentifierName$1(node.id);
148
+ if (name) declareBinding(classScope, name, "class", node);
149
+ declareNodeScopes(node.body, classScope, scopesByNode);
150
+ return;
151
+ }
152
+ case "ExportNamedDeclaration":
153
+ if (node.declaration) declareNodeScopes(node.declaration, currentScope, scopesByNode);
154
+ return;
155
+ case "ExportDefaultDeclaration":
156
+ if (node.declaration.type !== "Identifier") declareNodeScopes(node.declaration, currentScope, scopesByNode);
157
+ return;
158
+ default: for (const [key, value] of Object.entries(node)) {
159
+ if (SKIPPED_KEYS.has(key)) continue;
160
+ if (key === "id" || key === "implements" || key === "superTypeArguments") continue;
161
+ declareUnknownValue(value, currentScope, scopesByNode);
162
+ }
163
+ }
164
+ }
165
+ function declareUnknownValue(value, currentScope, scopesByNode) {
166
+ if (Array.isArray(value)) {
167
+ for (const item of value) declareUnknownValue(item, currentScope, scopesByNode);
168
+ return;
169
+ }
170
+ if (!isNode(value)) return;
171
+ declareNodeScopes(value, currentScope, scopesByNode);
172
+ }
173
+ function declareFunctionBindings(node, scope) {
174
+ const functionName = getIdentifierName$1(node.id);
175
+ if (functionName) declareBinding(scope, functionName, "function", node);
176
+ for (const param of node.params) for (const name of collectBindingNamesFromPattern$1(param)) declareBinding(scope, name, "param", param);
177
+ for (const name of collectFunctionScopedVarBindings(node.body)) declareBinding(scope, name, "var", node.body);
178
+ }
179
+ function declareBlockBindings(statements, scope) {
180
+ for (const statement of statements) {
181
+ const declaration = getStatementDeclaration$1(statement);
182
+ if (!declaration) continue;
183
+ if (declaration.type === "VariableDeclaration" && declaration.kind === "var") continue;
184
+ declareDeclarationBindings(scope, declaration);
185
+ }
186
+ }
187
+ function declareCatchBindings(node, scope) {
188
+ if (!node.param) return;
189
+ for (const name of collectBindingNamesFromPattern$1(node.param)) declareBinding(scope, name, "catch", node.param);
190
+ }
191
+ function declareSwitchBindings(cases, scope) {
192
+ const statements = [];
193
+ for (const switchCase of cases) for (const statement of switchCase.consequent) statements.push(statement);
194
+ declareBlockBindings(statements, scope);
195
+ }
196
+ function declareDeclarationBindings(scope, declaration) {
197
+ if (declaration.type === "FunctionDeclaration") {
198
+ const name = getIdentifierName$1(declaration.id);
199
+ if (name) declareBinding(scope, name, "function", declaration);
200
+ return;
201
+ }
202
+ if (declaration.type === "ClassDeclaration") {
203
+ const name = getIdentifierName$1(declaration.id);
204
+ if (name) declareBinding(scope, name, "class", declaration);
205
+ return;
206
+ }
207
+ if (declaration.type !== "VariableDeclaration") return;
208
+ for (const declarator of declaration.declarations) for (const name of collectBindingNamesFromPattern$1(declarator.id)) declareBinding(scope, name, declaration.kind, declarator);
209
+ }
210
+ function declareBinding(scope, name, kind, node) {
211
+ const binding = {
212
+ kind,
213
+ name,
214
+ node,
215
+ scope
216
+ };
217
+ scope.bindings.set(name, binding);
218
+ return binding;
219
+ }
220
+ function collectStatementReferences(statement, currentScope, scopesByNode, result, excludedNames) {
221
+ if (statement.type === "ImportDeclaration") return;
222
+ if (statement.type === "ExportNamedDeclaration") {
223
+ const declaration = statement.declaration;
224
+ if (declaration) collectNodeReferences(declaration, currentScope, scopesByNode, result, excludedNames);
225
+ return;
226
+ }
227
+ if (statement.type === "ExportDefaultDeclaration") {
228
+ const declaration = statement.declaration;
229
+ if (declaration.type !== "Identifier") collectNodeReferences(declaration, currentScope, scopesByNode, result, excludedNames);
230
+ return;
231
+ }
232
+ collectNodeReferences(statement, currentScope, scopesByNode, result, excludedNames);
233
+ }
234
+ function collectNodeReferences(node, currentScope, scopesByNode, result, excludedNames) {
235
+ if (!node) return;
236
+ if (node.type.startsWith("TS")) {
237
+ collectTsRuntimeReferences(node, currentScope, scopesByNode, result, excludedNames);
238
+ return;
239
+ }
240
+ switch (node.type) {
241
+ case "Identifier":
242
+ recordReference(node.name, node, currentScope, result, excludedNames);
243
+ return;
244
+ case "JSXIdentifier":
245
+ if (JSX_COMPONENT_RE.test(node.name)) recordReference(node.name, node, currentScope, result, excludedNames);
246
+ return;
247
+ case "ArrowFunctionExpression":
248
+ case "FunctionDeclaration":
249
+ case "FunctionExpression": {
250
+ const functionScope = scopesByNode.get(node) ?? currentScope;
251
+ for (const param of node.params) collectPatternReferences(param, functionScope, scopesByNode, result, excludedNames);
252
+ collectNodeReferences(node.body, functionScope, scopesByNode, result, excludedNames);
253
+ return;
254
+ }
255
+ case "BlockStatement": {
256
+ const blockScope = scopesByNode.get(node) ?? currentScope;
257
+ for (const statement of node.body) collectStatementReferences(statement, blockScope, scopesByNode, result, excludedNames);
258
+ return;
259
+ }
260
+ case "CatchClause": {
261
+ const catchScope = scopesByNode.get(node) ?? currentScope;
262
+ if (node.param) collectPatternReferences(node.param, catchScope, scopesByNode, result, excludedNames);
263
+ collectNodeReferences(node.body, catchScope, scopesByNode, result, excludedNames);
264
+ return;
265
+ }
266
+ case "ForStatement": {
267
+ const loopScope = scopesByNode.get(node) ?? currentScope;
268
+ collectNodeReferences(node.init, loopScope, scopesByNode, result, excludedNames);
269
+ collectNodeReferences(node.test, loopScope, scopesByNode, result, excludedNames);
270
+ collectNodeReferences(node.update, loopScope, scopesByNode, result, excludedNames);
271
+ collectNodeReferences(node.body, loopScope, scopesByNode, result, excludedNames);
272
+ return;
273
+ }
274
+ case "ForInStatement":
275
+ case "ForOfStatement": {
276
+ const loopScope = scopesByNode.get(node) ?? currentScope;
277
+ collectNodeReferences(node.left, loopScope, scopesByNode, result, excludedNames);
278
+ collectNodeReferences(node.right, loopScope, scopesByNode, result, excludedNames);
279
+ collectNodeReferences(node.body, loopScope, scopesByNode, result, excludedNames);
280
+ return;
281
+ }
282
+ case "SwitchStatement": {
283
+ collectNodeReferences(node.discriminant, currentScope, scopesByNode, result, excludedNames);
284
+ const switchScope = scopesByNode.get(node) ?? currentScope;
285
+ for (const switchCase of node.cases) {
286
+ collectNodeReferences(switchCase.test, switchScope, scopesByNode, result, excludedNames);
287
+ for (const statement of switchCase.consequent) collectStatementReferences(statement, switchScope, scopesByNode, result, excludedNames);
288
+ }
289
+ return;
290
+ }
291
+ case "ClassDeclaration":
292
+ case "ClassExpression": {
293
+ collectNodeReferences(node.superClass, currentScope, scopesByNode, result, excludedNames);
294
+ const classScope = scopesByNode.get(node) ?? currentScope;
295
+ collectNodeReferences(node.body, classScope, scopesByNode, result, excludedNames);
296
+ return;
297
+ }
298
+ case "VariableDeclaration":
299
+ for (const declarator of node.declarations) collectVariableDeclaratorReferences(declarator, currentScope, scopesByNode, result, excludedNames);
300
+ return;
301
+ case "MemberExpression":
302
+ collectNodeReferences(node.object, currentScope, scopesByNode, result, excludedNames);
303
+ if (node.computed) collectNodeReferences(node.property, currentScope, scopesByNode, result, excludedNames);
304
+ return;
305
+ case "MetaProperty": return;
306
+ case "LabeledStatement":
307
+ collectNodeReferences(node.body, currentScope, scopesByNode, result, excludedNames);
308
+ return;
309
+ case "BreakStatement":
310
+ case "ContinueStatement": return;
311
+ case "Property":
312
+ if (node.computed) collectNodeReferences(node.key, currentScope, scopesByNode, result, excludedNames);
313
+ collectNodeReferences(node.value, currentScope, scopesByNode, result, excludedNames);
314
+ return;
315
+ case "ObjectPattern":
316
+ case "ArrayPattern":
317
+ case "AssignmentPattern":
318
+ case "RestElement":
319
+ collectPatternReferences(node, currentScope, scopesByNode, result, excludedNames);
320
+ return;
321
+ case "JSXElement":
322
+ collectNodeReferences(node.openingElement, currentScope, scopesByNode, result, excludedNames);
323
+ for (const child of node.children) collectNodeReferences(child, currentScope, scopesByNode, result, excludedNames);
324
+ return;
325
+ case "JSXFragment":
326
+ for (const child of node.children) collectNodeReferences(child, currentScope, scopesByNode, result, excludedNames);
327
+ return;
328
+ case "JSXOpeningElement":
329
+ collectNodeReferences(node.name, currentScope, scopesByNode, result, excludedNames);
330
+ for (const attribute of node.attributes) collectNodeReferences(attribute, currentScope, scopesByNode, result, excludedNames);
331
+ return;
332
+ case "JSXClosingElement":
333
+ collectNodeReferences(node.name, currentScope, scopesByNode, result, excludedNames);
334
+ return;
335
+ case "JSXAttribute":
336
+ collectNodeReferences(node.value, currentScope, scopesByNode, result, excludedNames);
337
+ return;
338
+ case "JSXExpressionContainer":
339
+ collectNodeReferences(node.expression, currentScope, scopesByNode, result, excludedNames);
340
+ return;
341
+ case "JSXMemberExpression":
342
+ collectNodeReferences(node.object, currentScope, scopesByNode, result, excludedNames);
343
+ return;
344
+ case "MethodDefinition":
345
+ case "PropertyDefinition":
346
+ if (node.computed) collectNodeReferences(node.key, currentScope, scopesByNode, result, excludedNames);
347
+ collectNodeReferences(node.value, currentScope, scopesByNode, result, excludedNames);
348
+ return;
349
+ case "ImportDeclaration": return;
350
+ case "ExportNamedDeclaration":
351
+ if (node.declaration) collectNodeReferences(node.declaration, currentScope, scopesByNode, result, excludedNames);
352
+ return;
353
+ case "ExportDefaultDeclaration":
354
+ if (node.declaration.type !== "Identifier") collectNodeReferences(node.declaration, currentScope, scopesByNode, result, excludedNames);
355
+ return;
356
+ default: for (const [key, value] of Object.entries(node)) {
357
+ if (SKIPPED_KEYS.has(key)) continue;
358
+ if (key === "id" || key === "implements" || key === "superTypeArguments") continue;
359
+ collectUnknownValueReferences(value, currentScope, scopesByNode, result, excludedNames);
360
+ }
361
+ }
362
+ }
363
+ function collectUnknownValueReferences(value, currentScope, scopesByNode, result, excludedNames) {
364
+ if (Array.isArray(value)) {
365
+ for (const item of value) collectUnknownValueReferences(item, currentScope, scopesByNode, result, excludedNames);
366
+ return;
367
+ }
368
+ if (!isNode(value)) return;
369
+ collectNodeReferences(value, currentScope, scopesByNode, result, excludedNames);
370
+ }
371
+ function collectVariableDeclaratorReferences(declarator, currentScope, scopesByNode, result, excludedNames) {
372
+ collectPatternReferences(declarator.id, currentScope, scopesByNode, result, excludedNames);
373
+ collectNodeReferences(declarator.init, currentScope, scopesByNode, result, excludedNames);
374
+ }
375
+ function collectPatternReferences(node, currentScope, scopesByNode, result, excludedNames) {
376
+ if (!node) return;
377
+ if (node.type.startsWith("TS")) {
378
+ collectTsRuntimeReferences(node, currentScope, scopesByNode, result, excludedNames);
379
+ return;
380
+ }
381
+ switch (node.type) {
382
+ case "AssignmentPattern":
383
+ collectNodeReferences(node.right, currentScope, scopesByNode, result, excludedNames);
384
+ collectPatternReferences(node.left, currentScope, scopesByNode, result, excludedNames);
385
+ return;
386
+ case "ObjectPattern":
387
+ for (const property of node.properties) {
388
+ if (property.type === "Property") {
389
+ if (property.computed) collectNodeReferences(property.key, currentScope, scopesByNode, result, excludedNames);
390
+ collectPatternReferences(property.value, currentScope, scopesByNode, result, excludedNames);
391
+ continue;
392
+ }
393
+ collectPatternReferences(property.argument, currentScope, scopesByNode, result, excludedNames);
394
+ }
395
+ return;
396
+ case "ArrayPattern":
397
+ for (const element of node.elements) collectPatternReferences(element, currentScope, scopesByNode, result, excludedNames);
398
+ return;
399
+ case "RestElement":
400
+ collectPatternReferences(node.argument, currentScope, scopesByNode, result, excludedNames);
401
+ return;
402
+ default: return;
403
+ }
404
+ }
405
+ function recordReference(name, node, currentScope, result, excludedNames) {
406
+ const resolvedBinding = resolveBinding(name, currentScope);
407
+ result.references.push({
408
+ name,
409
+ node,
410
+ resolvedBinding
411
+ });
412
+ if (!resolvedBinding) return;
413
+ if (resolvedBinding.scope.type !== "program") return;
414
+ if (excludedNames.has(name)) return;
415
+ result.referencedTopLevelNames.add(name);
416
+ }
417
+ function resolveBinding(name, currentScope) {
418
+ let scope = currentScope;
419
+ while (scope) {
420
+ const binding = scope.bindings.get(name);
421
+ if (binding) return binding;
422
+ scope = scope.parent;
423
+ }
424
+ return null;
425
+ }
426
+ function getStatementDeclaration$1(statement) {
427
+ if (statement.type === "ExportNamedDeclaration") return statement.declaration ?? null;
428
+ if (statement.type === "ExportDefaultDeclaration" && (statement.declaration.type === "FunctionDeclaration" || statement.declaration.type === "ClassDeclaration")) return statement.declaration;
429
+ if (statement.type === "FunctionDeclaration" || statement.type === "ClassDeclaration" || statement.type === "VariableDeclaration") return statement;
430
+ return null;
431
+ }
432
+ function collectBindingNamesFromPattern$1(pattern) {
433
+ if (!pattern) return [];
434
+ switch (pattern.type) {
435
+ case "Identifier": return [pattern.name];
436
+ case "AssignmentPattern": return collectBindingNamesFromPattern$1(pattern.left);
437
+ case "RestElement": return collectBindingNamesFromPattern$1(pattern.argument);
438
+ case "ObjectPattern": return pattern.properties.flatMap((property) => {
439
+ if (property.type === "Property") return collectBindingNamesFromPattern$1(property.value);
440
+ return collectBindingNamesFromPattern$1(property.argument);
441
+ });
442
+ case "ArrayPattern": return pattern.elements.flatMap((element) => collectBindingNamesFromPattern$1(element));
443
+ default: return [];
444
+ }
445
+ }
446
+ function collectFunctionScopedVarBindings(node) {
447
+ const names = /* @__PURE__ */ new Set();
448
+ collectFunctionScopedVarBindingsInto(node, names);
449
+ return names;
450
+ }
451
+ function collectFunctionScopedVarBindingsInto(node, names) {
452
+ if (!node) return;
453
+ if (node.type.startsWith("TS")) {
454
+ collectFunctionScopedVarBindingsFromTsNode(node, names);
455
+ return;
456
+ }
457
+ switch (node.type) {
458
+ case "ArrowFunctionExpression":
459
+ case "FunctionDeclaration":
460
+ case "FunctionExpression":
461
+ case "ClassDeclaration":
462
+ case "ClassExpression": return;
463
+ case "VariableDeclaration":
464
+ if (node.kind === "var") for (const declarator of node.declarations) for (const name of collectBindingNamesFromPattern$1(declarator.id)) names.add(name);
465
+ return;
466
+ default: for (const [key, value] of Object.entries(node)) {
467
+ if (SKIPPED_KEYS.has(key)) continue;
468
+ if (key === "id" || key === "implements" || key === "superTypeArguments") continue;
469
+ collectFunctionScopedVarBindingsFromUnknown(value, names);
470
+ }
471
+ }
472
+ }
473
+ function collectFunctionScopedVarBindingsFromUnknown(value, names) {
474
+ if (Array.isArray(value)) {
475
+ for (const item of value) collectFunctionScopedVarBindingsFromUnknown(item, names);
476
+ return;
477
+ }
478
+ if (!isNode(value)) return;
479
+ collectFunctionScopedVarBindingsInto(value, names);
480
+ }
481
+ function declareTsRuntimeChildren(node, currentScope, scopesByNode) {
482
+ for (const child of getTsRuntimeChildren(node)) declareNodeScopes(child, currentScope, scopesByNode);
483
+ }
484
+ function collectTsRuntimeReferences(node, currentScope, scopesByNode, result, excludedNames) {
485
+ for (const child of getTsRuntimeChildren(node)) collectNodeReferences(child, currentScope, scopesByNode, result, excludedNames);
486
+ }
487
+ function collectFunctionScopedVarBindingsFromTsNode(node, names) {
488
+ for (const child of getTsRuntimeChildren(node)) collectFunctionScopedVarBindingsInto(child, names);
489
+ }
490
+ function getTsRuntimeChildren(node) {
491
+ switch (node.type) {
492
+ case "TSAsExpression":
493
+ case "TSInstantiationExpression":
494
+ case "TSNonNullExpression":
495
+ case "TSSatisfiesExpression":
496
+ case "TSTypeAssertion": return [node.expression];
497
+ default: return [];
498
+ }
499
+ }
500
+ function getIdentifierName$1(node) {
501
+ if (!node) return null;
502
+ if (node.type === "Identifier" || node.type === "JSXIdentifier") return node.name;
503
+ if (node.type === "Literal" && typeof node.value === "string") return node.value;
504
+ return null;
505
+ }
506
+ function isNode(value) {
507
+ return !!value && typeof value === "object" && "type" in value;
508
+ }
509
+ //#endregion
510
+ //#region src/client-module-transform.ts
511
+ const CLIENT_MODULE_QUERY = "pracht-client";
512
+ const SERVER_ONLY_EXPORTS = new Set([
513
+ "loader",
514
+ "head",
515
+ "headers",
516
+ "getStaticPaths"
517
+ ]);
518
+ const PRACHT_CLIENT_MODULE_QUERY = `?${CLIENT_MODULE_QUERY}`;
519
+ function isPrachtClientModuleId(id) {
520
+ const queryStart = id.indexOf("?");
521
+ if (queryStart === -1) return false;
522
+ return id.slice(queryStart + 1).split("&").includes(CLIENT_MODULE_QUERY);
523
+ }
524
+ function stripPrachtClientModuleQuery(id) {
525
+ const queryStart = id.indexOf("?");
526
+ if (queryStart === -1) return id;
527
+ const path = id.slice(0, queryStart);
528
+ const query = id.slice(queryStart + 1).split("&").filter((part) => part !== CLIENT_MODULE_QUERY);
529
+ return query.length > 0 ? `${path}?${query.join("&")}` : path;
530
+ }
531
+ function stripServerOnlyExportsForClient(code, id = "pracht-client-route.tsx") {
532
+ const states = createStatementStates(parseAst(code, { lang: getRolldownLang(id) }));
533
+ const initialBindingNames = collectCurrentTopLevelBindingNames(states);
534
+ const { changed, candidates } = removeServerOnlyExports(states, initialBindingNames);
535
+ if (!changed) return code;
536
+ pruneDeadBindings(states, initialBindingNames, candidates);
537
+ return renderProgram(code, states);
538
+ }
539
+ function createStatementStates(program) {
540
+ return program.body.map((node) => ({
541
+ node,
542
+ removed: false,
543
+ removedDeclarators: /* @__PURE__ */ new Set(),
544
+ removedSpecifiers: /* @__PURE__ */ new Set()
545
+ }));
546
+ }
547
+ function removeServerOnlyExports(states, initialBindingNames) {
548
+ let changed = false;
549
+ const candidates = /* @__PURE__ */ new Set();
550
+ for (const state of states) {
551
+ const statement = state.node;
552
+ if (statement.type !== "ExportNamedDeclaration" || statement.exportKind === "type") continue;
553
+ const declaration = statement.declaration;
554
+ if (declaration?.type === "FunctionDeclaration") {
555
+ const name = declaration.id?.name;
556
+ if (!name || !SERVER_ONLY_EXPORTS.has(name)) continue;
557
+ changed = true;
558
+ state.removed = true;
559
+ enqueueDependencies(candidates, collectTopLevelReferences(declaration, initialBindingNames, new Set([name])));
560
+ continue;
561
+ }
562
+ if (declaration?.type === "VariableDeclaration") {
563
+ const removable = getRemainingDeclaratorIndices(state).filter((index) => collectBindingNamesFromPattern(declaration.declarations[index].id).some((name) => SERVER_ONLY_EXPORTS.has(name)));
564
+ if (removable.length === 0) continue;
565
+ changed = true;
566
+ for (const index of removable) {
567
+ const declarator = declaration.declarations[index];
568
+ const declaredNames = new Set(collectBindingNamesFromPattern(declarator.id));
569
+ enqueueDependencies(candidates, collectVariableDeclaratorDependencies(declarator, declaration.kind, initialBindingNames, declaredNames));
570
+ state.removedDeclarators.add(index);
571
+ }
572
+ if (getRemainingDeclaratorIndices(state).length === 0) state.removed = true;
573
+ continue;
574
+ }
575
+ const removableSpecifiers = getRemainingSpecifierIndices(state).filter((index) => {
576
+ const specifier = statement.specifiers[index];
577
+ if (specifier.type !== "ExportSpecifier" || specifier.exportKind === "type") return false;
578
+ const localName = getIdentifierName(specifier.local);
579
+ const exportedName = getIdentifierName(specifier.exported);
580
+ return SERVER_ONLY_EXPORTS.has(localName ?? "") || SERVER_ONLY_EXPORTS.has(exportedName ?? "");
581
+ });
582
+ if (removableSpecifiers.length === 0) continue;
583
+ changed = true;
584
+ for (const index of removableSpecifiers) {
585
+ const specifier = statement.specifiers[index];
586
+ if (!statement.source) {
587
+ const localName = getIdentifierName(specifier.local);
588
+ if (localName) candidates.add(localName);
589
+ }
590
+ state.removedSpecifiers.add(index);
591
+ }
592
+ if (getRemainingSpecifierIndices(state).length === 0) state.removed = true;
593
+ }
594
+ return {
595
+ changed,
596
+ candidates
597
+ };
598
+ }
599
+ function pruneDeadBindings(states, initialBindingNames, candidates) {
600
+ let changed = true;
601
+ while (changed) {
602
+ changed = false;
603
+ const bindings = collectTopLevelBindings(states, initialBindingNames);
604
+ const exportedNames = collectExportedBindingNames(states);
605
+ const referencedNames = collectProgramReferences(states);
606
+ const pendingNames = Array.from(candidates);
607
+ for (const name of pendingNames) {
608
+ const binding = bindings.get(name);
609
+ if (!binding) continue;
610
+ if (exportedNames.has(name) || referencedNames.has(name)) continue;
611
+ removeBinding(states, binding);
612
+ enqueueDependencies(candidates, binding.dependencies);
613
+ changed = true;
614
+ }
615
+ }
616
+ }
617
+ function collectTopLevelBindings(states, dependencyBindingNames) {
618
+ const bindings = /* @__PURE__ */ new Map();
619
+ for (const [statementIndex, state] of states.entries()) {
620
+ if (state.removed) continue;
621
+ const statement = state.node;
622
+ if (statement.type === "ImportDeclaration") {
623
+ if (statement.importKind === "type") continue;
624
+ for (const index of getRemainingSpecifierIndices(state)) {
625
+ const specifier = statement.specifiers[index];
626
+ if (specifier.type === "ImportSpecifier" && specifier.importKind === "type") continue;
627
+ const local = specifier.local;
628
+ const name = getIdentifierName(local);
629
+ if (!name) continue;
630
+ const info = {
631
+ dependencies: /* @__PURE__ */ new Set(),
632
+ kind: "import",
633
+ names: new Set([name]),
634
+ node: specifier,
635
+ specifierIndex: index,
636
+ statementIndex
637
+ };
638
+ bindings.set(name, info);
639
+ }
640
+ continue;
641
+ }
642
+ const declaration = getStatementDeclaration(statement);
643
+ if (!declaration) continue;
644
+ if (declaration.type === "FunctionDeclaration") {
645
+ const name = getIdentifierName(declaration.id);
646
+ if (!name) continue;
647
+ const info = {
648
+ dependencies: collectTopLevelReferences(declaration, dependencyBindingNames, new Set([name])),
649
+ kind: "function",
650
+ names: new Set([name]),
651
+ node: declaration,
652
+ statementIndex
653
+ };
654
+ bindings.set(name, info);
655
+ continue;
656
+ }
657
+ if (declaration.type === "ClassDeclaration") {
658
+ const name = getIdentifierName(declaration.id);
659
+ if (!name) continue;
660
+ const info = {
661
+ dependencies: collectTopLevelReferences(declaration, dependencyBindingNames, new Set([name])),
662
+ kind: "class",
663
+ names: new Set([name]),
664
+ node: declaration,
665
+ statementIndex
666
+ };
667
+ bindings.set(name, info);
668
+ continue;
669
+ }
670
+ if (declaration.type !== "VariableDeclaration") continue;
671
+ for (const index of getRemainingDeclaratorIndices(state)) {
672
+ const declarator = declaration.declarations[index];
673
+ const names = new Set(collectBindingNamesFromPattern(declarator.id));
674
+ if (names.size === 0) continue;
675
+ const info = {
676
+ declaratorIndex: index,
677
+ dependencies: collectVariableDeclaratorDependencies(declarator, declaration.kind, dependencyBindingNames, names),
678
+ kind: "variable",
679
+ names,
680
+ node: declarator,
681
+ statementIndex
682
+ };
683
+ for (const name of names) bindings.set(name, info);
684
+ }
685
+ }
686
+ return bindings;
687
+ }
688
+ function collectCurrentTopLevelBindingNames(states) {
689
+ const names = /* @__PURE__ */ new Set();
690
+ for (const state of states) {
691
+ if (state.removed) continue;
692
+ const statement = state.node;
693
+ if (statement.type === "ImportDeclaration") {
694
+ if (statement.importKind === "type") continue;
695
+ for (const index of getRemainingSpecifierIndices(state)) {
696
+ const specifier = statement.specifiers[index];
697
+ if (specifier.type === "ImportSpecifier" && specifier.importKind === "type") continue;
698
+ const localName = getIdentifierName(specifier.local);
699
+ if (localName) names.add(localName);
700
+ }
701
+ continue;
702
+ }
703
+ const declaration = getStatementDeclaration(statement);
704
+ if (!declaration) continue;
705
+ if (declaration.type === "VariableDeclaration") {
706
+ for (const index of getRemainingDeclaratorIndices(state)) {
707
+ const declarator = declaration.declarations[index];
708
+ for (const name of collectBindingNamesFromPattern(declarator.id)) names.add(name);
709
+ }
710
+ continue;
711
+ }
712
+ for (const name of collectBindingNamesFromDeclaration(declaration)) names.add(name);
713
+ }
714
+ return names;
715
+ }
716
+ function collectExportedBindingNames(states) {
717
+ const names = /* @__PURE__ */ new Set();
718
+ for (const state of states) {
719
+ if (state.removed) continue;
720
+ const statement = state.node;
721
+ if (statement.type === "ExportNamedDeclaration") {
722
+ const declaration = statement.declaration;
723
+ if (declaration) if (declaration.type === "VariableDeclaration") for (const index of getRemainingDeclaratorIndices(state)) {
724
+ const declarator = declaration.declarations[index];
725
+ for (const name of collectBindingNamesFromPattern(declarator.id)) names.add(name);
726
+ }
727
+ else for (const name of collectBindingNamesFromDeclaration(declaration)) names.add(name);
728
+ for (const index of getRemainingSpecifierIndices(state)) {
729
+ const specifier = statement.specifiers[index];
730
+ if (specifier.type !== "ExportSpecifier" || specifier.exportKind === "type") continue;
731
+ const localName = getIdentifierName(specifier.local);
732
+ if (localName) names.add(localName);
733
+ }
734
+ }
735
+ if (statement.type !== "ExportDefaultDeclaration") continue;
736
+ const declaration = statement.declaration;
737
+ if (declaration.type === "Identifier") {
738
+ names.add(declaration.name);
739
+ continue;
740
+ }
741
+ if ((declaration.type === "FunctionDeclaration" || declaration.type === "ClassDeclaration") && declaration.id) names.add(declaration.id.name);
742
+ }
743
+ return names;
744
+ }
745
+ function collectProgramReferences(states) {
746
+ return analyzeRetainedStatements(normalizeRetainedStatements(states)).referencedTopLevelNames;
747
+ }
748
+ function removeBinding(states, binding) {
749
+ const state = states[binding.statementIndex];
750
+ if (binding.kind === "import" && binding.specifierIndex !== void 0) {
751
+ state.removedSpecifiers.add(binding.specifierIndex);
752
+ if (getRemainingSpecifierIndices(state).length === 0) state.removed = true;
753
+ return;
754
+ }
755
+ if (binding.kind === "variable" && binding.declaratorIndex !== void 0) {
756
+ state.removedDeclarators.add(binding.declaratorIndex);
757
+ if (getRemainingDeclaratorIndices(state).length === 0) state.removed = true;
758
+ return;
759
+ }
760
+ state.removed = true;
761
+ }
762
+ function renderProgram(code, states) {
763
+ let cursor = 0;
764
+ let out = "";
765
+ for (const state of states) {
766
+ const statement = state.node;
767
+ out += code.slice(cursor, statement.start);
768
+ out += renderStatement(code, state);
769
+ cursor = statement.end;
770
+ }
771
+ out += code.slice(cursor);
772
+ return out;
773
+ }
774
+ function renderStatement(code, state) {
775
+ if (state.removed) return "";
776
+ const statement = state.node;
777
+ const declaration = getStatementDeclaration(statement);
778
+ if (statement.type === "ImportDeclaration" && state.removedSpecifiers.size > 0) return renderImportDeclaration(code, statement, state);
779
+ if (statement.type === "ExportNamedDeclaration" && !statement.declaration && state.removedSpecifiers.size > 0) return renderExportSpecifiers(code, statement, state);
780
+ if (declaration?.type === "VariableDeclaration" && state.removedDeclarators.size > 0) return renderVariableDeclaration(code, statement, declaration, state);
781
+ return code.slice(statement.start, statement.end);
782
+ }
783
+ function renderImportDeclaration(code, statement, state) {
784
+ const remaining = getRemainingSpecifierIndices(state).map((index) => statement.specifiers[index]);
785
+ if (remaining.length === 0) return "";
786
+ const defaultSpecifier = remaining.find((specifier) => specifier.type === "ImportDefaultSpecifier");
787
+ const namespaceSpecifier = remaining.find((specifier) => specifier.type === "ImportNamespaceSpecifier");
788
+ const namedSpecifiers = remaining.filter((specifier) => specifier.type === "ImportSpecifier");
789
+ const clauseParts = [];
790
+ if (defaultSpecifier) clauseParts.push(code.slice(defaultSpecifier.start, defaultSpecifier.end));
791
+ if (namespaceSpecifier) clauseParts.push(code.slice(namespaceSpecifier.start, namespaceSpecifier.end));
792
+ if (namedSpecifiers.length > 0) clauseParts.push(`{ ${namedSpecifiers.map((specifier) => code.slice(specifier.start, specifier.end)).join(", ")} }`);
793
+ const importPrefix = ["import"];
794
+ if (statement.importKind === "type") importPrefix.push("type");
795
+ if (typeof statement.phase === "string" && statement.phase.length > 0) importPrefix.push(statement.phase);
796
+ return `${importPrefix.join(" ")} ${clauseParts.join(", ")} from ${code.slice(statement.source.start, statement.end)}`;
797
+ }
798
+ function renderExportSpecifiers(code, statement, state) {
799
+ const remaining = getRemainingSpecifierIndices(state).map((index) => statement.specifiers[index]);
800
+ if (remaining.length === 0) return "";
801
+ const exportPrefix = statement.exportKind === "type" ? "export type" : "export";
802
+ const sourceSuffix = statement.source ? ` from ${code.slice(statement.source.start, statement.end)}` : ";";
803
+ return `${exportPrefix} { ${remaining.map((specifier) => code.slice(specifier.start, specifier.end)).join(", ")} }${sourceSuffix}`;
804
+ }
805
+ function renderVariableDeclaration(code, statement, declaration, state) {
806
+ const remaining = getRemainingDeclaratorIndices(state).map((index) => declaration.declarations[index]);
807
+ if (remaining.length === 0) return "";
808
+ return `${statement.type === "ExportNamedDeclaration" ? "export " : ""}${declaration.kind} ${remaining.map((item) => code.slice(item.start, item.end)).join(", ")};`;
809
+ }
810
+ function getRemainingDeclaratorIndices(state) {
811
+ const declaration = getStatementDeclaration(state.node);
812
+ if (!declaration || declaration.type !== "VariableDeclaration") return [];
813
+ return declaration.declarations.map((_item, index) => index).filter((index) => !state.removedDeclarators.has(index));
814
+ }
815
+ function getRemainingSpecifierIndices(state) {
816
+ const statement = state.node;
817
+ if (!("specifiers" in statement) || !Array.isArray(statement.specifiers)) return [];
818
+ return statement.specifiers.map((_item, index) => index).filter((index) => !state.removedSpecifiers.has(index));
819
+ }
820
+ function collectVariableDeclaratorDependencies(declarator, declarationKind, topLevelBindingNames, excludedNames) {
821
+ return collectTopLevelReferences({
822
+ declarations: [declarator],
823
+ end: declarator.end,
824
+ kind: declarationKind,
825
+ start: declarator.start,
826
+ type: "VariableDeclaration"
827
+ }, topLevelBindingNames, excludedNames);
828
+ }
829
+ function collectTopLevelReferences(node, topLevelBindingNames, excludedNames) {
830
+ return analyzeRetainedStatements([{ node }], {
831
+ excludedNames,
832
+ knownTopLevelNames: topLevelBindingNames
833
+ }).referencedTopLevelNames;
834
+ }
835
+ function normalizeRetainedStatements(states) {
836
+ return states.map((state) => normalizeRetainedStatement(state)).filter((state) => state !== null);
837
+ }
838
+ function normalizeRetainedStatement(state) {
839
+ if (state.removed) return null;
840
+ const statement = state.node;
841
+ if (statement.type === "ImportDeclaration" && state.removedSpecifiers.size > 0) return { node: {
842
+ ...statement,
843
+ specifiers: getRemainingSpecifierIndices(state).map((index) => statement.specifiers[index])
844
+ } };
845
+ if (statement.type === "ExportNamedDeclaration" && !statement.declaration && state.removedSpecifiers.size > 0) return { node: {
846
+ ...statement,
847
+ specifiers: getRemainingSpecifierIndices(state).map((index) => statement.specifiers[index])
848
+ } };
849
+ const declaration = getStatementDeclaration(statement);
850
+ if (declaration?.type === "VariableDeclaration" && state.removedDeclarators.size > 0) {
851
+ const retainedDeclaration = {
852
+ ...declaration,
853
+ declarations: getRemainingDeclaratorIndices(state).map((index) => declaration.declarations[index])
854
+ };
855
+ if (statement.type === "ExportNamedDeclaration") return { node: {
856
+ ...statement,
857
+ declaration: retainedDeclaration
858
+ } };
859
+ return { node: retainedDeclaration };
860
+ }
861
+ return { node: statement };
862
+ }
863
+ function getStatementDeclaration(statement) {
864
+ if (statement.type === "ExportNamedDeclaration") return statement.declaration ?? null;
865
+ if (statement.type === "ExportDefaultDeclaration" && (statement.declaration.type === "FunctionDeclaration" || statement.declaration.type === "ClassDeclaration")) return statement.declaration;
866
+ if (statement.type === "FunctionDeclaration" || statement.type === "ClassDeclaration" || statement.type === "VariableDeclaration") return statement;
867
+ return null;
868
+ }
869
+ function collectBindingNamesFromDeclaration(declaration) {
870
+ if (declaration.type === "FunctionDeclaration" || declaration.type === "ClassDeclaration") return declaration.id ? [declaration.id.name] : [];
871
+ if (declaration.type === "VariableDeclaration") return declaration.declarations.flatMap((declarator) => collectBindingNamesFromPattern(declarator.id));
872
+ return [];
873
+ }
874
+ function collectBindingNamesFromPattern(pattern) {
875
+ if (!pattern) return [];
876
+ switch (pattern.type) {
877
+ case "Identifier": return [pattern.name];
878
+ case "AssignmentPattern": return collectBindingNamesFromPattern(pattern.left);
879
+ case "RestElement": return collectBindingNamesFromPattern(pattern.argument);
880
+ case "ObjectPattern": return pattern.properties.flatMap((property) => {
881
+ if (property.type === "Property") return collectBindingNamesFromPattern(property.value);
882
+ return collectBindingNamesFromPattern(property.argument);
883
+ });
884
+ case "ArrayPattern": return pattern.elements.flatMap((element) => collectBindingNamesFromPattern(element));
885
+ default: return [];
886
+ }
887
+ }
888
+ function enqueueDependencies(target, dependencies) {
889
+ for (const name of dependencies) target.add(name);
890
+ }
891
+ function getIdentifierName(node) {
892
+ if (!node) return null;
893
+ if (node.type === "Identifier" || node.type === "JSXIdentifier") return node.name;
894
+ if (node.type === "Literal" && typeof node.value === "string") return node.value;
895
+ return null;
896
+ }
897
+ function getRolldownLang(id) {
898
+ const path = stripPrachtClientModuleQuery(id).split("?")[0];
899
+ if (/\.(c|m)?tsx$/i.test(path)) return "tsx";
900
+ if (/\.(c|m)?ts$/i.test(path)) return "ts";
901
+ if (/\.(c|m)?jsx$/i.test(path)) return "jsx";
902
+ if (/\.mdx?$/i.test(path)) return "jsx";
903
+ if (/\.(c|m)?js$/i.test(path)) return "js";
904
+ return "tsx";
905
+ }
906
+ //#endregion
5
907
  //#region src/index.ts
6
908
  const PRACHT_CLIENT_MODULE_ID = "virtual:pracht/client";
7
909
  const PRACHT_SERVER_MODULE_ID = "virtual:pracht/server";
@@ -153,7 +1055,24 @@ async function pracht(options = {}) {
153
1055
  }
154
1056
  }
155
1057
  };
156
- const plugins = [...preact(), prachtPlugin];
1058
+ const clientModuleTransformPlugin = {
1059
+ name: "pracht:client-module-transform",
1060
+ enforce: "post",
1061
+ transform(code, id) {
1062
+ if (!isPrachtClientModuleId(id)) return null;
1063
+ const transformed = stripServerOnlyExportsForClient(code, id);
1064
+ if (transformed === code) return null;
1065
+ return {
1066
+ code: transformed,
1067
+ map: null
1068
+ };
1069
+ }
1070
+ };
1071
+ const plugins = [
1072
+ ...preact(),
1073
+ prachtPlugin,
1074
+ clientModuleTransformPlugin
1075
+ ];
157
1076
  const adapterPlugins = await resolved.adapter.vitePlugins?.();
158
1077
  if (adapterPlugins?.length) plugins.push(...adapterPlugins);
159
1078
  return plugins;
@@ -168,16 +1087,21 @@ function createPrachtClientModuleSource(options = {}, buildOptions = {}) {
168
1087
  "import { resolveApp, initClientRouter, readHydrationState } from \"@pracht/core\";",
169
1088
  appImport,
170
1089
  "",
171
- `const routeModules = import.meta.glob(${JSON.stringify(routeGlob)});`,
172
- `const shellModules = import.meta.glob(${JSON.stringify(shellGlob)});`,
1090
+ `const routeModules = import.meta.glob(${JSON.stringify(routeGlob)}, { query: ${JSON.stringify(PRACHT_CLIENT_MODULE_QUERY)} });`,
1091
+ `const shellModules = import.meta.glob(${JSON.stringify(shellGlob)}, { query: ${JSON.stringify(PRACHT_CLIENT_MODULE_QUERY)} });`,
173
1092
  "",
174
1093
  "const resolvedApp = resolveApp(app);",
175
1094
  "",
1095
+ "function normalizeModuleKey(key) {",
1096
+ " return key.split(\"?\")[0];",
1097
+ "}",
1098
+ "",
176
1099
  "function findModuleKey(modules, file) {",
177
1100
  " if (file in modules) return file;",
178
1101
  " const suffix = file.replace(/^\\.\\//,\"\");",
179
1102
  " for (const key of Object.keys(modules)) {",
180
- " if (key.endsWith(\"/\" + suffix) || key.endsWith(suffix)) return key;",
1103
+ " const normalizedKey = normalizeModuleKey(key);",
1104
+ " if (normalizedKey.endsWith(\"/\" + suffix) || normalizedKey.endsWith(suffix)) return key;",
181
1105
  " }",
182
1106
  " return null;",
183
1107
  "}",
@@ -391,8 +1315,9 @@ function readClientBuildAssets(root = process.cwd()) {
391
1315
  for (const [key, entry] of Object.entries(manifest)) {
392
1316
  if (!entry.src) continue;
393
1317
  const deps = collectTransitiveDeps(key);
394
- if (deps.css.length > 0) cssManifest[key] = deps.css.map((f) => `/${f}`);
395
- if (deps.js.length > 0) jsManifest[key] = deps.js.map((f) => `/${f}`);
1318
+ const manifestKey = stripPrachtClientModuleQuery(entry.src);
1319
+ if (deps.css.length > 0) cssManifest[manifestKey] = deps.css.map((f) => `/${f}`);
1320
+ if (deps.js.length > 0) jsManifest[manifestKey] = deps.js.map((f) => `/${f}`);
396
1321
  }
397
1322
  return {
398
1323
  clientEntryUrl: clientEntry ? `/${clientEntry.file}` : null,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pracht/vite-plugin",
3
- "version": "0.2.3",
3
+ "version": "0.2.4",
4
4
  "license": "MIT",
5
5
  "homepage": "https://github.com/JoviDeCroock/pracht/tree/main/packages/vite-plugin",
6
6
  "bugs": {
@@ -31,11 +31,11 @@
31
31
  "dependencies": {
32
32
  "@preact/preset-vite": "^2.10.5",
33
33
  "@prefresh/vite": "^2.0.0",
34
- "@pracht/adapter-node": "0.1.7",
35
- "@pracht/core": "0.2.6"
34
+ "@pracht/adapter-node": "0.1.8",
35
+ "@pracht/core": "0.2.7"
36
36
  },
37
37
  "peerDependencies": {
38
- "vite": "^7.0.0 || ^8.0.0"
38
+ "vite": "^8.0.0"
39
39
  },
40
40
  "scripts": {
41
41
  "build": "tsdown"