@fugood/bricks-ctor 2.25.0-beta.56 → 2.25.0-beta.58

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.
@@ -249,6 +249,37 @@ describe('compile event handlers', () => {
249
249
  })
250
250
  })
251
251
 
252
+ describe('compile expanded state', () => {
253
+ test('defaults canvas, bricks, and data collapsed for generated configs', async () => {
254
+ const config = await compile(makeApp([], [makeData(undefined)]))
255
+
256
+ expect(config.subspace_map[SUBSPACE_ID]._expanded).toEqual({
257
+ brick: false,
258
+ generator: true,
259
+ canvas: { [CANVAS_ID]: false },
260
+ property_bank: false,
261
+ property_bank_calc: true,
262
+ })
263
+ })
264
+
265
+ test('preserves explicit source unexpanded state when present', async () => {
266
+ const app = makeApp()
267
+ app.rootSubspace.unexpanded = {
268
+ generator: true,
269
+ dataCalculation: true,
270
+ }
271
+
272
+ const config = await compile(app)
273
+ const expanded = config.subspace_map[SUBSPACE_ID]._expanded
274
+
275
+ expect(expanded.brick).toBe(true)
276
+ expect(expanded.generator).toBe(false)
277
+ expect(expanded.canvas).toBeUndefined()
278
+ expect(expanded.property_bank).toBe(true)
279
+ expect(expanded.property_bank_calc).toBe(false)
280
+ })
281
+ })
282
+
252
283
  describe('compile data remote update', () => {
253
284
  test.each([
254
285
  [undefined, { bank_type: 'none' }],
package/compile/index.ts CHANGED
@@ -751,6 +751,17 @@ const compileAutomation = (automationMap: AutomationMap) =>
751
751
  }),
752
752
  )
753
753
 
754
+ const buildDefaultExpandedState = (subspace: Subspace) => ({
755
+ brick: false,
756
+ generator: true,
757
+ canvas: (subspace.canvases || []).reduce((acc, canvas) => {
758
+ if (canvas?.id) acc[canvas.id] = false
759
+ return acc
760
+ }, {}),
761
+ property_bank: false,
762
+ property_bank_calc: true,
763
+ })
764
+
754
765
  // Record the minimal compiled-config delta this compile produced to the shared audit
755
766
  // log (`.bricks/edits.jsonl`), so editing files directly and running `bun compile`
756
767
  // leaves the same trail as the MCP source-editing tools. Maintained only in the
@@ -868,7 +879,7 @@ export const compile = async (app: Application) => {
868
879
  property_bank: !subspace.unexpanded.data,
869
880
  property_bank_calc: !subspace.unexpanded.dataCalculation,
870
881
  }
871
- : undefined,
882
+ : buildDefaultExpandedState(subspace),
872
883
  layout: {
873
884
  width: subspace.layout?.width,
874
885
  height: subspace.layout?.height,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fugood/bricks-ctor",
3
- "version": "2.25.0-beta.56",
3
+ "version": "2.25.0-beta.58",
4
4
  "main": "index.ts",
5
5
  "scripts": {
6
6
  "typecheck": "tsc --noEmit",
@@ -11,7 +11,7 @@
11
11
  "@babel/parser": "7.28.5",
12
12
  "@babel/traverse": "7.28.5",
13
13
  "@babel/types": "7.28.5",
14
- "@fugood/bricks-cli": "^2.25.0-beta.53",
14
+ "@fugood/bricks-cli": "^2.25.0-beta.58",
15
15
  "@huggingface/gguf": "^0.3.2",
16
16
  "@iarna/toml": "^3.0.0",
17
17
  "@modelcontextprotocol/sdk": "^1.15.0",
@@ -29,5 +29,5 @@
29
29
  "peerDependencies": {
30
30
  "oxfmt": "^0.36.0"
31
31
  },
32
- "gitHead": "5d3de40404adc334a9a64046c5514e1cd86132db"
32
+ "gitHead": "355da5754f1136c10e073460af4727dae94f7e30"
33
33
  }
@@ -56,3 +56,43 @@ export const removeObjectProperty = (object: t.ObjectExpression, key: string) =>
56
56
  })
57
57
  if (index >= 0) object.properties.splice(index, 1)
58
58
  }
