@brickflow/cli 0.0.9 → 0.0.10

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @brickflow/cli
2
2
 
3
+ ## 0.0.10
4
+
5
+ ### Patch Changes
6
+
7
+ - Remove cli upgrade
8
+
3
9
  ## 0.0.9
4
10
 
5
11
  ### Patch Changes
package/index.mjs CHANGED
@@ -10,10 +10,24 @@ const commandsDir = path.join(cliDir, 'src')
10
10
  async function getAvailableCommands() {
11
11
  const entries = await readdir(commandsDir, { withFileTypes: true })
12
12
 
13
- return entries
14
- .filter((entry) => entry.isDirectory())
15
- .map((entry) => entry.name)
16
- .sort()
13
+ const commands = await Promise.all(
14
+ entries
15
+ .filter((entry) => entry.isDirectory())
16
+ .map(async (entry) => ((await hasCommandEntry(entry.name)) ? entry.name : null)),
17
+ )
18
+
19
+ return commands.filter(Boolean).sort()
20
+ }
21
+
22
+ async function hasCommandEntry(command) {
23
+ const commandEntry = path.join(commandsDir, command, 'index.js')
24
+
25
+ try {
26
+ await access(commandEntry)
27
+ return true
28
+ } catch {
29
+ return false
30
+ }
17
31
  }
18
32
 
