one 1.17.11 → 1.18.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/dist/cjs/cli/build.cjs +41 -2
  2. package/dist/cjs/cli/build.native.js +50 -2
  3. package/dist/cjs/cli/build.native.js.map +1 -1
  4. package/dist/cjs/getURL.native.js +6 -5
  5. package/dist/cjs/getURL.native.js.map +1 -1
  6. package/dist/cjs/getURL.native.test.cjs +26 -0
  7. package/dist/cjs/getURL.native.test.native.js +33 -0
  8. package/dist/cjs/getURL.native.test.native.js.map +1 -0
  9. package/dist/cjs/vite/constants.cjs +0 -2
  10. package/dist/cjs/vite/constants.native.js +0 -2
  11. package/dist/cjs/vite/constants.native.js.map +1 -1
  12. package/dist/cjs/vite/plugins/environmentGuardPlugin.cjs +25 -15
  13. package/dist/cjs/vite/plugins/environmentGuardPlugin.native.js +26 -16
  14. package/dist/cjs/vite/plugins/environmentGuardPlugin.native.js.map +1 -1
  15. package/dist/cjs/vite/plugins/environmentGuardPlugin.test.cjs +44 -31
  16. package/dist/cjs/vite/plugins/environmentGuardPlugin.test.native.js +44 -31
  17. package/dist/cjs/vite/plugins/environmentGuardPlugin.test.native.js.map +1 -1
  18. package/dist/cjs/vite/plugins/fileSystemRouterPlugin.cjs +8 -3
  19. package/dist/cjs/vite/plugins/fileSystemRouterPlugin.native.js +8 -3
  20. package/dist/cjs/vite/plugins/fileSystemRouterPlugin.native.js.map +1 -1
  21. package/dist/esm/cli/build.mjs +41 -2
  22. package/dist/esm/cli/build.mjs.map +1 -1
  23. package/dist/esm/cli/build.native.js +50 -2
  24. package/dist/esm/cli/build.native.js.map +1 -1
  25. package/dist/esm/getURL.native.js +6 -5
  26. package/dist/esm/getURL.native.js.map +1 -1
  27. package/dist/esm/getURL.native.test.js +27 -0
  28. package/dist/esm/getURL.native.test.js.map +6 -0
  29. package/dist/esm/getURL.native.test.mjs +27 -0
  30. package/dist/esm/getURL.native.test.mjs.map +1 -0
  31. package/dist/esm/getURL.native.test.native.js +31 -0
  32. package/dist/esm/getURL.native.test.native.js.map +1 -0
  33. package/dist/esm/vite/constants.mjs +1 -2
  34. package/dist/esm/vite/constants.mjs.map +1 -1
  35. package/dist/esm/vite/constants.native.js +1 -2
  36. package/dist/esm/vite/constants.native.js.map +1 -1
  37. package/dist/esm/vite/plugins/environmentGuardPlugin.mjs +25 -15
  38. package/dist/esm/vite/plugins/environmentGuardPlugin.mjs.map +1 -1
  39. package/dist/esm/vite/plugins/environmentGuardPlugin.native.js +26 -16
  40. package/dist/esm/vite/plugins/environmentGuardPlugin.native.js.map +1 -1
  41. package/dist/esm/vite/plugins/environmentGuardPlugin.test.mjs +44 -31
  42. package/dist/esm/vite/plugins/environmentGuardPlugin.test.mjs.map +1 -1
  43. package/dist/esm/vite/plugins/environmentGuardPlugin.test.native.js +44 -31
  44. package/dist/esm/vite/plugins/environmentGuardPlugin.test.native.js.map +1 -1
  45. package/dist/esm/vite/plugins/fileSystemRouterPlugin.mjs +8 -3
  46. package/dist/esm/vite/plugins/fileSystemRouterPlugin.mjs.map +1 -1
  47. package/dist/esm/vite/plugins/fileSystemRouterPlugin.native.js +8 -3
  48. package/dist/esm/vite/plugins/fileSystemRouterPlugin.native.js.map +1 -1
  49. package/env.d.ts +2 -0
  50. package/package.json +10 -10
  51. package/src/cli/build.ts +58 -1
  52. package/src/getURL.native.test.ts +33 -0
  53. package/src/getURL.native.ts +9 -7
  54. package/src/vite/constants.ts +0 -2
  55. package/src/vite/plugins/environmentGuardPlugin.test.ts +58 -33
  56. package/src/vite/plugins/environmentGuardPlugin.ts +50 -20
  57. package/src/vite/plugins/fileSystemRouterPlugin.tsx +18 -4
  58. package/types/cli/build.d.ts.map +1 -1
  59. package/types/getURL.native.d.ts.map +1 -1
  60. package/types/getURL.native.test.d.ts +2 -0
  61. package/types/getURL.native.test.d.ts.map +1 -0
  62. package/types/vite/constants.d.ts +0 -1
  63. package/types/vite/constants.d.ts.map +1 -1
  64. package/types/vite/plugins/environmentGuardPlugin.d.ts +16 -4
  65. package/types/vite/plugins/environmentGuardPlugin.d.ts.map +1 -1
  66. package/types/vite/plugins/fileSystemRouterPlugin.d.ts.map +1 -1
