@tamagui/static 1.15.32 → 1.15.34

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 (47) hide show
  1. package/dist/cjs/extractor/bundleConfig.js +131 -82
  2. package/dist/cjs/extractor/bundleConfig.js.map +1 -1
  3. package/dist/cjs/extractor/createExtractor.js +13 -20
  4. package/dist/cjs/extractor/createExtractor.js.map +1 -1
  5. package/dist/cjs/extractor/generateTamaguiStudioConfig.js +101 -0
  6. package/dist/cjs/extractor/generateTamaguiStudioConfig.js.map +6 -0
  7. package/dist/cjs/extractor/loadTamagui.js +65 -75
  8. package/dist/cjs/extractor/loadTamagui.js.map +1 -1
  9. package/dist/cjs/require.js +7 -10
  10. package/dist/cjs/require.js.map +1 -1
  11. package/dist/esm/extractor/bundleConfig.js +129 -82
  12. package/dist/esm/extractor/bundleConfig.js.map +1 -1
  13. package/dist/esm/extractor/bundleConfig.mjs +129 -82
  14. package/dist/esm/extractor/bundleConfig.mjs.map +1 -1
  15. package/dist/esm/extractor/createExtractor.js +13 -20
  16. package/dist/esm/extractor/createExtractor.js.map +1 -1
  17. package/dist/esm/extractor/createExtractor.mjs +13 -20
  18. package/dist/esm/extractor/createExtractor.mjs.map +1 -1
  19. package/dist/esm/extractor/generateTamaguiStudioConfig.js +66 -0
  20. package/dist/esm/extractor/generateTamaguiStudioConfig.js.map +6 -0
  21. package/dist/esm/extractor/generateTamaguiStudioConfig.mjs +66 -0
  22. package/dist/esm/extractor/generateTamaguiStudioConfig.mjs.map +6 -0
  23. package/dist/esm/extractor/loadTamagui.js +70 -76
  24. package/dist/esm/extractor/loadTamagui.js.map +1 -1
  25. package/dist/esm/extractor/loadTamagui.mjs +70 -76
  26. package/dist/esm/extractor/loadTamagui.mjs.map +1 -1
  27. package/dist/esm/require.js +6 -8
  28. package/dist/esm/require.js.map +1 -1
  29. package/dist/esm/require.mjs +6 -8
  30. package/dist/esm/require.mjs.map +1 -1
  31. package/package.json +14 -14
  32. package/src/extractor/bundleConfig.ts +162 -106
  33. package/src/extractor/createExtractor.ts +13 -21
  34. package/src/extractor/generateTamaguiStudioConfig.ts +99 -0
  35. package/src/extractor/loadTamagui.ts +85 -95
  36. package/src/require.ts +6 -8
  37. package/types/extractor/bundleConfig.d.ts +10 -7
  38. package/types/extractor/bundleConfig.d.ts.map +1 -1
  39. package/types/extractor/createExtractor.d.ts.map +1 -1
  40. package/types/extractor/generateTamaguiConfig.d.ts +2 -1
  41. package/types/extractor/generateTamaguiStudioConfig.d.ts +8 -0
  42. package/types/extractor/generateTamaguiStudioConfig.d.ts.map +1 -0
  43. package/types/extractor/loadTamagui.d.ts +18 -7
  44. package/types/extractor/loadTamagui.d.ts.map +1 -1
  45. package/types/require.d.ts +1 -2
  46. package/types/require.d.ts.map +1 -1
  47. package/src/extractor/generateTamaguiConfig.ts +0 -65
@@ -9,6 +9,8 @@ import type { StaticConfigParsed, TamaguiInternalConfig } from '@tamagui/web'
9
9
  import esbuild from 'esbuild'
10
10
  import { ensureDir, removeSync, writeFileSync } from 'fs-extra'
11
11
 
12
+ import { registerRequire } from '../require.js'
13
+ import { TamaguiOptions } from '../types.js'
12
14
  import { babelParse } from './babelParse.js'
13
15
  import { bundle } from './bundle.js'
14
16
 
@@ -34,12 +36,6 @@ export type TamaguiProjectInfo = {
34
36
  nameToPaths: NameToPaths
35
37
  }
