@tamagui/build 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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tamagui/build",
3
- "version": "1.0.1-beta.21",
3
+ "version": "1.0.1-beta.211",
4
4
  "bin": {
5
5
  "tamagui-build": "tamagui-build.js"
6
6
  },
@@ -13,12 +13,12 @@
13
13
  },
14
14
  "dependencies": {
15
15
  "chokidar": "^3.5.2",
16
- "esbuild": "^0.14.36",
16
+ "esbuild": "^0.15.11",
17
17
  "execa": "^5.0.0",
18
- "fast-glob": "^3.2.7",
19
- "fs-extra": "^9.1.0",
20
- "json5": "^2.2.0",
21
- "typescript": "^4.5.2"
18
+ "fast-glob": "^3.2.11",
19
+ "fs-extra": "^10.1.0",
20
+ "lodash.debounce": "^4.0.8",
21
+ "typescript": "^4.7.4"
22
22
  },
23
23
  "devDependencies": {
24
24
  "@types/fs-extra": "^9.0.13"
package/tamagui-build.js CHANGED
@@ -1,195 +1,246 @@
1
1
  #!/usr/bin/env node
2
+ /* eslint-disable no-console */
2
3
 
3
4
  const exec = require('execa')
4
5
  const fs = require('fs-extra')
5
- const json5 = require('json5')
6
6
  const esbuild = require('esbuild')
7
7
  const fg = require('fast-glob')
8
8
  const createExternalPlugin = require('./externalNodePlugin')
9
+ const debounce = require('lodash.debounce')
10
+ const { dirname } = require('path')
9
11
 
10
12
  const jsOnly = !!process.env.JS_ONLY
11
13
  const skipJS = !!(process.env.SKIP_JS || false)
12
- const shouldSkipTypes = !!(process.argv.includes('skip-types') || process.env.SKIP_TYPES)
14
+ const shouldSkipTypes = !!(process.argv.includes('--skip-types') || process.env.SKIP_TYPES)
15
+ const shouldBundle = !!process.argv.includes('--bundle')
16
+ const shouldBundleNodeModules = !!process.argv.includes('--bundle-modules')
13
17
  const shouldClean = !!process.argv.includes('clean')
14
18
  const shouldCleanBuildOnly = !!process.argv.includes('clean:build')
15
19
  const shouldWatch = process.argv.includes('--watch')
16
20
 
17
21
  const pkg = fs.readJSONSync('./package.json')
22
+ let shouldSkipInitialTypes = !!process.env.SKIP_TYPES_INITIAL
23
+ const pkgMain = pkg.main
24
+ const pkgModule = pkg.module
25
+ const pkgModuleJSX = pkg['module:jsx']
26
+ const pkgTypes = Boolean(pkg['types'] || pkg['typings'])
27
+
28
+ const flatOut = [pkgMain, pkgModule, pkgModuleJSX].filter(Boolean).length === 1
29
+
30
+ async function clean() {
31
+ try {
32
+ await Promise.allSettled([
33
+ //
34
+ fs.remove('.turbo'),
35
+ fs.remove('.ultra.cache.json'),
36
+ fs.remove('types'),
37
+ fs.remove('dist'),
38
+ ])
39
+ } catch {
40
+ // ok
41
+ }
42
+ if (shouldCleanBuildOnly) {
43
+ console.log('🔹 cleaned', pkg.name)
44
+ process.exit(0)
45
+ }
46
+ try {
47
+ await Promise.allSettled([fs.remove('node_modules')])
48
+ } catch {
49
+ // ok
50
+ }
51
+ console.log('🔹 cleaned', pkg.name)
52
+ process.exit(0)
53
+ }
18
54
 
19
55
  if (shouldClean || shouldCleanBuildOnly) {
20
- ;(async () => {
21
- try {
22
- await Promise.allSettled([fs.remove('.turbo'), fs.remove('types'), fs.remove('dist')])
23
- } catch {}
24
- if (shouldCleanBuildOnly) {
25
- console.log('» cleaned', pkg.name)
26
- process.exit(0)
27
- }
28
- try {
29
- await Promise.allSettled([fs.remove('node_modules')])
30
- } catch {}
31
- console.log('» cleaned', pkg.name)
56
+ clean().then(() => {
32
57
  process.exit(0)
33
- })()
34
- } else {
35
- let shouldSkipInitialTypes = !!process.env.SKIP_TYPES_INITIAL
36
-
37
- const pkgMain = pkg.main
38
- const pkgModule = pkg.module
39
-
40
- async function build() {
41
- console.log('»', pkg.name)
42
- const x = Date.now()
43
- let files = (await fg(['src/**/*.ts', 'src/**/*.tsx', 'src/**/*.css'])).filter(
44
- (x) => !x.includes('.d.ts')
45
- )
58
+ })
59
+ return
60
+ }
46
61
 
47
- if (process.env.NO_CLEAN) {
48
- console.log('skip typecheck')
49
- } else {
50
- fs.existsSync('tsconfig.tsbuildinfo') && fs.rmSync('tsconfig.tsbuildinfo')
51
- }
62
+ if (shouldWatch) {
63
+ process.env.IS_WATCHING = true
64
+ process.env.DISABLE_AUTORUN = true
65
+ build().then(() => {
66
+ const rebuild = debounce(build, 100)
67
+ const chokidar = require('chokidar')
68
+ chokidar
69
+ // prevent infinite loop but cause race condition if you just build directly
70
+ .watch('src', {
71
+ persistent: true,
72
+ alwaysStat: true,
73
+ ignoreInitial: true,
74
+ })
75
+ .on('change', rebuild)
76
+ .on('add', rebuild)
77
+ })
78
+ return
79
+ }
52
80
 
53
- async function buildTsc() {
54
- if (jsOnly || shouldSkipTypes) return
55
- if (shouldSkipInitialTypes) {
56
- shouldSkipInitialTypes = false
57
- return
58
- }
59
-
60
- // NOTE:
61
- // for Intellisense to work in monorepo you need baseUrl: "../.."
62
- // but to build things nicely we need here to reset a few things:
63
- // baseUrl: ., outDir: types, rootDir: src
64
- // now we can have the best of both worlds
65
-
66
- // NOTE: to get intellisense to *not* suggest importing from the index file when it re-exports another package...
67
- // (like tamagui does with @tamagui/core...)
68
- // we add `exclude: ['src/index.ts']` to the tsconfig.json which fixes that
69
- // but then it causes it to not export the types out from index... so....
70
- // we do a stupid, stupid thing to re-write it temporarily without it before build. then restore it after
71
- // honestly hate typescript config all around but this seems to work so fuck it
72
- const tsConfOg = await fs.readFile('tsconfig.json')
73
- const tsConfJSON = json5.parse(tsConfOg)
74
- if (tsConfJSON.exclude && tsConfJSON.exclude.includes('src/index.ts')) {
75
- tsConfJSON.exclude = tsConfJSON.exclude.filter((x) => x !== 'src/index.ts')
76
- await fs.writeJSON('tsconfig.json', tsConfJSON)
77
- }
78
- try {
79
- await exec('npx', [
80
- 'tsc',
81
- '--baseUrl',
82
- '.',
83
- '--outDir',
84
- 'types',
85
- '--rootDir',
86
- 'src',
87
- '--declaration',
88
- '--emitDeclarationOnly',
89
- '--declarationMap',
90
- ])
91
- } finally {
92
- // restore
93
- await fs.writeFile('tsconfig.json', tsConfOg)
94
- }
95
- }
81
+ build()
82
+
83
+ async function build() {
84
+ if (process.env.DEBUG) console.log('🔹', pkg.name)
85
+ try {
86
+ const start = Date.now()
87
+ await Promise.all([
88
+ //
89
+ buildTsc(),
90
+ buildJs(),
91
+ ])
92
+ console.log('built', pkg.name, 'in', Date.now() - start, 'ms')
93
+ } catch (error) {
94
+ console.error(`Error building:`, error.message)
95
+ }
96
+ }
97
+
98
+ // const targetDir = `.types${Math.floor(Math.random() * 1_000_000)}`
99
+ // const cleanup = () => {
100
+ // try {
101
+ // fs.removeSync(targetDir)
102
+ // } catch {
103
+ // // ok
104
+ // }
105
+ // }
96
106
 
97
- const externalPlugin = createExternalPlugin({
98
- skipNodeModulesBundle: true,
99
- })
107
+ // process.once('beforeExit', cleanup)
108
+ // process.once('SIGINT', cleanup)
109
+ // process.once('SIGTERM', cleanup)
100
110
 
111
+ async function buildTsc() {
112
+ if (!pkgTypes) return
113
+ if (jsOnly || shouldSkipTypes) return
114
+ if (shouldSkipInitialTypes) {
115
+ shouldSkipInitialTypes = false
116
+ return
117
+ }
118
+
119
+ async function buildThenCopy() {
120
+ if (!(await fs.pathExists(`tsconfig.json`))) {
121
+ throw new Error(`No tsconfig.json found`)
122
+ }
123
+ const targetDir = 'types'
101
124
  try {
102
- await Promise.all([
103
- buildTsc(),
104
- ...(skipJS
105
- ? []
106
- : [
107
- pkgMain
108
- ? esbuild
109
- .build({
110
- entryPoints: files,
111
- outdir: 'dist/cjs',
112
- bundle: false,
113
- sourcemap: true,
114
- target: 'node14',
115
- keepNames: true,
116
- format: 'cjs',
117
- color: true,
118
- logLevel: 'error',
119
- plugins: [externalPlugin],
120
- minify: false,
121
- platform: 'node',
122
- })
123
- .then(() => {
124
- console.log(' >-> commonjs')
125
- })
126
- : null,
127
- // dont bundle for tree shaking
128
- pkgModule
129
- ? esbuild
130
- .build({
131
- entryPoints: files,
132
- outdir: 'dist/esm',
133
- sourcemap: true,
134
- target: 'es2019',
135
- keepNames: true,
136
- format: 'esm',
137
- color: true,
138
- logLevel: 'error',
139
- minify: false,
140
- platform: 'neutral',
141
- })
142
- .then(() => {
143
- console.log(' >-> esm')
144
- })
145
- : null,
146
- esbuild
147
- .build({
148
- // only diff is jsx preserve and outdir
149
- jsx: 'preserve',
150
- outdir: 'dist/jsx',
151
- entryPoints: files,
152
- sourcemap: false,
153
- target: 'es2019',
154
- keepNames: true,
155
- format: 'esm',
156
- color: true,
157
- logLevel: 'error',
158
- minify: false,
159
- platform: 'neutral',
160
- })
161
- .then(() => {
162
- console.log(' >-> jsx')
163
- }),
164
- ]),
165
- ])
166
- } catch (error) {
167
- console.log('error', error)
125
+ // typescripts build cache messes up when doing declarationOnly
126
+ await fs.remove('tsconfig.tsbuildinfo')
127
+ await fs.ensureDir(targetDir)
128
+ const cmd = `tsc --baseUrl . --outDir ${targetDir} --rootDir src --emitDeclarationOnly --declarationMap`
129
+ // console.log('\x1b[2m$', `npx ${cmd}`)
130
+ await exec('npx', cmd.split(' '))
168
131
  } finally {
169
- console.log('built in', `${(Date.now() - x) / 1000}s`)
132
+ await fs.remove('tsconfig.tsbuildinfo')
170
133
  }
171
134
  }
172
135
 
173
- if (shouldWatch) {
174
- const path = require('path')
175
- process.env.IS_WATCHING = true
176
- process.env.DISABLE_AUTORUN = true
177
- build().then(() => {
178
- const finish = (_, path, stats) => {
179
- build()
180
- }
181
- const chokidar = require('chokidar')
182
- chokidar
183
- // prevent infinite loop but cause race condition if you just build directly
184
- .watch('src', {
185
- persistent: true,
186
- alwaysStat: true,
187
- ignoreInitial: true,
136
+ // NOTE:
137
+ // for Intellisense to work in monorepo you need baseUrl: "../.."
138
+ // but to build things nicely we need here to reset a few things:
139
+ // baseUrl: ., outDir: types, rootDir: src
140
+ // for best of both worlds
141
+
142
+ // there's a bug with typescript where outputting within the same dir just doesn't output for whatever reason
143
+ // i have a hunch it's some cache thing, because if i give a new outDir it works
144
+ // so fixing by always giving a random tmp outdir, and then copying
145
+ await buildThenCopy()
146
+ }
147
+
148
+ async function buildJs() {
149
+ if (skipJS) {
150
+ return
151
+ }
152
+ let files = (await fg(['src/**/*.(m)?[jt]s(x)?', 'src/**/*.css'])).filter(
153
+ (x) => !x.includes('.d.ts')
154
+ )
155
+ const externalPlugin = createExternalPlugin({
156
+ skipNodeModulesBundle: true,
157
+ })
158
+ const start = Date.now()
159
+ return await Promise.all([
160
+ pkgMain
161
+ ? esbuildWriteIfChanged({
162
+ entryPoints: files,
163
+ outdir: flatOut ? 'dist' : 'dist/cjs',
164
+ bundle: shouldBundle,
165
+ sourcemap: true,
166
+ target: 'node14',
167
+ keepNames: false,
168
+ format: 'cjs',
169
+ color: true,
170
+ allowOverwrite: true,
171
+ jsx: 'automatic',
172
+ logLevel: 'error',
173
+ plugins: shouldBundleNodeModules ? [] : [externalPlugin],
174
+ minify: false,
175
+ platform: 'node',
176
+ })
177
+ : null,
178
+ pkgModule
179
+ ? esbuildWriteIfChanged({
180
+ entryPoints: files,
181
+ outdir: flatOut ? 'dist' : 'dist/esm',
182
+ bundle: shouldBundle,
183
+ sourcemap: true,
184
+ target: 'node16',
185
+ keepNames: false,
186
+ jsx: 'automatic',
187
+ allowOverwrite: true,
188
+ format: 'esm',
189
+ color: true,
190
+ logLevel: 'error',
191
+ minify: false,
192
+ platform: shouldBundle ? 'node' : 'neutral',
188
193
  })
189
- .on('change', finish)
190
- .on('add', finish)
191
- })
194
+ : null,
195
+ pkgModuleJSX
196
+ ? esbuildWriteIfChanged({
197
+ // only diff is jsx preserve and outdir
198
+ jsx: 'preserve',
199
+ outdir: flatOut ? 'dist' : 'dist/jsx',
200
+ entryPoints: files,
201
+ bundle: shouldBundle,
202
+ sourcemap: true,
203
+ allowOverwrite: true,
204
+ target: 'es2020',
205
+ keepNames: false,
206
+ format: 'esm',
207
+ color: true,
208
+ logLevel: 'error',
209
+ minify: false,
210
+ platform: 'neutral',
211
+ })
212
+ : null,
213
+ ]).then(() => {
214
+ if (process.env.DEBUG) console.log(`built js in ${Date.now() - start}ms`)
215
+ })
216
+ }
217
+
218
+ /**
219
+ * esbuild but avoids touching unchanged files to not freak out vite
220
+ * @param {esbuild.BuildOptions} opts
221
+ * @returns {Promise<void>}
222
+ */
223
+ async function esbuildWriteIfChanged(opts) {
224
+ if (shouldWatch) {
225
+ const built = await esbuild.build({ ...opts, write: false })
226
+ if (!built.outputFiles) {
227
+ return
228
+ }
229
+ await Promise.all(
230
+ built.outputFiles.map(async (file) => {
231
+ const outDir = dirname(file.path)
232
+ await fs.ensureDir(outDir)
233
+ const outString = new TextDecoder().decode(file.contents)
234
+ if (
235
+ !(await fs.pathExists(file.path)) ||
236
+ (await fs.readFile(file.path, 'utf8')) !== outString
237
+ ) {
238
+ // console.log('write', file.path)
239
+ await fs.writeFile(file.path, outString)
240
+ }
241
+ })
242
+ )
192
243
  } else {
193
- build()
244
+ await esbuild.build(opts)
194
245
  }
195
246
  }
@@ -1 +0,0 @@
1
- @tamagui/build:build: cache hit, replaying output f080f7f6d7747555
package/tsconfig.json DELETED
@@ -1,9 +0,0 @@
1
- {
2
- "extends": "../../tsconfig.json",
3
- "include": [],
4
- "files": [],
5
- "compilerOptions": {
6
- "composite": true,
7
- "jsx": "preserve"
8
- },
9
- }