59
+
60
+ export const insertImport = (ast: t.File, declaration: t.ImportDeclaration) => {
61
+ const body = ast.program.body
62
+ const lastImportIndex = body.findLastIndex((statement) => t.isImportDeclaration(statement))
63
+ body.splice(lastImportIndex + 1, 0, declaration)
64
+ }
65
+
66
+ export const ensureBricksCtorImport = (
67
+ ast: t.File,
68
+ importKind: 'type' | 'value',
69
+ names: Iterable<string>,
70
+ ) => {
71
+ const missing = new Set(Array.from(names).filter(Boolean))
72
+ if (missing.size === 0) return
73
+
74
+ for (const statement of ast.program.body) {
75
+ if (!t.isImportDeclaration(statement) || statement.source.value !== 'bricks-ctor') continue
76
+ const isTypeImport = statement.importKind === 'type'
77
+ if ((importKind === 'type') !== isTypeImport) continue
78
+
79
+ statement.specifiers.forEach((specifier) => {
80
+ if (!t.isImportSpecifier(specifier)) return
81
+ const imported = specifier.imported
82
+ if (t.isIdentifier(imported)) missing.delete(imported.name)
83
+ if (t.isStringLiteral(imported)) missing.delete(imported.value)
84
+ })
85
+
86
+ missing.forEach((name) => {
87
+ statement.specifiers.push(t.importSpecifier(t.identifier(name), t.identifier(name)))
88
+ })
89
+ return
90
+ }
91
+
92
+ const declaration = t.importDeclaration(
93
+ Array.from(missing).map((name) => t.importSpecifier(t.identifier(name), t.identifier(name))),
94
+ t.stringLiteral('bricks-ctor'),
95
+ )
96
+ if (importKind === 'type') declaration.importKind = 'type'
97
+ insertImport(ast, declaration)
98
+ }
@@ -10,8 +10,10 @@ import { z } from 'zod'
10
10
 
11
11
  import { verifyProject } from './_verify'