36
38
 
37
- export type Props = {
38
- components: string[]
39
- config?: string
40
- forceExports?: boolean
41
- }
42
-
43
39
  const external = [
44
40
  '@tamagui/core',
45
41
  '@tamagui/web',
@@ -57,123 +53,176 @@ export const esbuildOptions = {
57
53
  platform: 'node',
58
54
  } as const
59
55
 
60
- export async function bundleConfig(props: Props) {
61
- const configEntry = props.config ? join(process.cwd(), props.config) : ''
62
- const tmpDir = join(process.cwd(), '.tamagui')
63
- const configOutPath = join(tmpDir, `tamagui.config.cjs`)
64
- const baseComponents = props.components.filter((x) => x !== '@tamagui/core')
65
- const componentOutPaths = baseComponents.map((componentModule) =>
66
- join(
67
- tmpDir,
68
- `${componentModule
69
- .split(sep)
70
- .join('-')
71
- .replace(/[^a-z0-9]+/gi, '')}-components.config.cjs`
72
- )
73
- )
56
+ export type BundledConfig = Awaited<ReturnType<typeof bundleConfig>>
74
57
 
75
- if (
76
- process.env.NODE_ENV === 'development' &&
77
- process.env.DEBUG?.startsWith('tamagui')
78
- ) {
79
- console.log(`Building config entry`, configEntry)
58
+ // will use cached one if watching
59
+ let currentConfig: BundledConfig
60
+ let isBundling = false
61
+ const waitForBundle = new Set<Function>()
62
+
63
+ let last: BundledConfig | undefined
64
+ export async function hasBundledConfigChanged() {
65
+ if (last === currentConfig) {
66
+ return false
80
67
  }
68
+ last = currentConfig
69
+ return true
70
+ }
81
71
 
82
- // build them to node-compat versions
83
- try {
84
- await ensureDir(tmpDir)
85
- } catch {
86
- //
72
+ export async function getBundledConfig(props: TamaguiOptions, rebuild = false) {
73
+ if (isBundling) {
74
+ await new Promise((res) => {
75
+ waitForBundle.add(res)
76
+ })
77
+ } else if (!currentConfig || rebuild) {
78
+ await bundleConfig(props)
87
79
  }
80
+ return currentConfig
81
+ }
88
82
 
89
- if (!loggedOutputInfo) {
90
- loggedOutputInfo = true
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 ${[
101
- ...componentOutPaths.map((p) => `.${sep}${relative(process.cwd(), p)}`),
102
- ].join('\n ')}
103
- `
83
+ export async function bundleConfig(props: TamaguiOptions) {
84
+ try {
85
+ isBundling = true
86
+
87
+ const configEntry = props.config ? join(process.cwd(), props.config) : ''
88
+ const tmpDir = join(process.cwd(), '.tamagui')
89
+
90
+ const configOutPath = join(tmpDir, `tamagui.config.cjs`)
91
+
92
+ const baseComponents = props.components.filter((x) => x !== '@tamagui/core')
93
+ const componentOutPaths = baseComponents.map((componentModule) =>
94
+ join(
95
+ tmpDir,
96
+ `${componentModule
97
+ .split(sep)
98
+ .join('-')
99
+ .replace(/[^a-z0-9]+/gi, '')}-components.config.cjs`
100
+ )
104
101
  )
105
- }
106
102
 
107
- await Promise.all([
108
- props.config
109
- ? bundle({
110
- entryPoints: [configEntry],
103
+ if (
104
+ process.env.NODE_ENV === 'development' &&
105
+ process.env.DEBUG?.startsWith('tamagui')
106
+ ) {
107
+ console.log(`Building config entry`, configEntry)
108
+ }
109
+
110
+ // build them to node-compat versions
111
+ try {
112
+ await ensureDir(tmpDir)
113
+ } catch {
114
+ //
115
+ }
116
+
117
+ const start = Date.now()
118
+
119
+ await Promise.all([
120
+ props.config
121
+ ? bundle({
122
+ entryPoints: [configEntry],
123
+ external,
124
+ outfile: configOutPath,
125
+ })
126
+ : null,
127
+ ...baseComponents.map((componentModule, i) => {
128
+ return bundle({
129
+ entryPoints: [componentModule],
130
+ resolvePlatformSpecificEntries: true,
111
131
  external,
112
- outfile: configOutPath,
132
+ outfile: componentOutPaths[i],
113
133
  })
114
- : null,
115
- ...baseComponents.map((componentModule, i) => {
116
- return bundle({
117
- entryPoints: [componentModule],
118
- resolvePlatformSpecificEntries: true,
119
- external,
120
- outfile: componentOutPaths[i],
121
- })
122
- }),
123
- ])
134
+ }),
135
+ ])
136
+
137
+ if (!loggedOutputInfo) {
138
+ loggedOutputInfo = true
139
+ colorLog(
140
+ Color.FgYellow,
141
+ `
142
+ Tamagui built config and components (${Date.now() - start}ms):`
143
+ )
144
+ colorLog(
145
+ Color.Dim,
146
+ `
147
+ Config .${sep}${relative(process.cwd(), configOutPath)}
148
+ Components ${[
149
+ ...componentOutPaths.map((p) => `.${sep}${relative(process.cwd(), p)}`),
150
+ ].join('\n ')}
151
+ `
152
+ )
153
+ }
124
154
 
125
- // get around node.js's module cache to get the new config...
126
- delete require.cache[path.resolve(configOutPath)]
155
+ // get around node.js's module cache to get the new config...
156
+ delete require.cache[path.resolve(configOutPath)]
127
157
 
128
- const out = require(configOutPath)
158
+ const out = require(configOutPath)
129
159
 
130
- const config = out.default || out
131
- if (!config) {
132
- throw new Error(`No config: ${config}`)
133
- }
160
+ const config = out.default || out
161
+ if (!config) {
162
+ throw new Error(`No config: ${config}`)
163
+ }
134
164
 
135
- let components = loadComponents({
136
- ...props,
137
- components: componentOutPaths,
138
- })
165
+ let components = loadComponents({
166
+ ...props,
167
+ components: componentOutPaths,
168
+ })
139
169
 
140
- if (!components) {
141
- throw new Error(`No components found: ${componentOutPaths.join(', ')}`)
142
- }
170
+ if (!components) {
171
+ throw new Error(`No components found: ${componentOutPaths.join(', ')}`)
172
+ }
143
173
 
144
- // map from built back to original module names
145
- for (const component of components) {
146
- component.moduleName = baseComponents[componentOutPaths.indexOf(component.moduleName)]
174
+ // map from built back to original module names
175
+ for (const component of components) {
176
+ component.moduleName =
177
+ baseComponents[componentOutPaths.indexOf(component.moduleName)]
178
+
179
+ if (!component.moduleName) {
180
+ console.warn(
181
+ `⚠️ no module name found: ${component.moduleName} ${JSON.stringify(
182
+ baseComponents
183
+ )} in ${JSON.stringify(componentOutPaths)}`
184
+ )
185
+ }
147
186
 
148
- // if (!component.moduleName) {
149
- // throw new Error(`Tamagui internal err`)
150
- // }
151
- }
187
+ // if (!component.moduleName) {
188
+ // throw new Error(`Tamagui internal err`)
189
+ // }
190
+ }
152
191
 
153
- // always load core so we can optimize if directly importing
154
- const coreComponents = loadComponents({
155
- ...props,
156
- components: ['@tamagui/core-node'],
157
- })
158
- if (coreComponents) {
159
- coreComponents[0].moduleName = '@tamagui/core'
160
- components = [...components, ...coreComponents]
161
- }
192
+ // always load core so we can optimize if directly importing
193
+ const coreComponents = loadComponents({
194
+ ...props,
195
+ components: ['@tamagui/core-node'],
196
+ })
197
+ if (coreComponents) {
198
+ coreComponents[0].moduleName = '@tamagui/core'
199
+ components = [...components, ...coreComponents]
200
+ }
162
201
 
163
- if (
164
- process.env.NODE_ENV === 'development' &&
165
- process.env.DEBUG?.startsWith('tamagui')
166
- ) {
167
- console.log('Loaded components', components)
168
- }
169
- return {
170
- components,
171
- nameToPaths: {},
172
- tamaguiConfig: config,
202
+ if (
203
+ process.env.NODE_ENV === 'development' &&
204
+ process.env.DEBUG?.startsWith('tamagui')
205
+ ) {
206
+ console.log('Loaded components', components)
207
+ }
208
+
209
+ const res = {
210
+ components,
211
+ nameToPaths: {},
212
+ tamaguiConfig: config,
213
+ }
214
+
215
+ currentConfig = res
216
+
217
+ return res
218
+ } finally {
219
+ isBundling = false
220
+ waitForBundle.forEach((cb) => cb())
221
+ waitForBundle.clear()
173
222
  }
174
223
  }
175
224
 
176
- export function loadComponents(props: Props): null | LoadedComponents[] {
225
+ export function loadComponents(props: TamaguiOptions): null | LoadedComponents[] {
177
226
  const componentsModules = props.components
178
227
  const key = componentsModules.join('')
179
228
  if (cacheComponents[key]) {
@@ -213,12 +262,19 @@ export function loadComponents(props: Props): null | LoadedComponents[] {
213
262
  console.log(`loadModule`, loadModule, require.resolve(loadModule))
214
263
  }
215
264
 
216
- return {
217
- moduleName: name,
218
- nameToInfo: getComponentStaticConfigByName(
265
+ const unregister = registerRequire()
266
+ try {
267
+ const nameToInfo = getComponentStaticConfigByName(
219
268
  name,
220
269
  interopDefaultExport(require(loadModule))
221
- ),
270
+ )
271
+
272
+ return {
273
+ moduleName: name,
274
+ nameToInfo,
275
+ }
276
+ } finally {
277
+ unregister()
222
278
  }
223
279
  }
224
280
 
@@ -105,17 +105,11 @@ export function createExtractor(
105
105
  // otherwise we'd import `rnw` and cause it to evaluate react-native-web which causes errors
106
106
 
107
107
  function loadSync(props: TamaguiOptions) {
108
- return (projectInfo ||= loadTamaguiSync({
109
- config: props.config || 'tamagui.config.ts',
110
- components: props.components || ['tamagui'],
111
- }))
108
+ return (projectInfo ||= loadTamaguiSync(props))
112
109
  }
113
110
 
114
111
  async function load(props: TamaguiOptions) {
115
- return (projectInfo ||= await loadTamagui({
116
- config: props.config || 'tamagui.config.ts',
117
- components: props.components || ['tamagui'],
118
- }))
112
+ return (projectInfo ||= await loadTamagui(props))
119
113
  }
120
114
 
121
115
  return {
@@ -196,8 +190,8 @@ export function createExtractor(
196
190
  return false
197
191
  }
198
192
  return !!(
199
- !!staticConfig.validStyles?.[name] ||
200
- !!pseudoDescriptors[name] ||
193
+ staticConfig.validStyles?.[name] ||
194
+ pseudoDescriptors[name] ||
201
195
  // dont disable variants or else you lose many things flattening
202
196
  staticConfig.variants?.[name] ||
203
197
  projectInfo?.tamaguiConfig.shorthands[name] ||
@@ -231,14 +225,12 @@ export function createExtractor(
231
225
  )
232
226
  }
233
227
  if (process.env.DEBUG?.startsWith('tamagui')) {
234
- const next = [...propsWithFileInfo.allLoadedComponents].map((info) => {
235
- const nameToInfo = { ...info.nameToInfo }
236
- for (const key in nameToInfo) {
237
- delete nameToInfo[key].staticConfig.validStyles
238
- }
239
- return { ...info, nameToInfo }
240
- })
241
- logger.info(['loaded:', JSON.stringify(next, null, 2)].join('\n'))
228
+ logger.info(
229
+ [
230
+ 'loaded:',
231
+ JSON.stringify(propsWithFileInfo.allLoadedComponents, null, 2),
232
+ ].join('\n')
233
+ )
242
234
  }
243
235
  }
244
236
 
@@ -328,9 +320,9 @@ export function createExtractor(
328
320
  )
329
321
  if (shouldPrintDebug === 'verbose') {
330
322
  logger.info(
331
- `import ${names.join(
323
+ ` - import ${isValidComponent ? '✅' : '⇣'} - ${names.join(
332
324
  ', '
333
- )} from ${moduleName} isValidComponent ${isValidComponent}`
325
+ )} from '${moduleName}'`
334
326
  )
335
327
  }
336
328
  if (isValidComponent) {
@@ -342,7 +334,7 @@ export function createExtractor(
342
334
 
343
335
  if (shouldPrintDebug) {
344
336
  logger.info(
345
- `file: ${sourcePath} ${JSON.stringify({ doesUseValidImport, hasImportedTheme })}`
337
+ `${JSON.stringify({ doesUseValidImport, hasImportedTheme }, null, 2)}\n`
346
338
  )
347
339
  }
348
340
 
@@ -0,0 +1,99 @@
1
+ import { join } from 'path'
2
+
3
+ import { getVariableValue } from '@tamagui/core-node'
4
+ import { TamaguiOptions } from '@tamagui/types'
5
+ import fs from 'fs-extra'
6
+
7
+ import { BundledConfig, getBundledConfig } from './bundleConfig.js'
8
+
9
+ const confFile = join(process.cwd(), '.tamagui', 'tamagui.config.json')
10
+
11
+ /**
12
+ * Sort of a super-set of bundleConfig(), this code needs some refactoring ideally
13
+ */
14
+
15
+ export async function generateTamaguiStudioConfig(
16
+ tamaguiOptions: TamaguiOptions,
17
+ configIn?: BundledConfig | null,
18
+ rebuild = false
19
+ ) {
20
+ const config = configIn ?? (await getBundledConfig(tamaguiOptions, rebuild))
21
+ await fs.writeJSON(
22
+ confFile,
23
+ {
24
+ ...config,
25
+ tamaguiConfig: transformConfig(config),
26
+ },
27
+ {
28
+ spaces: 2,
29
+ }
30
+ )
31
+ }
32
+
33
+ export function generateTamaguiStudioConfigSync(
34
+ _tamaguiOptions: TamaguiOptions,
35
+ config: BundledConfig
36
+ ) {
37
+ fs.writeJSONSync(
38
+ confFile,
39
+ {
40
+ ...config,
41
+ tamaguiConfig: transformConfig(config),
42
+ },
43
+ {
44
+ spaces: 2,
45
+ }
46
+ )
47
+ }
48
+
49
+ function transformConfig(config: BundledConfig) {
50
+ // ensure we don't mangle anything in the original
51
+ const next = JSON.parse(JSON.stringify(config))
52
+
53
+ const { components, nameToPaths } = next
54
+ const { themes, tokens } = next.tamaguiConfig
55
+
56
+ // reduce down to usable, smaller json
57
+
58
+ // slim themes, add name
59
+ for (const key in themes) {
60
+ const theme = themes[key]
61
+ // @ts-ignore
62
+ theme.id = key
63
+ for (const tkey in theme) {
64
+ theme[tkey] = getVariableValue(theme[tkey])
65
+ }
66
+ }
67
+
68
+ // flatten variables
69
+ for (const key in tokens) {
70
+ const token = { ...tokens[key] }
71
+ for (const tkey in token) {
72
+ token[tkey] = getVariableValue(token[tkey])
73
+ }
74
+ }
75
+
76
+ // remove bulky stuff in components
77
+ for (const component of components) {
78
+ for (const _ in component.nameToInfo) {
79
+ // avoid mutating
80
+ const compDefinition = { ...component.nameToInfo[_] }
81
+ component.nameToInfo[_] = compDefinition
82
+
83
+ const { parentStaticConfig, ...rest } = compDefinition.staticConfig
84
+ compDefinition.staticConfig = rest
85
+ }
86
+ }
87
+
88
+ // set to array
89
+ for (const key in nameToPaths) {
90
+ // @ts-ignore
91
+ nameToPaths[key] = [...nameToPaths[key]]
92
+ }
93
+
94
+ // remove stuff we dont need to send
95
+ const { fontsParsed, getCSS, tokensParsed, themeConfig, ...cleanedConfig } =
96
+ next.tamaguiConfig
97
+
98
+ return cleanedConfig
99
+ }