@tamagui/static 2.0.0-rc.3 → 2.0.0-rc.30

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 (140) hide show
  1. package/dist/checkDeps.cjs +164 -31
  2. package/dist/exports.cjs +3 -0
  3. package/dist/extractor/bundle.cjs +72 -35
  4. package/dist/extractor/bundleConfig.cjs +219 -35
  5. package/dist/extractor/createExtractor.cjs +170 -28
  6. package/dist/extractor/detectModuleFormat.cjs +49 -0
  7. package/dist/extractor/esbuildTsconfigPaths.cjs +3 -1
  8. package/dist/extractor/extractToClassNames.cjs +7 -5
  9. package/dist/extractor/extractToNative.cjs +7 -8
  10. package/dist/extractor/loadTamagui.cjs +1 -1
  11. package/dist/getPragmaOptions.cjs +7 -3
  12. package/dist/index.js +26 -16
  13. package/dist/registerRequire.cjs +23 -14
  14. package/package.json +26 -22
  15. package/src/checkDeps.ts +305 -68
  16. package/src/exports.ts +1 -0
  17. package/src/extractor/bundle.ts +140 -37
  18. package/src/extractor/bundleConfig.ts +435 -61
  19. package/src/extractor/createExtractor.ts +261 -41
  20. package/src/extractor/detectModuleFormat.ts +42 -0
  21. package/src/extractor/esbuildTsconfigPaths.ts +6 -1
  22. package/src/extractor/extractToClassNames.ts +15 -9
  23. package/src/extractor/extractToNative.ts +32 -25
  24. package/src/extractor/loadTamagui.ts +2 -2
  25. package/src/getPragmaOptions.ts +6 -1
  26. package/src/registerRequire.ts +40 -8
  27. package/types/checkDeps.d.ts.map +1 -1
  28. package/types/exports.d.ts +1 -0
  29. package/types/exports.d.ts.map +1 -1
  30. package/types/extractor/bundle.d.ts +83 -1
  31. package/types/extractor/bundle.d.ts.map +1 -1
  32. package/types/extractor/bundleConfig.d.ts +15 -2
  33. package/types/extractor/bundleConfig.d.ts.map +1 -1
  34. package/types/extractor/createExtractor.d.ts.map +1 -1
  35. package/types/extractor/detectModuleFormat.d.ts +5 -0
  36. package/types/extractor/detectModuleFormat.d.ts.map +1 -0
  37. package/types/extractor/esbuildTsconfigPaths.d.ts +8 -0
  38. package/types/extractor/esbuildTsconfigPaths.d.ts.map +1 -1
  39. package/types/extractor/extractToClassNames.d.ts.map +1 -1
  40. package/types/extractor/extractToNative.d.ts.map +1 -1
  41. package/types/getPragmaOptions.d.ts.map +1 -1
  42. package/types/registerRequire.d.ts.map +1 -1
  43. package/dist/check-dep-versions.js +0 -389
  44. package/dist/check-dep-versions.js.map +0 -6
  45. package/dist/checkDeps.js +0 -60
  46. package/dist/checkDeps.js.map +0 -6
  47. package/dist/constants.js +0 -34
  48. package/dist/constants.js.map +0 -6
  49. package/dist/exports.js +0 -34
  50. package/dist/exports.js.map +0 -6
  51. package/dist/extractor/accessSafe.js +0 -47
  52. package/dist/extractor/accessSafe.js.map +0 -6
  53. package/dist/extractor/babelParse.js +0 -59
  54. package/dist/extractor/babelParse.js.map +0 -6
  55. package/dist/extractor/buildClassName.js +0 -72
  56. package/dist/extractor/buildClassName.js.map +0 -6
  57. package/dist/extractor/bundle.js +0 -135
  58. package/dist/extractor/bundle.js.map +0 -6
  59. package/dist/extractor/bundleConfig.js +0 -352
  60. package/dist/extractor/bundleConfig.js.map +0 -6
  61. package/dist/extractor/concatClassName.js +0 -69
  62. package/dist/extractor/concatClassName.js.map +0 -6
  63. package/dist/extractor/createEvaluator.js +0 -66
  64. package/dist/extractor/createEvaluator.js.map +0 -6
  65. package/dist/extractor/createExtractor.js +0 -1215
  66. package/dist/extractor/createExtractor.js.map +0 -6
  67. package/dist/extractor/createLogger.js +0 -32
  68. package/dist/extractor/createLogger.js.map +0 -6
  69. package/dist/extractor/ensureImportingConcat.js +0 -50
  70. package/dist/extractor/ensureImportingConcat.js.map +0 -6
  71. package/dist/extractor/errors.js +0 -22
  72. package/dist/extractor/errors.js.map +0 -6
  73. package/dist/extractor/esbuildAliasPlugin.js +0 -36
  74. package/dist/extractor/esbuildAliasPlugin.js.map +0 -6
  75. package/dist/extractor/esbuildTsconfigPaths.js +0 -79
  76. package/dist/extractor/esbuildTsconfigPaths.js.map +0 -6
  77. package/dist/extractor/evaluateAstNode.js +0 -99
  78. package/dist/extractor/evaluateAstNode.js.map +0 -6
  79. package/dist/extractor/extractHelpers.js +0 -108
  80. package/dist/extractor/extractHelpers.js.map +0 -6
  81. package/dist/extractor/extractMediaStyle.js +0 -123
  82. package/dist/extractor/extractMediaStyle.js.map +0 -6
  83. package/dist/extractor/extractToClassNames.js +0 -351
  84. package/dist/extractor/extractToClassNames.js.map +0 -6
  85. package/dist/extractor/extractToNative.js +0 -286
  86. package/dist/extractor/extractToNative.js.map +0 -6
  87. package/dist/extractor/findTopmostFunction.js +0 -32
  88. package/dist/extractor/findTopmostFunction.js.map +0 -6
  89. package/dist/extractor/generatedUid.js +0 -42
  90. package/dist/extractor/generatedUid.js.map +0 -6
  91. package/dist/extractor/getPrefixLogs.js +0 -24
  92. package/dist/extractor/getPrefixLogs.js.map +0 -6
  93. package/dist/extractor/getPropValueFromAttributes.js +0 -65
  94. package/dist/extractor/getPropValueFromAttributes.js.map +0 -6
  95. package/dist/extractor/getSourceModule.js +0 -62
  96. package/dist/extractor/getSourceModule.js.map +0 -6
  97. package/dist/extractor/getStaticBindingsForScope.js +0 -145
  98. package/dist/extractor/getStaticBindingsForScope.js.map +0 -6
  99. package/dist/extractor/getTamaguiConfigPathFromOptionsConfig.js +0 -32
  100. package/dist/extractor/getTamaguiConfigPathFromOptionsConfig.js.map +0 -6
  101. package/dist/extractor/hoistClassNames.js +0 -63
  102. package/dist/extractor/hoistClassNames.js.map +0 -6
  103. package/dist/extractor/literalToAst.js +0 -90
  104. package/dist/extractor/literalToAst.js.map +0 -6
  105. package/dist/extractor/loadFile.js +0 -14
  106. package/dist/extractor/loadFile.js.map +0 -6
  107. package/dist/extractor/loadTamagui.js +0 -306
  108. package/dist/extractor/loadTamagui.js.map +0 -6
  109. package/dist/extractor/logLines.js +0 -30
  110. package/dist/extractor/logLines.js.map +0 -6
  111. package/dist/extractor/normalizeTernaries.js +0 -61
  112. package/dist/extractor/normalizeTernaries.js.map +0 -6
  113. package/dist/extractor/propsToFontFamilyCache.js +0 -33
  114. package/dist/extractor/propsToFontFamilyCache.js.map +0 -6
  115. package/dist/extractor/regenerateConfig.js +0 -123
  116. package/dist/extractor/regenerateConfig.js.map +0 -6
  117. package/dist/extractor/removeUnusedHooks.js +0 -72
  118. package/dist/extractor/removeUnusedHooks.js.map +0 -6
  119. package/dist/extractor/timer.js +0 -38
  120. package/dist/extractor/timer.js.map +0 -6
  121. package/dist/extractor/validHTMLAttributes.js +0 -72
  122. package/dist/extractor/validHTMLAttributes.js.map +0 -6
  123. package/dist/extractor/watchTamaguiConfig.js +0 -57
  124. package/dist/extractor/watchTamaguiConfig.js.map +0 -6
  125. package/dist/getPragmaOptions.js +0 -46
  126. package/dist/getPragmaOptions.js.map +0 -6
  127. package/dist/helpers/memoize.js +0 -33
  128. package/dist/helpers/memoize.js.map +0 -6
  129. package/dist/helpers/requireTamaguiCore.js +0 -30
  130. package/dist/helpers/requireTamaguiCore.js.map +0 -6
  131. package/dist/registerRequire.js +0 -100
  132. package/dist/registerRequire.js.map +0 -6
  133. package/dist/server.js +0 -58
  134. package/dist/server.js.map +0 -6
  135. package/dist/setup.js +0 -1
  136. package/dist/setup.js.map +0 -6
  137. package/dist/types.js +0 -14
  138. package/dist/types.js.map +0 -6
  139. package/dist/worker.js +0 -72
  140. package/dist/worker.js.map +0 -6
