@tanstack/start-plugin-core 1.163.3 → 1.163.5

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.
Files changed (47) hide show
  1. package/dist/esm/constants.d.ts +1 -0
  2. package/dist/esm/constants.js +2 -0
  3. package/dist/esm/constants.js.map +1 -1
  4. package/dist/esm/import-protection-plugin/ast.d.ts +3 -0
  5. package/dist/esm/import-protection-plugin/ast.js +8 -0
  6. package/dist/esm/import-protection-plugin/ast.js.map +1 -0
  7. package/dist/esm/import-protection-plugin/constants.d.ts +6 -0
  8. package/dist/esm/import-protection-plugin/constants.js +24 -0
  9. package/dist/esm/import-protection-plugin/constants.js.map +1 -0
  10. package/dist/esm/import-protection-plugin/extensionlessAbsoluteIdResolver.d.ts +22 -0
  11. package/dist/esm/import-protection-plugin/extensionlessAbsoluteIdResolver.js +95 -0
  12. package/dist/esm/import-protection-plugin/extensionlessAbsoluteIdResolver.js.map +1 -0
  13. package/dist/esm/import-protection-plugin/plugin.d.ts +2 -13
  14. package/dist/esm/import-protection-plugin/plugin.js +684 -299
  15. package/dist/esm/import-protection-plugin/plugin.js.map +1 -1
  16. package/dist/esm/import-protection-plugin/postCompileUsage.js +4 -2
  17. package/dist/esm/import-protection-plugin/postCompileUsage.js.map +1 -1
  18. package/dist/esm/import-protection-plugin/rewriteDeniedImports.d.ts +4 -5
  19. package/dist/esm/import-protection-plugin/rewriteDeniedImports.js +225 -3
  20. package/dist/esm/import-protection-plugin/rewriteDeniedImports.js.map +1 -1
  21. package/dist/esm/import-protection-plugin/sourceLocation.d.ts +4 -7
  22. package/dist/esm/import-protection-plugin/sourceLocation.js +18 -73
  23. package/dist/esm/import-protection-plugin/sourceLocation.js.map +1 -1
  24. package/dist/esm/import-protection-plugin/types.d.ts +94 -0
  25. package/dist/esm/import-protection-plugin/utils.d.ts +33 -1
  26. package/dist/esm/import-protection-plugin/utils.js +69 -3
  27. package/dist/esm/import-protection-plugin/utils.js.map +1 -1
  28. package/dist/esm/import-protection-plugin/virtualModules.d.ts +30 -2
  29. package/dist/esm/import-protection-plugin/virtualModules.js +66 -23
  30. package/dist/esm/import-protection-plugin/virtualModules.js.map +1 -1
  31. package/dist/esm/start-compiler-plugin/plugin.d.ts +2 -1
  32. package/dist/esm/start-compiler-plugin/plugin.js +1 -2
  33. package/dist/esm/start-compiler-plugin/plugin.js.map +1 -1
  34. package/package.json +4 -4
  35. package/src/constants.ts +2 -0
  36. package/src/import-protection-plugin/INTERNALS.md +462 -60
  37. package/src/import-protection-plugin/ast.ts +7 -0
  38. package/src/import-protection-plugin/constants.ts +25 -0
  39. package/src/import-protection-plugin/extensionlessAbsoluteIdResolver.ts +121 -0
  40. package/src/import-protection-plugin/plugin.ts +1080 -597
  41. package/src/import-protection-plugin/postCompileUsage.ts +8 -2
  42. package/src/import-protection-plugin/rewriteDeniedImports.ts +141 -9
  43. package/src/import-protection-plugin/sourceLocation.ts +19 -89
  44. package/src/import-protection-plugin/types.ts +103 -0
  45. package/src/import-protection-plugin/utils.ts +123 -4
  46. package/src/import-protection-plugin/virtualModules.ts +117 -31
  47. package/src/start-compiler-plugin/plugin.ts +7 -2
@@ -2,6 +2,7 @@ import { resolveViteId } from '../utils'
2
2
  import { VITE_ENVIRONMENT_NAMES } from '../constants'
3
3
  import { isValidExportName } from './rewriteDeniedImports'
4
4
  import { CLIENT_ENV_SUGGESTIONS } from './trace'
5
+ import { VITE_BROWSER_VIRTUAL_PREFIX } from './constants'
5
6
  import { relativizePath } from './utils'
6
7
  import type { ViolationInfo } from './trace'
7
8
 
@@ -23,7 +24,7 @@ export const MOCK_RUNTIME_PREFIX =
23
24
  'tanstack-start-import-protection:mock-runtime:'
24
25
  const RESOLVED_MOCK_RUNTIME_PREFIX = resolveViteId(MOCK_RUNTIME_PREFIX)
25
26
 
26
- export const MARKER_PREFIX = 'tanstack-start-import-protection:marker:'
27
+ const MARKER_PREFIX = 'tanstack-start-import-protection:marker:'
27
28
  const RESOLVED_MARKER_PREFIX = resolveViteId(MARKER_PREFIX)
