@tamagui/static 1.0.1-beta.21 → 1.0.1-beta.211

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 (260) hide show
  1. package/dist/{cjs/constants.js → constants.js} +9 -4
  2. package/dist/constants.js.map +7 -0
  3. package/dist/{cjs/extractor → extractor}/accessSafe.js +14 -4
  4. package/dist/{esm/extractor → extractor}/accessSafe.js.map +2 -2
  5. package/dist/{cjs/extractor → extractor}/babelParse.js +20 -17
  6. package/dist/extractor/babelParse.js.map +7 -0
  7. package/dist/{cjs/extractor → extractor}/buildClassName.js +40 -11
  8. package/dist/extractor/buildClassName.js.map +7 -0
  9. package/dist/extractor/bundle.js +117 -0
  10. package/dist/extractor/bundle.js.map +7 -0
  11. package/dist/{cjs/extractor → extractor}/createEvaluator.js +19 -14
  12. package/dist/extractor/createEvaluator.js.map +7 -0
  13. package/dist/extractor/createExtractor.js +1645 -0
  14. package/dist/extractor/createExtractor.js.map +7 -0
  15. package/dist/{cjs/extractor → extractor}/ensureImportingConcat.js +18 -8
  16. package/dist/extractor/ensureImportingConcat.js.map +7 -0
  17. package/dist/{cjs/extractor → extractor}/evaluateAstNode.js +14 -6
  18. package/dist/{esm/extractor → extractor}/evaluateAstNode.js.map +2 -2
  19. package/dist/{cjs/extractor → extractor}/extractHelpers.js +91 -27
  20. package/dist/extractor/extractHelpers.js.map +7 -0
  21. package/dist/{cjs/extractor → extractor}/extractMediaStyle.js +49 -50
  22. package/dist/extractor/extractMediaStyle.js.map +7 -0
  23. package/dist/{cjs/extractor → extractor}/extractToClassNames.js +165 -109
  24. package/dist/extractor/extractToClassNames.js.map +7 -0
  25. package/dist/{cjs/extractor → extractor}/findTopmostFunction.js +2 -3
  26. package/dist/{esm/extractor → extractor}/findTopmostFunction.js.map +2 -2
  27. package/dist/{cjs/extractor → extractor}/generatedUid.js +9 -4
  28. package/dist/{cjs/extractor → extractor}/generatedUid.js.map +3 -3
  29. package/dist/{cjs/extractor → extractor}/getPrefixLogs.js +1 -2
  30. package/dist/extractor/getPrefixLogs.js.map +7 -0
  31. package/dist/{cjs/extractor → extractor}/getPropValueFromAttributes.js +24 -15
  32. package/dist/extractor/getPropValueFromAttributes.js.map +7 -0
  33. package/dist/{cjs/extractor → extractor}/getSourceModule.js +5 -3
  34. package/dist/{esm/extractor → extractor}/getSourceModule.js.map +2 -2
  35. package/dist/{cjs/extractor → extractor}/getStaticBindingsForScope.js +88 -38
  36. package/dist/extractor/getStaticBindingsForScope.js.map +7 -0
  37. package/dist/{cjs/extractor → extractor}/hoistClassNames.js +5 -4
  38. package/dist/{esm/extractor → extractor}/hoistClassNames.js.map +3 -3
  39. package/dist/{cjs/extractor → extractor}/literalToAst.js +26 -34
  40. package/dist/{cjs/extractor → extractor}/literalToAst.js.map +2 -2
  41. package/dist/extractor/loadFile.js +21 -0
  42. package/dist/extractor/loadFile.js.map +7 -0
  43. package/dist/extractor/loadTamagui.js +421 -0
  44. package/dist/extractor/loadTamagui.js.map +7 -0
  45. package/dist/{cjs/extractor → extractor}/logLines.js +3 -3
  46. package/dist/{cjs/extractor → extractor}/logLines.js.map +2 -2
  47. package/dist/{cjs/extractor → extractor}/normalizeTernaries.js +13 -36
  48. package/dist/extractor/normalizeTernaries.js.map +7 -0
  49. package/dist/{cjs/extractor → extractor}/removeUnusedHooks.js +7 -5
  50. package/dist/{cjs/extractor → extractor}/removeUnusedHooks.js.map +2 -2
  51. package/dist/{cjs/extractor → extractor}/timer.js +11 -4
  52. package/dist/extractor/timer.js.map +7 -0
  53. package/dist/{cjs/extractor → extractor}/validHTMLAttributes.js +52 -0
  54. package/dist/extractor/validHTMLAttributes.js.map +7 -0
  55. package/dist/getPragmaOptions.js +68 -0
  56. package/dist/getPragmaOptions.js.map +7 -0
  57. package/dist/helpers/memoize.js +46 -0
  58. package/dist/helpers/memoize.js.map +7 -0
  59. package/dist/{cjs/index.js → index.js} +10 -7
  60. package/dist/index.js.map +7 -0
  61. package/dist/require.js +90 -0
  62. package/dist/require.js.map +7 -0
  63. package/dist/tamagui-node/tamagui.config.js +6781 -0
  64. package/dist/{jsx/types.js → tamagui-node/tamaguicore-components.config.js} +0 -0
  65. package/dist/tamagui-node/tamaguitestdesignsystem-components.config.js +31 -0
  66. package/dist/{cjs/types.js → types.js} +1 -0
  67. package/dist/types.js.map +7 -0
  68. package/dist/webpackPlugin.js +35 -0
  69. package/dist/webpackPlugin.js.map +7 -0
  70. package/package.json +47 -35
  71. package/src/constants.ts +14 -0
  72. package/src/extractor/accessSafe.ts +18 -0
  73. package/src/extractor/babelParse.ts +28 -0
  74. package/src/extractor/buildClassName.ts +77 -0
  75. package/src/extractor/bundle.ts +110 -0
  76. package/src/extractor/createEvaluator.ts +73 -0
  77. package/src/extractor/createExtractor.ts +2133 -0
  78. package/src/extractor/ensureImportingConcat.ts +32 -0
  79. package/src/extractor/evaluateAstNode.ts +121 -0
  80. package/src/extractor/extractHelpers.ts +201 -0
  81. package/src/extractor/extractMediaStyle.ts +199 -0
  82. package/src/extractor/extractToClassNames.ts +450 -0
  83. package/src/extractor/findTopmostFunction.ts +22 -0
  84. package/src/extractor/generatedUid.ts +43 -0
  85. package/src/extractor/getPrefixLogs.ts +6 -0
  86. package/src/extractor/getPropValueFromAttributes.ts +92 -0
  87. package/src/extractor/getSourceModule.ts +101 -0
  88. package/src/extractor/getStaticBindingsForScope.ts +227 -0
  89. package/src/extractor/hoistClassNames.ts +45 -0
  90. package/src/extractor/literalToAst.ts +84 -0
  91. package/src/extractor/loadFile.ts +17 -0
  92. package/src/extractor/loadTamagui.ts +480 -0
  93. package/src/extractor/logLines.ts +16 -0
  94. package/src/extractor/normalizeTernaries.ts +63 -0
  95. package/src/extractor/removeUnusedHooks.ts +76 -0
  96. package/src/extractor/timer.ts +29 -0
  97. package/src/extractor/validHTMLAttributes.ts +99 -0
  98. package/src/getPragmaOptions.ts +53 -0
  99. package/src/helpers/memoize.ts +21 -0
  100. package/src/index.ts +11 -0
  101. package/src/require.ts +107 -0
  102. package/src/types.ts +98 -0
  103. package/src/webpackPlugin.ts +9 -0
  104. package/tamagui.tsconfig.json +5 -0
  105. package/types/constants.d.ts +1 -1
  106. package/types/extractor/babelParse.d.ts +2 -1
  107. package/types/extractor/buildClassName.d.ts +5 -2
  108. package/types/extractor/bundle.d.ts +13 -0
  109. package/types/extractor/createEvaluator.d.ts +4 -4
  110. package/types/extractor/createExtractor.d.ts +26 -11
  111. package/types/extractor/extractHelpers.d.ts +16 -4
  112. package/types/extractor/extractMediaStyle.d.ts +3 -3
  113. package/types/extractor/extractToClassNames.d.ts +5 -9
  114. package/types/extractor/getPrefixLogs.d.ts +1 -1
  115. package/types/extractor/getPropValueFromAttributes.d.ts +16 -0
  116. package/types/extractor/getStaticBindingsForScope.d.ts +2 -1
  117. package/types/extractor/loadFile.d.ts +1 -0
  118. package/types/extractor/loadTamagui.d.ts +22 -6
  119. package/types/extractor/normalizeTernaries.d.ts +1 -1
  120. package/types/extractor/validHTMLAttributes.d.ts +49 -0
  121. package/types/getPragmaOptions.d.ts +9 -0
  122. package/types/helpers/memoize.d.ts +8 -0
  123. package/types/index.d.ts +9 -7
  124. package/types/require.d.ts +4 -0
  125. package/types/types.d.ts +32 -32
  126. package/types/webpackPlugin.d.ts +4 -0
  127. package/dist/cjs/constants.js.map +0 -7
  128. package/dist/cjs/extractor/accessSafe.js.map +0 -7
  129. package/dist/cjs/extractor/babelParse.js.map +0 -7
  130. package/dist/cjs/extractor/buildClassName.js.map +0 -7
  131. package/dist/cjs/extractor/createEvaluator.js.map +0 -7
  132. package/dist/cjs/extractor/createExtractor.js +0 -1221
  133. package/dist/cjs/extractor/createExtractor.js.map +0 -7
  134. package/dist/cjs/extractor/ensureImportingConcat.js.map +0 -7
  135. package/dist/cjs/extractor/evaluateAstNode.js.map +0 -7
  136. package/dist/cjs/extractor/extractHelpers.js.map +0 -7
  137. package/dist/cjs/extractor/extractMediaStyle.js.map +0 -7
  138. package/dist/cjs/extractor/extractToClassNames.js.map +0 -7
  139. package/dist/cjs/extractor/findTopmostFunction.js.map +0 -7
  140. package/dist/cjs/extractor/getPrefixLogs.js.map +0 -7
  141. package/dist/cjs/extractor/getPropValueFromAttributes.js.map +0 -7
  142. package/dist/cjs/extractor/getSourceModule.js.map +0 -7
  143. package/dist/cjs/extractor/getStaticBindingsForScope.js.map +0 -7
  144. package/dist/cjs/extractor/hoistClassNames.js.map +0 -7
  145. package/dist/cjs/extractor/loadTamagui.js +0 -106
  146. package/dist/cjs/extractor/loadTamagui.js.map +0 -7
  147. package/dist/cjs/extractor/normalizeTernaries.js.map +0 -7
  148. package/dist/cjs/extractor/timer.js.map +0 -7
  149. package/dist/cjs/extractor/validHTMLAttributes.js.map +0 -7
  150. package/dist/cjs/index.js.map +0 -7
  151. package/dist/cjs/patchReactNativeWeb.js +0 -167
  152. package/dist/cjs/patchReactNativeWeb.js.map +0 -7
  153. package/dist/cjs/types.js.map +0 -7
  154. package/dist/esm/constants.js +0 -14
  155. package/dist/esm/constants.js.map +0 -7
  156. package/dist/esm/extractor/accessSafe.js +0 -11
  157. package/dist/esm/extractor/babelParse.js +0 -30
  158. package/dist/esm/extractor/babelParse.js.map +0 -7
  159. package/dist/esm/extractor/buildClassName.js +0 -40
  160. package/dist/esm/extractor/buildClassName.js.map +0 -7
  161. package/dist/esm/extractor/createEvaluator.js +0 -52
  162. package/dist/esm/extractor/createEvaluator.js.map +0 -7
  163. package/dist/esm/extractor/createExtractor.js +0 -1169
  164. package/dist/esm/extractor/createExtractor.js.map +0 -7
  165. package/dist/esm/extractor/ensureImportingConcat.js +0 -24
  166. package/dist/esm/extractor/ensureImportingConcat.js.map +0 -7
  167. package/dist/esm/extractor/evaluateAstNode.js +0 -94
  168. package/dist/esm/extractor/extractHelpers.js +0 -103
  169. package/dist/esm/extractor/extractHelpers.js.map +0 -7
  170. package/dist/esm/extractor/extractMediaStyle.js +0 -152
  171. package/dist/esm/extractor/extractMediaStyle.js.map +0 -7
  172. package/dist/esm/extractor/extractToClassNames.js +0 -293
  173. package/dist/esm/extractor/extractToClassNames.js.map +0 -7
  174. package/dist/esm/extractor/findTopmostFunction.js +0 -23
  175. package/dist/esm/extractor/generatedUid.js +0 -28
  176. package/dist/esm/extractor/generatedUid.js.map +0 -7
  177. package/dist/esm/extractor/getPrefixLogs.js +0 -12
  178. package/dist/esm/extractor/getPrefixLogs.js.map +0 -7
  179. package/dist/esm/extractor/getPropValueFromAttributes.js +0 -49
  180. package/dist/esm/extractor/getPropValueFromAttributes.js.map +0 -7
  181. package/dist/esm/extractor/getSourceModule.js +0 -69
  182. package/dist/esm/extractor/getStaticBindingsForScope.js +0 -137
  183. package/dist/esm/extractor/getStaticBindingsForScope.js.map +0 -7
  184. package/dist/esm/extractor/hoistClassNames.js +0 -44
  185. package/dist/esm/extractor/literalToAst.js +0 -80
  186. package/dist/esm/extractor/literalToAst.js.map +0 -7
  187. package/dist/esm/extractor/loadTamagui.js +0 -84
  188. package/dist/esm/extractor/loadTamagui.js.map +0 -7
  189. package/dist/esm/extractor/logLines.js +0 -22
  190. package/dist/esm/extractor/logLines.js.map +0 -7
  191. package/dist/esm/extractor/normalizeTernaries.js +0 -53
  192. package/dist/esm/extractor/normalizeTernaries.js.map +0 -7
  193. package/dist/esm/extractor/removeUnusedHooks.js +0 -80
  194. package/dist/esm/extractor/removeUnusedHooks.js.map +0 -7
  195. package/dist/esm/extractor/timer.js +0 -24
  196. package/dist/esm/extractor/timer.js.map +0 -7
  197. package/dist/esm/extractor/validHTMLAttributes.js +0 -52
  198. package/dist/esm/extractor/validHTMLAttributes.js.map +0 -7
  199. package/dist/esm/index.js +0 -14
  200. package/dist/esm/index.js.map +0 -7
  201. package/dist/esm/patchReactNativeWeb.js +0 -142
  202. package/dist/esm/patchReactNativeWeb.js.map +0 -7
  203. package/dist/esm/types.js +0 -1
  204. package/dist/esm/types.js.map +0 -7
  205. package/dist/jsx/constants.js +0 -13
  206. package/dist/jsx/extractor/accessSafe.js +0 -10
  207. package/dist/jsx/extractor/babelParse.js +0 -29
  208. package/dist/jsx/extractor/buildClassName.js +0 -39
  209. package/dist/jsx/extractor/createEvaluator.js +0 -51
  210. package/dist/jsx/extractor/createExtractor.js +0 -1168
  211. package/dist/jsx/extractor/ensureImportingConcat.js +0 -23
  212. package/dist/jsx/extractor/evaluateAstNode.js +0 -93
  213. package/dist/jsx/extractor/extractHelpers.js +0 -102
  214. package/dist/jsx/extractor/extractMediaStyle.js +0 -151
  215. package/dist/jsx/extractor/extractToClassNames.js +0 -292
  216. package/dist/jsx/extractor/findTopmostFunction.js +0 -22
  217. package/dist/jsx/extractor/generatedUid.js +0 -27
  218. package/dist/jsx/extractor/getPrefixLogs.js +0 -11
  219. package/dist/jsx/extractor/getPropValueFromAttributes.js +0 -48
  220. package/dist/jsx/extractor/getSourceModule.js +0 -68
  221. package/dist/jsx/extractor/getStaticBindingsForScope.js +0 -136
  222. package/dist/jsx/extractor/hoistClassNames.js +0 -43
  223. package/dist/jsx/extractor/literalToAst.js +0 -79
  224. package/dist/jsx/extractor/loadTamagui.js +0 -83
  225. package/dist/jsx/extractor/logLines.js +0 -21
  226. package/dist/jsx/extractor/normalizeTernaries.js +0 -52
  227. package/dist/jsx/extractor/removeUnusedHooks.js +0 -79
  228. package/dist/jsx/extractor/timer.js +0 -23
  229. package/dist/jsx/extractor/validHTMLAttributes.js +0 -51
  230. package/dist/jsx/index.js +0 -13
  231. package/dist/jsx/patchReactNativeWeb.js +0 -141
  232. package/types/constants.d.ts.map +0 -1
  233. package/types/extractor/accessSafe.d.ts.map +0 -1
  234. package/types/extractor/babelParse.d.ts.map +0 -1
  235. package/types/extractor/buildClassName.d.ts.map +0 -1
  236. package/types/extractor/createEvaluator.d.ts.map +0 -1
  237. package/types/extractor/createExtractor.d.ts.map +0 -1
  238. package/types/extractor/ensureImportingConcat.d.ts.map +0 -1
  239. package/types/extractor/evaluateAstNode.d.ts.map +0 -1
  240. package/types/extractor/extractHelpers.d.ts.map +0 -1
  241. package/types/extractor/extractMediaStyle.d.ts.map +0 -1
  242. package/types/extractor/extractToClassNames.d.ts.map +0 -1
  243. package/types/extractor/findTopmostFunction.d.ts.map +0 -1
  244. package/types/extractor/generatedUid.d.ts.map +0 -1
  245. package/types/extractor/getPrefixLogs.d.ts.map +0 -1
  246. package/types/extractor/getPropValueFromAttributes.d.ts.map +0 -1
  247. package/types/extractor/getSourceModule.d.ts.map +0 -1
  248. package/types/extractor/getStaticBindingsForScope.d.ts.map +0 -1
  249. package/types/extractor/hoistClassNames.d.ts.map +0 -1
  250. package/types/extractor/literalToAst.d.ts.map +0 -1
  251. package/types/extractor/loadTamagui.d.ts.map +0 -1
  252. package/types/extractor/logLines.d.ts.map +0 -1
  253. package/types/extractor/normalizeTernaries.d.ts.map +0 -1
  254. package/types/extractor/removeUnusedHooks.d.ts.map +0 -1
  255. package/types/extractor/timer.d.ts.map +0 -1
  256. package/types/extractor/validHTMLAttributes.d.ts.map +0 -1
  257. package/types/index.d.ts.map +0 -1
  258. package/types/patchReactNativeWeb.d.ts +0 -2
  259. package/types/patchReactNativeWeb.d.ts.map +0 -1
  260. package/types/types.d.ts.map +0 -1
