@fugood/bricks-ctor 2.25.0-beta.60 → 2.25.0-beta.61

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 (190) hide show
  1. package/package.json +4 -28
  2. package/tools/deploy.ts +19 -176
  3. package/tools/mcp-server.ts +16 -33
  4. package/tools/postinstall.ts +21 -292
  5. package/tools/pull.ts +15 -195
  6. package/tools/push-config.ts +18 -113
  7. package/tools/simulator.ts +19 -148
  8. package/compile/__tests__/config-diff.test.js +0 -100
  9. package/compile/__tests__/index.test.js +0 -461
  10. package/compile/__tests__/util.test.js +0 -450
  11. package/compile/action-name-map.ts +0 -1079
  12. package/compile/config-diff.ts +0 -155
  13. package/compile/index.ts +0 -1594
  14. package/compile/util.ts +0 -482
  15. package/index.ts +0 -6
  16. package/skills/bricks-ctor/SKILL.md +0 -38
  17. package/skills/bricks-ctor/references/animation.md +0 -160
  18. package/skills/bricks-ctor/references/architecture-patterns.md +0 -88
  19. package/skills/bricks-ctor/references/automations.md +0 -232
  20. package/skills/bricks-ctor/references/buttress.md +0 -245
  21. package/skills/bricks-ctor/references/data-calculation.md +0 -252
  22. package/skills/bricks-ctor/references/local-sync.md +0 -129
  23. package/skills/bricks-ctor/references/media-flow.md +0 -165
  24. package/skills/bricks-ctor/references/remote-data-bank.md +0 -196
  25. package/skills/bricks-ctor/references/simulator.md +0 -132
  26. package/skills/bricks-ctor/references/source-editing-tools.md +0 -81
  27. package/skills/bricks-ctor/references/standby-transition.md +0 -124
  28. package/skills/bricks-ctor/references/verification-toolchain.md +0 -200
  29. package/skills/bricks-design/SKILL.md +0 -171
  30. package/skills/bricks-design/references/architecture-truths.md +0 -132
  31. package/skills/bricks-design/references/avoiding-complexity.md +0 -91
  32. package/skills/bricks-design/references/design-critique.md +0 -195
  33. package/skills/bricks-design/references/design-languages.md +0 -265
  34. package/skills/bricks-design/references/performance.md +0 -116
  35. package/skills/bricks-design/references/presentation-and-slideshow.md +0 -137
  36. package/skills/bricks-design/references/translating-inputs.md +0 -152
  37. package/skills/bricks-design/references/variations-and-tweaks.md +0 -124
  38. package/skills/bricks-design/references/when-the-brief-is-branded.md +0 -284
  39. package/skills/bricks-design/references/when-the-brief-is-vague.md +0 -85
  40. package/skills/bricks-design/references/workflow.md +0 -134
  41. package/skills/bricks-ux/SKILL.md +0 -114
  42. package/skills/bricks-ux/references/accessibility.md +0 -162
  43. package/skills/bricks-ux/references/flow-states.md +0 -175
  44. package/skills/bricks-ux/references/interaction-archetypes.md +0 -189
  45. package/skills/bricks-ux/references/monitoring-screens.md +0 -153
  46. package/skills/bricks-ux/references/pressable-composition.md +0 -126
  47. package/skills/bricks-ux/references/user-journey.md +0 -168
  48. package/skills/bricks-ux/references/ux-critique.md +0 -256
  49. package/skills/rive-marketplace/SKILL.md +0 -99
  50. package/tools/__tests__/_cli-error.test.ts +0 -35
  51. package/tools/__tests__/_mcp-config.test.ts +0 -67
  52. package/tools/__tests__/pull.test.ts +0 -108
  53. package/tools/_cli-error.ts +0 -17
  54. package/tools/_edits-log.ts +0 -41
  55. package/tools/_git-author.ts +0 -37
  56. package/tools/_last-pushed-commit.ts +0 -28
  57. package/tools/_mcp-config.ts +0 -42
  58. package/tools/_shell.ts +0 -180
  59. package/tools/icons/.gitattributes +0 -1
  60. package/tools/icons/fa6pro-glyphmap.json +0 -4686
  61. package/tools/icons/fa6pro-meta.json +0 -1
  62. package/tools/mcp-env.ts +0 -13
  63. package/tools/mcp-tools/__tests__/data-calc-editing.test.js +0 -516
  64. package/tools/mcp-tools/__tests__/entry-editing.test.js +0 -866
  65. package/tools/mcp-tools/__tests__/huggingface.test.ts +0 -49
  66. package/tools/mcp-tools/__tests__/icons.test.ts +0 -21
  67. package/tools/mcp-tools/__tests__/mcp-env.test.js +0 -19
  68. package/tools/mcp-tools/_editing-helpers.ts +0 -98
  69. package/tools/mcp-tools/_verify.ts +0 -50
  70. package/tools/mcp-tools/compile.ts +0 -104
  71. package/tools/mcp-tools/data-calc-editing.ts +0 -1311
  72. package/tools/mcp-tools/entry-editing.ts +0 -2297
  73. package/tools/mcp-tools/huggingface.ts +0 -772
  74. package/tools/mcp-tools/icons.ts +0 -97
  75. package/tools/mcp-tools/lottie.ts +0 -102
  76. package/tools/mcp-tools/media.ts +0 -113
  77. package/tools/simulator-main.mjs +0 -488
  78. package/tools/simulator-preload.cjs +0 -16
  79. package/types/animation.d.ts +0 -116
  80. package/types/automation.d.ts +0 -231
  81. package/types/brick-base.d.ts +0 -80
  82. package/types/bricks/Camera.d.ts +0 -246
  83. package/types/bricks/Chart.d.ts +0 -372
  84. package/types/bricks/GenerativeMedia.d.ts +0 -290
  85. package/types/bricks/Icon.d.ts +0 -98
  86. package/types/bricks/Image.d.ts +0 -126
  87. package/types/bricks/Items.d.ts +0 -480
  88. package/types/bricks/Lottie.d.ts +0 -168
  89. package/types/bricks/Maps.d.ts +0 -262
  90. package/types/bricks/QrCode.d.ts +0 -117
  91. package/types/bricks/Rect.d.ts +0 -150
  92. package/types/bricks/RichText.d.ts +0 -131
  93. package/types/bricks/Rive.d.ts +0 -220
  94. package/types/bricks/Scene3D.d.ts +0 -676
  95. package/types/bricks/Sketch.d.ts +0 -256
  96. package/types/bricks/Slideshow.d.ts +0 -201
  97. package/types/bricks/Svg.d.ts +0 -99
  98. package/types/bricks/Text.d.ts +0 -148
  99. package/types/bricks/TextInput.d.ts +0 -242
  100. package/types/bricks/Video.d.ts +0 -242
  101. package/types/bricks/VideoStreaming.d.ts +0 -112
  102. package/types/bricks/WebRtcStream.d.ts +0 -65
  103. package/types/bricks/WebView.d.ts +0 -168
  104. package/types/bricks/index.d.ts +0 -23
  105. package/types/canvas.d.ts +0 -82
  106. package/types/common.d.ts +0 -141
  107. package/types/data-calc-command/base.d.ts +0 -57
  108. package/types/data-calc-command/collection.d.ts +0 -418
  109. package/types/data-calc-command/color.d.ts +0 -432
  110. package/types/data-calc-command/constant.d.ts +0 -50
  111. package/types/data-calc-command/datetime.d.ts +0 -147
  112. package/types/data-calc-command/file.d.ts +0 -129
  113. package/types/data-calc-command/index.d.ts +0 -13
  114. package/types/data-calc-command/iteratee.d.ts +0 -23
  115. package/types/data-calc-command/logictype.d.ts +0 -190
  116. package/types/data-calc-command/math.d.ts +0 -275
  117. package/types/data-calc-command/object.d.ts +0 -119
  118. package/types/data-calc-command/sandbox.d.ts +0 -66
  119. package/types/data-calc-command/string.d.ts +0 -407
  120. package/types/data-calc-script.d.ts +0 -21
  121. package/types/data-calc.d.ts +0 -12
  122. package/types/data.d.ts +0 -97
  123. package/types/generators/AlarmClock.d.ts +0 -110
  124. package/types/generators/Assistant.d.ts +0 -640
  125. package/types/generators/BleCentral.d.ts +0 -247
  126. package/types/generators/BlePeripheral.d.ts +0 -208
  127. package/types/generators/CanvasMap.d.ts +0 -74
  128. package/types/generators/CastlesPay.d.ts +0 -87
  129. package/types/generators/DataBank.d.ts +0 -160
  130. package/types/generators/File.d.ts +0 -432
  131. package/types/generators/GraphQl.d.ts +0 -132
  132. package/types/generators/Http.d.ts +0 -222
  133. package/types/generators/HttpServer.d.ts +0 -230
  134. package/types/generators/Information.d.ts +0 -103
  135. package/types/generators/Intent.d.ts +0 -168
  136. package/types/generators/Iterator.d.ts +0 -108
  137. package/types/generators/Keyboard.d.ts +0 -105
  138. package/types/generators/LlmAnthropicCompat.d.ts +0 -212
  139. package/types/generators/LlmAppleBuiltin.d.ts +0 -159
  140. package/types/generators/LlmGgml.d.ts +0 -903
  141. package/types/generators/LlmMediaTekNeuroPilot.d.ts +0 -235
  142. package/types/generators/LlmMlx.d.ts +0 -228
  143. package/types/generators/LlmOnnx.d.ts +0 -213
  144. package/types/generators/LlmOpenAiCompat.d.ts +0 -312
  145. package/types/generators/LlmQualcommAiEngine.d.ts +0 -247
  146. package/types/generators/Mcp.d.ts +0 -637
  147. package/types/generators/McpServer.d.ts +0 -289
  148. package/types/generators/MediaFlow.d.ts +0 -170
  149. package/types/generators/MqttBroker.d.ts +0 -141
  150. package/types/generators/MqttClient.d.ts +0 -141
  151. package/types/generators/Question.d.ts +0 -408
  152. package/types/generators/RealtimeTranscription.d.ts +0 -287
  153. package/types/generators/RerankerGgml.d.ts +0 -195
  154. package/types/generators/SerialPort.d.ts +0 -151
  155. package/types/generators/SoundPlayer.d.ts +0 -94
  156. package/types/generators/SoundRecorder.d.ts +0 -139
  157. package/types/generators/SpeechToTextGgml.d.ts +0 -424
  158. package/types/generators/SpeechToTextOnnx.d.ts +0 -236
  159. package/types/generators/SpeechToTextPlatform.d.ts +0 -85
  160. package/types/generators/SqLite.d.ts +0 -159
  161. package/types/generators/Step.d.ts +0 -107
  162. package/types/generators/SttAppleBuiltin.d.ts +0 -153
  163. package/types/generators/Tcp.d.ts +0 -126
  164. package/types/generators/TcpServer.d.ts +0 -147
  165. package/types/generators/TextToSpeechAppleBuiltin.d.ts +0 -127
  166. package/types/generators/TextToSpeechGgml.d.ts +0 -221
  167. package/types/generators/TextToSpeechOnnx.d.ts +0 -178
  168. package/types/generators/TextToSpeechOpenAiLike.d.ts +0 -121
  169. package/types/generators/ThermalPrinter.d.ts +0 -193
  170. package/types/generators/Tick.d.ts +0 -83
  171. package/types/generators/Udp.d.ts +0 -120
  172. package/types/generators/VadGgml.d.ts +0 -260
  173. package/types/generators/VadOnnx.d.ts +0 -231
  174. package/types/generators/VadTraditional.d.ts +0 -138
  175. package/types/generators/VectorStore.d.ts +0 -257
  176. package/types/generators/Watchdog.d.ts +0 -107
  177. package/types/generators/WebCrawler.d.ts +0 -103
  178. package/types/generators/WebRtc.d.ts +0 -181
  179. package/types/generators/WebSocket.d.ts +0 -148
  180. package/types/generators/index.d.ts +0 -57
  181. package/types/index.d.ts +0 -13
  182. package/types/subspace.d.ts +0 -60
  183. package/types/switch.d.ts +0 -51
  184. package/types/system.d.ts +0 -707
  185. package/utils/__tests__/calc.test.js +0 -25
  186. package/utils/__tests__/id.test.js +0 -154
  187. package/utils/calc.ts +0 -130
  188. package/utils/data.ts +0 -495
  189. package/utils/event-props.ts +0 -912
  190. package/utils/id.ts +0 -133
