@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.
Files changed (74) hide show
  1. package/dist/api/createAPI.js +29 -11
  2. package/dist/api/createAPI.js.map +1 -1
  3. package/dist/api/createAPIv2.js +49 -11
  4. package/dist/api/createAPIv2.js.map +1 -1
  5. package/dist/components/createComponent.js +14 -5
  6. package/dist/components/createComponent.js.map +1 -1
  7. package/dist/components/createElement.js +48 -16
  8. package/dist/components/createElement.js.map +1 -1
  9. package/dist/components/createNode.js +23 -10
  10. package/dist/components/createNode.js.map +1 -1
  11. package/dist/components/createNode.test.js +3 -3
  12. package/dist/components/createNode.test.js.map +1 -1
  13. package/dist/components/createSlot.js +2 -1
  14. package/dist/components/createSlot.js.map +1 -1
  15. package/dist/components/createText.js +7 -2
  16. package/dist/components/createText.js.map +1 -1
  17. package/dist/components/renderComponent.d.ts +4 -1
  18. package/dist/components/renderComponent.js +4 -2
  19. package/dist/components/renderComponent.js.map +1 -1
  20. package/dist/context/subscribeToContext.js +12 -2
  21. package/dist/context/subscribeToContext.js.map +1 -1
  22. package/dist/custom-element/ToddleComponent.js +12 -4
  23. package/dist/custom-element/ToddleComponent.js.map +1 -1
  24. package/dist/custom-element.main.esm.js +29 -29
  25. package/dist/custom-element.main.esm.js.map +4 -4
  26. package/dist/editor/editorUtils.d.ts +1 -0
  27. package/dist/editor/editorUtils.js +14 -0
  28. package/dist/editor/editorUtils.js.map +1 -0
  29. package/dist/editor/types.d.ts +4 -0
  30. package/dist/editor/types.js.map +1 -1
  31. package/dist/editor-preview.main.js +71 -18
  32. package/dist/editor-preview.main.js.map +1 -1
  33. package/dist/events/handleAction.js +62 -31
  34. package/dist/events/handleAction.js.map +1 -1
  35. package/dist/page.main.esm.js +3 -3
  36. package/dist/page.main.esm.js.map +4 -4
  37. package/dist/page.main.js +39 -8
  38. package/dist/page.main.js.map +1 -1
  39. package/dist/utils/createFormulaCache.js.map +1 -1
  40. package/dist/utils/nodes.d.ts +1 -0
  41. package/dist/utils/nodes.js +9 -0
  42. package/dist/utils/nodes.js.map +1 -1
  43. package/dist/utils/nodes.test.d.ts +1 -0
  44. package/dist/utils/nodes.test.js +192 -0
  45. package/dist/utils/nodes.test.js.map +1 -0
  46. package/dist/utils/subscribeCustomProperty.d.ts +1 -1
  47. package/dist/utils/subscribeCustomProperty.js +8 -4
  48. package/dist/utils/subscribeCustomProperty.js.map +1 -1
  49. package/dist/utils/subscribeCustomProperty.test.d.ts +1 -0
  50. package/dist/utils/subscribeCustomProperty.test.js +63 -0
  51. package/dist/utils/subscribeCustomProperty.test.js.map +1 -0
  52. package/package.json +3 -3
  53. package/src/api/createAPI.ts +90 -46
  54. package/src/api/createAPIv2.ts +67 -13
  55. package/src/components/createComponent.ts +85 -67
  56. package/src/components/createElement.ts +63 -27
  57. package/src/components/createNode.test.ts +3 -3
  58. package/src/components/createNode.ts +47 -22
  59. package/src/components/createSlot.ts +2 -1
  60. package/src/components/createText.ts +34 -18
  61. package/src/components/renderComponent.ts +8 -1
  62. package/src/context/subscribeToContext.ts +12 -2
  63. package/src/custom-element/ToddleComponent.ts +37 -22
  64. package/src/editor/editorUtils.ts +13 -0
  65. package/src/editor/types.ts +5 -0
  66. package/src/editor-preview.main.ts +125 -46
  67. package/src/events/handleAction.ts +173 -96
  68. package/src/page.main.ts +64 -26
  69. package/src/types.d.ts +3 -0
  70. package/src/utils/createFormulaCache.ts +2 -2
  71. package/src/utils/nodes.test.ts +246 -0
  72. package/src/utils/nodes.ts +11 -0
  73. package/src/utils/subscribeCustomProperty.test.ts +78 -0
  74. package/src/utils/subscribeCustomProperty.ts +21 -22
@@ -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 { applyFormula, isFormula } from '@nordcraft/core/dist/formula/formula'
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 { mapValues } from '@nordcraft/core/dist/utils/collections'
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.map((p) => applyFormula(p.formula, formulaContext)).join('/')
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(api.headers, {
72
- data,
73
- component: ctx.component,
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(api.body, {
101
- data,
102
- component: ctx.component,
103
- formulaCache: ctx.formulaCache,
104
- root: ctx.root,
105
- package: ctx.package,
106
- toddle: ctx.toddle,
107
- env: ctx.env,
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(api.autoFetch, {
290
- data: ctx.dataSignal.get(),
291
- component: ctx.component,
292
- formulaCache: ctx.formulaCache,
293
- root: ctx.root,
294
- package: ctx.package,
295
- toddle: ctx.toddle,
296
- env: ctx.env,
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(api.autoFetch, {
312
- data: ctx.dataSignal.get(),
313
- component: ctx.component,
314
- formulaCache: ctx.formulaCache,
315
- root: ctx.root,
316
- package: ctx.package,
317
- toddle: ctx.toddle,
318
- env: ctx.env,
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
@@ -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(rule.formula, {
144
- ...formulaContext,
145
- data: {
146
- ...formulaContext.data,
147
- Apis: {
148
- [api.name]: ctx.dataSignal.get().Apis?.[api.name] as ApiStatus,
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 && applyFormula(api.autoFetch, updateContext)
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 === undefined ||
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(component.apis ?? {}, ([name, api]) => [
88
- name,
89
- {
90
- data: null,
91
- isLoading:
92
- api.autoFetch &&
93
- applyFormula(api.autoFetch, {
94
- ...formulaCtx,
95
- component,
96
- data: dataSignal.get(),
97
- })
98
- ? true
99
- : false,
100
- error: null,
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
- destroy: () =>
137
- abortController.abort(`Component ${component.name} unmounted`),
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(Object.entries(component.apis ?? {})).forEach(
144
- ([name, api]) => {
145
- if (isLegacyApi(api)) {
146
- apis[name] = createLegacyAPI(api, {
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
- } else {
167
- apis[name] = createAPI({
168
- apiRequest: api,
169
- ctx: {
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(formula.formula, {
225
- data,
226
- component,
227
- formulaCache: ctx.formulaCache,
228
- root: ctx.root,
229
- package: ctx.package,
230
- toddle: ctx.toddle,
231
- env: ctx.env,
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