@take-out/scripts 0.0.42 → 0.0.43

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 (2) hide show
  1. package/package.json +4 -3
  2. package/src/update-deps.ts +97 -107
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@take-out/scripts",
3
- "version": "0.0.42",
3
+ "version": "0.0.43",
4
4
  "type": "module",
5
- "main": "./src/index.ts",
5
+ "main": "./src/run.ts",
6
6
  "sideEffects": false,
7
7
  "exports": {
8
8
  "./package.json": "./package.json",
@@ -24,7 +24,8 @@
24
24
  "access": "public"
25
25
  },
26
26
  "dependencies": {
27
- "@take-out/helpers": "0.0.42"
27
+ "@take-out/helpers": "0.0.43",
28
+ "glob": "^11.0.0"
28
29
  },
29
30
  "devDependencies": {
30
31
  "vxrn": "*"
@@ -127,60 +127,62 @@ function doesPackageMatchPattern(packageName: string, pattern: string): boolean
127
127
  return packageName === pattern
128
128
  }
129
129
 
130
- async function fetchPackageVersionFromTag(
131
- packageName: string,
132
- tag: string
133
- ): Promise<string | null> {
134
- try {
135
- console.info(`⏳ Lookup ${packageName}@${tag}...`)
136
- // Use --json to ensure parseable output, even if it's just a string.
137
- const result = await $`npm view ${packageName}@${tag} version --json`.text()
138
- const versionData = JSON.parse(result.trim())
139
-
140
- let version: string | undefined
141
- if (Array.isArray(versionData)) {
142
- if (versionData.length === 0) {
143
- console.warn(`❓ No specific versions found for ${packageName}@${tag}.`)
144
- return null
145
- }
146
- // If multiple versions, prefer the last one, as it's often the latest/highest precedent for a tag.
147
- version = versionData[versionData.length - 1]
148
- if (versionData.length > 1) {
149
- console.info(
150
- `ℹ️ Multiple versions found for ${packageName}@${tag}: [${versionData.join(', ')}]. Using: ${version}`
151
- )
152
- }
153
- } else if (typeof versionData === 'string') {
154
- version = versionData
130
+ async function updatePackagesInWorkspace(
131
+ packagesToUpdate: string[],
132
+ cwd: string,
133
+ workspaceName: string
134
+ ) {
135
+ if (packagesToUpdate.length === 0) {
136
+ return
137
+ }
138
+
139
+ $.cwd(cwd)
140
+
141
+ if (globalTag) {
142
+ // check which packages actually have the tag
143
+ const packagesWithTag = (
144
+ await Promise.all(
145
+ packagesToUpdate.map(async (pkg) => {
146
+ try {
147
+ await $`npm view ${pkg}@${globalTag} version --json`.quiet()
148
+ return pkg
149
+ } catch {
150
+ return null
151
+ }
152
+ })
153
+ )
154
+ ).filter((pkg): pkg is string => pkg !== null)
155
+
156
+ if (packagesWithTag.length === 0) {
157
+ return
155
158
  }
156
159
 
157
- if (typeof version === 'string' && version.trim() !== '') {
158
- console.info(`✅ Found ${packageName}@${tag}: ${version}`)
159
- return version
160
+ console.info(` 📦 ${workspaceName}: updating ${packagesWithTag.length} package(s)`)
161
+
162
+ const packageNamesWithTags = packagesWithTag.map((pkg) => `${pkg}@${globalTag}`)
163
+
164
+ try {
165
+ await $`bun add ${packageNamesWithTags} --ignore-scripts`.quiet()
166
+ } catch (error: any) {
167
+ const errorMessage = error.message?.split('\n')[0]
168
+ console.warn(` ⚠️ ${workspaceName}: ${errorMessage}`)
160
169
  }
170
+ } else {
171
+ console.info(` 📦 ${workspaceName}: updating ${packagesToUpdate.length} package(s)`)
161
172
 
162
- console.warn(
163
- `❓ Unexpected or empty version format for ${packageName}@${tag}: ${JSON.stringify(versionData)}`
164
- )
165
- return null
166
- } catch (error: any) {
167
- // Trim error message to avoid overly verbose logs from npm
168
- const errorMessage = error.message?.split('\n')[0]
169
- console.warn(
170
- `⚠️ Could not fetch version for ${packageName}@${tag}. Error: ${errorMessage}`
171
- )
172
- return null
173
+ try {
174
+ await $`bun update ${packagesToUpdate} --latest --ignore-scripts`.quiet()
175
+ } catch (error: any) {
176
+ const errorMessage = error.message?.split('\n')[0]
177
+ console.warn(` ⚠️ ${workspaceName}: ${errorMessage}`)
178
+ }
173
179
  }
174
180
  }
175
181
 
176
- async function updatePackages(packagesToUpdate: string[], cwd: string) {
177
- if (packagesToUpdate.length === 0) {
178
- console.info('No packages to update after resolving versions.')
179
- return
180
- }
181
-
182
- $.cwd(cwd)
183
-
182
+ async function updatePackages(
183
+ packagesByWorkspace: Map<string, { dir: string; packages: string[] }>,
184
+ rootDir: string
185
+ ) {
184
186
  try {
185
187
  rmSync(`node_modules/vite`, {
186
188
  recursive: true,
@@ -191,64 +193,48 @@ async function updatePackages(packagesToUpdate: string[], cwd: string) {
191
193
  }
192
194
 
193
195
  if (globalTag) {
194
- // check which packages actually have the tag
195
196
  console.info(`🔍 Checking which packages have tag '${globalTag}'...\n`)
196
- const packagesWithTag = await Promise.all(
197
- packagesToUpdate.flatMap(async (pkg) => {
197
+ const allPackages = new Set<string>()
198
+ for (const { packages } of packagesByWorkspace.values()) {
199
+ packages.forEach((pkg) => allPackages.add(pkg))
200
+ }
201
+
202
+ const packagesWithTag = new Set<string>()
203
+ await Promise.all(
204
+ [...allPackages].map(async (pkg) => {
198
205
  try {
199
206
  await $`npm view ${pkg}@${globalTag} version --json`.quiet()
200
207
  console.info(` ✓ ${pkg}@${globalTag} exists`)
201
- return [pkg]
208
+ packagesWithTag.add(pkg)
202
209
  } catch {
203
210
  console.info(` ⊘ ${pkg}@${globalTag} not found, skipping`)
204
- return []
205
211
  }
206
212
  })
207
213
  )
208
214
 
209
- if (packagesWithTag.length === 0) {
215
+ if (packagesWithTag.size === 0) {
210
216
  console.info(`\n⚠️ No packages found with tag '${globalTag}'`)
211
217
  return
212
218
  }
213
219
 
214
- console.info(`
215
- 📦 Updating ${packagesWithTag.length} package(s) with tag '${globalTag}' using --ignore-scripts...
216
- `)
220
+ console.info(`\n📦 Updating packages across workspaces...`)
217
221
 
218
- const packageNamesWithTags = packagesWithTag.map((pkg) => `${pkg}@${globalTag}`)
219
- const addCommand = `bun add ${packageNamesWithTags.join(' ')} --ignore-scripts`
220
- console.info(`\n🪄 Running: ${addCommand}\n`)
221
-
222
- try {
223
- await $`bun add ${packageNamesWithTags} --ignore-scripts`
224
- console.info(
225
- `✅ Successfully updated all packages with tag '${globalTag}' (scripts ignored)`
226
- )
227
- } catch (error: any) {
228
- const errorMessage = error.message?.split('\n')[0]
229
- console.warn(`⚠️ Failed to update packages. Error: ${errorMessage}`)
222
+ for (const [name, { dir, packages }] of packagesByWorkspace) {
223
+ const validPackages = packages.filter((pkg) => packagesWithTag.has(pkg))
224
+ await updatePackagesInWorkspace(validPackages, dir, name)
230
225
  }
231
226
  } else {
232
- // Bulk update when not using tags
233
- console.info(`
234
- 📦 Bulk updating ${packagesToUpdate.length} package(s) using --latest --ignore-scripts...
235
- `)
227
+ console.info(`\n📦 Updating packages across workspaces...`)
236
228
 
237
- const updateCommand = `bun update ${packagesToUpdate.join(' ')} --latest --ignore-scripts`
238
- console.info(`\n🪄 Running: ${updateCommand}\n`)
239
-
240
- try {
241
- await $`bun update ${packagesToUpdate} --latest --ignore-scripts`
242
- console.info(`✅ Successfully updated all packages (scripts ignored)`)
243
- } catch (error: any) {
244
- const errorMessage = error.message?.split('\n')[0]
245
- console.warn(`⚠️ Failed to update packages. Error: ${errorMessage}`)
229
+ for (const [name, { dir, packages }] of packagesByWorkspace) {
230
+ await updatePackagesInWorkspace(packages, dir, name)
246
231
  }
247
232
  }
248
233
 
249
234
  console.info(
250
235
  "\n⚙️ Running a final 'bun install' to process all changes and run lifecycle scripts..."
251
236
  )
237
+ $.cwd(rootDir)
252
238
  try {
253
239
  await $`bun install`
254
240
  console.info("✅ Final 'bun install' completed successfully.")
@@ -261,15 +247,20 @@ async function updatePackages(packagesToUpdate: string[], cwd: string) {
261
247
  }
262
248
  }
263
249
 
250
+ function getWorkspaceName(packageJsonPath: string, rootDir: string): string {
251
+ const dir = packageJsonPath.replace('/package.json', '')
252
+ if (dir === rootDir) return 'root'
253
+ return dir.replace(rootDir + '/', '')
254
+ }
255
+
264
256
  async function main() {
265
257
  const rootDir = process.cwd()
266
258
  const packageJsonFiles = findPackageJsonFiles(rootDir)
267
259
  console.info(`Found ${packageJsonFiles.length} package.json files`)
268
260
 
269
- // Get workspace package names to exclude from updates
261
+ // get workspace package names to exclude from updates
270
262
  const workspacePackageNames = new Set<string>()
271
263
  for (const packageJsonPath of packageJsonFiles) {
272
- // skip the root package.json when collecting workspace names
273
264
  if (packageJsonPath === join(rootDir, 'package.json')) continue
274
265
 
275
266
  try {
@@ -287,50 +278,49 @@ async function main() {
287
278
  `Found ${workspacePackageNames.size} workspace packages to exclude from updates`
288
279
  )
289
280
 
290
- const allDependencies = new Set<string>()
281
+ // build map of packages to update per workspace
282
+ const packagesByWorkspace = new Map<string, { dir: string; packages: string[] }>()
283
+ const allMatchingDeps = new Set<string>()
291
284
 
292
285
  for (const packageJsonPath of packageJsonFiles) {
293
286
  const deps = extractDependencies(packageJsonPath)
294
- deps.forEach((dep) => allDependencies.add(dep))
295
- }
287
+ const matchingDeps: string[] = []
296
288
 
297
- console.info(`Found ${allDependencies.size} total dependencies`)
289
+ for (const dep of deps) {
290
+ // skip workspace packages
291
+ if (workspacePackageNames.has(dep)) continue
298
292
 
299
- const matchingDependencies: string[] = []
300
- for (const dep of allDependencies) {
301
- // skip workspace packages - they should never be updated through bun update
302
- if (workspacePackageNames.has(dep)) {
303
- console.info(`⏩ Skipping workspace package: ${dep}`)
304
- continue
293
+ for (const pattern of packagePatterns) {
294
+ if (doesPackageMatchPattern(dep, pattern)) {
295
+ matchingDeps.push(dep)
296
+ allMatchingDeps.add(dep)
297
+ break
298
+ }
299
+ }
305
300
  }
306
301
 
307
- for (const pattern of packagePatterns) {
308
- // packagePatterns from arg parsing
309
- if (doesPackageMatchPattern(dep, pattern)) {
310
- matchingDependencies.push(dep)
311
- break
312
- }
302
+ if (matchingDeps.length > 0) {
303
+ const dir = packageJsonPath.replace('/package.json', '')
304
+ const name = getWorkspaceName(packageJsonPath, rootDir)
305
+ packagesByWorkspace.set(name, { dir, packages: matchingDeps })
313
306
  }
314
307
  }
315
308
 
316
309
  console.info(
317
- `Found ${matchingDependencies.length} dependencies matching patterns: ${packagePatterns.join(', ')}`
310
+ `Found ${allMatchingDeps.size} dependencies matching patterns: ${packagePatterns.join(', ')}`
318
311
  )
312
+ console.info(`Found matches in ${packagesByWorkspace.size} workspace(s)`)
319
313
 
320
- if (matchingDependencies.length === 0) {
314
+ if (allMatchingDeps.size === 0) {
321
315
  console.info('No matching packages found to update.')
322
316
  return
323
317
  }
324
318
 
325
- const packagesForBunUpdate: string[] = [...matchingDependencies]
326
-
327
319
  if (globalTag) {
328
- console.info(
329
- `🏷️ Using tag '${globalTag}' for ${packagesForBunUpdate.length} package(s)`
330
- )
320
+ console.info(`🏷️ Using tag '${globalTag}'`)
331
321
  }
332
322
 
333
- await updatePackages(packagesForBunUpdate, rootDir)
323
+ await updatePackages(packagesByWorkspace, rootDir)
334
324
 
335
325
  console.info('\n🎉 Dependency update complete!')
336
326
  }