rnwind 0.0.4 → 0.0.6

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 (127) hide show
  1. package/lib/cjs/core/normalize-classname.cjs +25 -0
  2. package/lib/cjs/core/normalize-classname.cjs.map +1 -0
  3. package/lib/cjs/core/normalize-classname.d.ts +10 -0
  4. package/lib/cjs/core/style-builder/build-style.cjs +258 -58
  5. package/lib/cjs/core/style-builder/build-style.cjs.map +1 -1
  6. package/lib/cjs/core/style-builder/build-style.d.ts +6 -1
  7. package/lib/cjs/core/style-builder/union-builder.cjs +37 -3
  8. package/lib/cjs/core/style-builder/union-builder.cjs.map +1 -1
  9. package/lib/cjs/core/style-builder/union-builder.d.ts +21 -1
  10. package/lib/cjs/metro/dts.cjs +7 -16
  11. package/lib/cjs/metro/dts.cjs.map +1 -1
  12. package/lib/cjs/metro/dts.d.ts +2 -4
  13. package/lib/cjs/metro/state.cjs +30 -78
  14. package/lib/cjs/metro/state.cjs.map +1 -1
  15. package/lib/cjs/metro/state.d.ts +8 -25
  16. package/lib/cjs/metro/transformer.cjs +193 -34
  17. package/lib/cjs/metro/transformer.cjs.map +1 -1
  18. package/lib/cjs/metro/with-config.cjs +2 -2
  19. package/lib/cjs/metro/with-config.cjs.map +1 -1
  20. package/lib/cjs/metro/with-config.d.ts +11 -26
  21. package/lib/cjs/metro/wrap-imports.cjs +273 -0
  22. package/lib/cjs/metro/wrap-imports.cjs.map +1 -0
  23. package/lib/cjs/metro/wrap-imports.d.ts +26 -0
  24. package/lib/cjs/runtime/components/rnwind-provider.cjs +0 -17
  25. package/lib/cjs/runtime/components/rnwind-provider.cjs.map +1 -1
  26. package/lib/cjs/runtime/components/rnwind-provider.d.ts +0 -14
  27. package/lib/cjs/runtime/hooks/use-css.cjs +16 -10
  28. package/lib/cjs/runtime/hooks/use-css.cjs.map +1 -1
  29. package/lib/cjs/runtime/hooks/use-css.d.ts +15 -9
  30. package/lib/cjs/runtime/index.cjs +11 -13
  31. package/lib/cjs/runtime/index.cjs.map +1 -1
  32. package/lib/cjs/runtime/index.d.ts +4 -9
  33. package/lib/cjs/runtime/lookup-css.cjs +10 -0
  34. package/lib/cjs/runtime/lookup-css.cjs.map +1 -1
  35. package/lib/cjs/runtime/lookup-css.d.ts +7 -0
  36. package/lib/cjs/runtime/resolve.cjs +400 -0
  37. package/lib/cjs/runtime/resolve.cjs.map +1 -0
  38. package/lib/cjs/runtime/resolve.d.ts +66 -0
  39. package/lib/cjs/runtime/wrap.cjs +254 -0
  40. package/lib/cjs/runtime/wrap.cjs.map +1 -0
  41. package/lib/cjs/runtime/wrap.d.ts +37 -0
  42. package/lib/cjs/testing/index.cjs +81 -50
  43. package/lib/cjs/testing/index.cjs.map +1 -1
  44. package/lib/esm/core/normalize-classname.d.ts +10 -0
  45. package/lib/esm/core/normalize-classname.mjs +23 -0
  46. package/lib/esm/core/normalize-classname.mjs.map +1 -0
  47. package/lib/esm/core/style-builder/build-style.d.ts +6 -1
  48. package/lib/esm/core/style-builder/build-style.mjs +258 -58
  49. package/lib/esm/core/style-builder/build-style.mjs.map +1 -1
  50. package/lib/esm/core/style-builder/union-builder.d.ts +21 -1
  51. package/lib/esm/core/style-builder/union-builder.mjs +37 -3
  52. package/lib/esm/core/style-builder/union-builder.mjs.map +1 -1
  53. package/lib/esm/metro/dts.d.ts +2 -4
  54. package/lib/esm/metro/dts.mjs +7 -16
  55. package/lib/esm/metro/dts.mjs.map +1 -1
  56. package/lib/esm/metro/state.d.ts +8 -25
  57. package/lib/esm/metro/state.mjs +30 -76
  58. package/lib/esm/metro/state.mjs.map +1 -1
  59. package/lib/esm/metro/transformer.mjs +194 -35
  60. package/lib/esm/metro/transformer.mjs.map +1 -1
  61. package/lib/esm/metro/with-config.d.ts +11 -26
  62. package/lib/esm/metro/with-config.mjs +2 -2
  63. package/lib/esm/metro/with-config.mjs.map +1 -1
  64. package/lib/esm/metro/wrap-imports.d.ts +26 -0
  65. package/lib/esm/metro/wrap-imports.mjs +250 -0
  66. package/lib/esm/metro/wrap-imports.mjs.map +1 -0
  67. package/lib/esm/runtime/components/rnwind-provider.d.ts +0 -14
  68. package/lib/esm/runtime/components/rnwind-provider.mjs +1 -17
  69. package/lib/esm/runtime/components/rnwind-provider.mjs.map +1 -1
  70. package/lib/esm/runtime/hooks/use-css.d.ts +15 -9
  71. package/lib/esm/runtime/hooks/use-css.mjs +16 -10
  72. package/lib/esm/runtime/hooks/use-css.mjs.map +1 -1
  73. package/lib/esm/runtime/index.d.ts +4 -9
  74. package/lib/esm/runtime/index.mjs +4 -4
  75. package/lib/esm/runtime/index.mjs.map +1 -1
  76. package/lib/esm/runtime/lookup-css.d.ts +7 -0
  77. package/lib/esm/runtime/lookup-css.mjs +10 -1
  78. package/lib/esm/runtime/lookup-css.mjs.map +1 -1
  79. package/lib/esm/runtime/resolve.d.ts +66 -0
  80. package/lib/esm/runtime/resolve.mjs +393 -0
  81. package/lib/esm/runtime/resolve.mjs.map +1 -0
  82. package/lib/esm/runtime/wrap.d.ts +37 -0
  83. package/lib/esm/runtime/wrap.mjs +251 -0
  84. package/lib/esm/runtime/wrap.mjs.map +1 -0
  85. package/lib/esm/testing/index.mjs +84 -53
  86. package/lib/esm/testing/index.mjs.map +1 -1
  87. package/package.json +2 -1
  88. package/src/core/normalize-classname.ts +19 -0
  89. package/src/core/style-builder/build-style.ts +286 -55
  90. package/src/core/style-builder/union-builder.ts +36 -3
  91. package/src/metro/dts.ts +7 -19
  92. package/src/metro/state.ts +29 -74
  93. package/src/metro/transformer.ts +190 -34
  94. package/src/metro/with-config.ts +13 -28
  95. package/src/metro/wrap-imports.ts +260 -0
  96. package/src/runtime/components/rnwind-provider.tsx +0 -17
  97. package/src/runtime/hooks/use-css.ts +17 -11
  98. package/src/runtime/index.ts +3 -26
  99. package/src/runtime/lookup-css.ts +10 -0
  100. package/src/runtime/resolve.ts +438 -0
  101. package/src/runtime/wrap.tsx +267 -0
  102. package/src/testing/index.ts +106 -56
  103. package/lib/cjs/core/parser/text-truncate.cjs +0 -78
  104. package/lib/cjs/core/parser/text-truncate.cjs.map +0 -1
  105. package/lib/cjs/metro/transform-ast.cjs +0 -1472
  106. package/lib/cjs/metro/transform-ast.cjs.map +0 -1
  107. package/lib/cjs/metro/transform-ast.d.ts +0 -88
  108. package/lib/cjs/runtime/haptics.cjs +0 -113
  109. package/lib/cjs/runtime/haptics.cjs.map +0 -1
  110. package/lib/cjs/runtime/haptics.d.ts +0 -48
  111. package/lib/cjs/runtime/interactive-box.cjs +0 -35
  112. package/lib/cjs/runtime/interactive-box.cjs.map +0 -1
  113. package/lib/cjs/runtime/interactive-box.d.ts +0 -40
  114. package/lib/esm/core/parser/text-truncate.mjs +0 -75
  115. package/lib/esm/core/parser/text-truncate.mjs.map +0 -1
  116. package/lib/esm/metro/transform-ast.d.ts +0 -88
  117. package/lib/esm/metro/transform-ast.mjs +0 -1451
  118. package/lib/esm/metro/transform-ast.mjs.map +0 -1
  119. package/lib/esm/runtime/haptics.d.ts +0 -48
  120. package/lib/esm/runtime/haptics.mjs +0 -110
  121. package/lib/esm/runtime/haptics.mjs.map +0 -1
  122. package/lib/esm/runtime/interactive-box.d.ts +0 -40
  123. package/lib/esm/runtime/interactive-box.mjs +0 -33
  124. package/lib/esm/runtime/interactive-box.mjs.map +0 -1
  125. package/src/metro/transform-ast.ts +0 -1729
  126. package/src/runtime/haptics.ts +0 -120
  127. package/src/runtime/interactive-box.tsx +0 -57
