@fugood/bricks-project 2.21.0-beta.14.test0
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/api/application.ts +65 -0
- package/api/index.ts +1 -0
- package/compile/index.ts +485 -0
- package/compile/util.ts +347 -0
- package/index.ts +10 -0
- package/package.json +15 -0
- package/types/animation.ts +95 -0
- package/types/bricks.ts +3052 -0
- package/types/canvas.ts +78 -0
- package/types/common.ts +116 -0
- package/types/data-calc.ts +6950 -0
- package/types/data.ts +33 -0
- package/types/generators.ts +6633 -0
- package/types/index.ts +10 -0
- package/types/subspace.ts +33 -0
- package/types/switch.ts +45 -0
- package/types/system.ts +397 -0
- package/uuid.ts +58 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
const stage = process.env.BRICKS_STAGE || 'production'
|
|
2
|
+
|
|
3
|
+
const apiUrlMap = {
|
|
4
|
+
production: 'https://display.bricks.tools/api/graphql-workspace',
|
|
5
|
+
beta: 'https://display-beta.bricks.tools/api/graphql-workspace',
|
|
6
|
+
dev: 'http://localhost:3001/api/graphql-workspace',
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const apiURL = apiUrlMap[stage]
|
|
10
|
+
if (!apiURL) throw new Error(`Invalid BRICKS_STAGE: ${stage}`)
|
|
11
|
+
|
|
12
|
+
const workspaceToken = process.env.BRICKS_WORKSPACE_TOKEN
|
|
13
|
+
|
|
14
|
+
const doGQL = async (query: string, variables: Record<string, any>) => {
|
|
15
|
+
if (!workspaceToken) throw new Error('env BRICKS_WORKSPACE_TOKEN is not set')
|
|
16
|
+
|
|
17
|
+
const data = await fetch(apiURL, {
|
|
18
|
+
method: 'POST',
|
|
19
|
+
headers: {
|
|
20
|
+
'Content-Type': 'application/json',
|
|
21
|
+
Authorization: `Bearer ${workspaceToken}`,
|
|
22
|
+
},
|
|
23
|
+
body: JSON.stringify({ query, variables }),
|
|
24
|
+
}).then((res) => res.json())
|
|
25
|
+
return data
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const deployApp = async (appId: string, config: {}, lastCommitId: string) => {
|
|
29
|
+
const { errors } = await doGQL(
|
|
30
|
+
`mutation BRICKS_PROJECT_updateApplication($id: ID!, $config: JSON) {
|
|
31
|
+
updateApplication(
|
|
32
|
+
id: $id,
|
|
33
|
+
config: $config
|
|
34
|
+
) {
|
|
35
|
+
_id
|
|
36
|
+
name
|
|
37
|
+
}
|
|
38
|
+
}`,
|
|
39
|
+
{
|
|
40
|
+
id: appId,
|
|
41
|
+
config: {
|
|
42
|
+
...config,
|
|
43
|
+
bricks_project_last_commit_id: lastCommitId,
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
)
|
|
47
|
+
if (errors) throw new Error(errors[0].message)
|
|
48
|
+
return true
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export const pullApp = async (appId: string) => {
|
|
52
|
+
const { data, errors } = await doGQL(
|
|
53
|
+
`query BRICKS_PROJECT_application($id: ID!) {
|
|
54
|
+
application(id: $id) {
|
|
55
|
+
_id
|
|
56
|
+
name
|
|
57
|
+
description
|
|
58
|
+
config
|
|
59
|
+
}
|
|
60
|
+
}`,
|
|
61
|
+
{ id: appId },
|
|
62
|
+
)
|
|
63
|
+
if (errors) throw new Error(errors[0].message)
|
|
64
|
+
return data.application
|
|
65
|
+
}
|
package/api/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './application'
|
package/compile/index.ts
ADDED
|
@@ -0,0 +1,485 @@
|
|
|
1
|
+
import _ from 'lodash'
|
|
2
|
+
import { parse as parseAST, ExportNamedDeclaration, FunctionDeclaration } from 'acorn'
|
|
3
|
+
import escodegen from 'escodegen'
|
|
4
|
+
import {
|
|
5
|
+
Application,
|
|
6
|
+
Data,
|
|
7
|
+
AnimationDef,
|
|
8
|
+
AnimationComposeDef,
|
|
9
|
+
EventAction,
|
|
10
|
+
ActionWithDataParams,
|
|
11
|
+
ActionWithParams,
|
|
12
|
+
BrickItems,
|
|
13
|
+
SwitchCondData,
|
|
14
|
+
SwitchCondInnerStateCurrentCanvas,
|
|
15
|
+
SwitchCondPropertyBankByItemKey,
|
|
16
|
+
DataCalculationMap,
|
|
17
|
+
DataCalculationScript,
|
|
18
|
+
DataCalculationData,
|
|
19
|
+
DataCommand,
|
|
20
|
+
Brick,
|
|
21
|
+
Generator,
|
|
22
|
+
} from '../types'
|
|
23
|
+
import { generateCalulationMap } from './util'
|
|
24
|
+
|
|
25
|
+
const compileProperty = (property, result = {}) => {
|
|
26
|
+
if (Array.isArray(property)) {
|
|
27
|
+
return property.map((p) => compileProperty(p, result))
|
|
28
|
+
}
|
|
29
|
+
if (property?.__typename === 'DataLink' && property.data?.()) return `PROPERTY_BANK#${property.data().id}`
|
|
30
|
+
if (typeof property === 'function') return property()?.id // defined type instance getter
|
|
31
|
+
if (typeof property === 'object') {
|
|
32
|
+
return Object.entries(property).reduce((acc, [key, value]) => {
|
|
33
|
+
acc[key] = compileProperty(value, {})
|
|
34
|
+
return acc
|
|
35
|
+
}, result)
|
|
36
|
+
}
|
|
37
|
+
return property
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const convertOutletKey = (templateKey: string, key: string) => {
|
|
41
|
+
return `${templateKey}_${_.snakeCase(key).toUpperCase()}`
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const compileOutlets = (templateKey: string, outlets: { [key: string]: () => Data }) => {
|
|
45
|
+
return Object.entries(outlets).reduce((acc, [key, data]) => {
|
|
46
|
+
acc[convertOutletKey(templateKey, key)] = data().id
|
|
47
|
+
return acc
|
|
48
|
+
}, {})
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const convertEventKey = (templateKey: string, key: string) => {
|
|
52
|
+
return `${templateKey ? `${templateKey}_` : ''}${_.snakeCase(key).toUpperCase()}`
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const basicAnimationEvents = ['show', 'standby', 'breatheStart']
|
|
56
|
+
|
|
57
|
+
const compileAnimations = (templateKey: string, animations: { [key: string]: () => Animation }) => {
|
|
58
|
+
return Object.entries(animations).reduce((acc, [key, animation]) => {
|
|
59
|
+
acc[convertEventKey(basicAnimationEvents.includes(key) ? 'BRICK' : templateKey, key)] =
|
|
60
|
+
`ANIMATION#${animation().id}`
|
|
61
|
+
return acc
|
|
62
|
+
}, {})
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const compileEvents = (
|
|
66
|
+
templateKey: string,
|
|
67
|
+
eventMap: { [key: string]: Array<EventAction> },
|
|
68
|
+
options = { camelCase: false },
|
|
69
|
+
) => {
|
|
70
|
+
const { camelCase } = options
|
|
71
|
+
return Object.entries(eventMap).reduce((acc, [key, events]) => {
|
|
72
|
+
acc[convertEventKey(templateKey, key)] = events.map((event) => {
|
|
73
|
+
const { handler, action } = event
|
|
74
|
+
|
|
75
|
+
const parameterList: Array<object> = []
|
|
76
|
+
if (Object.hasOwn(action, 'params')) {
|
|
77
|
+
const actionDef = action as ActionWithParams
|
|
78
|
+
;(actionDef.params || []).forEach(({ input, value, mapping }) => {
|
|
79
|
+
parameterList.push({
|
|
80
|
+
[camelCase ? 'inputToReceiver' : 'input_to_receiver']: input,
|
|
81
|
+
[camelCase ? 'resultFromSender' : 'result_from_sender']: compileProperty(value),
|
|
82
|
+
[camelCase ? 'resultDataMapping' : 'result_data_mapping']: mapping,
|
|
83
|
+
})
|
|
84
|
+
})
|
|
85
|
+
} else if (Object.hasOwn(action, 'dataParams')) {
|
|
86
|
+
const actionDef = action as ActionWithDataParams
|
|
87
|
+
;(actionDef.dataParams || []).forEach(({ input, value, mapping }) => {
|
|
88
|
+
if (!input) return
|
|
89
|
+
parameterList.push({
|
|
90
|
+
[camelCase ? 'inputToReceiver' : 'input_to_receiver']: input().id,
|
|
91
|
+
[camelCase ? 'resultFromSender' : 'result_from_sender']: compileProperty(value),
|
|
92
|
+
[camelCase ? 'resultDataMapping' : 'result_data_mapping']: mapping,
|
|
93
|
+
})
|
|
94
|
+
})
|
|
95
|
+
}
|
|
96
|
+
let handlerKey
|
|
97
|
+
if (handler === 'system' || typeof handler === 'string') {
|
|
98
|
+
if (handler.startsWith('SUBSPACE_')) handlerKey = handler
|
|
99
|
+
else handlerKey = handler.toUpperCase()
|
|
100
|
+
} else if (typeof handler === 'function') {
|
|
101
|
+
handlerKey = (handler() as Brick | Generator)?.id
|
|
102
|
+
}
|
|
103
|
+
if (!handlerKey) throw new Error(`Invalid handler: ${handler}`)
|
|
104
|
+
return {
|
|
105
|
+
handler: handlerKey,
|
|
106
|
+
action: action.__actionName,
|
|
107
|
+
[camelCase ? 'parameterList' : 'parameter_list']: parameterList,
|
|
108
|
+
[camelCase ? 'waitAsync' : 'wait_async']: event.waitAsync,
|
|
109
|
+
}
|
|
110
|
+
})
|
|
111
|
+
return acc
|
|
112
|
+
}, {})
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const compileSwitchConds = (templateKey, conds) =>
|
|
116
|
+
(conds || []).map((item: any) => {
|
|
117
|
+
const result: any = { method: item.method }
|
|
118
|
+
if (item.__typename === 'SwitchCondData') {
|
|
119
|
+
const cond = item as SwitchCondData
|
|
120
|
+
result.type = 'property_bank'
|
|
121
|
+
result.key = cond.data().id
|
|
122
|
+
result.value = cond.value
|
|
123
|
+
} else if (item.__typename === 'SwitchCondPropertyBankByItemKey') {
|
|
124
|
+
const cond = item as SwitchCondPropertyBankByItemKey
|
|
125
|
+
result.type = 'property_bank_by_item_key'
|
|
126
|
+
result.key = cond.data().id
|
|
127
|
+
result.value = cond.value
|
|
128
|
+
} else if (item.__typename === 'SwitchCondInnerStateOutlet') {
|
|
129
|
+
result.type = 'inner_state'
|
|
130
|
+
result.key = convertOutletKey(templateKey, item.outlet)
|
|
131
|
+
result.value = item.value
|
|
132
|
+
} else if (item.__typename === 'SwitchCondInnerStateCurrentCanvas') {
|
|
133
|
+
const cond = item as SwitchCondInnerStateCurrentCanvas
|
|
134
|
+
result.type = 'inner_state'
|
|
135
|
+
result.key = 'current_canvas'
|
|
136
|
+
result.value = cond.value().id
|
|
137
|
+
}
|
|
138
|
+
return result
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
const compileApplicationSettings = (settings: Application['settings']) => {
|
|
142
|
+
return {
|
|
143
|
+
internet_reachability_url: settings?.internetReachabilityUrl,
|
|
144
|
+
enable_data_lock: settings?.enableDataLock,
|
|
145
|
+
show_deprecated_features: settings?.showDeprecatedFeatures,
|
|
146
|
+
enable_unstable_bricks: settings?.enableUnstableFeatures,
|
|
147
|
+
runtime_cache_options: settings?.runtimeCacheOptions
|
|
148
|
+
? {
|
|
149
|
+
disabled: settings.runtimeCacheOptions.disabled,
|
|
150
|
+
behavior: settings.runtimeCacheOptions.behavior,
|
|
151
|
+
retry_attempt_for_failure: settings.runtimeCacheOptions.retryAttemptForFailure,
|
|
152
|
+
}
|
|
153
|
+
: undefined,
|
|
154
|
+
tv_options: settings?.tvOptions
|
|
155
|
+
? {
|
|
156
|
+
disabled_selectable: settings.tvOptions.disabledSelectable,
|
|
157
|
+
selectable_color: settings.tvOptions.selectableColor,
|
|
158
|
+
selectable_border: settings.tvOptions.selectableBorder,
|
|
159
|
+
}
|
|
160
|
+
: undefined,
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const animationTypeMap = {
|
|
165
|
+
AnimationTimingConfig: 'timing',
|
|
166
|
+
AnimationSpringConfig: 'spring',
|
|
167
|
+
AnimationDecayConfig: 'decay',
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export const compile = (app: Application) => {
|
|
171
|
+
const config = {
|
|
172
|
+
title: app.name,
|
|
173
|
+
subspace_map: app.subspaces.reduce((subspaceMap, subspace) => {
|
|
174
|
+
subspaceMap[subspace.id] = {
|
|
175
|
+
title: subspace.title,
|
|
176
|
+
description: subspace.description,
|
|
177
|
+
layout: {
|
|
178
|
+
width: subspace.layout?.width,
|
|
179
|
+
height: subspace.layout?.height,
|
|
180
|
+
resize_mode: subspace.layout?.resizeMode,
|
|
181
|
+
},
|
|
182
|
+
animation_map: subspace.animations.reduce((map, animation) => {
|
|
183
|
+
if (animation.__typename === 'Animation') {
|
|
184
|
+
const animationDef = animation as AnimationDef
|
|
185
|
+
map[animationDef.id] = {
|
|
186
|
+
title: animationDef.title,
|
|
187
|
+
description: animationDef.description,
|
|
188
|
+
animationRunType: animationDef.runType,
|
|
189
|
+
property: animationDef.property,
|
|
190
|
+
type: animationTypeMap[animationDef.config.__type],
|
|
191
|
+
config: compileProperty(_.omit(animationDef.config, '__type')),
|
|
192
|
+
}
|
|
193
|
+
} else if (animation.__typename === 'AnimationCompose') {
|
|
194
|
+
const animationDef = animation as AnimationComposeDef
|
|
195
|
+
map[animationDef.id] = {
|
|
196
|
+
title: animationDef.title,
|
|
197
|
+
description: animationDef.description,
|
|
198
|
+
animationRunType: animationDef.runType,
|
|
199
|
+
compose_type: animationDef.composeType,
|
|
200
|
+
item_list: animationDef.items.map((item) => ({ animation_id: item().id })),
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return map
|
|
204
|
+
}, {}),
|
|
205
|
+
brick_map: subspace.bricks.reduce((map, brick) => {
|
|
206
|
+
const property = compileProperty(brick.property || {})
|
|
207
|
+
if (brick.templateKey === 'BRICK_ITEMS') {
|
|
208
|
+
const brickItems = brick as BrickItems
|
|
209
|
+
const buildList = (itemBrick) => ({
|
|
210
|
+
title: itemBrick.title,
|
|
211
|
+
brickId: itemBrick.brickId,
|
|
212
|
+
brickIdPrefix: itemBrick.brickIdPrefix,
|
|
213
|
+
templateKey: itemBrick.templateKey,
|
|
214
|
+
property: compileProperty(itemBrick.property),
|
|
215
|
+
animation: compileAnimations(itemBrick.templateKey, itemBrick.animation || {}),
|
|
216
|
+
outlet: compileOutlets(itemBrick.templateKey, itemBrick.outlets || {}),
|
|
217
|
+
eventMap: compileEvents(itemBrick.templateKey, itemBrick.eventMap || {}, {
|
|
218
|
+
camelCase: true,
|
|
219
|
+
}),
|
|
220
|
+
stateGroup: itemBrick.stateGroup.map((stateGroup) => ({
|
|
221
|
+
...stateGroup,
|
|
222
|
+
animation: compileAnimations(itemBrick.templateKey, stateGroup.animation || {}),
|
|
223
|
+
commented: stateGroup.disabled,
|
|
224
|
+
conds: compileSwitchConds(itemBrick.templateKey, stateGroup.conds || []),
|
|
225
|
+
property: compileProperty(stateGroup.property),
|
|
226
|
+
outlet: compileOutlets(itemBrick.templateKey, stateGroup.outlets || {}),
|
|
227
|
+
eventMap: compileEvents(itemBrick.templateKey, stateGroup.eventMap || {}, {
|
|
228
|
+
camelCase: true,
|
|
229
|
+
}),
|
|
230
|
+
})),
|
|
231
|
+
})
|
|
232
|
+
if (Array.isArray(brickItems.brickList)) {
|
|
233
|
+
const brickList = (brickItems.brickList || []).map(buildList)
|
|
234
|
+
property.brickList = brickList
|
|
235
|
+
} else {
|
|
236
|
+
// Not supported Data for brickList
|
|
237
|
+
throw new Error('Not supported Data for brickList directly')
|
|
238
|
+
}
|
|
239
|
+
if (Array.isArray(brickItems.brickDetails)) {
|
|
240
|
+
const brickDetails = (brickItems.brickDetails || []).map(buildList)
|
|
241
|
+
property.brickDetails = brickDetails
|
|
242
|
+
} else {
|
|
243
|
+
// Not supported Data for brickList
|
|
244
|
+
throw new Error('Not supported Data for brickList directly')
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
map[brick.id] = {
|
|
248
|
+
template_key: brick.templateKey,
|
|
249
|
+
title: brick.title,
|
|
250
|
+
description: brick.description,
|
|
251
|
+
property,
|
|
252
|
+
animation: compileAnimations(brick.templateKey, brick.animation || {}),
|
|
253
|
+
event_map: compileEvents(brick.templateKey, brick.events || {}),
|
|
254
|
+
outlet: compileOutlets(brick.templateKey, brick.outlets || {}),
|
|
255
|
+
state_group: brick.switches.reduce((acc, switchCase) => {
|
|
256
|
+
acc[switchCase.id] = {
|
|
257
|
+
title: switchCase.title,
|
|
258
|
+
description: switchCase.description,
|
|
259
|
+
break: switchCase.break,
|
|
260
|
+
override: switchCase.override,
|
|
261
|
+
commented: switchCase.disabled,
|
|
262
|
+
conds: compileSwitchConds(brick.templateKey, switchCase.conds || []),
|
|
263
|
+
property: compileProperty(switchCase.property),
|
|
264
|
+
outlet: compileOutlets(brick.templateKey, switchCase.outlets || {}),
|
|
265
|
+
event_map: compileEvents(brick.templateKey, switchCase.events || {}),
|
|
266
|
+
animation: compileAnimations(brick.templateKey, switchCase.animation || {}),
|
|
267
|
+
}
|
|
268
|
+
return acc
|
|
269
|
+
}, {}),
|
|
270
|
+
}
|
|
271
|
+
return map
|
|
272
|
+
}, {}),
|
|
273
|
+
root_canvas_id: subspace.rootCanvas.id,
|
|
274
|
+
canvas_map: subspace.canvases.reduce((map, canvas) => {
|
|
275
|
+
map[canvas.id] = {
|
|
276
|
+
title: canvas.title,
|
|
277
|
+
description: canvas.description,
|
|
278
|
+
property: compileProperty(canvas.property),
|
|
279
|
+
event_map: compileEvents('CANVAS', canvas.events || {}),
|
|
280
|
+
state_group: canvas.switches.reduce((acc, switchCase) => {
|
|
281
|
+
acc[switchCase.id] = {
|
|
282
|
+
title: switchCase.title,
|
|
283
|
+
description: switchCase.description,
|
|
284
|
+
break: switchCase.break,
|
|
285
|
+
override: switchCase.override,
|
|
286
|
+
commented: switchCase.disabled,
|
|
287
|
+
conds: compileSwitchConds('CANVAS', switchCase.conds || []),
|
|
288
|
+
property: compileProperty(switchCase.property),
|
|
289
|
+
event_map: compileEvents('CANVAS', switchCase.events || {}),
|
|
290
|
+
animation: compileAnimations('CANVAS', switchCase.animation || {}),
|
|
291
|
+
}
|
|
292
|
+
return acc
|
|
293
|
+
}, {}),
|
|
294
|
+
item_list: [], // TODO
|
|
295
|
+
}
|
|
296
|
+
return map
|
|
297
|
+
}, {}),
|
|
298
|
+
generator_map: subspace.generators.reduce((map, generator) => {
|
|
299
|
+
map[generator.id] = {
|
|
300
|
+
template_key: generator.templateKey,
|
|
301
|
+
title: generator.title,
|
|
302
|
+
description: generator.description,
|
|
303
|
+
property: compileProperty(generator.property || {}),
|
|
304
|
+
event_map: compileEvents(generator.templateKey, generator.events || {}),
|
|
305
|
+
outlet: compileOutlets(generator.templateKey, generator.outlets || {}),
|
|
306
|
+
state_group: generator.switches.reduce((acc, switchCase) => {
|
|
307
|
+
acc[switchCase.id] = {
|
|
308
|
+
title: switchCase.title,
|
|
309
|
+
description: switchCase.description,
|
|
310
|
+
break: switchCase.break,
|
|
311
|
+
override: switchCase.override,
|
|
312
|
+
commented: switchCase.disabled,
|
|
313
|
+
conds: compileSwitchConds(generator.templateKey, switchCase.conds || []),
|
|
314
|
+
property: compileProperty(switchCase.property),
|
|
315
|
+
outlet: compileOutlets(generator.templateKey, switchCase.outlets || {}),
|
|
316
|
+
event_map: compileEvents(generator.templateKey, switchCase.events || {}),
|
|
317
|
+
animation: compileAnimations(generator.templateKey, switchCase.animation || {}),
|
|
318
|
+
}
|
|
319
|
+
return acc
|
|
320
|
+
}, {}),
|
|
321
|
+
}
|
|
322
|
+
return map
|
|
323
|
+
}, {}),
|
|
324
|
+
property_bank_map: subspace.data.reduce((map, data) => {
|
|
325
|
+
map[data.id] = {
|
|
326
|
+
title: data.title,
|
|
327
|
+
description: data.description,
|
|
328
|
+
persist_data: data.persistData,
|
|
329
|
+
routing: data.routing,
|
|
330
|
+
schema: data.schema,
|
|
331
|
+
type: data.type,
|
|
332
|
+
value: data.value,
|
|
333
|
+
event_map: compileEvents('PROPERTY_BANK', data.events || {}),
|
|
334
|
+
}
|
|
335
|
+
return map
|
|
336
|
+
}, {}),
|
|
337
|
+
property_bank_calc_map: subspace.dataCalculation.reduce((map, dataCalc) => {
|
|
338
|
+
const calc: any = {
|
|
339
|
+
title: dataCalc.title,
|
|
340
|
+
description: dataCalc.description,
|
|
341
|
+
}
|
|
342
|
+
if (dataCalc.__typename === 'DataCalculationMap') {
|
|
343
|
+
calc.type = 'general'
|
|
344
|
+
const mapCalc = dataCalc as DataCalculationMap
|
|
345
|
+
|
|
346
|
+
const generateInputPorts = (inputs, outputs) =>
|
|
347
|
+
inputs.reduce((acc, port) => {
|
|
348
|
+
if (!port.source().id) return acc
|
|
349
|
+
|
|
350
|
+
const firstOutput = outputs[0]
|
|
351
|
+
let disableTriggerCommandIn = firstOutput?.target().id
|
|
352
|
+
|
|
353
|
+
if (!acc[port.key]) acc[port.key] = []
|
|
354
|
+
acc[port.key].push({
|
|
355
|
+
id: port.source().id,
|
|
356
|
+
port: port.sourceKey,
|
|
357
|
+
disable_trigger_command_in: disableTriggerCommandIn,
|
|
358
|
+
})
|
|
359
|
+
return acc
|
|
360
|
+
}, {})
|
|
361
|
+
|
|
362
|
+
const generateOutputPorts = (outputs) =>
|
|
363
|
+
outputs.reduce((acc, port) => {
|
|
364
|
+
if (!port.target().id) return acc
|
|
365
|
+
|
|
366
|
+
if (!acc[port.key]) acc[port.key] = []
|
|
367
|
+
acc[port.key].push({
|
|
368
|
+
id: port.target().id,
|
|
369
|
+
port: port.targetKey,
|
|
370
|
+
})
|
|
371
|
+
return acc
|
|
372
|
+
}, {})
|
|
373
|
+
|
|
374
|
+
const getNodeId = (node) => {
|
|
375
|
+
if (node.__typename === 'DataCalculationData') return node.data.id
|
|
376
|
+
if (node.__typename === 'DataCommand') return node.id
|
|
377
|
+
throw new Error(`Invalid node: ${JSON.stringify(node)}`)
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
calc.map = mapCalc.nodes.reduce((acc, node) => {
|
|
381
|
+
if (node.__typename === 'DataCalculationData') {
|
|
382
|
+
const dataNode = node as DataCalculationData
|
|
383
|
+
acc[getNodeId(dataNode)] = {
|
|
384
|
+
title: dataNode.title,
|
|
385
|
+
description: dataNode.description,
|
|
386
|
+
type: 'data-node',
|
|
387
|
+
properties: {},
|
|
388
|
+
in: generateInputPorts(dataNode.inputs, dataNode.outputs),
|
|
389
|
+
out: generateOutputPorts(dataNode.outputs),
|
|
390
|
+
}
|
|
391
|
+
} else if (node.__typename === 'DataCommand') {
|
|
392
|
+
const commandNode = node as DataCommand
|
|
393
|
+
const commandName = commandNode.__commandName
|
|
394
|
+
const type = commandName.split('_')[0].toLowerCase()
|
|
395
|
+
|
|
396
|
+
const args = commandNode.inputs.filter(
|
|
397
|
+
(input) =>
|
|
398
|
+
typeof input.source !== 'function' ||
|
|
399
|
+
input.source()?.__typename !== 'DataCalculationData' &&
|
|
400
|
+
input.source()?.__typename !== 'DataCommand',
|
|
401
|
+
)
|
|
402
|
+
const inputs = commandNode.inputs.filter(
|
|
403
|
+
(input) =>
|
|
404
|
+
typeof input.source === 'function' &&
|
|
405
|
+
(input.source()?.__typename === 'DataCalculationData' ||
|
|
406
|
+
input.source()?.__typename === 'DataCommand'),
|
|
407
|
+
)
|
|
408
|
+
acc[getNodeId(commandNode)] = {
|
|
409
|
+
title: commandNode.title,
|
|
410
|
+
description: commandNode.description,
|
|
411
|
+
type: `command-node-${type}`,
|
|
412
|
+
properties: {
|
|
413
|
+
command: commandNode.__commandName,
|
|
414
|
+
args: args.reduce((acc, input) => {
|
|
415
|
+
acc[input.key] = input.source
|
|
416
|
+
return acc
|
|
417
|
+
}, {}),
|
|
418
|
+
},
|
|
419
|
+
in: generateInputPorts(inputs, commandNode.outputs),
|
|
420
|
+
out: generateOutputPorts(commandNode.outputs),
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
return acc
|
|
424
|
+
}, {})
|
|
425
|
+
calc.editor_info = mapCalc.editorInfo.reduce((acc, editorInfo) => {
|
|
426
|
+
acc[getNodeId(editorInfo.node)] = {
|
|
427
|
+
position: editorInfo.position,
|
|
428
|
+
points: editorInfo.points.reduce((acc, point) => {
|
|
429
|
+
const sourceId = getNodeId(point.source)
|
|
430
|
+
const targetId = getNodeId(point.target)
|
|
431
|
+
const key = `${sourceId}-${point.sourceOutputKey}-${targetId}-${point.targetInputKey}`
|
|
432
|
+
acc[key] = point.positions
|
|
433
|
+
return acc
|
|
434
|
+
}, {}),
|
|
435
|
+
}
|
|
436
|
+
return acc
|
|
437
|
+
}, {})
|
|
438
|
+
} else if (dataCalc.__typename === 'DataCalculationScript') {
|
|
439
|
+
const scriptCalc = dataCalc as DataCalculationScript
|
|
440
|
+
calc.type = 'script'
|
|
441
|
+
|
|
442
|
+
const program = parseAST(scriptCalc.code, { sourceType: 'module', ecmaVersion: 2020 })
|
|
443
|
+
// export function main() { ... }
|
|
444
|
+
const declarationBody = (
|
|
445
|
+
(program.body[0] as ExportNamedDeclaration).declaration as FunctionDeclaration
|
|
446
|
+
)?.body
|
|
447
|
+
|
|
448
|
+
calc.script_config = {
|
|
449
|
+
code: escodegen.generate(declarationBody),
|
|
450
|
+
enable_async: scriptCalc.enableAsync,
|
|
451
|
+
inputs: scriptCalc.inputs.reduce((acc, input) => {
|
|
452
|
+
acc[input.data().id] = input.key
|
|
453
|
+
return acc
|
|
454
|
+
}, {}),
|
|
455
|
+
disabled_triggers: scriptCalc.inputs.reduce((acc, input) => {
|
|
456
|
+
acc[input.data().id] = !input.trigger
|
|
457
|
+
return acc
|
|
458
|
+
}, {}),
|
|
459
|
+
output: scriptCalc.output?.().id,
|
|
460
|
+
outputs: scriptCalc.outputs.reduce((acc, output) => {
|
|
461
|
+
if (!acc[output.key]) acc[output.key] = []
|
|
462
|
+
acc[output.key].push(output.data().id)
|
|
463
|
+
return acc
|
|
464
|
+
}, {}),
|
|
465
|
+
error: scriptCalc.error?.().id,
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
Object.assign(calc, generateCalulationMap(calc.script_config, {
|
|
469
|
+
snapshotMode: process.env.BRICKS_SNAPSHOT_MODE === '1',
|
|
470
|
+
}))
|
|
471
|
+
}
|
|
472
|
+
map[dataCalc.id] = calc
|
|
473
|
+
return map
|
|
474
|
+
}, {}),
|
|
475
|
+
action_map: subspace.actions || {},
|
|
476
|
+
event_map: compileEvents('', subspace.events || {}),
|
|
477
|
+
}
|
|
478
|
+
return subspaceMap
|
|
479
|
+
}, {}),
|
|
480
|
+
root_subspace_id: app.rootSubspace.id,
|
|
481
|
+
fonts: app.fonts,
|
|
482
|
+
...compileApplicationSettings(app.settings),
|
|
483
|
+
}
|
|
484
|
+
return config
|
|
485
|
+
}
|