@tamagui/build 2.7.7 → 3.0.0-beta.643.1

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 (53) hide show
  1. package/README.md +19 -0
  2. package/package.json +27 -5
  3. package/pretty-print-errors.js +0 -31
  4. package/tamagui-build-workspace.js +296 -0
  5. package/tamagui-build.js +466 -206
  6. package/tamagui-tsgo.js +14 -0
  7. package/typescript-native.js +13 -0
  8. package/.turbo/turbo-test$colon$web.log +0 -68
  9. package/.turbo/turbo-test.log +0 -44
  10. package/__tests__/fixtures/js-main-package/.turbo/turbo-build.log +0 -2
  11. package/__tests__/fixtures/js-main-package/LICENSE +0 -1
  12. package/__tests__/fixtures/js-main-package/dist/cjs/index.js +0 -24
  13. package/__tests__/fixtures/js-main-package/dist/cjs/index.js.map +0 -6
  14. package/__tests__/fixtures/js-main-package/dist/cjs/index.native.js +0 -31
  15. package/__tests__/fixtures/js-main-package/dist/cjs/index.native.js.map +0 -1
  16. package/__tests__/fixtures/js-main-package/dist/esm/index.mjs +0 -3
  17. package/__tests__/fixtures/js-main-package/dist/esm/index.mjs.map +0 -1
  18. package/__tests__/fixtures/js-main-package/dist/esm/index.native.js +0 -3
  19. package/__tests__/fixtures/js-main-package/dist/esm/index.native.js.map +0 -1
  20. package/__tests__/fixtures/js-main-package/package.json +0 -14
  21. package/__tests__/fixtures/js-main-package/src/index.ts +0 -1
  22. package/__tests__/fixtures/js-main-package/tsconfig.json +0 -13
  23. package/__tests__/fixtures/js-main-package/types/index.d.ts +0 -2
  24. package/__tests__/fixtures/js-main-package/types/index.d.ts.map +0 -1
  25. package/__tests__/fixtures/simple-package/.turbo/turbo-build.log +0 -2
  26. package/__tests__/fixtures/simple-package/LICENSE +0 -21
  27. package/__tests__/fixtures/simple-package/index.d.ts +0 -2
  28. package/__tests__/fixtures/simple-package/index.d.ts.map +0 -1
  29. package/__tests__/fixtures/simple-package/package.json +0 -25
  30. package/__tests__/fixtures/simple-package/src/index.ts +0 -71
  31. package/__tests__/fixtures/simple-package/src/nativeOnly.ts +0 -3
  32. package/__tests__/fixtures/simple-package/src/nested/index.ts +0 -1
  33. package/__tests__/fixtures/simple-package/tsconfig.json +0 -42
  34. package/__tests__/fixtures/subpath-only-package/.turbo/turbo-build.log +0 -3
  35. package/__tests__/fixtures/subpath-only-package/dist/cjs/feature.cjs +0 -25
  36. package/__tests__/fixtures/subpath-only-package/dist/cjs/feature.native.cjs +0 -27
  37. package/__tests__/fixtures/subpath-only-package/dist/cjs/feature.native.js +0 -29
  38. package/__tests__/fixtures/subpath-only-package/dist/cjs/feature.native.js.map +0 -1
  39. package/__tests__/fixtures/subpath-only-package/dist/esm/feature.mjs +0 -4
  40. package/__tests__/fixtures/subpath-only-package/dist/esm/feature.mjs.map +0 -1
  41. package/__tests__/fixtures/subpath-only-package/dist/esm/feature.native.js +0 -4
  42. package/__tests__/fixtures/subpath-only-package/dist/esm/feature.native.js.map +0 -1
  43. package/__tests__/fixtures/subpath-only-package/types/feature.d.ts.map +0 -11
  44. package/__tests__/fixtures/watch-package/.turbo/turbo-build.log +0 -2
  45. package/__tests__/fixtures/watch-package/LICENSE +0 -21
  46. package/__tests__/fixtures/watch-package/index.d.ts +0 -2
  47. package/__tests__/fixtures/watch-package/index.d.ts.map +0 -1
  48. package/__tests__/fixtures/watch-package/package.json +0 -22
  49. package/__tests__/fixtures/watch-package/src/watch.ts +0 -3
  50. package/__tests__/fixtures/watch-package/tsconfig.json +0 -42
  51. package/__tests__/fixtures/watch-package/watch.d.ts +0 -2
  52. package/__tests__/fixtures/watch-package/watch.d.ts.map +0 -1
  53. package/__tests__/integration.test.ts +0 -341