@@ -1,7 +1,8 @@
1
- import { basename, dirname, join } from 'node:path'
1
+ import { readFileSync } from 'node:fs'
2
2
  import esbuild from 'esbuild'
3
3
  import * as FS from 'fs-extra'
4
4
  import type { TamaguiPlatform } from '../types'
5
+ import { detectModuleFormat } from './detectModuleFormat'
5
6
  import { esbuildAliasPlugin } from './esbuildAliasPlugin'
6
7
  import { resolveWebOrNativeSpecificEntry } from './loadTamagui'
7
8
  import { TsconfigPathsPlugin } from './esbuildTsconfigPaths'
@@ -63,11 +64,23 @@ function getESBuildConfig(
63
64
  ? entryPoints
64
65
  : entryPoints.map(resolveWebOrNativeSpecificEntry)
65
66
 
67
+ // detect format from entry points if not explicitly provided by caller
68
+ const detectedFormat = options.format || detectEntryFormat(resolvedEntryPoints[0])
69
+
66
70
  const res: esbuild.BuildOptions = {
67
71
  bundle: true,
68
72
  entryPoints: resolvedEntryPoints,
69
- format: 'cjs',
70
- target: 'node20',
73
+ format: detectedFormat,
74
+ // for ESM: prefer "module" field for resolution, add require() shim for bundled CJS deps
75
+ ...(detectedFormat === 'esm'
76
+ ? {
77
+ mainFields: ['module', 'main'],
78
+ banner: {
79
+ js: 'import { createRequire as __cr } from "module"; const require = __cr(import.meta.url);',
80
+ },
81
+ }
82
+ : {}),
83
+ target: 'node24',
71
84
  jsx: 'transform',
72
85
  jsxFactory: 'react',
73
86
  allowOverwrite: true,
@@ -92,38 +105,126 @@ function getESBuildConfig(
92
105
  plugins: [
93
106
  TsconfigPathsPlugin(),
94
107
 
108
+ // handle ESM-only features that can't be used with CJS output
109
+ {
110
+ name: 'handle-esm-features',
111
+ setup(build) {
112
+ // only apply transforms for CJS output - ESM supports these natively
113
+ const isCjs =
114
+ build.initialOptions.format === 'cjs' || !build.initialOptions.format
115
+
116
+ build.onLoad({ filter: /\.(ts|tsx|js|jsx|mjs)$/ }, (args) => {
117
+ // skip if ESM output - import.meta and top-level await work natively
118
+ if (!isCjs) {
119
+ return null
120
+ }
121
+
122
+ // skip most node_modules
123
+ if (args.path.includes('node_modules') && !args.path.includes('@tamagui')) {
124
+ return null
125
+ }
126
+
127
+ let contents = readFileSync(args.path, 'utf8')
128
+ let modified = false
129
+
130
+ // transform import.meta.env -> process.env (Vite-style env vars)
131
+ if (contents.includes('import.meta.env')) {
132
+ contents = contents.replace(/import\.meta\.env/g, 'process.env')
133
+ modified = true
134
+ }
135
+
136
+ // transform import.meta.url -> "" (not needed for static extraction)
137
+ if (contents.includes('import.meta.url')) {
138
+ contents = contents.replace(/import\.meta\.url/g, '""')
139
+ modified = true
140
+ }
141
+
142
+ // transform import.meta.main -> false
143
+ if (contents.includes('import.meta.main')) {
144
+ contents = contents.replace(/import\.meta\.main/g, 'false')
145
+ modified = true
146
+ }
147
+
148
+ // stub files with top-level await - they're typically runtime-only
149
+ if (
150
+ /^\s*(?:const|let|var|export)\s+[^=]*=\s*await\b/m.test(contents) ||
151
+ /^await\s/m.test(contents)
152
+ ) {
153
+ if (process.env.DEBUG?.startsWith('tamagui')) {
154
+ console.info(`[tamagui] stubbing file with top-level await: ${args.path}`)
155
+ }
156
+ return {
157
+ contents: `// stubbed - contains top-level await\nmodule.exports = {}`,
158
+ loader: 'js',
159
+ }
160
+ }
161
+
162
+ if (modified) {
163
+ return {
164
+ contents,
165
+ loader: args.path.endsWith('.tsx')
166
+ ? 'tsx'
167
+ : args.path.endsWith('.ts')
168
+ ? 'ts'
169
+ : args.path.endsWith('.jsx')
170
+ ? 'jsx'
171
+ : 'js',
172
+ }
173
+ }
174
+
175
+ return null
176
+ })
177
+ },
178
+ },
179
+
95
180
  {
96
181
  name: 'external',
97
182
  setup(build) {
98
- build.onResolve({ filter: /@tamagui\/core/ }, (args) => {
183
+ const proxyWormPath = require.resolve('@tamagui/proxy-worm')
184
+
185
+ // only externalize @tamagui/core and @tamagui/web - these are provided at runtime
186
+ // other @tamagui/* packages (like @tamagui/config/v3) must be bundled in to avoid
187
+ // ESM race conditions when multiple threads require() them concurrently
188
+ build.onResolve({ filter: /^@tamagui\/(core|web)$/ }, (args) => {
189
+ if (args.kind === 'entry-point') {
190
+ return null
191
+ }
99
192
  return {
100
- path: platform === 'native' ? '@tamagui/core/native' : '@tamagui/core',
193
+ path: platform === 'native' ? '@tamagui/core/native' : args.path,
101
194
  external: true,
102
195
  }
103
196
  })
104
- build.onResolve({ filter: /react-native\/package.json$/ }, (args) => {
197
+
198
+ build.onResolve({ filter: /react-native\/package.json$/ }, () => {
105
199
  return {
106
200
  path: 'react-native/package.json',
107
201
  external: true,
108
202
  }
109
203
  })
110
- build.onResolve({ filter: /@tamagui\/web/ }, (args) => {
204
+
205
+ build.onResolve({ filter: /^(react-native|react-native\/.*)$/ }, () => {
111
206
  return {
112
- path: platform === 'native' ? '@tamagui/core/native' : '@tamagui/core',
207
+ path: '@tamagui/react-native-web-lite',
113
208
  external: true,
114
209
  }
115
210
  })
116
211
 
117
- build.onResolve({ filter: /^(react-native|react-native\/.*)$/ }, (args) => {
212
+ build.onResolve({ filter: /^react-native-reanimated(?:\/.*)?$/ }, () => {
118
213
  return {
119
- path: '@tamagui/react-native-web-lite',
120
- external: true,
214
+ path: proxyWormPath,
121
215
  }
122
216
  })
123
217
 
124
- build.onResolve({ filter: /react-native-reanimated/ }, (args) => {
218
+ build.onResolve({ filter: /^react-native-worklets(?:\/.*)?$/ }, () => {
125
219
  return {
126
- path: 'react-native-reanimated',
220
+ path: proxyWormPath,
221
+ }
222
+ })
223
+
224
+ // externalize animation libraries - not needed for static extraction
225
+ build.onResolve({ filter: /^(framer-motion|motion)/ }, (args) => {
226
+ return {
227
+ path: args.path,
127
228
  external: true,
128
229
  }
129
230
  })
@@ -139,36 +240,38 @@ function getESBuildConfig(
139
240
  return res
140
241
  }
141
242
 
243
+ function detectEntryFormat(entryPoint: string): esbuild.BuildOptions['format'] {
244
+ // file path - detect from file/package.json
245
+ if (entryPoint.startsWith('/') || entryPoint.startsWith('.')) {
246
+ return detectModuleFormat(entryPoint)
247
+ }
248
+ // bare module specifier - check package.json type field
249
+ try {
250
+ const pkgJsonPath = require.resolve(entryPoint + '/package.json')
251
+ const pkg = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'))
252
+ return pkg.type === 'module' ? 'esm' : 'cjs'
253
+ } catch {
254
+ return 'cjs'
255
+ }
256
+ }
257
+
142
258
  export async function esbundleTamaguiConfig(
143
259
  props: Props,
144
260
  platform: TamaguiPlatform,
145
261
  aliases?: Record<string, string>
146
262
  ) {
147
- await asyncLock(props)
148
263
  const config = getESBuildConfig(props, platform, aliases)
149
- return await esbuild.build(config)
150
- }
151
264
 
152
- // until i do fancier things w plugins:
153
- async function asyncLock(props: Props) {
154
- const lockFile = join(dirname(props.outfile), basename(props.outfile, '.lock'))
155
- const lockStat = await FS.stat(lockFile).catch(() => {
156
- /* ok */
265
+ // build to memory first, then write atomically (temp file + rename)
266
+ // to prevent other threads from reading partially-written files
267
+ const tmpFile = props.outfile + '.tmp.' + process.pid
268
+ const result = await esbuild.build({
269
+ ...config,
270
+ outfile: tmpFile,
157
271
  })
158
- const lockedMsAgo = !lockStat
159
- ? Number.POSITIVE_INFINITY
160
- : new Date().getTime() - new Date(lockStat.mtime).getTime()
161
- if (lockedMsAgo < 500) {
162
- if (process.env.DEBUG?.startsWith('tamagui')) {
163
- console.info(`Waiting for existing build`, props.entryPoints)
164
- }
165
- let tries = 5
166
- while (tries--) {
167
- if (await FS.pathExists(props.outfile)) {
168
- return
169
- }
170
- await new Promise((res) => setTimeout(res, 50))
171
- }
172
- }
173
- void FS.writeFile(lockFile, '')
272
+
273
+ // atomic rename prevents other threads from reading partial files
274
+ await FS.rename(tmpFile, props.outfile)
275
+
276
+ return result
174
277
  }