package/package.json CHANGED
@@ -1,33 +1,9 @@
1
1
  {
2
2
  "name": "@fugood/bricks-ctor",
3
- "version": "2.25.0-beta.60",
4
- "main": "index.ts",
5
- "scripts": {
6
- "typecheck": "tsc --noEmit",
7
- "build": "bun scripts/build.js"
8
- },
3
+ "version": "2.25.0-beta.61",
4
+ "description": "Deprecated: ctor tooling moved to the `bricks ctor` commands in @fugood/bricks-cli. This package now only forwards legacy project scripts and triggers migration.",
9
5
  "dependencies": {
10
- "@babel/generator": "7.28.5",
11
- "@babel/parser": "7.28.5",
12
- "@babel/traverse": "7.28.5",
13
- "@babel/types": "7.28.5",
14
- "@fugood/bricks-cli": "^2.25.0-beta.60",
15
- "@huggingface/gguf": "^0.3.2",
16
- "@iarna/toml": "^3.0.0",
17
- "@modelcontextprotocol/sdk": "^1.15.0",
18
- "@toon-format/toon": "^2.1.0",
19
- "@types/bun": "^1.3.9",
20
- "@types/escodegen": "^0.0.10",
21
- "@types/lodash": "^4.17.12",
22
- "acorn": "^8.13.0",
23
- "escodegen": "2.1.0",
24
- "fuse.js": "^7.0.0",
25
- "json5": "^2.0.1",
26
- "lodash": "^4.17.4",
27
- "uuid": "^8.3.1"
28
- },
29
- "peerDependencies": {
30
- "oxfmt": "^0.36.0"
6
+ "@fugood/bricks-cli": "^2.25.0-beta.61"
31
7
  },
32
- "gitHead": "c0dd2ea071f45382808ad55acfc9837217d683ca"
8
+ "gitHead": "342701683311c7e0dc295bac19a2f9a9517d3160"
33
9
  }