28
29
 
29
30
  const RESOLVED_MARKER_SERVER_ONLY = resolveViteId(`${MARKER_PREFIX}server-only`)
@@ -55,6 +56,13 @@ const RESOLVED_VIRTUAL_MODULE_MATCHERS = [
55
56
  RESOLVED_MARKER_PREFIX,
56
57
  ] as const
57
58
 
59
+ const RESOLVE_PREFIX_PAIRS = [
60
+ [MOCK_EDGE_PREFIX, RESOLVED_MOCK_EDGE_PREFIX],
61
+ [MOCK_RUNTIME_PREFIX, RESOLVED_MOCK_RUNTIME_PREFIX],
62
+ [MOCK_BUILD_PREFIX, RESOLVED_MOCK_BUILD_PREFIX],
63
+ [MARKER_PREFIX, RESOLVED_MARKER_PREFIX],
64
+ ] as const
65
+
58
66
  /**
59
67
  * Resolve import-protection's internal virtual module IDs.
60
68
  *
@@ -64,11 +72,26 @@ const RESOLVED_VIRTUAL_MODULE_MATCHERS = [
64
72
  export function resolveInternalVirtualModuleId(
65
73
  source: string,
66
74
  ): string | undefined {
67
- if (source === MOCK_MODULE_ID) return RESOLVED_MOCK_MODULE_ID
68
- if (source.startsWith(MOCK_EDGE_PREFIX)) return resolveViteId(source)
69
- if (source.startsWith(MOCK_RUNTIME_PREFIX)) return resolveViteId(source)
70
- if (source.startsWith(MOCK_BUILD_PREFIX)) return resolveViteId(source)
71
- if (source.startsWith(MARKER_PREFIX)) return resolveViteId(source)
75
+ if (source.startsWith(VITE_BROWSER_VIRTUAL_PREFIX)) {
76
+ return resolveInternalVirtualModuleId(
77
+ `\0${source.slice(VITE_BROWSER_VIRTUAL_PREFIX.length)}`,
78
+ )
79
+ }
80
+
81
+ if (source === MOCK_MODULE_ID || source === RESOLVED_MOCK_MODULE_ID) {
82
+ return RESOLVED_MOCK_MODULE_ID
83
+ }
84
+
85
+ for (const [unresolvedPrefix, resolvedPrefix] of RESOLVE_PREFIX_PAIRS) {
86
+ if (source.startsWith(unresolvedPrefix)) {
87
+ return resolveViteId(source)
88
+ }
89
+
90
+ if (source.startsWith(resolvedPrefix)) {
91
+ return source
92
+ }
93
+ }
94
+
72
95
  return undefined
73
96
  }
74
97
 
@@ -118,10 +141,9 @@ export function mockRuntimeModuleIdFromViolation(
118
141
 
119
142
  export function makeMockEdgeModuleId(
120
143
  exports: Array<string>,
121
- source: string,
122
144
  runtimeId: string,
123
145
  ): string {
124
- const payload = { source, exports, runtimeId }
146
+ const payload = { exports, runtimeId }
125
147
  return `${MOCK_EDGE_PREFIX}${toBase64Url(JSON.stringify(payload))}`
126
148
  }
127
149
 
@@ -254,36 +276,30 @@ export function loadSilentMockModule(): { code: string } {
254
276
  return { code: generateMockCode() }
255
277
  }
256
278
 
257
- export function loadMockEdgeModule(encodedPayload: string): { code: string } {
258
- let payload: { exports?: Array<string>; runtimeId?: string }
259
- try {
260
- payload = JSON.parse(fromBase64Url(encodedPayload)) as typeof payload
261
- } catch {
262
- payload = { exports: [] }
263
- }
264
- const names: Array<string> = Array.isArray(payload.exports)
265
- ? payload.exports.filter(
266
- (n): n is string =>
267
- typeof n === 'string' && n.length > 0 && n !== 'default',
268
- )
269
- : []
270
-
271
- const runtimeId: string =
272
- typeof payload.runtimeId === 'string' && payload.runtimeId.length > 0
273
- ? payload.runtimeId
274
- : MOCK_MODULE_ID
279
+ /**
280
+ * Filter export names to valid, non-default names.
281
+ */
282
+ function filterExportNames(exports: ReadonlyArray<string>): Array<string> {
283
+ return exports.filter((n) => n.length > 0 && n !== 'default')
284
+ }
275
285
 