@@ -0,0 +1,480 @@
1
+ import { readFileSync } from 'fs'
2
+ /* eslint-disable no-console */
3
+ import { basename, dirname, extname, join, relative, sep } from 'path'
4
+
5
+ import generate from '@babel/generator'
6
+ import traverse from '@babel/traverse'
7
+ import * as t from '@babel/types'
8
+ import { Color, colorLog } from '@tamagui/cli-color'
9
+ import { getDefaultTamaguiConfig } from '@tamagui/config-default-node'
10
+ import type { StaticConfigParsed, TamaguiInternalConfig } from '@tamagui/core-node'
11
+ import { createTamagui } from '@tamagui/core-node'
12
+ import esbuild from 'esbuild'
13
+ import { ensureDir, existsSync, removeSync, writeFileSync } from 'fs-extra'
14
+
15
+ import { SHOULD_DEBUG } from '../constants.js'
16
+ import { getNameToPaths, registerRequire, unregisterRequire } from '../require.js'
17
+ import { babelParse } from './babelParse'
18
+ import { bundle } from './bundle'
19
+
20
+ type NameToPaths = {
21
+ [key: string]: Set<string>
22
+ }
23
+
24
+ export type LoadedComponents = {
25
+ moduleName: string
26
+ nameToInfo: Record<
27
+ string,
28
+ {
29
+ staticConfig: StaticConfigParsed
30
+ }
31
+ >
32
+ }
33
+
34
+ export type TamaguiProjectInfo = {
35
+ components: LoadedComponents[]
36
+ tamaguiConfig: TamaguiInternalConfig
37
+ nameToPaths: NameToPaths
38
+ }
39
+
40
+ type Props = {
41
+ components: string[]
42
+ config?: string
43
+ forceExports?: boolean
44
+ }
45
+
46
+ const cache = {}
47
+
48
+ // TODO needs a plugin for webpack / vite to run this once at startup and not again until changed...
49
+
50
+ export async function loadTamagui(props: Props): Promise<TamaguiProjectInfo> {
51
+ const key = JSON.stringify(props)
52
+ if (cache[key]) {
53
+ if (cache[key] instanceof Promise) {
54
+ return await cache[key]
55
+ }
56
+ return cache[key]
57
+ }
58
+
59
+ let resolver: Function = () => {}
60
+ cache[key] = new Promise((res) => {
61
+ resolver = res
62
+ })
63
+
64
+ const tmpDir = join(process.cwd(), '.tamagui', 'tamagui-node')
65
+ const configOutPath = join(tmpDir, `tamagui.config.js`)
66
+ const baseComponents = props.components.filter((x) => x !== '@tamagui/core')
67
+ const componentOutPaths = baseComponents.map((componentModule) =>
68
+ join(
69
+ tmpDir,
70
+ `${componentModule
71
+ .split(sep)
72
+ .join('-')
73
+ .replace(/[^a-z0-9]+/gi, '')}-components.config.js`
74
+ )
75
+ )
76
+
77
+ const external = ['@tamagui/core', '@tamagui/core-node', 'react', 'react-dom', 'react-native-svg']
78
+ const configEntry = props.config ? join(process.cwd(), props.config) : ''
79
+
80
+ if (process.env.NODE_ENV === 'development' && process.env.DEBUG?.startsWith('tamagui')) {
81
+ console.log(`Building config entry`, configEntry)
82
+ }
83
+
84
+ // build them to node-compat versions
85
+ try {
86
+ await ensureDir(tmpDir)
87
+ } catch {
88
+ //
89
+ }
90
+
91
+ colorLog(
92
+ Color.FgYellow,
93
+ `
94
+ Tamagui built config and components:`
95
+ )
96
+ colorLog(
97
+ Color.Dim,
98
+ `
99
+ - Config .${sep}${relative(process.cwd(), configOutPath)}
100
+ - Components ${componentOutPaths
101
+ .map((p) => `.${sep}${relative(process.cwd(), p)}`)
102
+ .join('\n ')}
103
+ `
104
+ )
105
+
106
+ await Promise.all([
107
+ props.config
108
+ ? bundle({
109
+ entryPoints: [configEntry],
110
+ external,
111
+ outfile: configOutPath,
112
+ })
113
+ : null,
114
+ ...baseComponents.map((componentModule, i) => {
115
+ return bundle({
116
+ entryPoints: [componentModule],
117
+ resolvePlatformSpecificEntries: true,
118
+ external,
119
+ outfile: componentOutPaths[i],
120
+ })
121
+ }),
122
+ ])
123
+
124
+ try {
125
+ registerRequire()
126
+ const out = require(configOutPath)
127
+ const config = out.default || out
128
+
129
+ if (!config) {
130
+ throw new Error(`No config: ${config}`)
131
+ }
132
+
133
+ let components = loadComponents({
134
+ ...props,
135
+ components: componentOutPaths,
136
+ })
137
+
138
+ if (!components) {
139
+ throw new Error(`No components found: ${componentOutPaths.join(', ')}`)
140
+ }
141
+
142
+ // map from built back to original module names
143
+ for (const component of components) {
144
+ component.moduleName = baseComponents[componentOutPaths.indexOf(component.moduleName)]
145
+ if (!component.moduleName) {
146
+ throw new Error(`Tamagui internal err`)
147
+ }
148
+ }
149
+
150
+ // always load core so we can optimize if directly importing
151
+ const coreComponents = loadComponents({
152
+ ...props,
153
+ components: ['@tamagui/core-node'],
154
+ })
155
+ if (coreComponents) {
156
+ coreComponents[0].moduleName = '@tamagui/core'
157
+ components = [...components, ...coreComponents]
158
+ }
159
+
160
+ if (process.env.NODE_ENV === 'development' && process.env.DEBUG?.startsWith('tamagui')) {
161
+ console.log('Loaded components', components)
162
+ }
163
+
164
+ cache[key] = {
165
+ components,
166
+ nameToPaths: {},
167
+ tamaguiConfig: config,
168
+ }
169
+
170
+ // init core-node
171
+ createTamagui(cache[key].tamaguiConfig)
172
+
173
+ resolver(cache[key])
174
+
175
+ return cache[key]
176
+ } finally {
177
+ unregisterRequire()
178
+ }
179
+ }
180
+
181
+ export function resolveWebOrNativeSpecificEntry(entry: string) {
182
+ const resolved = require.resolve(entry)
183
+ const ext = extname(resolved)
184
+ const fileName = basename(resolved).replace(ext, '')
185
+ const specificExt = process.env.TAMAGUI_TARGET === 'web' ? 'web' : 'native'
186
+ const specificFile = join(dirname(resolved), fileName + '.' + specificExt + ext)
187
+ if (existsSync(specificFile)) {
188
+ return specificFile
189
+ }
190
+ return entry
191
+ }
192
+
193
+ const esbuildOptions = {
194
+ loader: 'tsx',
195
+ target: 'es2018',
196
+ format: 'cjs',
197
+ jsx: 'transform',
198
+ platform: 'node',
199
+ } as const
200
+
201
+ // loads in-process using esbuild-register
202
+ export function loadTamaguiSync(props: Props): TamaguiProjectInfo {
203
+ const key = JSON.stringify(props)
204
+ if (cache[key]) {
205
+ return cache[key]
206
+ }
207
+
208
+ const { unregister } = require('esbuild-register/dist/node').register(esbuildOptions)
209
+
210
+ try {
211
+ registerRequire()
212
+
213
+ // lets shim require and avoid importing react-native + react-native-web
214
+ // we just need to read the config around them
215
+ process.env.IS_STATIC = 'is_static'
216
+ const devValueOG = globalThis['__DEV__' as any]
217
+ globalThis['__DEV__' as any] = process.env.NODE_ENV === 'development'
218
+
219
+ try {
220
+ // config
221
+ let tamaguiConfig: TamaguiInternalConfig | null = null
222
+ if (props.config) {
223
+ const configPath = join(process.cwd(), props.config)
224
+ const exp = require(configPath)
225
+ tamaguiConfig = (exp['default'] || exp) as TamaguiInternalConfig
226
+ if (!tamaguiConfig || !tamaguiConfig.parsed) {
227
+ const confPath = require.resolve(configPath)
228
+ throw new Error(`Can't find valid config in ${confPath}:
229
+
230
+ Be sure you "export default" the config.`)
231
+ }
232
+ }
233
+
234
+ // components
235
+ const components = loadComponents(props)
236
+ if (!components) {
237
+ throw new Error(`No components loaded`)
238
+ }
239
+ if (process.env.DEBUG === 'tamagui') {
240
+ console.log(`components`, components)
241
+ }
242
+
243
+ // undo shims
244
+ process.env.IS_STATIC = undefined
245
+ globalThis['__DEV__' as any] = devValueOG
246
+
247
+ // set up core-node
248
+ if (props.config && tamaguiConfig) {
249
+ createTamagui(tamaguiConfig as any)
250
+ }
251
+
252
+ cache[key] = {
253
+ components,
254
+ tamaguiConfig,
255
+ nameToPaths: getNameToPaths(),
256
+ }
257
+ } catch (err) {
258
+ if (err instanceof Error) {
259
+ console.warn(
260
+ `Error loading tamagui.config.ts (set DEBUG=tamagui to see full stack), running tamagui without custom config`
261
+ )
262
+ console.log(`\n\n ${err.message}\n\n`)
263
+ if (SHOULD_DEBUG) {
264
+ console.log(err.stack)
265
+ }
266
+ } else {
267
+ console.error(`Error loading tamagui.config.ts`, err)
268
+ }
269
+ return {
270
+ components: [],
271
+ tamaguiConfig: getDefaultTamaguiConfig(),
272
+ nameToPaths: {},
273
+ }
274
+ }
275
+
276
+ return cache[key]
277
+ } finally {
278
+ unregister()
279
+ unregisterRequire()
280
+ }
281
+ }
282
+
283
+ function interopDefaultExport(mod: any) {
284
+ return mod?.default ?? mod
285
+ }
286
+
287
+ const cacheComponents: Record<string, LoadedComponents[]> = {}
288
+
289
+ function transformAddExports(ast: t.File) {
290
+ const usedNames = new Set<string>()
291
+
292
+ // avoid clobbering
293
+ traverse(ast, {
294
+ ExportNamedDeclaration(nodePath) {
295
+ if (nodePath.node.specifiers) {
296
+ for (const spec of nodePath.node.specifiers) {
297
+ usedNames.add(t.isIdentifier(spec.exported) ? spec.exported.name : spec.exported.value)
298
+ }
299
+ }
300
+ },
301
+ })
302
+
303
+ traverse(ast, {
304
+ VariableDeclaration(nodePath) {
305
+ // top level only
306
+ if (!t.isProgram(nodePath.parent)) return
307
+ const decs = nodePath.node.declarations
308
+ if (decs.length > 1) return
309
+ const [dec] = decs
310
+ if (!t.isIdentifier(dec.id)) return
311
+ if (!dec.init) return
312
+ if (usedNames.has(dec.id.name)) return
313
+ usedNames.add(dec.id.name)
314
+ nodePath.replaceWith(
315
+ t.exportNamedDeclaration(t.variableDeclaration('let', [dec]), [
316
+ t.exportSpecifier(t.identifier(dec.id.name), t.identifier(dec.id.name)),
317
+ ])
318
+ )
319
+ },
320
+ })
321
+
322
+ return generate(ast as any, {
323
+ concise: false,
324
+ filename: 'test.tsx',
325
+ retainLines: false,
326
+ sourceMaps: false,
327
+ }).code
328
+ }
329
+
330
+ function loadComponents(props: Props): null | LoadedComponents[] {
331
+ const componentsModules = props.components
332
+ const key = componentsModules.join('')
333
+ if (cacheComponents[key]) {
334
+ return cacheComponents[key]
335
+ }
336
+ try {
337
+ const info: LoadedComponents[] = componentsModules.flatMap((name) => {
338
+ const extension = extname(name)
339
+ const isLocal = Boolean(extension)
340
+ // during props.config pass we are passing in pre-bundled stuff
341
+ const writeTmp = isLocal && !props.config
342
+ const fileContents = writeTmp ? readFileSync(name, 'utf-8') : ''
343
+ const loadModule = writeTmp
344
+ ? join(dirname(name), `.tamagui-dynamic-eval-${basename(name)}.tsx`)
345
+ : name
346
+ let writtenContents = fileContents
347
+ let didBabel = false
348
+
349
+ const esbuildit = (src: string, target?: 'modern') =>
350
+ esbuild.transformSync(src, {
351
+ ...esbuildOptions,
352
+ ...(target === 'modern' && {
353
+ target: 'es2022',
354
+ jsx: 'transform',
355
+ loader: 'tsx',
356
+ platform: 'neutral',
357
+ format: 'esm',
358
+ }),
359
+ }).code
360
+
361
+ function attemptLoad({ forceExports = false } = {}) {
362
+ // need to write to tsx to enable reading it properly (:/ esbuild-register)
363
+ if (writeTmp) {
364
+ writtenContents = forceExports
365
+ ? esbuildit(transformAddExports(babelParse(esbuildit(fileContents, 'modern'))))
366
+ : esbuildit(fileContents)
367
+
368
+ writeFileSync(loadModule, writtenContents)
369
+ }
370
+ return {
371
+ moduleName: name,
372
+ nameToInfo: getComponentStaticConfigByName(
373
+ name,
374
+ interopDefaultExport(require(loadModule))
375
+ ),
376
+ }
377
+ }
378
+
379
+ const dispose = () => {
380
+ writeTmp && removeSync(loadModule)
381
+ }
382
+
383
+ try {
384
+ const res = attemptLoad({
385
+ forceExports: true,
386
+ })
387
+ didBabel = true
388
+ return res
389
+ } catch (err) {
390
+ console.log('babel err', err, writtenContents)
391
+ // ok
392
+ writtenContents = fileContents
393
+ if (process.env.DEBUG?.startsWith('tamagui')) {
394
+ console.log(`Error parsing babel likely`, err)
395
+ }
396
+ } finally {
397
+ dispose()
398
+ }
399
+
400
+ try {
401
+ return attemptLoad({
402
+ forceExports: false,
403
+ })
404
+ } catch (err) {
405
+ if (!process.env.TAMAGUI_DISABLE_WARN_DYNAMIC_LOAD) {
406
+ console.log(`
407
+
408
+ Tamagui attempted but failed to dynamically load components in:
409
+ ${name}
410
+
411
+ This will leave some styled() tags unoptimized.
412
+ Disable this file (or dynamic loading altogether):
413
+
414
+ disableExtractFoundComponents: ['${name}'] | true
415
+
416
+ Quiet this warning with environment variable:
417
+
418
+ TAMAGUI_DISABLE_WARN_DYNAMIC_LOAD=1
419
+
420
+ `)
421
+ console.log(err)
422
+ console.log(
423
+ `At: ${loadModule}`,
424
+ `\ndidBabel: ${didBabel}`,
425
+ `\nIn:`,
426
+ writtenContents,
427
+ `\nwriteTmp: `,
428
+ writeTmp
429
+ )
430
+ }
431
+ return []
432
+ } finally {
433
+ dispose()
434
+ }
435
+ })
436
+ cacheComponents[key] = info
437
+ return info
438
+ } catch (err: any) {
439
+ console.log(`Tamagui error bundling components`, err.message, err.stack)
440
+ return null
441
+ }
442
+ }
443
+
444
+ function getComponentStaticConfigByName(name: string, exported: any) {
445
+ if (!exported || typeof exported !== 'object' || Array.isArray(exported)) {
446
+ throw new Error(`Invalid export from package ${name}: ${typeof exported}`)
447
+ }
448
+ const components: Record<string, { staticConfig: StaticConfigParsed }> = {}
449
+ try {
450
+ for (const key in exported) {
451
+ const found = getTamaguiComponent(key, exported[key])
452
+ if (found) {
453
+ // remove non-stringifyable
454
+ const { Component, ...sc } = found.staticConfig
455
+ components[key] = { staticConfig: sc }
456
+ }
457
+ }
458
+ } catch (err) {
459
+ console.error(`Tamagui failed getting components`)
460
+ if (err instanceof Error) {
461
+ console.error(err.message, err.stack)
462
+ } else {
463
+ console.error(err)
464
+ }
465
+ }
466
+ return components
467
+ }
468
+
469
+ function getTamaguiComponent(
470
+ name: string,
471
+ Component: any
472
+ ): undefined | { staticConfig: StaticConfigParsed } {
473
+ if (name[0].toUpperCase() !== name[0]) {
474
+ return
475
+ }
476
+ const staticConfig = Component?.staticConfig as StaticConfigParsed | undefined
477
+ if (staticConfig) {
478
+ return Component
479
+ }
480
+ }
@@ -0,0 +1,16 @@
1
+ const prefix = ' '
2
+
3
+ export const logLines = (str: string, singleLine = false) => {
4
+ if (singleLine) {
5
+ return prefix + str.split(' ').join(`\n${prefix}`)
6
+ }
7
+ let lines: string[] = ['']
8
+ const items = str.split(' ')
9
+ for (const item of items) {
10
+ if (item.length + lines[lines.length - 1].length > 85) {
11
+ lines.push('')
12
+ }
13
+ lines[lines.length - 1] += item + ' '
14
+ }
15
+ return lines.map((line, i) => prefix + (i == 0 ? '' : ' ') + line.trim()).join('\n')
16
+ }
@@ -0,0 +1,63 @@
1
+ import generate from '@babel/generator'
2
+ import * as t from '@babel/types'
3
+ import invariant from 'invariant'
4
+
5
+ import { Ternary } from '../types.js'
6
+
7
+ export function normalizeTernaries(ternaries: Ternary[]) {
8
+ invariant(
9
+ Array.isArray(ternaries),
10
+ 'extractStaticTernaries expects param 1 to be an array of ternaries'
11
+ )
12
+
13
+ if (ternaries.length === 0) {
14
+ return []
15
+ }
16
+
17
+ const ternariesByKey: { [key: string]: Ternary } = {}
18
+
19
+ for (let idx = -1, len = ternaries.length; ++idx < len; ) {
20
+ const { test, consequent, alternate, remove, ...rest } = ternaries[idx]
21
+
22
+ let ternaryTest = test
23
+
24
+ // strip parens
25
+ if (t.isExpressionStatement(test)) {
26
+ ternaryTest = (test as any).expression
27
+ }
28
+
29
+ // convert `!thing` to `thing` with swapped consequent and alternate
30
+ let shouldSwap = false
31
+ if (t.isUnaryExpression(test) && test.operator === '!') {
32
+ ternaryTest = test.argument
33
+ shouldSwap = true
34
+ } else if (t.isBinaryExpression(test)) {
35
+ if (test.operator === '!==' || test.operator === '!=') {
36
+ ternaryTest = t.binaryExpression(test.operator, test.left, test.right)
37
+ shouldSwap = true
38
+ }
39
+ }
40
+
41
+ const key = generate(ternaryTest as any).code
42
+
43
+ if (!ternariesByKey[key]) {
44
+ ternariesByKey[key] = {
45
+ ...rest,
46
+ alternate: {},
47
+ consequent: {},
48
+ test: ternaryTest,
49
+ remove,
50
+ }
51
+ }
52
+ const altStyle = (shouldSwap ? consequent : alternate) ?? {}
53
+ const consStyle = (shouldSwap ? alternate : consequent) ?? {}
54
+ Object.assign(ternariesByKey[key].alternate!, altStyle)
55
+ Object.assign(ternariesByKey[key].consequent!, consStyle)
56
+ }
57
+
58
+ const ternaryExpression = Object.keys(ternariesByKey).map((key) => {
59
+ return ternariesByKey[key]
60
+ })
61
+
62
+ return ternaryExpression
63
+ }
@@ -0,0 +1,76 @@
1
+ import { NodePath } from '@babel/traverse'
2
+ import * as t from '@babel/types'
3
+
4
+ const hooks = {
5
+ useMedia: true,
6
+ useTheme: true,
7
+ }
8
+
9
+ export function removeUnusedHooks(compFn: NodePath<any>, shouldPrintDebug: boolean | 'verbose') {
10
+ compFn.scope.crawl()
11
+ // check the top level statements
12
+ let bodyStatements = compFn?.get('body')
13
+ if (!bodyStatements) {
14
+ console.log('no body statemnts?', compFn)
15
+ return
16
+ }
17
+ if (!Array.isArray(bodyStatements)) {
18
+ if (bodyStatements.isFunctionExpression()) {
19
+ bodyStatements = bodyStatements.scope.path.get('body')
20
+ } else {
21
+ bodyStatements = bodyStatements.get('body')
22
+ }
23
+ }
24
+ if (!bodyStatements || !Array.isArray(bodyStatements)) {
25
+ return
26
+ }
27
+ const statements = bodyStatements as NodePath<any>[]
28
+ for (const statement of statements) {
29
+ if (!statement.isVariableDeclaration()) {
30
+ continue
31
+ }
32
+ const declarations = statement.get('declarations')
33
+ if (!Array.isArray(declarations)) {
34
+ continue
35
+ }
36
+ const isBindingReferenced = (name: string) => {
37
+ return !!statement.scope.getBinding(name)?.referenced
38
+ }
39
+ for (const declarator of declarations) {
40
+ const id = declarator.get('id')
41
+ const init = declarator.node.init
42
+ if (Array.isArray(id) || Array.isArray(init)) {
43
+ continue
44
+ }
45
+ const shouldRemove = (() => {
46
+ const isHook =
47
+ t.isCallExpression(init) && t.isIdentifier(init.callee) && hooks[init.callee.name]
48
+ if (!isHook) {
49
+ return false
50
+ }
51
+ if (t.isIdentifier(id.node)) {
52
+ // remove "const media = useMedia()"
53
+ const name = id.node.name
54
+ return !isBindingReferenced(name)
55
+ } else if (t.isObjectPattern(id.node)) {
56
+ // remove "const { sm } = useMedia()"
57
+ const propPaths = id.get('properties') as NodePath<any>[]
58
+ return propPaths.every((prop) => {
59
+ if (!prop.isObjectProperty()) return false
60
+ const value = prop.get('value')
61
+ if (Array.isArray(value) || !value.isIdentifier()) return false
62
+ const name = value.node.name
63
+ return !isBindingReferenced(name)
64
+ })
65
+ }
66
+ return false
67
+ })()
68
+ if (shouldRemove) {
69
+ declarator.remove()
70
+ if (shouldPrintDebug) {
71
+ console.log(` [🪝] removed ${id.node['name'] ?? ''}`)
72
+ }
73
+ }
74
+ }
75
+ }
76
+ }
@@ -0,0 +1,29 @@
1
+ export const timer = () => {
2
+ const start = Date.now()
3
+ let last = start
4
+ return {
5
+ mark: (name: string, print = false) => {
6
+ if (print) {
7
+ const took = Date.now() - last
8
+ last = Date.now()
9
+ // eslint-disable-next-line no-console
10
+ console.log(`Time ${name}: ${took}ms`)
11
+ if (took > 10) {
12
+ // eslint-disable-next-line no-console
13
+ console.log(' long timer')
14
+ }
15
+ }
16
+ },
17
+ done: (print = false) => {
18
+ if (print) {
19
+ const total = Date.now() - start
20
+ // eslint-disable-next-line no-console
21
+ console.log(`Total time: ${total}ms`)
22
+ if (total > 50) {
23
+ // eslint-disable-next-line no-console
24
+ console.log(' long timer')
25
+ }
26
+ }
27
+ },
28
+ }
29
+ }