@brickflow/cli 0.0.57 → 0.0.59

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,17 @@
1
1
  # @brickflow/cli
2
2
 
3
+ ## 0.0.59
4
+
5
+ ### Patch Changes
6
+
7
+ - Fix dialog .ts
8
+
9
+ ## 0.0.58
10
+
11
+ ### Patch Changes
12
+
13
+ - Dialog release
14
+
3
15
  ## 0.0.57
4
16
 
5
17
  ### Patch Changes
package/README.md CHANGED
@@ -32,3 +32,13 @@ If a stroked element also has a visible fill, its original fill geometry is kept
32
32
  Run `brick svg` first for general SVGO optimization and `brick svg-fix` last for stroke expansion. After all strokes are expanded, later `svg-fix` runs do nothing; the two commands no longer alternate between competing canonical formats.
33
33
 
34
34
  Geometry and stroke lengths must be unitless or use `px`. Non-scaling strokes are rejected because expanding them correctly would require changing transforms; the original file is left untouched on failure.
35
+
36
+ ## Translation directories
37
+
38
+ `brick translate-sync`, `brick translate-context` and `brick translate` look for translatable sources in `packages/brick` and `apps/*` by default. Pass `--dirs` to use other directories:
39
+
40
+ ```sh
41
+ brick translate-sync --dirs "packages/stem,apps/*"
42
+ ```
43
+
44
+ Directories are comma-separated, relative to the workspace root, and may contain globs. Quote the value so the shell does not expand `*`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brickflow/cli",
3
- "version": "0.0.57",
3
+ "version": "0.0.59",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "index.mjs",
@@ -22,16 +22,16 @@
22
22
  "format:check": "pnpm exec prettier . --ignore-path ../../.prettierignore --check"
23
23
  },