276
- const exportLines: Array<string> = []
286
+ /**
287
+ * Generate ESM export lines that re-export named properties from `mock`.
288
+ *
289
+ * Produces `export const foo = mock.foo;` for valid identifiers and
290
+ * string-keyed re-exports for non-identifier names.
291
+ */
292
+ function generateExportLines(names: ReadonlyArray<string>): Array<string> {
293
+ const lines: Array<string> = []
277
294
  const stringExports: Array<{ alias: string; name: string }> = []
278
295
 
279
296
  for (let i = 0; i < names.length; i++) {
280
297
  const n = names[i]!
281
298
  if (isValidExportName(n)) {
282
- exportLines.push(`export const ${n} = mock.${n};`)
299
+ lines.push(`export const ${n} = mock.${n};`)
283
300
  } else {
284
- // ES2022 string-keyed export: use a temp var + re-export with string literal
285
301
  const alias = `__tss_str_${i}`
286
- exportLines.push(`const ${alias} = mock[${JSON.stringify(n)}];`)
302
+ lines.push(`const ${alias} = mock[${JSON.stringify(n)}];`)
287
303
  stringExports.push({ alias, name: n })
288
304
  }
289
305
  }
@@ -292,9 +308,79 @@ export function loadMockEdgeModule(encodedPayload: string): { code: string } {
292
308
  const reexports = stringExports
293
309
  .map((s) => `${s.alias} as ${JSON.stringify(s.name)}`)
294
310
  .join(', ')
295
- exportLines.push(`export { ${reexports} };`)
311
+ lines.push(`export { ${reexports} };`)
296
312
  }
297
313
 
314
+ return lines
315
+ }
316
+
317
+ /**
318
+ * Generate a self-contained mock module with explicit named exports.
319
+ *
320
+ * Used by the transform hook's "self-denial" check: when a denied file
321
+ * (e.g. `.server.ts` in the client environment) is transformed, its entire
322
+ * content is replaced with this mock module. This avoids returning virtual
323
+ * module IDs from `resolveId`, which prevents cross-environment cache
324
+ * contamination from third-party resolver plugins.
325
+ *
326
+ * The generated code is side-effect-free and tree-shakeable.
327
+ */
328
+ export function generateSelfContainedMockModule(exportNames: Array<string>): {
329
+ code: string
330
+ } {
331
+ const mockCode = generateMockCode()
332
+ const exportLines = generateExportLines(filterExportNames(exportNames))
333
+
334
+ return {
335
+ code: `${mockCode}
336
+ ${exportLines.join('\n')}
337
+ `,
338
+ }
339
+ }
340
+
341
+ /**
342
+ * Generate a dev-mode mock module for self-denial transforms.
343
+ *
344
+ * Similar to `loadMockEdgeModule` but takes export names and a runtime ID
345
+ * directly (instead of parsing them from a base64url-encoded payload).
346
+ * Used by the transform hook when a denied file (e.g. `.server.ts` in
347
+ * the client environment) is replaced in dev mode.
348
+ *
349
+ * The generated module imports mock-runtime for runtime diagnostics
350
+ * (error/warn on property access) and re-exports explicit named exports
351
+ * so that `import { foo } from './denied.server'` works.
352
+ */
353
+ export function generateDevSelfDenialModule(
354
+ exportNames: Array<string>,
355
+ runtimeId: string,
356
+ ): { code: string } {
357
+ const names = filterExportNames(exportNames)
358
+ const exportLines = generateExportLines(names)
359
+
360
+ return {
361
+ code: `import mock from ${JSON.stringify(runtimeId)};
362
+ ${exportLines.join('\n')}
363
+ export default mock;
364
+ `,
365
+ }
366
+ }
367
+
368
+ export function loadMockEdgeModule(encodedPayload: string): { code: string } {
369
+ let payload: { exports?: Array<string>; runtimeId?: string }
370
+ try {
371
+ payload = JSON.parse(fromBase64Url(encodedPayload)) as typeof payload
372
+ } catch {
373
+ payload = { exports: [] }
374
+ }
375
+ const names = filterExportNames(payload.exports ?? [])
376
+
377
+ const runtimeId: string =
378
+ typeof payload.runtimeId === 'string' && payload.runtimeId.length > 0
379
+ ? payload.runtimeId
380
+ : MOCK_MODULE_ID
381
+
382
+ const exportLines = generateExportLines(names)
383
+
298
384
  return {
299
385
  code: `import mock from ${JSON.stringify(runtimeId)};
300
386
  ${exportLines.join('\n')}
@@ -1,7 +1,11 @@
1
1
  import assert from 'node:assert'
2
2
  import { VIRTUAL_MODULES } from '@tanstack/start-server-core'
3
3
  import { resolve as resolvePath } from 'pathe'
4
- import { TRANSFORM_ID_REGEX, VITE_ENVIRONMENT_NAMES } from '../constants'
4
+ import {
5
+ SERVER_FN_LOOKUP,
6
+ TRANSFORM_ID_REGEX,
7
+ VITE_ENVIRONMENT_NAMES,
8
+ } from '../constants'
5
9
  import {
6
10
  KindDetectionPatterns,
7
11
  LookupKindsPerEnv,
@@ -82,7 +86,8 @@ const getLookupConfigurationsForEnv = (
82
86
  ]
83
87
  }
84
88
  }
85
- export const SERVER_FN_LOOKUP = 'server-fn-module-lookup'
89
+ // Re-export from shared constants for backwards compatibility
90
+ export { SERVER_FN_LOOKUP }
86
91
 
87
92
  function resolveViteId(id: string) {
88
93
  return `\0${id}`