@tanstack/redact 0.0.20 → 0.1.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.
Files changed (253) hide show
  1. package/dist/core/attributes.js +2 -1
  2. package/dist/core/attributes.js.map +2 -2
  3. package/dist/core/browser.d.ts +9 -0
  4. package/dist/core/browser.js +35 -0
  5. package/dist/core/browser.js.map +7 -0
  6. package/dist/core/index.d.ts +2 -2
  7. package/dist/core/index.js +3 -3
  8. package/dist/core/internal.d.ts +31 -8
  9. package/dist/core/internal.js +3 -1
  10. package/dist/core/internal.js.map +2 -2
  11. package/dist/core/resource-hints.d.ts +7 -0
  12. package/dist/core/resource-hints.js +19 -0
  13. package/dist/core/resource-hints.js.map +7 -0
  14. package/dist/core/types.js +1 -1
  15. package/dist/dom/_all.d.ts +11 -16
  16. package/dist/dom/_all.js +9 -20
  17. package/dist/dom/_all.js.map +2 -2
  18. package/dist/dom/client.d.ts +4 -4
  19. package/dist/dom/client.js +4 -4
  20. package/dist/dom/commit.d.ts +23 -0
  21. package/dist/dom/commit.js +191 -0
  22. package/dist/dom/commit.js.map +7 -0
  23. package/dist/dom/dispatcher.d.ts +4 -22
  24. package/dist/dom/dispatcher.js +184 -126
  25. package/dist/dom/dispatcher.js.map +3 -3
  26. package/dist/dom/dom.d.ts +2 -0
  27. package/dist/dom/dom.js +72 -52
  28. package/dist/dom/dom.js.map +2 -2
  29. package/dist/dom/error-info.d.ts +2 -0
  30. package/dist/dom/error-info.js +16 -0
  31. package/dist/dom/error-info.js.map +7 -0
  32. package/dist/dom/event-replay.js +1 -1
  33. package/dist/dom/features/activity/full.d.ts +1 -0
  34. package/dist/dom/features/activity/full.js +162 -0
  35. package/dist/dom/features/activity/full.js.map +7 -0
  36. package/dist/dom/features/activity/index.d.ts +1 -0
  37. package/dist/dom/features/activity/index.js +3 -0
  38. package/dist/dom/features/activity/index.js.map +7 -0
  39. package/dist/dom/features/activity/stub.d.ts +1 -0
  40. package/dist/dom/features/activity/stub.js +12 -0
  41. package/dist/dom/features/activity/stub.js.map +7 -0
  42. package/dist/dom/features/class/full.js +87 -21
  43. package/dist/dom/features/class/full.js.map +2 -2
  44. package/dist/dom/features/class/index.d.ts +1 -1
  45. package/dist/dom/features/class/index.js +2 -2
  46. package/dist/dom/features/class/stub.js +3 -3
  47. package/dist/dom/features/context/full.d.ts +4 -1
  48. package/dist/dom/features/context/full.js +69 -9
  49. package/dist/dom/features/context/full.js.map +2 -2
  50. package/dist/dom/features/context/index.d.ts +1 -1
  51. package/dist/dom/features/context/index.js +2 -2
  52. package/dist/dom/features/context/stub.d.ts +4 -1
  53. package/dist/dom/features/context/stub.js +15 -4
  54. package/dist/dom/features/context/stub.js.map +2 -2
  55. package/dist/dom/features/forward-ref/full.js +12 -21
  56. package/dist/dom/features/forward-ref/full.js.map +2 -2
  57. package/dist/dom/features/forward-ref/index.d.ts +1 -1
  58. package/dist/dom/features/forward-ref/index.js +2 -2
  59. package/dist/dom/features/forward-ref/stub.js +4 -4
  60. package/dist/dom/features/fragment-refs/index.d.ts +1 -0
  61. package/dist/dom/features/fragment-refs/index.js +8 -0
  62. package/dist/dom/features/fragment-refs/index.js.map +7 -0
  63. package/dist/dom/features/fragment-refs/stub.d.ts +3 -0
  64. package/dist/dom/features/fragment-refs/stub.js +14 -0
  65. package/dist/dom/features/fragment-refs/stub.js.map +7 -0
  66. package/dist/dom/features/hydration/full.d.ts +11 -6
  67. package/dist/dom/features/hydration/full.js +76 -76
  68. package/dist/dom/features/hydration/full.js.map +2 -2
  69. package/dist/dom/features/hydration/index.d.ts +1 -1
  70. package/dist/dom/features/hydration/index.js +2 -2
  71. package/dist/dom/features/hydration/stub.d.ts +7 -2
  72. package/dist/dom/features/hydration/stub.js +1 -1
  73. package/dist/dom/features/hydration/stub.js.map +1 -1
  74. package/dist/dom/features/index.d.ts +8 -7
  75. package/dist/dom/features/index.js +9 -8
  76. package/dist/dom/features/index.js.map +2 -2
  77. package/dist/dom/features/lazy/full.js +4 -4
  78. package/dist/dom/features/lazy/index.d.ts +1 -1
  79. package/dist/dom/features/lazy/index.js +2 -2
  80. package/dist/dom/features/lazy/stub.js +4 -4
  81. package/dist/dom/features/memo/full.js +8 -6
  82. package/dist/dom/features/memo/full.js.map +2 -2
  83. package/dist/dom/features/memo/index.d.ts +1 -1
  84. package/dist/dom/features/memo/index.js +2 -2
  85. package/dist/dom/features/memo/stub.js +4 -4
  86. package/dist/dom/features/portal/full.js +4 -4
  87. package/dist/dom/features/portal/index.d.ts +1 -1
  88. package/dist/dom/features/portal/index.js +2 -2
  89. package/dist/dom/features/portal/stub.js +4 -4
  90. package/dist/dom/features/suspense/full.js +192 -47
  91. package/dist/dom/features/suspense/full.js.map +2 -2
  92. package/dist/dom/features/suspense/index.d.ts +1 -1
  93. package/dist/dom/features/suspense/index.js +2 -2
  94. package/dist/dom/features/suspense/stub.js +4 -4
  95. package/dist/dom/features/view-transition/full.d.ts +6 -0
  96. package/dist/dom/features/view-transition/full.js +280 -0
  97. package/dist/dom/features/view-transition/full.js.map +7 -0
  98. package/dist/dom/features/view-transition/index.d.ts +1 -0
  99. package/dist/dom/features/view-transition/index.js +3 -0
  100. package/dist/dom/features/view-transition/index.js.map +7 -0
  101. package/dist/dom/features/view-transition/resources.d.ts +11 -0
  102. package/dist/dom/features/view-transition/resources.js +108 -0
  103. package/dist/dom/features/view-transition/resources.js.map +7 -0
  104. package/dist/dom/features/view-transition/stub.d.ts +6 -0
  105. package/dist/dom/features/view-transition/stub.js +22 -0
  106. package/dist/dom/features/view-transition/stub.js.map +7 -0
  107. package/dist/dom/features/view-transition/visual.d.ts +14 -0
  108. package/dist/dom/features/view-transition/visual.js +356 -0
  109. package/dist/dom/features/view-transition/visual.js.map +7 -0
  110. package/dist/dom/fragment-instance.d.ts +40 -0
  111. package/dist/dom/fragment-instance.js +324 -0
  112. package/dist/dom/fragment-instance.js.map +7 -0
  113. package/dist/dom/index.d.ts +11 -11
  114. package/dist/dom/index.js +11 -18
  115. package/dist/dom/index.js.map +3 -3
  116. package/dist/dom/portal.d.ts +2 -2
  117. package/dist/dom/portal.js +2 -2
  118. package/dist/dom/portal.js.map +1 -1
  119. package/dist/dom/reconcile.d.ts +32 -3
  120. package/dist/dom/reconcile.js +686 -222
  121. package/dist/dom/reconcile.js.map +2 -2
  122. package/dist/dom/resource-hints.d.ts +6 -0
  123. package/dist/dom/resource-hints.js +115 -0
  124. package/dist/dom/resource-hints.js.map +7 -0
  125. package/dist/dom/resource-store.d.ts +13 -0
  126. package/dist/dom/resource-store.js +43 -0
  127. package/dist/dom/resource-store.js.map +7 -0
  128. package/dist/dom/resources.d.ts +1 -0
  129. package/dist/dom/resources.js +44 -0
  130. package/dist/dom/resources.js.map +7 -0
  131. package/dist/dom/retained-effects.d.ts +6 -0
  132. package/dist/dom/retained-effects.js +49 -0
  133. package/dist/dom/retained-effects.js.map +7 -0
  134. package/dist/dom/root-internal.d.ts +4 -4
  135. package/dist/dom/root-internal.js +2 -2
  136. package/dist/dom/root-internal.js.map +2 -2
  137. package/dist/dom/root.d.ts +5 -5
  138. package/dist/dom/root.js +11 -11
  139. package/dist/dom/root.js.map +2 -2
  140. package/dist/dom/test-utils.js +1 -1
  141. package/dist/react/activity.d.ts +7 -0
  142. package/dist/react/activity.js +8 -0
  143. package/dist/react/activity.js.map +7 -0
  144. package/dist/react/children.d.ts +1 -1
  145. package/dist/react/children.js +3 -3
  146. package/dist/react/children.js.map +1 -1
  147. package/dist/react/class.d.ts +1 -1
  148. package/dist/react/class.js +3 -3
  149. package/dist/react/class.js.map +1 -1
  150. package/dist/react/compiler-runtime.js +2 -2
  151. package/dist/react/context.d.ts +1 -1
  152. package/dist/react/context.js +3 -3
  153. package/dist/react/context.js.map +1 -1
  154. package/dist/react/element.d.ts +6 -3
  155. package/dist/react/element.js +2 -2
  156. package/dist/react/element.js.map +2 -2
  157. package/dist/react/hooks.d.ts +26 -7
  158. package/dist/react/hooks.js +13 -3
  159. package/dist/react/hooks.js.map +2 -2
  160. package/dist/react/index.d.ts +39 -24
  161. package/dist/react/index.js +39 -19
  162. package/dist/react/index.js.map +3 -3
  163. package/dist/react/jsx-runtime.d.ts +2 -2
  164. package/dist/react/jsx-runtime.js +3 -3
  165. package/dist/react/memo.d.ts +1 -1
  166. package/dist/react/memo.js +1 -1
  167. package/dist/react/portal.js +1 -1
  168. package/dist/react/shared-internals.d.ts +15 -5
  169. package/dist/react/shared-internals.js +2 -3
  170. package/dist/react/shared-internals.js.map +2 -2
  171. package/dist/react/suspense.js +1 -1
  172. package/dist/react/view-transition.d.ts +32 -0
  173. package/dist/react/view-transition.js +13 -0
  174. package/dist/react/view-transition.js.map +7 -0
  175. package/dist/scheduler/index.js +1 -1
  176. package/dist/server/bootstrap-script.d.ts +1 -23
  177. package/dist/server/bootstrap-script.js +7 -6
  178. package/dist/server/bootstrap-script.js.map +2 -2
  179. package/dist/server/dispatcher.d.ts +28 -6
  180. package/dist/server/dispatcher.js +33 -15
  181. package/dist/server/dispatcher.js.map +2 -2
  182. package/dist/server/escape.js +16 -15
  183. package/dist/server/escape.js.map +2 -2
  184. package/dist/server/index.d.ts +6 -6
  185. package/dist/server/index.js +7 -7
  186. package/dist/server/renderToString.d.ts +1 -1
  187. package/dist/server/renderToString.js +12 -8
  188. package/dist/server/renderToString.js.map +2 -2
  189. package/dist/server/resource-hints.d.ts +22 -0
  190. package/dist/server/resource-hints.js +148 -0
  191. package/dist/server/resource-hints.js.map +7 -0
  192. package/dist/server/stream.d.ts +15 -2
  193. package/dist/server/stream.js +155 -63
  194. package/dist/server/stream.js.map +2 -2
  195. package/dist/server/walk.d.ts +15 -2
  196. package/dist/server/walk.js +143 -96
  197. package/dist/server/walk.js.map +2 -2
  198. package/dist/vite/index.d.ts +6 -0
  199. package/dist/vite/index.js +22 -6
  200. package/dist/vite/index.js.map +2 -2
  201. package/package.json +1 -1
  202. package/src/core/attributes.ts +1 -0
  203. package/src/core/browser.ts +33 -0
  204. package/src/core/internal.ts +24 -6
  205. package/src/core/resource-hints.ts +36 -0
  206. package/src/dom/_all.ts +1 -7
  207. package/src/dom/commit.ts +186 -0
  208. package/src/dom/dispatcher.ts +190 -134
  209. package/src/dom/dom.ts +70 -54
  210. package/src/dom/error-info.ts +15 -0
  211. package/src/dom/features/activity/full.ts +166 -0
  212. package/src/dom/features/activity/index.ts +1 -0
  213. package/src/dom/features/activity/stub.ts +14 -0
  214. package/src/dom/features/class/full.ts +72 -21
  215. package/src/dom/features/context/full.ts +66 -4
  216. package/src/dom/features/context/stub.ts +6 -0
  217. package/src/dom/features/forward-ref/full.ts +9 -19
  218. package/src/dom/features/fragment-refs/index.ts +1 -0
  219. package/src/dom/features/fragment-refs/stub.ts +3 -0
  220. package/src/dom/features/hydration/full.ts +84 -82
  221. package/src/dom/features/hydration/stub.ts +1 -1
  222. package/src/dom/features/index.ts +1 -0
  223. package/src/dom/features/memo/full.ts +4 -3
  224. package/src/dom/features/suspense/full.ts +187 -50
  225. package/src/dom/features/view-transition/full.ts +288 -0
  226. package/src/dom/features/view-transition/index.ts +1 -0
  227. package/src/dom/features/view-transition/resources.ts +107 -0
  228. package/src/dom/features/view-transition/stub.ts +7 -0
  229. package/src/dom/features/view-transition/visual.ts +406 -0
  230. package/src/dom/fragment-instance.ts +337 -0
  231. package/src/dom/index.ts +6 -7
  232. package/src/dom/portal.ts +1 -1
  233. package/src/dom/reconcile.ts +691 -244
  234. package/src/dom/resource-hints.ts +115 -0
  235. package/src/dom/resource-store.ts +52 -0
  236. package/src/dom/resources.ts +39 -0
  237. package/src/dom/retained-effects.ts +38 -0
  238. package/src/dom/root-internal.ts +4 -4
  239. package/src/dom/root.ts +12 -14
  240. package/src/react/activity.ts +10 -0
  241. package/src/react/element.ts +6 -2
  242. package/src/react/hooks.ts +12 -3
  243. package/src/react/index.ts +18 -0
  244. package/src/react/shared-internals.ts +3 -3
  245. package/src/react/view-transition.ts +41 -0
  246. package/src/server/bootstrap-script.ts +36 -5
  247. package/src/server/dispatcher.ts +35 -13
  248. package/src/server/escape.ts +15 -12
  249. package/src/server/renderToString.ts +7 -5
  250. package/src/server/resource-hints.ts +165 -0
  251. package/src/server/stream.ts +154 -62
  252. package/src/server/walk.ts +72 -11
  253. package/src/vite/index.ts +30 -13
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/vite/index.ts"],
4
- "sourcesContent": ["import { existsSync, readFileSync, realpathSync } from 'node:fs'\nimport { dirname, resolve as resolvePath } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nexport type RedactPreset = 'nano' | 'full'\n\n/**\n * Opt-in feature set. Each flag toggles whether the feature's real\n * implementation ships (`true`) or is swapped with a stub module that\n * degrades gracefully (`false`). Missing keys fall back to the preset's\n * default. Adding a feature to this interface propagates to consumer\n * configs as autocompleted options.\n */\nexport interface RedactFeatures {\n /**\n * `createPortal`. When `false`, portal elements render in place as a\n * Fragment (the `container` prop is ignored). `renderPortal` and its\n * deps are stripped from the bundle.\n */\n portal?: boolean\n /**\n * `createContext` / `useContext` / `<Provider>` / `<Consumer>`. When\n * `false`, Providers render as Fragments (value never propagates),\n * Consumers invoke their function-children with the context's default\n * value, and `useContext` returns the default. Provider-walk logic and\n * `renderProvider` are stripped.\n */\n context?: boolean\n /**\n * `<Suspense>` boundaries + streaming hydration. When `false`, Suspense\n * elements render as Fragments (children mount inline, `fallback` is\n * ignored). Thrown thenables still schedule a re-render on settle, so\n * eventual consistency works \u2014 just no fallback UI during the pending\n * window. Boundary-handler stack and hydration integration are stripped.\n */\n suspense?: boolean\n /**\n * `React.memo`. When `false`, memoized components still render but without\n * the prop-equality gate \u2014 every parent rerender passes through.\n * `shallowEqual` and the force-rerender bypass are stripped.\n */\n memo?: boolean\n /**\n * `React.forwardRef`. When `false`, forwardRef components still render but\n * the ref prop isn't forwarded to the inner function. React 19+ treats\n * refs as normal props on function components anyway, so most apps can\n * drop this. The dispatcher save/restore machinery is stripped.\n */\n forwardRef?: boolean\n /**\n * `React.lazy`. When `false`, lazy elements still resolve if their payload\n * is already available synchronously (e.g. pre-awaited RSC Flight); async\n * resolution throws a clear error. The hydration-deferred-reveal path and\n * Suspense coordination are stripped.\n */\n lazy?: boolean\n /**\n * Class components (`extends Component`). When `false`, class components\n * still render but only honor the core contract: constructor + `render()`\n * + `setState`. Dropped: `contextType`, `getDerivedStateFromProps`,\n * `shouldComponentUpdate`, `componentDidMount`/`Update`/`WillUnmount`,\n * `getDerivedStateFromError`/`componentDidCatch` (error boundaries).\n */\n classComponents?: boolean\n /**\n * SSR hydration (`hydrateRoot`). When `false`, `hydrateRoot` throws\n * (use `createRoot` for SPAs). The HydrationCursor / DOM adoption /\n * streaming-boundary coordination / event-replay / scroll-guard\n * machinery is stripped \u2014 the biggest single chunk of reducible code.\n */\n hydration?: boolean\n}\n\ninterface ResolvedFeatures {\n portal: boolean\n context: boolean\n suspense: boolean\n memo: boolean\n forwardRef: boolean\n lazy: boolean\n classComponents: boolean\n hydration: boolean\n}\n\nconst PRESET_DEFAULTS: Record<RedactPreset, ResolvedFeatures> = {\n // Opt-in: everything off. Turn individual features on via `features`.\n nano: {\n portal: false, context: false, suspense: false, memo: false,\n forwardRef: false, lazy: false, classComponents: false, hydration: false,\n },\n // Opt-out: everything on (drop-in React parity). Turn features off via `features`.\n full: {\n portal: true, context: true, suspense: true, memo: true,\n forwardRef: true, lazy: true, classComponents: true, hydration: true,\n },\n}\n\nfunction resolveFeatures(\n preset: RedactPreset,\n overrides: RedactFeatures,\n): ResolvedFeatures {\n const p = PRESET_DEFAULTS[preset]\n return {\n portal: overrides.portal ?? p.portal,\n context: overrides.context ?? p.context,\n suspense: overrides.suspense ?? p.suspense,\n memo: overrides.memo ?? p.memo,\n forwardRef: overrides.forwardRef ?? p.forwardRef,\n lazy: overrides.lazy ?? p.lazy,\n classComponents: overrides.classComponents ?? p.classComponents,\n hydration: overrides.hydration ?? p.hydration,\n }\n}\n\nexport interface RedactOptions {\n /** Skip aliasing specific specifiers, e.g. if a consumer wants real React somewhere. */\n skip?: ReadonlyArray<string>\n /**\n * Override package resolution root. Defaults to the Vite config root. Useful\n * for monorepos where the plugin lives in a different workspace than the\n * consumer app.\n */\n resolveFrom?: string\n /**\n * Explicit package roots, bypassing node_modules lookup. Keys are package\n * names (e.g. `@tanstack/redact`), values are absolute paths to the package\n * directory. Handy for cross-workspace testing / bring-your-own-build setups.\n */\n packageRoots?: Record<string, string>\n /**\n * Starting point for feature selection. `'full'` (default) turns every\n * feature on \u2014 drop-in React parity, opt-out individual features via\n * `features`. `'nano'` turns everything off \u2014 opt in to what you need.\n */\n preset?: RedactPreset\n /**\n * Per-feature overrides merged on top of the preset's defaults. Enables\n * fine-grained \"preset minus X\" or \"preset plus Y\" configurations.\n */\n features?: RedactFeatures\n}\n\n// Alias map. ORDER MATTERS \u2014 Vite's alias matcher uses first-match against\n// prefix, so more-specific specifiers MUST come before less-specific ones.\n// Without this, `react-dom/server` would prefix-match `react-dom` first and\n// resolve to `@tanstack/redact/dom/server` (wrong) instead of\n// `@tanstack/redact/server`.\n//\n// `use-sync-external-store` aliases are here because its CJS-only React 17\n// compat shim does `var React = require('react')`. That survives Vite's\n// pre-bundling intact and explodes in Cloudflare Workers (no `require`).\n// Modern React has `useSyncExternalStore` built-in, and `@tanstack/redact`\n// additionally exports `useSyncExternalStoreWithSelector` so this alias\n// is safe everywhere.\nconst ALIASES: Record<string, string> = {\n // ---- most-specific first ----\n 'use-sync-external-store/shim/with-selector': '@tanstack/redact',\n 'use-sync-external-store/shim/with-selector.js': '@tanstack/redact',\n 'use-sync-external-store/with-selector': '@tanstack/redact',\n 'use-sync-external-store/with-selector.js': '@tanstack/redact',\n 'use-sync-external-store/shim': '@tanstack/redact',\n 'use-sync-external-store': '@tanstack/redact',\n\n // React drop-in shim targets. Subpaths first.\n 'react/jsx-runtime': '@tanstack/redact/jsx-runtime',\n 'react/jsx-dev-runtime': '@tanstack/redact/jsx-dev-runtime',\n 'react/compiler-runtime': '@tanstack/redact/compiler-runtime',\n 'react-dom/client': '@tanstack/redact/dom-client',\n 'react-dom/server.edge': '@tanstack/redact/server',\n 'react-dom/static.edge': '@tanstack/redact/server',\n 'react-dom/server': '@tanstack/redact/server',\n 'react-dom/test-utils': '@tanstack/redact/dom-test-utils',\n 'react-dom': '@tanstack/redact/dom',\n react: '@tanstack/redact',\n scheduler: '@tanstack/redact/scheduler',\n\n // Self-aliases so Vite resolves `@tanstack/redact/*` imports to the same\n // canonical file path no matter where they originate (worker bundle vs\n // deps_ssr pre-bundle vs source). Without these, Cloudflare's\n // `noExternal: true` worker config inlines one copy while Vite's\n // optimizeDeps pre-bundles another, ending up with two separate\n // ReactSharedInternals instances and a null dispatcher in user hooks.\n // Subpaths first here too.\n '@tanstack/redact/jsx-runtime': '@tanstack/redact/jsx-runtime',\n '@tanstack/redact/jsx-dev-runtime': '@tanstack/redact/jsx-dev-runtime',\n '@tanstack/redact/compiler-runtime': '@tanstack/redact/compiler-runtime',\n '@tanstack/redact/dom-client': '@tanstack/redact/dom-client',\n '@tanstack/redact/dom-test-utils': '@tanstack/redact/dom-test-utils',\n '@tanstack/redact/server': '@tanstack/redact/server',\n '@tanstack/redact/scheduler': '@tanstack/redact/scheduler',\n '@tanstack/redact/dom': '@tanstack/redact/dom',\n '@tanstack/redact': '@tanstack/redact',\n}\n\nfunction splitSpecifier(specifier: string): { pkg: string; sub: string } {\n if (specifier.startsWith('@')) {\n const slash1 = specifier.indexOf('/')\n const slash2 = specifier.indexOf('/', slash1 + 1)\n if (slash2 < 0) return { pkg: specifier, sub: '' }\n return { pkg: specifier.slice(0, slash2), sub: specifier.slice(slash2 + 1) }\n }\n const slash = specifier.indexOf('/')\n if (slash < 0) return { pkg: specifier, sub: '' }\n return { pkg: specifier.slice(0, slash), sub: specifier.slice(slash + 1) }\n}\n\nfunction findPackageDir(pkg: string, fromDir: string): string | null {\n let dir = fromDir\n while (true) {\n const candidate = resolvePath(dir, 'node_modules', pkg)\n if (existsSync(resolvePath(candidate, 'package.json'))) return candidate\n const parent = dirname(dir)\n if (parent === dir) return null\n dir = parent\n }\n}\n\nfunction resolveExport(packageDir: string, sub: string): string | null {\n const pkgJsonPath = resolvePath(packageDir, 'package.json')\n let pkg: any\n try {\n pkg = JSON.parse(readFileSync(pkgJsonPath, 'utf8'))\n } catch {\n return null\n }\n const key = sub ? './' + sub : '.'\n const exp = pkg.exports?.[key]\n // Prefer published `import` (dist/.js) over `source` \u2014 dist is a single\n // transformed bundle so Vite's dep optimizer doesn't thrash on dozens of\n // individual source files. The package keeps cross-subpath imports\n // external, so there's still only one runtime instance.\n const pick = (v: any): string | null => {\n if (typeof v === 'string') return v\n if (v && typeof v === 'object') {\n return pick(v.import ?? v.module ?? v.source ?? v.default ?? null)\n }\n return null\n }\n const target = pick(exp)\n if (target) return resolvePath(packageDir, target)\n if (!sub) {\n const main = pkg.module ?? pkg.main\n if (typeof main === 'string') return resolvePath(packageDir, main)\n }\n return null\n}\n\n// When installed from npm, `@tanstack/redact` is declared as a `dependency`\n// of consumer apps. Under pnpm's strict mode it ends up nested under the\n// plugin's own `.pnpm/@tanstack+redact@.../node_modules/` rather than\n// hoisted to the consumer's root, so a `findPackageDir` walk starting at\n// the Vite project root won't always find it. Search from the plugin's own\n// directory first (which walks into its nested node_modules), then fall\n// back to the consumer root for hoisted installs.\nconst pluginDir = dirname(fileURLToPath(import.meta.url))\n\nfunction resolveSpecifier(\n specifier: string,\n fromDir: string,\n packageRoots: Record<string, string>,\n): string | null {\n const { pkg, sub } = splitSpecifier(specifier)\n const packageDir =\n packageRoots[pkg] ??\n findPackageDir(pkg, pluginDir) ??\n findPackageDir(pkg, fromDir)\n if (!packageDir) return null\n const target = resolveExport(packageDir, sub)\n if (!target) return null\n // Canonicalize through pnpm symlinks. Under strict pnpm, the package may\n // live nested under `.pnpm/@tanstack+redact@.../node_modules/*`, but each\n // of those is itself a symlink to the flat `.pnpm/@tanstack+redact@.../`\n // entry. Vite's `fetchModule` (used by TanStack Start's server-fn\n // compiler) follows the realpath, so the id seen by the capture-transform\n // differs from the nested id we'd return. That leaves the compiler's\n // moduleCache keyed on the realpath while `getModuleInfo` looks up the\n // nested path \u2192 miss \u2192 \"could not load module info\". Returning the\n // canonical realpath here keeps the two sides in agreement.\n try {\n return realpathSync(target)\n } catch {\n return target\n }\n}\n\ninterface OptimizeDepsWithInclude {\n include?: Array<string>\n}\n\nfunction pruneOptimizeDepsInclude(\n optimizeDeps: OptimizeDepsWithInclude | undefined,\n blocked: ReadonlySet<string>,\n): void {\n if (!optimizeDeps?.include) return\n\n optimizeDeps.include = optimizeDeps.include.filter((id) => {\n const tailSpecifier = id.split('>').pop()?.trim() ?? id\n return !blocked.has(id) && !blocked.has(tailSpecifier)\n })\n}\n\nexport function redact(options: RedactOptions = {}): any {\n const skip = new Set(options.skip ?? [])\n const entries = Object.entries(ALIASES).filter(([k]) => !skip.has(k))\n const excludeList = entries.map(([k]) => k)\n const optimizeDepsBlocked = new Set(excludeList)\n const features = resolveFeatures(options.preset ?? 'full', options.features ?? {})\n\n const resolvedMap: Record<string, string> = {}\n let done = false\n\n function resolveAll(root: string): void {\n if (done) return\n const fromDir = options.resolveFrom ?? root\n const packageRoots = options.packageRoots ?? {}\n for (const [from, to] of entries) {\n const resolved = resolveSpecifier(to, fromDir, packageRoots)\n if (resolved) resolvedMap[from] = resolved\n }\n done = true\n }\n\n return [{\n name: 'redact',\n enforce: 'pre',\n\n config() {\n // Single package \u2014 only one name to dedupe / no-external.\n const noExt = ['@tanstack/redact']\n const aliasMap = Object.fromEntries(entries.filter(([from, to]) => from !== to))\n // Dedupe `@tanstack/redact` so Vite resolves it to a single instance\n // even when multiple packages (e.g. @tanstack/react-router and user\n // code) drag it into different parts of the module graph.\n const dedupe = noExt\n // Scope `resolve.alias` to client + ssr environments ONLY. Do NOT set\n // a top-level alias: it would apply to the `rsc` environment too,\n // where `@vitejs/plugin-rsc`'s vendored `react-server-dom-server`\n // imports `react` and needs the *real* React (with the `.d` field on\n // ReactSharedInternals that our shim deliberately doesn't have).\n // Aliasing `react` \u2192 `@tanstack/redact` in the RSC env crashes Flight\n // serialization. The Cloudflare vite-plugin's rolldown worker-runner\n // also pre-scans bare specifiers via Vite's alias map (not plugin\n // hooks), but it scans within the *ssr* environment specifically \u2014\n // so per-env `environments.ssr.resolve.alias` covers it. The\n // `enforce: 'pre'` resolveId hook below already skips RSC, so the\n // remaining concern is alias placement. Object form is required \u2014\n // array form is silently ignored by rolldown's worker-runner.\n return {\n environments: {\n client: {\n optimizeDeps: { exclude: excludeList },\n resolve: { alias: aliasMap, dedupe },\n },\n ssr: {\n optimizeDeps: { exclude: excludeList },\n resolve: { alias: aliasMap, dedupe, noExternal: noExt },\n },\n },\n ssr: { noExternal: noExt },\n }\n },\n\n configResolved(config: any) {\n resolveAll(config.root)\n // With `packageRoots`, package sources live outside the consumer's Vite\n // project root, so the default server.fs.allow list blocks them. Append\n // to the resolved allow list rather than replacing via `config()`, so we\n // keep Vite's defaults (root + node_modules + client runtime).\n const fsAllow = Object.values(options.packageRoots ?? {})\n if (fsAllow.length && config.server?.fs?.allow) {\n for (const p of fsAllow) {\n if (!config.server.fs.allow.includes(p)) {\n config.server.fs.allow.push(p)\n }\n }\n }\n },\n\n async resolveId(this: any, id: string, importer?: string, opts?: any) {\n // Skip the RSC environment \u2014 it relies on real React internals via\n // @vitejs/plugin-rsc's vendored react-server-dom. Substituting our\n // shim there breaks Flight serialization. Client + SSR envs still swap.\n const envName = this?.environment?.name\n if (envName === 'rsc') return null\n\n // Feature-flag swap: when the reconciler's `features/index` module\n // imports a feature by relative path, redirect to that feature's stub\n // if the flag is off. The stub registers a graceful-degradation\n // matcher (e.g. Portal \u2192 Fragment) so user code keeps working.\n if (importer && /[\\\\/]features[\\\\/]index\\.[jt]sx?$/.test(importer)) {\n const m = id.match(/^\\.\\/([a-z-]+)$/)\n if (m) {\n const name = m[1] as keyof ResolvedFeatures\n if (name in features && !features[name]) {\n const r = await this.resolve(`./${name}/stub`, importer, {\n ...opts,\n skipSelf: true,\n })\n if (r) return r.id\n }\n }\n }\n\n // Hydration swap: hydration isn't self-registering, so it's imported\n // from reconcile.ts, root.ts, and the Suspense/Lazy feature modules.\n // Any specifier ending in `/hydration` that resolves to our feature\n // module gets redirected to the stub when the flag is off.\n if (!features.hydration && importer && /[\\\\/]hydration$/.test(id)) {\n const r = await this.resolve(id, importer, { ...opts, skipSelf: true })\n if (r && /features[\\\\/]hydration[\\\\/]index\\.(ts|js)$/.test(r.id)) {\n return r.id.replace(/index\\.(ts|js)$/, 'stub.$1')\n }\n }\n\n return resolvedMap[id] ?? null\n },\n }, {\n name: 'redact:optimize-deps-guard',\n enforce: 'post',\n\n configResolved(config: any) {\n // `optimizeDeps.exclude` loses when another plugin force-adds the same\n // ids to `include`. That lets Vite pre-bundle real React next to Redact,\n // producing duplicate dispatcher state. Prune after config settles so\n // Redact's client/SSR shims stay canonical.\n pruneOptimizeDepsInclude(config.optimizeDeps, optimizeDepsBlocked)\n pruneOptimizeDepsInclude(config.environments?.client?.optimizeDeps, optimizeDepsBlocked)\n pruneOptimizeDepsInclude(config.environments?.ssr?.optimizeDeps, optimizeDepsBlocked)\n // Leave `environments.rsc` untouched. RSC depends on real React internals.\n },\n }]\n}\n\nexport default redact\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { existsSync, readFileSync, realpathSync } from 'node:fs'\nimport { dirname, resolve as resolvePath } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nexport type RedactPreset = 'nano' | 'full'\n\n/**\n * Opt-in feature set. Each flag toggles whether the feature's real\n * implementation ships (`true`) or is swapped with a stub module that\n * degrades gracefully (`false`). Missing keys fall back to the preset's\n * default. Adding a feature to this interface propagates to consumer\n * configs as autocompleted options.\n */\nexport interface RedactFeatures {\n /** Activity visibility, retained state and disconnected effects. */\n activity?: boolean\n /** DOM instances, events, focus, layout and observers for Fragment refs. */\n fragmentRefs?: boolean\n /** Experimental native ViewTransition animations. Opt-in until snapshot parity is complete. */\n viewTransitions?: boolean\n /**\n * `createPortal`. When `false`, portal elements render in place as a\n * Fragment (the `container` prop is ignored). `renderPortal` and its\n * deps are stripped from the bundle.\n */\n portal?: boolean\n /**\n * `createContext` / `useContext` / `<Provider>` / `<Consumer>`. When\n * `false`, Providers render as Fragments (value never propagates),\n * Consumers invoke their function-children with the context's default\n * value, and `useContext` returns the default. Provider-walk logic and\n * `renderProvider` are stripped.\n */\n context?: boolean\n /**\n * `<Suspense>` boundaries + streaming hydration. When `false`, Suspense\n * elements render as Fragments (children mount inline, `fallback` is\n * ignored). Thrown thenables still schedule a re-render on settle, so\n * eventual consistency works \u2014 just no fallback UI during the pending\n * window. Boundary-handler stack and hydration integration are stripped.\n */\n suspense?: boolean\n /**\n * `React.memo`. When `false`, memoized components still render but without\n * the prop-equality gate \u2014 every parent rerender passes through.\n * `shallowEqual` and the force-rerender bypass are stripped.\n */\n memo?: boolean\n /**\n * `React.forwardRef`. When `false`, forwardRef components still render but\n * the ref prop isn't forwarded to the inner function. React 19+ treats\n * refs as normal props on function components anyway, so most apps can\n * drop this. The dispatcher save/restore machinery is stripped.\n */\n forwardRef?: boolean\n /**\n * `React.lazy`. When `false`, lazy elements still resolve if their payload\n * is already available synchronously (e.g. pre-awaited RSC Flight); async\n * resolution throws a clear error. The hydration-deferred-reveal path and\n * Suspense coordination are stripped.\n */\n lazy?: boolean\n /**\n * Class components (`extends Component`). When `false`, class components\n * still render but only honor the core contract: constructor + `render()`\n * + `setState`. Dropped: `contextType`, `getDerivedStateFromProps`,\n * `shouldComponentUpdate`, `componentDidMount`/`Update`/`WillUnmount`,\n * `getDerivedStateFromError`/`componentDidCatch` (error boundaries).\n */\n classComponents?: boolean\n /**\n * SSR hydration (`hydrateRoot`). When `false`, `hydrateRoot` throws\n * (use `createRoot` for SPAs). The HydrationCursor / DOM adoption /\n * streaming-boundary coordination / event-replay / scroll-guard\n * machinery is stripped \u2014 the biggest single chunk of reducible code.\n */\n hydration?: boolean\n}\n\ninterface ResolvedFeatures {\n activity: boolean\n fragmentRefs: boolean\n viewTransitions: boolean\n portal: boolean\n context: boolean\n suspense: boolean\n memo: boolean\n forwardRef: boolean\n lazy: boolean\n classComponents: boolean\n hydration: boolean\n}\n\nconst PRESET_DEFAULTS: Record<RedactPreset, ResolvedFeatures> = {\n // Opt-in: everything off. Turn individual features on via `features`.\n nano: {\n activity: false, fragmentRefs: false, viewTransitions: false,\n portal: false, context: false, suspense: false, memo: false,\n forwardRef: false, lazy: false, classComponents: false, hydration: false,\n },\n // Opt-out: everything on (drop-in React parity). Turn features off via `features`.\n full: {\n activity: true, fragmentRefs: true, viewTransitions: false,\n portal: true, context: true, suspense: true, memo: true,\n forwardRef: true, lazy: true, classComponents: true, hydration: true,\n },\n}\n\nfunction resolveFeatures(\n preset: RedactPreset,\n overrides: RedactFeatures,\n): ResolvedFeatures {\n const p = PRESET_DEFAULTS[preset]\n return {\n activity: overrides.activity ?? p.activity,\n fragmentRefs: overrides.fragmentRefs ?? p.fragmentRefs,\n viewTransitions: overrides.viewTransitions ?? p.viewTransitions,\n portal: overrides.portal ?? p.portal,\n context: overrides.context ?? p.context,\n suspense: overrides.suspense ?? p.suspense,\n memo: overrides.memo ?? p.memo,\n forwardRef: overrides.forwardRef ?? p.forwardRef,\n lazy: overrides.lazy ?? p.lazy,\n classComponents: overrides.classComponents ?? p.classComponents,\n hydration: overrides.hydration ?? p.hydration,\n }\n}\n\nexport interface RedactOptions {\n /** Skip aliasing specific specifiers, e.g. if a consumer wants real React somewhere. */\n skip?: ReadonlyArray<string>\n /**\n * Override package resolution root. Defaults to the Vite config root. Useful\n * for monorepos where the plugin lives in a different workspace than the\n * consumer app.\n */\n resolveFrom?: string\n /**\n * Explicit package roots, bypassing node_modules lookup. Keys are package\n * names (e.g. `@tanstack/redact`), values are absolute paths to the package\n * directory. Handy for cross-workspace testing / bring-your-own-build setups.\n */\n packageRoots?: Record<string, string>\n /**\n * Starting point for feature selection. `'full'` (default) turns every\n * feature on \u2014 drop-in React parity, opt-out individual features via\n * `features`. `'nano'` turns everything off \u2014 opt in to what you need.\n */\n preset?: RedactPreset\n /**\n * Per-feature overrides merged on top of the preset's defaults. Enables\n * fine-grained \"preset minus X\" or \"preset plus Y\" configurations.\n */\n features?: RedactFeatures\n}\n\n// Alias map. ORDER MATTERS \u2014 Vite's alias matcher uses first-match against\n// prefix, so more-specific specifiers MUST come before less-specific ones.\n// Without this, `react-dom/server` would prefix-match `react-dom` first and\n// resolve to `@tanstack/redact/dom/server` (wrong) instead of\n// `@tanstack/redact/server`.\n//\n// `use-sync-external-store` aliases are here because its CJS-only React 17\n// compat shim does `var React = require('react')`. That survives Vite's\n// pre-bundling intact and explodes in Cloudflare Workers (no `require`).\n// Modern React has `useSyncExternalStore` built-in, and `@tanstack/redact`\n// additionally exports `useSyncExternalStoreWithSelector` so this alias\n// is safe everywhere.\nconst ALIASES: Record<string, string> = {\n // ---- most-specific first ----\n 'use-sync-external-store/shim/with-selector': '@tanstack/redact',\n 'use-sync-external-store/shim/with-selector.js': '@tanstack/redact',\n 'use-sync-external-store/with-selector': '@tanstack/redact',\n 'use-sync-external-store/with-selector.js': '@tanstack/redact',\n 'use-sync-external-store/shim': '@tanstack/redact',\n 'use-sync-external-store': '@tanstack/redact',\n\n // React drop-in shim targets. Subpaths first.\n 'react/jsx-runtime': '@tanstack/redact/jsx-runtime',\n 'react/jsx-dev-runtime': '@tanstack/redact/jsx-dev-runtime',\n 'react/compiler-runtime': '@tanstack/redact/compiler-runtime',\n 'react-dom/client': '@tanstack/redact/dom-client',\n 'react-dom/server.browser': '@tanstack/redact/server',\n 'react-dom/server.bun': '@tanstack/redact/server',\n 'react-dom/server.edge': '@tanstack/redact/server',\n 'react-dom/server.node': '@tanstack/redact/server',\n 'react-dom/static.edge': '@tanstack/redact/server',\n 'react-dom/server': '@tanstack/redact/server',\n 'react-dom/test-utils': '@tanstack/redact/dom-test-utils',\n 'react-dom': '@tanstack/redact/dom',\n react: '@tanstack/redact',\n scheduler: '@tanstack/redact/scheduler',\n\n // Self-aliases so Vite resolves `@tanstack/redact/*` imports to the same\n // canonical file path no matter where they originate (worker bundle vs\n // deps_ssr pre-bundle vs source). Without these, Cloudflare's\n // `noExternal: true` worker config inlines one copy while Vite's\n // optimizeDeps pre-bundles another, ending up with two separate\n // ReactSharedInternals instances and a null dispatcher in user hooks.\n // Subpaths first here too.\n '@tanstack/redact/jsx-runtime': '@tanstack/redact/jsx-runtime',\n '@tanstack/redact/jsx-dev-runtime': '@tanstack/redact/jsx-dev-runtime',\n '@tanstack/redact/compiler-runtime': '@tanstack/redact/compiler-runtime',\n '@tanstack/redact/dom-client': '@tanstack/redact/dom-client',\n '@tanstack/redact/dom-test-utils': '@tanstack/redact/dom-test-utils',\n '@tanstack/redact/server': '@tanstack/redact/server',\n '@tanstack/redact/scheduler': '@tanstack/redact/scheduler',\n '@tanstack/redact/dom': '@tanstack/redact/dom',\n '@tanstack/redact': '@tanstack/redact',\n}\n\nfunction splitSpecifier(specifier: string): { pkg: string; sub: string } {\n if (specifier.startsWith('@')) {\n const slash1 = specifier.indexOf('/')\n const slash2 = specifier.indexOf('/', slash1 + 1)\n if (slash2 < 0) return { pkg: specifier, sub: '' }\n return { pkg: specifier.slice(0, slash2), sub: specifier.slice(slash2 + 1) }\n }\n const slash = specifier.indexOf('/')\n if (slash < 0) return { pkg: specifier, sub: '' }\n return { pkg: specifier.slice(0, slash), sub: specifier.slice(slash + 1) }\n}\n\nfunction findPackageDir(pkg: string, fromDir: string): string | null {\n let dir = fromDir\n while (true) {\n const candidate = resolvePath(dir, 'node_modules', pkg)\n if (existsSync(resolvePath(candidate, 'package.json'))) return candidate\n const parent = dirname(dir)\n if (parent === dir) return null\n dir = parent\n }\n}\n\nfunction resolveExport(packageDir: string, sub: string): string | null {\n const pkgJsonPath = resolvePath(packageDir, 'package.json')\n let pkg: any\n try {\n pkg = JSON.parse(readFileSync(pkgJsonPath, 'utf8'))\n } catch {\n return null\n }\n const key = sub ? './' + sub : '.'\n const exp = pkg.exports?.[key]\n // Prefer published JavaScript over TypeScript sources. Dist preserves one\n // file per module, so subpath imports share state and feature boundaries.\n const pick = (v: any): string | null => {\n if (typeof v === 'string') return v\n if (v && typeof v === 'object') {\n return pick(v.import ?? v.module ?? v.source ?? v.default ?? null)\n }\n return null\n }\n const target = pick(exp)\n if (target) return resolvePath(packageDir, target)\n if (!sub) {\n const main = pkg.module ?? pkg.main\n if (typeof main === 'string') return resolvePath(packageDir, main)\n }\n return null\n}\n\n// When installed from npm, `@tanstack/redact` is declared as a `dependency`\n// of consumer apps. Under pnpm's strict mode it ends up nested under the\n// plugin's own `.pnpm/@tanstack+redact@.../node_modules/` rather than\n// hoisted to the consumer's root, so a `findPackageDir` walk starting at\n// the Vite project root won't always find it. Search from the plugin's own\n// directory first (which walks into its nested node_modules), then fall\n// back to the consumer root for hoisted installs.\nconst pluginDir = dirname(fileURLToPath(import.meta.url))\n\nfunction resolveSpecifier(\n specifier: string,\n fromDir: string,\n packageRoots: Record<string, string>,\n): string | null {\n const { pkg, sub } = splitSpecifier(specifier)\n const packageDir =\n packageRoots[pkg] ??\n findPackageDir(pkg, pluginDir) ??\n findPackageDir(pkg, fromDir)\n if (!packageDir) return null\n const target = resolveExport(packageDir, sub)\n if (!target) return null\n // Canonicalize through pnpm symlinks. Under strict pnpm, the package may\n // live nested under `.pnpm/@tanstack+redact@.../node_modules/*`, but each\n // of those is itself a symlink to the flat `.pnpm/@tanstack+redact@.../`\n // entry. Vite's `fetchModule` (used by TanStack Start's server-fn\n // compiler) follows the realpath, so the id seen by the capture-transform\n // differs from the nested id we'd return. That leaves the compiler's\n // moduleCache keyed on the realpath while `getModuleInfo` looks up the\n // nested path \u2192 miss \u2192 \"could not load module info\". Returning the\n // canonical realpath here keeps the two sides in agreement.\n try {\n return realpathSync(target)\n } catch {\n return target\n }\n}\n\ninterface OptimizeDepsWithInclude {\n include?: Array<string>\n}\n\nfunction pruneOptimizeDepsInclude(\n optimizeDeps: OptimizeDepsWithInclude | undefined,\n blocked: ReadonlySet<string>,\n): void {\n if (!optimizeDeps?.include) return\n\n optimizeDeps.include = optimizeDeps.include.filter((id) => {\n const tailSpecifier = id.split('>').pop()?.trim() ?? id\n return !blocked.has(id) && !blocked.has(tailSpecifier)\n })\n}\n\nexport function redact(options: RedactOptions = {}): any {\n const skip = new Set(options.skip ?? [])\n const entries = Object.entries(ALIASES).filter(([k]) => !skip.has(k))\n const excludeList = entries.map(([k]) => k)\n const optimizeDepsBlocked = new Set(excludeList)\n const features = resolveFeatures(options.preset ?? 'full', options.features ?? {})\n\n const resolvedMap: Record<string, string> = {}\n let done = false\n\n function resolveAll(root: string): void {\n if (done) return\n const fromDir = options.resolveFrom ?? root\n const packageRoots = options.packageRoots ?? {}\n for (const [from, to] of entries) {\n const resolved = resolveSpecifier(to, fromDir, packageRoots)\n if (resolved) resolvedMap[from] = resolved\n }\n done = true\n }\n\n return [{\n name: 'redact',\n enforce: 'pre',\n\n config() {\n // Single package \u2014 only one name to dedupe / no-external.\n const noExt = ['@tanstack/redact']\n const aliasMap = Object.fromEntries(entries.filter(([from, to]) => from !== to))\n // Dedupe `@tanstack/redact` so Vite resolves it to a single instance\n // even when multiple packages (e.g. @tanstack/react-router and user\n // code) drag it into different parts of the module graph.\n const dedupe = noExt\n // Scope `resolve.alias` to client + ssr environments ONLY. Do NOT set\n // a top-level alias: it would apply to the `rsc` environment too,\n // where `@vitejs/plugin-rsc`'s vendored `react-server-dom-server`\n // imports `react` and needs the *real* React (with the `.d` field on\n // ReactSharedInternals that our shim deliberately doesn't have).\n // Aliasing `react` \u2192 `@tanstack/redact` in the RSC env crashes Flight\n // serialization. The Cloudflare vite-plugin's rolldown worker-runner\n // also pre-scans bare specifiers via Vite's alias map (not plugin\n // hooks), but it scans within the *ssr* environment specifically \u2014\n // so per-env `environments.ssr.resolve.alias` covers it. The\n // `enforce: 'pre'` resolveId hook below already skips RSC, so the\n // remaining concern is alias placement. Object form is required \u2014\n // array form is silently ignored by rolldown's worker-runner.\n return {\n environments: {\n client: {\n optimizeDeps: { exclude: excludeList },\n resolve: { alias: aliasMap, dedupe },\n },\n ssr: {\n optimizeDeps: { exclude: excludeList },\n resolve: { alias: aliasMap, dedupe, noExternal: noExt },\n },\n },\n ssr: { noExternal: noExt },\n }\n },\n\n configResolved(config: any) {\n resolveAll(config.root)\n // With `packageRoots`, package sources live outside the consumer's Vite\n // project root, so the default server.fs.allow list blocks them. Append\n // to the resolved allow list rather than replacing via `config()`, so we\n // keep Vite's defaults (root + node_modules + client runtime).\n const fsAllow = Object.values(options.packageRoots ?? {})\n if (fsAllow.length && config.server?.fs?.allow) {\n for (const p of fsAllow) {\n if (!config.server.fs.allow.includes(p)) {\n config.server.fs.allow.push(p)\n }\n }\n }\n },\n\n async resolveId(this: any, id: string, importer?: string, opts?: any) {\n // Skip the RSC environment \u2014 it relies on real React internals via\n // @vitejs/plugin-rsc's vendored react-server-dom. Substituting our\n // shim there breaks Flight serialization. Client + SSR envs still swap.\n const envName = this?.environment?.name\n if (envName === 'rsc') return null\n\n // Feature-flag swap: when the reconciler's `features/index` module\n // imports a feature by relative path, redirect to that feature's stub\n // if the flag is off. The stub registers a graceful-degradation\n // matcher (e.g. Portal \u2192 Fragment) so user code keeps working.\n if (importer && /[\\\\/]features[\\\\/]index\\.[jt]sx?$/.test(importer)) {\n const m = id.match(/^\\.\\/([a-z-]+)(\\/index\\.js)?$/)\n if (m) {\n const dir = m[1]!\n const name = (dir === 'forward-ref' ? 'forwardRef' : dir === 'fragment-refs' ? 'fragmentRefs' : dir === 'view-transition' ? 'viewTransitions' : dir === 'class' ? 'classComponents' : dir) as keyof ResolvedFeatures\n if (name in features && !features[name]) {\n const r = await this.resolve(`./${dir}/stub${m[2] ? '.js' : ''}`, importer, {\n ...opts,\n skipSelf: true,\n })\n if (r) return r.id\n }\n }\n }\n\n // Peer imports must use the same feature selection as the registration\n // entrypoint, or an enabled feature can bring a disabled one back in.\n const peer = id.match(/[\\\\/](context|hydration|fragment-refs|view-transition)(?:[\\\\/]index\\.js)?$/)\n const peerKey = peer?.[1] === 'fragment-refs' ? 'fragmentRefs' : peer?.[1] === 'view-transition' ? 'viewTransitions' : peer?.[1] as 'context' | 'hydration' | undefined\n if (importer && peer && peerKey && !features[peerKey]) {\n const r = await this.resolve(id, importer, { ...opts, skipSelf: true })\n const resolvedFeature = r?.id.match(/features[\\\\/](context|hydration|fragment-refs|view-transition)[\\\\/]index\\.(ts|js)$/)\n if (resolvedFeature?.[1] === peer[1]) {\n return r.id.replace(/index\\.(ts|js)$/, 'stub.$1')\n }\n }\n\n return resolvedMap[id] ?? null\n },\n }, {\n name: 'redact:optimize-deps-guard',\n enforce: 'post',\n\n configResolved(config: any) {\n // `optimizeDeps.exclude` loses when another plugin force-adds the same\n // ids to `include`. That lets Vite pre-bundle real React next to Redact,\n // producing duplicate dispatcher state. Prune after config settles so\n // Redact's client/SSR shims stay canonical.\n pruneOptimizeDepsInclude(config.optimizeDeps, optimizeDepsBlocked)\n pruneOptimizeDepsInclude(config.environments?.client?.optimizeDeps, optimizeDepsBlocked)\n pruneOptimizeDepsInclude(config.environments?.ssr?.optimizeDeps, optimizeDepsBlocked)\n // Leave `environments.rsc` untouched. RSC depends on real React internals.\n },\n }]\n}\n\nexport default redact\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/redact",
3
- "version": "0.0.20",
3
+ "version": "0.1.0",
4
4
  "description": "React, redacted. A minimal React-API-compatible drop-in replacement.",
5
5
  "type": "module",
6
6
  "main": "./dist/react/index.js",
@@ -14,6 +14,7 @@ export function attributeName(name: string, isSvg = false): string {
14
14
  if (name === 'acceptCharset') return 'accept-charset'
15
15
  if (name === 'crossOrigin') return 'crossorigin'
16
16
  if (name === 'noModule') return 'nomodule'
17
+ if (name === 'maskType') return 'mask-type'
17
18
  if (name === 'viewBox') return 'viewBox'
18
19
  return name.startsWith('aria-') || name.startsWith('data-')
19
20
  ? name
@@ -0,0 +1,33 @@
1
+ export const REACT_RECOVERABLE_TYPE = Symbol.for('react.recoverable')
2
+
3
+ export interface BrowserToken {
4
+ readonly $$typeof: typeof REACT_RECOVERABLE_TYPE
5
+ readonly _reason: string | (() => unknown) | undefined
6
+ }
7
+
8
+ export function browser(reason?: string | (() => unknown)): BrowserToken {
9
+ return { $$typeof: REACT_RECOVERABLE_TYPE, _reason: reason }
10
+ }
11
+
12
+ export function isBrowserToken(value: any): value is BrowserToken {
13
+ return value?.$$typeof === REACT_RECOVERABLE_TYPE
14
+ }
15
+
16
+ export function browserError(token: BrowserToken): Error {
17
+ let cause: unknown = token._reason
18
+ if (typeof cause === 'function') {
19
+ try {
20
+ cause = cause()
21
+ } catch {
22
+ cause = 'The reason for browser-only rendering could not be determined because its initializer threw.'
23
+ }
24
+ }
25
+ const error = new Error('Browser-only rendering was requested by `browser()`.',
26
+ token._reason === undefined ? undefined : { cause })
27
+ Object.defineProperty(error, REACT_RECOVERABLE_TYPE, { value: true })
28
+ return error
29
+ }
30
+
31
+ export function isBrowserError(error: any): error is Error {
32
+ return error?.[REACT_RECOVERABLE_TYPE] === true
33
+ }
@@ -14,6 +14,8 @@ export const enum FiberTag {
14
14
  Lazy = 10,
15
15
  Suspense = 11,
16
16
  Root = 12,
17
+ Activity = 13,
18
+ Resource = 14,
17
19
  }
18
20
 
19
21
  export interface Hook {
@@ -21,12 +23,13 @@ export interface Hook {
21
23
  q: any
22
24
  d: any
23
25
  c: any
24
- n: Hook | null
25
26
  }
26
27
 
27
28
  export interface Effect {
28
- t: 0 | 1
29
+ t: 0 | 1 | 2
29
30
  c: () => any
31
+ d?: () => void
32
+ s?: boolean // Store subscriptions run in layout but stay connected in Suspense.
30
33
  }
31
34
 
32
35
  export interface Fiber {
@@ -42,24 +45,39 @@ export interface Fiber {
42
45
  parent: Fiber | null
43
46
  child: Fiber | null
44
47
  sibling: Fiber | null
45
- hooks: Hook | null
48
+ hooks: Hook[] | null
46
49
  cu: Array<() => void> | null
47
50
  dy: boolean
48
51
  um: boolean
52
+ pd?: boolean
53
+ su?: Fiber | null // Retained Suspense primary update target.
54
+ ld?: boolean // Layout effects and refs are disconnected, not passive effects.
49
55
  root: FiberRoot | null
56
+ depth?: number
57
+ cx?: Map<any, any> | null
58
+ cr?: Ref<any> | null
59
+ rc?: (() => void) | null
50
60
  }
51
61
 
62
+ export type RecoverableErrorHandler = (error: unknown, info: { componentStack: string | null; errorBoundary?: unknown }) => void
63
+
52
64
  export interface FiberRoot {
53
65
  c: Element | DocumentFragment
54
66
  r: Fiber
55
67
  p: Set<Fiber>
56
68
  s: boolean
57
- re?: ((err: unknown) => void) | undefined
58
- ce?: ((err: unknown) => void) | undefined
59
- ue?: ((err: unknown) => void) | undefined
69
+ u?: (() => void) | undefined
70
+ er?: Array<{ error: unknown; stack: string }> | undefined
71
+ eb?: boolean
72
+ sp?: boolean
73
+ re?: RecoverableErrorHandler | undefined
74
+ ce?: RecoverableErrorHandler | undefined
75
+ ue?: RecoverableErrorHandler | undefined
60
76
  i: string | undefined
61
77
  ic: number
62
78
  h: boolean
79
+ a?: boolean
80
+ fr?: boolean
63
81
  }
64
82
 
65
83
  export function createFiber(tag: FiberTag, type: any, key: string | null): Fiber {
@@ -0,0 +1,36 @@
1
+ export type ResourceHintKind =
2
+ | 'dns-prefetch'
3
+ | 'preconnect'
4
+ | 'preload'
5
+ | 'modulepreload'
6
+ | 'stylesheet'
7
+ | 'script'
8
+ | 'module-script'
9
+
10
+ // Only supported string options reach the dispatcher, using the public camelCase
11
+ // names. Fonts have crossOrigin: ''. Stylesheet precedence defaults to 'default'.
12
+ // Module preloads omit as for the implicit script destination. href is non-empty.
13
+ // A server renderer returns true to consume a hint in its current request, even
14
+ // when deduplication means no new output. Returning false falls through to the DOM.
15
+ export type ResourceHintOptions = Record<string, string>
16
+
17
+ export const resourceHintDispatcher: {
18
+ emit?: (kind: ResourceHintKind, href: string, options: ResourceHintOptions) => boolean
19
+ } = {}
20
+
21
+ // The renderer excludes SVG before calling this. A ref does not opt a resource
22
+ // out of sharing, but event ownership, disabled sheets and itemProp do.
23
+ export function resourceKind(type: string, props: any): 'style' | 'stylesheet' | 'script' | undefined {
24
+ if (props.itemProp != null) return
25
+ if (type === 'style') {
26
+ if (typeof props.precedence === 'string' && typeof props.href === 'string' && props.href) return 'style'
27
+ } else if (type === 'link') {
28
+ if (props.rel === 'stylesheet' && typeof props.href === 'string' && props.href && typeof props.precedence === 'string' && props.disabled == null && !props.onLoad && !props.onError) return 'stylesheet'
29
+ } else if (type === 'script' && props.async && typeof props.async !== 'function' && typeof props.async !== 'symbol' && typeof props.src === 'string' && props.src && !props.onLoad && !props.onError) return 'script'
30
+ }
31
+
32
+ export function resourceURL(value: string): string {
33
+ return /^[\u0000-\u0020]*j[\r\n\t]*a[\r\n\t]*v[\r\n\t]*a[\r\n\t]*s[\r\n\t]*c[\r\n\t]*r[\r\n\t]*i[\r\n\t]*p[\r\n\t]*t[\r\n\t]*:/i.test(value)
34
+ ? "javascript:throw new Error('React has blocked a javascript: URL as a security precaution.')"
35
+ : value
36
+ }
package/src/dom/_all.ts CHANGED
@@ -18,13 +18,7 @@ export type { Root, RootOptions } from './root'
18
18
  export { createPortal } from './portal'
19
19
  export { act } from './test-utils'
20
20
 
21
- // Resource hints stubs
22
- export function preconnect(_href: string, _opts?: any): void {}
23
- export function prefetchDNS(_href: string): void {}
24
- export function preload(_href: string, _opts?: any): void {}
25
- export function preinit(_href: string, _opts?: any): void {}
26
- export function preloadModule(_href: string, _opts?: any): void {}
27
- export function preinitModule(_href: string, _opts?: any): void {}
21
+ export { preconnect, prefetchDNS, preload, preinit, preloadModule, preinitModule } from './resource-hints'
28
22
 
29
23
  export const version = '19.2.3'
30
24
 
@@ -0,0 +1,186 @@
1
+ import { FiberTag, type Fiber, type Hook } from '../core'
2
+ import { setProp } from './dom'
3
+
4
+ export interface CommitPlan {
5
+ q: any[][] // Before-mutation, mutation, effect, rollback and failure queues.
6
+ c: number[][] // Queue lengths saved at each rollback checkpoint.
7
+ b: number // Next before-mutation callback, including reentrant commits.
8
+ m: boolean // Mutation phase has started, preventing duplicate commits.
9
+ }
10
+
11
+ export let currentCommit: CommitPlan | null = null
12
+ let activeCommit: CommitPlan | null = null
13
+ let reusableCommit: CommitPlan | undefined
14
+ let checkpointHook: (() => void) | undefined
15
+
16
+ function createCommit(): CommitPlan {
17
+ return { q: [[], [], [], [], []], c: [], b: 0, m: false }
18
+ }
19
+
20
+ export function prepareCommit(render: () => void, plan = createCommit()): CommitPlan {
21
+ const previous = currentCommit
22
+ currentCommit = plan
23
+ try { render() } catch (error) {
24
+ currentCommit = null
25
+ const failed = plan.q[4]!
26
+ for (let i = 0; i < failed.length; i++) {
27
+ const work = failed[i]
28
+ if (typeof work === 'function') work()
29
+ else {
30
+ const children = failed[++i] as Fiber[] | undefined
31
+ work.child = children?.[0] ?? null
32
+ if (children) for (let j = 0; j < children.length; j++) children[j]!.sibling = children[j + 1] ?? null
33
+ }
34
+ }
35
+ throw error
36
+ } finally { currentCommit = previous }
37
+ return plan
38
+ }
39
+
40
+ export function queueMutation(work: () => void): void {
41
+ if (!currentCommit) { work(); return }
42
+ currentCommit.q[1]!.push(work)
43
+ }
44
+
45
+ export function queueText(node: Text, value: string): void {
46
+ if (currentCommit) currentCommit.q[1]!.push(value, node)
47
+ else node.data = value
48
+ }
49
+
50
+ export function queueProp(node: Element, key: string, value: any, previous: any, svg: boolean): void {
51
+ if (currentCommit) currentCommit.q[1]!.push(node, key, value, previous, svg)
52
+ else setProp(node, key, value, previous, svg)
53
+ }
54
+
55
+ export function queueBeforeMutation(work: () => void): void {
56
+ if (currentCommit) currentCommit.q[0]!.push(work)
57
+ else work()
58
+ }
59
+
60
+ export function queueCommitEffects(work: () => void): void {
61
+ const plan = currentCommit || activeCommit
62
+ if (plan) plan.q[2]!.push(work)
63
+ else work()
64
+ }
65
+
66
+ export function onCommitRollback(work: () => void): void {
67
+ currentCommit?.q[3]!.push(work)
68
+ }
69
+
70
+ export function onCommitFailure(work: () => void): void {
71
+ if (currentCommit) currentCommit.q[4]!.push(work)
72
+ else work()
73
+ }
74
+
75
+ // Structural reconciliation already builds the previous child list. Keep
76
+ // that list for a failed preparation without allocating per-fiber closures.
77
+ export function rememberChildList(parent: Fiber, children?: Fiber[]): void {
78
+ currentCommit?.q[4]!.push(parent, children)
79
+ }
80
+
81
+ export function setCommitCheckpointHook(hook: () => void): void {
82
+ checkpointHook = hook
83
+ }
84
+
85
+ export function checkpointCommit(fiber?: Fiber): number {
86
+ if (!currentCommit) return -1
87
+ const checkpoint = currentCommit.c.length
88
+ currentCommit.c.push(currentCommit.q.map(queue => queue.length))
89
+ if (fiber) rememberSubtree(fiber)
90
+ checkpointHook?.()
91
+ return checkpoint
92
+ }
93
+
94
+ function rememberSubtree(fiber: Fiber): void {
95
+ const saved = { ...fiber }
96
+ // Memo and lazy preserve their wrapper tag around the same class instance.
97
+ const instance = fiber.sn?._fiber === fiber ? fiber.sn : null
98
+ // Hook has four fields. One flat snapshot preserves slot and dispatch
99
+ // identity without a tuple and object clone for every hook.
100
+ const hooks: any[] | null = fiber.hooks && []
101
+ if (hooks) for (const hook of fiber.hooks!) {
102
+ const queue = hook.q
103
+ hooks.push(hook, hook.s, queue, hook.d, hook.c, queue && typeof queue === 'object' ? { ...queue } : null)
104
+ }
105
+ const memoized = fiber.ms && (instance || fiber.tag === FiberTag.Suspense || fiber.tag === FiberTag.Fragment)
106
+ ? { ...fiber.ms } : null
107
+ if (fiber.cx) saved.cx = new Map(fiber.cx)
108
+ if (fiber.cu) saved.cu = fiber.cu.slice()
109
+ const props = instance?.props, state = instance?.state, context = instance?.context
110
+ onCommitRollback(() => {
111
+ Object.assign(fiber, saved)
112
+ if (memoized) {
113
+ for (const key in fiber.ms) if (!(key in memoized)) delete fiber.ms[key]
114
+ Object.assign(fiber.ms, memoized)
115
+ }
116
+ if (hooks) {
117
+ fiber.hooks!.length = hooks.length / 6
118
+ for (let index = 0; index < hooks.length; index += 6) {
119
+ const hook: Hook = fiber.hooks![index / 6] = hooks[index]
120
+ hook.s = hooks[index + 1]
121
+ hook.q = hooks[index + 2]
122
+ hook.d = hooks[index + 3]
123
+ hook.c = hooks[index + 4]
124
+ const queue = hooks[index + 5]
125
+ if (queue) Object.assign(hook.q, queue)
126
+ }
127
+ }
128
+ if (instance) { instance.props = props; instance.state = state; instance.context = context }
129
+ })
130
+ for (let child = fiber.child; child; child = child.sibling) rememberSubtree(child)
131
+ if (fiber.tag === FiberTag.Suspense && fiber.ms?.f) rememberSubtree(fiber.ms.f)
132
+ }
133
+
134
+ export function rewindCommit(checkpoint: number): void {
135
+ if (!currentCommit || checkpoint < 0) return
136
+ const lengths = currentCommit.c[checkpoint]!
137
+ const undo = currentCommit.q[3]!
138
+ for (let index = undo.length - 1; index >= lengths[3]!; index--) undo[index]!()
139
+ currentCommit.q.forEach((queue, index) => { queue.length = lengths[index]! })
140
+ currentCommit.c.length = checkpoint
141
+ }
142
+
143
+ export function commitBeforeMutation(plan: CommitPlan): void {
144
+ const queue = plan.q[0]!
145
+ while (plan.b < queue.length) queue[plan.b++]!()
146
+ }
147
+
148
+ export function commitMutation(plan: CommitPlan): void {
149
+ if (plan.m) return
150
+ commitBeforeMutation(plan)
151
+ if (plan.m) return
152
+ plan.m = true
153
+ const previous = activeCommit
154
+ activeCommit = plan
155
+ try {
156
+ const mutations = plan.q[1]!
157
+ for (let index = 0; index < mutations.length; index++) {
158
+ const work = mutations[index]
159
+ if (typeof work === 'function') work()
160
+ else if (typeof work === 'string') mutations[++index].data = work
161
+ else setProp(work, mutations[++index], mutations[++index], mutations[++index], mutations[++index])
162
+ }
163
+ for (const work of plan.q[2]!) work()
164
+ } finally {
165
+ activeCommit = previous
166
+ for (const queue of plan.q) queue.length = 0
167
+ plan.c.length = 0
168
+ }
169
+ }
170
+
171
+ export function commitSynchronously(render: () => void): void {
172
+ if (currentCommit) { render(); return }
173
+ const plan = reusableCommit || createCommit()
174
+ reusableCommit = undefined
175
+ plan.b = 0
176
+ plan.m = false
177
+ try { commitMutation(prepareCommit(render, plan)) }
178
+ finally {
179
+ // Failed preparation must not leave work for a later synchronous root.
180
+ if (!plan.m) {
181
+ for (const queue of plan.q) queue.length = 0
182
+ plan.c.length = 0
183
+ }
184
+ reusableCommit = plan
185
+ }
186
+ }