@brickflow/cli 0.0.8 → 0.0.9
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 +6 -0
- package/package.json +1 -1
- package/src/latest/index.js +3 -4
- package/src/shared/workspace-root.js +31 -0
- package/src/translate/ai-context.js +50 -50
- package/src/translate/utils.js +22 -22
- package/src/upgrade/index.js +7 -7
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
package/src/latest/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { exec } from 'child_process'
|
|
2
2
|
import fs from 'fs'
|
|
3
3
|
import { globSync } from 'glob'
|
|
4
|
-
|
|
5
|
-
import {
|
|
4
|
+
|
|
5
|
+
import { resolveWorkspaceRoot } from '../shared/workspace-root.js'
|
|
6
6
|
|
|
7
7
|
const args = process.argv.slice(3)
|
|
8
8
|
|
|
@@ -16,8 +16,7 @@ if (args.length > 0) {
|
|
|
16
16
|
process.exit(1)
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
const
|
|
20
|
-
const workspaceRoot = path.resolve(currentDir, './')
|
|
19
|
+
const workspaceRoot = resolveWorkspaceRoot()
|
|
21
20
|
const packageJsonPaths = globSync('**/package.json', {
|
|
22
21
|
absolute: true,
|
|
23
22
|
cwd: workspaceRoot,
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
|
|
4
|
+
const WORKSPACE_MARKERS = ['.git', 'pnpm-workspace.yaml', 'lerna.json', 'turbo.json']
|
|
5
|
+
|
|
6
|
+
export function resolveWorkspaceRoot(startDir = process.cwd()) {
|
|
7
|
+
let currentDir = path.resolve(startDir)
|
|
8
|
+
let packageRoot = null
|
|
9
|
+
|
|
10
|
+
while (true) {
|
|
11
|
+
if (hasAnyFile(currentDir, WORKSPACE_MARKERS)) {
|
|
12
|
+
return currentDir
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (fs.existsSync(path.join(currentDir, 'package.json'))) {
|
|
16
|
+
packageRoot = currentDir
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const parentDir = path.dirname(currentDir)
|
|
20
|
+
|
|
21
|
+
if (parentDir === currentDir) {
|
|
22
|
+
return packageRoot || startDir
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
currentDir = parentDir
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function hasAnyFile(directoryPath, fileNames) {
|
|
30
|
+
return fileNames.some((fileName) => fs.existsSync(path.join(directoryPath, fileName)))
|
|
31
|
+
}
|
|
@@ -20,6 +20,10 @@ const CONTEXT_FILE_NAME = 'ai-context.json'
|
|
|
20
20
|
const CHANGE_THRESHOLD = readFloat('TRANSLATE_CONTEXT_MIN_CHANGE', 0.3)
|
|
21
21
|
const SOURCE_MAX_CHARS = readPositiveInt('TRANSLATE_CONTEXT_SOURCE_MAX_CHARS', 16000)
|
|
22
22
|
|
|
23
|
+
export function buildAiContextHelp(command = 'brick translate-context') {
|
|
24
|
+
return `${buildTranslateHelp(command)}\n\nExtra:\n --force`
|
|
25
|
+
}
|
|
26
|
+
|
|
23
27
|
export function calculateChangeRatio(previousSource, nextSource) {
|
|
24
28
|
const before = normalizeSource(previousSource)
|
|
25
29
|
const after = normalizeSource(nextSource)
|
|
@@ -112,6 +116,52 @@ export function getContextFilePath(samplePath) {
|
|
|
112
116
|
return join(dirname(samplePath), CONTEXT_FILE_NAME)
|
|
113
117
|
}
|
|
114
118
|
|
|
119
|
+
export async function runAiContextCli(rawArgs = process.argv.slice(3), command = 'brick translate-context') {
|
|
120
|
+
const helpText = buildAiContextHelp(command)
|
|
121
|
+
|
|
122
|
+
if (rawArgs.includes('--help') || rawArgs.includes('-h')) {
|
|
123
|
+
console.log(helpText)
|
|
124
|
+
process.exit(0)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const force = rawArgs.includes('--force')
|
|
128
|
+
const filteredArgs = rawArgs.filter((arg) => arg !== '--force')
|
|
129
|
+
const { options, positional } = parseTranslateRuntimeArgs(filteredArgs)
|
|
130
|
+
|
|
131
|
+
try {
|
|
132
|
+
setTranslateRuntimeConfig(options)
|
|
133
|
+
} catch (error) {
|
|
134
|
+
console.error(error instanceof Error ? error.message : String(error))
|
|
135
|
+
console.error('')
|
|
136
|
+
console.error(helpText)
|
|
137
|
+
process.exit(1)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const targets = listTranslationTargets(workspaceRoot)
|
|
141
|
+
const requestedSamplePaths =
|
|
142
|
+
positional.length > 0 ? new Set(positional.map((samplePath) => resolve(workspaceRoot, samplePath))) : null
|
|
143
|
+
const targetEntries = requestedSamplePaths
|
|
144
|
+
? targets.filter(({ samplePath }) => requestedSamplePaths.has(samplePath))
|
|
145
|
+
: targets
|
|
146
|
+
|
|
147
|
+
for (const { samplePath, sourceFilePath } of targetEntries) {
|
|
148
|
+
if (!sourceFilePath || !fs.existsSync(samplePath)) {
|
|
149
|
+
continue
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const description = await ensureAiContext({
|
|
153
|
+
force,
|
|
154
|
+
sample: JSON.parse(fs.readFileSync(samplePath, 'utf-8')),
|
|
155
|
+
samplePath,
|
|
156
|
+
sourceFilePath,
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
if (description) {
|
|
160
|
+
console.log(`🧠 Context updated: ${relative(workspaceRoot, samplePath)}`)
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
115
165
|
function buildContextContents({ sampleEntries, samplePath, sourceCode, sourceFilePath }) {
|
|
116
166
|
return [
|
|
117
167
|
`Sample path: ${samplePath}`,
|
|
@@ -251,56 +301,6 @@ function readPositiveInt(name, fallback) {
|
|
|
251
301
|
return Number.isFinite(value) && value > 0 ? value : fallback
|
|
252
302
|
}
|
|
253
303
|
|
|
254
|
-
export function buildAiContextHelp(command = 'brick translate-context') {
|
|
255
|
-
return `${buildTranslateHelp(command)}\n\nExtra:\n --force`
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
export async function runAiContextCli(rawArgs = process.argv.slice(3), command = 'brick translate-context') {
|
|
259
|
-
const helpText = buildAiContextHelp(command)
|
|
260
|
-
|
|
261
|
-
if (rawArgs.includes('--help') || rawArgs.includes('-h')) {
|
|
262
|
-
console.log(helpText)
|
|
263
|
-
process.exit(0)
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
const force = rawArgs.includes('--force')
|
|
267
|
-
const filteredArgs = rawArgs.filter((arg) => arg !== '--force')
|
|
268
|
-
const { options, positional } = parseTranslateRuntimeArgs(filteredArgs)
|
|
269
|
-
|
|
270
|
-
try {
|
|
271
|
-
setTranslateRuntimeConfig(options)
|
|
272
|
-
} catch (error) {
|
|
273
|
-
console.error(error instanceof Error ? error.message : String(error))
|
|
274
|
-
console.error('')
|
|
275
|
-
console.error(helpText)
|
|
276
|
-
process.exit(1)
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
const targets = listTranslationTargets(workspaceRoot)
|
|
280
|
-
const requestedSamplePaths =
|
|
281
|
-
positional.length > 0 ? new Set(positional.map((samplePath) => resolve(workspaceRoot, samplePath))) : null
|
|
282
|
-
const targetEntries = requestedSamplePaths
|
|
283
|
-
? targets.filter(({ samplePath }) => requestedSamplePaths.has(samplePath))
|
|
284
|
-
: targets
|
|
285
|
-
|
|
286
|
-
for (const { samplePath, sourceFilePath } of targetEntries) {
|
|
287
|
-
if (!sourceFilePath || !fs.existsSync(samplePath)) {
|
|
288
|
-
continue
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
const description = await ensureAiContext({
|
|
292
|
-
force,
|
|
293
|
-
sample: JSON.parse(fs.readFileSync(samplePath, 'utf-8')),
|
|
294
|
-
samplePath,
|
|
295
|
-
sourceFilePath,
|
|
296
|
-
})
|
|
297
|
-
|
|
298
|
-
if (description) {
|
|
299
|
-
console.log(`🧠 Context updated: ${relative(workspaceRoot, samplePath)}`)
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
|
|
304
304
|
function writeTextPreservingEol(filePath, content) {
|
|
305
305
|
const eol = detectEol(filePath)
|
|
306
306
|
const normalized = String(content).replace(/\r?\n/g, eol)
|
package/src/translate/utils.js
CHANGED
|
@@ -235,28 +235,6 @@ export function getTranslationPaths(id) {
|
|
|
235
235
|
}
|
|
236
236
|
}
|
|
237
237
|
|
|
238
|
-
export function listWorkspaceFiles(workspaceRoot) {
|
|
239
|
-
try {
|
|
240
|
-
const output = execFileSync('git', ['ls-files', '-co', '--exclude-standard', '-z'], {
|
|
241
|
-
cwd: workspaceRoot,
|
|
242
|
-
encoding: 'utf-8',
|
|
243
|
-
})
|
|
244
|
-
|
|
245
|
-
return output
|
|
246
|
-
.split('\0')
|
|
247
|
-
.filter(Boolean)
|
|
248
|
-
.map((file) => resolve(workspaceRoot, file))
|
|
249
|
-
.filter((filePath) => existsSync(filePath))
|
|
250
|
-
} catch {
|
|
251
|
-
return globSync('**/*', {
|
|
252
|
-
absolute: true,
|
|
253
|
-
cwd: workspaceRoot,
|
|
254
|
-
ignore: IGNORED_GLOB_PATTERNS,
|
|
255
|
-
nodir: true,
|
|
256
|
-
})
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
|
|
260
238
|
export function listTranslationSamplePaths(workspaceRoot) {
|
|
261
239
|
return globSync(TRANSLATION_SAMPLE_GLOB, {
|
|
262
240
|
absolute: true,
|
|
@@ -286,6 +264,28 @@ export function listTranslationTargets(workspaceRoot) {
|
|
|
286
264
|
}))
|
|
287
265
|
}
|
|
288
266
|
|
|
267
|
+
export function listWorkspaceFiles(workspaceRoot) {
|
|
268
|
+
try {
|
|
269
|
+
const output = execFileSync('git', ['ls-files', '-co', '--exclude-standard', '-z'], {
|
|
270
|
+
cwd: workspaceRoot,
|
|
271
|
+
encoding: 'utf-8',
|
|
272
|
+
})
|
|
273
|
+
|
|
274
|
+
return output
|
|
275
|
+
.split('\0')
|
|
276
|
+
.filter(Boolean)
|
|
277
|
+
.map((file) => resolve(workspaceRoot, file))
|
|
278
|
+
.filter((filePath) => existsSync(filePath))
|
|
279
|
+
} catch {
|
|
280
|
+
return globSync('**/*', {
|
|
281
|
+
absolute: true,
|
|
282
|
+
cwd: workspaceRoot,
|
|
283
|
+
ignore: IGNORED_GLOB_PATTERNS,
|
|
284
|
+
nodir: true,
|
|
285
|
+
})
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
289
|
export function normalize(input) {
|
|
290
290
|
return input.trim().toLowerCase().replace(/\s+/g, ' ')
|
|
291
291
|
}
|
package/src/upgrade/index.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { exec } from 'child_process'
|
|
2
2
|
import fs from 'fs'
|
|
3
3
|
import path from 'path'
|
|
4
|
-
|
|
4
|
+
|
|
5
|
+
import { resolveWorkspaceRoot } from '../shared/workspace-root.js'
|
|
5
6
|
|
|
6
7
|
const args = process.argv.slice(3)
|
|
7
8
|
|
|
@@ -15,8 +16,7 @@ if (args.length > 0) {
|
|
|
15
16
|
process.exit(1)
|
|
16
17
|
}
|
|
17
18
|
|
|
18
|
-
const
|
|
19
|
-
const workspaceRoot = path.resolve(currentDir, '../../../..')
|
|
19
|
+
const workspaceRoot = resolveWorkspaceRoot()
|
|
20
20
|
const packageJsonPaths = findPackageJsonPaths()
|
|
21
21
|
const localPackageNames = collectLocalBrickflowPackageNames(packageJsonPaths)
|
|
22
22
|
|
|
@@ -139,10 +139,6 @@ function updateDependencySections(packageJson, latestVersionsMap) {
|
|
|
139
139
|
}
|
|
140
140
|
}
|
|
141
141
|
|
|
142
|
-
function writeJson(filePath, value) {
|
|
143
|
-
fs.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`)
|
|
144
|
-
}
|
|
145
|
-
|
|
146
142
|
function walkDirectoryForPackageJson(directoryPath) {
|
|
147
143
|
const entries = fs.readdirSync(directoryPath, { withFileTypes: true })
|
|
148
144
|
const filePaths = []
|
|
@@ -166,3 +162,7 @@ function walkDirectoryForPackageJson(directoryPath) {
|
|
|
166
162
|
|
|
167
163
|
return filePaths
|
|
168
164
|
}
|
|
165
|
+
|
|
166
|
+
function writeJson(filePath, value) {
|
|
167
|
+
fs.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`)
|
|
168
|
+
}
|