@@ -1 +1 @@
1
- {"version":3,"file":"state.cjs","sources":["../../../../src/metro/state.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs'\nimport path from 'node:path'\nimport { createHash } from 'node:crypto'\nimport { UnionBuilder } from '../core/style-builder'\nimport { TailwindParser, type SourceEntry } from '../core/parser'\nimport { resolveThemeCss } from './css-imports'\n\n/**\n * Default oxide Scanner globs — walk every JS/TS source under the\n * project root AND every monorepo watch folder, excluding\n * `node_modules` and rnwind's own cache dir so we don't rescan\n * generated scheme files.\n *\n * Monorepo layouts (Yarn workspaces, pnpm workspaces, Nx) surface\n * sibling package roots as `metroConfig.watchFolders`. Every folder\n * Metro watches must also be scanned so atoms declared in shared UI\n * packages make it into the union — without this, only the app's\n * own files would be scanned and every UI-package atom would resolve\n * to `undefined` at runtime.\n * @param projectRoot Absolute project root.\n * @param cacheDir Absolute rnwind cache dir (to exclude).\n * @param watchFolders Extra monorepo roots Metro is watching.\n * @returns Scanner sources suitable for `parser.parseProject()`.\n */\nfunction defaultSources(projectRoot: string, cacheDir: string, watchFolders: readonly string[]): readonly SourceEntry[] {\n const cacheBaseName = path.basename(cacheDir)\n const roots = new Set<string>([projectRoot, ...watchFolders])\n const sources: SourceEntry[] = []\n for (const root of roots) {\n sources.push({ base: root, pattern: '**/*.{ts,tsx,js,jsx}', negated: false }, { base: root, pattern: '**/node_modules/**', negated: true }, { base: root, pattern: `**/${cacheBaseName}/**`, negated: true })\n }\n return sources\n}\n\n/**\n * Read monorepo watch-folder paths out of the worker environment.\n * Empty array when the host isn't a monorepo.\n * @returns Absolute paths Metro also watches (sibling packages).\n */\nfunction readWatchFolders(): readonly string[] {\n const raw = process.env[WATCH_FOLDERS_ENV]\n if (!raw || raw.length === 0) return []\n return raw.split('\\0').filter((entry) => entry.length > 0)\n}\n\n/** Env var Metro workers read to locate the theme CSS on disk. */\nconst CSS_ENTRY_ENV = 'RNWIND_CSS_ENTRY_FILE'\n/** Env var Metro workers read to locate the cache directory (`.rnwind`). */\nconst CACHE_DIR_ENV = 'RNWIND_CACHE_DIR'\n/** Env var carrying `watchFolders` from Metro config (NUL-separated). */\nconst WATCH_FOLDERS_ENV = 'RNWIND_WATCH_FOLDERS'\n/** Env var carrying extra className prefixes the Metro config supplied. */\nconst CLASSNAME_PREFIXES_ENV = 'RNWIND_CLASSNAME_PREFIXES'\n/** Env var carrying extra import sources whose JSX exports get className→style rewrites. Comma-separated. */\nconst HOST_SOURCES_ENV = 'RNWIND_HOST_SOURCES'\n/** Env var carrying extra JSX tag names (verbatim, may contain `.`) treated as hosts. Comma-separated. */\nconst HOST_COMPONENTS_ENV = 'RNWIND_HOST_COMPONENTS'\n\n/** Memoised library fingerprint — read once per worker process. */\nlet libraryFingerprint: string | undefined\n\n/** Live state shared across one Metro transform worker. */\nlet cached: RnwindState | null = null\n\n/**\n * Cheap content-hash readout. SHA-256 prefix of the FULLY-RESOLVED theme\n * CSS — `@import`s flattened — so an edit to a theme file the entry only\n * re-exports (`@import \"@acme/ui/theme.css\"`) still rotates the hash and\n * invalidates Metro's cache. Returns `'missing'` when the entry can't be\n * read so the cache key stays deterministic.\n * @param cssPath Absolute CSS path.\n * @returns 16-char hex content hash.\n */\nfunction readThemeHashFor(cssPath: string): string {\n if (!existsSync(cssPath)) return 'missing'\n try {\n return createHash('sha256').update(resolveThemeCss(cssPath)).digest('hex').slice(0, 16)\n } catch {\n return 'missing'\n }\n}\n\n/**\n * Hash a small set of rnwind library files whose changes affect the\n * generated transform output. When the library is rebuilt (workspace\n * dev OR npm install of a new version) the file bytes change, the\n * fingerprint rotates, and Metro's transform cache invalidates.\n *\n * Includes the JSX rewriter (`transform-ast`) alongside the parser /\n * style-builder so a change to the transformer — e.g. renaming the\n * injected context hook — invalidates every stale per-file cache entry\n * on the next dev run. Without this, a user upgrading rnwind in-place\n * would keep loading the old transformed bytes; React-refresh would\n * then preserve fiber state across the version bump and the rendered\n * hook list could shift, surfacing as \"change in the order of Hooks\"\n * runtime errors.\n * Memoised — read once per worker process.\n * @returns 16-char hex fingerprint.\n */\nfunction getLibraryFingerprint(): string {\n if (libraryFingerprint !== undefined) return libraryFingerprint\n const here = path.dirname(__filename)\n const candidates = [\n path.resolve(here, '..', 'core', 'style-builder', 'build-style.mjs'),\n path.resolve(here, '..', 'core', 'style-builder', 'build-style.cjs'),\n path.resolve(here, '..', 'core', 'parser', 'tw-parser.mjs'),\n path.resolve(here, '..', 'core', 'parser', 'tw-parser.cjs'),\n path.resolve(here, 'transform-ast.mjs'),\n path.resolve(here, 'transform-ast.cjs'),\n path.resolve(here, 'transformer.mjs'),\n path.resolve(here, 'transformer.cjs'),\n // Source-tree fallback for tests + workspace dev (no built lib yet).\n path.resolve(here, '..', '..', 'src', 'core', 'style-builder', 'build-style.ts'),\n path.resolve(here, '..', '..', 'src', 'core', 'parser', 'tw-parser.ts'),\n path.resolve(here, '..', '..', 'src', 'metro', 'transform-ast.ts'),\n path.resolve(here, '..', '..', 'src', 'metro', 'transformer.ts'),\n ]\n const hash = createHash('sha256')\n let included = 0\n for (const file of candidates) {\n if (!existsSync(file)) continue\n try {\n hash.update(readFileSync(file))\n included += 1\n } catch {\n // Unreadable file — skip; fingerprint still derives from whatever WE could read.\n }\n }\n libraryFingerprint = included > 0 ? hash.digest('hex').slice(0, 16) : '0'.repeat(16)\n return libraryFingerprint\n}\n\n/**\n * Worker-local state. Lazy-initialised on first access so files that\n * bypass the transform don't pay for construction.\n */\nexport interface RnwindState {\n parser: TailwindParser\n builder: UnionBuilder\n themeCss: string\n themeHash: string\n projectRoot: string\n}\n\n/**\n * Publish the theme CSS path + cache dir to the environment so worker\n * subprocesses (spawned by Metro once `babelTransformerPath` is set)\n * can rebuild the same state without re-reading the Metro config.\n * @param cssEntryFile Absolute path to the user's theme CSS.\n * @param cacheDir Absolute path to the cache dir (`.rnwind`).\n * @param watchFolders\n * @param classNamePrefixes Extra JSX prop-name prefixes to rewrite.\n * @param hostSources\n * @param hostComponents\n */\nexport function configureRnwindState(\n cssEntryFile: string,\n cacheDir: string,\n watchFolders: readonly string[] = [],\n classNamePrefixes?: readonly string[],\n hostSources?: readonly string[],\n hostComponents?: readonly string[],\n): void {\n process.env[CSS_ENTRY_ENV] = cssEntryFile\n process.env[CACHE_DIR_ENV] = cacheDir\n if (watchFolders.length === 0) {\n delete process.env[WATCH_FOLDERS_ENV]\n } else {\n process.env[WATCH_FOLDERS_ENV] = watchFolders.join('\\0')\n }\n if (!classNamePrefixes || classNamePrefixes.length === 0) {\n delete process.env[CLASSNAME_PREFIXES_ENV]\n } else {\n process.env[CLASSNAME_PREFIXES_ENV] = classNamePrefixes.join(',')\n }\n if (!hostSources || hostSources.length === 0) {\n delete process.env[HOST_SOURCES_ENV]\n } else {\n process.env[HOST_SOURCES_ENV] = hostSources.join(',')\n }\n if (!hostComponents || hostComponents.length === 0) {\n delete process.env[HOST_COMPONENTS_ENV]\n } else {\n process.env[HOST_COMPONENTS_ENV] = hostComponents.join(',')\n }\n cached = null\n}\n\n/**\n * Read the caller-configured extra className prefixes out of the\n * worker environment. Returns an empty array when unset — the\n * transformer applies the built-in `contentContainer` default on top\n * either way.\n * @returns User-supplied extra prefixes.\n */\nexport function getClassNamePrefixes(): readonly string[] {\n const raw = process.env[CLASSNAME_PREFIXES_ENV]\n if (!raw || raw.length === 0) return []\n return raw.split(',').filter((entry) => entry.length > 0)\n}\n\n/**\n * Read the caller-configured extra host module sources out of the\n * worker environment. Empty array when unset — the transformer applies\n * its built-in default list on top either way.\n * @returns User-supplied extra host sources.\n */\nexport function getHostSources(): readonly string[] {\n const raw = process.env[HOST_SOURCES_ENV]\n if (!raw || raw.length === 0) return []\n return raw.split(',').filter((entry) => entry.length > 0)\n}\n\n/**\n * Read the caller-configured extra host JSX tag names out of the worker\n * environment. Verbatim names — may include `.` for member expressions\n * like `'Animated.View'`.\n * @returns User-supplied extra host component names.\n */\nexport function getHostComponents(): readonly string[] {\n const raw = process.env[HOST_COMPONENTS_ENV]\n if (!raw || raw.length === 0) return []\n return raw.split(',').filter((entry) => entry.length > 0)\n}\n\n/**\n * Fetch (or build) the worker-local rnwind state. Re-reads the theme\n * CSS hash on every call: if the user edited `global.css` while Metro\n * is running, the cached state is dropped and a fresh parser + ledger\n * is built. Combined with the `getCacheKey()` export on the\n * transformer (which folds the same hash into Metro's per-file cache\n * key) every CSS edit produces a full, correct re-bundle.\n * @param projectRoot\n * @returns The live rnwind state.\n */\nexport function getRnwindState(projectRoot: string): RnwindState {\n const cssEntry = process.env[CSS_ENTRY_ENV]\n const cacheDir = process.env[CACHE_DIR_ENV]\n if (!cssEntry) throw new Error('rnwind: RNWIND_CSS_ENTRY_FILE is not set — did `withRnwindConfig` run?')\n if (!cacheDir) throw new Error('rnwind: RNWIND_CACHE_DIR is not set — did `withRnwindConfig` run?')\n const currentHash = readThemeHashFor(cssEntry)\n if (cached?.themeHash === currentHash && cached.projectRoot === projectRoot) return cached\n const themeCss = resolveThemeCss(cssEntry)\n const parser = new TailwindParser({\n themeCss,\n sources: defaultSources(projectRoot, cacheDir, readWatchFolders()),\n })\n const builder = new UnionBuilder(cacheDir, parser)\n cached = { parser, builder, themeCss, themeHash: currentHash, projectRoot }\n return cached\n}\n\n/**\n * Compute the rnwind cache-key suffix Metro mixes into every per-file\n * transform cache entry via the transformer's `getCacheKey()` export.\n * Includes the CSS path + its current content hash + the rnwind\n * library fingerprint, so any edit to `global.css` OR a library\n * upgrade flips the cache key and forces Metro to re-run the\n * transformer.\n * @returns Deterministic string suitable for appending to Metro's cache key.\n */\nexport function getRnwindCacheKey(): string {\n const cssEntry = process.env[CSS_ENTRY_ENV] ?? ''\n const prefixes = process.env[CLASSNAME_PREFIXES_ENV] ?? ''\n // Host source / component config changes which JSX tags get rewritten,\n // so it MUST flip the cache key — otherwise Metro replays stale\n // transforms (a newly-opted-in host keeps its raw className, a removed\n // one keeps the rewrite).\n const hostSources = process.env[HOST_SOURCES_ENV] ?? ''\n const hostComponents = process.env[HOST_COMPONENTS_ENV] ?? ''\n return `rnwind:${cssEntry}:${readThemeHashFor(cssEntry)}|lib:${getLibraryFingerprint()}|pfx:${prefixes}|hs:${hostSources}|hc:${hostComponents}`\n}\n\n/** Drop the cached state — call after editing the theme CSS. */\nexport function resetRnwindState(): void {\n cached = null\n}\n\n/**\n * Drop cached state, rebuild parser/builder with the fresh CSS, rescan\n * the project, and rewrite every scheme file on disk. This is what\n * `withRnwindConfig`'s CSS file-watcher invokes so `global.css` edits\n * propagate to the app via Metro's HMR — without this, the CSS-as-JS\n * module would re-emit `export {}` whose bytes never change, so Metro\n * would never invalidate downstream modules.\n * @param projectRoot Absolute project root (from `metroConfig.projectRoot`).\n */\nexport async function onThemeChange(projectRoot: string): Promise<void> {\n resetRnwindState()\n const state = getRnwindState(projectRoot)\n await state.builder.writeSchemes()\n}\n\n/**\n * Resolve the on-disk path of the scheme manifest module for the\n * resolver. The manifest eager-imports `common.style.js` and\n * lazy-requires each variant scheme; SchemeProvider calls its\n * `ensureSchemeLoaded` export to trigger per-scheme requires.\n * @returns Absolute path to `<cacheDir>/schemes.js`.\n */\nexport function manifestPathFor(): string {\n const cacheDir = process.env[CACHE_DIR_ENV]\n if (!cacheDir) throw new Error('rnwind: RNWIND_CACHE_DIR is not set')\n return path.join(cacheDir, 'schemes.js')\n}\n"],"names":["existsSync","createHash","resolveThemeCss","readFileSync","TailwindParser","UnionBuilder"],"mappings":"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"}
1
+ {"version":3,"file":"state.cjs","sources":["../../../../src/metro/state.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs'\nimport path from 'node:path'\nimport { createHash } from 'node:crypto'\nimport { UnionBuilder } from '../core/style-builder'\nimport { TailwindParser, type SourceEntry } from '../core/parser'\nimport { resolveThemeCss } from './css-imports'\nimport { buildWrapModules } from './wrap-imports'\n\n/**\n * Default oxide Scanner globs — walk every JS/TS source under the\n * project root AND every monorepo watch folder, excluding\n * `node_modules` and rnwind's own cache dir so we don't rescan\n * generated scheme files.\n *\n * Monorepo layouts (Yarn workspaces, pnpm workspaces, Nx) surface\n * sibling package roots as `metroConfig.watchFolders`. Every folder\n * Metro watches must also be scanned so atoms declared in shared UI\n * packages make it into the union — without this, only the app's\n * own files would be scanned and every UI-package atom would resolve\n * to `undefined` at runtime.\n * @param projectRoot Absolute project root.\n * @param cacheDir Absolute rnwind cache dir (to exclude).\n * @param watchFolders Extra monorepo roots Metro is watching.\n * @returns Scanner sources suitable for `parser.parseProject()`.\n */\nfunction defaultSources(projectRoot: string, cacheDir: string, watchFolders: readonly string[]): readonly SourceEntry[] {\n const cacheBaseName = path.basename(cacheDir)\n const roots = new Set<string>([projectRoot, ...watchFolders])\n const sources: SourceEntry[] = []\n for (const root of roots) {\n sources.push({ base: root, pattern: '**/*.{ts,tsx,js,jsx}', negated: false }, { base: root, pattern: '**/node_modules/**', negated: true }, { base: root, pattern: `**/${cacheBaseName}/**`, negated: true })\n }\n return sources\n}\n\n/**\n * Read monorepo watch-folder paths out of the worker environment.\n * Empty array when the host isn't a monorepo.\n * @returns Absolute paths Metro also watches (sibling packages).\n */\nfunction readWatchFolders(): readonly string[] {\n const raw = process.env[WATCH_FOLDERS_ENV]\n if (!raw || raw.length === 0) return []\n return raw.split('\\0').filter((entry) => entry.length > 0)\n}\n\n/** Env var Metro workers read to locate the theme CSS on disk. */\nconst CSS_ENTRY_ENV = 'RNWIND_CSS_ENTRY_FILE'\n/** Env var Metro workers read to locate the cache directory (`.rnwind`). */\nconst CACHE_DIR_ENV = 'RNWIND_CACHE_DIR'\n/** Env var carrying `watchFolders` from Metro config (NUL-separated). */\nconst WATCH_FOLDERS_ENV = 'RNWIND_WATCH_FOLDERS'\n/** Env var carrying extra modules whose component exports get `wrap()`-ed. Comma-separated. */\nconst WRAP_MODULES_ENV = 'RNWIND_WRAP_MODULES'\n\n/** Memoised library fingerprint — read once per worker process. */\nlet libraryFingerprint: string | undefined\n\n/** Live state shared across one Metro transform worker. */\nlet cached: RnwindState | null = null\n\n/**\n * Cheap content-hash readout. SHA-256 prefix of the FULLY-RESOLVED theme\n * CSS — `@import`s flattened — so an edit to a theme file the entry only\n * re-exports (`@import \"@acme/ui/theme.css\"`) still rotates the hash and\n * invalidates Metro's cache. Returns `'missing'` when the entry can't be\n * read so the cache key stays deterministic.\n * @param cssPath Absolute CSS path.\n * @returns 16-char hex content hash.\n */\nfunction readThemeHashFor(cssPath: string): string {\n if (!existsSync(cssPath)) return 'missing'\n try {\n return createHash('sha256').update(resolveThemeCss(cssPath)).digest('hex').slice(0, 16)\n } catch {\n return 'missing'\n }\n}\n\n/**\n * Hash a small set of rnwind library files whose changes affect the\n * generated transform output. When the library is rebuilt (workspace\n * dev OR npm install of a new version) the file bytes change, the\n * fingerprint rotates, and Metro's transform cache invalidates.\n *\n * Includes the import-rewriter (`wrap-imports`) and runtime resolver\n * alongside the parser / style-builder so a change to the transformer —\n * e.g. renaming the injected wrap helper — invalidates every stale\n * per-file cache entry on the next dev run. Without this, a user upgrading rnwind in-place\n * would keep loading the old transformed bytes; React-refresh would\n * then preserve fiber state across the version bump and the rendered\n * hook list could shift, surfacing as \"change in the order of Hooks\"\n * runtime errors.\n * Memoised — read once per worker process.\n * @returns 16-char hex fingerprint.\n */\nfunction getLibraryFingerprint(): string {\n if (libraryFingerprint !== undefined) return libraryFingerprint\n const here = path.dirname(__filename)\n const candidates = [\n path.resolve(here, '..', 'core', 'style-builder', 'build-style.mjs'),\n path.resolve(here, '..', 'core', 'style-builder', 'build-style.cjs'),\n path.resolve(here, '..', 'core', 'parser', 'tw-parser.mjs'),\n path.resolve(here, '..', 'core', 'parser', 'tw-parser.cjs'),\n path.resolve(here, 'wrap-imports.mjs'),\n path.resolve(here, 'wrap-imports.cjs'),\n path.resolve(here, 'transformer.mjs'),\n path.resolve(here, 'transformer.cjs'),\n // Source-tree fallback for tests + workspace dev (no built lib yet).\n path.resolve(here, '..', '..', 'src', 'core', 'style-builder', 'build-style.ts'),\n path.resolve(here, '..', '..', 'src', 'core', 'parser', 'tw-parser.ts'),\n path.resolve(here, '..', '..', 'src', 'metro', 'wrap-imports.ts'),\n path.resolve(here, '..', '..', 'src', 'metro', 'transformer.ts'),\n ]\n const hash = createHash('sha256')\n let included = 0\n for (const file of candidates) {\n if (!existsSync(file)) continue\n try {\n hash.update(readFileSync(file))\n included += 1\n } catch {\n // Unreadable file — skip; fingerprint still derives from whatever WE could read.\n }\n }\n libraryFingerprint = included > 0 ? hash.digest('hex').slice(0, 16) : '0'.repeat(16)\n return libraryFingerprint\n}\n\n/**\n * Worker-local state. Lazy-initialised on first access so files that\n * bypass the transform don't pay for construction.\n */\nexport interface RnwindState {\n parser: TailwindParser\n builder: UnionBuilder\n themeCss: string\n themeHash: string\n projectRoot: string\n}\n\n/**\n * Publish the theme CSS path + cache dir to the environment so worker\n * subprocesses (spawned by Metro once `babelTransformerPath` is set)\n * can rebuild the same state without re-reading the Metro config.\n * @param cssEntryFile Absolute path to the user's theme CSS.\n * @param cacheDir Absolute path to the cache dir (`.rnwind`).\n * @param watchFolders Monorepo watch folders to scan for atoms.\n * @param wrapModules Extra modules whose component exports get `wrap()`-ed.\n */\nexport function configureRnwindState(\n cssEntryFile: string,\n cacheDir: string,\n watchFolders: readonly string[] = [],\n wrapModules?: readonly string[],\n): void {\n process.env[CSS_ENTRY_ENV] = cssEntryFile\n process.env[CACHE_DIR_ENV] = cacheDir\n if (watchFolders.length === 0) {\n delete process.env[WATCH_FOLDERS_ENV]\n } else {\n process.env[WATCH_FOLDERS_ENV] = watchFolders.join('\\0')\n }\n if (!wrapModules || wrapModules.length === 0) {\n delete process.env[WRAP_MODULES_ENV]\n } else {\n process.env[WRAP_MODULES_ENV] = wrapModules.join(',')\n }\n cached = null\n}\n\n/**\n * Effective module → wrap-policy map: the built-in defaults merged with\n * any extra modules the Metro config supplied.\n * @returns Module → policy map the import-rewrite consults.\n */\nexport function getWrapModules(): ReturnType<typeof buildWrapModules> {\n const raw = process.env[WRAP_MODULES_ENV]\n const extra = raw && raw.length > 0 ? raw.split(',').filter((entry) => entry.length > 0) : undefined\n return buildWrapModules(extra)\n}\n\n/**\n * Fetch (or build) the worker-local rnwind state. Re-reads the theme\n * CSS hash on every call: if the user edited `global.css` while Metro\n * is running, the cached state is dropped and a fresh parser + ledger\n * is built. Combined with the `getCacheKey()` export on the\n * transformer (which folds the same hash into Metro's per-file cache\n * key) every CSS edit produces a full, correct re-bundle.\n * @param projectRoot\n * @returns The live rnwind state.\n */\nexport function getRnwindState(projectRoot: string): RnwindState {\n const cssEntry = process.env[CSS_ENTRY_ENV]\n const cacheDir = process.env[CACHE_DIR_ENV]\n if (!cssEntry) throw new Error('rnwind: RNWIND_CSS_ENTRY_FILE is not set — did `withRnwindConfig` run?')\n if (!cacheDir) throw new Error('rnwind: RNWIND_CACHE_DIR is not set — did `withRnwindConfig` run?')\n const currentHash = readThemeHashFor(cssEntry)\n if (cached?.themeHash === currentHash && cached.projectRoot === projectRoot) return cached\n const themeCss = resolveThemeCss(cssEntry)\n const parser = new TailwindParser({\n themeCss,\n sources: defaultSources(projectRoot, cacheDir, readWatchFolders()),\n })\n const builder = new UnionBuilder(cacheDir, parser)\n cached = { parser, builder, themeCss, themeHash: currentHash, projectRoot }\n return cached\n}\n\n/**\n * Compute the rnwind cache-key suffix Metro mixes into every per-file\n * transform cache entry via the transformer's `getCacheKey()` export.\n * Includes the CSS path + its current content hash + the rnwind\n * library fingerprint, so any edit to `global.css` OR a library\n * upgrade flips the cache key and forces Metro to re-run the\n * transformer.\n * @returns Deterministic string suitable for appending to Metro's cache key.\n */\nexport function getRnwindCacheKey(): string {\n const cssEntry = process.env[CSS_ENTRY_ENV] ?? ''\n // Wrap-module config changes which import sites get `wrap()`-ed, so it\n // MUST flip the cache key — otherwise Metro replays stale transforms\n // (a newly-opted-in module keeps its raw import, a removed one keeps\n // the wrap).\n const wrapModules = process.env[WRAP_MODULES_ENV] ?? ''\n return `rnwind:${cssEntry}:${readThemeHashFor(cssEntry)}|lib:${getLibraryFingerprint()}|wm:${wrapModules}`\n}\n\n/** Drop the cached state — call after editing the theme CSS. */\nexport function resetRnwindState(): void {\n cached = null\n}\n\n/**\n * Drop cached state, rebuild parser/builder with the fresh CSS, rescan\n * the project, and rewrite every scheme file on disk. This is what\n * `withRnwindConfig`'s CSS file-watcher invokes so `global.css` edits\n * propagate to the app via Metro's HMR — without this, the CSS-as-JS\n * module would re-emit `export {}` whose bytes never change, so Metro\n * would never invalidate downstream modules.\n * @param projectRoot Absolute project root (from `metroConfig.projectRoot`).\n */\nexport async function onThemeChange(projectRoot: string): Promise<void> {\n resetRnwindState()\n const state = getRnwindState(projectRoot)\n await state.builder.writeSchemes()\n}\n\n/**\n * Resolve the on-disk path of the scheme manifest module for the\n * resolver. The manifest eager-imports `common.style.js` and\n * lazy-requires each variant scheme; SchemeProvider calls its\n * `ensureSchemeLoaded` export to trigger per-scheme requires.\n * @returns Absolute path to `<cacheDir>/schemes.js`.\n */\nexport function manifestPathFor(): string {\n const cacheDir = process.env[CACHE_DIR_ENV]\n if (!cacheDir) throw new Error('rnwind: RNWIND_CACHE_DIR is not set')\n return path.join(cacheDir, 'schemes.js')\n}\n"],"names":["existsSync","createHash","resolveThemeCss","readFileSync","buildWrapModules","TailwindParser","UnionBuilder"],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import { UnionBuilder } from '../core/style-builder';
2
2
  import { TailwindParser } from '../core/parser';
3
+ import { buildWrapModules } from './wrap-imports';
3
4
  /**
4
5
  * Worker-local state. Lazy-initialised on first access so files that
5
6
  * bypass the transform don't pay for construction.
@@ -17,34 +18,16 @@ export interface RnwindState {
17
18
  * can rebuild the same state without re-reading the Metro config.
18
19
  * @param cssEntryFile Absolute path to the user's theme CSS.
19
20
  * @param cacheDir Absolute path to the cache dir (`.rnwind`).
20
- * @param watchFolders
21
- * @param classNamePrefixes Extra JSX prop-name prefixes to rewrite.
22
- * @param hostSources
23
- * @param hostComponents
21
+ * @param watchFolders Monorepo watch folders to scan for atoms.
22
+ * @param wrapModules Extra modules whose component exports get `wrap()`-ed.
24
23
  */
25
- export declare function configureRnwindState(cssEntryFile: string, cacheDir: string, watchFolders?: readonly string[], classNamePrefixes?: readonly string[], hostSources?: readonly string[], hostComponents?: readonly string[]): void;
24
+ export declare function configureRnwindState(cssEntryFile: string, cacheDir: string, watchFolders?: readonly string[], wrapModules?: readonly string[]): void;
26
25
  /**
27
- * Read the caller-configured extra className prefixes out of the
28
- * worker environment. Returns an empty array when unset — the
29
- * transformer applies the built-in `contentContainer` default on top
30
- * either way.
31
- * @returns User-supplied extra prefixes.
26
+ * Effective module → wrap-policy map: the built-in defaults merged with
27
+ * any extra modules the Metro config supplied.
28
+ * @returns Module policy map the import-rewrite consults.
32
29
  */
33
- export declare function getClassNamePrefixes(): readonly string[];
34
- /**
35
- * Read the caller-configured extra host module sources out of the
36
- * worker environment. Empty array when unset — the transformer applies
37
- * its built-in default list on top either way.
38
- * @returns User-supplied extra host sources.
39
- */
40
- export declare function getHostSources(): readonly string[];
41
- /**
42
- * Read the caller-configured extra host JSX tag names out of the worker
43
- * environment. Verbatim names — may include `.` for member expressions
44
- * like `'Animated.View'`.
45
- * @returns User-supplied extra host component names.
46
- */
47
- export declare function getHostComponents(): readonly string[];
30
+ export declare function getWrapModules(): ReturnType<typeof buildWrapModules>;
48
31
  /**
49
32
  * Fetch (or build) the worker-local rnwind state. Re-reads the theme
50
33
  * CSS hash on every call: if the user edited `global.css` while Metro
@@ -5,8 +5,8 @@ var parser = require('@babel/parser');
5
5
  var generate = require('@babel/generator');
6
6
  var node_crypto = require('node:crypto');
7
7
  var node_fs = require('node:fs');
8
- var transformAst = require('./transform-ast.cjs');
9
8
  var state = require('./state.cjs');
9
+ var wrapImports = require('./wrap-imports.cjs');
10
10
  var resolver = require('./resolver.cjs');
11
11
  var warnUnknownClasses$1 = require('./warn-unknown-classes.cjs');
12
12
 
@@ -75,10 +75,19 @@ function parseUserSource(source) {
75
75
  * @param candidates Every candidate oxide surfaced from the source.
76
76
  * @param atoms Successfully resolved atoms (keys are class names).
77
77
  * @param filename Source path, prefixed onto the warning.
78
+ * @param features Feature-atom maps (gradient / haptic) — their names are
79
+ * known classes even though they carry no RN style, so they're excluded
80
+ * from the unknown-class warning.
78
81
  */
79
- function warnUnknownClasses(source, candidates, atoms, filename) {
80
- const atomNames = new Set(atoms.keys());
81
- const unknown = warnUnknownClasses$1.filterUnknownClassCandidates(source, candidates, atomNames);
82
+ function warnUnknownClasses(source, candidates, atoms, filename, features = []) {
83
+ // Feature atoms (gradient / haptic) resolve to no RN style, so they're
84
+ // absent from `atoms` — but they're NOT unknown. Fold their names into
85
+ // the known set so `active:haptic-rigid` etc. don't warn at build time.
86
+ const known = new Set(atoms.keys());
87
+ for (const map of features)
88
+ for (const name of map.keys())
89
+ known.add(name);
90
+ const unknown = warnUnknownClasses$1.filterUnknownClassCandidates(source, candidates, known);
82
91
  if (unknown.length === 0)
83
92
  return;
84
93
  // eslint-disable-next-line no-console
@@ -121,52 +130,181 @@ function isThemeCssEntry(filename) {
121
130
  return typeof cssEntry === 'string' && cssEntry.length > 0 && cssEntry === filename;
122
131
  }
123
132
  /**
124
- * Parse + run rnwind's JSX rewrite + regenerate source code. When
125
- * parsing or transformation fails, fall back to the original source —
126
- * we don't want a transient parse error to crash Metro for a file the
127
- * upstream might handle fine.
133
+ * Wrap host imports + compile any className literals, then regenerate
134
+ * source. Two paths:
135
+ * - **className present**: oxide-scan the file, record its atoms into
136
+ * the union, and inject the generated-style + theme-signature
137
+ * side-effect imports so the runtime registries populate.
138
+ * - **import-only** (a `{...rest}` forwarder or a leaf with no literal
139
+ * `className=`): just wrap the host imports so a forwarded className
140
+ * still resolves at render — no oxide scan, no injected imports.
141
+ *
142
+ * On parse failure, fall back to the original source — a transient parse
143
+ * error shouldn't crash Metro for a file the upstream might handle fine.
128
144
  * @param args Metro args; `src` is the original source text.
129
- * @returns Rewritten source text (with `className=` rewrites applied).
145
+ * @returns Rewritten source text.
130
146
  */
131
147
  async function rewriteSource(args) {
132
148
  const ast = parseUserSource(args.src);
133
149
  if (!ast)
134
150
  return args.src;
151
+ // Wrap host component imports so `<View className=…>` resolves at render
152
+ // through the runtime `wrap` (works for literal, spread, and forwarded
153
+ // classNames alike). No JSX is rewritten here.
154
+ const wrapped = wrapImports.rewriteWrapImports(ast, state.getWrapModules());
155
+ if (!/classname=/i.test(args.src)) {
156
+ // Import-only file: nothing to compile. Drop any stale atom
157
+ // contribution (className may have just been removed) and emit the
158
+ // wrapped imports — or the untouched source when nothing wrapped.
159
+ dropFileSafely(args.filename, projectRootOf(args));
160
+ return wrapped ? generateModule(ast).code : args.src;
161
+ }
135
162
  const state$1 = state.getRnwindState(projectRootOf(args));
136
163
  const extension = extensionOf(args.filename);
137
164
  const parsed = await state$1.parser.parseAtoms({ content: args.src, extension });
138
- warnUnknownClasses(args.src, parsed.candidates, parsed.atoms, args.filename);
139
- const classNamePrefixes = state.getClassNamePrefixes();
140
- const hostSources = state.getHostSources();
141
- const hostComponents = state.getHostComponents();
165
+ warnUnknownClasses(args.src, parsed.candidates, parsed.atoms, args.filename, [parsed.gradientAtoms, parsed.hapticAtoms]);
142
166
  if (parsed.atoms.size === 0) {
143
167
  state$1.builder.dropFile(args.filename);
144
168
  await state$1.builder.writeSchemes();
145
- transformAst.transformAst(ast, {
146
- styleSpecifiers: [],
147
- gradientAtoms: parsed.gradientAtoms,
148
- hapticAtoms: parsed.hapticAtoms,
149
- classNamePrefixes,
150
- hostSources,
151
- hostComponents,
152
- });
153
169
  injectThemeSignatureImport(ast);
154
170
  return generateModule(ast).code;
155
171
  }
156
- const { changed } = await state$1.builder.recordFile(args.filename, parsed.atoms, parsed.keyframes);
172
+ const literals = collectClassNameLiterals(ast);
173
+ const { changed } = await state$1.builder.recordFile(args.filename, parsed.atoms, parsed.keyframes, literals);
157
174
  if (changed)
158
175
  await state$1.builder.writeSchemes();
159
- transformAst.transformAst(ast, {
160
- styleSpecifiers: resolver.STYLE_SPECIFIERS,
161
- gradientAtoms: parsed.gradientAtoms,
162
- hapticAtoms: parsed.hapticAtoms,
163
- classNamePrefixes,
164
- hostSources,
165
- hostComponents,
166
- });
176
+ injectSideEffectImports(ast, resolver.STYLE_SPECIFIERS);
167
177
  injectThemeSignatureImport(ast);
168
178
  return generateModule(ast).code;
169
179
  }
180
+ /**
181
+ * Drop a file's union contribution, swallowing the "state not configured"
182
+ * error unit tests hit when they call the transformer without
183
+ * `configureRnwindState`.
184
+ * @param filename Absolute source path.
185
+ * @param projectRoot Project root for state lookup.
186
+ */
187
+ function dropFileSafely(filename, projectRoot) {
188
+ try {
189
+ state.getRnwindState(projectRoot).builder.dropFile(filename);
190
+ }
191
+ catch {
192
+ // State not configured (standalone/unit test). Nothing to drop.
193
+ }
194
+ }
195
+ /**
196
+ * Whether a JSX attribute names a className-style prop (`className` or
197
+ * any `<prefix>ClassName`).
198
+ * @param node JSX attribute node.
199
+ * @returns True when the attribute is a className prop.
200
+ */
201
+ function isClassNameAttribute(node) {
202
+ if (!t__namespace.isJSXIdentifier(node.name))
203
+ return false;
204
+ const { name } = node.name;
205
+ return name === 'className' || name.endsWith('ClassName');
206
+ }
207
+ /**
208
+ * Pull static string literals out of a className expression. Handles a
209
+ * bare string, a no-substitution template, and the branches of a
210
+ * ternary / `&&` (so `cond ? 'a' : 'b'` and `flag && 'x'` both register
211
+ * their literals). Dynamic interpolations are skipped — they resolve via
212
+ * the runtime atom path.
213
+ * @param expr Expression inside a `className={...}` container.
214
+ * @param out Accumulator for discovered literals.
215
+ */
216
+ function collectLiteralsFromExpression(expr, out) {
217
+ if (!expr)
218
+ return;
219
+ if (t__namespace.isStringLiteral(expr)) {
220
+ out.push(expr.value);
221
+ return;
222
+ }
223
+ if (t__namespace.isTemplateLiteral(expr) && expr.expressions.length === 0 && expr.quasis.length === 1) {
224
+ const cooked = expr.quasis[0]?.value.cooked;
225
+ if (typeof cooked === 'string')
226
+ out.push(cooked);
227
+ return;
228
+ }
229
+ if (t__namespace.isConditionalExpression(expr)) {
230
+ collectLiteralsFromExpression(expr.consequent, out);
231
+ collectLiteralsFromExpression(expr.alternate, out);
232
+ return;
233
+ }
234
+ if (t__namespace.isLogicalExpression(expr)) {
235
+ collectLiteralsFromExpression(expr.right, out);
236
+ }
237
+ }
238
+ /** AST node keys the literal walk skips — position / comment metadata. */
239
+ const SKIP_WALK_KEYS = new Set(['type', 'loc', 'start', 'end', 'range', 'leadingComments', 'trailingComments', 'innerComments']);
240
+ /**
241
+ * Collect the static literals from one className JSX attribute into the
242
+ * dedup accumulator.
243
+ * @param attribute The (already className-matched) JSX attribute.
244
+ * @param seen Dedup set of literals already collected.
245
+ * @param out Ordered accumulator.
246
+ */
247
+ function collectAttributeLiterals(attribute, seen, out) {
248
+ const { value } = attribute;
249
+ const found = [];
250
+ if (t__namespace.isStringLiteral(value))
251
+ found.push(value.value);
252
+ else if (t__namespace.isJSXExpressionContainer(value))
253
+ collectLiteralsFromExpression(value.expression, found);
254
+ for (const literal of found) {
255
+ if (seen.has(literal))
256
+ continue;
257
+ seen.add(literal);
258
+ out.push(literal);
259
+ }
260
+ }
261
+ /**
262
+ * Walk the AST for every `className=` / `<prefix>ClassName=` literal so
263
+ * the builder can pre-merge each into a per-scheme molecule. A generic
264
+ * node walk (no scope build) keeps it cheap; only JSX attribute nodes do
265
+ * any work.
266
+ * @param ast Parsed Babel file.
267
+ * @returns Distinct literal className strings, in first-seen order.
268
+ */
269
+ function collectClassNameLiterals(ast) {
270
+ const out = [];
271
+ const seen = new Set();
272
+ const visit = (node) => {
273
+ if (!node || typeof node !== 'object')
274
+ return;
275
+ if (Array.isArray(node)) {
276
+ for (const child of node)
277
+ visit(child);
278
+ return;
279
+ }
280
+ const typed = node;
281
+ if (typeof typed.type !== 'string')
282
+ return;
283
+ if (typed.type === 'JSXAttribute' && isClassNameAttribute(node)) {
284
+ collectAttributeLiterals(node, seen, out);
285
+ }
286
+ for (const key in typed) {
287
+ if (SKIP_WALK_KEYS.has(key))
288
+ continue;
289
+ visit(typed[key]);
290
+ }
291
+ };
292
+ visit(ast.program);
293
+ return out;
294
+ }
295
+ /**
296
+ * Prepend side-effect imports (`import '<spec>'`) so the generated
297
+ * per-scheme style + manifest modules load — registering this file's
298
+ * atoms / molecules / features into the runtime registries the wrapper's
299
+ * `resolve` reads.
300
+ * @param ast Babel File AST to mutate in place.
301
+ * @param specifiers Module specifiers to side-effect-import.
302
+ */
303
+ function injectSideEffectImports(ast, specifiers) {
304
+ for (const specifier of specifiers) {
305
+ ast.program.body.unshift(t__namespace.importDeclaration([], t__namespace.stringLiteral(specifier)));
306
+ }
307
+ }
170
308
  /**
171
309
  * Prepend `import 'rnwind/__generated/theme-signature'` to every
172
310
  * rnwind-transformed file. The resolver maps that specifier to the
@@ -262,10 +400,16 @@ function loadUpstream() {
262
400
  function isRewriteCandidate(args) {
263
401
  if (!/\.(?:tsx|ts|jsx|js)$/i.test(args.filename))
264
402
  return false;
265
- // Case-insensitive so `<prefix>ClassName=` (e.g. `contentContainerClassName=`)
266
- // which has a capital `C` and so doesn't contain the lowercase
267
- // `className=` still routes the file through the rewrite pass.
268
- if (!/classname=/i.test(args.src))
403
+ // Process the file when it either:
404
+ // - carries a `className=` / `<prefix>ClassName=` literal (case-
405
+ // insensitive `contentContainerClassName=` has a capital C), or
406
+ // - spreads props (`{...rest}`) onto a host from a wrap-module, where a
407
+ // forwarded className must still get its import wrapped (no literal
408
+ // appears in this file). A style-less `<View/>` with neither is left
409
+ // alone so it never pays for an unused wrapper.
410
+ const hasClassName = /classname=/i.test(args.src);
411
+ const isForwarder = /\{\s*\.\.\./.test(args.src) && mentionsWrapModule(args.src);
412
+ if (!hasClassName && !isForwarder)
269
413
  return false;
270
414
  if (!args.filename.includes('/node_modules/'))
271
415
  return true;
@@ -278,6 +422,21 @@ function isRewriteCandidate(args) {
278
422
  return false;
279
423
  }
280
424
  }
425
+ /**
426
+ * Cheap pre-parse check: does the source import from any configured
427
+ * wrap-module? A quoted specifier match is enough — `rewriteWrapImports`
428
+ * re-verifies precisely on the AST, so a false positive only costs a
429
+ * no-op parse.
430
+ * @param source Source text.
431
+ * @returns True when a wrap-module specifier appears in the source.
432
+ */
433
+ function mentionsWrapModule(source) {
434
+ for (const moduleName of state.getWrapModules().keys()) {
435
+ if (source.includes(`'${moduleName}'`) || source.includes(`"${moduleName}"`))
436
+ return true;
437
+ }
438
+ return false;
439
+ }
281
440
  /**
282
441
  * Fallback parse when no upstream is configured AND Metro didn't hand
283
442
  * us an AST. Used by unit tests and standalone setups.
@@ -1 +1 @@
1
- {"version":3,"file":"transformer.cjs","sources":["../../../../src/metro/transformer.ts"],"sourcesContent":["import type { File } from '@babel/types'\nimport * as t from '@babel/types'\nimport { parse } from '@babel/parser'\nimport generate from '@babel/generator'\nimport { createHash } from 'node:crypto'\nimport { realpathSync } from 'node:fs'\nimport { transformAst } from './transform-ast'\nimport { getClassNamePrefixes, getHostComponents, getHostSources, getRnwindCacheKey, getRnwindState, onThemeChange } from './state'\nimport { STYLE_SPECIFIERS, THEME_SIGNATURE_MODULE } from './resolver'\nimport { filterUnknownClassCandidates } from './warn-unknown-classes'\n\n/** The shape of the upstream module we delegate parsing/babel work to. */\ninterface UpstreamTransformer {\n transform: (args: BabelTransformerArgs) => Promise<BabelTransformerResult> | BabelTransformerResult\n}\n\n/** Env var that points at the upstream `babelTransformerPath` we override. */\nconst UPSTREAM_ENV = 'RNWIND_UPSTREAM_TRANSFORMER'\n\n/** Cached upstream module — required once, reused across every transform call. */\nlet cachedUpstream: UpstreamTransformer | null = null\n\nconst generateModule = (generate as unknown as { default?: typeof generate }).default ?? generate\n\n/**\n * Parse user source with the broad plugin set (Flow + JSX + TypeScript\n * + class properties). Permissive on purpose so we don't reject any\n * file the upstream could have handled. Returns `null` when parse\n * fails — caller falls back to the raw source string.\n * @param source Source text.\n * @returns Parsed AST, or null on parse failure.\n */\nfunction parseUserSource(source: string): File | null {\n try {\n return parse(source, {\n sourceType: 'unambiguous',\n allowReturnOutsideFunction: true,\n allowImportExportEverywhere: true,\n plugins: ['typescript', 'jsx'],\n }) as unknown as File\n } catch {\n try {\n return parse(source, {\n sourceType: 'unambiguous',\n allowReturnOutsideFunction: true,\n allowImportExportEverywhere: true,\n plugins: ['flow', 'jsx'],\n }) as unknown as File\n } catch {\n return null\n }\n }\n}\n\n/**\n * Print Tailwind-shaped candidates oxide picked up but the parser\n * could NOT compile — typo, missing custom utility, or class not in\n * the user's theme. Filtering by candidates that ALSO appear inside a\n * `className=\"…\"` literal eliminates false positives from imports,\n * comments, and JSX prop values.\n * @param source Original source text — searched for className literals.\n * @param candidates Every candidate oxide surfaced from the source.\n * @param atoms Successfully resolved atoms (keys are class names).\n * @param filename Source path, prefixed onto the warning.\n */\nfunction warnUnknownClasses(\n source: string,\n candidates: readonly string[],\n atoms: ReadonlyMap<string, unknown>,\n filename: string,\n): void {\n const atomNames = new Set(atoms.keys())\n const unknown = filterUnknownClassCandidates(source, candidates, atomNames)\n if (unknown.length === 0) return\n // eslint-disable-next-line no-console\n console.warn(`rnwind: unknown class${unknown.length > 1 ? 'es' : ''} in ${filename}: ${unknown.join(', ')}`)\n}\n\n/**\n * Extract the bare extension for oxide / internal switches.\n * @param filename Absolute path.\n * @returns Extension without the leading dot (`tsx` / `ts` / `js` / `jsx`).\n */\nfunction extensionOf(filename: string): string {\n const index = filename.lastIndexOf('.')\n if (index === -1) return 'tsx'\n return filename.slice(index + 1)\n}\n\n/**\n * Read the project root Metro hands us per-transform. Falls back to\n * `process.cwd()` only when the upstream harness doesn't set it (unit\n * tests, standalone). Metro's production pipeline always sets it.\n * @param args Metro transformer args.\n * @returns Absolute project root.\n */\nfunction projectRootOf(args: BabelTransformerArgs): string {\n const fromOptions = args.options?.projectRoot\n if (typeof fromOptions === 'string' && fromOptions.length > 0) return fromOptions\n return process.cwd()\n}\n\n/**\n * Whether a `.css` filename is the user's theme entry (the file\n * `withRnwindConfig` pointed us at via `RNWIND_CSS_ENTRY_FILE`).\n * Only the theme CSS should trigger a scheme rebuild — unrelated CSS\n * files in the project stay invisible to rnwind.\n * @param filename Absolute CSS path.\n * @returns Whether the file is the configured theme entry.\n */\nfunction isThemeCssEntry(filename: string): boolean {\n const cssEntry = process.env.RNWIND_CSS_ENTRY_FILE\n return typeof cssEntry === 'string' && cssEntry.length > 0 && cssEntry === filename\n}\n\n/**\n * Parse + run rnwind's JSX rewrite + regenerate source code. When\n * parsing or transformation fails, fall back to the original source —\n * we don't want a transient parse error to crash Metro for a file the\n * upstream might handle fine.\n * @param args Metro args; `src` is the original source text.\n * @returns Rewritten source text (with `className=` rewrites applied).\n */\nasync function rewriteSource(args: BabelTransformerArgs): Promise<string> {\n const ast = parseUserSource(args.src)\n if (!ast) return args.src\n\n const state = getRnwindState(projectRootOf(args))\n const extension = extensionOf(args.filename)\n const parsed = await state.parser.parseAtoms({ content: args.src, extension })\n\n warnUnknownClasses(args.src, parsed.candidates, parsed.atoms, args.filename)\n\n const classNamePrefixes = getClassNamePrefixes()\n const hostSources = getHostSources()\n const hostComponents = getHostComponents()\n if (parsed.atoms.size === 0) {\n state.builder.dropFile(args.filename)\n await state.builder.writeSchemes()\n transformAst(ast, {\n styleSpecifiers: [],\n gradientAtoms: parsed.gradientAtoms,\n hapticAtoms: parsed.hapticAtoms,\n classNamePrefixes,\n hostSources,\n hostComponents,\n })\n injectThemeSignatureImport(ast)\n return generateModule(ast).code\n }\n\n const { changed } = await state.builder.recordFile(args.filename, parsed.atoms, parsed.keyframes)\n if (changed) await state.builder.writeSchemes()\n\n transformAst(ast, {\n styleSpecifiers: STYLE_SPECIFIERS as unknown as readonly string[],\n gradientAtoms: parsed.gradientAtoms,\n hapticAtoms: parsed.hapticAtoms,\n classNamePrefixes,\n hostSources,\n hostComponents,\n })\n injectThemeSignatureImport(ast)\n return generateModule(ast).code\n}\n\n/**\n * Prepend `import 'rnwind/__generated/theme-signature'` to every\n * rnwind-transformed file. The resolver maps that specifier to the\n * user's theme CSS so Metro's dependency graph carries a real edge\n * from this JS file to the CSS. When the user edits `global.css`,\n * the CSS module's SHA1 changes, and Metro invalidates every JS file\n * holding this import — forcing them to re-transform with the new\n * theme. The `.css` branch in {@link transform} returns an empty\n * `export {}` module so the runtime cost is one extra `require()`.\n * @param ast Babel File AST to mutate in place.\n */\nfunction injectThemeSignatureImport(ast: File): void {\n const declaration = t.importDeclaration([], t.stringLiteral(THEME_SIGNATURE_MODULE))\n ast.program.body.unshift(declaration)\n}\n\n/**\n * Read the upstream transformer's `getCacheKey()` so our cache-key\n * contribution composes with — rather than replaces — whatever the\n * host framework wants to mix in.\n * @returns Upstream cache key, or `null` when no upstream exposes one.\n */\nfunction loadUpstreamCacheKey(): string | null {\n const upstream = loadUpstream() as (UpstreamTransformer & { getCacheKey?: () => string }) | null\n if (!upstream) return null\n try {\n return typeof upstream.getCacheKey === 'function' ? upstream.getCacheKey() : null\n } catch {\n return null\n }\n}\n\n/**\n * Invoke the upstream `babelTransformerPath` Metro originally had\n * configured. The path is read from `RNWIND_UPSTREAM_TRANSFORMER`,\n * which `withRnwindConfig` sets at Metro startup. When the env var is\n * unset (unit tests, standalone use), fall back to a typescript+jsx\n * parse.\n * @param args Metro's per-file args.\n * @returns Upstream transform result containing the post-babel AST.\n */\nasync function runUpstream(args: BabelTransformerArgs): Promise<BabelTransformerResult> {\n if (args.ast && !process.env[UPSTREAM_ENV]) return { ast: args.ast }\n const upstream = loadUpstream()\n if (upstream) return await Promise.resolve(upstream.transform(args))\n if (args.ast) return { ast: args.ast }\n return { ast: parseSource(args.src) }\n}\n\n/**\n * Lazily require the upstream transformer module. Cached after first\n * load so per-file overhead is one cache lookup.\n * @returns Upstream module, or null when env is unset.\n */\nfunction loadUpstream(): UpstreamTransformer | null {\n if (cachedUpstream) return cachedUpstream\n const upstreamPath = process.env[UPSTREAM_ENV]\n if (!upstreamPath || upstreamPath.length === 0) return null\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires\n const required = require(upstreamPath) as UpstreamTransformer | { default?: UpstreamTransformer }\n const upstream = (required as { default?: UpstreamTransformer }).default ?? (required as UpstreamTransformer)\n if (typeof upstream.transform !== 'function') return null\n cachedUpstream = upstream\n return upstream\n } catch (error) {\n // eslint-disable-next-line no-console\n if (process.env.RNWIND_DEBUG) console.error('rnwind: failed to load upstream transformer:', error)\n return null\n }\n}\n\n/**\n * Cheap guard — the file has to look JS/TS, live outside `node_modules`,\n * and mention `className=` before we spend AST cycles on it.\n *\n * Symlink awareness: monorepo workspaces (yarn / pnpm / bun workspaces)\n * symlink each package into the consumer's `node_modules/<name>`, so a\n * file from `packages/ui/src/Foo.tsx` ends up reaching the transformer\n * as `<root>/node_modules/ui/src/Foo.tsx`. The naïve `/node_modules/`\n * check would skip every workspace UI file. We `realpath` the filename\n * once and only bail when the resolved real path is ALSO under\n * node_modules — true third-party installs.\n * @param args Metro args.\n * @returns Whether the file might need the rnwind pass.\n */\nfunction isRewriteCandidate(args: BabelTransformerArgs): boolean {\n if (!/\\.(?:tsx|ts|jsx|js)$/i.test(args.filename)) return false\n // Case-insensitive so `<prefix>ClassName=` (e.g. `contentContainerClassName=`)\n // — which has a capital `C` and so doesn't contain the lowercase\n // `className=` — still routes the file through the rewrite pass.\n if (!/classname=/i.test(args.src)) return false\n if (!args.filename.includes('/node_modules/')) return true\n // node_modules in path → could be a workspace symlink; resolve it.\n try {\n return !realpathSync(args.filename).includes('/node_modules/')\n } catch {\n // realpath failed (broken symlink, missing file). Fall back to skipping.\n return false\n }\n}\n\n/**\n * Fallback parse when no upstream is configured AND Metro didn't hand\n * us an AST. Used by unit tests and standalone setups.\n * @param source Source text.\n * @returns Parsed Babel File.\n */\nfunction parseSource(source: string): File {\n return parse(source, { sourceType: 'module', plugins: ['typescript', 'jsx'] }) as unknown as File\n}\n\n/** Metro's babel transformer signature. */\nexport interface BabelTransformerArgs {\n filename: string\n src: string\n options: { projectRoot?: string; [key: string]: unknown }\n ast?: File\n plugins?: readonly unknown[]\n}\n\n/** Return shape Metro expects from a babel transformer. */\nexport interface BabelTransformerResult {\n ast: File\n metadata?: unknown\n}\n\n/**\n * rnwind's Metro babel transformer. Two phases per source file:\n *\n * 1. **Pre-process the source string before handing it to the upstream\n * babel pipeline.** babel-preset-expo / React's JSX transform run\n * inside the upstream and convert `<View className=\"...\"/>` into\n * `React.createElement(View, {className})`. If we walked the AST\n * AFTER the upstream, there'd be no JSX attributes left to\n * rewrite. So we parse, run our pass, regenerate code, and feed\n * THAT to the upstream as `src`.\n * 2. **Delegate to the upstream `babelTransformerPath`** (Expo's\n * default handles Flow stripping, expo-router macros, etc.).\n *\n * Skip both phases when the file isn't a JS/TS source under user\n * code, or doesn't mention `className=` — hand straight to upstream.\n * @param args Metro's per-file args.\n * @returns Mutated AST + metadata.\n */\nexport async function transform(args: BabelTransformerArgs): Promise<BabelTransformerResult> {\n // Short-circuit `.css` inputs: the theme CSS is pulled into the dep\n // graph as a sentinel (see `THEME_SIGNATURE_MODULE` in resolver.ts)\n // so Metro watches it and invalidates importers on edit, but the\n // file's CSS syntax can't go through a JS babel transformer.\n //\n // When the CSS being transformed IS the user's theme entry, we\n // piggyback on Metro's own file-watcher: Metro calls us here on\n // every CSS save; we trigger `onThemeChange` to rebuild parser +\n // rewrite scheme files with the new values. Metro's dep graph then\n // HMRs the regenerated `common.style.js` to the running app.\n //\n // Emitting the CSS content hash in the fake JS output is what makes\n // Metro propagate invalidation to downstream importers — constant\n // `export {}` bytes would never look changed and Metro would skip\n // the chain.\n if (args.filename.endsWith('.css')) {\n if (isThemeCssEntry(args.filename)) {\n try {\n await onThemeChange(projectRootOf(args))\n } catch {\n // CSS edit happened outside a configured project (e.g. tests).\n }\n }\n const themeHash = createHash('sha256').update(args.src).digest('hex').slice(0, 16)\n const stub = `export const __rnwindThemeHash = ${JSON.stringify(themeHash)};\\n`\n return { ast: parse(stub, { sourceType: 'module' }) as unknown as File }\n }\n if (!isRewriteCandidate(args)) {\n if (/\\.(?:tsx|ts|jsx|js)$/i.test(args.filename) && !args.filename.includes('/node_modules/')) {\n try {\n getRnwindState(projectRootOf(args)).builder.dropFile(args.filename)\n } catch {\n // State not configured (e.g. test). Nothing to drop.\n }\n }\n return runUpstream(args)\n }\n\n const rewrittenSource = await rewriteSource(args)\n return runUpstream({ ...args, src: rewrittenSource, ast: undefined })\n}\n\n/**\n * Metro's babel-transformer contract: a `getCacheKey()` export is\n * sampled per-file and mixed into the transform cache key. Returning\n * a string that includes the theme CSS content hash invalidates every\n * cached transform on every CSS edit — so the bundle rebuilds with\n * the new theme automatically on the next request.\n * @returns Cache-key segment that includes rnwind's current theme hash.\n */\nexport function getCacheKey(): string {\n const upstreamKey = loadUpstreamCacheKey()\n const ownKey = getRnwindCacheKey()\n return upstreamKey ? `${upstreamKey}|${ownKey}` : ownKey\n}\n\n/** Test-only — drop the cached upstream so a new env var picks up next call. */\nexport function __resetUpstreamCache(): void {\n cachedUpstream = null\n}\n"],"names":["parse","filterUnknownClassCandidates","state","getRnwindState","getClassNamePrefixes","getHostSources","getHostComponents","transformAst","STYLE_SPECIFIERS","t","THEME_SIGNATURE_MODULE","realpathSync","onThemeChange","createHash","getRnwindCacheKey"],"mappings":"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"}
1
+ {"version":3,"file":"transformer.cjs","sources":["../../../../src/metro/transformer.ts"],"sourcesContent":["import type { File } from '@babel/types'\nimport * as t from '@babel/types'\nimport { parse } from '@babel/parser'\nimport generate from '@babel/generator'\nimport { createHash } from 'node:crypto'\nimport { realpathSync } from 'node:fs'\nimport { getRnwindCacheKey, getRnwindState, getWrapModules, onThemeChange } from './state'\nimport { rewriteWrapImports } from './wrap-imports'\nimport { STYLE_SPECIFIERS, THEME_SIGNATURE_MODULE } from './resolver'\nimport { filterUnknownClassCandidates } from './warn-unknown-classes'\n\n/** The shape of the upstream module we delegate parsing/babel work to. */\ninterface UpstreamTransformer {\n transform: (args: BabelTransformerArgs) => Promise<BabelTransformerResult> | BabelTransformerResult\n}\n\n/** Env var that points at the upstream `babelTransformerPath` we override. */\nconst UPSTREAM_ENV = 'RNWIND_UPSTREAM_TRANSFORMER'\n\n/** Cached upstream module — required once, reused across every transform call. */\nlet cachedUpstream: UpstreamTransformer | null = null\n\nconst generateModule = (generate as unknown as { default?: typeof generate }).default ?? generate\n\n/**\n * Parse user source with the broad plugin set (Flow + JSX + TypeScript\n * + class properties). Permissive on purpose so we don't reject any\n * file the upstream could have handled. Returns `null` when parse\n * fails — caller falls back to the raw source string.\n * @param source Source text.\n * @returns Parsed AST, or null on parse failure.\n */\nfunction parseUserSource(source: string): File | null {\n try {\n return parse(source, {\n sourceType: 'unambiguous',\n allowReturnOutsideFunction: true,\n allowImportExportEverywhere: true,\n plugins: ['typescript', 'jsx'],\n }) as unknown as File\n } catch {\n try {\n return parse(source, {\n sourceType: 'unambiguous',\n allowReturnOutsideFunction: true,\n allowImportExportEverywhere: true,\n plugins: ['flow', 'jsx'],\n }) as unknown as File\n } catch {\n return null\n }\n }\n}\n\n/**\n * Print Tailwind-shaped candidates oxide picked up but the parser\n * could NOT compile — typo, missing custom utility, or class not in\n * the user's theme. Filtering by candidates that ALSO appear inside a\n * `className=\"…\"` literal eliminates false positives from imports,\n * comments, and JSX prop values.\n * @param source Original source text — searched for className literals.\n * @param candidates Every candidate oxide surfaced from the source.\n * @param atoms Successfully resolved atoms (keys are class names).\n * @param filename Source path, prefixed onto the warning.\n * @param features Feature-atom maps (gradient / haptic) — their names are\n * known classes even though they carry no RN style, so they're excluded\n * from the unknown-class warning.\n */\nfunction warnUnknownClasses(\n source: string,\n candidates: readonly string[],\n atoms: ReadonlyMap<string, unknown>,\n filename: string,\n features: ReadonlyArray<ReadonlyMap<string, unknown>> = [],\n): void {\n // Feature atoms (gradient / haptic) resolve to no RN style, so they're\n // absent from `atoms` — but they're NOT unknown. Fold their names into\n // the known set so `active:haptic-rigid` etc. don't warn at build time.\n const known = new Set(atoms.keys())\n for (const map of features) for (const name of map.keys()) known.add(name)\n const unknown = filterUnknownClassCandidates(source, candidates, known)\n if (unknown.length === 0) return\n // eslint-disable-next-line no-console\n console.warn(`rnwind: unknown class${unknown.length > 1 ? 'es' : ''} in ${filename}: ${unknown.join(', ')}`)\n}\n\n/**\n * Extract the bare extension for oxide / internal switches.\n * @param filename Absolute path.\n * @returns Extension without the leading dot (`tsx` / `ts` / `js` / `jsx`).\n */\nfunction extensionOf(filename: string): string {\n const index = filename.lastIndexOf('.')\n if (index === -1) return 'tsx'\n return filename.slice(index + 1)\n}\n\n/**\n * Read the project root Metro hands us per-transform. Falls back to\n * `process.cwd()` only when the upstream harness doesn't set it (unit\n * tests, standalone). Metro's production pipeline always sets it.\n * @param args Metro transformer args.\n * @returns Absolute project root.\n */\nfunction projectRootOf(args: BabelTransformerArgs): string {\n const fromOptions = args.options?.projectRoot\n if (typeof fromOptions === 'string' && fromOptions.length > 0) return fromOptions\n return process.cwd()\n}\n\n/**\n * Whether a `.css` filename is the user's theme entry (the file\n * `withRnwindConfig` pointed us at via `RNWIND_CSS_ENTRY_FILE`).\n * Only the theme CSS should trigger a scheme rebuild — unrelated CSS\n * files in the project stay invisible to rnwind.\n * @param filename Absolute CSS path.\n * @returns Whether the file is the configured theme entry.\n */\nfunction isThemeCssEntry(filename: string): boolean {\n const cssEntry = process.env.RNWIND_CSS_ENTRY_FILE\n return typeof cssEntry === 'string' && cssEntry.length > 0 && cssEntry === filename\n}\n\n/**\n * Wrap host imports + compile any className literals, then regenerate\n * source. Two paths:\n * - **className present**: oxide-scan the file, record its atoms into\n * the union, and inject the generated-style + theme-signature\n * side-effect imports so the runtime registries populate.\n * - **import-only** (a `{...rest}` forwarder or a leaf with no literal\n * `className=`): just wrap the host imports so a forwarded className\n * still resolves at render — no oxide scan, no injected imports.\n *\n * On parse failure, fall back to the original source — a transient parse\n * error shouldn't crash Metro for a file the upstream might handle fine.\n * @param args Metro args; `src` is the original source text.\n * @returns Rewritten source text.\n */\nasync function rewriteSource(args: BabelTransformerArgs): Promise<string> {\n const ast = parseUserSource(args.src)\n if (!ast) return args.src\n\n // Wrap host component imports so `<View className=…>` resolves at render\n // through the runtime `wrap` (works for literal, spread, and forwarded\n // classNames alike). No JSX is rewritten here.\n const wrapped = rewriteWrapImports(ast, getWrapModules())\n\n if (!/classname=/i.test(args.src)) {\n // Import-only file: nothing to compile. Drop any stale atom\n // contribution (className may have just been removed) and emit the\n // wrapped imports — or the untouched source when nothing wrapped.\n dropFileSafely(args.filename, projectRootOf(args))\n return wrapped ? generateModule(ast).code : args.src\n }\n\n const state = getRnwindState(projectRootOf(args))\n const extension = extensionOf(args.filename)\n const parsed = await state.parser.parseAtoms({ content: args.src, extension })\n\n warnUnknownClasses(args.src, parsed.candidates, parsed.atoms, args.filename, [parsed.gradientAtoms, parsed.hapticAtoms])\n\n if (parsed.atoms.size === 0) {\n state.builder.dropFile(args.filename)\n await state.builder.writeSchemes()\n injectThemeSignatureImport(ast)\n return generateModule(ast).code\n }\n\n const literals = collectClassNameLiterals(ast)\n const { changed } = await state.builder.recordFile(args.filename, parsed.atoms, parsed.keyframes, literals)\n if (changed) await state.builder.writeSchemes()\n\n injectSideEffectImports(ast, STYLE_SPECIFIERS)\n injectThemeSignatureImport(ast)\n return generateModule(ast).code\n}\n\n/**\n * Drop a file's union contribution, swallowing the \"state not configured\"\n * error unit tests hit when they call the transformer without\n * `configureRnwindState`.\n * @param filename Absolute source path.\n * @param projectRoot Project root for state lookup.\n */\nfunction dropFileSafely(filename: string, projectRoot: string): void {\n try {\n getRnwindState(projectRoot).builder.dropFile(filename)\n } catch {\n // State not configured (standalone/unit test). Nothing to drop.\n }\n}\n\n/**\n * Whether a JSX attribute names a className-style prop (`className` or\n * any `<prefix>ClassName`).\n * @param node JSX attribute node.\n * @returns True when the attribute is a className prop.\n */\nfunction isClassNameAttribute(node: t.JSXAttribute): boolean {\n if (!t.isJSXIdentifier(node.name)) return false\n const {name} = node.name\n return name === 'className' || name.endsWith('ClassName')\n}\n\n/**\n * Pull static string literals out of a className expression. Handles a\n * bare string, a no-substitution template, and the branches of a\n * ternary / `&&` (so `cond ? 'a' : 'b'` and `flag && 'x'` both register\n * their literals). Dynamic interpolations are skipped — they resolve via\n * the runtime atom path.\n * @param expr Expression inside a `className={...}` container.\n * @param out Accumulator for discovered literals.\n */\nfunction collectLiteralsFromExpression(expr: t.Expression | t.JSXEmptyExpression | null | undefined, out: string[]): void {\n if (!expr) return\n if (t.isStringLiteral(expr)) {\n out.push(expr.value)\n return\n }\n if (t.isTemplateLiteral(expr) && expr.expressions.length === 0 && expr.quasis.length === 1) {\n const cooked = expr.quasis[0]?.value.cooked\n if (typeof cooked === 'string') out.push(cooked)\n return\n }\n if (t.isConditionalExpression(expr)) {\n collectLiteralsFromExpression(expr.consequent, out)\n collectLiteralsFromExpression(expr.alternate, out)\n return\n }\n if (t.isLogicalExpression(expr)) {\n collectLiteralsFromExpression(expr.right as t.Expression, out)\n }\n}\n\n/** AST node keys the literal walk skips — position / comment metadata. */\nconst SKIP_WALK_KEYS = new Set(['type', 'loc', 'start', 'end', 'range', 'leadingComments', 'trailingComments', 'innerComments'])\n\n/**\n * Collect the static literals from one className JSX attribute into the\n * dedup accumulator.\n * @param attribute The (already className-matched) JSX attribute.\n * @param seen Dedup set of literals already collected.\n * @param out Ordered accumulator.\n */\nfunction collectAttributeLiterals(attribute: t.JSXAttribute, seen: Set<string>, out: string[]): void {\n const { value } = attribute\n const found: string[] = []\n if (t.isStringLiteral(value)) found.push(value.value)\n else if (t.isJSXExpressionContainer(value)) collectLiteralsFromExpression(value.expression, found)\n for (const literal of found) {\n if (seen.has(literal)) continue\n seen.add(literal)\n out.push(literal)\n }\n}\n\n/**\n * Walk the AST for every `className=` / `<prefix>ClassName=` literal so\n * the builder can pre-merge each into a per-scheme molecule. A generic\n * node walk (no scope build) keeps it cheap; only JSX attribute nodes do\n * any work.\n * @param ast Parsed Babel file.\n * @returns Distinct literal className strings, in first-seen order.\n */\nfunction collectClassNameLiterals(ast: File): readonly string[] {\n const out: string[] = []\n const seen = new Set<string>()\n const visit = (node: unknown): void => {\n if (!node || typeof node !== 'object') return\n if (Array.isArray(node)) {\n for (const child of node) visit(child)\n return\n }\n const typed = node as { type?: string; [key: string]: unknown }\n if (typeof typed.type !== 'string') return\n if (typed.type === 'JSXAttribute' && isClassNameAttribute(node as t.JSXAttribute)) {\n collectAttributeLiterals(node as t.JSXAttribute, seen, out)\n }\n for (const key in typed) {\n if (SKIP_WALK_KEYS.has(key)) continue\n visit(typed[key])\n }\n }\n visit(ast.program)\n return out\n}\n\n/**\n * Prepend side-effect imports (`import '<spec>'`) so the generated\n * per-scheme style + manifest modules load — registering this file's\n * atoms / molecules / features into the runtime registries the wrapper's\n * `resolve` reads.\n * @param ast Babel File AST to mutate in place.\n * @param specifiers Module specifiers to side-effect-import.\n */\nfunction injectSideEffectImports(ast: File, specifiers: readonly string[]): void {\n for (const specifier of specifiers) {\n ast.program.body.unshift(t.importDeclaration([], t.stringLiteral(specifier)))\n }\n}\n\n/**\n * Prepend `import 'rnwind/__generated/theme-signature'` to every\n * rnwind-transformed file. The resolver maps that specifier to the\n * user's theme CSS so Metro's dependency graph carries a real edge\n * from this JS file to the CSS. When the user edits `global.css`,\n * the CSS module's SHA1 changes, and Metro invalidates every JS file\n * holding this import — forcing them to re-transform with the new\n * theme. The `.css` branch in {@link transform} returns an empty\n * `export {}` module so the runtime cost is one extra `require()`.\n * @param ast Babel File AST to mutate in place.\n */\nfunction injectThemeSignatureImport(ast: File): void {\n const declaration = t.importDeclaration([], t.stringLiteral(THEME_SIGNATURE_MODULE))\n ast.program.body.unshift(declaration)\n}\n\n/**\n * Read the upstream transformer's `getCacheKey()` so our cache-key\n * contribution composes with — rather than replaces — whatever the\n * host framework wants to mix in.\n * @returns Upstream cache key, or `null` when no upstream exposes one.\n */\nfunction loadUpstreamCacheKey(): string | null {\n const upstream = loadUpstream() as (UpstreamTransformer & { getCacheKey?: () => string }) | null\n if (!upstream) return null\n try {\n return typeof upstream.getCacheKey === 'function' ? upstream.getCacheKey() : null\n } catch {\n return null\n }\n}\n\n/**\n * Invoke the upstream `babelTransformerPath` Metro originally had\n * configured. The path is read from `RNWIND_UPSTREAM_TRANSFORMER`,\n * which `withRnwindConfig` sets at Metro startup. When the env var is\n * unset (unit tests, standalone use), fall back to a typescript+jsx\n * parse.\n * @param args Metro's per-file args.\n * @returns Upstream transform result containing the post-babel AST.\n */\nasync function runUpstream(args: BabelTransformerArgs): Promise<BabelTransformerResult> {\n if (args.ast && !process.env[UPSTREAM_ENV]) return { ast: args.ast }\n const upstream = loadUpstream()\n if (upstream) return await Promise.resolve(upstream.transform(args))\n if (args.ast) return { ast: args.ast }\n return { ast: parseSource(args.src) }\n}\n\n/**\n * Lazily require the upstream transformer module. Cached after first\n * load so per-file overhead is one cache lookup.\n * @returns Upstream module, or null when env is unset.\n */\nfunction loadUpstream(): UpstreamTransformer | null {\n if (cachedUpstream) return cachedUpstream\n const upstreamPath = process.env[UPSTREAM_ENV]\n if (!upstreamPath || upstreamPath.length === 0) return null\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires\n const required = require(upstreamPath) as UpstreamTransformer | { default?: UpstreamTransformer }\n const upstream = (required as { default?: UpstreamTransformer }).default ?? (required as UpstreamTransformer)\n if (typeof upstream.transform !== 'function') return null\n cachedUpstream = upstream\n return upstream\n } catch (error) {\n // eslint-disable-next-line no-console\n if (process.env.RNWIND_DEBUG) console.error('rnwind: failed to load upstream transformer:', error)\n return null\n }\n}\n\n/**\n * Cheap guard — the file has to look JS/TS, live outside `node_modules`,\n * and mention `className=` before we spend AST cycles on it.\n *\n * Symlink awareness: monorepo workspaces (yarn / pnpm / bun workspaces)\n * symlink each package into the consumer's `node_modules/<name>`, so a\n * file from `packages/ui/src/Foo.tsx` ends up reaching the transformer\n * as `<root>/node_modules/ui/src/Foo.tsx`. The naïve `/node_modules/`\n * check would skip every workspace UI file. We `realpath` the filename\n * once and only bail when the resolved real path is ALSO under\n * node_modules — true third-party installs.\n * @param args Metro args.\n * @returns Whether the file might need the rnwind pass.\n */\nfunction isRewriteCandidate(args: BabelTransformerArgs): boolean {\n if (!/\\.(?:tsx|ts|jsx|js)$/i.test(args.filename)) return false\n // Process the file when it either:\n // - carries a `className=` / `<prefix>ClassName=` literal (case-\n // insensitive — `contentContainerClassName=` has a capital C), or\n // - spreads props (`{...rest}`) onto a host from a wrap-module, where a\n // forwarded className must still get its import wrapped (no literal\n // appears in this file). A style-less `<View/>` with neither is left\n // alone so it never pays for an unused wrapper.\n const hasClassName = /classname=/i.test(args.src)\n const isForwarder = /\\{\\s*\\.\\.\\./.test(args.src) && mentionsWrapModule(args.src)\n if (!hasClassName && !isForwarder) return false\n if (!args.filename.includes('/node_modules/')) return true\n // node_modules in path → could be a workspace symlink; resolve it.\n try {\n return !realpathSync(args.filename).includes('/node_modules/')\n } catch {\n // realpath failed (broken symlink, missing file). Fall back to skipping.\n return false\n }\n}\n\n/**\n * Cheap pre-parse check: does the source import from any configured\n * wrap-module? A quoted specifier match is enough — `rewriteWrapImports`\n * re-verifies precisely on the AST, so a false positive only costs a\n * no-op parse.\n * @param source Source text.\n * @returns True when a wrap-module specifier appears in the source.\n */\nfunction mentionsWrapModule(source: string): boolean {\n for (const moduleName of getWrapModules().keys()) {\n if (source.includes(`'${moduleName}'`) || source.includes(`\"${moduleName}\"`)) return true\n }\n return false\n}\n\n/**\n * Fallback parse when no upstream is configured AND Metro didn't hand\n * us an AST. Used by unit tests and standalone setups.\n * @param source Source text.\n * @returns Parsed Babel File.\n */\nfunction parseSource(source: string): File {\n return parse(source, { sourceType: 'module', plugins: ['typescript', 'jsx'] }) as unknown as File\n}\n\n/** Metro's babel transformer signature. */\nexport interface BabelTransformerArgs {\n filename: string\n src: string\n options: { projectRoot?: string; [key: string]: unknown }\n ast?: File\n plugins?: readonly unknown[]\n}\n\n/** Return shape Metro expects from a babel transformer. */\nexport interface BabelTransformerResult {\n ast: File\n metadata?: unknown\n}\n\n/**\n * rnwind's Metro babel transformer. Two phases per source file:\n *\n * 1. **Pre-process the source string before handing it to the upstream\n * babel pipeline.** babel-preset-expo / React's JSX transform run\n * inside the upstream and convert `<View className=\"...\"/>` into\n * `React.createElement(View, {className})`. If we walked the AST\n * AFTER the upstream, there'd be no JSX attributes left to\n * rewrite. So we parse, run our pass, regenerate code, and feed\n * THAT to the upstream as `src`.\n * 2. **Delegate to the upstream `babelTransformerPath`** (Expo's\n * default handles Flow stripping, expo-router macros, etc.).\n *\n * Skip both phases when the file isn't a JS/TS source under user\n * code, or doesn't mention `className=` — hand straight to upstream.\n * @param args Metro's per-file args.\n * @returns Mutated AST + metadata.\n */\nexport async function transform(args: BabelTransformerArgs): Promise<BabelTransformerResult> {\n // Short-circuit `.css` inputs: the theme CSS is pulled into the dep\n // graph as a sentinel (see `THEME_SIGNATURE_MODULE` in resolver.ts)\n // so Metro watches it and invalidates importers on edit, but the\n // file's CSS syntax can't go through a JS babel transformer.\n //\n // When the CSS being transformed IS the user's theme entry, we\n // piggyback on Metro's own file-watcher: Metro calls us here on\n // every CSS save; we trigger `onThemeChange` to rebuild parser +\n // rewrite scheme files with the new values. Metro's dep graph then\n // HMRs the regenerated `common.style.js` to the running app.\n //\n // Emitting the CSS content hash in the fake JS output is what makes\n // Metro propagate invalidation to downstream importers — constant\n // `export {}` bytes would never look changed and Metro would skip\n // the chain.\n if (args.filename.endsWith('.css')) {\n if (isThemeCssEntry(args.filename)) {\n try {\n await onThemeChange(projectRootOf(args))\n } catch {\n // CSS edit happened outside a configured project (e.g. tests).\n }\n }\n const themeHash = createHash('sha256').update(args.src).digest('hex').slice(0, 16)\n const stub = `export const __rnwindThemeHash = ${JSON.stringify(themeHash)};\\n`\n return { ast: parse(stub, { sourceType: 'module' }) as unknown as File }\n }\n if (!isRewriteCandidate(args)) {\n if (/\\.(?:tsx|ts|jsx|js)$/i.test(args.filename) && !args.filename.includes('/node_modules/')) {\n try {\n getRnwindState(projectRootOf(args)).builder.dropFile(args.filename)\n } catch {\n // State not configured (e.g. test). Nothing to drop.\n }\n }\n return runUpstream(args)\n }\n\n const rewrittenSource = await rewriteSource(args)\n return runUpstream({ ...args, src: rewrittenSource, ast: undefined })\n}\n\n/**\n * Metro's babel-transformer contract: a `getCacheKey()` export is\n * sampled per-file and mixed into the transform cache key. Returning\n * a string that includes the theme CSS content hash invalidates every\n * cached transform on every CSS edit — so the bundle rebuilds with\n * the new theme automatically on the next request.\n * @returns Cache-key segment that includes rnwind's current theme hash.\n */\nexport function getCacheKey(): string {\n const upstreamKey = loadUpstreamCacheKey()\n const ownKey = getRnwindCacheKey()\n return upstreamKey ? `${upstreamKey}|${ownKey}` : ownKey\n}\n\n/** Test-only — drop the cached upstream so a new env var picks up next call. */\nexport function __resetUpstreamCache(): void {\n cachedUpstream = null\n}\n"],"names":["parse","filterUnknownClassCandidates","rewriteWrapImports","getWrapModules","state","getRnwindState","STYLE_SPECIFIERS","t","THEME_SIGNATURE_MODULE","realpathSync","onThemeChange","createHash","getRnwindCacheKey"],"mappings":"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"}
@@ -149,7 +149,7 @@ function withRnwindConfig(metroConfig, options) {
149
149
  const cssEntry = path.isAbsolute(options.cssEntryFile) ? options.cssEntryFile : path.resolve(projectRoot, options.cssEntryFile);
150
150
  node_fs.mkdirSync(cacheDir, { recursive: true });
151
151
  const watchFolders = (metroConfig.watchFolders ?? []).filter((p) => typeof p === 'string' && p.length > 0);
152
- state.configureRnwindState(cssEntry, cacheDir, watchFolders, options.classNamePrefixes, options.hostSources, options.hostComponents);
152
+ state.configureRnwindState(cssEntry, cacheDir, watchFolders, options.wrapModules);
153
153
  // Warm the state eagerly (in the Metro master process) so oxide's
154
154
  // Scanner walks every project source (and every monorepo
155
155
  // watch-folder) ONCE and the manifest + scheme files hold the
@@ -182,7 +182,7 @@ function withRnwindConfig(metroConfig, options) {
182
182
  if (options.dtsFile !== false) {
183
183
  const dtsPath = options.dtsFile ?? path.resolve(projectRoot, 'rnwind-types.d.ts');
184
184
  const schemes = discoverSchemes(cssEntry, projectRoot);
185
- dts.writeDtsFile(dtsPath, schemes, options.classNamePrefixes);
185
+ dts.writeDtsFile(dtsPath, schemes);
186
186
  }
187
187
  // Watch the theme CSS. On edit, we rewrite scheme files AND touch
188
188
  // mtime on every transformed source file so Metro invalidates them