@fugood/bricks-project 2.24.0-beta.9 → 2.24.1-beta.0
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/compile/action-name-map.ts +38 -0
- package/compile/index.ts +460 -158
- package/compile/util.ts +2 -0
- package/package.json +8 -3
- package/package.json.bak +28 -0
- package/skills/{bricks-project → bricks-ctor}/SKILL.md +2 -2
- package/skills/{bricks-project → bricks-ctor}/rules/animation.md +1 -1
- package/skills/{bricks-project → bricks-ctor}/rules/architecture-patterns.md +7 -0
- package/skills/{bricks-project → bricks-ctor}/rules/buttress.md +10 -7
- package/skills/{bricks-project → bricks-ctor}/rules/data-calculation.md +3 -2
- package/skills/{bricks-project → bricks-ctor}/rules/local-sync.md +2 -2
- package/skills/{bricks-project → bricks-ctor}/rules/media-flow.md +3 -3
- package/skills/{bricks-project → bricks-ctor}/rules/remote-data-bank.md +6 -6
- package/skills/{bricks-project → bricks-ctor}/rules/standby-transition.md +1 -1
- package/skills/bricks-design/LICENSE.txt +180 -0
- package/skills/bricks-design/SKILL.md +66 -0
- package/tools/_git-author.ts +29 -0
- package/tools/_shell.ts +173 -0
- package/tools/deploy.ts +91 -23
- package/tools/icons/fa6pro-meta.json +3669 -26125
- package/tools/mcp-server.ts +11 -878
- package/tools/mcp-tools/compile.ts +92 -0
- package/tools/mcp-tools/huggingface.ts +762 -0
- package/tools/mcp-tools/icons.ts +70 -0
- package/tools/mcp-tools/lottie.ts +102 -0
- package/tools/mcp-tools/media.ts +110 -0
- package/tools/postinstall.ts +143 -40
- package/tools/preview-main.mjs +135 -2
- package/tools/preview.ts +68 -33
- package/tools/pull.ts +56 -32
- package/tsconfig.json +16 -0
- package/types/animation.ts +4 -0
- package/types/automation.ts +4 -1
- package/types/brick-base.ts +1 -1
- package/types/bricks/Camera.ts +47 -12
- package/types/bricks/Chart.ts +9 -3
- package/types/bricks/GenerativeMedia.ts +29 -13
- package/types/bricks/Icon.ts +8 -4
- package/types/bricks/Image.ts +9 -5
- package/types/bricks/Items.ts +28 -14
- package/types/bricks/Lottie.ts +14 -6
- package/types/bricks/Maps.ts +15 -7
- package/types/bricks/QrCode.ts +8 -4
- package/types/bricks/Rect.ts +44 -5
- package/types/bricks/RichText.ts +8 -4
- package/types/bricks/Rive.ts +20 -10
- package/types/bricks/Slideshow.ts +19 -9
- package/types/bricks/Svg.ts +7 -3
- package/types/bricks/Text.ts +8 -4
- package/types/bricks/TextInput.ts +22 -12
- package/types/bricks/Video.ts +10 -6
- package/types/bricks/VideoStreaming.ts +7 -3
- package/types/bricks/WebRtcStream.ts +6 -2
- package/types/bricks/WebView.ts +11 -7
- package/types/canvas.ts +2 -0
- package/types/common.ts +15 -8
- package/types/data-calc-command.ts +2 -0
- package/types/data-calc.ts +1 -0
- package/types/data.ts +2 -0
- package/types/generators/AlarmClock.ts +16 -10
- package/types/generators/Assistant.ts +68 -17
- package/types/generators/BleCentral.ts +30 -10
- package/types/generators/BlePeripheral.ts +10 -6
- package/types/generators/CanvasMap.ts +9 -5
- package/types/generators/CastlesPay.ts +14 -6
- package/types/generators/DataBank.ts +43 -8
- package/types/generators/File.ts +108 -29
- package/types/generators/GraphQl.ts +11 -5
- package/types/generators/Http.ts +32 -9
- package/types/generators/HttpServer.ts +22 -14
- package/types/generators/Information.ts +8 -4
- package/types/generators/Intent.ts +14 -4
- package/types/generators/Iterator.ts +14 -10
- package/types/generators/Keyboard.ts +26 -12
- package/types/generators/LlmAnthropicCompat.ts +32 -10
- package/types/generators/LlmAppleBuiltin.ts +24 -9
- package/types/generators/LlmGgml.ts +139 -30
- package/types/generators/LlmMediaTekNeuroPilot.ts +235 -0
- package/types/generators/LlmMlx.ts +227 -0
- package/types/generators/LlmOnnx.ts +33 -13
- package/types/generators/LlmOpenAiCompat.ts +46 -10
- package/types/generators/LlmQualcommAiEngine.ts +44 -12
- package/types/generators/Mcp.ts +374 -33
- package/types/generators/McpServer.ts +57 -18
- package/types/generators/MediaFlow.ts +37 -11
- package/types/generators/MqttBroker.ts +28 -10
- package/types/generators/MqttClient.ts +18 -8
- package/types/generators/Question.ts +12 -8
- package/types/generators/RealtimeTranscription.ts +107 -18
- package/types/generators/RerankerGgml.ts +42 -11
- package/types/generators/SerialPort.ts +17 -9
- package/types/generators/SoundPlayer.ts +9 -3
- package/types/generators/SoundRecorder.ts +23 -8
- package/types/generators/SpeechToTextGgml.ts +51 -17
- package/types/generators/SpeechToTextOnnx.ts +17 -10
- package/types/generators/SpeechToTextPlatform.ts +14 -6
- package/types/generators/SqLite.ts +19 -9
- package/types/generators/Step.ts +8 -4
- package/types/generators/SttAppleBuiltin.ts +21 -8
- package/types/generators/Tcp.ts +12 -8
- package/types/generators/TcpServer.ts +19 -13
- package/types/generators/TextToSpeechAppleBuiltin.ts +20 -7
- package/types/generators/TextToSpeechGgml.ts +28 -10
- package/types/generators/TextToSpeechOnnx.ts +18 -11
- package/types/generators/TextToSpeechOpenAiLike.ts +13 -7
- package/types/generators/ThermalPrinter.ts +12 -8
- package/types/generators/Tick.ts +10 -6
- package/types/generators/Udp.ts +16 -7
- package/types/generators/VadGgml.ts +50 -13
- package/types/generators/VadOnnx.ts +41 -11
- package/types/generators/VadTraditional.ts +27 -12
- package/types/generators/VectorStore.ts +32 -11
- package/types/generators/Watchdog.ts +18 -9
- package/types/generators/WebCrawler.ts +10 -6
- package/types/generators/WebRtc.ts +29 -15
- package/types/generators/WebSocket.ts +10 -6
- package/types/generators/index.ts +2 -0
- package/types/subspace.ts +4 -0
- package/types/system.ts +1 -1
- package/utils/event-props.ts +833 -1022
- package/api/index.ts +0 -1
- package/api/instance.ts +0 -213
- package/types/generators/TextToSpeechApple.ts +0 -113
- package/types/generators/TtsAppleBuiltin.ts +0 -105
- /package/skills/{bricks-project → bricks-ctor}/rules/automations.md +0 -0
package/tools/preview-main.mjs
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { app, BrowserWindow } from 'electron'
|
|
3
3
|
import { readFile, writeFile } from 'fs/promises'
|
|
4
4
|
import { watchFile } from 'fs'
|
|
5
|
+
import { createServer } from 'http'
|
|
5
6
|
import { parseArgs } from 'util'
|
|
6
7
|
import * as TOON from '@toon-format/toon'
|
|
7
8
|
|
|
@@ -14,6 +15,7 @@ const { values } = parseArgs({
|
|
|
14
15
|
'test-id': { type: 'string' },
|
|
15
16
|
'test-title-like': { type: 'string' },
|
|
16
17
|
'no-keep-open': { type: 'boolean' },
|
|
18
|
+
'cdp-port': { type: 'string' },
|
|
17
19
|
},
|
|
18
20
|
strict: true,
|
|
19
21
|
allowPositionals: true,
|
|
@@ -70,6 +72,133 @@ const previewUrlMap = {
|
|
|
70
72
|
const previewUrl = previewUrlMap[stage]
|
|
71
73
|
if (!previewUrl) throw new Error(`Invalid BRICKS_STAGE: ${stage}`)
|
|
72
74
|
|
|
75
|
+
// --- CDP WebSocket Server ---
|
|
76
|
+
// Bridges external CDP clients to the preview's postMessage-based CDP bridge.
|
|
77
|
+
// Usage: --cdp-port 9222
|
|
78
|
+
|
|
79
|
+
const startCdpServer = async (mainWindow, port) => {
|
|
80
|
+
const { WebSocketServer } = await import('ws')
|
|
81
|
+
const clients = new Set()
|
|
82
|
+
|
|
83
|
+
// Inject a listener in the preview that forwards CDP responses/events via console
|
|
84
|
+
const injectCdpRelay = () =>
|
|
85
|
+
mainWindow.webContents.executeJavaScript(`
|
|
86
|
+
if (!window.__cdpRelayInstalled) {
|
|
87
|
+
window.__cdpRelayInstalled = true
|
|
88
|
+
window.addEventListener('message', (evt) => {
|
|
89
|
+
try {
|
|
90
|
+
const d = typeof evt.data === 'string' ? JSON.parse(evt.data) : evt.data
|
|
91
|
+
if (d && (d.type === 'cdp-response' || d.type === 'cdp-event'))
|
|
92
|
+
console.log('[CDP]' + JSON.stringify(d))
|
|
93
|
+
} catch {}
|
|
94
|
+
})
|
|
95
|
+
}
|
|
96
|
+
`)
|
|
97
|
+
|
|
98
|
+
// Capture CDP messages from the preview's console output
|
|
99
|
+
mainWindow.webContents.on('console-message', (_event, ...rest) => {
|
|
100
|
+
const message = typeof rest[0] === 'object' ? rest[0].message : rest[1]
|
|
101
|
+
if (!message?.startsWith('[CDP]')) return
|
|
102
|
+
try {
|
|
103
|
+
const data = JSON.parse(message.slice(5))
|
|
104
|
+
// Translate to standard CDP wire format (strip internal type field)
|
|
105
|
+
const wireMsg =
|
|
106
|
+
data.type === 'cdp-response'
|
|
107
|
+
? { id: data.id, result: data.result, error: data.error }
|
|
108
|
+
: { method: data.method, params: data.params }
|
|
109
|
+
if (data.sessionId) wireMsg.sessionId = data.sessionId
|
|
110
|
+
const payload = JSON.stringify(wireMsg)
|
|
111
|
+
for (const c of clients) if (c.readyState === 1) c.send(payload)
|
|
112
|
+
} catch {}
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
// Find an available port before binding
|
|
116
|
+
const findPort = (p) =>
|
|
117
|
+
new Promise((resolve) => {
|
|
118
|
+
const probe = createServer()
|
|
119
|
+
probe.once('error', () => {
|
|
120
|
+
if (p < port + 100) resolve(findPort(p + 1))
|
|
121
|
+
else resolve(null)
|
|
122
|
+
})
|
|
123
|
+
probe.listen(p, () => probe.close(() => resolve(p)))
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
const actualPort = await findPort(port)
|
|
127
|
+
if (!actualPort) {
|
|
128
|
+
console.warn(`CDP server: no available port in range ${port}-${port + 99}`)
|
|
129
|
+
return
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// HTTP discovery endpoints (chrome://inspect, Playwright, etc.)
|
|
133
|
+
const httpServer = createServer((req, res) => {
|
|
134
|
+
if (req.url === '/json/list' || req.url === '/json') {
|
|
135
|
+
res.writeHead(200, { 'Content-Type': 'application/json' })
|
|
136
|
+
res.end(
|
|
137
|
+
JSON.stringify([
|
|
138
|
+
{
|
|
139
|
+
description: 'BRICKS Preview (CTOR Preview)',
|
|
140
|
+
id: 'bricks-preview',
|
|
141
|
+
title: 'BRICKS Preview',
|
|
142
|
+
type: 'page',
|
|
143
|
+
url: previewUrl,
|
|
144
|
+
webSocketDebuggerUrl: `ws://localhost:${actualPort}/ws`,
|
|
145
|
+
},
|
|
146
|
+
]),
|
|
147
|
+
)
|
|
148
|
+
return
|
|
149
|
+
}
|
|
150
|
+
if (req.url === '/json/version') {
|
|
151
|
+
res.writeHead(200, { 'Content-Type': 'application/json' })
|
|
152
|
+
res.end(JSON.stringify({ Browser: 'BRICKS Preview', 'Protocol-Version': '1.3' }))
|
|
153
|
+
return
|
|
154
|
+
}
|
|
155
|
+
// bricks-cli discovery endpoint
|
|
156
|
+
if (req.url === '/devtools/info') {
|
|
157
|
+
res.writeHead(200, { 'Content-Type': 'application/json' })
|
|
158
|
+
res.end(
|
|
159
|
+
JSON.stringify({
|
|
160
|
+
name: 'BRICKS Preview',
|
|
161
|
+
port: actualPort,
|
|
162
|
+
protocols: ['cdp'],
|
|
163
|
+
hasPasscode: false,
|
|
164
|
+
}),
|
|
165
|
+
)
|
|
166
|
+
return
|
|
167
|
+
}
|
|
168
|
+
res.writeHead(404)
|
|
169
|
+
res.end()
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
const wss = new WebSocketServer({ server: httpServer, path: '/ws' })
|
|
173
|
+
wss.on('connection', (ws) => {
|
|
174
|
+
clients.add(ws)
|
|
175
|
+
injectCdpRelay()
|
|
176
|
+
|
|
177
|
+
ws.on('message', (raw) => {
|
|
178
|
+
try {
|
|
179
|
+
const req = JSON.parse(raw.toString())
|
|
180
|
+
const cdpReq = JSON.stringify({
|
|
181
|
+
type: 'cdp-request',
|
|
182
|
+
id: req.id,
|
|
183
|
+
method: req.method,
|
|
184
|
+
params: req.params || {},
|
|
185
|
+
sessionId: req.sessionId,
|
|
186
|
+
})
|
|
187
|
+
mainWindow.webContents.executeJavaScript(`window.postMessage(${JSON.stringify(cdpReq)})`)
|
|
188
|
+
} catch {}
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
ws.on('close', () => clients.delete(ws))
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
httpServer.listen(actualPort, () => {
|
|
195
|
+
console.log(`CDP server: ws://localhost:${actualPort}/ws`)
|
|
196
|
+
console.log(
|
|
197
|
+
`Inspect: devtools://devtools/bundled/inspector.html?ws=localhost:${actualPort}/ws`,
|
|
198
|
+
)
|
|
199
|
+
})
|
|
200
|
+
}
|
|
201
|
+
|
|
73
202
|
app.on('ready', () => {
|
|
74
203
|
let show = true
|
|
75
204
|
if (takeScreenshotConfig && !takeScreenshotConfig.noHeadless) show = false
|
|
@@ -124,12 +253,16 @@ app.on('ready', () => {
|
|
|
124
253
|
})
|
|
125
254
|
`)
|
|
126
255
|
}
|
|
256
|
+
// Start CDP WebSocket server if requested
|
|
257
|
+
const cdpPort = values['cdp-port'] ? parseInt(values['cdp-port'], 10) : null
|
|
258
|
+
if (cdpPort) startCdpServer(mainWindow, cdpPort)
|
|
127
259
|
})
|
|
128
260
|
|
|
129
261
|
// Capture console messages from the preview
|
|
130
262
|
if (testId) {
|
|
131
|
-
mainWindow.webContents.on('console-message', (
|
|
132
|
-
|
|
263
|
+
mainWindow.webContents.on('console-message', (_event, ...rest) => {
|
|
264
|
+
const message = typeof rest[0] === 'object' ? rest[0].message : rest[1]
|
|
265
|
+
if (message?.startsWith('[TEST_RESULT]')) {
|
|
133
266
|
const data = JSON.parse(message.replace('[TEST_RESULT]', ''))
|
|
134
267
|
console.log(`[TEST_RESULT_TOON]${TOON.encode(data.result)}`)
|
|
135
268
|
if (!takeScreenshotConfig && noKeepOpen) app.quit()
|
package/tools/preview.ts
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { spawn } from 'node:child_process'
|
|
2
|
+
import { readFile, writeFile } from 'node:fs/promises'
|
|
3
|
+
import { watch, unlinkSync } from 'fs'
|
|
3
4
|
import type { FSWatcher } from 'fs'
|
|
5
|
+
import { createInterface } from 'node:readline'
|
|
4
6
|
import { parseArgs } from 'util'
|
|
5
7
|
import debounce from 'lodash/debounce'
|
|
8
|
+
import { sh } from './_shell'
|
|
6
9
|
|
|
7
10
|
const { values } = parseArgs({
|
|
8
|
-
args:
|
|
11
|
+
args: process.argv,
|
|
9
12
|
options: {
|
|
10
13
|
'skip-typecheck': { type: 'boolean' },
|
|
11
14
|
'clear-cache': { type: 'boolean' },
|
|
@@ -19,6 +22,8 @@ const { values } = parseArgs({
|
|
|
19
22
|
'test-id': { type: 'string' },
|
|
20
23
|
'test-title-like': { type: 'string' },
|
|
21
24
|
'no-keep-open': { type: 'boolean' },
|
|
25
|
+
'cdp-port': { type: 'string' },
|
|
26
|
+
'no-cdp': { type: 'boolean' },
|
|
22
27
|
},
|
|
23
28
|
strict: true,
|
|
24
29
|
allowPositionals: true,
|
|
@@ -26,7 +31,7 @@ const { values } = parseArgs({
|
|
|
26
31
|
|
|
27
32
|
const cwd = process.cwd()
|
|
28
33
|
|
|
29
|
-
const app = await
|
|
34
|
+
const app = JSON.parse(await readFile(`${cwd}/application.json`, 'utf8'))
|
|
30
35
|
|
|
31
36
|
const args: string[] = []
|
|
32
37
|
if (values['clear-cache']) args.push('--clear-cache')
|
|
@@ -62,11 +67,16 @@ if (values['no-keep-open']) {
|
|
|
62
67
|
args.push('--no-keep-open')
|
|
63
68
|
}
|
|
64
69
|
|
|
70
|
+
if (!values['no-cdp']) {
|
|
71
|
+
const cdpPort = parseInt(values['cdp-port'] || '', 10) || 19852
|
|
72
|
+
args.push('--cdp-port', String(cdpPort))
|
|
73
|
+
}
|
|
74
|
+
|
|
65
75
|
const useTypecheck = !values['skip-typecheck']
|
|
66
76
|
|
|
67
77
|
const compile = async () => {
|
|
68
|
-
if (useTypecheck) await
|
|
69
|
-
await
|
|
78
|
+
if (useTypecheck) await sh`bun typecheck`
|
|
79
|
+
await sh`bun compile.ts`
|
|
70
80
|
}
|
|
71
81
|
|
|
72
82
|
await compile()
|
|
@@ -80,36 +90,61 @@ if (needWatcher) {
|
|
|
80
90
|
})
|
|
81
91
|
}
|
|
82
92
|
|
|
83
|
-
const
|
|
84
|
-
env: { ...process.env, BRICKS_STAGE: app.stage || 'production' },
|
|
85
|
-
stdout: 'pipe',
|
|
86
|
-
stderr: 'inherit',
|
|
87
|
-
})
|
|
93
|
+
const devtoolsInfoPath = `${cwd}/.bricks/devtools.json`
|
|
88
94
|
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
95
|
+
const cleanupDevtoolsInfo = () => {
|
|
96
|
+
try {
|
|
97
|
+
unlinkSync(devtoolsInfoPath)
|
|
98
|
+
} catch {}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Kill existing preview process if devtools.json contains a stale pid
|
|
102
|
+
try {
|
|
103
|
+
const devtoolsInfo = JSON.parse(await readFile(devtoolsInfoPath, 'utf8'))
|
|
104
|
+
if (devtoolsInfo.pid) {
|
|
105
|
+
try {
|
|
106
|
+
process.kill(devtoolsInfo.pid)
|
|
107
|
+
} catch {}
|
|
108
|
+
cleanupDevtoolsInfo()
|
|
109
|
+
}
|
|
110
|
+
} catch {}
|
|
111
|
+
|
|
112
|
+
const proc = spawn(
|
|
113
|
+
'bunx',
|
|
114
|
+
['--bun', 'electron', `${import.meta.dirname}/preview-main.mjs`, ...args],
|
|
115
|
+
{
|
|
116
|
+
env: { ...process.env, BRICKS_STAGE: app.stage || 'production' },
|
|
117
|
+
stdio: ['inherit', 'pipe', 'inherit'],
|
|
118
|
+
},
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
const rl = createInterface({ input: proc.stdout! })
|
|
122
|
+
|
|
123
|
+
rl.on('line', (line) => {
|
|
124
|
+
if (line.startsWith('[TEST_RESULT_TOON]')) {
|
|
125
|
+
const toonData = line.replace('[TEST_RESULT_TOON]', '')
|
|
126
|
+
console.log(toonData)
|
|
127
|
+
return
|
|
128
|
+
}
|
|
129
|
+
if (!line) return
|
|
130
|
+
// Detect CDP server startup from preview-main output
|
|
131
|
+
const cdpMatch = line.match(/^CDP server: ws:\/\/localhost:(\d+)/)
|
|
132
|
+
if (cdpMatch) {
|
|
133
|
+
const info = {
|
|
134
|
+
port: parseInt(cdpMatch[1], 10),
|
|
135
|
+
pid: proc.pid,
|
|
136
|
+
address: 'localhost',
|
|
137
|
+
name: `${app.name || 'Unnamed'} (CTOR Preview)`,
|
|
138
|
+
startedAt: new Date().toISOString(),
|
|
108
139
|
}
|
|
140
|
+
writeFile(devtoolsInfoPath, JSON.stringify(info, null, 2))
|
|
109
141
|
}
|
|
110
|
-
|
|
142
|
+
console.log(line)
|
|
143
|
+
})
|
|
111
144
|
|
|
112
|
-
await
|
|
113
|
-
|
|
145
|
+
await new Promise<void>((resolve) => {
|
|
146
|
+
proc.on('close', () => resolve())
|
|
147
|
+
})
|
|
114
148
|
|
|
149
|
+
cleanupDevtoolsInfo()
|
|
115
150
|
if (watcher) watcher.close()
|
package/tools/pull.ts
CHANGED
|
@@ -1,16 +1,30 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { format } from '
|
|
1
|
+
import { readFile, writeFile } from 'node:fs/promises'
|
|
2
|
+
import { format } from 'oxfmt'
|
|
3
|
+
import { sh } from './_shell'
|
|
4
|
+
import { buildCommitArgs } from './_git-author'
|
|
3
5
|
|
|
4
6
|
const cwd = process.cwd()
|
|
7
|
+
const args = process.argv.slice(2)
|
|
8
|
+
const force = args.includes('--force') || args.includes('-f')
|
|
5
9
|
|
|
6
10
|
// Check git status
|
|
7
|
-
const { exitCode } = await
|
|
11
|
+
const { exitCode } = await sh`cd ${cwd} && git status`.nothrow()
|
|
8
12
|
const isGitRepo = exitCode === 0
|
|
9
13
|
|
|
10
14
|
if (isGitRepo) {
|
|
11
|
-
const unstagedChanges = await
|
|
12
|
-
if (unstagedChanges)
|
|
13
|
-
|
|
15
|
+
const unstagedChanges = await sh`cd ${cwd} && git diff --name-only --diff-filter=ACMR`.text()
|
|
16
|
+
if (unstagedChanges) {
|
|
17
|
+
if (force) {
|
|
18
|
+
console.log('Force mode: committing unstaged changes before pull...')
|
|
19
|
+
await sh`cd ${cwd} && git add .`
|
|
20
|
+
const preCommitArgs = await buildCommitArgs(cwd, [
|
|
21
|
+
'chore(force-pull): saved unstaged changes before pull',
|
|
22
|
+
])
|
|
23
|
+
await sh`cd ${cwd} && git ${preCommitArgs}`
|
|
24
|
+
} else {
|
|
25
|
+
throw new Error('Unstaged changes found, please commit or stash your changes before pulling')
|
|
26
|
+
}
|
|
27
|
+
}
|
|
14
28
|
} else {
|
|
15
29
|
const confirmContinue = prompt(
|
|
16
30
|
'No git repository found, so it will not be safe to pull, continue? (y/n)',
|
|
@@ -19,13 +33,14 @@ if (isGitRepo) {
|
|
|
19
33
|
}
|
|
20
34
|
|
|
21
35
|
// Read application.json
|
|
22
|
-
const app = await
|
|
36
|
+
const app = JSON.parse(await readFile(`${cwd}/application.json`, 'utf8'))
|
|
23
37
|
|
|
24
38
|
const isModule = app.type === 'module'
|
|
25
39
|
const command = isModule ? 'module' : 'app'
|
|
26
40
|
|
|
27
41
|
// Fetch project files using CLI
|
|
28
|
-
|
|
42
|
+
console.log(`Pulling ${command} project (${app.id})...`)
|
|
43
|
+
const result = await sh`bricks ${command} project-pull ${app.id} --json`.quiet().nothrow()
|
|
29
44
|
|
|
30
45
|
if (result.exitCode !== 0) {
|
|
31
46
|
const output = result.stderr.toString() || result.stdout.toString()
|
|
@@ -40,12 +55,13 @@ if (result.exitCode !== 0) {
|
|
|
40
55
|
const { files, lastCommitId } = JSON.parse(result.stdout.toString())
|
|
41
56
|
|
|
42
57
|
let useMain = false
|
|
43
|
-
if (isGitRepo) {
|
|
44
|
-
|
|
58
|
+
if (isGitRepo && !force) {
|
|
59
|
+
console.log(`Checking commit ${lastCommitId}...`)
|
|
60
|
+
const found = (await sh`cd ${cwd} && git rev-list -1 ${lastCommitId}`.nothrow().text())
|
|
45
61
|
.trim()
|
|
46
62
|
.match(/^[\da-f]{40}$/)
|
|
47
63
|
|
|
48
|
-
const commitId = (await
|
|
64
|
+
const commitId = (await sh`cd ${cwd} && git rev-parse HEAD`.text()).trim()
|
|
49
65
|
|
|
50
66
|
if (commitId === lastCommitId) throw new Error('Commit not changed')
|
|
51
67
|
|
|
@@ -53,18 +69,18 @@ if (isGitRepo) {
|
|
|
53
69
|
? 'BRICKS_PROJECT_try-pull-module'
|
|
54
70
|
: 'BRICKS_PROJECT_try-pull-application'
|
|
55
71
|
|
|
56
|
-
await
|
|
72
|
+
await sh`cd ${cwd} && git branch -D ${branchName}`.nothrow()
|
|
57
73
|
|
|
58
74
|
if (found) {
|
|
59
|
-
await
|
|
75
|
+
await sh`cd ${cwd} && git checkout -b ${branchName} ${lastCommitId}`.nothrow()
|
|
60
76
|
} else {
|
|
61
|
-
await
|
|
77
|
+
await sh`cd ${cwd} && git checkout -b ${branchName}`
|
|
62
78
|
useMain = true
|
|
63
79
|
}
|
|
64
80
|
}
|
|
65
81
|
|
|
66
|
-
const
|
|
67
|
-
.
|
|
82
|
+
const oxfmtConfig = await readFile(`${cwd}/.oxfmtrc.json`, 'utf8')
|
|
83
|
+
.then(JSON.parse)
|
|
68
84
|
.catch(() => ({
|
|
69
85
|
trailingComma: 'all',
|
|
70
86
|
tabWidth: 2,
|
|
@@ -74,25 +90,33 @@ const prettierConfig = await Bun.file(`${cwd}/.prettierrc`)
|
|
|
74
90
|
}))
|
|
75
91
|
|
|
76
92
|
await Promise.all(
|
|
77
|
-
files.map(async (file: { name: string; input: string; formatable?: boolean }) =>
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
file.
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
)
|
|
84
|
-
),
|
|
93
|
+
files.map(async (file: { name: string; input: string; formatable?: boolean }) => {
|
|
94
|
+
let content = file.input
|
|
95
|
+
if (file.formatable) {
|
|
96
|
+
const result = await format(file.name, file.input, oxfmtConfig)
|
|
97
|
+
content = result.code
|
|
98
|
+
}
|
|
99
|
+
return writeFile(`${cwd}/${file.name}`, content)
|
|
100
|
+
}),
|
|
85
101
|
)
|
|
86
102
|
|
|
87
103
|
if (isGitRepo) {
|
|
88
|
-
await
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
104
|
+
await sh`cd ${cwd} && git add .`
|
|
105
|
+
const hasChanges = !!(await sh`cd ${cwd} && git diff --cached --name-only`.text()).trim()
|
|
106
|
+
if (hasChanges) {
|
|
107
|
+
const commitMsg = force
|
|
108
|
+
? `chore(force-pull): apply force pull-${command}`
|
|
109
|
+
: isModule
|
|
110
|
+
? 'chore(project): apply file changes from BRICKS module'
|
|
111
|
+
: 'chore(project): apply file changes from BRICKS application'
|
|
112
|
+
const commitArgs = await buildCommitArgs(cwd, [commitMsg])
|
|
113
|
+
await sh`cd ${cwd} && git ${commitArgs}`
|
|
114
|
+
}
|
|
115
|
+
if (!force && !useMain) {
|
|
116
|
+
await sh`cd ${cwd} && git merge main`
|
|
95
117
|
}
|
|
96
118
|
}
|
|
97
119
|
|
|
98
|
-
console.log(
|
|
120
|
+
console.log(
|
|
121
|
+
`${isModule ? 'Module' : 'App'} project pulled: ${files.length} files${force ? ' (force)' : ''}`,
|
|
122
|
+
)
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"lib": ["ESNext"],
|
|
4
|
+
"target": "ESNext",
|
|
5
|
+
"module": "ESNext",
|
|
6
|
+
"moduleDetection": "force",
|
|
7
|
+
"allowJs": true,
|
|
8
|
+
"resolveJsonModule": true,
|
|
9
|
+
"moduleResolution": "bundler",
|
|
10
|
+
"allowImportingTsExtensions": true,
|
|
11
|
+
"verbatimModuleSyntax": true,
|
|
12
|
+
"noEmit": true,
|
|
13
|
+
"skipLibCheck": true,
|
|
14
|
+
},
|
|
15
|
+
"exclude": ["node_modules"],
|
|
16
|
+
}
|
package/types/animation.ts
CHANGED
|
@@ -61,8 +61,10 @@ export interface AnimationDecayConfig {
|
|
|
61
61
|
export interface AnimationDef {
|
|
62
62
|
__typename: 'Animation'
|
|
63
63
|
id: string
|
|
64
|
+
alias?: string
|
|
64
65
|
title: string
|
|
65
66
|
description?: string
|
|
67
|
+
hideShortRef?: boolean
|
|
66
68
|
runType?: 'once' | 'loop'
|
|
67
69
|
property:
|
|
68
70
|
| 'transform.translateX'
|
|
@@ -80,8 +82,10 @@ export interface AnimationDef {
|
|
|
80
82
|
export interface AnimationComposeDef {
|
|
81
83
|
__typename: 'AnimationCompose'
|
|
82
84
|
id: string
|
|
85
|
+
alias?: string
|
|
83
86
|
title: string
|
|
84
87
|
description?: string
|
|
88
|
+
hideShortRef?: boolean
|
|
85
89
|
runType?: 'once' | 'loop'
|
|
86
90
|
composeType: 'parallel' | 'sequence'
|
|
87
91
|
items: Array<() => Animation>
|
package/types/automation.ts
CHANGED
|
@@ -45,7 +45,7 @@ export interface TestCaseJumpCondition {
|
|
|
45
45
|
operator?: JumpConditionOperator
|
|
46
46
|
value?: any
|
|
47
47
|
// The test case to jump to (getter function for dynamic IDs or string for static IDs)
|
|
48
|
-
jump_to
|
|
48
|
+
jump_to?: string | (() => TestCase)
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
/**
|
|
@@ -182,6 +182,7 @@ export interface TestCase {
|
|
|
182
182
|
__typename: 'TestCase'
|
|
183
183
|
id: string
|
|
184
184
|
name: string
|
|
185
|
+
hideShortRef?: boolean
|
|
185
186
|
run: TestMethodRun
|
|
186
187
|
exit_on_failed: boolean
|
|
187
188
|
commented: boolean
|
|
@@ -203,6 +204,7 @@ export interface AutomationTest {
|
|
|
203
204
|
__typename: 'AutomationTest'
|
|
204
205
|
id: string
|
|
205
206
|
title: string
|
|
207
|
+
hideShortRef?: boolean
|
|
206
208
|
timeout: number
|
|
207
209
|
trigger_type?: TestTriggerType
|
|
208
210
|
cron?: string // Cron expression when trigger_type is 'cron'
|
|
@@ -220,6 +222,7 @@ export interface AutomationTestMap {
|
|
|
220
222
|
__typename: 'AutomationTestMap'
|
|
221
223
|
id: string
|
|
222
224
|
title: string
|
|
225
|
+
hideShortRef?: boolean
|
|
223
226
|
createdAt: number
|
|
224
227
|
tests: AutomationTest[]
|
|
225
228
|
}
|
package/types/brick-base.ts
CHANGED
|
@@ -59,7 +59,7 @@ export interface BrickBasicProperty {
|
|
|
59
59
|
shadowOffsetWidth?: number | DataLink
|
|
60
60
|
/* The brick shadow offset height */
|
|
61
61
|
shadowOffsetHeight?: number | DataLink
|
|
62
|
-
/* Brick pressable.
|
|
62
|
+
/* Brick pressable.
|
|
63
63
|
Disabled: Disabled even if event or animation is set.
|
|
64
64
|
Bypass: Disable and bypass the touch event on the brick. */
|
|
65
65
|
pressable?: 'enabled' | 'disabled' | 'bypass' | DataLink
|
package/types/bricks/Camera.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
/* Auto generated by build script
|
|
1
|
+
/* Auto generated by build script
|
|
2
|
+
*
|
|
3
|
+
* Camera view with photo capture and barcode scanning capabilities
|
|
4
|
+
*/
|
|
2
5
|
import type { SwitchCondInnerStateCurrentCanvas, SwitchCondData, SwitchDef } from '../switch'
|
|
3
6
|
import type { Data, DataLink } from '../data'
|
|
4
7
|
import type { Animation, AnimationBasicEvents } from '../animation'
|
|
@@ -12,6 +15,7 @@ import type {
|
|
|
12
15
|
EventProperty,
|
|
13
16
|
} from '../common'
|
|
14
17
|
import type { BrickBasicProperty, BrickBasicEvents, BrickBasicEventsForItem } from '../brick-base'
|
|
18
|
+
import type { TemplateEventPropsMap } from '../../utils/event-props'
|
|
15
19
|
|
|
16
20
|
/* Take picture on the Camera */
|
|
17
21
|
export type BrickCameraActionTakePicture = ActionWithParams & {
|
|
@@ -151,31 +155,62 @@ Default property:
|
|
|
151
155
|
}
|
|
152
156
|
events?: BrickBasicEvents & {
|
|
153
157
|
/* Event of the Camera state change */
|
|
154
|
-
stateChange?: Array<EventAction
|
|
158
|
+
stateChange?: Array<EventAction<string & keyof TemplateEventPropsMap['Camera']['stateChange']>>
|
|
155
159
|
/* Event of the Camera record start */
|
|
156
160
|
recordStart?: Array<EventAction>
|
|
157
161
|
/* Event of the Camera record end */
|
|
158
162
|
recordEnd?: Array<EventAction>
|
|
159
163
|
/* Event of the Camera barcode read */
|
|
160
|
-
barcodeRead?: Array<EventAction
|
|
164
|
+
barcodeRead?: Array<EventAction<string & keyof TemplateEventPropsMap['Camera']['barcodeRead']>>
|
|
161
165
|
/* Event of the Camera picture taken */
|
|
162
|
-
pictureTaken?: Array<
|
|
166
|
+
pictureTaken?: Array<
|
|
167
|
+
EventAction<string & keyof TemplateEventPropsMap['Camera']['pictureTaken']>
|
|
168
|
+
>
|
|
163
169
|
/* Event of the Camera record finished */
|
|
164
|
-
recordFinish?: Array<
|
|
170
|
+
recordFinish?: Array<
|
|
171
|
+
EventAction<string & keyof TemplateEventPropsMap['Camera']['recordFinish']>
|
|
172
|
+
>
|
|
165
173
|
/* Event of the Camera mount error */
|
|
166
|
-
mountError?: Array<EventAction
|
|
174
|
+
mountError?: Array<EventAction<string & keyof TemplateEventPropsMap['Camera']['mountError']>>
|
|
167
175
|
}
|
|
168
176
|
outlets?: {
|
|
169
177
|
/* Camera device and format information */
|
|
170
|
-
info?: () => Data
|
|
178
|
+
info?: () => Data<{ [key: string]: any }>
|
|
171
179
|
/* Picture taken result */
|
|
172
|
-
pictureTaken?: () => Data
|
|
180
|
+
pictureTaken?: () => Data<{
|
|
181
|
+
width?: number
|
|
182
|
+
height?: number
|
|
183
|
+
uri?: string
|
|
184
|
+
base64?: string
|
|
185
|
+
[key: string]: any
|
|
186
|
+
}>
|
|
173
187
|
/* Record video result */
|
|
174
|
-
recordVideo?: () => Data
|
|
188
|
+
recordVideo?: () => Data<{
|
|
189
|
+
uri?: string
|
|
190
|
+
[key: string]: any
|
|
191
|
+
}>
|
|
175
192
|
/* Barcode read result */
|
|
176
|
-
barcodeRead?: () => Data
|
|
193
|
+
barcodeRead?: () => Data<{
|
|
194
|
+
type?: string
|
|
195
|
+
data?: string
|
|
196
|
+
rawData?: string
|
|
197
|
+
bounds?: {
|
|
198
|
+
origin?: {
|
|
199
|
+
x?: number
|
|
200
|
+
y?: number
|
|
201
|
+
[key: string]: any
|
|
202
|
+
}
|
|
203
|
+
size?: {
|
|
204
|
+
width?: number
|
|
205
|
+
height?: number
|
|
206
|
+
[key: string]: any
|
|
207
|
+
}
|
|
208
|
+
[key: string]: any
|
|
209
|
+
}
|
|
210
|
+
[key: string]: any
|
|
211
|
+
}>
|
|
177
212
|
/* Faces detected result */
|
|
178
|
-
faceDetected?: () => Data
|
|
213
|
+
faceDetected?: () => Data<Array<{ [key: string]: any }>>
|
|
179
214
|
}
|
|
180
215
|
animation?: AnimationBasicEvents & {
|
|
181
216
|
stateChange?: Animation
|
|
@@ -188,7 +223,7 @@ Default property:
|
|
|
188
223
|
}
|
|
189
224
|
}
|
|
190
225
|
|
|
191
|
-
/* Camera view
|
|
226
|
+
/* Camera view with photo capture and barcode scanning capabilities */
|
|
192
227
|
export type BrickCamera = Brick &
|
|
193
228
|
BrickCameraDef & {
|
|
194
229
|
templateKey: 'BRICK_CAMERA'
|
package/types/bricks/Chart.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
/* Auto generated by build script
|
|
1
|
+
/* Auto generated by build script
|
|
2
|
+
*
|
|
3
|
+
* Chart brick, based on [Apache ECharts](https://echarts.apache.org/en/index.html).
|
|
4
|
+
*/
|
|
2
5
|
import type { SwitchCondInnerStateCurrentCanvas, SwitchCondData, SwitchDef } from '../switch'
|
|
3
6
|
import type { Data, DataLink } from '../data'
|
|
4
7
|
import type { Animation, AnimationBasicEvents } from '../animation'
|
|
@@ -12,6 +15,7 @@ import type {
|
|
|
12
15
|
EventProperty,
|
|
13
16
|
} from '../common'
|
|
14
17
|
import type { BrickBasicProperty, BrickBasicEvents, BrickBasicEventsForItem } from '../brick-base'
|
|
18
|
+
import type { TemplateEventPropsMap } from '../../utils/event-props'
|
|
15
19
|
|
|
16
20
|
/* Data highlight */
|
|
17
21
|
export type BrickChartActionDataHighlight = ActionWithParams & {
|
|
@@ -332,9 +336,11 @@ Default property:
|
|
|
332
336
|
/* Event of chart render */
|
|
333
337
|
onRender?: Array<EventAction>
|
|
334
338
|
/* Event of data point on press */
|
|
335
|
-
onPress?: Array<EventAction
|
|
339
|
+
onPress?: Array<EventAction<string & keyof TemplateEventPropsMap['Chart']['onPress']>>
|
|
336
340
|
/* Event of legend select changed */
|
|
337
|
-
onLegendSelectChanged?: Array<
|
|
341
|
+
onLegendSelectChanged?: Array<
|
|
342
|
+
EventAction<string & keyof TemplateEventPropsMap['Chart']['onLegendSelectChanged']>
|
|
343
|
+
>
|
|
338
344
|
}
|
|
339
345
|
animation?: AnimationBasicEvents & {
|
|
340
346
|
onRender?: Animation
|