@fugood/bricks-project 2.24.0-beta.8 → 2.24.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 +7 -3
- package/package.json.bak +27 -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/automations.md +7 -7
- package/skills/{bricks-project → bricks-ctor}/rules/buttress.md +10 -7
- package/skills/{bricks-project → bricks-ctor}/rules/data-calculation.md +1 -1
- 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/deploy.ts +66 -12
- package/tools/icons/fa6pro-meta.json +3669 -26125
- package/tools/mcp-server.ts +11 -878
- package/tools/mcp-tools/compile.ts +91 -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 +137 -40
- package/tools/preview-main.mjs +135 -2
- package/tools/preview.ts +41 -2
- package/tools/pull.ts +37 -19
- 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 +48 -13
- package/types/bricks/Chart.ts +10 -4
- package/types/bricks/GenerativeMedia.ts +30 -14
- package/types/bricks/Icon.ts +9 -5
- package/types/bricks/Image.ts +10 -6
- package/types/bricks/Items.ts +29 -15
- package/types/bricks/Lottie.ts +15 -7
- package/types/bricks/Maps.ts +16 -8
- package/types/bricks/QrCode.ts +9 -5
- package/types/bricks/Rect.ts +45 -6
- package/types/bricks/RichText.ts +9 -5
- package/types/bricks/Rive.ts +21 -11
- package/types/bricks/Slideshow.ts +20 -10
- package/types/bricks/Svg.ts +8 -4
- package/types/bricks/Text.ts +9 -5
- package/types/bricks/TextInput.ts +23 -13
- package/types/bricks/Video.ts +11 -7
- package/types/bricks/VideoStreaming.ts +8 -4
- package/types/bricks/WebRtcStream.ts +7 -3
- package/types/bricks/WebView.ts +12 -8
- package/types/canvas.ts +4 -2
- package/types/common.ts +19 -12
- 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 +17 -11
- package/types/generators/Assistant.ts +69 -18
- package/types/generators/BleCentral.ts +31 -11
- package/types/generators/BlePeripheral.ts +11 -7
- package/types/generators/CanvasMap.ts +10 -6
- package/types/generators/CastlesPay.ts +15 -7
- package/types/generators/DataBank.ts +44 -9
- package/types/generators/File.ts +109 -30
- package/types/generators/GraphQl.ts +12 -6
- package/types/generators/Http.ts +33 -10
- package/types/generators/HttpServer.ts +23 -15
- package/types/generators/Information.ts +9 -5
- package/types/generators/Intent.ts +15 -5
- package/types/generators/Iterator.ts +15 -11
- package/types/generators/Keyboard.ts +27 -13
- package/types/generators/LlmAnthropicCompat.ts +33 -11
- package/types/generators/LlmAppleBuiltin.ts +25 -10
- package/types/generators/LlmGgml.ts +140 -31
- package/types/generators/LlmMediaTekNeuroPilot.ts +235 -0
- package/types/generators/LlmMlx.ts +227 -0
- package/types/generators/LlmOnnx.ts +34 -14
- package/types/generators/LlmOpenAiCompat.ts +47 -11
- package/types/generators/LlmQualcommAiEngine.ts +45 -13
- package/types/generators/Mcp.ts +375 -34
- package/types/generators/McpServer.ts +58 -19
- package/types/generators/MediaFlow.ts +38 -12
- package/types/generators/MqttBroker.ts +29 -11
- package/types/generators/MqttClient.ts +19 -9
- package/types/generators/Question.ts +13 -9
- package/types/generators/RealtimeTranscription.ts +108 -19
- package/types/generators/RerankerGgml.ts +43 -12
- package/types/generators/SerialPort.ts +18 -10
- package/types/generators/SoundPlayer.ts +10 -4
- package/types/generators/SoundRecorder.ts +24 -9
- package/types/generators/SpeechToTextGgml.ts +52 -18
- package/types/generators/SpeechToTextOnnx.ts +18 -11
- package/types/generators/SpeechToTextPlatform.ts +15 -7
- package/types/generators/SqLite.ts +20 -10
- package/types/generators/Step.ts +9 -5
- package/types/generators/SttAppleBuiltin.ts +22 -9
- package/types/generators/Tcp.ts +13 -9
- package/types/generators/TcpServer.ts +20 -14
- package/types/generators/TextToSpeechAppleBuiltin.ts +21 -8
- package/types/generators/TextToSpeechGgml.ts +29 -11
- package/types/generators/TextToSpeechOnnx.ts +19 -12
- package/types/generators/TextToSpeechOpenAiLike.ts +14 -8
- package/types/generators/ThermalPrinter.ts +13 -9
- package/types/generators/Tick.ts +11 -7
- package/types/generators/Udp.ts +17 -8
- package/types/generators/VadGgml.ts +51 -14
- package/types/generators/VadOnnx.ts +42 -12
- package/types/generators/VadTraditional.ts +28 -13
- package/types/generators/VectorStore.ts +33 -12
- package/types/generators/Watchdog.ts +19 -10
- package/types/generators/WebCrawler.ts +11 -7
- package/types/generators/WebRtc.ts +30 -16
- package/types/generators/WebSocket.ts +11 -7
- 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/utils/id.ts +4 -0
- 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/compile/index.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
/* eslint-disable no-underscore-dangle -- Uses __typename, __actionName, etc. for type system */
|
|
2
|
+
import camelCase from 'lodash/camelCase'
|
|
3
|
+
import upperFirst from 'lodash/upperFirst'
|
|
2
4
|
import snakeCase from 'lodash/snakeCase'
|
|
3
5
|
import omit from 'lodash/omit'
|
|
4
6
|
import { parse as parseAST } from 'acorn'
|
|
5
7
|
import type { ExportNamedDeclaration, FunctionDeclaration } from 'acorn'
|
|
6
8
|
import escodegen from 'escodegen'
|
|
9
|
+
import { makeId } from '../utils/id'
|
|
7
10
|
import { generateCalulationMap } from './util'
|
|
8
11
|
import { templateActionNameMap } from './action-name-map'
|
|
9
12
|
import { templateEventPropsMap } from '../utils/event-props'
|
|
@@ -34,6 +37,40 @@ import type {
|
|
|
34
37
|
TestVariable,
|
|
35
38
|
} from '../types'
|
|
36
39
|
|
|
40
|
+
const uuidPattern = '[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}'
|
|
41
|
+
|
|
42
|
+
const entryIdPatterns = {
|
|
43
|
+
SUBSPACE: new RegExp(`^SUBSPACE_${uuidPattern}$`),
|
|
44
|
+
CANVAS: new RegExp(`^CANVAS_${uuidPattern}$`),
|
|
45
|
+
BRICK: new RegExp(`^BRICK_${uuidPattern}$`),
|
|
46
|
+
GENERATOR: new RegExp(`^(GENERATOR|AUTO_GENERATOR)_${uuidPattern}$`),
|
|
47
|
+
ANIMATION: new RegExp(`^ANIMATION_${uuidPattern}$`),
|
|
48
|
+
PROPERTY_BANK_DATA_NODE: new RegExp(`^PROPERTY_BANK_DATA_NODE_${uuidPattern}$`),
|
|
49
|
+
PROPERTY_BANK_COMMAND_NODE: new RegExp(`^PROPERTY_BANK_COMMAND_NODE_${uuidPattern}$`),
|
|
50
|
+
PROPERTY_BANK_COMMAND_MAP: new RegExp(`^PROPERTY_BANK_COMMAND_MAP_${uuidPattern}$`),
|
|
51
|
+
BRICK_STATE_GROUP: new RegExp(`^BRICK_STATE_GROUP_${uuidPattern}$`),
|
|
52
|
+
TEST: new RegExp(`^TEST_${uuidPattern}$`),
|
|
53
|
+
TEST_CASE: new RegExp(`^TEST_CASE_${uuidPattern}$`),
|
|
54
|
+
TEST_VAR: new RegExp(`^TEST_VAR_${uuidPattern}$`),
|
|
55
|
+
AUTOMATION_MAP: /^AUTOMATION_MAP_.*/,
|
|
56
|
+
} as const
|
|
57
|
+
|
|
58
|
+
type EntryIdPatternKey = keyof typeof entryIdPatterns
|
|
59
|
+
|
|
60
|
+
const assertEntryId = (
|
|
61
|
+
id: unknown,
|
|
62
|
+
patternKey: EntryIdPatternKey,
|
|
63
|
+
errorReference: string = '',
|
|
64
|
+
): string => {
|
|
65
|
+
const pattern = entryIdPatterns[patternKey]
|
|
66
|
+
if (typeof id !== 'string' || !pattern.test(id)) {
|
|
67
|
+
throw new Error(
|
|
68
|
+
`Invalid ${patternKey} id${errorReference ? ` ${errorReference}` : ''}: ${String(id)}`,
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
return id
|
|
72
|
+
}
|
|
73
|
+
|
|
37
74
|
const compileProperty = (property, errorReference: string, result = {}) => {
|
|
38
75
|
if (Array.isArray(property)) {
|
|
39
76
|
return property.map((p) => compileProperty(p, errorReference))
|
|
@@ -57,14 +94,39 @@ const compileProperty = (property, errorReference: string, result = {}) => {
|
|
|
57
94
|
return property
|
|
58
95
|
}
|
|
59
96
|
|
|
97
|
+
const compileScriptCalculationCode = (code = '') => {
|
|
98
|
+
try {
|
|
99
|
+
const program = parseAST(code, { sourceType: 'module', ecmaVersion: 2020 })
|
|
100
|
+
// export function main() { ... }
|
|
101
|
+
const declarationBody = (
|
|
102
|
+
(program.body[0] as ExportNamedDeclaration).declaration as FunctionDeclaration
|
|
103
|
+
)?.body
|
|
104
|
+
return escodegen.generate(declarationBody, {
|
|
105
|
+
format: {
|
|
106
|
+
indent: { style: ' ' },
|
|
107
|
+
semicolons: false,
|
|
108
|
+
},
|
|
109
|
+
comment: true,
|
|
110
|
+
})
|
|
111
|
+
} catch {
|
|
112
|
+
return code || ''
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const getTemplateName = (key: string) =>
|
|
117
|
+
upperFirst(camelCase(key.replace(/^(BRICK|GENERATOR)_/, '')))
|
|
118
|
+
|
|
60
119
|
const compileEventActionValue = (templateKey, eventKey, value, errorReference) => {
|
|
61
|
-
const tmplEventProperties = templateEventPropsMap[templateKey]
|
|
120
|
+
const tmplEventProperties = templateEventPropsMap[getTemplateName(templateKey)]
|
|
62
121
|
const props = tmplEventProperties?.[eventKey]
|
|
63
122
|
if (!props) return compileProperty(value, errorReference)
|
|
64
|
-
if (
|
|
65
|
-
|
|
123
|
+
if (typeof value === 'string' && value in props) {
|
|
124
|
+
const expectedType = props[value]
|
|
125
|
+
if (expectedType) return value
|
|
126
|
+
}
|
|
127
|
+
if (typeof value === 'string' && /^(BRICK|GENERATOR)_/.test(value)) {
|
|
66
128
|
console.warn(
|
|
67
|
-
`[Warning]
|
|
129
|
+
`[Warning] Event property "${value}" is not compatible with event "${eventKey}" of ${templateKey} ${errorReference}`,
|
|
68
130
|
)
|
|
69
131
|
}
|
|
70
132
|
return compileProperty(value, errorReference)
|
|
@@ -79,8 +141,9 @@ const compileOutlets = (
|
|
|
79
141
|
errorReference: string,
|
|
80
142
|
) =>
|
|
81
143
|
Object.entries(outlets).reduce((acc, [key, data]) => {
|
|
82
|
-
|
|
83
|
-
|
|
144
|
+
const dataInstance = data?.()
|
|
145
|
+
const dataId = assertEntryId(dataInstance?.id, 'PROPERTY_BANK_DATA_NODE', errorReference)
|
|
146
|
+
acc[convertOutletKey(templateKey, key)] = dataId
|
|
84
147
|
return acc
|
|
85
148
|
}, {})
|
|
86
149
|
|
|
@@ -95,9 +158,9 @@ const compileAnimations = (
|
|
|
95
158
|
errorReference: string,
|
|
96
159
|
) =>
|
|
97
160
|
Object.entries(animations).reduce((acc, [key, animation]) => {
|
|
98
|
-
|
|
161
|
+
const animationId = assertEntryId(animation?.id, 'ANIMATION', errorReference)
|
|
99
162
|
acc[convertEventKey(basicAnimationEvents.includes(key) ? 'BRICK' : templateKey, key)] =
|
|
100
|
-
`ANIMATION#${
|
|
163
|
+
`ANIMATION#${animationId}`
|
|
101
164
|
return acc
|
|
102
165
|
}, {})
|
|
103
166
|
|
|
@@ -134,7 +197,7 @@ const compileEvents = (
|
|
|
134
197
|
if (!handlerKey) throw new Error(`Invalid handler: ${handler} ${errorReference}`)
|
|
135
198
|
|
|
136
199
|
const parameterList: Array<object> = []
|
|
137
|
-
if (Object.
|
|
200
|
+
if (Object.prototype.hasOwnProperty.call(action, 'params')) {
|
|
138
201
|
const actionDef = action as ActionWithParams
|
|
139
202
|
;(actionDef.params || []).forEach(({ input, value, mapping }) => {
|
|
140
203
|
const param = {
|
|
@@ -147,7 +210,7 @@ const compileEvents = (
|
|
|
147
210
|
if (mapping) param[camelCase ? 'resultDataMapping' : 'result_data_mapping'] = true
|
|
148
211
|
parameterList.push(param)
|
|
149
212
|
})
|
|
150
|
-
} else if (Object.
|
|
213
|
+
} else if (Object.prototype.hasOwnProperty.call(action, 'dataParams')) {
|
|
151
214
|
const actionDef = action as ActionWithDataParams
|
|
152
215
|
;(actionDef.dataParams || []).forEach(({ input, value, mapping }) => {
|
|
153
216
|
if (!input) return
|
|
@@ -231,6 +294,7 @@ const compileApplicationSettings = (settings: Application['settings']) => ({
|
|
|
231
294
|
use_gemini_api_key_system_data: settings.ai.useGeminiApiKeySystemData,
|
|
232
295
|
}
|
|
233
296
|
: undefined,
|
|
297
|
+
hide_short_refs: settings?.hideShortRefs,
|
|
234
298
|
})
|
|
235
299
|
|
|
236
300
|
const animationTypeMap = {
|
|
@@ -299,10 +363,10 @@ const compileRemoteUpdate = (remoteUpdate: Data['remoteUpdate']) => {
|
|
|
299
363
|
}
|
|
300
364
|
|
|
301
365
|
const compileModule = (subspace: Subspace) => {
|
|
302
|
-
if (!subspace.module) return {}
|
|
366
|
+
if (!subspace.module?.id) return {}
|
|
303
367
|
return {
|
|
304
368
|
module: {
|
|
305
|
-
link:
|
|
369
|
+
link: subspace.module.link ?? false,
|
|
306
370
|
id: subspace.module.id,
|
|
307
371
|
version: subspace.module.version,
|
|
308
372
|
},
|
|
@@ -350,20 +414,28 @@ function compileRunArray(run: unknown[]): unknown[] {
|
|
|
350
414
|
const compileTestCase = (testCase: TestCase) => ({
|
|
351
415
|
id: testCase.id,
|
|
352
416
|
name: testCase.name,
|
|
417
|
+
hide_short_ref: testCase.hideShortRef,
|
|
353
418
|
run: compileRunArray(testCase.run),
|
|
354
419
|
exit_on_failed: testCase.exit_on_failed,
|
|
355
420
|
commented: testCase.commented,
|
|
356
421
|
pre_delay: testCase.pre_delay,
|
|
357
422
|
post_delay: testCase.post_delay,
|
|
358
423
|
post_delay_rule: testCase.post_delay_rule,
|
|
359
|
-
jump_cond: testCase.jump_cond.map((cond) =>
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
424
|
+
jump_cond: testCase.jump_cond.map((cond) => {
|
|
425
|
+
if (cond.jump_to == null) {
|
|
426
|
+
console.warn(
|
|
427
|
+
`[Warning] jump_cond is missing jump_to in test case "${testCase.name}" (${testCase.id})`,
|
|
428
|
+
)
|
|
429
|
+
}
|
|
430
|
+
return {
|
|
431
|
+
type: cond.type,
|
|
432
|
+
status: cond.status,
|
|
433
|
+
variable: cond.variable,
|
|
434
|
+
operator: cond.operator,
|
|
435
|
+
value: cond.value,
|
|
436
|
+
jump_to: cond.jump_to,
|
|
437
|
+
}
|
|
438
|
+
}),
|
|
367
439
|
})
|
|
368
440
|
|
|
369
441
|
/**
|
|
@@ -381,60 +453,158 @@ const compileTestVariable = (variable: TestVariable) => ({
|
|
|
381
453
|
*/
|
|
382
454
|
const arrayToIdMap = <T extends { id: string }, R>(
|
|
383
455
|
items: T[],
|
|
384
|
-
transform: (item: T) => R,
|
|
385
|
-
|
|
456
|
+
transform: (item: T, index: number) => R,
|
|
457
|
+
options: {
|
|
458
|
+
patternKey: EntryIdPatternKey
|
|
459
|
+
getErrorReference: (item: T, index: number) => string
|
|
460
|
+
},
|
|
461
|
+
): Record<string, R> =>
|
|
462
|
+
Object.fromEntries(
|
|
463
|
+
items.map((item, index) => {
|
|
464
|
+
const itemId = assertEntryId(
|
|
465
|
+
item.id,
|
|
466
|
+
options.patternKey,
|
|
467
|
+
options.getErrorReference(item, index),
|
|
468
|
+
)
|
|
469
|
+
return [itemId, transform(item, index)]
|
|
470
|
+
}),
|
|
471
|
+
)
|
|
386
472
|
|
|
387
473
|
/**
|
|
388
474
|
* Compile typed AutomationTest to raw format
|
|
389
475
|
*/
|
|
390
|
-
const compileAutomationTest = (
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
476
|
+
const compileAutomationTest = (
|
|
477
|
+
test: AutomationTest,
|
|
478
|
+
options: { mapId: string; testIndex: number },
|
|
479
|
+
) => {
|
|
480
|
+
const testId = assertEntryId(
|
|
481
|
+
test.id,
|
|
482
|
+
'TEST',
|
|
483
|
+
`(automation map: ${options.mapId}, test index: ${options.testIndex})`,
|
|
484
|
+
)
|
|
485
|
+
|
|
486
|
+
return {
|
|
487
|
+
id: testId,
|
|
488
|
+
title: test.title,
|
|
489
|
+
hide_short_ref: test.hideShortRef,
|
|
490
|
+
timeout: test.timeout,
|
|
491
|
+
trigger_type: test.trigger_type,
|
|
492
|
+
cron: test.cron,
|
|
493
|
+
skip_trigger_type_check: test.skip_trigger_type_check,
|
|
494
|
+
local_sync: test.local_sync,
|
|
495
|
+
meta: test.meta,
|
|
496
|
+
case_map: arrayToIdMap(test.cases, compileTestCase, {
|
|
497
|
+
patternKey: 'TEST_CASE',
|
|
498
|
+
getErrorReference: (_, index) =>
|
|
499
|
+
`(automation map: ${options.mapId}, test: ${testId}, case index: ${index})`,
|
|
500
|
+
}),
|
|
501
|
+
var_map: arrayToIdMap(test.variables, compileTestVariable, {
|
|
502
|
+
patternKey: 'TEST_VAR',
|
|
503
|
+
getErrorReference: (_, index) =>
|
|
504
|
+
`(automation map: ${options.mapId}, test: ${testId}, variable index: ${index})`,
|
|
505
|
+
}),
|
|
506
|
+
}
|
|
507
|
+
}
|
|
402
508
|
|
|
403
509
|
/**
|
|
404
510
|
* Compile typed AutomationTestMap to raw format
|
|
405
511
|
*/
|
|
406
|
-
const compileAutomationTestMap = (testMap: AutomationTestMap) =>
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
512
|
+
const compileAutomationTestMap = (testMap: AutomationTestMap, mapId: string) => {
|
|
513
|
+
assertEntryId(testMap.id, 'AUTOMATION_MAP', `(automation map id field: ${mapId})`)
|
|
514
|
+
|
|
515
|
+
return {
|
|
516
|
+
title: testMap.title,
|
|
517
|
+
hide_short_ref: testMap.hideShortRef,
|
|
518
|
+
createdAt: testMap.createdAt,
|
|
519
|
+
map: arrayToIdMap(
|
|
520
|
+
testMap.tests,
|
|
521
|
+
(test, index) => compileAutomationTest(test, { mapId, testIndex: index }),
|
|
522
|
+
{
|
|
523
|
+
patternKey: 'TEST',
|
|
524
|
+
getErrorReference: (_, index) => `(automation map: ${mapId}, test index: ${index})`,
|
|
525
|
+
},
|
|
526
|
+
),
|
|
527
|
+
}
|
|
528
|
+
}
|
|
411
529
|
|
|
412
530
|
/**
|
|
413
531
|
* Compile typed AutomationMap to raw automation_map format
|
|
414
532
|
*/
|
|
415
533
|
const compileAutomation = (automationMap: AutomationMap) =>
|
|
416
534
|
Object.fromEntries(
|
|
417
|
-
Object.entries(automationMap).map(([mapId, testMap]) =>
|
|
418
|
-
mapId,
|
|
419
|
-
compileAutomationTestMap(testMap)
|
|
420
|
-
|
|
535
|
+
Object.entries(automationMap).map(([mapId, testMap]) => {
|
|
536
|
+
const automationMapId = assertEntryId(mapId, 'AUTOMATION_MAP', '(automation map key)')
|
|
537
|
+
return [automationMapId, compileAutomationTestMap(testMap, automationMapId)]
|
|
538
|
+
}),
|
|
421
539
|
)
|
|
422
540
|
|
|
423
541
|
export const compile = async (app: Application) => {
|
|
424
542
|
await new Promise((resolve) => setImmediate(resolve, 0))
|
|
425
543
|
const timestamp = Date.now()
|
|
544
|
+
// Pre-index subspace ids so the canvas-item validation below stays O(1).
|
|
545
|
+
const subspaceIdSet = new Set(app.subspaces.map((s) => s.id))
|
|
426
546
|
const config = {
|
|
427
547
|
title: `${app.name || 'Unknown'}(${timestamp})`,
|
|
428
|
-
subspace_map: app.subspaces.reduce((subspaceMap, subspace) => {
|
|
429
|
-
|
|
548
|
+
subspace_map: app.subspaces.reduce((subspaceMap, subspace, subspaceIndex) => {
|
|
549
|
+
const subspaceId = assertEntryId(
|
|
550
|
+
subspace.id,
|
|
551
|
+
'SUBSPACE',
|
|
552
|
+
`(subspace index: ${subspaceIndex})`,
|
|
553
|
+
)
|
|
554
|
+
|
|
555
|
+
// Linked module subspaces reference external content — only include
|
|
556
|
+
// module metadata, not local canvas/brick/data compilation.
|
|
557
|
+
// Include a placeholder root canvas so the config passes schema
|
|
558
|
+
// validation (root_canvas_id is required before the conditional
|
|
559
|
+
// schema fix is published).
|
|
560
|
+
if (subspace.module?.link) {
|
|
561
|
+
const placeholderCanvasId = makeId('canvas')
|
|
562
|
+
subspaceMap[subspaceId] = {
|
|
563
|
+
title: subspace.title,
|
|
564
|
+
description: subspace.description,
|
|
565
|
+
unused: subspace.unused,
|
|
566
|
+
portal: subspace.portal,
|
|
567
|
+
layout: {
|
|
568
|
+
width: subspace.layout?.width,
|
|
569
|
+
height: subspace.layout?.height,
|
|
570
|
+
resize_mode: subspace.layout?.resizeMode,
|
|
571
|
+
},
|
|
572
|
+
root_canvas_id: placeholderCanvasId,
|
|
573
|
+
property_bank_map: {},
|
|
574
|
+
brick_map: {},
|
|
575
|
+
generator_map: {},
|
|
576
|
+
animation_map: {},
|
|
577
|
+
canvas_map: {
|
|
578
|
+
[placeholderCanvasId]: { item_list: [] },
|
|
579
|
+
},
|
|
580
|
+
...compileModule(subspace),
|
|
581
|
+
}
|
|
582
|
+
return subspaceMap
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
const rootCanvasId = assertEntryId(
|
|
586
|
+
subspace.rootCanvas?.id,
|
|
587
|
+
'CANVAS',
|
|
588
|
+
`(subspace: ${subspaceId}, root canvas)`,
|
|
589
|
+
)
|
|
590
|
+
|
|
591
|
+
subspaceMap[subspaceId] = {
|
|
430
592
|
title: subspace.title,
|
|
431
593
|
description: subspace.description,
|
|
594
|
+
hide_short_ref: subspace.hideShortRef,
|
|
595
|
+
unused: subspace.unused,
|
|
596
|
+
portal: subspace.portal,
|
|
432
597
|
_expanded: subspace.unexpanded
|
|
433
598
|
? {
|
|
434
599
|
brick: !subspace.unexpanded.brick,
|
|
435
600
|
generator: !subspace.unexpanded.generator,
|
|
436
|
-
canvas: subspace.unexpanded.canvas?.reduce((acc, canvas) => {
|
|
437
|
-
|
|
601
|
+
canvas: subspace.unexpanded.canvas?.reduce((acc, canvas, canvasIndex) => {
|
|
602
|
+
const unexpandedCanvasId = assertEntryId(
|
|
603
|
+
canvas?.id,
|
|
604
|
+
'CANVAS',
|
|
605
|
+
`(subspace: ${subspaceId}, unexpanded canvas index: ${canvasIndex})`,
|
|
606
|
+
)
|
|
607
|
+
acc[unexpandedCanvasId] = !canvas?.id
|
|
438
608
|
return acc
|
|
439
609
|
}, {}),
|
|
440
610
|
property_bank: !subspace.unexpanded.data,
|
|
@@ -451,32 +621,42 @@ export const compile = async (app: Application) => {
|
|
|
451
621
|
change_canvas: subspace.localSyncChangeCanvas,
|
|
452
622
|
}
|
|
453
623
|
: undefined,
|
|
454
|
-
animation_map: subspace.animations.reduce((map, animation) => {
|
|
624
|
+
animation_map: subspace.animations.reduce((map, animation, animationIndex) => {
|
|
625
|
+
const animationId = assertEntryId(
|
|
626
|
+
animation?.id,
|
|
627
|
+
'ANIMATION',
|
|
628
|
+
`(animation index: ${animationIndex}, subspace: ${subspaceId})`,
|
|
629
|
+
)
|
|
630
|
+
|
|
455
631
|
if (animation.__typename === 'Animation') {
|
|
456
632
|
const animationDef = animation as AnimationDef
|
|
457
|
-
map[
|
|
633
|
+
map[animationId] = {
|
|
634
|
+
alias: animationDef.alias,
|
|
458
635
|
title: animationDef.title,
|
|
459
636
|
description: animationDef.description,
|
|
637
|
+
hide_short_ref: animationDef.hideShortRef,
|
|
460
638
|
animationRunType: animationDef.runType,
|
|
461
639
|
property: animationDef.property,
|
|
462
640
|
type: animationTypeMap[animationDef.config.__type],
|
|
463
641
|
config: compileProperty(
|
|
464
642
|
omit(animationDef.config, '__type'),
|
|
465
|
-
`(animation: ${
|
|
643
|
+
`(animation: ${animationId}, subspace ${subspaceId})`,
|
|
466
644
|
),
|
|
467
645
|
}
|
|
468
646
|
} else if (animation.__typename === 'AnimationCompose') {
|
|
469
647
|
const animationDef = animation as AnimationComposeDef
|
|
470
|
-
map[
|
|
648
|
+
map[animationId] = {
|
|
649
|
+
alias: animationDef.alias,
|
|
471
650
|
title: animationDef.title,
|
|
472
651
|
description: animationDef.description,
|
|
652
|
+
hide_short_ref: animationDef.hideShortRef,
|
|
473
653
|
animationRunType: animationDef.runType,
|
|
474
654
|
compose_type: animationDef.composeType,
|
|
475
655
|
item_list: animationDef.items.map((item, index) => {
|
|
476
656
|
const innerAnimation = item()
|
|
477
657
|
if (!innerAnimation?.id)
|
|
478
658
|
throw new Error(
|
|
479
|
-
`Invalid animation index: ${index} (animation: ${innerAnimation.id}, subspace ${
|
|
659
|
+
`Invalid animation index: ${index} (animation: ${innerAnimation.id}, subspace ${subspaceId})`,
|
|
480
660
|
)
|
|
481
661
|
return { animation_id: innerAnimation.id }
|
|
482
662
|
}),
|
|
@@ -484,10 +664,15 @@ export const compile = async (app: Application) => {
|
|
|
484
664
|
}
|
|
485
665
|
return map
|
|
486
666
|
}, {}),
|
|
487
|
-
brick_map: subspace.bricks.reduce((map, brick) => {
|
|
667
|
+
brick_map: subspace.bricks.reduce((map, brick, brickIndex) => {
|
|
668
|
+
const brickId = assertEntryId(
|
|
669
|
+
brick.id,
|
|
670
|
+
'BRICK',
|
|
671
|
+
`(brick index: ${brickIndex}, subspace: ${subspaceId})`,
|
|
672
|
+
)
|
|
488
673
|
const property = compileProperty(
|
|
489
674
|
brick.property || {},
|
|
490
|
-
`(brick: ${
|
|
675
|
+
`(brick: ${brickId}, subspace ${subspaceId})`,
|
|
491
676
|
)
|
|
492
677
|
if (brick.templateKey === 'BRICK_ITEMS') {
|
|
493
678
|
const brickItems = brick as BrickItems
|
|
@@ -499,25 +684,31 @@ export const compile = async (app: Application) => {
|
|
|
499
684
|
frame: itemBrick.frame,
|
|
500
685
|
property: compileProperty(
|
|
501
686
|
itemBrick.property,
|
|
502
|
-
`(brick: ${
|
|
687
|
+
`(brick: ${brickId}, ${key}: ${index}, subspace ${subspaceId})`,
|
|
503
688
|
),
|
|
504
689
|
propertyMapping: itemBrick.propertyMapping,
|
|
505
690
|
animation: compileAnimations(
|
|
506
691
|
itemBrick.templateKey,
|
|
507
692
|
itemBrick.animation || {},
|
|
508
|
-
`(brick: ${
|
|
693
|
+
`(brick: ${brickId}, ${key}: ${index}, subspace ${subspaceId})`,
|
|
509
694
|
),
|
|
510
695
|
outlet: compileOutlets(
|
|
511
696
|
itemBrick.templateKey,
|
|
512
697
|
itemBrick.outlets || {},
|
|
513
|
-
`(brick: ${
|
|
698
|
+
`(brick: ${brickId}, ${key}: ${index}, subspace ${subspaceId})`,
|
|
514
699
|
),
|
|
515
700
|
eventMap: compileEvents(itemBrick.templateKey, itemBrick.eventMap || {}, {
|
|
516
701
|
camelCase: true,
|
|
517
|
-
errorReference: `(brick: ${
|
|
702
|
+
errorReference: `(brick: ${brickId}, ${key}: ${index}, subspace ${subspaceId})`,
|
|
518
703
|
}),
|
|
519
|
-
stateGroup: itemBrick.stateGroup.reduce((acc, stateGroup) => {
|
|
520
|
-
|
|
704
|
+
stateGroup: itemBrick.stateGroup.reduce((acc, stateGroup, stateGroupIndex) => {
|
|
705
|
+
const stateGroupId = assertEntryId(
|
|
706
|
+
stateGroup.id,
|
|
707
|
+
'BRICK_STATE_GROUP',
|
|
708
|
+
`(brick: ${brickId}, ${key}: ${index}, switch index: ${stateGroupIndex}, subspace ${subspaceId})`,
|
|
709
|
+
)
|
|
710
|
+
|
|
711
|
+
acc[stateGroupId] = {
|
|
521
712
|
title: stateGroup.title,
|
|
522
713
|
description: stateGroup.description,
|
|
523
714
|
override: stateGroup.override,
|
|
@@ -526,35 +717,40 @@ export const compile = async (app: Application) => {
|
|
|
526
717
|
conds: compileSwitchConds(
|
|
527
718
|
itemBrick.templateKey,
|
|
528
719
|
stateGroup.conds || [],
|
|
529
|
-
`(brick: ${
|
|
720
|
+
`(brick: ${brickId}, ${key}: ${index}, switch: ${stateGroupId}, subspace ${subspaceId})`,
|
|
530
721
|
),
|
|
531
722
|
property: compileProperty(
|
|
532
723
|
stateGroup.property,
|
|
533
|
-
`(brick: ${
|
|
724
|
+
`(brick: ${brickId}, ${key}: ${index}, switch: ${stateGroupId}, subspace ${subspaceId})`,
|
|
534
725
|
),
|
|
535
726
|
animation: compileAnimations(
|
|
536
727
|
itemBrick.templateKey,
|
|
537
728
|
stateGroup.animation || {},
|
|
538
|
-
`(brick: ${
|
|
729
|
+
`(brick: ${brickId}, ${key}: ${index}, switch: ${stateGroupId}, subspace ${subspaceId})`,
|
|
539
730
|
),
|
|
540
731
|
outlet: compileOutlets(
|
|
541
732
|
itemBrick.templateKey,
|
|
542
733
|
stateGroup.outlets || {},
|
|
543
|
-
`(brick: ${
|
|
734
|
+
`(brick: ${brickId}, ${key}: ${index}, switch: ${stateGroupId}, subspace ${subspaceId})`,
|
|
544
735
|
),
|
|
545
736
|
eventMap: compileEvents(itemBrick.templateKey, stateGroup.eventMap || {}, {
|
|
546
737
|
camelCase: true,
|
|
547
|
-
errorReference: `(brick: ${
|
|
738
|
+
errorReference: `(brick: ${brickId}, ${key}: ${index}, switch: ${stateGroupId}, subspace ${subspaceId})`,
|
|
548
739
|
}),
|
|
549
740
|
}
|
|
550
741
|
return acc
|
|
551
742
|
}, {}),
|
|
743
|
+
show: itemBrick.show,
|
|
744
|
+
pressToOpenDetail: itemBrick.pressToOpenDetail,
|
|
745
|
+
pressToBackList: itemBrick.pressToBackList,
|
|
552
746
|
})
|
|
553
747
|
if (Array.isArray(brickItems.brickList)) {
|
|
554
748
|
const brickList = (brickItems.brickList || []).map((item, index) =>
|
|
555
749
|
buildList(item, index, 'brickList'),
|
|
556
750
|
)
|
|
557
751
|
property.brickList = brickList
|
|
752
|
+
} else if (!brickItems.brickList) {
|
|
753
|
+
property.brickList = []
|
|
558
754
|
} else {
|
|
559
755
|
// Not supported Data for brickList
|
|
560
756
|
throw new TypeError('Not supported Data for brickList directly')
|
|
@@ -564,32 +760,42 @@ export const compile = async (app: Application) => {
|
|
|
564
760
|
buildList(item, index, 'brickDetails'),
|
|
565
761
|
)
|
|
566
762
|
property.brickDetails = brickDetails
|
|
763
|
+
} else if (!brickItems.brickDetails) {
|
|
764
|
+
property.brickDetails = []
|
|
567
765
|
} else {
|
|
568
766
|
// Not supported Data for brickList
|
|
569
767
|
throw new TypeError('Not supported Data for brickList directly')
|
|
570
768
|
}
|
|
571
769
|
}
|
|
572
|
-
map[
|
|
770
|
+
map[brickId] = {
|
|
573
771
|
template_key: brick.templateKey,
|
|
772
|
+
alias: brick.alias,
|
|
574
773
|
title: brick.title,
|
|
575
774
|
description: brick.description,
|
|
775
|
+
hide_short_ref: brick.hideShortRef,
|
|
576
776
|
property,
|
|
577
777
|
animation: compileAnimations(
|
|
578
778
|
brick.templateKey,
|
|
579
779
|
brick.animation || {},
|
|
580
|
-
`(brick: ${
|
|
780
|
+
`(brick: ${brickId}, subspace ${subspaceId})`,
|
|
581
781
|
),
|
|
582
782
|
event_map: compileEvents(brick.templateKey, brick.events || {}, {
|
|
583
783
|
camelCase: false,
|
|
584
|
-
errorReference: `(brick: ${
|
|
784
|
+
errorReference: `(brick: ${brickId}, subspace ${subspaceId})`,
|
|
585
785
|
}),
|
|
586
786
|
outlet: compileOutlets(
|
|
587
787
|
brick.templateKey,
|
|
588
788
|
brick.outlets || {},
|
|
589
|
-
`(brick: ${
|
|
789
|
+
`(brick: ${brickId}, subspace ${subspaceId})`,
|
|
590
790
|
),
|
|
591
|
-
state_group: brick.switches?.reduce((acc, switchCase) => {
|
|
592
|
-
|
|
791
|
+
state_group: brick.switches?.reduce((acc, switchCase, switchIndex) => {
|
|
792
|
+
const switchId = assertEntryId(
|
|
793
|
+
switchCase.id,
|
|
794
|
+
'BRICK_STATE_GROUP',
|
|
795
|
+
`(brick: ${brickId}, switch index: ${switchIndex}, subspace ${subspaceId})`,
|
|
796
|
+
)
|
|
797
|
+
|
|
798
|
+
acc[switchId] = {
|
|
593
799
|
title: switchCase.title,
|
|
594
800
|
description: switchCase.description,
|
|
595
801
|
break: switchCase.break,
|
|
@@ -598,25 +804,25 @@ export const compile = async (app: Application) => {
|
|
|
598
804
|
conds: compileSwitchConds(
|
|
599
805
|
brick.templateKey,
|
|
600
806
|
switchCase.conds || [],
|
|
601
|
-
`(brick: ${
|
|
807
|
+
`(brick: ${brickId}, switch: ${switchId}, subspace ${subspaceId})`,
|
|
602
808
|
),
|
|
603
809
|
property: compileProperty(
|
|
604
810
|
switchCase.property,
|
|
605
|
-
`(brick: ${
|
|
811
|
+
`(brick: ${brickId}, switch: ${switchId}, subspace ${subspaceId})`,
|
|
606
812
|
),
|
|
607
813
|
outlet: compileOutlets(
|
|
608
814
|
brick.templateKey,
|
|
609
815
|
switchCase.outlets || {},
|
|
610
|
-
`(brick: ${
|
|
816
|
+
`(brick: ${brickId}, switch: ${switchId}, subspace ${subspaceId})`,
|
|
611
817
|
),
|
|
612
818
|
event_map: compileEvents(brick.templateKey, switchCase.events || {}, {
|
|
613
819
|
camelCase: false,
|
|
614
|
-
errorReference: `(brick: ${
|
|
820
|
+
errorReference: `(brick: ${brickId}, switch: ${switchId}, subspace ${subspaceId})`,
|
|
615
821
|
}),
|
|
616
822
|
animation: compileAnimations(
|
|
617
823
|
brick.templateKey,
|
|
618
824
|
switchCase.animation || {},
|
|
619
|
-
`(brick: ${
|
|
825
|
+
`(brick: ${brickId}, switch: ${switchId}, subspace ${subspaceId})`,
|
|
620
826
|
),
|
|
621
827
|
}
|
|
622
828
|
return acc
|
|
@@ -624,21 +830,35 @@ export const compile = async (app: Application) => {
|
|
|
624
830
|
}
|
|
625
831
|
return map
|
|
626
832
|
}, {}),
|
|
627
|
-
root_canvas_id:
|
|
628
|
-
canvas_map: subspace.canvases.reduce((map, canvas) => {
|
|
629
|
-
|
|
833
|
+
root_canvas_id: rootCanvasId,
|
|
834
|
+
canvas_map: subspace.canvases.reduce((map, canvas, canvasIndex) => {
|
|
835
|
+
const canvasId = assertEntryId(
|
|
836
|
+
canvas.id,
|
|
837
|
+
'CANVAS',
|
|
838
|
+
`(canvas index: ${canvasIndex}, subspace: ${subspaceId})`,
|
|
839
|
+
)
|
|
840
|
+
|
|
841
|
+
map[canvasId] = {
|
|
842
|
+
alias: canvas.alias,
|
|
630
843
|
title: canvas.title,
|
|
631
844
|
description: canvas.description,
|
|
845
|
+
hide_short_ref: canvas.hideShortRef,
|
|
632
846
|
property: compileProperty(
|
|
633
847
|
canvas.property,
|
|
634
|
-
`(canvas: ${
|
|
848
|
+
`(canvas: ${canvasId}, subspace ${subspaceId})`,
|
|
635
849
|
),
|
|
636
850
|
event_map: compileEvents('CANVAS', canvas.events || {}, {
|
|
637
851
|
camelCase: false,
|
|
638
|
-
errorReference: `(canvas: ${
|
|
852
|
+
errorReference: `(canvas: ${canvasId}, subspace ${subspaceId})`,
|
|
639
853
|
}),
|
|
640
|
-
state_group: canvas.switches?.reduce((acc, switchCase) => {
|
|
641
|
-
|
|
854
|
+
state_group: canvas.switches?.reduce((acc, switchCase, switchIndex) => {
|
|
855
|
+
const switchId = assertEntryId(
|
|
856
|
+
switchCase.id,
|
|
857
|
+
'BRICK_STATE_GROUP',
|
|
858
|
+
`(canvas: ${canvasId}, switch index: ${switchIndex}, subspace ${subspaceId})`,
|
|
859
|
+
)
|
|
860
|
+
|
|
861
|
+
acc[switchId] = {
|
|
642
862
|
title: switchCase.title,
|
|
643
863
|
description: switchCase.description,
|
|
644
864
|
break: switchCase.break,
|
|
@@ -647,20 +867,20 @@ export const compile = async (app: Application) => {
|
|
|
647
867
|
conds: compileSwitchConds(
|
|
648
868
|
'CANVAS',
|
|
649
869
|
switchCase.conds || [],
|
|
650
|
-
`(canvas: ${
|
|
870
|
+
`(canvas: ${canvasId}, switch: ${switchId}, subspace ${subspaceId})`,
|
|
651
871
|
),
|
|
652
872
|
property: compileProperty(
|
|
653
873
|
switchCase.property,
|
|
654
|
-
`(canvas: ${
|
|
874
|
+
`(canvas: ${canvasId}, switch: ${switchId}, subspace ${subspaceId})`,
|
|
655
875
|
),
|
|
656
876
|
event_map: compileEvents('CANVAS', switchCase.events || {}, {
|
|
657
877
|
camelCase: false,
|
|
658
|
-
errorReference: `(canvas: ${
|
|
878
|
+
errorReference: `(canvas: ${canvasId}, switch: ${switchId}, subspace ${subspaceId})`,
|
|
659
879
|
}),
|
|
660
880
|
animation: compileAnimations(
|
|
661
881
|
'CANVAS',
|
|
662
882
|
switchCase.animation || {},
|
|
663
|
-
`(canvas: ${
|
|
883
|
+
`(canvas: ${canvasId}, switch: ${switchId}, subspace ${subspaceId})`,
|
|
664
884
|
),
|
|
665
885
|
}
|
|
666
886
|
return acc
|
|
@@ -671,16 +891,16 @@ export const compile = async (app: Application) => {
|
|
|
671
891
|
const brick = (item.item as () => Brick)()
|
|
672
892
|
if (!brick?.id)
|
|
673
893
|
throw new Error(
|
|
674
|
-
`Invalid canvas item index: ${index}, brick not found (canvas: ${
|
|
894
|
+
`Invalid canvas item index: ${index}, brick not found (canvas: ${canvasId}, subspace ${subspaceId})`,
|
|
675
895
|
)
|
|
676
896
|
itemPayload = { brick_id: brick.id }
|
|
677
897
|
} else {
|
|
678
|
-
const
|
|
679
|
-
if (!
|
|
898
|
+
const targetSubspaceId = item.item
|
|
899
|
+
if (!subspaceIdSet.has(targetSubspaceId))
|
|
680
900
|
throw new Error(
|
|
681
|
-
`Invalid canvas item index: ${index}, subspace not found (canvas: ${
|
|
901
|
+
`Invalid canvas item index: ${index}, subspace not found (canvas: ${canvasId}, subspace ${subspaceId})`,
|
|
682
902
|
)
|
|
683
|
-
itemPayload = { subspace_id:
|
|
903
|
+
itemPayload = { subspace_id: targetSubspaceId }
|
|
684
904
|
}
|
|
685
905
|
return {
|
|
686
906
|
type: typeof item.item === 'function' ? 'brick' : 'subspace',
|
|
@@ -692,11 +912,19 @@ export const compile = async (app: Application) => {
|
|
|
692
912
|
}
|
|
693
913
|
return map
|
|
694
914
|
}, {}),
|
|
695
|
-
generator_map: subspace.generators.reduce((map, generator) => {
|
|
696
|
-
|
|
915
|
+
generator_map: subspace.generators.reduce((map, generator, generatorIndex) => {
|
|
916
|
+
const generatorId = assertEntryId(
|
|
917
|
+
generator.id,
|
|
918
|
+
'GENERATOR',
|
|
919
|
+
`(generator index: ${generatorIndex}, subspace: ${subspaceId})`,
|
|
920
|
+
)
|
|
921
|
+
|
|
922
|
+
map[generatorId] = {
|
|
697
923
|
template_key: generator.templateKey,
|
|
924
|
+
alias: generator.alias,
|
|
698
925
|
title: generator.title,
|
|
699
926
|
description: generator.description,
|
|
927
|
+
hide_short_ref: generator.hideShortRef,
|
|
700
928
|
local_sync: generator.localSyncRunMode
|
|
701
929
|
? {
|
|
702
930
|
run_mode: generator.localSyncRunMode,
|
|
@@ -704,19 +932,25 @@ export const compile = async (app: Application) => {
|
|
|
704
932
|
: undefined,
|
|
705
933
|
property: compileProperty(
|
|
706
934
|
generator.property || {},
|
|
707
|
-
`(generator: ${
|
|
935
|
+
`(generator: ${generatorId}, subspace ${subspaceId})`,
|
|
708
936
|
),
|
|
709
937
|
event_map: compileEvents(generator.templateKey, generator.events || {}, {
|
|
710
938
|
camelCase: false,
|
|
711
|
-
errorReference: `(generator: ${
|
|
939
|
+
errorReference: `(generator: ${generatorId}, subspace ${subspaceId})`,
|
|
712
940
|
}),
|
|
713
941
|
outlet: compileOutlets(
|
|
714
942
|
generator.templateKey,
|
|
715
943
|
generator.outlets || {},
|
|
716
|
-
`(generator: ${
|
|
944
|
+
`(generator: ${generatorId}, subspace ${subspaceId})`,
|
|
717
945
|
),
|
|
718
|
-
state_group: generator.switches?.reduce((acc, switchCase) => {
|
|
719
|
-
|
|
946
|
+
state_group: generator.switches?.reduce((acc, switchCase, switchIndex) => {
|
|
947
|
+
const switchId = assertEntryId(
|
|
948
|
+
switchCase.id,
|
|
949
|
+
'BRICK_STATE_GROUP',
|
|
950
|
+
`(generator: ${generatorId}, switch index: ${switchIndex}, subspace ${subspaceId})`,
|
|
951
|
+
)
|
|
952
|
+
|
|
953
|
+
acc[switchId] = {
|
|
720
954
|
title: switchCase.title,
|
|
721
955
|
description: switchCase.description,
|
|
722
956
|
break: switchCase.break,
|
|
@@ -725,25 +959,25 @@ export const compile = async (app: Application) => {
|
|
|
725
959
|
conds: compileSwitchConds(
|
|
726
960
|
generator.templateKey,
|
|
727
961
|
switchCase.conds || [],
|
|
728
|
-
`(generator: ${
|
|
962
|
+
`(generator: ${generatorId}, switch: ${switchId}, subspace ${subspaceId})`,
|
|
729
963
|
),
|
|
730
964
|
property: compileProperty(
|
|
731
965
|
switchCase.property,
|
|
732
|
-
`(generator: ${
|
|
966
|
+
`(generator: ${generatorId}, switch: ${switchId}, subspace ${subspaceId})`,
|
|
733
967
|
),
|
|
734
968
|
outlet: compileOutlets(
|
|
735
969
|
generator.templateKey,
|
|
736
970
|
switchCase.outlets || {},
|
|
737
|
-
`(generator: ${
|
|
971
|
+
`(generator: ${generatorId}, switch: ${switchId}, subspace ${subspaceId})`,
|
|
738
972
|
),
|
|
739
973
|
event_map: compileEvents(generator.templateKey, switchCase.events || {}, {
|
|
740
974
|
camelCase: false,
|
|
741
|
-
errorReference: `(generator: ${
|
|
975
|
+
errorReference: `(generator: ${generatorId}, switch: ${switchId}, subspace ${subspaceId})`,
|
|
742
976
|
}),
|
|
743
977
|
animation: compileAnimations(
|
|
744
978
|
generator.templateKey,
|
|
745
979
|
switchCase.animation || {},
|
|
746
|
-
`(generator: ${
|
|
980
|
+
`(generator: ${generatorId}, switch: ${switchId}, subspace ${subspaceId})`,
|
|
747
981
|
),
|
|
748
982
|
}
|
|
749
983
|
return acc
|
|
@@ -751,10 +985,18 @@ export const compile = async (app: Application) => {
|
|
|
751
985
|
}
|
|
752
986
|
return map
|
|
753
987
|
}, {}),
|
|
754
|
-
property_bank_map: subspace.data.reduce((map, data) => {
|
|
755
|
-
|
|
988
|
+
property_bank_map: subspace.data.reduce((map, data, dataIndex) => {
|
|
989
|
+
const dataId = assertEntryId(
|
|
990
|
+
data.id,
|
|
991
|
+
'PROPERTY_BANK_DATA_NODE',
|
|
992
|
+
`(data index: ${dataIndex}, subspace: ${subspaceId})`,
|
|
993
|
+
)
|
|
994
|
+
|
|
995
|
+
map[dataId] = {
|
|
996
|
+
alias: data.alias,
|
|
756
997
|
title: data.title,
|
|
757
998
|
description: data.description,
|
|
999
|
+
hide_short_ref: data.hideShortRef,
|
|
758
1000
|
linked: data.metadata?.linked,
|
|
759
1001
|
linkedFrom: data.metadata?.linkedFrom,
|
|
760
1002
|
local_sync: data.localSyncUpdateMode
|
|
@@ -768,35 +1010,72 @@ export const compile = async (app: Application) => {
|
|
|
768
1010
|
schema: data.schema,
|
|
769
1011
|
type: data.type,
|
|
770
1012
|
...compileKind(data.kind),
|
|
771
|
-
value: compileProperty(data.value, `(data: ${
|
|
1013
|
+
value: compileProperty(data.value, `(data: ${dataId}, subspace ${subspaceId})`),
|
|
772
1014
|
event_map: compileEvents('PROPERTY_BANK', data.events || {}, {
|
|
773
1015
|
camelCase: false,
|
|
774
|
-
errorReference: `(data: ${
|
|
1016
|
+
errorReference: `(data: ${dataId}, subspace ${subspaceId})`,
|
|
775
1017
|
}),
|
|
776
1018
|
hit_equal: data.hit_equal,
|
|
777
1019
|
hit_regex: data.hit_regex,
|
|
778
1020
|
}
|
|
779
1021
|
return map
|
|
780
1022
|
}, {}),
|
|
781
|
-
property_bank_calc_map: subspace.dataCalculation.reduce((map, dataCalc) => {
|
|
1023
|
+
property_bank_calc_map: subspace.dataCalculation.reduce((map, dataCalc, dataCalcIndex) => {
|
|
1024
|
+
const dataCalcId = assertEntryId(
|
|
1025
|
+
dataCalc.id,
|
|
1026
|
+
'PROPERTY_BANK_COMMAND_MAP',
|
|
1027
|
+
`(data calc index: ${dataCalcIndex}, subspace: ${subspaceId})`,
|
|
1028
|
+
)
|
|
1029
|
+
|
|
782
1030
|
const calc: any = {
|
|
783
1031
|
title: dataCalc.title,
|
|
784
1032
|
description: dataCalc.description,
|
|
1033
|
+
hide_short_ref: dataCalc.hideShortRef,
|
|
785
1034
|
}
|
|
786
1035
|
if (dataCalc.triggerMode) calc.trigger_type = dataCalc.triggerMode
|
|
787
1036
|
if (dataCalc.__typename === 'DataCalculationMap') {
|
|
788
1037
|
calc.type = 'general'
|
|
789
1038
|
const mapCalc = dataCalc as DataCalculationMap
|
|
790
1039
|
|
|
1040
|
+
const getNodeId = (
|
|
1041
|
+
node: DataCalculationData | DataCommand,
|
|
1042
|
+
reference = '',
|
|
1043
|
+
nodeIndex?: number,
|
|
1044
|
+
) => {
|
|
1045
|
+
const nodeReference = [
|
|
1046
|
+
`data calc: ${dataCalcId}`,
|
|
1047
|
+
`subspace: ${subspaceId}`,
|
|
1048
|
+
typeof nodeIndex === 'number' ? `node index: ${nodeIndex}` : undefined,
|
|
1049
|
+
reference || undefined,
|
|
1050
|
+
]
|
|
1051
|
+
.filter(Boolean)
|
|
1052
|
+
.join(', ')
|
|
1053
|
+
|
|
1054
|
+
if (node.__typename === 'DataCalculationData') {
|
|
1055
|
+
return assertEntryId(
|
|
1056
|
+
node.data()?.id,
|
|
1057
|
+
'PROPERTY_BANK_DATA_NODE',
|
|
1058
|
+
`(${nodeReference})`,
|
|
1059
|
+
)
|
|
1060
|
+
}
|
|
1061
|
+
if (node.__typename === 'DataCommand') {
|
|
1062
|
+
return assertEntryId(node.id, 'PROPERTY_BANK_COMMAND_NODE', `(${nodeReference})`)
|
|
1063
|
+
}
|
|
1064
|
+
throw new Error(`Invalid node: ${JSON.stringify(node)}`)
|
|
1065
|
+
}
|
|
1066
|
+
|
|
791
1067
|
const generateInputPorts = (inputs) =>
|
|
792
|
-
inputs.reduce((acc, port) => {
|
|
1068
|
+
inputs.reduce((acc, port, portIndex) => {
|
|
793
1069
|
if (!acc[port.key]) acc[port.key] = null
|
|
794
1070
|
|
|
795
1071
|
let sourceId
|
|
796
1072
|
const sourceNode = port.source()
|
|
797
|
-
if (
|
|
798
|
-
|
|
799
|
-
|
|
1073
|
+
if (
|
|
1074
|
+
sourceNode?.__typename === 'DataCalculationData' ||
|
|
1075
|
+
sourceNode?.__typename === 'DataCommand'
|
|
1076
|
+
) {
|
|
1077
|
+
sourceId = getNodeId(sourceNode, `input port index: ${portIndex}`)
|
|
1078
|
+
}
|
|
800
1079
|
|
|
801
1080
|
if (!sourceId) return acc
|
|
802
1081
|
if (!acc[port.key]) acc[port.key] = []
|
|
@@ -810,14 +1089,17 @@ export const compile = async (app: Application) => {
|
|
|
810
1089
|
}, {})
|
|
811
1090
|
|
|
812
1091
|
const generateOutputPorts = (outputs) =>
|
|
813
|
-
outputs.reduce((acc, port) => {
|
|
1092
|
+
outputs.reduce((acc, port, portIndex) => {
|
|
814
1093
|
if (!acc[port.key]) acc[port.key] = null
|
|
815
1094
|
|
|
816
1095
|
let targetId
|
|
817
1096
|
const targetNode = port.target()
|
|
818
|
-
if (
|
|
819
|
-
|
|
820
|
-
|
|
1097
|
+
if (
|
|
1098
|
+
targetNode?.__typename === 'DataCalculationData' ||
|
|
1099
|
+
targetNode?.__typename === 'DataCommand'
|
|
1100
|
+
) {
|
|
1101
|
+
targetId = getNodeId(targetNode, `output port index: ${portIndex}`)
|
|
1102
|
+
}
|
|
821
1103
|
|
|
822
1104
|
if (!targetId) return acc
|
|
823
1105
|
if (!acc[port.key]) acc[port.key] = []
|
|
@@ -829,18 +1111,13 @@ export const compile = async (app: Application) => {
|
|
|
829
1111
|
return acc
|
|
830
1112
|
}, {})
|
|
831
1113
|
|
|
832
|
-
|
|
833
|
-
if (node.__typename === 'DataCalculationData') return node.data().id
|
|
834
|
-
if (node.__typename === 'DataCommand') return node.id
|
|
835
|
-
throw new Error(`Invalid node: ${JSON.stringify(node)}`)
|
|
836
|
-
}
|
|
837
|
-
|
|
838
|
-
calc.map = mapCalc.nodes.reduce((acc, node) => {
|
|
1114
|
+
calc.map = mapCalc.nodes.reduce((acc, node, nodeIndex) => {
|
|
839
1115
|
if (node.__typename === 'DataCalculationData') {
|
|
840
1116
|
const dataNode = node as DataCalculationData
|
|
841
|
-
acc[getNodeId(dataNode)] = {
|
|
1117
|
+
acc[getNodeId(dataNode, 'data node', nodeIndex)] = {
|
|
842
1118
|
title: dataNode.title,
|
|
843
1119
|
description: dataNode.description,
|
|
1120
|
+
hide_short_ref: dataNode.hideShortRef,
|
|
844
1121
|
type: 'data-node',
|
|
845
1122
|
properties: {},
|
|
846
1123
|
in: generateInputPorts(dataNode.inputs),
|
|
@@ -863,9 +1140,10 @@ export const compile = async (app: Application) => {
|
|
|
863
1140
|
(input.source()?.__typename === 'DataCalculationData' ||
|
|
864
1141
|
input.source()?.__typename === 'DataCommand'),
|
|
865
1142
|
)
|
|
866
|
-
acc[getNodeId(commandNode)] = {
|
|
1143
|
+
acc[getNodeId(commandNode, 'command node', nodeIndex)] = {
|
|
867
1144
|
title: commandNode.title,
|
|
868
1145
|
description: commandNode.description,
|
|
1146
|
+
hide_short_ref: commandNode.hideShortRef,
|
|
869
1147
|
type: `command-node-${type}`,
|
|
870
1148
|
properties: {
|
|
871
1149
|
command: commandNode.__commandName,
|
|
@@ -881,11 +1159,11 @@ export const compile = async (app: Application) => {
|
|
|
881
1159
|
return acc
|
|
882
1160
|
}, {})
|
|
883
1161
|
calc.editor_info = mapCalc.editorInfo.reduce((acc, editorInfo) => {
|
|
884
|
-
acc[getNodeId(editorInfo.node)] = {
|
|
1162
|
+
acc[getNodeId(editorInfo.node, 'editor info node')] = {
|
|
885
1163
|
position: editorInfo.position,
|
|
886
1164
|
points: editorInfo.points.reduce((pointsAcc, point) => {
|
|
887
|
-
const sourceId = getNodeId(point.source)
|
|
888
|
-
const targetId = getNodeId(point.target)
|
|
1165
|
+
const sourceId = getNodeId(point.source, 'editor info point source')
|
|
1166
|
+
const targetId = getNodeId(point.target, 'editor info point target')
|
|
889
1167
|
const key = `${sourceId}-${point.sourceOutputKey}-${targetId}-${point.targetInputKey}`
|
|
890
1168
|
pointsAcc[key] = point.positions
|
|
891
1169
|
return pointsAcc
|
|
@@ -897,43 +1175,55 @@ export const compile = async (app: Application) => {
|
|
|
897
1175
|
const scriptCalc = dataCalc as DataCalculationScript
|
|
898
1176
|
calc.type = 'script'
|
|
899
1177
|
|
|
900
|
-
|
|
901
|
-
try {
|
|
902
|
-
const program = parseAST(scriptCalc.code, { sourceType: 'module', ecmaVersion: 2020 })
|
|
903
|
-
// export function main() { ... }
|
|
904
|
-
const declarationBody = (
|
|
905
|
-
(program.body[0] as ExportNamedDeclaration).declaration as FunctionDeclaration
|
|
906
|
-
)?.body
|
|
907
|
-
code = escodegen.generate(declarationBody, {
|
|
908
|
-
format: {
|
|
909
|
-
indent: { style: ' ' },
|
|
910
|
-
semicolons: false,
|
|
911
|
-
},
|
|
912
|
-
comment: true,
|
|
913
|
-
})
|
|
914
|
-
} catch {
|
|
915
|
-
code = scriptCalc.code || ''
|
|
916
|
-
}
|
|
1178
|
+
const code = compileScriptCalculationCode(scriptCalc.code)
|
|
917
1179
|
calc.script_config = {
|
|
918
|
-
|
|
1180
|
+
title: scriptCalc.title ?? '',
|
|
1181
|
+
note: scriptCalc.note ?? '',
|
|
919
1182
|
code,
|
|
920
1183
|
enable_async: scriptCalc.enableAsync,
|
|
921
1184
|
trigger_mode: scriptCalc.triggerMode,
|
|
922
1185
|
inputs: scriptCalc.inputs.reduce((acc, input) => {
|
|
923
|
-
|
|
1186
|
+
const inputId = assertEntryId(
|
|
1187
|
+
input.data()?.id,
|
|
1188
|
+
'PROPERTY_BANK_DATA_NODE',
|
|
1189
|
+
`(data calc: ${dataCalcId}, script input: ${input.key}, subspace: ${subspaceId})`,
|
|
1190
|
+
)
|
|
1191
|
+
acc[inputId] = input.key
|
|
924
1192
|
return acc
|
|
925
1193
|
}, {}),
|
|
926
1194
|
disabled_triggers: scriptCalc.inputs.reduce((acc, input) => {
|
|
927
|
-
|
|
1195
|
+
const inputId = assertEntryId(
|
|
1196
|
+
input.data()?.id,
|
|
1197
|
+
'PROPERTY_BANK_DATA_NODE',
|
|
1198
|
+
`(data calc: ${dataCalcId}, script trigger input: ${input.key}, subspace: ${subspaceId})`,
|
|
1199
|
+
)
|
|
1200
|
+
acc[inputId] = !input.trigger
|
|
928
1201
|
return acc
|
|
929
1202
|
}, {}),
|
|
930
|
-
output: scriptCalc.output
|
|
1203
|
+
output: scriptCalc.output
|
|
1204
|
+
? assertEntryId(
|
|
1205
|
+
scriptCalc.output()?.id,
|
|
1206
|
+
'PROPERTY_BANK_DATA_NODE',
|
|
1207
|
+
`(data calc: ${dataCalcId}, script output, subspace: ${subspaceId})`,
|
|
1208
|
+
)
|
|
1209
|
+
: null,
|
|
931
1210
|
outputs: scriptCalc.outputs.reduce((acc, output) => {
|
|
932
1211
|
if (!acc[output.key]) acc[output.key] = []
|
|
933
|
-
|
|
1212
|
+
const outputId = assertEntryId(
|
|
1213
|
+
output.data()?.id,
|
|
1214
|
+
'PROPERTY_BANK_DATA_NODE',
|
|
1215
|
+
`(data calc: ${dataCalcId}, script outputs key: ${output.key}, subspace: ${subspaceId})`,
|
|
1216
|
+
)
|
|
1217
|
+
acc[output.key].push(outputId)
|
|
934
1218
|
return acc
|
|
935
1219
|
}, {}),
|
|
936
|
-
error: scriptCalc.error
|
|
1220
|
+
error: scriptCalc.error
|
|
1221
|
+
? assertEntryId(
|
|
1222
|
+
scriptCalc.error()?.id,
|
|
1223
|
+
'PROPERTY_BANK_DATA_NODE',
|
|
1224
|
+
`(data calc: ${dataCalcId}, script error output, subspace: ${subspaceId})`,
|
|
1225
|
+
)
|
|
1226
|
+
: null,
|
|
937
1227
|
}
|
|
938
1228
|
|
|
939
1229
|
Object.assign(
|
|
@@ -943,25 +1233,32 @@ export const compile = async (app: Application) => {
|
|
|
943
1233
|
}),
|
|
944
1234
|
)
|
|
945
1235
|
}
|
|
946
|
-
map[
|
|
1236
|
+
map[dataCalcId] = calc
|
|
947
1237
|
return map
|
|
948
1238
|
}, {}),
|
|
949
1239
|
action_map: subspace.actions || undefined,
|
|
950
1240
|
event_map: compileEvents('', subspace.events || {}, {
|
|
951
1241
|
camelCase: false,
|
|
952
|
-
errorReference: `(subspace ${
|
|
1242
|
+
errorReference: `(subspace ${subspaceId})`,
|
|
953
1243
|
}),
|
|
954
1244
|
routing: subspace.dataRouting.reduce((acc, data, index) => {
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
1245
|
+
const dataId = assertEntryId(
|
|
1246
|
+
data?.id,
|
|
1247
|
+
'PROPERTY_BANK_DATA_NODE',
|
|
1248
|
+
`(data routing index: ${index}, subspace ${subspaceId})`,
|
|
1249
|
+
)
|
|
1250
|
+
acc[dataId] = { enabled_routing: true }
|
|
958
1251
|
return acc
|
|
959
1252
|
}, {}),
|
|
960
1253
|
...compileModule(subspace),
|
|
961
1254
|
}
|
|
962
1255
|
return subspaceMap
|
|
963
1256
|
}, {}),
|
|
964
|
-
root_subspace_id:
|
|
1257
|
+
root_subspace_id: assertEntryId(
|
|
1258
|
+
app.rootSubspace?.id,
|
|
1259
|
+
'SUBSPACE',
|
|
1260
|
+
'(application root subspace)',
|
|
1261
|
+
),
|
|
965
1262
|
fonts: app.fonts,
|
|
966
1263
|
...compileApplicationSettings(app.settings),
|
|
967
1264
|
// Use typed automationMap if available, otherwise fall back to TEMP metadata
|
|
@@ -975,3 +1272,8 @@ export const compile = async (app: Application) => {
|
|
|
975
1272
|
}
|
|
976
1273
|
return config
|
|
977
1274
|
}
|
|
1275
|
+
|
|
1276
|
+
export const checkConfig = async (configPath: string) => {
|
|
1277
|
+
const { $ } = await import('bun')
|
|
1278
|
+
await $`bricks app check-config ${configPath}`
|
|
1279
|
+
}
|