@take-out/scripts 0.0.93 ā 0.0.95
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 +6 -4
- package/src/build-initial.ts +76 -81
- package/src/clean.ts +21 -21
- package/src/cmd.ts +85 -0
- package/src/dev-tunnel.ts +141 -159
- package/src/ensure-port.ts +62 -70
- package/src/ensure-tunnel.ts +13 -9
- package/src/env-pull.ts +49 -47
- package/src/env-update.ts +140 -175
- package/src/exec-with-env.ts +14 -11
- package/src/helpers/args.ts +4 -4
- package/src/helpers/get-test-env.ts +5 -3
- package/src/node-version-check.ts +9 -5
- package/src/release.ts +429 -404
- package/src/sst-get-environment.ts +5 -1
- package/src/typecheck.ts +15 -16
- package/src/up.ts +361 -374
- package/src/update-changelog.ts +39 -43
- package/src/update-local-env.ts +139 -158
- package/src/wait-for-dev.ts +21 -20
package/src/up.ts
CHANGED
|
@@ -1,66 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
* @description Upgrade packages by name (takeout, tamagui, one, zero, better-auth)
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { existsSync, readdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
|
|
8
|
-
import { join } from 'node:path'
|
|
9
|
-
|
|
10
|
-
import { $ } from 'bun'
|
|
11
|
-
|
|
12
|
-
let globalTag: string | undefined
|
|
13
|
-
const packagePatterns: string[] = []
|
|
14
|
-
|
|
15
|
-
const args = process.argv.slice(2)
|
|
16
|
-
|
|
17
|
-
// check if first arg is a named upgrade set
|
|
18
|
-
const rootDir = process.cwd()
|
|
19
|
-
const rootPackageJson = JSON.parse(readFileSync(join(rootDir, 'package.json'), 'utf-8'))
|
|
20
|
-
const upgradeSets: Record<string, string[]> = rootPackageJson.upgradeSets || {}
|
|
21
|
-
|
|
22
|
-
for (let i = 0; i < args.length; i++) {
|
|
23
|
-
const arg = args[i]!
|
|
24
|
-
if (arg.startsWith('--tag=')) {
|
|
25
|
-
const tagValue = arg.split('=')[1]
|
|
26
|
-
if (tagValue) {
|
|
27
|
-
globalTag = tagValue
|
|
28
|
-
} else {
|
|
29
|
-
console.error('Error: --tag option requires a value. Example: --tag=canary')
|
|
30
|
-
process.exit(1)
|
|
31
|
-
}
|
|
32
|
-
} else if (arg === '--tag') {
|
|
33
|
-
console.error('Error: --tag option requires a value and must use = syntax.')
|
|
34
|
-
console.error('Correct usage: --tag=canary')
|
|
35
|
-
console.error('Example: bun tko up --tag=canary react react-dom')
|
|
36
|
-
process.exit(1)
|
|
37
|
-
} else if (arg === '--canary') {
|
|
38
|
-
globalTag = 'canary'
|
|
39
|
-
} else if (arg === '--rc') {
|
|
40
|
-
globalTag = 'rc'
|
|
41
|
-
} else if (arg in upgradeSets) {
|
|
42
|
-
// expand named upgrade set to its patterns
|
|
43
|
-
packagePatterns.push(...upgradeSets[arg]!)
|
|
44
|
-
} else {
|
|
45
|
-
packagePatterns.push(arg)
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
if (packagePatterns.length === 0) {
|
|
50
|
-
const setNames = Object.keys(upgradeSets)
|
|
51
|
-
if (setNames.length > 0) {
|
|
52
|
-
console.info('Usage: bun tko up <target|pattern> [options]')
|
|
53
|
-
console.info(`\nAvailable upgrade sets: ${setNames.join(', ')}`)
|
|
54
|
-
console.info('\nOr provide package patterns directly:')
|
|
55
|
-
console.info(' bun tko up @vxrn/* vxrn')
|
|
56
|
-
console.info(' bun tko up --tag=canary react react-dom')
|
|
57
|
-
} else {
|
|
58
|
-
console.error('Please provide at least one package pattern to update.')
|
|
59
|
-
console.error('Example: bun tko up @vxrn/* vxrn')
|
|
60
|
-
console.error('Or with a tag: bun tko up --tag=canary @vxrn/* vxrn')
|
|
61
|
-
}
|
|
62
|
-
process.exit(1)
|
|
63
|
-
}
|
|
3
|
+
import { cmd } from './cmd'
|
|
64
4
|
|
|
65
5
|
interface PackageJson {
|
|
66
6
|
dependencies?: Record<string, string>
|
|
@@ -69,383 +9,430 @@ interface PackageJson {
|
|
|
69
9
|
optionalDependencies?: Record<string, string>
|
|
70
10
|
}
|
|
71
11
|
|
|
72
|
-
|
|
73
|
-
|
|
12
|
+
await cmd`upgrade packages by name or pattern`
|
|
13
|
+
.args('--tag string --canary boolean --rc boolean')
|
|
14
|
+
.run(async ({ args, $, path, fs }) => {
|
|
15
|
+
const { existsSync, readdirSync, readFileSync, writeFileSync, rmSync } =
|
|
16
|
+
await import('node:fs')
|
|
17
|
+
|
|
18
|
+
let globalTag: string | undefined = args.tag
|
|
19
|
+
if (args.canary) globalTag = 'canary'
|
|
20
|
+
if (args.rc) globalTag = 'rc'
|
|
21
|
+
|
|
22
|
+
const packagePatterns: string[] = []
|
|
23
|
+
const rootDir = process.cwd()
|
|
24
|
+
const rootPackageJson = JSON.parse(
|
|
25
|
+
readFileSync(path.join(rootDir, 'package.json'), 'utf-8')
|
|
26
|
+
)
|
|
27
|
+
const upgradeSets: Record<string, string[]> = rootPackageJson.upgradeSets || {}
|
|
28
|
+
|
|
29
|
+
for (const arg of args.rest) {
|
|
30
|
+
if (arg in upgradeSets) {
|
|
31
|
+
// expand named upgrade set to its patterns
|
|
32
|
+
packagePatterns.push(...upgradeSets[arg]!)
|
|
33
|
+
} else {
|
|
34
|
+
packagePatterns.push(arg)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
74
37
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
38
|
+
if (packagePatterns.length === 0) {
|
|
39
|
+
const setNames = Object.keys(upgradeSets)
|
|
40
|
+
if (setNames.length > 0) {
|
|
41
|
+
console.info('Usage: bun tko up <target|pattern> [options]')
|
|
42
|
+
console.info(`\nAvailable upgrade sets: ${setNames.join(', ')}`)
|
|
43
|
+
console.info('\nOr provide package patterns directly:')
|
|
44
|
+
console.info(' bun tko up @vxrn/* vxrn')
|
|
45
|
+
console.info(' bun tko up --tag canary react react-dom')
|
|
46
|
+
} else {
|
|
47
|
+
console.error('Please provide at least one package pattern to update.')
|
|
48
|
+
console.error('Example: bun tko up @vxrn/* vxrn')
|
|
49
|
+
console.error('Or with a tag: bun tko up --tag canary @vxrn/* vxrn')
|
|
50
|
+
}
|
|
51
|
+
process.exit(1)
|
|
52
|
+
}
|
|
78
53
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const packageJson = JSON.parse(readFileSync(join(dir, 'package.json'), 'utf-8'))
|
|
82
|
-
if (packageJson.workspaces) {
|
|
83
|
-
let workspacePaths: string[] = []
|
|
54
|
+
function findPackageJsonFiles(dir: string): string[] {
|
|
55
|
+
const results: string[] = []
|
|
84
56
|
|
|
85
|
-
if (
|
|
86
|
-
|
|
87
|
-
} else if (packageJson.workspaces.packages) {
|
|
88
|
-
workspacePaths = packageJson.workspaces.packages
|
|
57
|
+
if (existsSync(path.join(dir, 'package.json'))) {
|
|
58
|
+
results.push(path.join(dir, 'package.json'))
|
|
89
59
|
}
|
|
90
60
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
61
|
+
// check if it's a monorepo with workspaces
|
|
62
|
+
try {
|
|
63
|
+
const packageJson = JSON.parse(
|
|
64
|
+
readFileSync(path.join(dir, 'package.json'), 'utf-8')
|
|
65
|
+
)
|
|
66
|
+
if (packageJson.workspaces) {
|
|
67
|
+
let workspacePaths: string[] = []
|
|
68
|
+
|
|
69
|
+
if (Array.isArray(packageJson.workspaces)) {
|
|
70
|
+
workspacePaths = packageJson.workspaces
|
|
71
|
+
} else if (packageJson.workspaces.packages) {
|
|
72
|
+
workspacePaths = packageJson.workspaces.packages
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
for (const workspace of workspacePaths) {
|
|
76
|
+
// handle glob patterns like "packages/*", "code/**/*", "./code/ui/**/*"
|
|
77
|
+
const normalizedWorkspace = workspace.replace(/^\.\//, '')
|
|
78
|
+
|
|
79
|
+
if (normalizedWorkspace.includes('**')) {
|
|
80
|
+
// nested glob pattern - use glob to find all package.json files
|
|
81
|
+
const baseDir = normalizedWorkspace.split('**')[0]!.replace(/\/$/, '')
|
|
82
|
+
const basePath = path.join(dir, baseDir)
|
|
83
|
+
|
|
84
|
+
if (existsSync(basePath)) {
|
|
85
|
+
const findPackages = (searchDir: string) => {
|
|
86
|
+
try {
|
|
87
|
+
const entries = readdirSync(searchDir, { withFileTypes: true })
|
|
88
|
+
for (const entry of entries) {
|
|
89
|
+
if (entry.isDirectory() && entry.name !== 'node_modules') {
|
|
90
|
+
const subPath = path.join(searchDir, entry.name)
|
|
91
|
+
const pkgPath = path.join(subPath, 'package.json')
|
|
92
|
+
if (existsSync(pkgPath)) {
|
|
93
|
+
results.push(pkgPath)
|
|
94
|
+
}
|
|
95
|
+
// recurse into subdirectories
|
|
96
|
+
findPackages(subPath)
|
|
97
|
+
}
|
|
110
98
|
}
|
|
111
|
-
|
|
112
|
-
|
|
99
|
+
} catch (_e) {
|
|
100
|
+
// ignore permission errors
|
|
113
101
|
}
|
|
114
102
|
}
|
|
115
|
-
|
|
116
|
-
// ignore permission errors
|
|
103
|
+
findPackages(basePath)
|
|
117
104
|
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
105
|
+
} else if (normalizedWorkspace.includes('*')) {
|
|
106
|
+
// simple glob pattern like "packages/*"
|
|
107
|
+
const workspaceDir = normalizedWorkspace.replace(/\/\*$/, '')
|
|
108
|
+
if (existsSync(path.join(dir, workspaceDir))) {
|
|
109
|
+
const subdirs = readdirSync(path.join(dir, workspaceDir), {
|
|
110
|
+
withFileTypes: true,
|
|
111
|
+
})
|
|
112
|
+
.filter((dirent) => dirent.isDirectory())
|
|
113
|
+
.map((dirent) => path.join(dir, workspaceDir, dirent.name))
|
|
114
|
+
|
|
115
|
+
for (const subdir of subdirs) {
|
|
116
|
+
if (existsSync(path.join(subdir, 'package.json'))) {
|
|
117
|
+
results.push(path.join(subdir, 'package.json'))
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
} else {
|
|
122
|
+
// exact path like "code/tamagui.dev" or "./code/sandbox"
|
|
123
|
+
const pkgPath = path.join(dir, normalizedWorkspace, 'package.json')
|
|
124
|
+
if (existsSync(pkgPath)) {
|
|
125
|
+
results.push(pkgPath)
|
|
132
126
|
}
|
|
133
127
|
}
|
|
134
128
|
}
|
|
135
|
-
} else {
|
|
136
|
-
// exact path like "code/tamagui.dev" or "./code/sandbox"
|
|
137
|
-
const pkgPath = join(dir, normalizedWorkspace, 'package.json')
|
|
138
|
-
if (existsSync(pkgPath)) {
|
|
139
|
-
results.push(pkgPath)
|
|
140
|
-
}
|
|
141
129
|
}
|
|
130
|
+
} catch (_error) {
|
|
131
|
+
// ignore errors parsing package.json
|
|
142
132
|
}
|
|
143
|
-
}
|
|
144
|
-
} catch (_error) {
|
|
145
|
-
// ignore errors parsing package.json
|
|
146
|
-
}
|
|
147
133
|
|
|
148
|
-
|
|
149
|
-
}
|
|
134
|
+
return results
|
|
135
|
+
}
|
|
150
136
|
|
|
151
|
-
function extractDependencies(packageJsonPath: string): string[] {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
137
|
+
function extractDependencies(packageJsonPath: string): string[] {
|
|
138
|
+
try {
|
|
139
|
+
const content = readFileSync(packageJsonPath, 'utf-8')
|
|
140
|
+
const packageJson = JSON.parse(content) as PackageJson
|
|
155
141
|
|
|
156
|
-
|
|
142
|
+
const deps: string[] = []
|
|
157
143
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
144
|
+
const addNonWorkspaceDeps = (depsObject: Record<string, string> | undefined) => {
|
|
145
|
+
if (!depsObject) return
|
|
146
|
+
for (const [name, version] of Object.entries(depsObject)) {
|
|
147
|
+
// skip workspace dependencies
|
|
148
|
+
if (!version.startsWith('workspace:')) {
|
|
149
|
+
deps.push(name)
|
|
150
|
+
}
|
|
151
|
+
}
|
|
164
152
|
}
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
153
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
154
|
+
addNonWorkspaceDeps(packageJson.dependencies)
|
|
155
|
+
addNonWorkspaceDeps(packageJson.devDependencies)
|
|
156
|
+
addNonWorkspaceDeps(packageJson.peerDependencies)
|
|
157
|
+
addNonWorkspaceDeps(packageJson.optionalDependencies)
|
|
172
158
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
}
|
|
159
|
+
return deps
|
|
160
|
+
} catch (error) {
|
|
161
|
+
console.error(`Error parsing ${packageJsonPath}:`, error)
|
|
162
|
+
return []
|
|
163
|
+
}
|
|
164
|
+
}
|
|
179
165
|
|
|
180
|
-
function doesPackageMatchPattern(packageName: string, pattern: string): boolean {
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
}
|
|
166
|
+
function doesPackageMatchPattern(packageName: string, pattern: string): boolean {
|
|
167
|
+
if (pattern.includes('*')) {
|
|
168
|
+
const regex = new RegExp(`^${pattern.replace(/\*/g, '.*')}$`)
|
|
169
|
+
return regex.test(packageName)
|
|
170
|
+
}
|
|
171
|
+
return packageName === pattern
|
|
172
|
+
}
|
|
187
173
|
|
|
188
|
-
function updatePackageJsonVersions(
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
): number {
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
174
|
+
function updatePackageJsonVersions(
|
|
175
|
+
packageJsonPath: string,
|
|
176
|
+
packagesToUpdate: string[],
|
|
177
|
+
versionMap: Map<string, string>
|
|
178
|
+
): number {
|
|
179
|
+
const content = readFileSync(packageJsonPath, 'utf-8')
|
|
180
|
+
const packageJson = JSON.parse(content) as PackageJson
|
|
181
|
+
let updatedCount = 0
|
|
182
|
+
|
|
183
|
+
const updateDeps = (depsObject: Record<string, string> | undefined) => {
|
|
184
|
+
if (!depsObject) return
|
|
185
|
+
for (const pkg of packagesToUpdate) {
|
|
186
|
+
const current = depsObject[pkg]
|
|
187
|
+
if (current && !current.startsWith('workspace:')) {
|
|
188
|
+
const newVersion = versionMap.get(pkg)
|
|
189
|
+
if (newVersion) {
|
|
190
|
+
// for tagged versions (canary, rc, etc), use exact version (no prefix)
|
|
191
|
+
// otherwise preserve version prefix (^, ~, >=, etc)
|
|
192
|
+
if (globalTag) {
|
|
193
|
+
depsObject[pkg] = newVersion
|
|
194
|
+
} else {
|
|
195
|
+
// wildcard "*" means newly added placeholder, use ^ prefix
|
|
196
|
+
if (current === '*') {
|
|
197
|
+
depsObject[pkg] = `^${newVersion}`
|
|
198
|
+
updatedCount++
|
|
199
|
+
continue
|
|
200
|
+
}
|
|
201
|
+
const prefixMatch = current.match(/^([^\d]*)/)
|
|
202
|
+
const prefix = prefixMatch?.[1] || ''
|
|
203
|
+
depsObject[pkg] = `${prefix}${newVersion}`
|
|
204
|
+
}
|
|
212
205
|
updatedCount++
|
|
213
|
-
continue
|
|
214
206
|
}
|
|
215
|
-
const prefixMatch = current.match(/^([^\d]*)/)
|
|
216
|
-
const prefix = prefixMatch?.[1] || ''
|
|
217
|
-
depsObject[pkg] = `${prefix}${newVersion}`
|
|
218
207
|
}
|
|
219
|
-
updatedCount++
|
|
220
208
|
}
|
|
221
209
|
}
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
210
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
211
|
+
updateDeps(packageJson.dependencies)
|
|
212
|
+
updateDeps(packageJson.devDependencies)
|
|
213
|
+
updateDeps(packageJson.peerDependencies)
|
|
214
|
+
updateDeps(packageJson.optionalDependencies)
|
|
229
215
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
216
|
+
if (updatedCount > 0) {
|
|
217
|
+
writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\n')
|
|
218
|
+
}
|
|
233
219
|
|
|
234
|
-
|
|
235
|
-
}
|
|
220
|
+
return updatedCount
|
|
221
|
+
}
|
|
236
222
|
|
|
237
|
-
async function updatePackages(
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
) {
|
|
242
|
-
try {
|
|
243
|
-
rmSync(`node_modules/vite`, {
|
|
244
|
-
recursive: true,
|
|
245
|
-
force: true,
|
|
246
|
-
})
|
|
247
|
-
} catch (_e) {
|
|
248
|
-
// ignore if vite is not there
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
// collect all unique packages to update
|
|
252
|
-
const allPackages = new Set<string>()
|
|
253
|
-
for (const { packages } of packagesByWorkspace.values()) {
|
|
254
|
-
packages.forEach((pkg) => allPackages.add(pkg))
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
// fetch versions for all packages (with tag if specified)
|
|
258
|
-
const versionMap = new Map<string, string>()
|
|
259
|
-
console.info(`\nš Fetching versions for ${allPackages.size} package(s)...`)
|
|
260
|
-
|
|
261
|
-
await Promise.all(
|
|
262
|
-
[...allPackages].map(async (pkg) => {
|
|
223
|
+
async function updatePackages(
|
|
224
|
+
packagesByWorkspace: Map<string, { dir: string; packages: string[] }>,
|
|
225
|
+
rootDir: string,
|
|
226
|
+
packageJsonFiles: string[]
|
|
227
|
+
) {
|
|
263
228
|
try {
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
}
|
|
229
|
+
rmSync(`node_modules/vite`, {
|
|
230
|
+
recursive: true,
|
|
231
|
+
force: true,
|
|
232
|
+
})
|
|
233
|
+
} catch (_e) {
|
|
234
|
+
// ignore if vite is not there
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// collect all unique packages to update
|
|
238
|
+
const allPackages = new Set<string>()
|
|
239
|
+
for (const { packages } of packagesByWorkspace.values()) {
|
|
240
|
+
packages.forEach((pkg) => allPackages.add(pkg))
|
|
277
241
|
}
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
242
|
+
|
|
243
|
+
// fetch versions for all packages (with tag if specified)
|
|
244
|
+
const versionMap = new Map<string, string>()
|
|
245
|
+
console.info(`\nš Fetching versions for ${allPackages.size} package(s)...`)
|
|
246
|
+
|
|
247
|
+
await Promise.all(
|
|
248
|
+
[...allPackages].map(async (pkg) => {
|
|
249
|
+
try {
|
|
250
|
+
const tag = globalTag || 'latest'
|
|
251
|
+
const result = await $`npm view ${pkg}@${tag} version`.quiet()
|
|
252
|
+
const version = result.text().trim()
|
|
253
|
+
if (version) {
|
|
254
|
+
versionMap.set(pkg, version)
|
|
255
|
+
console.info(` ā ${pkg}@${tag} ā ${version}`)
|
|
256
|
+
}
|
|
257
|
+
} catch {
|
|
258
|
+
if (globalTag) {
|
|
259
|
+
console.info(` ā ${pkg}@${globalTag} not found, skipping`)
|
|
260
|
+
} else {
|
|
261
|
+
console.info(` ā ${pkg} not found, skipping`)
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
})
|
|
299
265
|
)
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
console.info(
|
|
303
|
-
|
|
266
|
+
|
|
267
|
+
if (versionMap.size === 0) {
|
|
268
|
+
console.info(`\nā ļø No packages found to update`)
|
|
269
|
+
return
|
|
304
270
|
}
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
271
|
+
|
|
272
|
+
// update all package.json files directly
|
|
273
|
+
console.info(`\nš¦ Updating ${packageJsonFiles.length} package.json file(s)...`)
|
|
274
|
+
let totalUpdates = 0
|
|
275
|
+
|
|
276
|
+
for (const packageJsonPath of packageJsonFiles) {
|
|
277
|
+
const packagesInWorkspace =
|
|
278
|
+
packagesByWorkspace.get(getWorkspaceName(packageJsonPath, rootDir))?.packages ||
|
|
279
|
+
[]
|
|
280
|
+
|
|
281
|
+
if (packagesInWorkspace.length > 0) {
|
|
282
|
+
const updates = updatePackageJsonVersions(
|
|
283
|
+
packageJsonPath,
|
|
284
|
+
packagesInWorkspace,
|
|
285
|
+
versionMap
|
|
286
|
+
)
|
|
287
|
+
if (updates > 0) {
|
|
288
|
+
const name = getWorkspaceName(packageJsonPath, rootDir)
|
|
289
|
+
console.info(` ā ${name}: ${updates} package(s)`)
|
|
290
|
+
totalUpdates += updates
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
console.info(`\nš Updated ${totalUpdates} dependency version(s)`)
|
|
296
|
+
|
|
297
|
+
console.info(`\nāļø Running 'bun install'...`)
|
|
298
|
+
$.cwd(rootDir)
|
|
320
299
|
try {
|
|
321
|
-
await $`bun pm cache rm`.quiet()
|
|
322
300
|
await $`bun install`
|
|
323
301
|
console.info('ā
Done!')
|
|
324
|
-
} catch (
|
|
325
|
-
const
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
302
|
+
} catch (error: any) {
|
|
303
|
+
const stderr = error.stderr?.toString() || error.message || ''
|
|
304
|
+
// check if it's a version resolution error (common after new publish)
|
|
305
|
+
if (
|
|
306
|
+
stderr.includes('No version matching') ||
|
|
307
|
+
stderr.includes('failed to resolve')
|
|
308
|
+
) {
|
|
309
|
+
console.info(`ā ļø Version not in cache, clearing cache and retrying...`)
|
|
310
|
+
try {
|
|
311
|
+
await $`bun pm cache rm`.quiet()
|
|
312
|
+
await $`bun install`
|
|
313
|
+
console.info('ā
Done!')
|
|
314
|
+
} catch (retryError: any) {
|
|
315
|
+
const retryStderr = retryError.stderr?.toString() || retryError.message || ''
|
|
316
|
+
console.error(
|
|
317
|
+
`šØ 'bun install' failed after cache clear: ${retryStderr.split('\n')[0]}`
|
|
318
|
+
)
|
|
319
|
+
}
|
|
320
|
+
} else {
|
|
321
|
+
console.error(`šØ 'bun install' failed: ${stderr.split('\n')[0]}`)
|
|
322
|
+
}
|
|
329
323
|
}
|
|
330
|
-
} else {
|
|
331
|
-
console.error(`šØ 'bun install' failed: ${stderr.split('\n')[0]}`)
|
|
332
324
|
}
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
325
|
|
|
336
|
-
function getWorkspaceName(packageJsonPath: string, rootDir: string): string {
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
}
|
|
326
|
+
function getWorkspaceName(packageJsonPath: string, rootDir: string): string {
|
|
327
|
+
const dir = packageJsonPath.replace('/package.json', '')
|
|
328
|
+
if (dir === rootDir) return 'root'
|
|
329
|
+
return dir.replace(rootDir + '/', '')
|
|
330
|
+
}
|
|
341
331
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
console.info(`Found ${packageJsonFiles.length} package.json files`)
|
|
332
|
+
const packageJsonFiles = findPackageJsonFiles(rootDir)
|
|
333
|
+
console.info(`Found ${packageJsonFiles.length} package.json files`)
|
|
345
334
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
335
|
+
// get workspace package names to exclude from updates
|
|
336
|
+
const workspacePackageNames = new Set<string>()
|
|
337
|
+
for (const packageJsonPath of packageJsonFiles) {
|
|
338
|
+
if (packageJsonPath === path.join(rootDir, 'package.json')) continue
|
|
350
339
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
340
|
+
try {
|
|
341
|
+
const content = readFileSync(packageJsonPath, 'utf-8')
|
|
342
|
+
const packageJson = JSON.parse(content)
|
|
343
|
+
if (packageJson.name) {
|
|
344
|
+
workspacePackageNames.add(packageJson.name)
|
|
345
|
+
}
|
|
346
|
+
} catch (_error) {
|
|
347
|
+
// ignore errors
|
|
356
348
|
}
|
|
357
|
-
} catch (_error) {
|
|
358
|
-
// ignore errors
|
|
359
349
|
}
|
|
360
|
-
}
|
|
361
350
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
351
|
+
console.info(
|
|
352
|
+
`Found ${workspacePackageNames.size} workspace packages to exclude from updates`
|
|
353
|
+
)
|
|
365
354
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
355
|
+
// build map of packages to update per workspace
|
|
356
|
+
const packagesByWorkspace = new Map<string, { dir: string; packages: string[] }>()
|
|
357
|
+
const allMatchingDeps = new Set<string>()
|
|
369
358
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
359
|
+
for (const packageJsonPath of packageJsonFiles) {
|
|
360
|
+
const deps = extractDependencies(packageJsonPath)
|
|
361
|
+
const matchingDeps: string[] = []
|
|
373
362
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
363
|
+
for (const dep of deps) {
|
|
364
|
+
// skip workspace packages
|
|
365
|
+
if (workspacePackageNames.has(dep)) continue
|
|
377
366
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
367
|
+
for (const pattern of packagePatterns) {
|
|
368
|
+
if (doesPackageMatchPattern(dep, pattern)) {
|
|
369
|
+
matchingDeps.push(dep)
|
|
370
|
+
allMatchingDeps.add(dep)
|
|
371
|
+
break
|
|
372
|
+
}
|
|
383
373
|
}
|
|
384
374
|
}
|
|
385
|
-
}
|
|
386
375
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
376
|
+
if (matchingDeps.length > 0) {
|
|
377
|
+
const dir = packageJsonPath.replace('/package.json', '')
|
|
378
|
+
const name = getWorkspaceName(packageJsonPath, rootDir)
|
|
379
|
+
packagesByWorkspace.set(name, { dir, packages: matchingDeps })
|
|
380
|
+
}
|
|
391
381
|
}
|
|
392
|
-
}
|
|
393
382
|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
383
|
+
if (allMatchingDeps.size === 0) {
|
|
384
|
+
// no existing deps matched, but exact patterns (no wildcards) can be added fresh
|
|
385
|
+
const exactPatterns = packagePatterns.filter((p) => !p.includes('*'))
|
|
386
|
+
if (exactPatterns.length === 0) {
|
|
387
|
+
console.info(
|
|
388
|
+
`Found 0 dependencies matching patterns: ${packagePatterns.join(', ')}`
|
|
389
|
+
)
|
|
390
|
+
console.info('No matching packages found to update.')
|
|
391
|
+
return
|
|
392
|
+
}
|
|
404
393
|
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
394
|
+
// add as new dependencies to the root package.json
|
|
395
|
+
console.info(`No existing deps found, adding to root: ${exactPatterns.join(', ')}`)
|
|
396
|
+
const rootPkgPath = path.join(rootDir, 'package.json')
|
|
408
397
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
398
|
+
for (const pkg of exactPatterns) {
|
|
399
|
+
allMatchingDeps.add(pkg)
|
|
400
|
+
}
|
|
412
401
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
402
|
+
packagesByWorkspace.set('root', {
|
|
403
|
+
dir: rootDir,
|
|
404
|
+
packages: exactPatterns,
|
|
405
|
+
})
|
|
417
406
|
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
407
|
+
// insert placeholder so updatePackageJsonVersions can set the real version
|
|
408
|
+
const rootPkg = JSON.parse(readFileSync(rootPkgPath, 'utf-8'))
|
|
409
|
+
if (!rootPkg.dependencies) {
|
|
410
|
+
rootPkg.dependencies = {}
|
|
411
|
+
}
|
|
412
|
+
for (const pkg of exactPatterns) {
|
|
413
|
+
if (!rootPkg.dependencies[pkg] && !rootPkg.devDependencies?.[pkg]) {
|
|
414
|
+
rootPkg.dependencies[pkg] = '*'
|
|
415
|
+
}
|
|
426
416
|
}
|
|
417
|
+
writeFileSync(rootPkgPath, JSON.stringify(rootPkg, null, 2) + '\n')
|
|
418
|
+
} else {
|
|
419
|
+
console.info(
|
|
420
|
+
`Found ${allMatchingDeps.size} dependencies matching patterns: ${packagePatterns.join(', ')}`
|
|
421
|
+
)
|
|
422
|
+
console.info(`Found matches in ${packagesByWorkspace.size} workspace(s)`)
|
|
427
423
|
}
|
|
428
|
-
writeFileSync(rootPkgPath, JSON.stringify(rootPkg, null, 2) + '\n')
|
|
429
|
-
} else {
|
|
430
|
-
console.info(
|
|
431
|
-
`Found ${allMatchingDeps.size} dependencies matching patterns: ${packagePatterns.join(', ')}`
|
|
432
|
-
)
|
|
433
|
-
console.info(`Found matches in ${packagesByWorkspace.size} workspace(s)`)
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
if (globalTag) {
|
|
437
|
-
console.info(`š·ļø Using tag '${globalTag}'`)
|
|
438
|
-
}
|
|
439
424
|
|
|
440
|
-
|
|
425
|
+
if (globalTag) {
|
|
426
|
+
console.info(`š·ļø Using tag '${globalTag}'`)
|
|
427
|
+
}
|
|
441
428
|
|
|
442
|
-
|
|
443
|
-
if (packagePatterns.includes('@rocicorp/zero')) {
|
|
444
|
-
console.info('\nš Updating local env for Zero...')
|
|
445
|
-
await $`bun tko run update-local-env`
|
|
446
|
-
}
|
|
429
|
+
await updatePackages(packagesByWorkspace, rootDir, packageJsonFiles)
|
|
447
430
|
|
|
448
|
-
|
|
449
|
-
|
|
431
|
+
// special handling for zero - update ZERO_VERSION in .env
|
|
432
|
+
if (packagePatterns.includes('@rocicorp/zero')) {
|
|
433
|
+
console.info('\nš Updating local env for Zero...')
|
|
434
|
+
await $`bun tko run update-local-env`
|
|
435
|
+
}
|
|
450
436
|
|
|
451
|
-
|
|
437
|
+
console.info('\nš Dependency update complete!')
|
|
438
|
+
})
|