12
12
  import {
13
+ ensureBricksCtorImport,
13
14
  getObjectProperty,
14
15
  getStringProperty,
16
+ insertImport,
15
17
  isRecord,
16
18
  makeObjectKey,
17
19
  oxfmtOptions,
@@ -328,12 +330,6 @@ const relativeImportSource = (fromFile: string, toFile: string) => {
328
330
  return rel.replace(/\.(ts|tsx|js|jsx)$/, '')
329
331
  }
330
332
 
331
- const insertImport = (ast: t.File, declaration: t.ImportDeclaration) => {
332
- const body = ast.program.body
333
- const lastImportIndex = body.findLastIndex((statement) => t.isImportDeclaration(statement))
334
- body.splice(lastImportIndex + 1, 0, declaration)
335
- }
336
-
337
333
  const ensureNamespaceImport = (parsed: ParsedFile, source: string, preferredLocal: string) => {
338
334
  for (const statement of parsed.ast.program.body) {
339
335
  if (!t.isImportDeclaration(statement) || statement.source.value !== source) continue
@@ -352,40 +348,6 @@ const ensureNamespaceImport = (parsed: ParsedFile, source: string, preferredLoca
352
348
  return preferredLocal
353
349
  }
354
350
 
355
- const ensureBricksCtorImport = (
356
- ast: t.File,
357
- importKind: 'type' | 'value',
358
- names: Iterable<string>,
359
- ) => {
360
- const missing = new Set(Array.from(names).filter(Boolean))
361
- if (missing.size === 0) return
362
-
363
- for (const statement of ast.program.body) {
364
- if (!t.isImportDeclaration(statement) || statement.source.value !== 'bricks-ctor') continue
365
- const isTypeImport = statement.importKind === 'type'
366
- if ((importKind === 'type') !== isTypeImport) continue
367
-
368
- statement.specifiers.forEach((specifier) => {
369
- if (!t.isImportSpecifier(specifier)) return
370
- const imported = specifier.imported
371
- if (t.isIdentifier(imported)) missing.delete(imported.name)
372
- if (t.isStringLiteral(imported)) missing.delete(imported.value)
373
- })
374
-
375
- missing.forEach((name) => {
376
- statement.specifiers.push(t.importSpecifier(t.identifier(name), t.identifier(name)))
377
- })
378
- return
379
- }
380
-
381
- const declaration = t.importDeclaration(
382
- Array.from(missing).map((name) => t.importSpecifier(t.identifier(name), t.identifier(name))),
383
- t.stringLiteral('bricks-ctor'),
384
- )
385
- if (importKind === 'type') declaration.importKind = 'type'
386
- insertImport(ast, declaration)
387
- }
388
-
389
351
  const ensureReadFileImport = (ast: t.File) => {
390
352
  for (const statement of ast.program.body) {
391
353
  if (!t.isImportDeclaration(statement) || statement.source.value !== 'node:fs/promises') {
@@ -11,9 +11,11 @@ import { z } from 'zod'
11
11
 
12
12
  import { verifyProject } from './_verify'
13
13
  import {
14
+ ensureBricksCtorImport,
14
15
  getObjectProperty,
15
16
  getPropertyKeyName,
16
17
  getStringProperty,
18
+ insertImport,
17
19
  isRecord,
18
20
  makeObjectKey,
19
21
  oxfmtOptions,
@@ -576,13 +578,6 @@ const getTopLevelNames = (ast: t.File) => {
576
578
  return names
577
579
  }
578
580
 
579
- const insertImport = (ast: t.File, declaration: t.ImportDeclaration) => {
580
- const lastImportIndex = ast.program.body.findLastIndex((statement) =>
581
- t.isImportDeclaration(statement),
582
- )
583
- ast.program.body.splice(lastImportIndex + 1, 0, declaration)
584
- }
585
-
586
581
  const ensureNamespaceImport = (
587
582
  parsed: ParsedFile,
588
583
  namespace: string,
@@ -611,40 +606,6 @@ const ensureNamespaceImport = (
611
606
  return localName
612
607
  }
613
608
 
614
- const ensureBricksCtorImport = (
615
- ast: t.File,
616
- importKind: 'type' | 'value',
617
- names: Iterable<string>,
618
- ) => {
619
- const missing = new Set(Array.from(names).filter(Boolean))
620
- if (missing.size === 0) return
621
-
622
- for (const statement of ast.program.body) {
623
- if (!t.isImportDeclaration(statement) || statement.source.value !== 'bricks-ctor') continue
624
- const isTypeImport = statement.importKind === 'type'
625
- if ((importKind === 'type') !== isTypeImport) continue
626
-
627
- statement.specifiers.forEach((specifier) => {
628
- if (!t.isImportSpecifier(specifier)) return
629
- const imported = specifier.imported
630
- if (t.isIdentifier(imported)) missing.delete(imported.name)
631
- if (t.isStringLiteral(imported)) missing.delete(imported.value)
632
- })
633
-
634
- missing.forEach((name) => {
635
- statement.specifiers.push(t.importSpecifier(t.identifier(name), t.identifier(name)))
636
- })
637
- return
638
- }
639
-
640
- const declaration = t.importDeclaration(
641
- Array.from(missing).map((name) => t.importSpecifier(t.identifier(name), t.identifier(name))),
642
- t.stringLiteral('bricks-ctor'),
643
- )
644
- if (importKind === 'type') declaration.importKind = 'type'
645
- insertImport(ast, declaration)
646
- }
647
-
648
609
  const applyPendingImports = (ctx: EditContext) => {
649
610
  ensureBricksCtorImport(ctx.parsed.ast, 'type', ctx.typeImports)
650
611
  ensureBricksCtorImport(ctx.parsed.ast, 'value', ctx.valueImports)
@@ -269,6 +269,7 @@ Default property:
269
269
  y?: number | DataLink
270
270
  width?: number | DataLink
271
271
  height?: number | DataLink
272
+ type?: string | DataLink
272
273
  standbyMode?: 'custom' | 'top' | 'bottom' | 'left' | 'right' | DataLink
273
274
  standbyFrame?: DataLink | {}
274
275
  standbyOpacity?: number | DataLink
@@ -319,6 +320,7 @@ Default property:
319
320
  }
320
321
  show?: string | DataLink
321
322
  pressToOpenDetail?: boolean | DataLink
323
+ pressToBackList?: boolean | DataLink
322
324
  }
323
325
  >
324
326
  | DataLink
@@ -346,6 +348,7 @@ Default property:
346
348
  y?: number | DataLink
347
349
  width?: number | DataLink
348
350
  height?: number | DataLink
351
+ type?: string | DataLink
349
352
  standbyMode?: 'custom' | 'top' | 'bottom' | 'left' | 'right' | DataLink
350
353
  standbyFrame?: DataLink | {}
351
354
  standbyOpacity?: number | DataLink
@@ -395,6 +398,7 @@ Default property:
395
398
  renderOutOfViewport?: boolean | DataLink
396
399
  }
397
400
  show?: string | DataLink
401
+ pressToOpenDetail?: boolean | DataLink
398
402
  pressToBackList?: boolean | DataLink
399
403
  }
400
404
  >