@nordcraft/runtime 1.0.95 → 1.0.96
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/dist/api/createAPI.js +29 -11
- package/dist/api/createAPI.js.map +1 -1
- package/dist/api/createAPIv2.js +49 -11
- package/dist/api/createAPIv2.js.map +1 -1
- package/dist/components/createComponent.js +14 -5
- package/dist/components/createComponent.js.map +1 -1
- package/dist/components/createElement.js +48 -16
- package/dist/components/createElement.js.map +1 -1
- package/dist/components/createNode.js +23 -10
- package/dist/components/createNode.js.map +1 -1
- package/dist/components/createNode.test.js +3 -3
- package/dist/components/createNode.test.js.map +1 -1
- package/dist/components/createSlot.js +2 -1
- package/dist/components/createSlot.js.map +1 -1
- package/dist/components/createText.js +7 -2
- package/dist/components/createText.js.map +1 -1
- package/dist/components/renderComponent.d.ts +4 -1
- package/dist/components/renderComponent.js +4 -2
- package/dist/components/renderComponent.js.map +1 -1
- package/dist/context/subscribeToContext.js +12 -2
- package/dist/context/subscribeToContext.js.map +1 -1
- package/dist/custom-element/ToddleComponent.js +12 -4
- package/dist/custom-element/ToddleComponent.js.map +1 -1
- package/dist/custom-element.main.esm.js +29 -29
- package/dist/custom-element.main.esm.js.map +4 -4
- package/dist/editor/editorUtils.d.ts +1 -0
- package/dist/editor/editorUtils.js +14 -0
- package/dist/editor/editorUtils.js.map +1 -0
- package/dist/editor/types.d.ts +4 -0
- package/dist/editor/types.js.map +1 -1
- package/dist/editor-preview.main.js +71 -18
- package/dist/editor-preview.main.js.map +1 -1
- package/dist/events/handleAction.js +62 -31
- package/dist/events/handleAction.js.map +1 -1
- package/dist/page.main.esm.js +3 -3
- package/dist/page.main.esm.js.map +4 -4
- package/dist/page.main.js +39 -8
- package/dist/page.main.js.map +1 -1
- package/dist/utils/createFormulaCache.js.map +1 -1
- package/dist/utils/nodes.d.ts +1 -0
- package/dist/utils/nodes.js +9 -0
- package/dist/utils/nodes.js.map +1 -1
- package/dist/utils/nodes.test.d.ts +1 -0
- package/dist/utils/nodes.test.js +192 -0
- package/dist/utils/nodes.test.js.map +1 -0
- package/dist/utils/subscribeCustomProperty.d.ts +1 -1
- package/dist/utils/subscribeCustomProperty.js +8 -4
- package/dist/utils/subscribeCustomProperty.js.map +1 -1
- package/dist/utils/subscribeCustomProperty.test.d.ts +1 -0
- package/dist/utils/subscribeCustomProperty.test.js +63 -0
- package/dist/utils/subscribeCustomProperty.test.js.map +1 -0
- package/package.json +3 -3
- package/src/api/createAPI.ts +90 -46
- package/src/api/createAPIv2.ts +67 -13
- package/src/components/createComponent.ts +85 -67
- package/src/components/createElement.ts +63 -27
- package/src/components/createNode.test.ts +3 -3
- package/src/components/createNode.ts +47 -22
- package/src/components/createSlot.ts +2 -1
- package/src/components/createText.ts +34 -18
- package/src/components/renderComponent.ts +8 -1
- package/src/context/subscribeToContext.ts +12 -2
- package/src/custom-element/ToddleComponent.ts +37 -22
- package/src/editor/editorUtils.ts +13 -0
- package/src/editor/types.ts +5 -0
- package/src/editor-preview.main.ts +125 -46
- package/src/events/handleAction.ts +173 -96
- package/src/page.main.ts +64 -26
- package/src/types.d.ts +3 -0
- package/src/utils/createFormulaCache.ts +2 -2
- package/src/utils/nodes.test.ts +246 -0
- package/src/utils/nodes.ts +11 -0
- package/src/utils/subscribeCustomProperty.test.ts +78 -0
- package/src/utils/subscribeCustomProperty.ts +21 -22
package/src/api/createAPI.ts
CHANGED
|
@@ -2,9 +2,13 @@
|
|
|
2
2
|
import type { LegacyComponentAPI } from '@nordcraft/core/dist/api/apiTypes'
|
|
3
3
|
import { mapHeadersToObject } from '@nordcraft/core/dist/api/headers'
|
|
4
4
|
import type { ComponentData } from '@nordcraft/core/dist/component/component.types'
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
applyFormula,
|
|
7
|
+
isFormula,
|
|
8
|
+
type FormulaContext,
|
|
9
|
+
} from '@nordcraft/core/dist/formula/formula'
|
|
6
10
|
import type { Nullable } from '@nordcraft/core/dist/types'
|
|
7
|
-
import {
|
|
11
|
+
import { mapObject } from '@nordcraft/core/dist/utils/collections'
|
|
8
12
|
import { parseJSONWithDate } from '@nordcraft/core/dist/utils/json'
|
|
9
13
|
import { handleAction } from '../events/handleAction'
|
|
10
14
|
import type { Signal } from '../signal/signal'
|
|
@@ -35,7 +39,7 @@ export function createLegacyAPI(
|
|
|
35
39
|
api: LegacyComponentAPI,
|
|
36
40
|
data: ComponentData,
|
|
37
41
|
): ApiRequest {
|
|
38
|
-
const formulaContext = {
|
|
42
|
+
const formulaContext: FormulaContext = {
|
|
39
43
|
data,
|
|
40
44
|
component: ctx.component,
|
|
41
45
|
formulaCache: ctx.formulaCache,
|
|
@@ -43,14 +47,20 @@ export function createLegacyAPI(
|
|
|
43
47
|
package: ctx.package,
|
|
44
48
|
toddle: ctx.toddle,
|
|
45
49
|
env: ctx.env,
|
|
50
|
+
jsonPath: ctx.jsonPath,
|
|
51
|
+
reportFormulaEvaluation: ctx.reportFormulaEvaluation,
|
|
46
52
|
}
|
|
47
53
|
|
|
48
54
|
// construct the url
|
|
49
|
-
const baseUrl = applyFormula(api.url, formulaContext) ?? ''
|
|
55
|
+
const baseUrl = applyFormula(api.url, formulaContext, ['url']) ?? ''
|
|
50
56
|
const urlPath =
|
|
51
57
|
api.path && api.path.length > 0
|
|
52
58
|
? '/' +
|
|
53
|
-
api.path
|
|
59
|
+
api.path
|
|
60
|
+
.map((p, i) =>
|
|
61
|
+
applyFormula(p.formula, formulaContext, ['path', i, 'formula']),
|
|
62
|
+
)
|
|
63
|
+
.join('/')
|
|
54
64
|
: ''
|
|
55
65
|
|
|
56
66
|
// build querystring
|
|
@@ -60,25 +70,21 @@ export function createLegacyAPI(
|
|
|
60
70
|
? '?' +
|
|
61
71
|
queryParams
|
|
62
72
|
.map(
|
|
63
|
-
(param) =>
|
|
73
|
+
(param, i) =>
|
|
64
74
|
`${param.name}=${encodeURIComponent(
|
|
65
|
-
applyFormula(param.formula, formulaContext
|
|
75
|
+
applyFormula(param.formula, formulaContext, [
|
|
76
|
+
'queryParams',
|
|
77
|
+
i,
|
|
78
|
+
'formula',
|
|
79
|
+
]),
|
|
66
80
|
)}`,
|
|
67
81
|
)
|
|
68
82
|
.join('&')
|
|
69
83
|
: ''
|
|
70
84
|
const headers = isFormula(api.headers) // this is supporting a few legacy cases where the whole header object was set as a formula. This is no longer possible
|
|
71
|
-
? applyFormula(
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
formulaCache: ctx.formulaCache,
|
|
75
|
-
root: ctx.root,
|
|
76
|
-
package: ctx.package,
|
|
77
|
-
toddle: ctx.toddle,
|
|
78
|
-
env: ctx.env,
|
|
79
|
-
})
|
|
80
|
-
: mapValues(api.headers ?? {}, (value) =>
|
|
81
|
-
applyFormula(value, {
|
|
85
|
+
? applyFormula(
|
|
86
|
+
api.headers,
|
|
87
|
+
{
|
|
82
88
|
data,
|
|
83
89
|
component: ctx.component,
|
|
84
90
|
formulaCache: ctx.formulaCache,
|
|
@@ -86,7 +92,27 @@ export function createLegacyAPI(
|
|
|
86
92
|
package: ctx.package,
|
|
87
93
|
toddle: ctx.toddle,
|
|
88
94
|
env: ctx.env,
|
|
89
|
-
|
|
95
|
+
jsonPath: ctx.jsonPath,
|
|
96
|
+
reportFormulaEvaluation: ctx.reportFormulaEvaluation,
|
|
97
|
+
},
|
|
98
|
+
['headers'],
|
|
99
|
+
)
|
|
100
|
+
: mapObject(api.headers ?? {}, ([key, value]) =>
|
|
101
|
+
applyFormula(
|
|
102
|
+
value,
|
|
103
|
+
{
|
|
104
|
+
data,
|
|
105
|
+
component: ctx.component,
|
|
106
|
+
formulaCache: ctx.formulaCache,
|
|
107
|
+
root: ctx.root,
|
|
108
|
+
package: ctx.package,
|
|
109
|
+
toddle: ctx.toddle,
|
|
110
|
+
env: ctx.env,
|
|
111
|
+
jsonPath: ctx.jsonPath,
|
|
112
|
+
reportFormulaEvaluation: ctx.reportFormulaEvaluation,
|
|
113
|
+
},
|
|
114
|
+
['headers', key],
|
|
115
|
+
),
|
|
90
116
|
)
|
|
91
117
|
const contentType = String(
|
|
92
118
|
Object.entries(headers).find(
|
|
@@ -97,15 +123,21 @@ export function createLegacyAPI(
|
|
|
97
123
|
const body =
|
|
98
124
|
api.body && ['POST', 'PUT', 'PATCH', 'DELETE'].includes(method)
|
|
99
125
|
? encodeBody(
|
|
100
|
-
applyFormula(
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
126
|
+
applyFormula(
|
|
127
|
+
api.body,
|
|
128
|
+
{
|
|
129
|
+
data,
|
|
130
|
+
component: ctx.component,
|
|
131
|
+
formulaCache: ctx.formulaCache,
|
|
132
|
+
root: ctx.root,
|
|
133
|
+
package: ctx.package,
|
|
134
|
+
toddle: ctx.toddle,
|
|
135
|
+
env: ctx.env,
|
|
136
|
+
jsonPath: ctx.jsonPath,
|
|
137
|
+
reportFormulaEvaluation: ctx.reportFormulaEvaluation,
|
|
138
|
+
},
|
|
139
|
+
['body'],
|
|
140
|
+
),
|
|
109
141
|
contentType,
|
|
110
142
|
)
|
|
111
143
|
: undefined
|
|
@@ -286,15 +318,21 @@ export function createLegacyAPI(
|
|
|
286
318
|
data: null,
|
|
287
319
|
isLoading:
|
|
288
320
|
api.autoFetch &&
|
|
289
|
-
applyFormula(
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
321
|
+
applyFormula(
|
|
322
|
+
api.autoFetch,
|
|
323
|
+
{
|
|
324
|
+
data: ctx.dataSignal.get(),
|
|
325
|
+
component: ctx.component,
|
|
326
|
+
formulaCache: ctx.formulaCache,
|
|
327
|
+
root: ctx.root,
|
|
328
|
+
package: ctx.package,
|
|
329
|
+
toddle: ctx.toddle,
|
|
330
|
+
env: ctx.env,
|
|
331
|
+
jsonPath: ctx.jsonPath,
|
|
332
|
+
reportFormulaEvaluation: ctx.reportFormulaEvaluation,
|
|
333
|
+
},
|
|
334
|
+
['autoFetch'],
|
|
335
|
+
)
|
|
298
336
|
? true
|
|
299
337
|
: false,
|
|
300
338
|
error: null,
|
|
@@ -308,15 +346,21 @@ export function createLegacyAPI(
|
|
|
308
346
|
payloadSignal.subscribe((body) => {
|
|
309
347
|
if (
|
|
310
348
|
api.autoFetch &&
|
|
311
|
-
applyFormula(
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
349
|
+
applyFormula(
|
|
350
|
+
api.autoFetch,
|
|
351
|
+
{
|
|
352
|
+
data: ctx.dataSignal.get(),
|
|
353
|
+
component: ctx.component,
|
|
354
|
+
formulaCache: ctx.formulaCache,
|
|
355
|
+
root: ctx.root,
|
|
356
|
+
package: ctx.package,
|
|
357
|
+
toddle: ctx.toddle,
|
|
358
|
+
env: ctx.env,
|
|
359
|
+
jsonPath: ctx.jsonPath,
|
|
360
|
+
reportFormulaEvaluation: ctx.reportFormulaEvaluation,
|
|
361
|
+
},
|
|
362
|
+
['autoFetch'],
|
|
363
|
+
)
|
|
320
364
|
) {
|
|
321
365
|
// We should only lookup cached data for pages since
|
|
322
366
|
// we don't fetch data for component APIs during SSR
|
package/src/api/createAPIv2.ts
CHANGED
|
@@ -97,7 +97,7 @@ export function createAPI({
|
|
|
97
97
|
componentData: ComponentData | undefined,
|
|
98
98
|
): FormulaContext {
|
|
99
99
|
// Use the general formula context to evaluate the arguments of the api
|
|
100
|
-
const formulaContext = {
|
|
100
|
+
const formulaContext: FormulaContext = {
|
|
101
101
|
data: ctx.dataSignal.get(),
|
|
102
102
|
component: ctx.component,
|
|
103
103
|
formulaCache: ctx.formulaCache,
|
|
@@ -105,13 +105,15 @@ export function createAPI({
|
|
|
105
105
|
package: ctx.package,
|
|
106
106
|
toddle: ctx.toddle,
|
|
107
107
|
env: ctx.env,
|
|
108
|
+
jsonPath: ctx.jsonPath,
|
|
109
|
+
reportFormulaEvaluation: ctx.reportFormulaEvaluation,
|
|
108
110
|
}
|
|
109
111
|
|
|
110
112
|
// Make sure inputs are also available in the formula context
|
|
111
113
|
const evaluatedInputs = Object.entries(api.inputs).reduce<
|
|
112
114
|
Record<string, unknown>
|
|
113
115
|
>((acc, [key, value]) => {
|
|
114
|
-
acc[key] = applyFormula(value.formula, formulaContext)
|
|
116
|
+
acc[key] = applyFormula(value.formula, formulaContext, ['inputs', key])
|
|
115
117
|
return acc
|
|
116
118
|
}, {})
|
|
117
119
|
|
|
@@ -131,6 +133,8 @@ export function createAPI({
|
|
|
131
133
|
data,
|
|
132
134
|
toddle: ctx.toddle,
|
|
133
135
|
env: ctx.env,
|
|
136
|
+
jsonPath: ctx.jsonPath,
|
|
137
|
+
reportFormulaEvaluation: ctx.reportFormulaEvaluation,
|
|
134
138
|
}
|
|
135
139
|
}
|
|
136
140
|
|
|
@@ -140,15 +144,19 @@ export function createAPI({
|
|
|
140
144
|
([_, rule]) => rule.index,
|
|
141
145
|
)) {
|
|
142
146
|
const formulaContext = getFormulaContext(api, componentData)
|
|
143
|
-
const location = applyFormula(
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
...formulaContext
|
|
147
|
-
|
|
148
|
-
|
|
147
|
+
const location = applyFormula(
|
|
148
|
+
rule.formula,
|
|
149
|
+
{
|
|
150
|
+
...formulaContext,
|
|
151
|
+
data: {
|
|
152
|
+
...formulaContext.data,
|
|
153
|
+
Apis: {
|
|
154
|
+
[api.name]: ctx.dataSignal.get().Apis?.[api.name] as ApiStatus,
|
|
155
|
+
},
|
|
149
156
|
},
|
|
150
157
|
},
|
|
151
|
-
|
|
158
|
+
['redirectRules', ruleName],
|
|
159
|
+
)
|
|
152
160
|
if (typeof location === 'string') {
|
|
153
161
|
const url = validateUrl({
|
|
154
162
|
path: location,
|
|
@@ -282,6 +290,18 @@ export function createAPI({
|
|
|
282
290
|
},
|
|
283
291
|
},
|
|
284
292
|
})
|
|
293
|
+
|
|
294
|
+
ctx.reportFormulaEvaluation?.(['apis', api.name], {
|
|
295
|
+
isLoading: false,
|
|
296
|
+
data: data.body,
|
|
297
|
+
error: null,
|
|
298
|
+
response: {
|
|
299
|
+
status: data.status,
|
|
300
|
+
headers: data.headers,
|
|
301
|
+
performance,
|
|
302
|
+
},
|
|
303
|
+
})
|
|
304
|
+
|
|
285
305
|
const appliedRedirectRule = handleRedirectRules(api, componentData)
|
|
286
306
|
if (appliedRedirectRule) {
|
|
287
307
|
ctx.dataSignal.set({
|
|
@@ -345,6 +365,18 @@ export function createAPI({
|
|
|
345
365
|
},
|
|
346
366
|
},
|
|
347
367
|
})
|
|
368
|
+
|
|
369
|
+
ctx.reportFormulaEvaluation?.(['apis', api.name], {
|
|
370
|
+
isLoading: false,
|
|
371
|
+
data: null,
|
|
372
|
+
error: data.body,
|
|
373
|
+
response: {
|
|
374
|
+
status: data.status,
|
|
375
|
+
headers: data.headers,
|
|
376
|
+
performance,
|
|
377
|
+
},
|
|
378
|
+
})
|
|
379
|
+
|
|
348
380
|
const appliedRedirectRule = handleRedirectRules(api, componentData)
|
|
349
381
|
if (appliedRedirectRule) {
|
|
350
382
|
ctx.dataSignal.set({
|
|
@@ -400,6 +432,13 @@ export function createAPI({
|
|
|
400
432
|
},
|
|
401
433
|
},
|
|
402
434
|
})
|
|
435
|
+
|
|
436
|
+
ctx.reportFormulaEvaluation?.(['apis', api.name], {
|
|
437
|
+
isLoading: true,
|
|
438
|
+
data: ctx.dataSignal.get().Apis?.[api.name]?.data ?? null,
|
|
439
|
+
error: null,
|
|
440
|
+
})
|
|
441
|
+
|
|
403
442
|
let response
|
|
404
443
|
|
|
405
444
|
try {
|
|
@@ -407,6 +446,7 @@ export function createAPI({
|
|
|
407
446
|
? (applyFormula(
|
|
408
447
|
api.server.proxy.enabled.formula,
|
|
409
448
|
getFormulaContext(api, componentData),
|
|
449
|
+
['server', 'proxy', 'enabled'],
|
|
410
450
|
) ?? false)
|
|
411
451
|
: false
|
|
412
452
|
|
|
@@ -429,6 +469,7 @@ export function createAPI({
|
|
|
429
469
|
applyFormula(
|
|
430
470
|
api.server?.proxy?.useTemplatesInBody?.formula,
|
|
431
471
|
getFormulaContext(api, componentData),
|
|
472
|
+
['server', 'proxy', 'useTemplatesInBody'],
|
|
432
473
|
),
|
|
433
474
|
)
|
|
434
475
|
if (allowBodyTemplateValues) {
|
|
@@ -490,6 +531,7 @@ export function createAPI({
|
|
|
490
531
|
applyFormula(
|
|
491
532
|
api.client?.debounce?.formula,
|
|
492
533
|
getFormulaContext(api, componentData),
|
|
534
|
+
['client', 'debounce'],
|
|
493
535
|
),
|
|
494
536
|
)
|
|
495
537
|
})
|
|
@@ -984,15 +1026,24 @@ export function createAPI({
|
|
|
984
1026
|
payloadSignal = ctx.dataSignal.map((data) => {
|
|
985
1027
|
const payloadContext = getFormulaContext(api, data)
|
|
986
1028
|
const request = constructRequest(api, data)
|
|
1029
|
+
|
|
1030
|
+
if (ctx.reportFormulaEvaluation) {
|
|
1031
|
+
const apiStatus = data.Apis?.[api.name]
|
|
1032
|
+
if (apiStatus) {
|
|
1033
|
+
ctx.reportFormulaEvaluation(['apis', api.name], apiStatus)
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
987
1036
|
return {
|
|
988
1037
|
request,
|
|
989
1038
|
api: getApiForComparison(api),
|
|
990
1039
|
// Serialize the Headers object to be able to compare changes
|
|
991
1040
|
headers: Array.from(request.requestSettings.headers.entries()),
|
|
992
1041
|
autoFetch: api.autoFetch
|
|
993
|
-
? applyFormula(api.autoFetch, payloadContext)
|
|
1042
|
+
? applyFormula(api.autoFetch, payloadContext, ['autoFetch'])
|
|
994
1043
|
: false,
|
|
995
|
-
proxy: applyFormula(api.server?.proxy?.enabled.formula, payloadContext
|
|
1044
|
+
proxy: applyFormula(api.server?.proxy?.enabled.formula, payloadContext, [
|
|
1045
|
+
'proxy',
|
|
1046
|
+
]),
|
|
996
1047
|
}
|
|
997
1048
|
})
|
|
998
1049
|
payloadSignal.subscribe(async (apiData) => {
|
|
@@ -1050,6 +1101,7 @@ export function createAPI({
|
|
|
1050
1101
|
applyFormula(
|
|
1051
1102
|
api.autoFetch,
|
|
1052
1103
|
getFormulaContext(api, initialComponentData),
|
|
1104
|
+
['autoFetch'],
|
|
1053
1105
|
)
|
|
1054
1106
|
) {
|
|
1055
1107
|
// Execute will set the initial status of the api in the dataSignal
|
|
@@ -1155,7 +1207,8 @@ export function createAPI({
|
|
|
1155
1207
|
api = newApi
|
|
1156
1208
|
const updateContext = getFormulaContext(api, componentData)
|
|
1157
1209
|
const autoFetch =
|
|
1158
|
-
api.autoFetch &&
|
|
1210
|
+
api.autoFetch &&
|
|
1211
|
+
applyFormula(api.autoFetch, updateContext, ['autoFetch'])
|
|
1159
1212
|
if (autoFetch) {
|
|
1160
1213
|
const request = constructRequest(newApi, componentData)
|
|
1161
1214
|
payloadSignal?.set({
|
|
@@ -1165,6 +1218,7 @@ export function createAPI({
|
|
|
1165
1218
|
proxy: applyFormula(
|
|
1166
1219
|
newApi.server?.proxy?.enabled.formula,
|
|
1167
1220
|
updateContext,
|
|
1221
|
+
['proxy'],
|
|
1168
1222
|
),
|
|
1169
1223
|
// Serialize the Headers object to be able to compare changes
|
|
1170
1224
|
headers: Array.from(request.requestSettings.headers.entries()),
|
|
@@ -1174,7 +1228,7 @@ export function createAPI({
|
|
|
1174
1228
|
triggerActions: (componentData) => {
|
|
1175
1229
|
const apiData = ctx.dataSignal.get().Apis?.[api.name]
|
|
1176
1230
|
if (
|
|
1177
|
-
apiData
|
|
1231
|
+
!isDefined(apiData) ||
|
|
1178
1232
|
(apiData.data === null && apiData.error === null)
|
|
1179
1233
|
) {
|
|
1180
1234
|
return
|
|
@@ -6,9 +6,10 @@ import type {
|
|
|
6
6
|
} from '@nordcraft/core/dist/component/component.types'
|
|
7
7
|
import { applyFormula } from '@nordcraft/core/dist/formula/formula'
|
|
8
8
|
import { appendUnit } from '@nordcraft/core/dist/styling/customProperty'
|
|
9
|
-
import { mapObject } from '@nordcraft/core/dist/utils/collections'
|
|
9
|
+
import { filterObject, mapObject } from '@nordcraft/core/dist/utils/collections'
|
|
10
10
|
import { getNodeSelector } from '@nordcraft/core/dist/utils/getNodeSelector'
|
|
11
11
|
import { isDefined } from '@nordcraft/core/dist/utils/util'
|
|
12
|
+
import type { ComponentAPI } from '@nordcraft/core/src/api/apiTypes'
|
|
12
13
|
import { isContextApiV2 } from '../api/apiUtils'
|
|
13
14
|
import { createLegacyAPI } from '../api/createAPI'
|
|
14
15
|
import { createAPI } from '../api/createAPIv2'
|
|
@@ -68,6 +69,7 @@ export function createComponent({
|
|
|
68
69
|
package: ctx.package,
|
|
69
70
|
toddle: ctx.toddle,
|
|
70
71
|
env: ctx.env,
|
|
72
|
+
reportFormulaEvaluation: ctx.reportFormulaEvaluation,
|
|
71
73
|
}
|
|
72
74
|
const attributesSignal = dataSignal.map((data) => {
|
|
73
75
|
return mapObject(node.attrs, ([attr, value]) => [
|
|
@@ -84,22 +86,25 @@ export function createComponent({
|
|
|
84
86
|
const componentDataSignal = signal<ComponentData>({
|
|
85
87
|
Location: dataSignal.get().Location,
|
|
86
88
|
Attributes: attributesSignal.get(),
|
|
87
|
-
Apis: mapObject(
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
89
|
+
Apis: mapObject(
|
|
90
|
+
filterObject(component.apis ?? {}, ([_, api]) => isDefined(api)),
|
|
91
|
+
([name, api]) => [
|
|
92
|
+
name,
|
|
93
|
+
{
|
|
94
|
+
data: null,
|
|
95
|
+
isLoading:
|
|
96
|
+
api!.autoFetch &&
|
|
97
|
+
applyFormula(api!.autoFetch, {
|
|
98
|
+
...formulaCtx,
|
|
99
|
+
component,
|
|
100
|
+
data: dataSignal.get(),
|
|
101
|
+
})
|
|
102
|
+
? true
|
|
103
|
+
: false,
|
|
104
|
+
error: null,
|
|
105
|
+
},
|
|
106
|
+
],
|
|
107
|
+
),
|
|
103
108
|
})
|
|
104
109
|
|
|
105
110
|
// Subscribe to global stores (currently only theme)
|
|
@@ -132,18 +137,51 @@ export function createComponent({
|
|
|
132
137
|
|
|
133
138
|
// Call the abort signal if the component's datasignal is destroyed (component unmounted) to cancel any pending requests
|
|
134
139
|
const abortController = new AbortController()
|
|
135
|
-
componentDataSignal.subscribe(
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
140
|
+
componentDataSignal.subscribe(
|
|
141
|
+
(data) => {
|
|
142
|
+
Object.entries(data.Variables ?? {}).forEach(([name, value]) => {
|
|
143
|
+
ctx.reportFormulaEvaluation?.(['variables', name], value)
|
|
144
|
+
})
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
destroy: () =>
|
|
148
|
+
abortController.abort(`Component ${component.name} unmounted`),
|
|
149
|
+
},
|
|
150
|
+
)
|
|
139
151
|
const formulaCache = createFormulaCache(component)
|
|
140
152
|
|
|
141
153
|
// Note: this function must run procedurally to ensure apis (which are in correct order) can reference each other
|
|
142
154
|
const apis: Record<string, ContextApi> = {}
|
|
143
|
-
sortApiObjects(
|
|
144
|
-
(
|
|
145
|
-
|
|
146
|
-
|
|
155
|
+
sortApiObjects(
|
|
156
|
+
Object.entries(component.apis ?? {}).filter(
|
|
157
|
+
(entry): entry is [string, ComponentAPI] => isDefined(entry[1]),
|
|
158
|
+
),
|
|
159
|
+
).forEach(([name, api]) => {
|
|
160
|
+
if (isLegacyApi(api)) {
|
|
161
|
+
apis[name] = createLegacyAPI(api, {
|
|
162
|
+
...ctx,
|
|
163
|
+
apis,
|
|
164
|
+
component,
|
|
165
|
+
dataSignal: componentDataSignal,
|
|
166
|
+
abortSignal: abortController.signal,
|
|
167
|
+
isRootComponent: false,
|
|
168
|
+
formulaCache,
|
|
169
|
+
package: node.package ?? ctx.package,
|
|
170
|
+
triggerEvent: (eventTrigger, data) => {
|
|
171
|
+
const eventHandler = Object.values(node.events).find(
|
|
172
|
+
(e) => e.trigger === eventTrigger,
|
|
173
|
+
)
|
|
174
|
+
if (eventHandler) {
|
|
175
|
+
eventHandler.actions?.forEach((action) =>
|
|
176
|
+
handleAction(action, { ...dataSignal.get(), Event: data }, ctx),
|
|
177
|
+
)
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
})
|
|
181
|
+
} else {
|
|
182
|
+
apis[name] = createAPI({
|
|
183
|
+
apiRequest: api,
|
|
184
|
+
ctx: {
|
|
147
185
|
...ctx,
|
|
148
186
|
apis,
|
|
149
187
|
component,
|
|
@@ -162,39 +200,11 @@ export function createComponent({
|
|
|
162
200
|
)
|
|
163
201
|
}
|
|
164
202
|
},
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
...ctx,
|
|
171
|
-
apis,
|
|
172
|
-
component,
|
|
173
|
-
dataSignal: componentDataSignal,
|
|
174
|
-
abortSignal: abortController.signal,
|
|
175
|
-
isRootComponent: false,
|
|
176
|
-
formulaCache,
|
|
177
|
-
package: node.package ?? ctx.package,
|
|
178
|
-
triggerEvent: (eventTrigger, data) => {
|
|
179
|
-
const eventHandler = Object.values(node.events).find(
|
|
180
|
-
(e) => e.trigger === eventTrigger,
|
|
181
|
-
)
|
|
182
|
-
if (eventHandler) {
|
|
183
|
-
eventHandler.actions?.forEach((action) =>
|
|
184
|
-
handleAction(
|
|
185
|
-
action,
|
|
186
|
-
{ ...dataSignal.get(), Event: data },
|
|
187
|
-
ctx,
|
|
188
|
-
),
|
|
189
|
-
)
|
|
190
|
-
}
|
|
191
|
-
},
|
|
192
|
-
},
|
|
193
|
-
componentData: componentDataSignal.get(),
|
|
194
|
-
})
|
|
195
|
-
}
|
|
196
|
-
},
|
|
197
|
-
)
|
|
203
|
+
},
|
|
204
|
+
componentData: componentDataSignal.get(),
|
|
205
|
+
})
|
|
206
|
+
}
|
|
207
|
+
})
|
|
198
208
|
Object.values(apis)
|
|
199
209
|
.filter(isContextApiV2)
|
|
200
210
|
.forEach((api) => {
|
|
@@ -221,15 +231,21 @@ export function createComponent({
|
|
|
221
231
|
.map(([name, formula]) => [
|
|
222
232
|
name,
|
|
223
233
|
componentDataSignal.map((data) =>
|
|
224
|
-
applyFormula(
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
234
|
+
applyFormula(
|
|
235
|
+
formula.formula,
|
|
236
|
+
{
|
|
237
|
+
data,
|
|
238
|
+
component,
|
|
239
|
+
formulaCache: ctx.formulaCache,
|
|
240
|
+
root: ctx.root,
|
|
241
|
+
package: ctx.package,
|
|
242
|
+
toddle: ctx.toddle,
|
|
243
|
+
env: ctx.env,
|
|
244
|
+
jsonPath: ctx.jsonPath,
|
|
245
|
+
reportFormulaEvaluation: ctx.reportFormulaEvaluation,
|
|
246
|
+
},
|
|
247
|
+
['formulas', name],
|
|
248
|
+
),
|
|
233
249
|
),
|
|
234
250
|
]),
|
|
235
251
|
)
|
|
@@ -301,6 +317,8 @@ export function createComponent({
|
|
|
301
317
|
node.id === 'root'
|
|
302
318
|
? { ...instance, [ctx.component.name]: 'root' }
|
|
303
319
|
: { [ctx.component.name]: node.id ?? '' },
|
|
320
|
+
jsonPath: ctx.jsonPath,
|
|
321
|
+
reportFormulaEvaluation: ctx.reportFormulaEvaluation,
|
|
304
322
|
})
|
|
305
323
|
|
|
306
324
|
// Custom properties instance overrides are added after the child tree is rendered to ensure correct order
|