package/README.md CHANGED
@@ -61,6 +61,25 @@ It assumes your package.json looks something like this:
61
61
  }
62
62
  ```
63
63
 
64
+ Packages that intentionally expose only subpaths can omit `main`, `module`, and
65
+ `types` so those fields do not advertise a root entry. Declare the build outputs
66
+ directly instead:
67
+
68
+ ```json
69
+ {
70
+ "exports": {
71
+ "./feature": {
72
+ "types": "./types/feature.d.ts",
73
+ "import": "./dist/esm/feature.mjs",
74
+ "require": "./dist/cjs/feature.cjs"
75
+ }
76
+ },
77
+ "tamagui-build": {
78
+ "outputs": ["cjs", "esm", "types"]
79
+ }
80
+ }
81
+ ```
82
+
64
83
  ### Install
65
84
 
66
85
  `npx @tamagui/build` or install and use the CLI:
package/package.json CHANGED
@@ -1,9 +1,23 @@
1
1
  {
2
2
  "name": "@tamagui/build",
3
- "version": "2.7.7",
3
+ "version": "3.0.0-beta.643.1",
4
4
  "gitHead": "a49cc7ea6b93ba384e77a4880ae48ac4a5635c14",
5
+ "files": [
6
+ "babel-plugin-process-env-to-meta.js",
7
+ "babel-plugin-process-env-to-meta.ts",
8
+ "esbuild-es5.js",
9
+ "externalNodePlugin.js",
10
+ "pretty-print-errors.js",
11
+ "tamagui-build.js",
12
+ "tamagui-build-workspace.js",
13
+ "tamagui-tsgo.js",
14
+ "typescript-native.js",
15
+ "teesx.sh"
16
+ ],
5
17
  "bin": {
6
18
  "tamagui-build": "tamagui-build.js",
19
+ "tamagui-build-workspace": "tamagui-build-workspace.js",
20
+ "tamagui-tsgo": "tamagui-tsgo.js",
7
21
  "teesx": "teesx.sh"
8
22
  },
9
23
  "publishConfig": {
@@ -17,20 +31,28 @@
17
31
  "@babel/core": "^7.25.2",
18
32
  "@babel/preset-typescript": "^7.26.0",
19
33
  "@swc/core": "^1.14.0",
20
- "@tamagui/babel-plugin-fully-specified": "2.7.7",
21
34
  "@types/fs-extra": "^9.0.13",
22
35
  "baseline-browser-mapping": "^2.9.15",
23
36
  "chokidar": "^3.5.2",
24
- "esbuild": "^0.27.2",
37
+ "esbuild": "0.28.1",
25
38
  "esbuild-register": "^3.6.0",
26
39
  "execa": "^5.0.0",
27
40
  "fast-glob": "^3.2.11",
28
41
  "fs-extra": "^11.2.0",
42
+ "get-tsconfig": "^4.14.0",
29
43
  "lodash.debounce": "^4.0.8",
30
44
  "oxc-transform": "^0.112.0",
31
45
  "picomatch": "4.0.3",
32
- "rolldown": "1.0.1",
33
- "typescript": "~5.9.2"
46
+ "rolldown": "1.0.1"
47
+ },
48
+ "optionalDependencies": {
49
+ "@typescript/typescript-darwin-arm64": "7.1.0-dev.20260722.1",
50
+ "@typescript/typescript-darwin-x64": "7.1.0-dev.20260722.1",
51
+ "@typescript/typescript-linux-arm": "7.1.0-dev.20260722.1",
52
+ "@typescript/typescript-linux-arm64": "7.1.0-dev.20260722.1",
53
+ "@typescript/typescript-linux-x64": "7.1.0-dev.20260722.1",
54
+ "@typescript/typescript-win32-arm64": "7.1.0-dev.20260722.1",
55
+ "@typescript/typescript-win32-x64": "7.1.0-dev.20260722.1"
34
56
  },
35
57
  "peerDependencies": {
36
58
  "babel-plugin-react-compiler": ">=1"
@@ -1,35 +1,5 @@
1
1
  /* eslint-disable no-console */
2
2
 
3
- /**
4
- * Pretty print TypeScript diagnostics with file location and error codes
5
- * @param {import('typescript').Diagnostic[]} diagnostics
6
- * @param {import('typescript')} ts
7
- */
8
- function printTypescriptDiagnostics(diagnostics, ts) {
9
- console.error('\n❌ TypeScript compilation errors:\n')
10
-
11
- diagnostics.forEach((diagnostic) => {
12
- const messageText =
13
- typeof diagnostic.messageText === 'string'
14
- ? diagnostic.messageText
15
- : diagnostic.messageText?.messageText || JSON.stringify(diagnostic.messageText)
16
-
17
- if (diagnostic.file && diagnostic.start !== undefined) {
18
- const { line, character } = ts.getLineAndCharacterOfPosition(
19
- diagnostic.file,
20
- diagnostic.start
21
- )
22
- console.error(
23
- ` ${diagnostic.file.fileName}:${line + 1}:${character + 1} - error TS${diagnostic.code}: ${messageText}`
24
- )
25
- } else {
26
- console.error(` error TS${diagnostic.code}: ${messageText}`)
27
- }
28
- })
29
-
30
- console.error('')
31
- }
32
-
33
3
  /**
34
4
  * Pretty print esbuild errors with file location and code snippets
35
5
  * @param {Error & { errors?: any[], warnings?: any[] }} err
@@ -158,7 +128,6 @@ function printOxcErrors(errors) {
158
128
  }
159
129
 
160
130
  module.exports = {
161
- printTypescriptDiagnostics,
162
131
  printEsbuildError,
163
132
  printBuildError,
164
133
  printTypescriptCompilationError,
@@ -0,0 +1,296 @@
1
+ #!/usr/bin/env node
2
+ /* eslint-disable no-console */
3
+
4
+ const { spawn } = require('node:child_process')
5
+ const os = require('node:os')
6
+ const path = require('node:path')
7
+ const FSE = require('fs-extra')
8
+ const fastGlob = require('fast-glob')
9
+ const chokidar = require('chokidar')
10
+
11
+ const args = process.argv.slice(2)
12
+ const root = path.resolve(readOption('--root') || process.cwd())
13
+ const shouldWatch = args.includes('--watch')
14
+ const shouldList = args.includes('--list')
15
+ const requestedScript = readOption('--script')
16
+ const skipInitialBuild = Boolean(process.env.SKIP_INITIAL_BUILD)
17
+ const requestedConcurrency = Number(readOption('--concurrency'))
18
+ const concurrency =
19
+ Number.isInteger(requestedConcurrency) && requestedConcurrency > 0
20
+ ? requestedConcurrency
21
+ : Math.min(8, os.availableParallelism())
22
+ const filters = readOptions('--filter')
23
+ const buildScript = path.join(__dirname, 'tamagui-build.js')
24
+
25
+ function readOption(name) {
26
+ const index = args.indexOf(name)
27
+ return index === -1 ? null : args[index + 1]
28
+ }
29
+
30
+ function readOptions(name) {
31
+ const values = []
32
+ for (let index = 0; index < args.length; index++) {
33
+ if (args[index] === name && args[index + 1]) {
34
+ values.push(args[index + 1])
35
+ }
36
+ }
37
+ return values
38
+ }
39
+
40
+ function getBuildArgs(command) {
41
+ const tokens = command.split(/\s+/).filter(Boolean)
42
+ const commandIndex = tokens.findIndex(
43
+ (token) => token === 'tamagui-build' || token.endsWith('/tamagui-build.js')
44
+ )
45
+ if (commandIndex === -1) return null
46
+
47
+ const packageArgs = tokens.slice(commandIndex + 1)
48
+ const output = packageArgs.filter((arg) => arg !== '--watch')
49
+
50
+ if (args.includes('--skip-types') && !output.includes('--skip-types')) {
51
+ output.push('--skip-types')
52
+ }
53
+
54
+ return output
55
+ }
56
+
57
+ function getWorkspacePackages() {
58
+ const rootPackage = FSE.readJSONSync(path.join(root, 'package.json'))
59
+ const workspaces = Array.isArray(rootPackage.workspaces)
60
+ ? rootPackage.workspaces
61
+ : rootPackage.workspaces?.packages || []
62
+ const packageJsonPatterns = workspaces.map((workspace) =>
63
+ path.posix.join(workspace.replace(/^\.\//, ''), 'package.json')
64
+ )
65
+ const packageJsonPaths = fastGlob.sync(packageJsonPatterns, {
66
+ cwd: root,
67
+ absolute: true,
68
+ onlyFiles: true,
69
+ ignore: ['**/node_modules/**', '**/dist/**'],
70
+ })
71
+
72
+ return packageJsonPaths
73
+ .map((packageJsonPath) => {
74
+ const packageRoot = path.dirname(packageJsonPath)
75
+ const packageJson = FSE.readJSONSync(packageJsonPath)
76
+ const selectedScript = requestedScript
77
+ ? packageJson.scripts?.[requestedScript]
78
+ ? requestedScript
79
+ : null
80
+ : shouldWatch
81
+ ? packageJson.scripts?.watch
82
+ ? 'watch'
83
+ : packageJson.scripts?.['build:watch']
84
+ ? 'build:watch'
85
+ : null
86
+ : packageJson.scripts?.build
87
+ ? 'build'
88
+ : null
89
+ const selectedCommand = selectedScript ? packageJson.scripts[selectedScript] : null
90
+ if (!selectedCommand) return null
91
+
92
+ const packageArgs = getBuildArgs(selectedCommand)
93
+ if (
94
+ requestedScript === 'clean:build' &&
95
+ packageArgs &&
96
+ getBuildArgs(packageJson.scripts?.build || '')?.includes('--skip-types')
97
+ ) {
98
+ packageArgs.push('--skip-types')
99
+ }
100
+
101
+ if (filters.length && !filters.includes(packageJson.name)) return null
102
+
103
+ return {
104
+ name: packageJson.name,
105
+ root: packageRoot,
106
+ src: path.join(packageRoot, 'src'),
107
+ args: packageArgs,
108
+ script: packageArgs ? null : selectedScript,
109
+ dependencies: Object.keys({
110
+ ...packageJson.dependencies,
111
+ ...packageJson.devDependencies,
112
+ ...packageJson.optionalDependencies,
113
+ }),
114
+ }
115
+ })
116
+ .filter(Boolean)
117
+ .sort((a, b) => a.name.localeCompare(b.name))
118
+ }
119
+
120
+ const packages = getWorkspacePackages()
121
+ const packageNames = new Set(packages.map((item) => item.name))
122
+ const scheduledBuilds = new Set()
123
+ const completedBuilds = new Set()
124
+ const failedBuilds = new Set()
125
+ const queuedRoots = new Set()
126
+ const dirtyRoots = new Set()
127
+ const runningChildren = new Set()
128
+ const queue = []
129
+ let running = 0
130
+ let shuttingDown = false
131
+
132
+ function enqueue(item) {
133
+ if (queuedRoots.has(item.root)) {
134
+ dirtyRoots.add(item.root)
135
+ return
136
+ }
137
+
138
+ queuedRoots.add(item.root)
139
+ queue.push(item)
140
+ drainQueue()
141
+ }
142
+
143
+ function drainQueue() {
144
+ while (!shuttingDown && running < concurrency && queue.length) {
145
+ const item = queue.shift()
146
+ running++
147
+
148
+ const child = item.script
149
+ ? spawn('bun', ['run', item.script], {
150
+ cwd: item.root,
151
+ env: process.env,
152
+ stdio: 'inherit',
153
+ })
154
+ : spawn(process.execPath, [buildScript, ...item.args], {
155
+ cwd: item.root,
156
+ env: process.env,
157
+ stdio: 'inherit',
158
+ })
159
+ runningChildren.add(child)
160
+
161
+ child.on('exit', (code, signal) => {
162
+ runningChildren.delete(child)
163
+ running--
164
+ queuedRoots.delete(item.root)
165
+
166
+ const failed = Boolean(code || signal)
167
+
168
+ if (code && !shuttingDown) {
169
+ console.error(`build failed for ${item.name} with exit code ${code}`)
170
+ if (!shouldWatch) process.exitCode = code
171
+ } else if (signal && !shuttingDown) {
172
+ console.error(`build stopped for ${item.name} by ${signal}`)
173
+ if (!shouldWatch) process.exitCode = 1
174
+ }
175
+
176
+ if (dirtyRoots.delete(item.root)) {
177
+ enqueue(item)
178
+ }
179
+
180
+ if (!shouldWatch) {
181
+ if (failed) {
182
+ failedBuilds.add(item.name)
183
+ } else {
184
+ completedBuilds.add(item.name)
185
+ }
186
+ scheduleWorkspaceBuilds()
187
+ }
188
+
189
+ drainQueue()
190
+ })
191
+ }
192
+ }
193
+
194
+ function scheduleWorkspaceBuilds() {
195
+ let scheduled = false
196
+
197
+ for (const item of packages) {
198
+ if (scheduledBuilds.has(item.name)) continue
199
+
200
+ const workspaceDependencies = requestedScript
201
+ ? []
202
+ : item.dependencies.filter((dependency) => packageNames.has(dependency))
203
+ const failedDependency = workspaceDependencies.find((dependency) =>
204
+ failedBuilds.has(dependency)
205
+ )
206
+
207
+ if (failedDependency) {
208
+ scheduledBuilds.add(item.name)
209
+ failedBuilds.add(item.name)
210
+ process.exitCode = 1
211
+ console.error(`skipping ${item.name} because ${failedDependency} failed`)
212
+ scheduled = true
213
+ continue
214
+ }
215
+
216
+ if (workspaceDependencies.every((dependency) => completedBuilds.has(dependency))) {
217
+ scheduledBuilds.add(item.name)
218
+ enqueue(item)
219
+ scheduled = true
220
+ }
221
+ }
222
+
223
+ if (
224
+ scheduled &&
225
+ running === 0 &&
226
+ queue.length === 0 &&
227
+ scheduledBuilds.size < packages.length
228
+ ) {
229
+ scheduleWorkspaceBuilds()
230
+ return
231
+ }
232
+
233
+ if (running === 0 && queue.length === 0 && scheduledBuilds.size < packages.length) {
234
+ const blocked = packages
235
+ .filter((item) => !scheduledBuilds.has(item.name))
236
+ .map((item) => item.name)
237
+ process.exitCode = 1
238
+ console.error(`workspace dependency cycle: ${blocked.join(', ')}`)
239
+ }
240
+ }
241
+
242
+ async function shutdown(signal) {
243
+ if (shuttingDown) return
244
+ shuttingDown = true
245
+ await watcher?.close()
246
+ for (const child of runningChildren) {
247
+ child.kill(signal)
248
+ }
249
+ }
250
+
251
+ if (shouldList) {
252
+ for (const item of packages) {
253
+ console.info(
254
+ `${item.name}\t${path.relative(root, item.root)}\t${item.script ? `bun run ${item.script}` : `tamagui-build ${item.args.join(' ')}`}`
255
+ )
256
+ }
257
+ process.exit(0)
258
+ }
259
+
260
+ let watcher = null
261
+
262
+ if (shouldWatch) {
263
+ const sourceRoots = packages.filter((item) => FSE.existsSync(item.src))
264
+ const sourceRootByPath = [...sourceRoots]
265
+ .sort((a, b) => b.src.length - a.src.length)
266
+ .map((item) => [item.src + path.sep, item])
267
+
268
+ watcher = chokidar.watch(
269
+ sourceRoots.map((item) => item.src),
270
+ {
271
+ persistent: true,
272
+ ignoreInitial: true,
273
+ }
274
+ )
275
+
276
+ const rebuild = (filePath) => {
277
+ const absolutePath = path.resolve(filePath)
278
+ const match = sourceRootByPath.find(([sourceRoot]) =>
279
+ `${absolutePath}${path.sep}`.startsWith(sourceRoot)
280
+ )
281
+ if (match) enqueue(match[1])
282
+ }
283
+
284
+ watcher.on('add', rebuild).on('change', rebuild).on('unlink', rebuild)
285
+
286
+ if (!skipInitialBuild) {
287
+ for (const item of sourceRoots) enqueue(item)
288
+ }
289
+
290
+ console.info(`watching ${sourceRoots.length} workspace packages with one watcher`)
291
+ } else {
292
+ scheduleWorkspaceBuilds()
293
+ }
294
+
295
+ process.on('SIGINT', () => void shutdown('SIGINT'))
296
+ process.on('SIGTERM', () => void shutdown('SIGTERM'))