@tamagui/static 1.0.1-beta.20 → 1.0.1-beta.201

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 +1650 -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 +161 -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 +2147 -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 +445 -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 +478 -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,478 @@
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: .${sep}${relative(process.cwd(), componentOutPaths.join(', '))}
101
+ `
102
+ )
103
+
104
+ await Promise.all([
105
+ props.config
106
+ ? bundle({
107
+ entryPoints: [configEntry],
108
+ external,
109
+ outfile: configOutPath,
110
+ })
111
+ : null,
112
+ ...baseComponents.map((componentModule, i) => {
113
+ return bundle({
114
+ entryPoints: [componentModule],
115
+ resolvePlatformSpecificEntries: true,
116
+ external,
117
+ outfile: componentOutPaths[i],
118
+ })
119
+ }),
120
+ ])
121
+
122
+ try {
123
+ registerRequire()
124
+ const out = require(configOutPath)
125
+ const config = out.default || out
126
+
127
+ if (!config) {
128
+ throw new Error(`No config: ${config}`)
129
+ }
130
+
131
+ let components = loadComponents({
132
+ ...props,
133
+ components: componentOutPaths,
134
+ })
135
+
136
+ if (!components) {
137
+ throw new Error(`No components found: ${componentOutPaths.join(', ')}`)
138
+ }
139
+
140
+ // map from built back to original module names
141
+ for (const component of components) {
142
+ component.moduleName = baseComponents[componentOutPaths.indexOf(component.moduleName)]
143
+ if (!component.moduleName) {
144
+ throw new Error(`Tamagui internal err`)
145
+ }
146
+ }
147
+
148
+ // always load core so we can optimize if directly importing
149
+ const coreComponents = loadComponents({
150
+ ...props,
151
+ components: ['@tamagui/core-node'],
152
+ })
153
+ if (coreComponents) {
154
+ coreComponents[0].moduleName = '@tamagui/core'
155
+ components = [...components, ...coreComponents]
156
+ }
157
+
158
+ if (process.env.NODE_ENV === 'development' && process.env.DEBUG?.startsWith('tamagui')) {
159
+ console.log('Loaded components', components)
160
+ }
161
+
162
+ cache[key] = {
163
+ components,
164
+ nameToPaths: {},
165
+ tamaguiConfig: config,
166
+ }
167
+
168
+ // init core-node
169
+ createTamagui(cache[key].tamaguiConfig)
170
+
171
+ resolver(cache[key])
172
+
173
+ return cache[key]
174
+ } finally {
175
+ unregisterRequire()
176
+ }
177
+ }
178
+
179
+ export function resolveWebOrNativeSpecificEntry(entry: string) {
180
+ const resolved = require.resolve(entry)
181
+ const ext = extname(resolved)
182
+ const fileName = basename(resolved).replace(ext, '')
183
+ const specificExt = process.env.TAMAGUI_TARGET === 'web' ? 'web' : 'native'
184
+ const specificFile = join(dirname(resolved), fileName + '.' + specificExt + ext)
185
+ if (existsSync(specificFile)) {
186
+ return specificFile
187
+ }
188
+ return entry
189
+ }
190
+
191
+ const esbuildOptions = {
192
+ loader: 'tsx',
193
+ target: 'es2018',
194
+ format: 'cjs',
195
+ jsx: 'transform',
196
+ platform: 'node',
197
+ } as const
198
+
199
+ // loads in-process using esbuild-register
200
+ export function loadTamaguiSync(props: Props): TamaguiProjectInfo {
201
+ const key = JSON.stringify(props)
202
+ if (cache[key]) {
203
+ return cache[key]
204
+ }
205
+
206
+ const { unregister } = require('esbuild-register/dist/node').register(esbuildOptions)
207
+
208
+ try {
209
+ registerRequire()
210
+
211
+ // lets shim require and avoid importing react-native + react-native-web
212
+ // we just need to read the config around them
213
+ process.env.IS_STATIC = 'is_static'
214
+ const devValueOG = globalThis['__DEV__' as any]
215
+ globalThis['__DEV__' as any] = process.env.NODE_ENV === 'development'
216
+
217
+ try {
218
+ // config
219
+ let tamaguiConfig: TamaguiInternalConfig | null = null
220
+ if (props.config) {
221
+ const configPath = join(process.cwd(), props.config)
222
+ const exp = require(configPath)
223
+ tamaguiConfig = (exp['default'] || exp) as TamaguiInternalConfig
224
+ if (!tamaguiConfig || !tamaguiConfig.parsed) {
225
+ const confPath = require.resolve(configPath)
226
+ throw new Error(`Can't find valid config in ${confPath}:
227
+
228
+ Be sure you "export default" the config.`)
229
+ }
230
+ }
231
+
232
+ // components
233
+ const components = loadComponents(props)
234
+ if (!components) {
235
+ throw new Error(`No components loaded`)
236
+ }
237
+ if (process.env.DEBUG === 'tamagui') {
238
+ console.log(`components`, components)
239
+ }
240
+
241
+ // undo shims
242
+ process.env.IS_STATIC = undefined
243
+ globalThis['__DEV__' as any] = devValueOG
244
+
245
+ // set up core-node
246
+ if (props.config && tamaguiConfig) {
247
+ createTamagui(tamaguiConfig as any)
248
+ }
249
+
250
+ cache[key] = {
251
+ components,
252
+ tamaguiConfig,
253
+ nameToPaths: getNameToPaths(),
254
+ }
255
+ } catch (err) {
256
+ if (err instanceof Error) {
257
+ console.warn(
258
+ `Error loading tamagui.config.ts (set DEBUG=tamagui to see full stack), running tamagui without custom config`
259
+ )
260
+ console.log(`\n\n ${err.message}\n\n`)
261
+ if (SHOULD_DEBUG) {
262
+ console.log(err.stack)
263
+ }
264
+ } else {
265
+ console.error(`Error loading tamagui.config.ts`, err)
266
+ }
267
+ return {
268
+ components: [],
269
+ tamaguiConfig: getDefaultTamaguiConfig(),
270
+ nameToPaths: {},
271
+ }
272
+ }
273
+
274
+ return cache[key]
275
+ } finally {
276
+ unregister()
277
+ unregisterRequire()
278
+ }
279
+ }
280
+
281
+ function interopDefaultExport(mod: any) {
282
+ return mod?.default ?? mod
283
+ }
284
+
285
+ const cacheComponents: Record<string, LoadedComponents[]> = {}
286
+
287
+ function transformAddExports(ast: t.File) {
288
+ const usedNames = new Set<string>()
289
+
290
+ // avoid clobbering
291
+ traverse(ast, {
292
+ ExportNamedDeclaration(nodePath) {
293
+ if (nodePath.node.specifiers) {
294
+ for (const spec of nodePath.node.specifiers) {
295
+ usedNames.add(t.isIdentifier(spec.exported) ? spec.exported.name : spec.exported.value)
296
+ }
297
+ }
298
+ },
299
+ })
300
+
301
+ traverse(ast, {
302
+ VariableDeclaration(nodePath) {
303
+ // top level only
304
+ if (!t.isProgram(nodePath.parent)) return
305
+ const decs = nodePath.node.declarations
306
+ if (decs.length > 1) return
307
+ const [dec] = decs
308
+ if (!t.isIdentifier(dec.id)) return
309
+ if (!dec.init) return
310
+ if (usedNames.has(dec.id.name)) return
311
+ usedNames.add(dec.id.name)
312
+ nodePath.replaceWith(
313
+ t.exportNamedDeclaration(t.variableDeclaration('let', [dec]), [
314
+ t.exportSpecifier(t.identifier(dec.id.name), t.identifier(dec.id.name)),
315
+ ])
316
+ )
317
+ },
318
+ })
319
+
320
+ return generate(ast as any, {
321
+ concise: false,
322
+ filename: 'test.tsx',
323
+ retainLines: false,
324
+ sourceMaps: false,
325
+ }).code
326
+ }
327
+
328
+ function loadComponents(props: Props): null | LoadedComponents[] {
329
+ const componentsModules = props.components
330
+ const key = componentsModules.join('')
331
+ if (cacheComponents[key]) {
332
+ return cacheComponents[key]
333
+ }
334
+ try {
335
+ const info: LoadedComponents[] = componentsModules.flatMap((name) => {
336
+ const extension = extname(name)
337
+ const isLocal = Boolean(extension)
338
+ // during props.config pass we are passing in pre-bundled stuff
339
+ const writeTmp = isLocal && !props.config
340
+ const fileContents = writeTmp ? readFileSync(name, 'utf-8') : ''
341
+ const loadModule = writeTmp
342
+ ? join(dirname(name), `.tamagui-dynamic-eval-${basename(name)}.tsx`)
343
+ : name
344
+ let writtenContents = fileContents
345
+ let didBabel = false
346
+
347
+ const esbuildit = (src: string, target?: 'modern') =>
348
+ esbuild.transformSync(src, {
349
+ ...esbuildOptions,
350
+ ...(target === 'modern' && {
351
+ target: 'es2022',
352
+ jsx: 'transform',
353
+ loader: 'tsx',
354
+ platform: 'neutral',
355
+ format: 'esm',
356
+ }),
357
+ }).code
358
+
359
+ function attemptLoad({ forceExports = false } = {}) {
360
+ // need to write to tsx to enable reading it properly (:/ esbuild-register)
361
+ if (writeTmp) {
362
+ writtenContents = forceExports
363
+ ? esbuildit(transformAddExports(babelParse(esbuildit(fileContents, 'modern'))))
364
+ : esbuildit(fileContents)
365
+
366
+ writeFileSync(loadModule, writtenContents)
367
+ }
368
+ return {
369
+ moduleName: name,
370
+ nameToInfo: getComponentStaticConfigByName(
371
+ name,
372
+ interopDefaultExport(require(loadModule))
373
+ ),
374
+ }
375
+ }
376
+
377
+ const dispose = () => {
378
+ writeTmp && removeSync(loadModule)
379
+ }
380
+
381
+ try {
382
+ const res = attemptLoad({
383
+ forceExports: true,
384
+ })
385
+ didBabel = true
386
+ return res
387
+ } catch (err) {
388
+ console.log('babel err', err, writtenContents)
389
+ // ok
390
+ writtenContents = fileContents
391
+ if (process.env.DEBUG?.startsWith('tamagui')) {
392
+ console.log(`Error parsing babel likely`, err)
393
+ }
394
+ } finally {
395
+ dispose()
396
+ }
397
+
398
+ try {
399
+ return attemptLoad({
400
+ forceExports: false,
401
+ })
402
+ } catch (err) {
403
+ if (!process.env.TAMAGUI_DISABLE_WARN_DYNAMIC_LOAD) {
404
+ console.log(`
405
+
406
+ Tamagui attempted but failed to dynamically load components in:
407
+ ${name}
408
+
409
+ This will leave some styled() tags unoptimized.
410
+ Disable this file (or dynamic loading altogether):
411
+
412
+ disableExtractFoundComponents: ['${name}'] | true
413
+
414
+ Quiet this warning with environment variable:
415
+
416
+ TAMAGUI_DISABLE_WARN_DYNAMIC_LOAD=1
417
+
418
+ `)
419
+ console.log(err)
420
+ console.log(
421
+ `At: ${loadModule}`,
422
+ `\ndidBabel: ${didBabel}`,
423
+ `\nIn:`,
424
+ writtenContents,
425
+ `\nwriteTmp: `,
426
+ writeTmp
427
+ )
428
+ }
429
+ return []
430
+ } finally {
431
+ dispose()
432
+ }
433
+ })
434
+ cacheComponents[key] = info
435
+ return info
436
+ } catch (err: any) {
437
+ console.log(`Tamagui error bundling components`, err.message, err.stack)
438
+ return null
439
+ }
440
+ }
441
+
442
+ function getComponentStaticConfigByName(name: string, exported: any) {
443
+ if (!exported || typeof exported !== 'object' || Array.isArray(exported)) {
444
+ throw new Error(`Invalid export from package ${name}: ${typeof exported}`)
445
+ }
446
+ const components: Record<string, { staticConfig: StaticConfigParsed }> = {}
447
+ try {
448
+ for (const key in exported) {
449
+ const found = getTamaguiComponent(key, exported[key])
450
+ if (found) {
451
+ // remove non-stringifyable
452
+ const { Component, ...sc } = found.staticConfig
453
+ components[key] = { staticConfig: sc }
454
+ }
455
+ }
456
+ } catch (err) {
457
+ console.error(`Tamagui failed getting components`)
458
+ if (err instanceof Error) {
459
+ console.error(err.message, err.stack)
460
+ } else {
461
+ console.error(err)
462
+ }
463
+ }
464
+ return components
465
+ }
466
+
467
+ function getTamaguiComponent(
468
+ name: string,
469
+ Component: any
470
+ ): undefined | { staticConfig: StaticConfigParsed } {
471
+ if (name[0].toUpperCase() !== name[0]) {
472
+ return
473
+ }
474
+ const staticConfig = Component?.staticConfig as StaticConfigParsed | undefined
475
+ if (staticConfig) {
476
+ return Component
477
+ }
478
+ }
@@ -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
+ }