24
24
  "dependencies": {
25
- "@babel/parser": "8.0.4",
26
- "@babel/traverse": "8.0.4",
27
- "@babel/types": "8.0.4",
28
- "@google/genai": "2.21.0",
29
- "@napi-rs/canvas": "1.0.8",
30
- "@vue/compiler-sfc": "3.5.42",
25
+ "@babel/parser": "8.0.10",
26
+ "@babel/traverse": "8.0.10",
27
+ "@babel/types": "8.0.10",
28
+ "@google/genai": "2.32.0",
29
+ "@napi-rs/canvas": "1.1.0",
30
+ "@vue/compiler-sfc": "3.5.44",
31
31
  "fantasticon": "4.1.0",
32
- "glob": "13.0.6",
32
+ "glob": "14.0.3",
33
33
  "looks-same": "10.0.1",
34
- "sharp": "0.35.4",
34
+ "sharp": "0.35.5",
35
35
  "svgo": "4.1.0",
36
36
  "svgpath": "2.6.0",
37
37
  "transformation-matrix": "3.1.0"
@@ -5,7 +5,7 @@ import { resolveWorkspaceRoot } from '../shared/workspace-root.js'
5
5
  import { getContextFilePath, readAiContextDescription } from '../translate-context/ai-context.js'
6
6
  import { translateBatch } from './ai.js'
7
7
  import { buildTranslateHelp, parseTranslateRuntimeArgs, setTranslateRuntimeConfig } from './runtime-config.js'
8
- import { listTranslationTargets, sortObjectKeys, stringifySortedJson } from './utils.js'
8
+ import { listTranslationTargets, setTranslateDirs, sortObjectKeys, stringifySortedJson } from './utils.js'
9
9
 
10
10
  const workspaceRoot = resolveWorkspaceRoot()
11
11
  const rawArgs = process.argv.slice(3)
@@ -20,6 +20,7 @@ let requestedLanguageCodes
20
20
 
21
21
  try {
22
22
  setTranslateRuntimeConfig(options)
23
+ setTranslateDirs(options.dirs, workspaceRoot)
23
24
  requestedLanguageCodes = parseLanguageCodes(options.locales)
24
25
  } catch (error) {
25
26
  console.error(error instanceof Error ? error.message : String(error))
@@ -1,3 +1,5 @@
1
+ import { DEFAULT_TRANSLATE_DIRS } from './utils.js'
2
+
1
3
  export const DEFAULT_CONTEXT_MODEL = 'gemini-3.1-flash-lite-preview'
2
4
 
3
5
  let runtimeConfig = null
@@ -14,6 +16,7 @@ Required options:
14
16
 
15
17
  Optional:
16
18
  --context-model "<model>" Default: ${DEFAULT_CONTEXT_MODEL}
19
+ --dirs "<dir,dir>" Default: ${DEFAULT_TRANSLATE_DIRS.join(',')}
17
20
 
18
21
  Example:
19
22
  ${command} \\
@@ -34,6 +37,7 @@ export function parseTranslateRuntimeArgs(rawArgs) {
34
37
  const options = {
35
38
  apiKey: null,
36
39
  contextModel: DEFAULT_CONTEXT_MODEL,
40
+ dirs: undefined,
37
41
  locales: undefined,
38
42
  productContext: null,
39
43
  }
@@ -60,6 +64,12 @@ export function parseTranslateRuntimeArgs(rawArgs) {
60
64
  continue
61
65
  }
62
66
 
67
+ if (value === '--dirs') {
68
+ options.dirs = rawArgs[index + 1] ?? null
69
+ index += 1
70
+ continue
71
+ }
72
+
63
73
  if (value === '--locales') {
64
74
  options.locales = rawArgs[index + 1] ?? null
65
75
  index += 1
@@ -4,9 +4,11 @@ import { isIdentifier, isMemberExpression, isStringLiteral, isTemplateLiteral }
4
4
  import { compileTemplate, parse as parseSFC } from '@vue/compiler-sfc'
5
5
  import { execFileSync } from 'child_process'
6
6
  import { createHash } from 'crypto'
7
- import { existsSync } from 'fs'
7
+ import { existsSync, statSync } from 'fs'
8
8
  import { globSync } from 'glob'
9
- import { join, resolve } from 'path'
9
+ import { dirname, join, relative, resolve } from 'path'
10
+
11
+ import { resolveWorkspaceRoot } from '../shared/workspace-root.js'
10
12
 
11
13
  const tTraverse = traverseModule.default || traverseModule
12
14
  const IGNORED_GLOB_PATTERNS = [
@@ -18,8 +20,12 @@ const IGNORED_GLOB_PATTERNS = [
18
20
  '**/public/**',
19
21
  ]
20
22
  const IGNORED_SOURCE_SEGMENTS = ['/node_modules/', '/.nuxt/', '/dist/', '/.output/', '/coverage/', '/public/']
21
- const TRANSLATION_SAMPLE_GLOB =
22
- '{packages/brick,apps/*}/{components/**/translate,pages-translate/*,layouts-translate/**,script-translate/*}/sample.json'
23
+ export const DEFAULT_TRANSLATE_DIRS = ['packages/brick', 'apps/*']
24
+ const TRANSLATION_DIRS_GLOB = '{components/**/translate,pages-translate/*,layouts-translate/**,script-translate/*}'
25
+
26
+ let translateDirs = DEFAULT_TRANSLATE_DIRS
27
+ let translateRoots = null
28
+ let workspaceRootDir = null
23
29
 
24
30
  export function compileVueToJS(code, filePath) {
25
31
  const { descriptor } = parseSFC(code)
@@ -127,23 +133,30 @@ export function getProjectName(id) {
127
133
 
128
134
  export function getProjectRoot(id) {
129
135
  const normalizedId = id.replace(/[?#].*$/, '')
130
- const brickMatch = normalizedId.match(/^(.*\/packages\/brick)(?:\/|$)/)
131
136
 
132
- if (brickMatch) {
133
- return brickMatch[1]
137
+ if (!translateRoots) {
138
+ setTranslateDirs(undefined, resolveWorkspaceRoot())
134
139
  }
135
140
 
136
- const appMatch = normalizedId.match(/^(.*\/apps\/[^/]+)(?:\/|$)/)
137
-
138
- return appMatch?.[1] ?? null
141
+ return translateRoots.find((rootDir) => normalizedId.startsWith(`${rootDir}/`)) ?? null
139
142
  }
140
143
 
141
144
  export function getScriptName(id) {
142
- const relativePath = id.split('/packages/')[1] ?? id.split('/apps/')[1] ?? id.replace(/^\//, '')
145
+ const projectRoot = getProjectRoot(id)
146
+ const baseDir = projectRoot ? dirname(projectRoot) : (workspaceRootDir ?? resolveWorkspaceRoot())
147
+ const relativePath = relative(baseDir, id).replace(/\\/g, '/')
143
148
 
144
149
  return toPageName(relativePath.replace(/\.\w+$/, '').replace(/\//g, '_'))
145
150
  }
146
151
 
152
+ export function getTranslateDirs() {
153
+ return translateDirs
154
+ }
155
+
156
+ export function getTranslationGlobs(fileName) {
157
+ return translateDirs.map((dir) => `${dir}/${TRANSLATION_DIRS_GLOB}/${fileName}`)
158
+ }
159
+
147
160
  export function getTranslationPaths(id) {
148
161
  if (isVueSubResourceId(id)) {
149
162
  return null
@@ -158,18 +171,16 @@ export function getTranslationPaths(id) {
158
171
  return null
159
172
  }
160
173
 
161
- const isComponent =
162
- normalizedId.endsWith('.vue') &&
163
- (normalizedId.includes('/packages/brick/components/') ||
164
- (normalizedId.includes('/apps/') && normalizedId.includes('/components/')))
174
+ const projectRoot = getProjectRoot(normalizedId)
175
+ if (!projectRoot) {
176
+ return null
177
+ }
178
+
179
+ const isComponent = normalizedId.endsWith('.vue') && normalizedId.includes('/components/')
165
180
  const isPage = normalizedId.endsWith('.vue') && normalizedId.includes('/pages/')
166
181
  const isLayout = normalizedId.endsWith('.vue') && normalizedId.includes('/layouts/')
167
- const projectRoot = getProjectRoot(normalizedId)
168
182
  const isScript =
169
- !normalizedId.endsWith('.vue') &&
170
- Boolean(projectRoot) &&
171
- /\.(?:js|ts)$/.test(normalizedId) &&
172
- !normalizedId.endsWith('.d.ts')
183
+ !normalizedId.endsWith('.vue') && /\.(?:js|ts)$/.test(normalizedId) && !normalizedId.endsWith('.d.ts')
173
184
 
174
185
  if (isComponent && !normalizedId.endsWith('/index.vue')) {
175
186
  return null
@@ -235,7 +246,7 @@ export function getTranslationPaths(id) {
235
246
  }
236
247
 
237
248
  export function listTranslationSamplePaths(workspaceRoot) {
238
- return globSync(TRANSLATION_SAMPLE_GLOB, {
249
+ return globSync(getTranslationGlobs('sample.json'), {
239
250
  absolute: true,
240
251
  cwd: workspaceRoot,
241
252
  ignore: IGNORED_GLOB_PATTERNS,
@@ -289,6 +300,32 @@ export function normalize(input) {
289
300
  return input.trim().toLowerCase().replace(/\s+/g, ' ')
290
301
  }
291
302
 
303
+ export function setTranslateDirs(value, workspaceRoot) {
304
+ const dirs =
305
+ value === undefined
306
+ ? DEFAULT_TRANSLATE_DIRS
307
+ : String(value ?? '')
308
+ .split(',')
309
+ .map((dir) => dir.trim().replace(/\\/g, '/').replace(/^\.\//, '').replace(/\/+$/, ''))
310
+ .filter(Boolean)
311
+
312
+ if (dirs.length === 0) {
313
+ throw new Error(
314
+ 'Invalid --dirs value. Use comma-separated directories, for example: --dirs "packages/stem,apps/*"',
315
+ )
316
+ }
317
+
318
+ translateDirs = dirs
319
+ workspaceRootDir = workspaceRoot
320
+ translateRoots = globSync(dirs, {
321
+ absolute: true,
322
+ cwd: workspaceRoot,
323
+ ignore: IGNORED_GLOB_PATTERNS,
324
+ })
325
+ .filter((dirPath) => statSync(dirPath).isDirectory())
326
+ .sort((left, right) => right.length - left.length)
327
+ }
328
+
292
329
  export function shortHash(input) {
293
330
  return createHash('md5').update(input).digest('hex').slice(0, 4)
294
331
  }
@@ -14,12 +14,15 @@ import {
14
14
  parseTranslateRuntimeArgs,
15
15
  setTranslateRuntimeConfig,
16
16
  } from '../translate/runtime-config.js'
17
- import { listTranslationTargets, stringifySortedJson } from '../translate/utils.js'
17
+ import {
18
+ getTranslationGlobs,
19
+ listTranslationTargets,
20
+ setTranslateDirs,
21
+ stringifySortedJson,
22
+ } from '../translate/utils.js'
18
23
 
19
24
  const workspaceRoot = resolveWorkspaceRoot()
20
25
  const CONTEXT_FILE_NAME = 'ai-context.json'
21
- const CONTEXT_FILE_GLOB =
22
- '{packages/brick,apps/*}/{components/**/translate,pages-translate/*,layouts-translate/**,script-translate/*}/ai-context.json'
23
26
  const CHANGE_THRESHOLD = readFloat('TRANSLATE_CONTEXT_MIN_CHANGE', 0.3)
24
27
  const SOURCE_MAX_CHARS = readPositiveInt('TRANSLATE_CONTEXT_SOURCE_MAX_CHARS', 16000)
25
28
 
@@ -122,7 +125,7 @@ export function readAiContextDescription(samplePath) {
122
125
 
123
126
  export function removeObsoleteAiContexts(targets, rootDir = workspaceRoot) {
124
127
  const activeContextPaths = new Set(targets.map(({ samplePath }) => getContextFilePath(samplePath)))
125
- const contextPaths = globSync(CONTEXT_FILE_GLOB, {
128
+ const contextPaths = globSync(getTranslationGlobs(CONTEXT_FILE_NAME), {
126
129
  absolute: true,
127
130
  cwd: rootDir,
128
131
  nodir: true,
@@ -152,6 +155,7 @@ export async function runAiContextCli(rawArgs = process.argv.slice(3), command =
152
155
 
153
156
  try {
154
157
  setTranslateRuntimeConfig(options)
158
+ setTranslateDirs(options.dirs, workspaceRoot)
155
159
  } catch (error) {
156
160
  console.error(error instanceof Error ? error.message : String(error))
157
161
  console.error('')
@@ -4,9 +4,12 @@ import path from 'path'
4
4
 
5
5
  import {
6
6
  compileVueToJS,
7
+ DEFAULT_TRANSLATE_DIRS,
7
8
  extractStrings,
9
+ getTranslateDirs,
8
10
  getTranslationPaths,
9
11
  listWorkspaceFiles,
12
+ setTranslateDirs,
10
13
  sortObjectKeys,
11
14
  stringifySortedJson,
12
15
  } from '../translate/utils.js'
@@ -20,21 +23,31 @@ if (args.includes('--help') || args.includes('-h')) {
20
23
  process.exit(0)
21
24
  }
22
25
 
23
- if (args.length > 0) {
26
+ const dirsIndex = args.indexOf('--dirs')
27
+ const isValidArgs = args.length === 0 || (args.length === 2 && dirsIndex === 0)
28
+
29
+ if (!isValidArgs) {
24
30
  printHelp()
25
31
  process.exit(1)
26
32
  }
27
33
 
28
34
  const workspaceRoot = resolveWorkspaceRoot()
35
+
36
+ try {
37
+ setTranslateDirs(dirsIndex === 0 ? args[1] : undefined, workspaceRoot)
38
+ } catch (error) {
39
+ console.error(error instanceof Error ? error.message : String(error))
40
+ process.exit(1)
41
+ }
29
42
  const activeTranslationDirs = new Set()
30
43
  const cleanupRoots = new Set()
31
- const staticCleanupRoots = [
32
- path.resolve(workspaceRoot, 'packages/brick/script-translate'),
33
- ...globSync('apps/*/script-translate', {
44
+ const staticCleanupRoots = globSync(
45
+ getTranslateDirs().map((dir) => `${dir}/script-translate`),
46
+ {
34
47
  absolute: true,
35
48
  cwd: workspaceRoot,
36
- }),
37
- ]
49
+ },
50
+ )
38
51
 
39
52
  const files = listWorkspaceFiles(workspaceRoot).filter(
40
53
  (file) => /\.(?:js|ts|vue)$/.test(file) && !file.endsWith('.d.ts'),
@@ -152,7 +165,10 @@ function printHelp() {
152
165
  console.log(`brick translate-sync
153
166
 
154
167
  Usage:
155
- brick translate-sync
168
+ brick translate-sync [--dirs "<dir,dir>"]
169
+
170
+ Options:
171
+ --dirs Comma-separated translation directories. Default: ${DEFAULT_TRANSLATE_DIRS.join(',')}
156
172
 
157
173
  Notes:
158
174
  Scans source files and regenerates translation sample.json files