package/tools/deploy.ts CHANGED
@@ -1,176 +1,19 @@
1
- import { access, readFile, writeFile } from 'node:fs/promises'
2
- import { parseArgs } from 'util'
3
- import { sh } from './_shell'
4
- import { extractCliErrorMessage } from './_cli-error'
5
- import { buildCommitArgs } from './_git-author'
6
- import { writeLastPushedCommit } from './_last-pushed-commit'
7
-
8
- if (!process.env.BRICKS_RELEASE_SIGN) {
9
- process.env.BRICKS_RELEASE_SIGN = 'CTOR'
10
- }
11
-
12
- const cwd = process.cwd()
13
-
14
- const exists = async (p: string) => {
15
- try {
16
- await access(p)
17
- return true
18
- } catch {
19
- return false
20
- }
21
- }
22
-
23
- const readJson = async (p: string) => JSON.parse(await readFile(p, 'utf8'))
24
-
25
- const {
26
- values: {
27
- changelogs: changelogsArg,
28
- 'changelogs-file': changelogsFile,
29
- 'auto-commit': autoCommit,
30
- 'auto-version': autoVersion,
31
- version: versionArg,
32
- yes,
33
- help,
34
- },
35
- } = parseArgs({
36
- args: process.argv.slice(2),
37
- options: {
38
- changelogs: { type: 'string' },
39
- 'changelogs-file': { type: 'string' },
40
- 'auto-commit': { type: 'boolean' },
41
- 'auto-version': { type: 'boolean' },
42
- version: { type: 'string' },
43
- yes: { type: 'boolean', short: 'y' },
44
- help: { type: 'boolean', short: 'h' },
45
- },
46
- allowPositionals: true,
47
- })
48
-
49
- if (help) {
50
- console.log(`Options:
51
- --changelogs <text> Changelogs text for the release
52
- --changelogs-file <path> Read changelogs from a file
53
- --auto-commit Auto-commit unstaged changes before deploying
54
- --auto-version Auto-bump patch version before deploying
55
- --version <version> Set explicit version for the release
56
- -y, --yes Skip all prompts
57
- -h, --help Show this help message`)
58
- process.exit(0)
59
- }
60
-
61
- // Check git status
62
- const { exitCode } = await sh`cd ${cwd} && git status`.quiet().nothrow()
63
- const isGitRepo = exitCode === 0
64
-
65
- if (!isGitRepo && !yes) {
66
- const confirmContinue = prompt('No git repository found, continue? (y/n)')
67
- if (confirmContinue !== 'y') throw new Error('Deployment cancelled')
68
- }
69
-
70
- // Read application.json
71
- const app = await readJson(`${cwd}/application.json`)
72
- const config = await readJson(`${cwd}/.bricks/build/application-config.json`)
73
-
74
- // Resolve version: explicit flag > auto-bump > package.json
75
- const pkgPath = `${cwd}/package.json`
76
- const pkgExists = await exists(pkgPath)
77
- let version: string | undefined
78
-
79
- if (versionArg) {
80
- version = versionArg
81
- if (pkgExists) {
82
- const pkg = await readJson(pkgPath)
83
- pkg.version = version
84
- await writeFile(pkgPath, JSON.stringify(pkg, null, 2) + '\n')
85
- }
86
- } else if (autoVersion && pkgExists) {
87
- const pkg = await readJson(pkgPath)
88
- const parts = (pkg.version || '0.0.0').split('.')
89
- parts[2] = String(Number(parts[2] || 0) + 1)
90
- version = parts.join('.')
91
- pkg.version = version
92
- await writeFile(pkgPath, JSON.stringify(pkg, null, 2) + '\n')
93
- } else {
94
- version = pkgExists ? (await readJson(pkgPath)).version : undefined
95
- }
96
-
97
- // Get changelog from flag or file
98
- let changelogs = ''
99
- if (changelogsArg) {
100
- changelogs = changelogsArg
101
- } else if (changelogsFile) {
102
- if (!(await exists(changelogsFile))) {
103
- throw new Error(`Changelogs file not found: ${changelogsFile}`)
104
- }
105
- changelogs = await readFile(changelogsFile, 'utf8')
106
- } else if (!yes) {
107
- changelogs = prompt('Enter changelogs (optional, press Enter to skip):') || ''
108
- }
109
-
110
- // Handle unstaged changes
111
- let commitId = ''
112
- if (isGitRepo) {
113
- const unstagedChanges = await sh`cd ${cwd} && git diff --name-only --diff-filter=ACMR`.text()
114
- if (unstagedChanges) {
115
- if (autoCommit) {
116
- const commitMsg = `chore: release ${version || 'new version'}`
117
- const commitBody = changelogs || '[no changelogs]'
118
- await sh`cd ${cwd} && git add -A`
119
- const commitArgs = await buildCommitArgs(cwd, [commitMsg, commitBody])
120
- await sh`cd ${cwd} && git ${commitArgs}`
121
- } else {
122
- throw new Error(
123
- 'Unstaged changes found, please commit or stash your changes before deploying',
124
- )
125
- }
126
- }
127
- commitId = (await sh`cd ${cwd} && git rev-parse HEAD`.text()).trim()
128
- }
129
-
130
- // Ask for confirmation
131
- if (!yes) {
132
- const confirm = prompt('Are you sure you want to deploy? (y/n)')
133
- if (confirm !== 'y') throw new Error('Deployment cancelled')
134
- }
135
-
136
- const isModule = app.type === 'module'
137
- const command = isModule ? 'module' : 'app'
138
-
139
- // Add project-specific fields to config and write to temp file
140
- const releaseConfig = {
141
- ...config,
142
- title: version || config.title,
143
- bricks_project_last_commit_id: commitId || undefined,
144
- }
145
- const configPath = `${cwd}/.bricks/build/release-config.json`
146
- await writeFile(configPath, JSON.stringify(releaseConfig))
147
-
148
- const args = ['bricks', command, 'release', app.id, '-c', configPath, '--json']
149
-
150
- if (app.name) {
151
- args.push('--name', app.name)
152
- }
153
-
154
- if (version) {
155
- args.push('--version', version)
156
- }
157
-
158
- if (changelogs) {
159
- args.push('--changelogs', changelogs)
160
- }
161
-
162
- const result = await sh`${args}`.quiet().nothrow()
163
-
164
- if (result.exitCode !== 0) {
165
- const output = result.stderr.toString() || result.stdout.toString()
166
- throw new Error(extractCliErrorMessage(output, 'Release failed'))
167
- }
168
-
169
- const output = JSON.parse(result.stdout.toString())
170
-
171
- // Record the commit we just pushed from so a later pull can use it as the
172
- // merge base regardless of what the server stores in
173
- // bricks_project_last_commit_id.
174
- if (commitId) await writeLastPushedCommit(cwd, commitId)
175
-
176
- console.log(`${isModule ? 'Module' : 'App'} deployed: ${output.name}`)
1
+ #!/usr/bin/env bun
2
+ // @fugood/bricks-ctor is deprecated all tooling now lives in the `bricks ctor *` commands
3
+ // (the @fugood/bricks-cli package). This thin forwarder keeps legacy project scripts working
4
+ // and lets `bricks ctor postinstall` migrate the project onto the new commands.
5
+ import { spawnSync } from 'node:child_process'
6
+ import { existsSync } from 'node:fs'
7
+ import { fileURLToPath } from 'node:url'
8
+
9
+ // Prefer the CLI installed next to this shim (@fugood/bricks-cli is our only dependency)
10
+ // over a PATH lookup, so the forwarder works without a global install.
11
+ const localBricks = fileURLToPath(new URL('../../../.bin/bricks', import.meta.url))
12
+ const bricks = existsSync(localBricks) ? localBricks : 'bricks'
13
+
14
+ const result = spawnSync(bricks, ['ctor', 'deploy', ...process.argv.slice(2)], { stdio: 'inherit' })
15
+ if (result.error) {
16
+ console.error(`bricks-ctor forwarder failed to run \`${bricks}\`: ${result.error.message}`)
17
+ process.exit(1)
18
+ }
19
+ process.exit(result.status ?? 1)
@@ -1,36 +1,19 @@
1
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
2
- import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
1
+ #!/usr/bin/env bun
2
+ // @fugood/bricks-ctor is deprecated all tooling now lives in the `bricks ctor *` commands
3
+ // (the @fugood/bricks-cli package). This thin forwarder keeps legacy project scripts working
4
+ // and lets `bricks ctor postinstall` migrate the project onto the new commands.
5
+ import { spawnSync } from 'node:child_process'
6
+ import { existsSync } from 'node:fs'
7
+ import { fileURLToPath } from 'node:url'
3
8
 