19
33
  function isValidCommandName(command) {
@@ -45,14 +59,11 @@ async function runCommand(command) {
45
59
  return false
46
60
  }
47
61
 
48
- const commandEntry = path.join(commandsDir, command, 'index.js')
49
-
50
- try {
51
- await access(commandEntry)
52
- } catch {
62
+ if (!(await hasCommandEntry(command))) {
53
63
  return false
54
64
  }
55
65
 
66
+ const commandEntry = path.join(commandsDir, command, 'index.js')
56
67
  await import(pathToFileURL(commandEntry).href)
57
68
  return true
58
69
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brickflow/cli",
3
- "version": "0.0.9",
3
+ "version": "0.0.10",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "index.mjs",
@@ -5,13 +5,14 @@ import { globSync } from 'glob'
5
5
  import { resolveWorkspaceRoot } from '../shared/workspace-root.js'
6
6
 
7
7
  const args = process.argv.slice(3)
8
+ const filters = args.filter((arg) => arg !== '--help' && arg !== '-h')
8
9
 
9
10
  if (args.includes('--help') || args.includes('-h')) {
10
11
  printHelp()
11
12
  process.exit(0)
12
13
  }
13
14
 
14
- if (args.length > 0) {
15
+ if (filters.some((filter) => !isValidFilter(filter))) {
15
16
  printHelp()
16
17
  process.exit(1)
17
18
  }
@@ -22,6 +23,14 @@ const packageJsonPaths = globSync('**/package.json', {
22
23
  cwd: workspaceRoot,
23
24
  ignore: ['**/node_modules/**'],
24
25
  }).sort()
26
+ const latestVersions = await readLatestVersions(packageJsonPaths, filters)
27
+
28
+ if (latestVersions.size === 0) {
29
+ const scopeLabel = filters.length > 0 ? ` matching "${filters.join('", "')}"` : ''
30
+
31
+ console.log(`No packages found${scopeLabel}`)
32
+ process.exit(0)
33
+ }
25
34
 
26
35
  console.log('\x1b[32m', '\rPackage update')
27
36
 
@@ -36,7 +45,7 @@ for await (const packageJsonPath of packageJsonPaths) {
36
45
  }),
37
46
  )
38
47
 
39
- await updateJson(packageJson)
48
+ updateJson(packageJson, latestVersions)
40
49
  fs.writeFileSync(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}\n`)
41
50
 
42
51
  const percent = Math.round((index * 100) / packageJsonPaths.length)
@@ -46,19 +55,66 @@ for await (const packageJsonPath of packageJsonPaths) {
46
55
  process.stdout.write('\n')
47
56
  console.log('\x1b[0m', '')
48
57
 
58
+ function collectPackageNames(filePaths, packageFilters) {
59
+ const packageNames = new Set()
60
+
61
+ for (const filePath of filePaths) {
62
+ const packageJson = JSON.parse(fs.readFileSync(filePath, 'utf-8'))
63
+
64
+ for (const [dependencyName, dependencyVersion] of Object.entries(packageJson.dependencies || {})) {
65
+ if (shouldUpdateDependency(dependencyName, dependencyVersion, packageFilters)) {
66
+ packageNames.add(dependencyName)
67
+ }
68
+ }
69
+
70
+ for (const [dependencyName, dependencyVersion] of Object.entries(packageJson.devDependencies || {})) {
71
+ if (shouldUpdateDependency(dependencyName, dependencyVersion, packageFilters)) {
72
+ packageNames.add(dependencyName)
73
+ }
74
+ }
75
+ }
76
+
77
+ return [...packageNames].sort()
78
+ }
79
+
80
+ function escapeRegex(value) {
81
+ return value.replace(/[|\\{}()[\]^$+?.]/g, '\\$&')
82
+ }
83
+
84
+ function isValidFilter(value) {
85
+ return typeof value === 'string' && value.length > 0
86
+ }
87
+
49
88
  function isWorkspaceVersion(value) {
50
89
  return value === 'workspace:*' || value === 'workspace: *'
51
90
  }
52
91
 
92
+ function matchesAnyFilter(packageName, packageFilters) {
93
+ if (packageFilters.length === 0) {
94
+ return true
95
+ }
96
+
97
+ return packageFilters.some((filter) => matchesFilter(packageName, filter))
98
+ }
99
+
100
+ function matchesFilter(packageName, filter) {
101
+ const pattern = escapeRegex(filter).replace(/\*/g, '.*').replace(/\?/g, '.')
102
+
103
+ return new RegExp(`^${pattern}$`).test(packageName)
104
+ }
105
+
53
106
  function printHelp() {
54
107
  console.log(`brick latest
55
108
 
56
109
  Usage:
57
110
  brick latest
111
+ brick latest "@brickflow/*"
112
+ brick latest "vue" "@brickflow/*"
58
113
 
59
114
  Notes:
60
115
  Scans all package.json files in the repository, including the root one
61
116
  Updates dependencies and devDependencies to the latest npm versions
117
+ Optional wildcard filters limit which package names are updated
62
118
  Skips workspace:* versions`)
63
119
  }
64
120
 
@@ -76,29 +132,45 @@ function readLatestVersion(packageName) {
76
132
  })
77
133
  }
78
134
 
79
- async function updateJson(jsonData) {
80
- await Promise.all([
81
- ...Object.entries(jsonData.dependencies || {}).map(async ([key, value]) => {
82
- if (isWorkspaceVersion(value)) {
83
- return
84
- }
135
+ async function readLatestVersions(filePaths, packageFilters) {
136
+ const packageNames = collectPackageNames(filePaths, packageFilters)
137
+ const versionsMap = new Map()
85
138
 
86
- const version = await readLatestVersion(key)
139
+ await Promise.all(
140
+ packageNames.map(async (packageName) => {
141
+ const version = await readLatestVersion(packageName)
87
142
 
88
143
  if (version) {
89
- jsonData.dependencies[key] = version
144
+ versionsMap.set(packageName, version)
90
145
  }
91
146
  }),
92
- ...Object.entries(jsonData.devDependencies || {}).map(async ([key, value]) => {
93
- if (isWorkspaceVersion(value)) {
94
- return
95
- }
147
+ )
96
148
 
97
- const version = await readLatestVersion(key)
149
+ return versionsMap
150
+ }
98
151
 
99
- if (version) {
100
- jsonData.devDependencies[key] = version
101
- }
102
- }),
103
- ])
152
+ function shouldUpdateDependency(packageName, version, packageFilters) {
153
+ return !isWorkspaceVersion(version) && matchesAnyFilter(packageName, packageFilters)
154
+ }
155
+
156
+ function updateJson(jsonData, versionsMap) {
157
+ for (const [dependencyName, version] of Object.entries(jsonData.dependencies || {})) {
158
+ if (isWorkspaceVersion(version)) {
159
+ continue
160
+ }
161
+
162
+ if (versionsMap.has(dependencyName)) {
163
+ jsonData.dependencies[dependencyName] = versionsMap.get(dependencyName)
164
+ }
165
+ }
166
+
167
+ for (const [dependencyName, version] of Object.entries(jsonData.devDependencies || {})) {
168
+ if (isWorkspaceVersion(version)) {
169
+ continue
170
+ }
171
+
172
+ if (versionsMap.has(dependencyName)) {
173
+ jsonData.devDependencies[dependencyName] = versionsMap.get(dependencyName)
174
+ }
175
+ }
104
176
  }
@@ -1,168 +0,0 @@
1
- import { exec } from 'child_process'
2
- import fs from 'fs'
3
- import path from 'path'
4
-
5
- import { resolveWorkspaceRoot } from '../shared/workspace-root.js'
6
-
7
- const args = process.argv.slice(3)
8
-
9
- if (args.includes('--help') || args.includes('-h')) {
10
- printHelp()
11
- process.exit(0)
12
- }
13
-
14
- if (args.length > 0) {
15
- printHelp()
16
- process.exit(1)
17
- }
18
-
19
- const workspaceRoot = resolveWorkspaceRoot()
20
- const packageJsonPaths = findPackageJsonPaths()
21
- const localPackageNames = collectLocalBrickflowPackageNames(packageJsonPaths)
22
-
23
- if (localPackageNames.length === 0) {
24
- console.log('No local @brickflow/* packages found in the repository')
25
- process.exit(0)
26
- }
27
-
28
- const latestVersions = new Map()
29
-
30
- for (const packageName of localPackageNames) {
31
- const version = await readLatestVersion(packageName)
32
-
33
- if (version) {
34
- latestVersions.set(packageName, version)
35
- }
36
- }
37
-
38
- if (latestVersions.size === 0) {
39
- throw new Error('Could not resolve latest versions for local @brickflow/* packages')
40
- }
41
-
42
- console.log('\x1b[32m', '\rBrickflow package upgrade')
43
-
44
- let changedFiles = 0
45
- let index = 0
46
-
47
- for (const packageJsonPath of packageJsonPaths) {
48
- index += 1
49
-
50
- const packageJson = readJson(packageJsonPath)
51
- const before = JSON.stringify(packageJson)
52
-
53
- updateDependencySections(packageJson, latestVersions)
54
-
55
- if (JSON.stringify(packageJson) !== before) {
56
- writeJson(packageJsonPath, packageJson)
57
- changedFiles += 1
58
- console.log(`\nšŸ“¦ Updated ${getPackageLabel(packageJsonPath)}`)
59
- }
60
-
61
- const percent = Math.round((index * 100) / packageJsonPaths.length)
62
- process.stdout.write(`\ršŸ”© Upgrade: [${'ā–ˆ'.repeat(Math.round(percent / 10)).padEnd(10, ' ')}] ${percent}%`)
63
- }
64
-
65
- process.stdout.write('\n')
66
- console.log(`Updated ${changedFiles} package.json file(s)`)
67
- console.log('\x1b[0m', '')
68
-
69
- function collectLocalBrickflowPackageNames(filePaths) {
70
- return filePaths
71
- .map((filePath) => readJson(filePath).name)
72
- .filter((packageName) => isBrickflowPackageName(packageName))
73
- .sort()
74
- }
75
-
76
- function findPackageJsonPaths() {
77
- return walkDirectoryForPackageJson(workspaceRoot).sort()
78
- }
79
-
80
- function getDependencySections(packageJson) {
81
- return ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies']
82
- .map((sectionName) => ({
83
- name: sectionName,
84
- value: packageJson[sectionName],
85
- }))
86
- .filter((section) => section.value && typeof section.value === 'object')
87
- }
88
-
89
- function getPackageLabel(packageJsonPath) {
90
- const relativePath = path.relative(workspaceRoot, packageJsonPath).replace(/\\/g, '/')
91
- const packageDir = path.dirname(relativePath)
92
-
93
- return packageDir === '.' ? 'root' : packageDir
94
- }
95
-
96
- function isBrickflowPackageName(packageName) {
97
- return typeof packageName === 'string' && packageName.startsWith('@brickflow/')
98
- }
99
-
100
- function printHelp() {
101
- console.log(`brick upgrade
102
-
103
- Usage:
104
- brick upgrade
105
-
106
- Notes:
107
- Finds local @brickflow/* package names from package.json files in the repository
108
- Fetches the latest published version for each of those packages
109
- Updates matching dependencies, devDependencies, peerDependencies and optionalDependencies in all package.json files`)
110
- }
111
-
112
- function readJson(filePath) {
113
- return JSON.parse(fs.readFileSync(filePath, 'utf8'))
114
- }
115
-
116
- function readLatestVersion(packageName) {
117
- return new Promise((resolve) => {
118
- exec(`npm view ${packageName} version`, (error, stdout) => {
119
- if (error) {
120
- console.warn(`Skipping ${packageName}: ${error.message}`)
121
- resolve(null)
122
- return
123
- }
124
-
125
- resolve(String(stdout).trim().replace('\n', ''))
126
- })
127
- })
128
- }
129
-
130
- function updateDependencySections(packageJson, latestVersionsMap) {
131
- for (const section of getDependencySections(packageJson)) {
132
- for (const dependencyName of Object.keys(section.value)) {
133
- const latestVersion = latestVersionsMap.get(dependencyName)
134
-
135
- if (latestVersion) {
136
- section.value[dependencyName] = latestVersion
137
- }
138
- }
139
- }
140
- }
141
-
142
- function walkDirectoryForPackageJson(directoryPath) {
143
- const entries = fs.readdirSync(directoryPath, { withFileTypes: true })
144
- const filePaths = []
145
-
146
- for (const entry of entries) {
147
- if (entry.name === 'node_modules') {
148
- continue
149
- }
150
-
151
- const entryPath = path.join(directoryPath, entry.name)
152
-
153
- if (entry.isDirectory()) {
154
- filePaths.push(...walkDirectoryForPackageJson(entryPath))
155
- continue
156
- }
157
-
158
- if (entry.isFile() && entry.name === 'package.json') {
159
- filePaths.push(entryPath)
160
- }
161
- }
162
-
163
- return filePaths
164
- }
165
-
166
- function writeJson(filePath, value) {
167
- fs.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`)
168
- }