@oneblink/sdk-core 10.1.0-beta.8 → 10.1.0-beta.9
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.
|
@@ -115,4 +115,21 @@ declare const fixElementName: (elementName: string) => string;
|
|
|
115
115
|
* @returns
|
|
116
116
|
*/
|
|
117
117
|
declare function injectFormElementsIntoForm(form: FormTypes.Form, forms: FormTypes.Form[], injectAuthenticatedForms?: boolean): FormTypes.FormElement[];
|
|
118
|
-
|
|
118
|
+
/**
|
|
119
|
+
* Async counterpart to {@link injectFormElementsIntoForm}. Injects embedded
|
|
120
|
+
* `form` / `infoPage` elements for each form in `forms`. Uses `getForm` to load
|
|
121
|
+
* embedded forms and caches results by id for the duration of the call so each
|
|
122
|
+
* form is retrieved at most once across the whole batch.
|
|
123
|
+
*
|
|
124
|
+
* Mutates each form object in `forms` in place (the array entries are updated
|
|
125
|
+
* by reference); nothing is returned. Forms returned from `getForm` are not
|
|
126
|
+
* mutated — their element trees are cloned before embedding.
|
|
127
|
+
*
|
|
128
|
+
* @param forms The forms to inject elements into (mutated in place)
|
|
129
|
+
* @param getForm Retrieves a single form by id when it is referenced by a
|
|
130
|
+
* `form` / `infoPage` element
|
|
131
|
+
* @param injectAuthenticatedForms Indicates whether forms requiring
|
|
132
|
+
* authentication should be injected, defaults to true
|
|
133
|
+
*/
|
|
134
|
+
declare function injectFormElementsIntoForms(forms: FormTypes.Form[], getForm: (formId: number) => Promise<FormTypes.Form | undefined>, injectAuthenticatedForms?: boolean): Promise<void>;
|
|
135
|
+
export { forEachFormElement, forEachFormElementWithOptions, findFormElement, parseDynamicFormElementOptions, flattenFormElements, determineIsInfoPage, fixElementName, injectFormElementsIntoForm, injectFormElementsIntoForms, };
|
|
@@ -252,37 +252,24 @@ function injectFormElements(elements, forms, parentIds, injectAuthenticatedForms
|
|
|
252
252
|
element.elements = childElements;
|
|
253
253
|
}
|
|
254
254
|
if (element.type === 'form' || element.type === 'infoPage') {
|
|
255
|
-
const
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
|
|
255
|
+
const resolved = resolveEmbeddedFormElement(element, forms.find((form) => element.formId === form.id), parentIds, injectAuthenticatedForms);
|
|
256
|
+
switch (resolved.type) {
|
|
257
|
+
case 'replace': {
|
|
258
|
+
newElements.push(resolved.element);
|
|
259
|
+
break;
|
|
260
|
+
}
|
|
261
|
+
case 'skip': {
|
|
262
|
+
break;
|
|
263
|
+
}
|
|
264
|
+
case 'continue': {
|
|
265
|
+
// Clone so inject mutations (e.g. containers rewritten when cycle
|
|
266
|
+
// edges are omitted) do not alter the source form, which may be
|
|
267
|
+
// shared via the forms list.
|
|
268
|
+
element.elements = injectFormElements(structuredClone(resolved.form.elements), forms, [...parentIds, resolved.form.id], injectAuthenticatedForms);
|
|
269
|
+
newElements.push(element);
|
|
270
|
+
break;
|
|
271
|
+
}
|
|
266
272
|
}
|
|
267
|
-
if (formToInject.isAuthenticated && !injectAuthenticatedForms) {
|
|
268
|
-
console.log(`No form elements injected for element id: ${element.id}, as request was unauthenticated and target form (form id: ${formToInject.id}) requires authentication.`);
|
|
269
|
-
const newElement = {
|
|
270
|
-
...element,
|
|
271
|
-
type: 'html',
|
|
272
|
-
name: 'Form_requires_authenticated',
|
|
273
|
-
label: 'Form Requires Authentication.',
|
|
274
|
-
defaultValue: 'Unable to display the embedded form for this element, as the form requires authentication. Please login and refresh to view this embedded form.',
|
|
275
|
-
};
|
|
276
|
-
newElements.push(newElement);
|
|
277
|
-
return newElements;
|
|
278
|
-
}
|
|
279
|
-
const injectingParentForm = parentIds && parentIds.find((id) => element.formId === id);
|
|
280
|
-
if (injectingParentForm) {
|
|
281
|
-
console.log(`Infinite loop was detected while attempting to inject form id: ${injectingParentForm}. Ignoring elements...`);
|
|
282
|
-
return newElements;
|
|
283
|
-
}
|
|
284
|
-
element.elements = injectFormElements(formToInject.elements, forms, [...parentIds, formToInject.id], injectAuthenticatedForms);
|
|
285
|
-
newElements.push(element);
|
|
286
273
|
}
|
|
287
274
|
else {
|
|
288
275
|
newElements.push(element);
|
|
@@ -290,5 +277,104 @@ function injectFormElements(elements, forms, parentIds, injectAuthenticatedForms
|
|
|
290
277
|
return newElements;
|
|
291
278
|
}, []);
|
|
292
279
|
}
|
|
293
|
-
|
|
280
|
+
function resolveEmbeddedFormElement(element, formToInject, parentIds, injectAuthenticatedForms) {
|
|
281
|
+
if (!formToInject) {
|
|
282
|
+
return {
|
|
283
|
+
type: 'replace',
|
|
284
|
+
element: {
|
|
285
|
+
...element,
|
|
286
|
+
type: 'html',
|
|
287
|
+
name: 'Form_not_found',
|
|
288
|
+
label: 'Form not found.',
|
|
289
|
+
defaultValue: 'Unable to display the embedded form for this element, as the form was not found. Please contact your Administrator.',
|
|
290
|
+
},
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
if (formToInject.isAuthenticated && !injectAuthenticatedForms) {
|
|
294
|
+
console.log(`No form elements injected for element id: ${element.id}, as request was unauthenticated and target form (form id: ${formToInject.id}) requires authentication.`);
|
|
295
|
+
return {
|
|
296
|
+
type: 'replace',
|
|
297
|
+
element: {
|
|
298
|
+
...element,
|
|
299
|
+
type: 'html',
|
|
300
|
+
name: 'Form_requires_authenticated',
|
|
301
|
+
label: 'Form Requires Authentication.',
|
|
302
|
+
defaultValue: 'Unable to display the embedded form for this element, as the form requires authentication. Please login and refresh to view this embedded form.',
|
|
303
|
+
},
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
const injectingParentForm = parentIds.find((id) => element.formId === id);
|
|
307
|
+
if (injectingParentForm) {
|
|
308
|
+
console.log(`Infinite loop was detected while attempting to inject form id: ${injectingParentForm}. Ignoring elements...`);
|
|
309
|
+
return { type: 'skip' };
|
|
310
|
+
}
|
|
311
|
+
return { type: 'continue', form: formToInject };
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Async counterpart to {@link injectFormElementsIntoForm}. Injects embedded
|
|
315
|
+
* `form` / `infoPage` elements for each form in `forms`. Uses `getForm` to load
|
|
316
|
+
* embedded forms and caches results by id for the duration of the call so each
|
|
317
|
+
* form is retrieved at most once across the whole batch.
|
|
318
|
+
*
|
|
319
|
+
* Mutates each form object in `forms` in place (the array entries are updated
|
|
320
|
+
* by reference); nothing is returned. Forms returned from `getForm` are not
|
|
321
|
+
* mutated — their element trees are cloned before embedding.
|
|
322
|
+
*
|
|
323
|
+
* @param forms The forms to inject elements into (mutated in place)
|
|
324
|
+
* @param getForm Retrieves a single form by id when it is referenced by a
|
|
325
|
+
* `form` / `infoPage` element
|
|
326
|
+
* @param injectAuthenticatedForms Indicates whether forms requiring
|
|
327
|
+
* authentication should be injected, defaults to true
|
|
328
|
+
*/
|
|
329
|
+
async function injectFormElementsIntoForms(forms, getForm, injectAuthenticatedForms = true) {
|
|
330
|
+
const formCache = new Map();
|
|
331
|
+
const getFormCached = async (formId) => {
|
|
332
|
+
if (formCache.has(formId)) {
|
|
333
|
+
return formCache.get(formId);
|
|
334
|
+
}
|
|
335
|
+
const retrieved = (await getForm(formId)) ?? undefined;
|
|
336
|
+
formCache.set(formId, retrieved);
|
|
337
|
+
return retrieved;
|
|
338
|
+
};
|
|
339
|
+
for (const form of forms) {
|
|
340
|
+
form.elements = await injectFormElementsAsync(form.elements, getFormCached, [form.id], injectAuthenticatedForms);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
async function injectFormElementsAsync(elements, getForm, parentIds, injectAuthenticatedForms) {
|
|
344
|
+
const newElements = [];
|
|
345
|
+
for (const element of elements) {
|
|
346
|
+
if ((element.type === 'page' ||
|
|
347
|
+
element.type === 'repeatableSet' ||
|
|
348
|
+
element.type === 'section') &&
|
|
349
|
+
Array.isArray(element.elements)) {
|
|
350
|
+
element.elements = await injectFormElementsAsync(element.elements, getForm, parentIds, injectAuthenticatedForms);
|
|
351
|
+
}
|
|
352
|
+
if (element.type === 'form' || element.type === 'infoPage') {
|
|
353
|
+
const form = await getForm(element.formId);
|
|
354
|
+
const resolved = resolveEmbeddedFormElement(element, form, parentIds, injectAuthenticatedForms);
|
|
355
|
+
switch (resolved.type) {
|
|
356
|
+
case 'replace': {
|
|
357
|
+
newElements.push(resolved.element);
|
|
358
|
+
break;
|
|
359
|
+
}
|
|
360
|
+
case 'skip': {
|
|
361
|
+
break;
|
|
362
|
+
}
|
|
363
|
+
case 'continue': {
|
|
364
|
+
// Clone so inject mutations (e.g. containers rewritten when cycle
|
|
365
|
+
// edges are omitted) do not alter the source form, which may be
|
|
366
|
+
// cached or a later batch root.
|
|
367
|
+
element.elements = await injectFormElementsAsync(structuredClone(resolved.form.elements), getForm, [...parentIds, resolved.form.id], injectAuthenticatedForms);
|
|
368
|
+
newElements.push(element);
|
|
369
|
+
break;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
else {
|
|
374
|
+
newElements.push(element);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
return newElements;
|
|
378
|
+
}
|
|
379
|
+
export { forEachFormElement, forEachFormElementWithOptions, findFormElement, parseDynamicFormElementOptions, flattenFormElements, determineIsInfoPage, fixElementName, injectFormElementsIntoForm, injectFormElementsIntoForms, };
|
|
294
380
|
//# sourceMappingURL=formElementsService.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"formElementsService.js","sourceRoot":"","sources":["../src/formElementsService.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAC5C,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAA;AAEhE;;;;;;;;;;;;;;GAcG;AACH,SAAS,kBAAkB,CACzB,QAAiC,EACjC,OAGS;IAET,eAAe,CAAC,QAAQ,EAAE,CAAC,WAAW,EAAE,cAAc,EAAE,EAAE;QACxD,OAAO,CAAC,WAAW,EAAE,cAAc,CAAC,CAAA;QACpC,OAAO,KAAK,CAAA;IACd,CAAC,CAAC,CAAA;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,SAAS,6BAA6B,CACpC,QAAiC,EACjC,OAGS;IAET,eAAe,CAAC,QAAQ,EAAE,CAAC,WAAW,EAAE,cAAc,EAAE,EAAE;QACxD,MAAM,kBAAkB,GACtB,eAAe,CAAC,YAAY,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAA;QAC5D,IAAI,kBAAkB,EAAE,CAAC;YACvB,OAAO,CAAC,kBAAkB,EAAE,cAAc,CAAC,CAAA;QAC7C,CAAC;QACD,OAAO,KAAK,CAAA;IACd,CAAC,CAAC,CAAA;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,SAAS,eAAe,CACtB,QAAiC,EACjC,SAGY,EACZ,iBAA0C,EAAE;IAE5C,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,SAAS,CAAC,OAAO,EAAE,cAAc,CAAC,EAAE,CAAC;YACvC,OAAO,OAAO,CAAA;QAChB,CAAC;QAED,IACE,CAAC,OAAO,CAAC,IAAI,KAAK,eAAe;YAC/B,OAAO,CAAC,IAAI,KAAK,MAAM;YACvB,OAAO,CAAC,IAAI,KAAK,MAAM;YACvB,OAAO,CAAC,IAAI,KAAK,UAAU;YAC3B,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC;YAC7B,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,EAC/B,CAAC;YACD,MAAM,aAAa,GAAG,eAAe,CAAC,OAAO,CAAC,QAAQ,EAAE,SAAS,EAAE;gBACjE,GAAG,cAAc;gBACjB,OAAO;aACR,CAAC,CAAA;YAEF,IAAI,aAAa,EAAE,CAAC;gBAClB,OAAO,aAAa,CAAA;YACtB,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,SAAS,8BAA8B,CACrC,IAAa;IAEb,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,CAAA;IACX,CAAC;IACD,OAAO,IAAI,CAAC,MAAM,CAChB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE;QACzB,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC/B,OAAO,CAAC,IAAI,CAAC;gBACX,KAAK,EAAE,MAAM;gBACb,KAAK,EAAE,MAAM;aACd,CAAC,CAAA;QACJ,CAAC;aAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;YACtC,MAAM,MAAM,GAAG,MAAiC,CAAA;YAChD,MAAM,KAAK,GACT,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,KAAK;gBAC9C,CAAC,CAAC,MAAM,CAAC,KAAK;gBACd,CAAC,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAA;YACtB,MAAM,KAAK,GACT,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,KAAK;gBAC9C,CAAC,CAAC,MAAM,CAAC,KAAK;gBACd,CAAC,CAAC,KAAK,CAAA;YACX,MAAM,MAAM,GACV,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM;gBAChD,CAAC,CAAC,MAAM,CAAC,MAAM;gBACf,CAAC,CAAC,SAAS,CAAA;YACf,MAAM,aAAa,GACjB,OAAO,MAAM,CAAC,aAAa,KAAK,SAAS;gBACvC,CAAC,CAAC,MAAM,CAAC,aAAa;gBACtB,CAAC,CAAC,SAAS,CAAA;YACf,MAAM,QAAQ,GACZ,OAAO,MAAM,CAAC,QAAQ,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ;gBACpD,CAAC,CAAC,MAAM,CAAC,QAAQ;gBACjB,CAAC,CAAC,SAAS,CAAA;YACf,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC;gBACjD,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAEtB,CAAC,IAAI,EAAE,SAAkB,EAAE,EAAE;oBAC7B,IACE,OAAO,SAAS,KAAK,QAAQ;wBAC7B,SAAS;wBACT,OAAO,IAAI,SAAS;wBACpB,OAAO,SAAS,CAAC,KAAK,KAAK,QAAQ;wBACnC,OAAO,IAAI,SAAS;wBACpB,OAAO,SAAS,CAAC,KAAK,KAAK,QAAQ,EACnC,CAAC;wBACD,IAAI,CAAC,IAAI,CAAC;4BACR,KAAK,EAAE,SAAS,CAAC,KAAK;4BACtB,KAAK,EAAE,SAAS,CAAC,KAAK;yBACvB,CAAC,CAAA;oBACJ,CAAC;oBACD,OAAO,IAAI,CAAA;gBACb,CAAC,EAAE,EAAE,CAAC;gBACR,CAAC,CAAC,SAAS,CAAA;YACb,OAAO,CAAC,IAAI,CAAC;gBACX,KAAK;gBACL,KAAK;gBACL,MAAM;gBACN,UAAU;gBACV,aAAa;gBACb,QAAQ;gBACR,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC;oBACpC,CAAC,CAAC,8BAA8B,CAAC,MAAM,CAAC,OAAO,CAAC;oBAChD,CAAC,CAAC,SAAS;aACd,CAAC,CAAA;QACJ,CAAC;QACD,OAAO,OAAO,CAAA;IAChB,CAAC,EACD,EAAE,CACH,CAAA;AACH,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,SAAS,mBAAmB,CAC1B,QAAiC;IAEjC,OAAO,QAAQ,CAAC,MAAM,CACpB,CAAC,iBAAiB,EAAE,OAAO,EAAE,EAAE;QAC7B,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QAC/B,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;YACrB,KAAK,SAAS,CAAC;YACf,KAAK,MAAM,CAAC,CAAC,CAAC;gBACZ,iBAAiB,CAAC,IAAI,CAAC,GAAG,mBAAmB,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAA;YAClE,CAAC;QACH,CAAC;QACD,OAAO,iBAAiB,CAAA;IAC1B,CAAC,EACD,EAAE,CACH,CAAA;AACH,CAAC;AAED,MAAM,gBAAgB,GAAgC;IACpD,SAAS;IACT,MAAM;IACN,OAAO;IACP,SAAS;IACT,MAAM;IACN,UAAU;IACV,MAAM;CACP,CAAA;AACD;;;;;;GAMG;AACH,SAAS,mBAAmB,CAAC,IAAoB;IAC/C,MAAM,iBAAiB,GAAG,eAAe,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE;QAC7D,OAAO,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;IAC3C,CAAC,CAAC,CAAA;IACF,OAAO,CAAC,iBAAiB,CAAA;AAC3B,CAAC;AAED;;;;;GAKG;AACH,MAAM,cAAc,GAAG,CAAC,WAAmB,EAAE,EAAE;IAC7C,yEAAyE;IACzE,+BAA+B;IAC/B,OAAO,WAAW;SACf,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC;SACxB,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,IAAI,EAAE,CAAA;AACX,CAAC,CAAA;AAED;;;;;;;;;;GAUG;AACH,SAAS,0BAA0B,CACjC,IAAoB,EACpB,KAAuB,EACvB,wBAAwB,GAAG,IAAI;IAE/B,MAAM,yBAAyB,GAAG,kBAAkB,CAClD,IAAI,CAAC,QAAQ,EACb,KAAK,EACL,CAAC,IAAI,CAAC,EAAE,CAAC,EACT,wBAAwB,CACzB,CAAA;IACD,IAAI,CAAC,QAAQ,GAAG,yBAAyB,CAAA;IACzC,OAAO,IAAI,CAAC,QAAQ,CAAA;AACtB,CAAC;AAED,SAAS,kBAAkB,CACzB,QAAiC,EACjC,KAAuB,EACvB,SAAmB,EACnB,wBAAiC;IAEjC,OAAO,QAAQ,CAAC,MAAM,CAA0B,CAAC,WAAW,EAAE,OAAO,EAAE,EAAE;QACvE,IACE,CAAC,OAAO,CAAC,IAAI,KAAK,MAAM;YACtB,OAAO,CAAC,IAAI,KAAK,eAAe;YAChC,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC;YAC7B,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,EAC/B,CAAC;YACD,MAAM,aAAa,GAAG,kBAAkB,CACtC,OAAO,CAAC,QAAQ,EAChB,KAAK,EACL,SAAS,EACT,wBAAwB,CACzB,CAAA;YACD,OAAO,CAAC,QAAQ,GAAG,aAAa,CAAA;QAClC,CAAC;QAED,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,IAAI,OAAO,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YAC3D,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,KAAK,IAAI,CAAC,EAAE,CAAC,CAAA;YAErE,IAAI,CAAC,YAAY,EAAE,CAAC;gBAClB,MAAM,UAAU,GAA0B;oBACxC,GAAG,OAAO;oBACV,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,gBAAgB;oBACtB,KAAK,EAAE,iBAAiB;oBACxB,YAAY,EACV,qHAAqH;iBACxH,CAAA;gBACD,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;gBAC5B,OAAO,WAAW,CAAA;YACpB,CAAC;YAED,IAAI,YAAY,CAAC,eAAe,IAAI,CAAC,wBAAwB,EAAE,CAAC;gBAC9D,OAAO,CAAC,GAAG,CACT,6CAA6C,OAAO,CAAC,EAAE,8DAA8D,YAAY,CAAC,EAAE,4BAA4B,CACjK,CAAA;gBAED,MAAM,UAAU,GAA0B;oBACxC,GAAG,OAAO;oBACV,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,6BAA6B;oBACnC,KAAK,EAAE,+BAA+B;oBACtC,YAAY,EACV,iJAAiJ;iBACpJ,CAAA;gBACD,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;gBAC5B,OAAO,WAAW,CAAA;YACpB,CAAC;YAED,MAAM,mBAAmB,GACvB,SAAS,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,KAAK,EAAE,CAAC,CAAA;YAE5D,IAAI,mBAAmB,EAAE,CAAC;gBACxB,OAAO,CAAC,GAAG,CACT,kEAAkE,mBAAmB,wBAAwB,CAC9G,CAAA;gBACD,OAAO,WAAW,CAAA;YACpB,CAAC;YAED,OAAO,CAAC,QAAQ,GAAG,kBAAkB,CACnC,YAAY,CAAC,QAAQ,EACrB,KAAK,EACL,CAAC,GAAG,SAAS,EAAE,YAAY,CAAC,EAAE,CAAC,EAC/B,wBAAwB,CACzB,CAAA;YACD,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QAC3B,CAAC;aAAM,CAAC;YACN,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QAC3B,CAAC;QAED,OAAO,WAAW,CAAA;IACpB,CAAC,EAAE,EAAE,CAAC,CAAA;AACR,CAAC;AAED,OAAO,EACL,kBAAkB,EAClB,6BAA6B,EAC7B,eAAe,EACf,8BAA8B,EAC9B,mBAAmB,EACnB,mBAAmB,EACnB,cAAc,EACd,0BAA0B,GAC3B,CAAA","sourcesContent":["import { FormTypes } from '@oneblink/types'\nimport { typeCastService } from './index.js'\nexport { matchElementsTagRegex } from './form-elements-regex.js'\n\n/**\n * Iterate over all form elements, also iterating over nested form element (e.g.\n * page elements).\n *\n * #### Example\n *\n * ```js\n * formElementsService.forEachFormElement(form.elements, (formElement) => {\n * // do something with formElement\n * })\n * ```\n *\n * @param elements The form elements to iterate over\n * @param forEach Function to execute on each form element\n */\nfunction forEachFormElement(\n elements: FormTypes.FormElement[],\n forEach: (\n element: FormTypes.FormElement,\n elements: FormTypes.FormElement[],\n ) => void,\n): void {\n findFormElement(elements, (formElement, parentElements) => {\n forEach(formElement, parentElements)\n return false\n })\n}\n\n/**\n * Iterate over all form elements that have options (e.g. `'select'` type\n * elements), also iterating over nested form element (e.g. page elements).\n *\n * #### Example\n *\n * ```js\n * formElementsService.forEachFormElementWithOptions(\n * form.elements,\n * (formElementWithOptions) => {\n * // do something with formElementWithOptions\n * },\n * )\n * ```\n *\n * @param elements The form elements to iterate over\n * @param forEach Function to execute on each form element with options\n */\nfunction forEachFormElementWithOptions(\n elements: FormTypes.FormElement[],\n forEach: (\n elementWithOptions: FormTypes.FormElementWithOptions,\n elements: FormTypes.FormElement[],\n ) => void,\n): void {\n findFormElement(elements, (formElement, parentElements) => {\n const optionsFormElement =\n typeCastService.formElements.toOptionsElement(formElement)\n if (optionsFormElement) {\n forEach(optionsFormElement, parentElements)\n }\n return false\n })\n}\n\n/**\n * Iterate over all form elements and return an element that matches a\n * predicate, also iterating over nested form element (e.g. page elements). Will\n * return `undefined` if no matching element is found.\n *\n * #### Example\n *\n * ```js\n * const formElement = formElementsService.findFormElement(\n * form.elements,\n * (formElement) => {\n * return formElement.id === '123-abc'\n * },\n * )\n * ```\n *\n * @param elements The form elements to iterate over\n * @param predicate Predicate function to execute on each form element\n * @param parentElements\n * @returns\n */\nfunction findFormElement(\n elements: FormTypes.FormElement[],\n predicate: (\n element: FormTypes.FormElement,\n elements: FormTypes.FormElement[],\n ) => boolean,\n parentElements: FormTypes.FormElement[] = [],\n): FormTypes.FormElement | undefined {\n for (const element of elements) {\n if (predicate(element, parentElements)) {\n return element\n }\n\n if (\n (element.type === 'repeatableSet' ||\n element.type === 'page' ||\n element.type === 'form' ||\n element.type === 'infoPage' ||\n element.type === 'section') &&\n Array.isArray(element.elements)\n ) {\n const nestedElement = findFormElement(element.elements, predicate, [\n ...parentElements,\n element,\n ])\n\n if (nestedElement) {\n return nestedElement\n }\n }\n }\n}\n\n/**\n * Parse unknown data as valid dynamic options for a forms element. This will\n * always return an Array of valid dynamic options.\n *\n * #### Example\n *\n * ```js\n * const options = formElementsService.parseDynamicFormElementOptions(data)\n * // \"options\" are valid for a form element\n * ```\n *\n * @param data\n * @returns\n */\nfunction parseDynamicFormElementOptions(\n data: unknown,\n): FormTypes.DynamicChoiceElementOption[] {\n if (!Array.isArray(data)) {\n return []\n }\n return data.reduce<FormTypes.DynamicChoiceElementOption[]>(\n (options, record, index) => {\n if (typeof record === 'string') {\n options.push({\n value: record,\n label: record,\n })\n } else if (typeof record === 'object') {\n const option = record as Record<string, unknown>\n const value =\n typeof option.value === 'string' && option.value\n ? option.value\n : index.toString()\n const label =\n typeof option.label === 'string' && option.label\n ? option.label\n : value\n const colour =\n typeof option.colour === 'string' && option.colour\n ? option.colour\n : undefined\n const displayAlways =\n typeof option.displayAlways === 'boolean'\n ? option.displayAlways\n : undefined\n const imageUrl =\n typeof option.imageUrl === 'string' && option.imageUrl\n ? option.imageUrl\n : undefined\n const attributes = Array.isArray(option.attributes)\n ? option.attributes.reduce<\n FormTypes.DynamicChoiceElementOptionAttribute[]\n >((memo, attribute: unknown) => {\n if (\n typeof attribute === 'object' &&\n attribute &&\n 'value' in attribute &&\n typeof attribute.value === 'string' &&\n 'label' in attribute &&\n typeof attribute.label === 'string'\n ) {\n memo.push({\n value: attribute.value,\n label: attribute.label,\n })\n }\n return memo\n }, [])\n : undefined\n options.push({\n value,\n label,\n colour,\n attributes,\n displayAlways,\n imageUrl,\n options: Array.isArray(option.options)\n ? parseDynamicFormElementOptions(option.options)\n : undefined,\n })\n }\n return options\n },\n [],\n )\n}\n\n/**\n * Takes the nested definition structure and returns all form elements as 1d\n * array.\n *\n * #### Example\n *\n * ```js\n * const flattenedElements = formElementsService.flattenFormElements(\n * form.elements,\n * )\n * ```\n *\n * @param elements\n * @returns\n */\nfunction flattenFormElements(\n elements: FormTypes.FormElement[],\n): FormTypes.FormElement[] {\n return elements.reduce<FormTypes.FormElement[]>(\n (flattenedElements, element) => {\n flattenedElements.push(element)\n switch (element.type) {\n case 'section':\n case 'page': {\n flattenedElements.push(...flattenFormElements(element.elements))\n }\n }\n return flattenedElements\n },\n [],\n )\n}\n\nconst infoPageElements: FormTypes.FormElementType[] = [\n 'heading',\n 'html',\n 'image',\n 'section',\n 'page',\n 'infoPage',\n 'form',\n]\n/**\n * Determine a form is considered an info page. This means the form does not\n * allow any user input.\n *\n * @param form\n * @returns\n */\nfunction determineIsInfoPage(form: FormTypes.Form): boolean {\n const foundInputElement = findFormElement(form.elements, (e) => {\n return !infoPageElements.includes(e.type)\n })\n return !foundInputElement\n}\n\n/**\n * Remove invalid characters from a form element name.\n *\n * @param elementName\n * @returns\n */\nconst fixElementName = (elementName: string) => {\n // removes characters that aren't letters, numbers, underscores or dashes\n // replaces empty spaces with _\n return elementName\n .replace(/[^-\\w\\s]/g, '')\n .replace(/\\s/g, '_')\n .trim()\n}\n\n/**\n * Injects the elements of any elements with type `FORM` or `INFOPAGE` into the\n * form\n *\n * @param form The form to inject elements into\n * @param forms The forms that will be used to inject elements from if\n * referenced\n * @param injectAuthenticatedForms Indicates whether forms requiring\n * authentication should be injected, defaults to true\n * @returns\n */\nfunction injectFormElementsIntoForm(\n form: FormTypes.Form,\n forms: FormTypes.Form[],\n injectAuthenticatedForms = true,\n): FormTypes.FormElement[] {\n const elementsWithInjectedForms = injectFormElements(\n form.elements,\n forms,\n [form.id],\n injectAuthenticatedForms,\n )\n form.elements = elementsWithInjectedForms\n return form.elements\n}\n\nfunction injectFormElements(\n elements: FormTypes.FormElement[],\n forms: FormTypes.Form[],\n parentIds: number[],\n injectAuthenticatedForms: boolean,\n): FormTypes.FormElement[] {\n return elements.reduce<FormTypes.FormElement[]>((newElements, element) => {\n if (\n (element.type === 'page' ||\n element.type === 'repeatableSet' ||\n element.type === 'section') &&\n Array.isArray(element.elements)\n ) {\n const childElements = injectFormElements(\n element.elements,\n forms,\n parentIds,\n injectAuthenticatedForms,\n )\n element.elements = childElements\n }\n\n if (element.type === 'form' || element.type === 'infoPage') {\n const formToInject = forms.find((form) => element.formId === form.id)\n\n if (!formToInject) {\n const newElement: FormTypes.HtmlElement = {\n ...element,\n type: 'html',\n name: 'Form_not_found',\n label: 'Form not found.',\n defaultValue:\n 'Unable to display the embedded form for this element, as the form was not found. Please contact your Administrator.',\n }\n newElements.push(newElement)\n return newElements\n }\n\n if (formToInject.isAuthenticated && !injectAuthenticatedForms) {\n console.log(\n `No form elements injected for element id: ${element.id}, as request was unauthenticated and target form (form id: ${formToInject.id}) requires authentication.`,\n )\n\n const newElement: FormTypes.HtmlElement = {\n ...element,\n type: 'html',\n name: 'Form_requires_authenticated',\n label: 'Form Requires Authentication.',\n defaultValue:\n 'Unable to display the embedded form for this element, as the form requires authentication. Please login and refresh to view this embedded form.',\n }\n newElements.push(newElement)\n return newElements\n }\n\n const injectingParentForm =\n parentIds && parentIds.find((id) => element.formId === id)\n\n if (injectingParentForm) {\n console.log(\n `Infinite loop was detected while attempting to inject form id: ${injectingParentForm}. Ignoring elements...`,\n )\n return newElements\n }\n\n element.elements = injectFormElements(\n formToInject.elements,\n forms,\n [...parentIds, formToInject.id],\n injectAuthenticatedForms,\n )\n newElements.push(element)\n } else {\n newElements.push(element)\n }\n\n return newElements\n }, [])\n}\n\nexport {\n forEachFormElement,\n forEachFormElementWithOptions,\n findFormElement,\n parseDynamicFormElementOptions,\n flattenFormElements,\n determineIsInfoPage,\n fixElementName,\n injectFormElementsIntoForm,\n}\n"]}
|
|
1
|
+
{"version":3,"file":"formElementsService.js","sourceRoot":"","sources":["../src/formElementsService.ts"],"names":[],"mappings":"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","sourcesContent":["import { FormTypes } from '@oneblink/types'\nimport { typeCastService } from './index.js'\nexport { matchElementsTagRegex } from './form-elements-regex.js'\n\n/**\n * Iterate over all form elements, also iterating over nested form element (e.g.\n * page elements).\n *\n * #### Example\n *\n * ```js\n * formElementsService.forEachFormElement(form.elements, (formElement) => {\n * // do something with formElement\n * })\n * ```\n *\n * @param elements The form elements to iterate over\n * @param forEach Function to execute on each form element\n */\nfunction forEachFormElement(\n elements: FormTypes.FormElement[],\n forEach: (\n element: FormTypes.FormElement,\n elements: FormTypes.FormElement[],\n ) => void,\n): void {\n findFormElement(elements, (formElement, parentElements) => {\n forEach(formElement, parentElements)\n return false\n })\n}\n\n/**\n * Iterate over all form elements that have options (e.g. `'select'` type\n * elements), also iterating over nested form element (e.g. page elements).\n *\n * #### Example\n *\n * ```js\n * formElementsService.forEachFormElementWithOptions(\n * form.elements,\n * (formElementWithOptions) => {\n * // do something with formElementWithOptions\n * },\n * )\n * ```\n *\n * @param elements The form elements to iterate over\n * @param forEach Function to execute on each form element with options\n */\nfunction forEachFormElementWithOptions(\n elements: FormTypes.FormElement[],\n forEach: (\n elementWithOptions: FormTypes.FormElementWithOptions,\n elements: FormTypes.FormElement[],\n ) => void,\n): void {\n findFormElement(elements, (formElement, parentElements) => {\n const optionsFormElement =\n typeCastService.formElements.toOptionsElement(formElement)\n if (optionsFormElement) {\n forEach(optionsFormElement, parentElements)\n }\n return false\n })\n}\n\n/**\n * Iterate over all form elements and return an element that matches a\n * predicate, also iterating over nested form element (e.g. page elements). Will\n * return `undefined` if no matching element is found.\n *\n * #### Example\n *\n * ```js\n * const formElement = formElementsService.findFormElement(\n * form.elements,\n * (formElement) => {\n * return formElement.id === '123-abc'\n * },\n * )\n * ```\n *\n * @param elements The form elements to iterate over\n * @param predicate Predicate function to execute on each form element\n * @param parentElements\n * @returns\n */\nfunction findFormElement(\n elements: FormTypes.FormElement[],\n predicate: (\n element: FormTypes.FormElement,\n elements: FormTypes.FormElement[],\n ) => boolean,\n parentElements: FormTypes.FormElement[] = [],\n): FormTypes.FormElement | undefined {\n for (const element of elements) {\n if (predicate(element, parentElements)) {\n return element\n }\n\n if (\n (element.type === 'repeatableSet' ||\n element.type === 'page' ||\n element.type === 'form' ||\n element.type === 'infoPage' ||\n element.type === 'section') &&\n Array.isArray(element.elements)\n ) {\n const nestedElement = findFormElement(element.elements, predicate, [\n ...parentElements,\n element,\n ])\n\n if (nestedElement) {\n return nestedElement\n }\n }\n }\n}\n\n/**\n * Parse unknown data as valid dynamic options for a forms element. This will\n * always return an Array of valid dynamic options.\n *\n * #### Example\n *\n * ```js\n * const options = formElementsService.parseDynamicFormElementOptions(data)\n * // \"options\" are valid for a form element\n * ```\n *\n * @param data\n * @returns\n */\nfunction parseDynamicFormElementOptions(\n data: unknown,\n): FormTypes.DynamicChoiceElementOption[] {\n if (!Array.isArray(data)) {\n return []\n }\n return data.reduce<FormTypes.DynamicChoiceElementOption[]>(\n (options, record, index) => {\n if (typeof record === 'string') {\n options.push({\n value: record,\n label: record,\n })\n } else if (typeof record === 'object') {\n const option = record as Record<string, unknown>\n const value =\n typeof option.value === 'string' && option.value\n ? option.value\n : index.toString()\n const label =\n typeof option.label === 'string' && option.label\n ? option.label\n : value\n const colour =\n typeof option.colour === 'string' && option.colour\n ? option.colour\n : undefined\n const displayAlways =\n typeof option.displayAlways === 'boolean'\n ? option.displayAlways\n : undefined\n const imageUrl =\n typeof option.imageUrl === 'string' && option.imageUrl\n ? option.imageUrl\n : undefined\n const attributes = Array.isArray(option.attributes)\n ? option.attributes.reduce<\n FormTypes.DynamicChoiceElementOptionAttribute[]\n >((memo, attribute: unknown) => {\n if (\n typeof attribute === 'object' &&\n attribute &&\n 'value' in attribute &&\n typeof attribute.value === 'string' &&\n 'label' in attribute &&\n typeof attribute.label === 'string'\n ) {\n memo.push({\n value: attribute.value,\n label: attribute.label,\n })\n }\n return memo\n }, [])\n : undefined\n options.push({\n value,\n label,\n colour,\n attributes,\n displayAlways,\n imageUrl,\n options: Array.isArray(option.options)\n ? parseDynamicFormElementOptions(option.options)\n : undefined,\n })\n }\n return options\n },\n [],\n )\n}\n\n/**\n * Takes the nested definition structure and returns all form elements as 1d\n * array.\n *\n * #### Example\n *\n * ```js\n * const flattenedElements = formElementsService.flattenFormElements(\n * form.elements,\n * )\n * ```\n *\n * @param elements\n * @returns\n */\nfunction flattenFormElements(\n elements: FormTypes.FormElement[],\n): FormTypes.FormElement[] {\n return elements.reduce<FormTypes.FormElement[]>(\n (flattenedElements, element) => {\n flattenedElements.push(element)\n switch (element.type) {\n case 'section':\n case 'page': {\n flattenedElements.push(...flattenFormElements(element.elements))\n }\n }\n return flattenedElements\n },\n [],\n )\n}\n\nconst infoPageElements: FormTypes.FormElementType[] = [\n 'heading',\n 'html',\n 'image',\n 'section',\n 'page',\n 'infoPage',\n 'form',\n]\n/**\n * Determine a form is considered an info page. This means the form does not\n * allow any user input.\n *\n * @param form\n * @returns\n */\nfunction determineIsInfoPage(form: FormTypes.Form): boolean {\n const foundInputElement = findFormElement(form.elements, (e) => {\n return !infoPageElements.includes(e.type)\n })\n return !foundInputElement\n}\n\n/**\n * Remove invalid characters from a form element name.\n *\n * @param elementName\n * @returns\n */\nconst fixElementName = (elementName: string) => {\n // removes characters that aren't letters, numbers, underscores or dashes\n // replaces empty spaces with _\n return elementName\n .replace(/[^-\\w\\s]/g, '')\n .replace(/\\s/g, '_')\n .trim()\n}\n\n/**\n * Injects the elements of any elements with type `FORM` or `INFOPAGE` into the\n * form\n *\n * @param form The form to inject elements into\n * @param forms The forms that will be used to inject elements from if\n * referenced\n * @param injectAuthenticatedForms Indicates whether forms requiring\n * authentication should be injected, defaults to true\n * @returns\n */\nfunction injectFormElementsIntoForm(\n form: FormTypes.Form,\n forms: FormTypes.Form[],\n injectAuthenticatedForms = true,\n): FormTypes.FormElement[] {\n const elementsWithInjectedForms = injectFormElements(\n form.elements,\n forms,\n [form.id],\n injectAuthenticatedForms,\n )\n form.elements = elementsWithInjectedForms\n return form.elements\n}\n\nfunction injectFormElements(\n elements: FormTypes.FormElement[],\n forms: FormTypes.Form[],\n parentIds: number[],\n injectAuthenticatedForms: boolean,\n): FormTypes.FormElement[] {\n return elements.reduce<FormTypes.FormElement[]>((newElements, element) => {\n if (\n (element.type === 'page' ||\n element.type === 'repeatableSet' ||\n element.type === 'section') &&\n Array.isArray(element.elements)\n ) {\n const childElements = injectFormElements(\n element.elements,\n forms,\n parentIds,\n injectAuthenticatedForms,\n )\n element.elements = childElements\n }\n\n if (element.type === 'form' || element.type === 'infoPage') {\n const resolved = resolveEmbeddedFormElement(\n element,\n forms.find((form) => element.formId === form.id),\n parentIds,\n injectAuthenticatedForms,\n )\n\n switch (resolved.type) {\n case 'replace': {\n newElements.push(resolved.element)\n break\n }\n case 'skip': {\n break\n }\n case 'continue': {\n // Clone so inject mutations (e.g. containers rewritten when cycle\n // edges are omitted) do not alter the source form, which may be\n // shared via the forms list.\n element.elements = injectFormElements(\n structuredClone(resolved.form.elements),\n forms,\n [...parentIds, resolved.form.id],\n injectAuthenticatedForms,\n )\n newElements.push(element)\n break\n }\n }\n } else {\n newElements.push(element)\n }\n\n return newElements\n }, [])\n}\n\ntype ResolveEmbeddedFormResult =\n | { type: 'replace'; element: FormTypes.HtmlElement }\n | { type: 'skip' }\n | { type: 'continue'; form: FormTypes.Form }\n\nfunction resolveEmbeddedFormElement(\n element: FormTypes.FormFormElement,\n formToInject: FormTypes.Form | undefined,\n parentIds: number[],\n injectAuthenticatedForms: boolean,\n): ResolveEmbeddedFormResult {\n if (!formToInject) {\n return {\n type: 'replace',\n element: {\n ...element,\n type: 'html',\n name: 'Form_not_found',\n label: 'Form not found.',\n defaultValue:\n 'Unable to display the embedded form for this element, as the form was not found. Please contact your Administrator.',\n },\n }\n }\n\n if (formToInject.isAuthenticated && !injectAuthenticatedForms) {\n console.log(\n `No form elements injected for element id: ${element.id}, as request was unauthenticated and target form (form id: ${formToInject.id}) requires authentication.`,\n )\n\n return {\n type: 'replace',\n element: {\n ...element,\n type: 'html',\n name: 'Form_requires_authenticated',\n label: 'Form Requires Authentication.',\n defaultValue:\n 'Unable to display the embedded form for this element, as the form requires authentication. Please login and refresh to view this embedded form.',\n },\n }\n }\n\n const injectingParentForm = parentIds.find((id) => element.formId === id)\n\n if (injectingParentForm) {\n console.log(\n `Infinite loop was detected while attempting to inject form id: ${injectingParentForm}. Ignoring elements...`,\n )\n return { type: 'skip' }\n }\n\n return { type: 'continue', form: formToInject }\n}\n\n/**\n * Async counterpart to {@link injectFormElementsIntoForm}. Injects embedded\n * `form` / `infoPage` elements for each form in `forms`. Uses `getForm` to load\n * embedded forms and caches results by id for the duration of the call so each\n * form is retrieved at most once across the whole batch.\n *\n * Mutates each form object in `forms` in place (the array entries are updated\n * by reference); nothing is returned. Forms returned from `getForm` are not\n * mutated — their element trees are cloned before embedding.\n *\n * @param forms The forms to inject elements into (mutated in place)\n * @param getForm Retrieves a single form by id when it is referenced by a\n * `form` / `infoPage` element\n * @param injectAuthenticatedForms Indicates whether forms requiring\n * authentication should be injected, defaults to true\n */\nasync function injectFormElementsIntoForms(\n forms: FormTypes.Form[],\n getForm: (formId: number) => Promise<FormTypes.Form | undefined>,\n injectAuthenticatedForms = true,\n): Promise<void> {\n const formCache = new Map<number, FormTypes.Form | undefined>()\n\n const getFormCached = async (formId: number) => {\n if (formCache.has(formId)) {\n return formCache.get(formId)\n }\n const retrieved = (await getForm(formId)) ?? undefined\n formCache.set(formId, retrieved)\n return retrieved\n }\n\n for (const form of forms) {\n form.elements = await injectFormElementsAsync(\n form.elements,\n getFormCached,\n [form.id],\n injectAuthenticatedForms,\n )\n }\n}\n\nasync function injectFormElementsAsync(\n elements: FormTypes.FormElement[],\n getForm: (formId: number) => Promise<FormTypes.Form | undefined>,\n parentIds: number[],\n injectAuthenticatedForms: boolean,\n): Promise<FormTypes.FormElement[]> {\n const newElements: FormTypes.FormElement[] = []\n\n for (const element of elements) {\n if (\n (element.type === 'page' ||\n element.type === 'repeatableSet' ||\n element.type === 'section') &&\n Array.isArray(element.elements)\n ) {\n element.elements = await injectFormElementsAsync(\n element.elements,\n getForm,\n parentIds,\n injectAuthenticatedForms,\n )\n }\n\n if (element.type === 'form' || element.type === 'infoPage') {\n const form = await getForm(element.formId)\n const resolved = resolveEmbeddedFormElement(\n element,\n form,\n parentIds,\n injectAuthenticatedForms,\n )\n\n switch (resolved.type) {\n case 'replace': {\n newElements.push(resolved.element)\n break\n }\n case 'skip': {\n break\n }\n case 'continue': {\n // Clone so inject mutations (e.g. containers rewritten when cycle\n // edges are omitted) do not alter the source form, which may be\n // cached or a later batch root.\n element.elements = await injectFormElementsAsync(\n structuredClone(resolved.form.elements),\n getForm,\n [...parentIds, resolved.form.id],\n injectAuthenticatedForms,\n )\n newElements.push(element)\n break\n }\n }\n } else {\n newElements.push(element)\n }\n }\n\n return newElements\n}\n\nexport {\n forEachFormElement,\n forEachFormElementWithOptions,\n findFormElement,\n parseDynamicFormElementOptions,\n flattenFormElements,\n determineIsInfoPage,\n fixElementName,\n injectFormElementsIntoForm,\n injectFormElementsIntoForms,\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oneblink/sdk-core",
|
|
3
3
|
"description": "OneBlink SDK for JavaScript (works in Browsers and NodeJS)",
|
|
4
|
-
"version": "10.1.0-beta.
|
|
4
|
+
"version": "10.1.0-beta.9",
|
|
5
5
|
"author": "OneBlink <developers@oneblink.io> (https://oneblink.io)",
|
|
6
6
|
"bugs": {
|
|
7
7
|
"url": "https://github.com/oneblink/sdk-core-js/issues"
|