4
- import { register as registerCompile } from './mcp-tools/compile'
5
- import { register as registerLottie } from './mcp-tools/lottie'
6
- import { register as registerIcons } from './mcp-tools/icons'
7
- import { register as registerHuggingface } from './mcp-tools/huggingface'
8
- import { register as registerMedia } from './mcp-tools/media'
9
- import { register as registerEntryEditing } from './mcp-tools/entry-editing'
10
- import { register as registerDataCalcEditing } from './mcp-tools/data-calc-editing'
11
- import { shouldRegisterEditingTools } from './mcp-env'
9
+ // Prefer the CLI installed next to this shim (@fugood/bricks-cli is our only dependency)
10
+ // over a PATH lookup, so the forwarder works without a global install.
11
+ const localBricks = fileURLToPath(new URL('../../../.bin/bricks', import.meta.url))
12
+ const bricks = existsSync(localBricks) ? localBricks : 'bricks'
12
13
 
13
- const server = new McpServer({
14
- name: 'bricks-ctor',
15
- version: '1.0.0',
16
- })
17
-
18
- const { dirname } = import.meta
19
- const projectDir = String(dirname).split('/node_modules/')[0]
20
-
21
- // NOTE: Cursor (Or VSCode) seems set ELECTRON_RUN_AS_NODE to 1, so we need to unset it
22
- process.env.ELECTRON_RUN_AS_NODE = ''
23
-
24
- registerCompile(server, projectDir)
25
- registerLottie(server)
26
- registerIcons(server)
27
- registerHuggingface(server)
28
- registerMedia(server, projectDir)
29
-
30
- if (shouldRegisterEditingTools()) {
31
- registerEntryEditing(server, projectDir)
32
- registerDataCalcEditing(server, projectDir)
14
+ const result = spawnSync(bricks, ['ctor', 'mcp', ...process.argv.slice(2)], { stdio: 'inherit' })
15
+ if (result.error) {
16
+ console.error(`bricks-ctor forwarder failed to run \`${bricks}\`: ${result.error.message}`)
17
+ process.exit(1)
33
18
  }
34
-
35
- const transport = new StdioServerTransport()
36
- await server.connect(transport)
19
+ process.exit(result.status ?? 1)
@@ -1,292 +1,21 @@
1
- import {
2
- cp,
3
- lstat,
4
- mkdir,
5
- readFile,
6
- readdir,
7
- readlink,
8
- rm,
9
- stat,
10
- symlink,
11
- writeFile,
12
- } from 'fs/promises'
13
- import * as path from 'path'
14
- import TOML from '@iarna/toml'
15
- import { handleMcpConfigOverride } from './_mcp-config'
16
-
17
- const cwd = process.cwd()
18
- const projectSkillsDir = path.join(cwd, '.bricks', 'skills')
19
- const compatibilitySkillLinks = [
20
- path.join(cwd, '.claude', 'skills'),
21
- path.join(cwd, '.codex', 'skills'),
22
- ]
23
-
24
- async function exists(f: string) {
25
- try {
26
- await stat(f)
27
- return true
28
- } catch {
29
- return false
30
- }
31
- }
32
-
33
- async function pathExists(f: string) {
34
- try {
35
- await lstat(f)
36
- return true
37
- } catch {
38
- return false
39
- }
40
- }
41
-
42
- // Migrate old projects: remove legacy project/ directory
43
- const oldProjectDir = path.join(cwd, 'project')
44
- if (await exists(oldProjectDir)) {
45
- await rm(oldProjectDir, { recursive: true, force: true })
46
- console.log('Removed legacy project/ directory')
47
- }
48
-
49
- // handle flag --skip-copy
50
- const skipCopyProject = process.argv.includes('--skip-copy-project')
51
- if (skipCopyProject) {
52
- console.log('Skipping copy of files to ctor/')
53
- } else {
54
- const libFiles = ['types', 'utils', 'index.ts']
55
-
56
- const ctorDir = path.join(cwd, 'ctor')
57
- await mkdir(ctorDir, { recursive: true })
58
- await Promise.all(
59
- libFiles.map((file) =>
60
- cp(path.join(import.meta.dirname, '..', file), path.join(ctorDir, file), {
61
- recursive: true,
62
- }),
63
- ),
64
- )
65
- console.log('Copied files to ctor/')
66
- }
67
-
68
- const projectMcpServer = {
69
- command: 'bun',
70
- args: [`${cwd}/node_modules/@fugood/bricks-ctor/tools/mcp-server.ts`],
71
- }
72
-
73
- // Codex cancels MCP tool calls it cannot prompt approval for (e.g. `codex exec`),
74
- // so the project-local server's tools must be pre-approved in its config entry.
75
- const codexProjectMcpServer = {
76
- ...projectMcpServer,
77
- default_tools_approval_mode: 'approve',
78
- }
79
-
80
- type CodexMcpConfig = {
81
- mcp_servers: Record<string, typeof codexProjectMcpServer | typeof projectMcpServer>
82
- }
83
-
84
- const hasClaudeCode = await exists(`${cwd}/CLAUDE.md`)
85
- const hasAgentsMd = await exists(`${cwd}/AGENTS.md`)
86
-
87
- if (hasClaudeCode || hasAgentsMd) {
88
- // Keep the workspace-level JSON MCP config aligned for tools that read .mcp.json.
89
- const mcpConfigPath = `${cwd}/.mcp.json`
90
- await handleMcpConfigOverride(mcpConfigPath, projectMcpServer)
91
- }
92
-
93
- const copyMissingSkills = async (sourceDir: string, targetDir: string) => {
94
- if (!(await exists(sourceDir))) return
95
-
96
- const packageSkills = await readdir(sourceDir, { withFileTypes: true })
97
- const skillsToInstall = packageSkills.filter(
98
- (entry) => entry.isDirectory() && !entry.name.startsWith('.'),
99
- )
100
-
101
- await mkdir(targetDir, { recursive: true })
102
-
103
- await Promise.all(
104
- skillsToInstall.map(async (entry) => {
105
- const targetSkillDir = path.join(targetDir, entry.name)
106
- if (await exists(targetSkillDir)) {
107
- console.log(`Skill '${entry.name}' already exists, skipping`)
108
- } else {
109
- await cp(path.join(sourceDir, entry.name), targetSkillDir, { recursive: true })
110
- console.log(`Installed skill '${entry.name}' to ${targetDir}/`)
111
- }
112
- }),
113
- )
114
- }
115
-
116
- const migrateSkillsDir = async (legacySkillsDir: string, canonicalSkillsDir: string) => {
117
- if (!(await pathExists(legacySkillsDir))) return
118
-
119
- const legacyStats = await lstat(legacySkillsDir)
120
-
121
- if (legacyStats.isSymbolicLink()) {
122
- const linkTarget = await readlink(legacySkillsDir)
123
- const resolvedTarget = path.resolve(path.dirname(legacySkillsDir), linkTarget)
124
- if (resolvedTarget === canonicalSkillsDir) return
125
-
126
- await copyMissingSkills(resolvedTarget, canonicalSkillsDir)
127
- await rm(legacySkillsDir, { force: true, recursive: true })
128
- return
129
- }
130
-
131
- if (legacyStats.isDirectory()) {
132
- await copyMissingSkills(legacySkillsDir, canonicalSkillsDir)
133
- await rm(legacySkillsDir, { force: true, recursive: true })
134
- return
135
- }
136
-
137
- console.warn(`Skipping skills migration for ${legacySkillsDir}; expected a directory or symlink`)
138
- }
139
-
140
- const ensureCompatibilitySkillLink = async (linkPath: string, targetDir: string) => {
141
- await mkdir(path.dirname(linkPath), { recursive: true })
142
-
143
- if (await pathExists(linkPath)) {
144
- const linkStats = await lstat(linkPath)
145
- if (linkStats.isSymbolicLink()) {
146
- const linkTarget = await readlink(linkPath)
147
- const resolvedTarget = path.resolve(path.dirname(linkPath), linkTarget)
148
- if (resolvedTarget === targetDir) return
149
- } else {
150
- console.warn(
151
- `Skipping skills symlink at ${linkPath}; path already exists and is not a symlink`,
152
- )
153
- return
154
- }
155
- }
156
-
157
- const relativeTarget = path.relative(path.dirname(linkPath), targetDir)
158
- const symlinkType = process.platform === 'win32' ? 'junction' : 'dir'
159
- await symlink(relativeTarget, linkPath, symlinkType)
160
- console.log(`Linked ${linkPath} -> ${relativeTarget}`)
161
- }
162
-
163
- const setupSkills = async () => {
164
- const packageSkillsDir = path.join(import.meta.dirname, '..', 'skills')
165
- await mkdir(projectSkillsDir, { recursive: true })
166
- await copyMissingSkills(packageSkillsDir, projectSkillsDir)
167
-
168
- for (const linkPath of compatibilitySkillLinks) {
169
- await migrateSkillsDir(linkPath, projectSkillsDir)
170
- await ensureCompatibilitySkillLink(linkPath, projectSkillsDir)
171
- }
172
- }
173
-
174
- if (hasClaudeCode || hasAgentsMd) {
175
- // Install project skills once and expose them through compatibility symlinks.
176
- await setupSkills()
177
- }
178
-
179
- type ClaudeSettings = {
180
- autoMode?: {
181
- environment?: string[]
182
- allow?: string[]
183
- soft_deny?: string[]
184
- hard_deny?: string[]
185
- }
186
- [key: string]: unknown
187
- }
188
-
189
- // Trusted infrastructure for auto mode's classifier. `$defaults` keeps the
190
- // built-in environment (the working repo and its git remotes); the extra
191
- // entries stop routine syncs to the BRICKS backend from being treated as
192
- // external exfiltration. See https://code.claude.com/docs/en/auto-mode-config
193
- const autoModeEnvironment = [
194
- '$defaults',
195
- 'Organization: BRICKS (bricks.tools). Primary use: building BRICKS apps/modules with the bricks CLI and the local bricks-ctor MCP server.',
196
- 'Trusted internal domains: all *.bricks.tools services — api.bricks.tools (project GraphQL API), bank.bricks.tools (config & asset Bank API), cdn.bricks.tools (asset CDN), plus the control/display/activity services. This project syncs its config and assets to these endpoints.',
197
- ]
198
-
199
- // `.claude/settings.local.json` is per-developer local config; keep it untracked.
200
- const ensureSettingsLocalGitignored = async () => {
201
- const gitignorePath = path.join(cwd, '.gitignore')
202
- const entry = '.claude/settings.local.json'
203
- const coveredBy = new Set([entry, '.claude', '.claude/', '.claude/*', '*.local.json'])
204
-
205
- let content = ''
206
- if (await exists(gitignorePath)) {
207
- content = await readFile(gitignorePath, 'utf-8')
208
- if (content.split('\n').some((line) => coveredBy.has(line.trim()))) return
209
- }
210
-
211
- const separator = content.length === 0 ? '' : content.endsWith('\n') ? '\n' : '\n\n'
212
- await writeFile(gitignorePath, `${content}${separator}# Claude Code local settings\n${entry}\n`)
213
- console.log(`Added ${entry} to .gitignore`)
214
- }
215
-
216
- // Pre-configure auto mode once, on initial setup. We only seed the classifier's
217
- // trusted infrastructure — not `permissions.defaultMode: 'auto'`, which Claude
218
- // Code ignores from project/local settings (a repo can't grant itself auto mode;
219
- // it only takes effect from ~/.claude/settings.json). An existing autoMode block
220
- // is left untouched so reinstalls never clobber a developer's customizations.
221
- const setupClaudeAutoMode = async () => {
222
- const settingsPath = path.join(cwd, '.claude', 'settings.local.json')
223
-
224
- let settings: ClaudeSettings = {}
225
- if (await exists(settingsPath)) {
226
- try {
227
- settings = JSON.parse(await readFile(settingsPath, 'utf-8'))
228
- } catch {
229
- console.warn(`Skipping auto mode setup; ${settingsPath} is not valid JSON`)
230
- return
231
- }
232
- if (settings.autoMode) return
233
- }
234
-
235
- settings.autoMode = { environment: autoModeEnvironment }
236
-
237
- await mkdir(path.dirname(settingsPath), { recursive: true })
238
- await writeFile(settingsPath, `${JSON.stringify(settings, null, 2)}\n`)
239
- console.log(`Set up auto mode in ${settingsPath}`)
240
-
241
- await ensureSettingsLocalGitignored()
242
- }
243
-
244
- if (hasClaudeCode) {
245
- // Pre-configure auto mode's trusted infrastructure for Claude Code projects.
246
- await setupClaudeAutoMode()
247
- }
248
-
249
- if (hasAgentsMd) {
250
- // Codex stores its project-local MCP config in .codex/config.toml.
251
- const defaultCodexMcpConfig = {
252
- mcp_servers: {
253
- 'bricks-ctor': codexProjectMcpServer,
254
- },
255
- }
256
-
257
- const handleCodexMcpConfigOverride = async (mcpConfigPath: string) => {
258
- let mcpConfig: CodexMcpConfig
259
- if (await exists(mcpConfigPath)) {
260
- let parsed: unknown
261
- try {
262
- parsed = TOML.parse(await readFile(mcpConfigPath, 'utf-8'))
263
- } catch {
264
- // A malformed config is left untouched (with a warning) rather than overwritten with
265
- // the default — clobbering it would silently delete the user's other server entries.
266
- // Mirrors handleMcpConfigOverride's handling of a malformed .mcp.json.
267
- console.warn(`Skipping .codex/config.toml update; ${mcpConfigPath} is not valid TOML`)
268
- return
269
- }
270
- mcpConfig =
271
- parsed && typeof parsed === 'object' ? (parsed as CodexMcpConfig) : { mcp_servers: {} }
272
- if (!mcpConfig.mcp_servers || typeof mcpConfig.mcp_servers !== 'object') {
273
- mcpConfig.mcp_servers = {}
274
- }
275
- mcpConfig.mcp_servers['bricks-ctor'] = codexProjectMcpServer
276
- delete mcpConfig.mcp_servers['bricks-project']
277
- } else {
278
- mcpConfig = defaultCodexMcpConfig
279
- }
280
-
281
- await writeFile(mcpConfigPath, `${TOML.stringify(mcpConfig)}\n`)
282
-
283
- console.log(`Updated ${mcpConfigPath}`)
284
- }
285
-
286
- // Keep the Codex TOML MCP config aligned with the same bricks-ctor server entry.
287
- const codexConfigPath = `${cwd}/.codex/config.toml`
288
- await handleCodexMcpConfigOverride(codexConfigPath)
289
- }
290
-
291
- // TODO: .cursor/skills if needed
292
- // TODO: User setting in application.json to avoid unnecessary skills/config setup
1
+ #!/usr/bin/env bun
2
+ // @fugood/bricks-ctor is deprecated — all tooling now lives in the `bricks ctor *` commands
3
+ // (the @fugood/bricks-cli package). This thin forwarder keeps legacy project scripts working
4
+ // and lets `bricks ctor postinstall` migrate the project onto the new commands.
5
+ import { spawnSync } from 'node:child_process'
6
+ import { existsSync } from 'node:fs'
7
+ import { fileURLToPath } from 'node:url'
8
+
9
+ // Prefer the CLI installed next to this shim (@fugood/bricks-cli is our only dependency)
10
+ // over a PATH lookup, so the forwarder works without a global install.
11
+ const localBricks = fileURLToPath(new URL('../../../.bin/bricks', import.meta.url))
12
+ const bricks = existsSync(localBricks) ? localBricks : 'bricks'
13
+
14
+ const result = spawnSync(bricks, ['ctor', 'postinstall', ...process.argv.slice(2)], {
15
+ stdio: 'inherit',
16
+ })
17
+ if (result.error) {
18
+ console.error(`bricks-ctor forwarder failed to run \`${bricks}\`: ${result.error.message}`)
19
+ process.exit(1)
20
+ }
21
+ process.exit(result.status ?? 1)