@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.
- package/package.json +4 -28
- package/tools/deploy.ts +19 -176
- package/tools/mcp-server.ts +16 -33
- package/tools/postinstall.ts +21 -292
- package/tools/pull.ts +15 -195
- package/tools/push-config.ts +18 -113
- package/tools/simulator.ts +19 -148
- package/compile/__tests__/config-diff.test.js +0 -100
- package/compile/__tests__/index.test.js +0 -461
- package/compile/__tests__/util.test.js +0 -450
- package/compile/action-name-map.ts +0 -1079
- package/compile/config-diff.ts +0 -155
- package/compile/index.ts +0 -1594
- package/compile/util.ts +0 -482
- package/index.ts +0 -6
- package/skills/bricks-ctor/SKILL.md +0 -38
- package/skills/bricks-ctor/references/animation.md +0 -160
- package/skills/bricks-ctor/references/architecture-patterns.md +0 -88
- package/skills/bricks-ctor/references/automations.md +0 -232
- package/skills/bricks-ctor/references/buttress.md +0 -245
- package/skills/bricks-ctor/references/data-calculation.md +0 -252
- package/skills/bricks-ctor/references/local-sync.md +0 -129
- package/skills/bricks-ctor/references/media-flow.md +0 -165
- package/skills/bricks-ctor/references/remote-data-bank.md +0 -196
- package/skills/bricks-ctor/references/simulator.md +0 -132
- package/skills/bricks-ctor/references/source-editing-tools.md +0 -81
- package/skills/bricks-ctor/references/standby-transition.md +0 -124
- package/skills/bricks-ctor/references/verification-toolchain.md +0 -200
- package/skills/bricks-design/SKILL.md +0 -171
- package/skills/bricks-design/references/architecture-truths.md +0 -132
- package/skills/bricks-design/references/avoiding-complexity.md +0 -91
- package/skills/bricks-design/references/design-critique.md +0 -195
- package/skills/bricks-design/references/design-languages.md +0 -265
- package/skills/bricks-design/references/performance.md +0 -116
- package/skills/bricks-design/references/presentation-and-slideshow.md +0 -137
- package/skills/bricks-design/references/translating-inputs.md +0 -152
- package/skills/bricks-design/references/variations-and-tweaks.md +0 -124
- package/skills/bricks-design/references/when-the-brief-is-branded.md +0 -284
- package/skills/bricks-design/references/when-the-brief-is-vague.md +0 -85
- package/skills/bricks-design/references/workflow.md +0 -134
- package/skills/bricks-ux/SKILL.md +0 -114
- package/skills/bricks-ux/references/accessibility.md +0 -162
- package/skills/bricks-ux/references/flow-states.md +0 -175
- package/skills/bricks-ux/references/interaction-archetypes.md +0 -189
- package/skills/bricks-ux/references/monitoring-screens.md +0 -153
- package/skills/bricks-ux/references/pressable-composition.md +0 -126
- package/skills/bricks-ux/references/user-journey.md +0 -168
- package/skills/bricks-ux/references/ux-critique.md +0 -256
- package/skills/rive-marketplace/SKILL.md +0 -99
- package/tools/__tests__/_cli-error.test.ts +0 -35
- package/tools/__tests__/_mcp-config.test.ts +0 -67
- package/tools/__tests__/pull.test.ts +0 -108
- package/tools/_cli-error.ts +0 -17
- package/tools/_edits-log.ts +0 -41
- package/tools/_git-author.ts +0 -37
- package/tools/_last-pushed-commit.ts +0 -28
- package/tools/_mcp-config.ts +0 -42
- package/tools/_shell.ts +0 -180
- package/tools/icons/.gitattributes +0 -1
- package/tools/icons/fa6pro-glyphmap.json +0 -4686
- package/tools/icons/fa6pro-meta.json +0 -1
- package/tools/mcp-env.ts +0 -13
- package/tools/mcp-tools/__tests__/data-calc-editing.test.js +0 -516
- package/tools/mcp-tools/__tests__/entry-editing.test.js +0 -866
- package/tools/mcp-tools/__tests__/huggingface.test.ts +0 -49
- package/tools/mcp-tools/__tests__/icons.test.ts +0 -21
- package/tools/mcp-tools/__tests__/mcp-env.test.js +0 -19
- package/tools/mcp-tools/_editing-helpers.ts +0 -98
- package/tools/mcp-tools/_verify.ts +0 -50
- package/tools/mcp-tools/compile.ts +0 -104
- package/tools/mcp-tools/data-calc-editing.ts +0 -1311
- package/tools/mcp-tools/entry-editing.ts +0 -2297
- package/tools/mcp-tools/huggingface.ts +0 -772
- package/tools/mcp-tools/icons.ts +0 -97
- package/tools/mcp-tools/lottie.ts +0 -102
- package/tools/mcp-tools/media.ts +0 -113
- package/tools/simulator-main.mjs +0 -488
- package/tools/simulator-preload.cjs +0 -16
- package/types/animation.d.ts +0 -116
- package/types/automation.d.ts +0 -231
- package/types/brick-base.d.ts +0 -80
- package/types/bricks/Camera.d.ts +0 -246
- package/types/bricks/Chart.d.ts +0 -372
- package/types/bricks/GenerativeMedia.d.ts +0 -290
- package/types/bricks/Icon.d.ts +0 -98
- package/types/bricks/Image.d.ts +0 -126
- package/types/bricks/Items.d.ts +0 -480
- package/types/bricks/Lottie.d.ts +0 -168
- package/types/bricks/Maps.d.ts +0 -262
- package/types/bricks/QrCode.d.ts +0 -117
- package/types/bricks/Rect.d.ts +0 -150
- package/types/bricks/RichText.d.ts +0 -131
- package/types/bricks/Rive.d.ts +0 -220
- package/types/bricks/Scene3D.d.ts +0 -676
- package/types/bricks/Sketch.d.ts +0 -256
- package/types/bricks/Slideshow.d.ts +0 -201
- package/types/bricks/Svg.d.ts +0 -99
- package/types/bricks/Text.d.ts +0 -148
- package/types/bricks/TextInput.d.ts +0 -242
- package/types/bricks/Video.d.ts +0 -242
- package/types/bricks/VideoStreaming.d.ts +0 -112
- package/types/bricks/WebRtcStream.d.ts +0 -65
- package/types/bricks/WebView.d.ts +0 -168
- package/types/bricks/index.d.ts +0 -23
- package/types/canvas.d.ts +0 -82
- package/types/common.d.ts +0 -141
- package/types/data-calc-command/base.d.ts +0 -57
- package/types/data-calc-command/collection.d.ts +0 -418
- package/types/data-calc-command/color.d.ts +0 -432
- package/types/data-calc-command/constant.d.ts +0 -50
- package/types/data-calc-command/datetime.d.ts +0 -147
- package/types/data-calc-command/file.d.ts +0 -129
- package/types/data-calc-command/index.d.ts +0 -13
- package/types/data-calc-command/iteratee.d.ts +0 -23
- package/types/data-calc-command/logictype.d.ts +0 -190
- package/types/data-calc-command/math.d.ts +0 -275
- package/types/data-calc-command/object.d.ts +0 -119
- package/types/data-calc-command/sandbox.d.ts +0 -66
- package/types/data-calc-command/string.d.ts +0 -407
- package/types/data-calc-script.d.ts +0 -21
- package/types/data-calc.d.ts +0 -12
- package/types/data.d.ts +0 -97
- package/types/generators/AlarmClock.d.ts +0 -110
- package/types/generators/Assistant.d.ts +0 -640
- package/types/generators/BleCentral.d.ts +0 -247
- package/types/generators/BlePeripheral.d.ts +0 -208
- package/types/generators/CanvasMap.d.ts +0 -74
- package/types/generators/CastlesPay.d.ts +0 -87
- package/types/generators/DataBank.d.ts +0 -160
- package/types/generators/File.d.ts +0 -432
- package/types/generators/GraphQl.d.ts +0 -132
- package/types/generators/Http.d.ts +0 -222
- package/types/generators/HttpServer.d.ts +0 -230
- package/types/generators/Information.d.ts +0 -103
- package/types/generators/Intent.d.ts +0 -168
- package/types/generators/Iterator.d.ts +0 -108
- package/types/generators/Keyboard.d.ts +0 -105
- package/types/generators/LlmAnthropicCompat.d.ts +0 -212
- package/types/generators/LlmAppleBuiltin.d.ts +0 -159
- package/types/generators/LlmGgml.d.ts +0 -903
- package/types/generators/LlmMediaTekNeuroPilot.d.ts +0 -235
- package/types/generators/LlmMlx.d.ts +0 -228
- package/types/generators/LlmOnnx.d.ts +0 -213
- package/types/generators/LlmOpenAiCompat.d.ts +0 -312
- package/types/generators/LlmQualcommAiEngine.d.ts +0 -247
- package/types/generators/Mcp.d.ts +0 -637
- package/types/generators/McpServer.d.ts +0 -289
- package/types/generators/MediaFlow.d.ts +0 -170
- package/types/generators/MqttBroker.d.ts +0 -141
- package/types/generators/MqttClient.d.ts +0 -141
- package/types/generators/Question.d.ts +0 -408
- package/types/generators/RealtimeTranscription.d.ts +0 -287
- package/types/generators/RerankerGgml.d.ts +0 -195
- package/types/generators/SerialPort.d.ts +0 -151
- package/types/generators/SoundPlayer.d.ts +0 -94
- package/types/generators/SoundRecorder.d.ts +0 -139
- package/types/generators/SpeechToTextGgml.d.ts +0 -424
- package/types/generators/SpeechToTextOnnx.d.ts +0 -236
- package/types/generators/SpeechToTextPlatform.d.ts +0 -85
- package/types/generators/SqLite.d.ts +0 -159
- package/types/generators/Step.d.ts +0 -107
- package/types/generators/SttAppleBuiltin.d.ts +0 -153
- package/types/generators/Tcp.d.ts +0 -126
- package/types/generators/TcpServer.d.ts +0 -147
- package/types/generators/TextToSpeechAppleBuiltin.d.ts +0 -127
- package/types/generators/TextToSpeechGgml.d.ts +0 -221
- package/types/generators/TextToSpeechOnnx.d.ts +0 -178
- package/types/generators/TextToSpeechOpenAiLike.d.ts +0 -121
- package/types/generators/ThermalPrinter.d.ts +0 -193
- package/types/generators/Tick.d.ts +0 -83
- package/types/generators/Udp.d.ts +0 -120
- package/types/generators/VadGgml.d.ts +0 -260
- package/types/generators/VadOnnx.d.ts +0 -231
- package/types/generators/VadTraditional.d.ts +0 -138
- package/types/generators/VectorStore.d.ts +0 -257
- package/types/generators/Watchdog.d.ts +0 -107
- package/types/generators/WebCrawler.d.ts +0 -103
- package/types/generators/WebRtc.d.ts +0 -181
- package/types/generators/WebSocket.d.ts +0 -148
- package/types/generators/index.d.ts +0 -57
- package/types/index.d.ts +0 -13
- package/types/subspace.d.ts +0 -60
- package/types/switch.d.ts +0 -51
- package/types/system.d.ts +0 -707
- package/utils/__tests__/calc.test.js +0 -25
- package/utils/__tests__/id.test.js +0 -154
- package/utils/calc.ts +0 -130
- package/utils/data.ts +0 -495
- package/utils/event-props.ts +0 -912
- package/utils/id.ts +0 -133
package/tools/simulator-main.mjs
DELETED
|
@@ -1,488 +0,0 @@
|
|
|
1
|
-
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
2
|
-
import { app, BrowserWindow, ipcMain } from 'electron'
|
|
3
|
-
import { mkdir, readdir, readFile, rm, writeFile } from 'fs/promises'
|
|
4
|
-
import { watchFile } from 'fs'
|
|
5
|
-
import { createServer } from 'http'
|
|
6
|
-
import path from 'node:path'
|
|
7
|
-
import { fileURLToPath } from 'node:url'
|
|
8
|
-
import { parseArgs } from 'util'
|
|
9
|
-
import * as TOON from '@toon-format/toon'
|
|
10
|
-
|
|
11
|
-
for (const stream of [process.stdout, process.stderr]) {
|
|
12
|
-
stream.on('error', (err) => {
|
|
13
|
-
if (err.code !== 'EPIPE') throw err
|
|
14
|
-
})
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const { values } = parseArgs({
|
|
18
|
-
args: process.argv,
|
|
19
|
-
options: {
|
|
20
|
-
'clear-cache': { type: 'boolean' },
|
|
21
|
-
'take-screenshot': { type: 'string' },
|
|
22
|
-
'show-menu': { type: 'boolean' },
|
|
23
|
-
'test-id': { type: 'string' },
|
|
24
|
-
'test-title-like': { type: 'string' },
|
|
25
|
-
'no-keep-open': { type: 'boolean' },
|
|
26
|
-
'cdp-port': { type: 'string' },
|
|
27
|
-
},
|
|
28
|
-
strict: true,
|
|
29
|
-
allowPositionals: true,
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
const cwd = process.cwd()
|
|
33
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
34
|
-
const AUTOMATION_SCREENSHOT_PROJECT_DIR = path.join('.bricks', 'automation_screenshots')
|
|
35
|
-
const DEFAULT_SIMULATOR_SECURITY_SETTINGS = Object.freeze({
|
|
36
|
-
allowedInsecureHosts: [],
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
const isObject = (value) => !!value && typeof value === 'object' && !Array.isArray(value)
|
|
40
|
-
|
|
41
|
-
const resolveAutomationScreenshotPath = (requestedPath = '') => {
|
|
42
|
-
const baseDir = path.resolve(cwd, AUTOMATION_SCREENSHOT_PROJECT_DIR)
|
|
43
|
-
const raw = String(requestedPath || AUTOMATION_SCREENSHOT_PROJECT_DIR)
|
|
44
|
-
const fromProject = path.resolve(cwd, raw)
|
|
45
|
-
const target =
|
|
46
|
-
fromProject === baseDir || fromProject.startsWith(`${baseDir}${path.sep}`)
|
|
47
|
-
? fromProject
|
|
48
|
-
: path.resolve(baseDir, raw)
|
|
49
|
-
|
|
50
|
-
if (target !== baseDir && !target.startsWith(`${baseDir}${path.sep}`)) {
|
|
51
|
-
throw new Error('Automation screenshot path must stay inside the project screenshot directory.')
|
|
52
|
-
}
|
|
53
|
-
return target
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
const normalizeAutomationScreenshotEncoding = (encoding) =>
|
|
57
|
-
encoding === 'base64' ? 'base64' : 'utf8'
|
|
58
|
-
|
|
59
|
-
const registerAutomationScreenshotIpc = () => {
|
|
60
|
-
ipcMain.handle('bricks-automation-screenshots:exists', async (_event, filePath) => {
|
|
61
|
-
try {
|
|
62
|
-
await readFile(resolveAutomationScreenshotPath(filePath))
|
|
63
|
-
return true
|
|
64
|
-
} catch {
|
|
65
|
-
return false
|
|
66
|
-
}
|
|
67
|
-
})
|
|
68
|
-
ipcMain.handle('bricks-automation-screenshots:readdir', async (_event, dirPath) => {
|
|
69
|
-
try {
|
|
70
|
-
return await readdir(resolveAutomationScreenshotPath(dirPath))
|
|
71
|
-
} catch {
|
|
72
|
-
return []
|
|
73
|
-
}
|
|
74
|
-
})
|
|
75
|
-
ipcMain.handle('bricks-automation-screenshots:mkdir', async (_event, dirPath) => {
|
|
76
|
-
await mkdir(resolveAutomationScreenshotPath(dirPath), { recursive: true })
|
|
77
|
-
})
|
|
78
|
-
ipcMain.handle('bricks-automation-screenshots:unlink', async (_event, filePath) => {
|
|
79
|
-
await rm(resolveAutomationScreenshotPath(filePath), { recursive: true, force: true })
|
|
80
|
-
})
|
|
81
|
-
ipcMain.handle('bricks-automation-screenshots:read-file', async (_event, filePath, encoding) =>
|
|
82
|
-
readFile(
|
|
83
|
-
resolveAutomationScreenshotPath(filePath),
|
|
84
|
-
normalizeAutomationScreenshotEncoding(encoding),
|
|
85
|
-
),
|
|
86
|
-
)
|
|
87
|
-
ipcMain.handle(
|
|
88
|
-
'bricks-automation-screenshots:write-file',
|
|
89
|
-
async (_event, filePath, contents, encoding) => {
|
|
90
|
-
const target = resolveAutomationScreenshotPath(filePath)
|
|
91
|
-
await mkdir(path.dirname(target), { recursive: true })
|
|
92
|
-
await writeFile(target, contents, normalizeAutomationScreenshotEncoding(encoding))
|
|
93
|
-
},
|
|
94
|
-
)
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
const normalizeSimulatorSecuritySettings = (settings = {}) => {
|
|
98
|
-
const source = isObject(settings) ? settings : {}
|
|
99
|
-
const allowedHosts = Array.isArray(source.allowedInsecureHosts)
|
|
100
|
-
? source.allowedInsecureHosts
|
|
101
|
-
: DEFAULT_SIMULATOR_SECURITY_SETTINGS.allowedInsecureHosts
|
|
102
|
-
|
|
103
|
-
return {
|
|
104
|
-
allowedInsecureHosts: allowedHosts
|
|
105
|
-
.filter((host) => typeof host === 'string')
|
|
106
|
-
.map((host) => host.trim().toLowerCase())
|
|
107
|
-
.filter(Boolean),
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
const normalizeAllowedConnection = (value) => {
|
|
112
|
-
const raw = String(value || '')
|
|
113
|
-
.trim()
|
|
114
|
-
.toLowerCase()
|
|
115
|
-
if (!raw) return null
|
|
116
|
-
if (!/^[a-z][a-z0-9+.-]*:\/\//i.test(raw)) return { host: raw, protocol: null }
|
|
117
|
-
try {
|
|
118
|
-
const url = new URL(raw)
|
|
119
|
-
return {
|
|
120
|
-
host: url.host.toLowerCase(),
|
|
121
|
-
protocol: url.protocol,
|
|
122
|
-
}
|
|
123
|
-
} catch {
|
|
124
|
-
return null
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
const shouldBlockInsecureConnection = (rawUrl, settings = {}) => {
|
|
129
|
-
const normalized = normalizeSimulatorSecuritySettings(settings)
|
|
130
|
-
|
|
131
|
-
try {
|
|
132
|
-
const url = new URL(String(rawUrl || ''))
|
|
133
|
-
if (url.protocol !== 'http:' && url.protocol !== 'ws:') return false
|
|
134
|
-
const host = url.host.toLowerCase()
|
|
135
|
-
const hostname = url.hostname.toLowerCase().replace(/^\[|\]$/g, '')
|
|
136
|
-
return !normalized.allowedInsecureHosts.some((allowedHost) => {
|
|
137
|
-
const allowed = normalizeAllowedConnection(allowedHost)
|
|
138
|
-
if (!allowed) return false
|
|
139
|
-
if (allowed.protocol && allowed.protocol !== url.protocol) return false
|
|
140
|
-
return allowed.host === host || allowed.host === hostname
|
|
141
|
-
})
|
|
142
|
-
} catch {
|
|
143
|
-
return false
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
const getUnsecureConnectionHost = (rawUrl) => {
|
|
148
|
-
try {
|
|
149
|
-
const url = new URL(String(rawUrl || ''))
|
|
150
|
-
if (url.protocol !== 'http:' && url.protocol !== 'ws:') return null
|
|
151
|
-
return url.host.toLowerCase()
|
|
152
|
-
} catch {
|
|
153
|
-
return null
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
const readSimulatorProjectSettings = async () => {
|
|
158
|
-
try {
|
|
159
|
-
return normalizeSimulatorSecuritySettings(
|
|
160
|
-
JSON.parse(await readFile(`${cwd}/simulator.json`, 'utf8')),
|
|
161
|
-
)
|
|
162
|
-
} catch {
|
|
163
|
-
return normalizeSimulatorSecuritySettings()
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
let takeScreenshotConfig = null
|
|
168
|
-
try {
|
|
169
|
-
if (values['take-screenshot']) {
|
|
170
|
-
takeScreenshotConfig = JSON.parse(values['take-screenshot'])
|
|
171
|
-
if (!takeScreenshotConfig.path) takeScreenshotConfig.path = `${cwd}/screenshot.jpg`
|
|
172
|
-
if (!takeScreenshotConfig.width) takeScreenshotConfig.width = 1280
|
|
173
|
-
if (!takeScreenshotConfig.height) takeScreenshotConfig.height = 768
|
|
174
|
-
if (!takeScreenshotConfig.delay) takeScreenshotConfig.delay = 1000
|
|
175
|
-
}
|
|
176
|
-
} catch (e) {
|
|
177
|
-
console.error('Invalid take-screenshot config', e)
|
|
178
|
-
// eslint-disable-next-line unicorn/no-process-exit
|
|
179
|
-
process.exit(1)
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
let config = JSON.parse(await readFile(`${cwd}/.bricks/build/application-config.json`))
|
|
183
|
-
let simulatorSettings = await readSimulatorProjectSettings()
|
|
184
|
-
|
|
185
|
-
// Resolve testId from testTitleLike
|
|
186
|
-
let testId = values['test-id'] || null
|
|
187
|
-
if (!testId && values['test-title-like']) {
|
|
188
|
-
const titleLike = values['test-title-like'].toLowerCase()
|
|
189
|
-
const automationMap = config.automation_map || {}
|
|
190
|
-
for (const group of Object.values(automationMap)) {
|
|
191
|
-
const found = Object.entries(group.map || {}).find(([, test]) =>
|
|
192
|
-
test.title?.toLowerCase().includes(titleLike),
|
|
193
|
-
)
|
|
194
|
-
if (found) {
|
|
195
|
-
;[testId] = found
|
|
196
|
-
break
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
if (!testId) {
|
|
200
|
-
throw new Error(`No automation found matching title: ${values['test-title-like']}`)
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
const noKeepOpen = values['no-keep-open'] ?? false
|
|
205
|
-
|
|
206
|
-
const stage = process.env.BRICKS_STAGE || 'production'
|
|
207
|
-
|
|
208
|
-
const previewUrlMap = {
|
|
209
|
-
production: 'https://control.bricks.tools/applicationPreview.html',
|
|
210
|
-
beta: 'https://control-beta.bricks.tools/applicationPreview.html',
|
|
211
|
-
development: 'http://localhost:3006/dev-applicationPreview.html',
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
const previewUrl = previewUrlMap[stage]
|
|
215
|
-
if (!previewUrl) throw new Error(`Invalid BRICKS_STAGE: ${stage}`)
|
|
216
|
-
simulatorSettings = normalizeSimulatorSecuritySettings({
|
|
217
|
-
...simulatorSettings,
|
|
218
|
-
allowedInsecureHosts: [
|
|
219
|
-
...simulatorSettings.allowedInsecureHosts,
|
|
220
|
-
getUnsecureConnectionHost(previewUrl),
|
|
221
|
-
].filter(Boolean),
|
|
222
|
-
})
|
|
223
|
-
|
|
224
|
-
// --- CDP WebSocket Server ---
|
|
225
|
-
// Bridges external CDP clients to the preview's postMessage-based CDP bridge.
|
|
226
|
-
// Usage: --cdp-port 9222
|
|
227
|
-
|
|
228
|
-
const startCdpServer = async (mainWindow, port) => {
|
|
229
|
-
const { WebSocketServer } = await import('ws')
|
|
230
|
-
const clients = new Set()
|
|
231
|
-
|
|
232
|
-
// Inject a listener in the preview that forwards CDP responses/events via console
|
|
233
|
-
const injectCdpRelay = () =>
|
|
234
|
-
mainWindow.webContents.executeJavaScript(`
|
|
235
|
-
if (!window.__cdpRelayInstalled) {
|
|
236
|
-
window.__cdpRelayInstalled = true
|
|
237
|
-
window.addEventListener('message', (evt) => {
|
|
238
|
-
try {
|
|
239
|
-
const d = typeof evt.data === 'string' ? JSON.parse(evt.data) : evt.data
|
|
240
|
-
if (d && (d.type === 'cdp-response' || d.type === 'cdp-event'))
|
|
241
|
-
console.log('[CDP]' + JSON.stringify(d))
|
|
242
|
-
} catch {}
|
|
243
|
-
})
|
|
244
|
-
}
|
|
245
|
-
`)
|
|
246
|
-
|
|
247
|
-
// Capture CDP messages from the preview's console output
|
|
248
|
-
mainWindow.webContents.on('console-message', (_event, ...rest) => {
|
|
249
|
-
const message = typeof rest[0] === 'object' ? rest[0].message : rest[1]
|
|
250
|
-
if (!message?.startsWith('[CDP]')) return
|
|
251
|
-
try {
|
|
252
|
-
const data = JSON.parse(message.slice(5))
|
|
253
|
-
// Translate to standard CDP wire format (strip internal type field)
|
|
254
|
-
const wireMsg =
|
|
255
|
-
data.type === 'cdp-response'
|
|
256
|
-
? { id: data.id, result: data.result, error: data.error }
|
|
257
|
-
: { method: data.method, params: data.params }
|
|
258
|
-
if (data.sessionId) wireMsg.sessionId = data.sessionId
|
|
259
|
-
const payload = JSON.stringify(wireMsg)
|
|
260
|
-
for (const c of clients) if (c.readyState === 1) c.send(payload)
|
|
261
|
-
} catch {}
|
|
262
|
-
})
|
|
263
|
-
|
|
264
|
-
// Find an available port before binding
|
|
265
|
-
const findPort = (p) =>
|
|
266
|
-
new Promise((resolve) => {
|
|
267
|
-
const probe = createServer()
|
|
268
|
-
probe.once('error', () => {
|
|
269
|
-
if (p < port + 100) resolve(findPort(p + 1))
|
|
270
|
-
else resolve(null)
|
|
271
|
-
})
|
|
272
|
-
probe.listen(p, () => probe.close(() => resolve(p)))
|
|
273
|
-
})
|
|
274
|
-
|
|
275
|
-
const actualPort = await findPort(port)
|
|
276
|
-
if (!actualPort) {
|
|
277
|
-
console.warn(`CDP server: no available port in range ${port}-${port + 99}`)
|
|
278
|
-
return
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
// HTTP discovery endpoints (chrome://inspect, Playwright, etc.)
|
|
282
|
-
const httpServer = createServer((req, res) => {
|
|
283
|
-
if (req.url === '/json/list' || req.url === '/json') {
|
|
284
|
-
res.writeHead(200, { 'Content-Type': 'application/json' })
|
|
285
|
-
res.end(
|
|
286
|
-
JSON.stringify([
|
|
287
|
-
{
|
|
288
|
-
description: 'BRICKS Simulator',
|
|
289
|
-
id: 'bricks-simulator',
|
|
290
|
-
title: 'BRICKS Simulator',
|
|
291
|
-
type: 'page',
|
|
292
|
-
url: previewUrl,
|
|
293
|
-
webSocketDebuggerUrl: `ws://localhost:${actualPort}/ws`,
|
|
294
|
-
},
|
|
295
|
-
]),
|
|
296
|
-
)
|
|
297
|
-
return
|
|
298
|
-
}
|
|
299
|
-
if (req.url === '/json/version') {
|
|
300
|
-
res.writeHead(200, { 'Content-Type': 'application/json' })
|
|
301
|
-
res.end(JSON.stringify({ Browser: 'BRICKS Simulator', 'Protocol-Version': '1.3' }))
|
|
302
|
-
return
|
|
303
|
-
}
|
|
304
|
-
// bricks-cli discovery endpoint
|
|
305
|
-
if (req.url === '/devtools/info') {
|
|
306
|
-
res.writeHead(200, { 'Content-Type': 'application/json' })
|
|
307
|
-
res.end(
|
|
308
|
-
JSON.stringify({
|
|
309
|
-
name: 'BRICKS Simulator',
|
|
310
|
-
port: actualPort,
|
|
311
|
-
protocols: ['cdp'],
|
|
312
|
-
hasPasscode: false,
|
|
313
|
-
}),
|
|
314
|
-
)
|
|
315
|
-
return
|
|
316
|
-
}
|
|
317
|
-
res.writeHead(404)
|
|
318
|
-
res.end()
|
|
319
|
-
})
|
|
320
|
-
|
|
321
|
-
const wss = new WebSocketServer({ server: httpServer, path: '/ws' })
|
|
322
|
-
wss.on('connection', (ws) => {
|
|
323
|
-
clients.add(ws)
|
|
324
|
-
injectCdpRelay()
|
|
325
|
-
|
|
326
|
-
ws.on('message', (raw) => {
|
|
327
|
-
try {
|
|
328
|
-
const req = JSON.parse(raw.toString())
|
|
329
|
-
const cdpReq = JSON.stringify({
|
|
330
|
-
type: 'cdp-request',
|
|
331
|
-
id: req.id,
|
|
332
|
-
method: req.method,
|
|
333
|
-
params: req.params || {},
|
|
334
|
-
sessionId: req.sessionId,
|
|
335
|
-
})
|
|
336
|
-
mainWindow.webContents.executeJavaScript(`window.postMessage(${JSON.stringify(cdpReq)})`)
|
|
337
|
-
} catch {}
|
|
338
|
-
})
|
|
339
|
-
|
|
340
|
-
ws.on('close', () => clients.delete(ws))
|
|
341
|
-
})
|
|
342
|
-
|
|
343
|
-
httpServer.listen(actualPort, () => {
|
|
344
|
-
console.log(`CDP server: ws://localhost:${actualPort}/ws`)
|
|
345
|
-
console.log(
|
|
346
|
-
`Inspect: devtools://devtools/bundled/inspector.html?ws=localhost:${actualPort}/ws`,
|
|
347
|
-
)
|
|
348
|
-
})
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
app.on('ready', () => {
|
|
352
|
-
registerAutomationScreenshotIpc()
|
|
353
|
-
let show = true
|
|
354
|
-
if (takeScreenshotConfig && !takeScreenshotConfig.noHeadless) show = false
|
|
355
|
-
const mainWindow = new BrowserWindow({
|
|
356
|
-
width: takeScreenshotConfig?.width || 1280,
|
|
357
|
-
height: takeScreenshotConfig?.height || 768,
|
|
358
|
-
frame: !takeScreenshotConfig,
|
|
359
|
-
show,
|
|
360
|
-
webPreferences: {
|
|
361
|
-
preload: path.join(__dirname, 'simulator-preload.cjs'),
|
|
362
|
-
contextIsolation: true,
|
|
363
|
-
nodeIntegration: false,
|
|
364
|
-
},
|
|
365
|
-
})
|
|
366
|
-
mainWindow.setBackgroundColor('#333')
|
|
367
|
-
mainWindow.webContents.session.webRequest.onBeforeRequest(
|
|
368
|
-
{ urls: ['http://*/*', 'ws://*/*'] },
|
|
369
|
-
(details, callback) => {
|
|
370
|
-
callback({ cancel: shouldBlockInsecureConnection(details.url, simulatorSettings) })
|
|
371
|
-
},
|
|
372
|
-
)
|
|
373
|
-
mainWindow.loadURL(previewUrl)
|
|
374
|
-
|
|
375
|
-
const sendConfig = () => {
|
|
376
|
-
const payload = {
|
|
377
|
-
type: 'config',
|
|
378
|
-
configFile: { _originTitle: 'Test', ...config, title: Math.random().toString() },
|
|
379
|
-
workspace: { billing: { lock: {}, plan: 'free' } },
|
|
380
|
-
showMenu: values['show-menu'] || false,
|
|
381
|
-
testId,
|
|
382
|
-
}
|
|
383
|
-
mainWindow.webContents.executeJavaScript(
|
|
384
|
-
`window.postMessage(JSON.stringify(${JSON.stringify(payload)}))`,
|
|
385
|
-
)
|
|
386
|
-
if (takeScreenshotConfig) {
|
|
387
|
-
const { delay, width, height, path } = takeScreenshotConfig
|
|
388
|
-
setTimeout(async () => {
|
|
389
|
-
let screenshotFailed = false
|
|
390
|
-
console.log('Taking screenshot')
|
|
391
|
-
try {
|
|
392
|
-
const image = await mainWindow.webContents.capturePage()
|
|
393
|
-
console.log('Writing screenshot to', path)
|
|
394
|
-
await writeFile(path, image.resize({ width, height }).toJPEG(75))
|
|
395
|
-
} catch (err) {
|
|
396
|
-
screenshotFailed = true
|
|
397
|
-
console.error('Screenshot capture/write failed', err)
|
|
398
|
-
} finally {
|
|
399
|
-
if (noKeepOpen) {
|
|
400
|
-
console.log('Closing app')
|
|
401
|
-
if (screenshotFailed) app.exit(1)
|
|
402
|
-
else app.quit()
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
}, delay)
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
mainWindow.webContents.once('dom-ready', () => {
|
|
410
|
-
sendConfig()
|
|
411
|
-
// Listen for test result messages from the preview
|
|
412
|
-
if (testId) {
|
|
413
|
-
mainWindow.webContents.executeJavaScript(`
|
|
414
|
-
window.addEventListener('message', (evt) => {
|
|
415
|
-
try {
|
|
416
|
-
const data = JSON.parse(evt.data)
|
|
417
|
-
if (data.type === 'bricks-preview-test-result') {
|
|
418
|
-
console.log('[TEST_RESULT]' + JSON.stringify(data))
|
|
419
|
-
}
|
|
420
|
-
} catch (e) {}
|
|
421
|
-
})
|
|
422
|
-
`)
|
|
423
|
-
}
|
|
424
|
-
// Start CDP WebSocket server if requested
|
|
425
|
-
const cdpPort = values['cdp-port'] ? parseInt(values['cdp-port'], 10) : null
|
|
426
|
-
if (cdpPort) startCdpServer(mainWindow, cdpPort)
|
|
427
|
-
})
|
|
428
|
-
|
|
429
|
-
// Capture console messages from the preview
|
|
430
|
-
if (testId) {
|
|
431
|
-
mainWindow.webContents.on('console-message', (_event, ...rest) => {
|
|
432
|
-
const message = typeof rest[0] === 'object' ? rest[0].message : rest[1]
|
|
433
|
-
if (message?.startsWith('[TEST_RESULT]')) {
|
|
434
|
-
const data = JSON.parse(message.replace('[TEST_RESULT]', ''))
|
|
435
|
-
console.log(`[TEST_RESULT_TOON]${TOON.encode(data.result)}`)
|
|
436
|
-
if (!takeScreenshotConfig && noKeepOpen) app.quit()
|
|
437
|
-
}
|
|
438
|
-
})
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
if (values['clear-cache']) {
|
|
442
|
-
console.log('Clearing cache')
|
|
443
|
-
mainWindow.webContents.session.clearCache()
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
mainWindow.on('close', () => app.quit())
|
|
447
|
-
|
|
448
|
-
watchFile(
|
|
449
|
-
`${cwd}/.bricks/build/application-config.json`,
|
|
450
|
-
{
|
|
451
|
-
bigint: false,
|
|
452
|
-
persistent: true,
|
|
453
|
-
interval: 1000,
|
|
454
|
-
},
|
|
455
|
-
async () => {
|
|
456
|
-
console.log('Detected config changed')
|
|
457
|
-
config = JSON.parse(await readFile(`${cwd}/.bricks/build/application-config.json`))
|
|
458
|
-
const nextSimulatorSettings = await readSimulatorProjectSettings()
|
|
459
|
-
simulatorSettings = normalizeSimulatorSecuritySettings({
|
|
460
|
-
...nextSimulatorSettings,
|
|
461
|
-
allowedInsecureHosts: [
|
|
462
|
-
...nextSimulatorSettings.allowedInsecureHosts,
|
|
463
|
-
getUnsecureConnectionHost(previewUrl),
|
|
464
|
-
].filter(Boolean),
|
|
465
|
-
})
|
|
466
|
-
sendConfig()
|
|
467
|
-
},
|
|
468
|
-
)
|
|
469
|
-
watchFile(
|
|
470
|
-
`${cwd}/simulator.json`,
|
|
471
|
-
{
|
|
472
|
-
bigint: false,
|
|
473
|
-
persistent: true,
|
|
474
|
-
interval: 1000,
|
|
475
|
-
},
|
|
476
|
-
async () => {
|
|
477
|
-
console.log('Detected simulator settings changed')
|
|
478
|
-
const nextSimulatorSettings = await readSimulatorProjectSettings()
|
|
479
|
-
simulatorSettings = normalizeSimulatorSecuritySettings({
|
|
480
|
-
...nextSimulatorSettings,
|
|
481
|
-
allowedInsecureHosts: [
|
|
482
|
-
...nextSimulatorSettings.allowedInsecureHosts,
|
|
483
|
-
getUnsecureConnectionHost(previewUrl),
|
|
484
|
-
].filter(Boolean),
|
|
485
|
-
})
|
|
486
|
-
},
|
|
487
|
-
)
|
|
488
|
-
})
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
const { contextBridge, ipcRenderer } = require('electron')
|
|
2
|
-
|
|
3
|
-
const AUTOMATION_SCREENSHOT_ROOT = '.bricks/automation_screenshots'
|
|
4
|
-
|
|
5
|
-
contextBridge.exposeInMainWorld('BRICKS_AUTOMATION_SCREENSHOTS', {
|
|
6
|
-
rootDir: AUTOMATION_SCREENSHOT_ROOT,
|
|
7
|
-
exists: (filePath) => ipcRenderer.invoke('bricks-automation-screenshots:exists', filePath),
|
|
8
|
-
readdir: (dirPath) => ipcRenderer.invoke('bricks-automation-screenshots:readdir', dirPath),
|
|
9
|
-
readDir: (dirPath) => ipcRenderer.invoke('bricks-automation-screenshots:readdir', dirPath),
|
|
10
|
-
mkdir: (dirPath) => ipcRenderer.invoke('bricks-automation-screenshots:mkdir', dirPath),
|
|
11
|
-
unlink: (filePath) => ipcRenderer.invoke('bricks-automation-screenshots:unlink', filePath),
|
|
12
|
-
readFile: (filePath, encoding) =>
|
|
13
|
-
ipcRenderer.invoke('bricks-automation-screenshots:read-file', filePath, encoding),
|
|
14
|
-
writeFile: (filePath, contents, encoding) =>
|
|
15
|
-
ipcRenderer.invoke('bricks-automation-screenshots:write-file', filePath, contents, encoding),
|
|
16
|
-
})
|
package/types/animation.d.ts
DELETED
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
export type Easing =
|
|
2
|
-
| ''
|
|
3
|
-
| 'easeInSine'
|
|
4
|
-
| 'easeOutSine'
|
|
5
|
-
| 'easeInOutSine'
|
|
6
|
-
| 'easeInQuad'
|
|
7
|
-
| 'easeOutQuad'
|
|
8
|
-
| 'easeInOutQuad'
|
|
9
|
-
| 'easeInCubic'
|
|
10
|
-
| 'easeOutCubic'
|
|
11
|
-
| 'easeInOutCubic'
|
|
12
|
-
| 'easeInQuart'
|
|
13
|
-
| 'easeOutQuart'
|
|
14
|
-
| 'easeInOutQuart'
|
|
15
|
-
| 'easeInQuint'
|
|
16
|
-
| 'easeOutQuint'
|
|
17
|
-
| 'easeInOutQuint'
|
|
18
|
-
| 'easeInExpo'
|
|
19
|
-
| 'easeOutExpo'
|
|
20
|
-
| 'easeInOutExpo'
|
|
21
|
-
| 'easeInCirc'
|
|
22
|
-
| 'easeOutCirc'
|
|
23
|
-
| 'easeInOutCirc'
|
|
24
|
-
| 'easeInBack'
|
|
25
|
-
| 'easeOutBack'
|
|
26
|
-
| 'easeInOutBack'
|
|
27
|
-
| 'easeInElastic'
|
|
28
|
-
| 'easeOutElastic'
|
|
29
|
-
| 'easeInOutElastic'
|
|
30
|
-
| 'easeInBounce'
|
|
31
|
-
| 'easeOutBounce'
|
|
32
|
-
| 'easeInOutBounce'
|
|
33
|
-
| string // Support format like 'cubic-bezier(x1, y1, x2, y2)'
|
|
34
|
-
|
|
35
|
-
export interface AnimationTimingConfig {
|
|
36
|
-
__type: 'AnimationTimingConfig'
|
|
37
|
-
toValue: number // BRICKS Grid unit
|
|
38
|
-
duration: number // ms
|
|
39
|
-
easing: Easing
|
|
40
|
-
delay: number // ms
|
|
41
|
-
isInteraction: boolean
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export interface AnimationSpringConfig {
|
|
45
|
-
__type: 'AnimationSpringConfig'
|
|
46
|
-
toValue: number // BRICKS Grid unit
|
|
47
|
-
// Use one spring parameter family: tension/friction, speed/bounciness,
|
|
48
|
-
// or stiffness/damping/mass.
|
|
49
|
-
friction?: number
|
|
50
|
-
tension?: number
|
|
51
|
-
speed?: number
|
|
52
|
-
bounciness?: number
|
|
53
|
-
stiffness?: number
|
|
54
|
-
damping?: number
|
|
55
|
-
mass?: number
|
|
56
|
-
velocity?: number
|
|
57
|
-
delay?: number
|
|
58
|
-
isInteraction?: boolean
|
|
59
|
-
overshootClamping?: boolean
|
|
60
|
-
restDisplacementThreshold?: number
|
|
61
|
-
restSpeedThreshold?: number
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export interface AnimationDecayConfig {
|
|
65
|
-
__type: 'AnimationDecayConfig'
|
|
66
|
-
toValue: number // BRICKS Grid unit
|
|
67
|
-
velocity: number
|
|
68
|
-
deceleration: number
|
|
69
|
-
isInteraction: boolean
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export interface AnimationDef {
|
|
73
|
-
__typename: 'Animation'
|
|
74
|
-
id: string
|
|
75
|
-
alias?: string
|
|
76
|
-
title?: string
|
|
77
|
-
description?: string
|
|
78
|
-
hideShortRef?: boolean
|
|
79
|
-
runType?: 'once' | 'loop'
|
|
80
|
-
property:
|
|
81
|
-
| 'transform.translateX'
|
|
82
|
-
| 'transform.translateY'
|
|
83
|
-
| 'transform.scale'
|
|
84
|
-
| 'transform.scaleX'
|
|
85
|
-
| 'transform.scaleY'
|
|
86
|
-
| 'transform.rotate'
|
|
87
|
-
| 'transform.rotateX'
|
|
88
|
-
| 'transform.rotateY'
|
|
89
|
-
| 'opacity'
|
|
90
|
-
config: AnimationTimingConfig | AnimationSpringConfig | AnimationDecayConfig
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export interface AnimationComposeDef {
|
|
94
|
-
__typename: 'AnimationCompose'
|
|
95
|
-
id: string
|
|
96
|
-
alias?: string
|
|
97
|
-
title: string
|
|
98
|
-
description?: string
|
|
99
|
-
hideShortRef?: boolean
|
|
100
|
-
runType?: 'once' | 'loop'
|
|
101
|
-
composeType: 'parallel' | 'sequence'
|
|
102
|
-
items: Array<() => Animation>
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
export type Animation = AnimationDef | AnimationComposeDef
|
|
106
|
-
|
|
107
|
-
// Animation event handlers accept either a direct Animation or a getter that
|
|
108
|
-
// returns one. The getter form is useful for lazy/forward references between
|
|
109
|
-
// animations defined across files.
|
|
110
|
-
export type AnimationOrGetter = Animation | (() => Animation)
|
|
111
|
-
|
|
112
|
-
export interface AnimationBasicEvents {
|
|
113
|
-
showStart?: AnimationOrGetter
|
|
114
|
-
standby?: AnimationOrGetter
|
|
115
|
-
breatheStart?: AnimationOrGetter
|
|
116
|
-
}
|