@@ -7,10 +7,16 @@
7
7
  *
8
8
  * | import | allowed in | throws in |
9
9
  * |-----------------|------------------|----------------------------|
10
- * | server-only | ssr | client, ios, android |
11
- * | client-only | client | ssr, ios, android |
12
- * | native-only | ios, android | client, ssr |
10
+ * | server-only | any server env | any client env |
11
+ * | client-only | any client env | any server env |
12
+ * | native-only | ios, android | other names |
13
13
  * | web-only | client, ssr | ios, android |
14
+ *
15
+ * server-only / client-only key off `env.config.consumer` so they work
16
+ * uniformly across `ssr`, custom names like `worker` (cloudflare deploy),
17
+ * or any other consumer-tagged environment a downstream framework defines.
18
+ * native-only / web-only stay name-based because they discriminate by
19
+ * platform, not by consumer type.
14
20
  */
15
21
 
16
22
  import type { Plugin } from 'vite'
@@ -27,13 +33,16 @@ const GUARD_SPECIFIERS = [
27
33
  type GuardSpecifier = (typeof GUARD_SPECIFIERS)[number]
28
34
  type ViteEnvironment = 'client' | 'ssr' | 'ios' | 'android'
29
35
 
30
- const ALLOWED_ENVIRONMENTS: Record<GuardSpecifier, readonly ViteEnvironment[]> = {
31
- 'server-only': ['ssr'],
32
- 'client-only': ['client'],
36
+ const ALLOWED_BY_NAME: Partial<Record<GuardSpecifier, readonly ViteEnvironment[]>> = {
33
37
  'native-only': ['ios', 'android'],
34
38
  'web-only': ['client', 'ssr'],
35
39
  }
36
40
 
41
+ const ALLOWED_BY_CONSUMER: Partial<Record<GuardSpecifier, 'server' | 'client'>> = {
42
+ 'server-only': 'server',
43
+ 'client-only': 'client',
44
+ }
45
+
37
46
  export type EnvironmentGuardOptions = {
38
47
  /**
39
48
  * Disable all environment guard checks. When true, all guard imports
@@ -55,10 +64,17 @@ export type EnvironmentGuardOptions = {
55
64
  /**
56
65
  * returns a virtual module id if the specifier is a guard, otherwise null.
57
66
  * pure function extracted for testing.
67
+ *
68
+ * `consumer` is vite's environment.config.consumer ('server' | 'client').
69
+ * encoded into the virtual id so loadEnvironmentGuard can decide whether
70
+ * server-only / client-only fire without re-deriving it. callers that
71
+ * don't have access to a consumer (legacy callsites, tests) may pass
72
+ * undefined; load will then fall back to name-based matching.
58
73
  */
59
74
  export function resolveEnvironmentGuard(
60
75
  specifier: string,
61
76
  envName: string,
77
+ consumer?: 'server' | 'client',
62
78
  options?: EnvironmentGuardOptions
63
79
  ): string | null {
64
80
  if (!GUARD_SPECIFIERS.includes(specifier as GuardSpecifier)) {
@@ -73,7 +89,7 @@ export function resolveEnvironmentGuard(
73
89
  return `${VIRTUAL_PREFIX}${specifier}:disabled`
74
90
  }
75
91
 
76
- return `${VIRTUAL_PREFIX}${specifier}:${envName}`
92
+ return `${VIRTUAL_PREFIX}${specifier}:${envName}:${consumer ?? 'unknown'}`
77
93
  }
78
94
 
79
95
  /**
@@ -86,24 +102,37 @@ export function loadEnvironmentGuard(id: string): string | null {
86
102
  }
87
103
 
88
104
  const rest = id.slice(VIRTUAL_PREFIX.length)
89
- const lastColon = rest.lastIndexOf(':')
90
- if (lastColon === -1) return null
105
+ const parts = rest.split(':')
91
106
 
92
- const specifier = rest.slice(0, lastColon) as GuardSpecifier
93
- const envName = rest.slice(lastColon + 1)
94
-
95
- // disabled guards always pass
96
- if (envName === 'disabled') {
107
+ // legacy 2-part form: `${specifier}:disabled` always passes
108
+ if (parts.length === 2 && parts[1] === 'disabled') {
97
109
  return 'export {}'
98
110
  }
99
111
 
100
- const allowed = ALLOWED_ENVIRONMENTS[specifier]
101
- if (!allowed) return null
102
-
103
- if (allowed.includes(envName as ViteEnvironment)) {
104
- return 'export {}'
112
+ const specifier = parts[0] as GuardSpecifier
113
+ const envName = parts[1]
114
+ const consumer = parts[2] as 'server' | 'client' | 'unknown' | undefined
115
+
116
+ // server-only / client-only: consumer-based. works for any env name a
117
+ // framework defines (ssr, worker, edge, custom) — the test is "what
118
+ // does vite consider this environment to be consumed by?"
119
+ const requiredConsumer = ALLOWED_BY_CONSUMER[specifier]
120
+ if (requiredConsumer) {
121
+ if (consumer === requiredConsumer) return 'export {}'
122
+ // if consumer wasn't recorded (legacy 2-part form or `unknown`),
123
+ // fall back to the historical name-based behaviour so existing tests
124
+ // keep working without modification.
125
+ if (!consumer || consumer === 'unknown') {
126
+ const legacyAllowed = requiredConsumer === 'server' ? ['ssr'] : ['client']
127
+ if (legacyAllowed.includes(envName)) return 'export {}'
128
+ }
129
+ return `throw new Error("${specifier} cannot be imported in the \\"${envName}\\" environment")`
105
130
  }
106
131
 
132
+ // native-only / web-only: name-based.
133
+ const allowedNames = ALLOWED_BY_NAME[specifier]
134
+ if (!allowedNames) return null
135
+ if (allowedNames.includes(envName as ViteEnvironment)) return 'export {}'
107
136
  return `throw new Error("${specifier} cannot be imported in the \\"${envName}\\" environment")`
108
137
  }
109
138
 
@@ -115,7 +144,8 @@ export function environmentGuardPlugin(options?: EnvironmentGuardOptions): Plugi
115
144
  resolveId(source) {
116
145
  const envName = this.environment?.name
117
146
  if (!envName) return null
118
- return resolveEnvironmentGuard(source, envName, options)
147
+ const consumer = this.environment?.config?.consumer
148
+ return resolveEnvironmentGuard(source, envName, consumer, options)
119
149
  },
120
150
 
121
151
  load(id) {
@@ -16,7 +16,6 @@ import { isStatusRedirect } from '../../utils/isStatus'
16
16
  import { promiseWithResolvers } from '../../utils/promiseWithResolvers'
17
17
  import { isRouteFileWatchEvent } from '../../utils/routeFileWatch'
18
18
  import { trackLoaderDependencies } from '../../utils/trackLoaderDependencies'
19
- import { LoaderDataCache } from '../../vite/constants'
20
19
  import { replaceLoader } from '../../vite/replaceLoader'
21
20
  import type { One } from '../../vite/types'
22
21
  import { setServerContext } from '../one-server-only'
@@ -41,6 +40,13 @@ export function createFileSystemRouterPlugin(options: One.PluginOptions): Plugin
41
40
  let runner: ModuleRunner
42
41
  let server: ViteDevServer
43
42
 
43
+ // Only clear the SSR module runner cache when a file actually changed, not on
44
+ // every request. Clearing per-request forces a full re-evaluation of the whole
45
+ // server module tree (new AsyncFunction per module) on each page render, which
46
+ // leaks heap unboundedly under sustained navigation (→ 5-8GB RSS / OOM) and also
47
+ // re-transforms every module. The file watcher below flips this back to true.
48
+ let needsCacheClear = true
49
+
44
50
  // Track file dependencies from loaders for hot reload
45
51
  // Maps file path -> set of route paths that depend on it
46
52
  // Track file dependencies from loaders for hot reload.
@@ -147,7 +153,10 @@ export function createFileSystemRouterPlugin(options: One.PluginOptions): Plugin
147
153
  // so we must branch on route.file, not the joined path.
148
154
  const isGeneratedNotFound = route.file === ''
149
155
  const routeFile = isGeneratedNotFound ? '' : path.join(routerRoot, route.file)
150
- runner.clearCache()
156
+ if (needsCacheClear) {
157
+ runner.clearCache()
158
+ needsCacheClear = false
159
+ }
151
160
 
152
161
  globalThis['__vxrnresetState']?.()
153
162
 
@@ -270,8 +279,6 @@ export function createFileSystemRouterPlugin(options: One.PluginOptions): Plugin
270
279
  matches,
271
280
  })
272
281
 
273
- LoaderDataCache[route.file] = loaderData
274
-
275
282
  // detect 404: not-found routes, missing page exports, or ssg dynamic routes with invalid slugs
276
283
  const isDynamicRoute = Object.keys(route.routeKeys || {}).length > 0
277
284
 
@@ -610,6 +617,13 @@ export function createFileSystemRouterPlugin(options: One.PluginOptions): Plugin
610
617
 
611
618
  const appDir = path.resolve(process.cwd(), getRouterRootFromOneOptions(options))
612
619
 
620
+ // any watched file change means the SSR runner may be serving stale module
621
+ // code — mark the cache dirty so the next render re-evaluates once (set
622
+ // immediately/undebounced so it can't race ahead of a render)
623
+ server.watcher.on('all', () => {
624
+ needsCacheClear = true
625
+ })
626
+
613
627
  // on change ./app stuff lets reload this to pick up any route changes
614
628
  const fileWatcherChangeListener = debounce((type: string, changedPath: string) => {
615
629
  if (
@@ -1 +1 @@
1
- {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/cli/build.ts"],"names":[],"mappings":"AA6UA,wBAAsB,KAAK,CAAC,IAAI,EAAE;IAChC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,SAAS,CAAA;IACpC,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,iBAkvCA"}
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/cli/build.ts"],"names":[],"mappings":"AA0XA,wBAAsB,KAAK,CAAC,IAAI,EAAE;IAChC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,SAAS,CAAA;IACpC,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,iBA8vCA"}
@@ -1 +1 @@
1
- {"version":3,"file":"getURL.native.d.ts","sourceRoot":"","sources":["../src/getURL.native.ts"],"names":[],"mappings":"AAIA,wBAAgB,MAAM,WAwBrB"}
1
+ {"version":3,"file":"getURL.native.d.ts","sourceRoot":"","sources":["../src/getURL.native.ts"],"names":[],"mappings":"AAIA,wBAAgB,MAAM,WA0BrB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=getURL.native.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getURL.native.test.d.ts","sourceRoot":"","sources":["../src/getURL.native.test.ts"],"names":[],"mappings":""}
@@ -1,5 +1,4 @@
1
1
  export declare const EMPTY_LOADER_STRING = "export function loader() {return \"__vxrn__loader__\"};";
2
2
  export declare function makeLoaderRouteIdStub(routeId: string): string;
3
- export declare const LoaderDataCache: {};
4
3
  export declare const SERVER_CONTEXT_POST_RENDER_STRING = "_one_post_render_data_";
5
4
  //# sourceMappingURL=constants.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/vite/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mBAAmB,4DAA0D,CAAA;AAE1F,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED,eAAO,MAAM,eAAe,IAAK,CAAA;AAEjC,eAAO,MAAM,iCAAiC,2BAA2B,CAAA"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/vite/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mBAAmB,4DAA0D,CAAA;AAE1F,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED,eAAO,MAAM,iCAAiC,2BAA2B,CAAA"}
@@ -7,10 +7,16 @@
7
7
  *
8
8
  * | import | allowed in | throws in |
9
9
  * |-----------------|------------------|----------------------------|
10
- * | server-only | ssr | client, ios, android |
11
- * | client-only | client | ssr, ios, android |
12
- * | native-only | ios, android | client, ssr |
10
+ * | server-only | any server env | any client env |
11
+ * | client-only | any client env | any server env |
12
+ * | native-only | ios, android | other names |
13
13
  * | web-only | client, ssr | ios, android |
14
+ *
15
+ * server-only / client-only key off `env.config.consumer` so they work
16
+ * uniformly across `ssr`, custom names like `worker` (cloudflare deploy),
17
+ * or any other consumer-tagged environment a downstream framework defines.
18
+ * native-only / web-only stay name-based because they discriminate by
19
+ * platform, not by consumer type.
14
20
  */
15
21
  import type { Plugin } from 'vite';
16
22
  declare const GUARD_SPECIFIERS: readonly ["server-only", "client-only", "native-only", "web-only"];
@@ -34,8 +40,14 @@ export type EnvironmentGuardOptions = {
34
40
  /**
35
41
  * returns a virtual module id if the specifier is a guard, otherwise null.
36
42
  * pure function extracted for testing.
43
+ *
44
+ * `consumer` is vite's environment.config.consumer ('server' | 'client').
45
+ * encoded into the virtual id so loadEnvironmentGuard can decide whether
46
+ * server-only / client-only fire without re-deriving it. callers that
47
+ * don't have access to a consumer (legacy callsites, tests) may pass
48
+ * undefined; load will then fall back to name-based matching.
37
49
  */
38
- export declare function resolveEnvironmentGuard(specifier: string, envName: string, options?: EnvironmentGuardOptions): string | null;
50
+ export declare function resolveEnvironmentGuard(specifier: string, envName: string, consumer?: 'server' | 'client', options?: EnvironmentGuardOptions): string | null;
39
51
  /**
40
52
  * returns the module source for a virtual guard id.
41
53
  * pure function extracted for testing.
@@ -1 +1 @@
1
- {"version":3,"file":"environmentGuardPlugin.d.ts","sourceRoot":"","sources":["../../../src/vite/plugins/environmentGuardPlugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAIlC,QAAA,MAAM,gBAAgB,oEAKZ,CAAA;AAEV,KAAK,cAAc,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAA;AAUvD,MAAM,MAAM,uBAAuB,GAAG;IACpC;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAElB;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,cAAc,EAAE,CAAA;CACjC,CAAA;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,uBAAuB,GAChC,MAAM,GAAG,IAAI,CAcf;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAyB9D;AAED,wBAAgB,sBAAsB,CAAC,OAAO,CAAC,EAAE,uBAAuB,GAAG,MAAM,CAehF"}
1
+ {"version":3,"file":"environmentGuardPlugin.d.ts","sourceRoot":"","sources":["../../../src/vite/plugins/environmentGuardPlugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAIlC,QAAA,MAAM,gBAAgB,oEAKZ,CAAA;AAEV,KAAK,cAAc,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAA;AAavD,MAAM,MAAM,uBAAuB,GAAG;IACpC;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAElB;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,cAAc,EAAE,CAAA;CACjC,CAAA;AAED;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,QAAQ,GAAG,QAAQ,EAC9B,OAAO,CAAC,EAAE,uBAAuB,GAChC,MAAM,GAAG,IAAI,CAcf;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAsC9D;AAED,wBAAgB,sBAAsB,CAAC,OAAO,CAAC,EAAE,uBAAuB,GAAG,MAAM,CAgBhF"}
@@ -1 +1 @@
1
- {"version":3,"file":"fileSystemRouterPlugin.d.ts","sourceRoot":"","sources":["../../../src/vite/plugins/fileSystemRouterPlugin.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAW,MAAM,EAAiB,MAAM,MAAM,CAAA;AAgB1D,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAiB3C,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,GAAG,CAAC,aAAa,GAAG,MAAM,CAmvB/E"}
1
+ {"version":3,"file":"fileSystemRouterPlugin.d.ts","sourceRoot":"","sources":["../../../src/vite/plugins/fileSystemRouterPlugin.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAW,MAAM,EAAiB,MAAM,MAAM,CAAA;AAe1D,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAiB3C,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,GAAG,CAAC,aAAa,GAAG,MAAM,CAkwB/E"}