@wise/dynamic-flow-client 5.6.0 → 5.6.2

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/build/main.js CHANGED
@@ -416,7 +416,7 @@ var ja_default = {
416
416
  "dynamicFlows.FileUploadSchema.maxFileSizeError": "\u5927\u5909\u7533\u3057\u8A33\u3054\u3056\u3044\u307E\u305B\u3093\u304C\u3001\u30D5\u30A1\u30A4\u30EB\u304C\u5927\u304D\u3059\u304E\u307E\u3059\u3002\u3053\u308C\u3088\u308A\u5C0F\u3055\u3044\u30D5\u30A1\u30A4\u30EB\u3092\u30A2\u30C3\u30D7\u30ED\u30FC\u30C9\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
417
417
  "dynamicFlows.FileUploadSchema.wrongFileTypeError": "\u305D\u306E\u30D5\u30A1\u30A4\u30EB\u5F62\u5F0F\u306F\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002\u5225\u306E\u30D5\u30A1\u30A4\u30EB\u3092\u30A2\u30C3\u30D7\u30ED\u30FC\u30C9\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
418
418
  "dynamicFlows.Help.ariaLabel": "\u8A73\u7D30\u306F\u3053\u3061\u3089\u3092\u30AF\u30EA\u30C3\u30AF\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
419
- "dynamicFlows.MultiSelect.summary": "{first}\u3068\u305D\u306E\u4ED6{count}",
419
+ "dynamicFlows.MultiSelect.summary": "{first}\u3068\u305D\u306E\u4ED6{count}\u30AA\u30D7\u30B7\u30E7\u30F3",
420
420
  "dynamicFlows.MultipleFileUploadSchema.maxFileSizeError": "\u5927\u5909\u7533\u3057\u8A33\u3054\u3056\u3044\u307E\u305B\u3093\u304C\u3001\u30D5\u30A1\u30A4\u30EB\u304C\u5927\u304D\u3059\u304E\u307E\u3059\u3002\u3053\u308C\u3088\u308A\u5C0F\u3055\u3044\u30D5\u30A1\u30A4\u30EB\u3092\u30A2\u30C3\u30D7\u30ED\u30FC\u30C9\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
421
421
  "dynamicFlows.MultipleFileUploadSchema.maxItemsError": "{maxItems}\u500B\u4EE5\u4E0B\u306E\u30D5\u30A1\u30A4\u30EB\u3092\u30A2\u30C3\u30D7\u30ED\u30FC\u30C9\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
422
422
  "dynamicFlows.MultipleFileUploadSchema.minItemsError": "{minItems}\u500B\u4EE5\u4E0A\u306E\u30D5\u30A1\u30A4\u30EB\u3092\u30A2\u30C3\u30D7\u30ED\u30FC\u30C9\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
@@ -2317,6 +2317,35 @@ var modalToComponent = (uid, { content, title }, mapperProps, schemaComponents)
2317
2317
  mapperProps.onComponentUpdate
2318
2318
  );
2319
2319
 
2320
+ // src/domain/components/step/ExternalConfirmationComponent.ts
2321
+ var createExternalConfirmation = (uid, url, onComponentUpdate) => {
2322
+ const update = getInputUpdateFunction(onComponentUpdate);
2323
+ return {
2324
+ type: "external-confirmation",
2325
+ kind: "layout",
2326
+ uid,
2327
+ url,
2328
+ status: "initial",
2329
+ onSuccess() {
2330
+ update(this, (draft) => {
2331
+ draft.status = "success";
2332
+ });
2333
+ },
2334
+ onFailure() {
2335
+ if (this.status === "initial") {
2336
+ update(this, (draft) => {
2337
+ draft.status = "failure";
2338
+ });
2339
+ }
2340
+ },
2341
+ onCancel() {
2342
+ update(this, (draft) => {
2343
+ draft.status = "dismissed";
2344
+ });
2345
+ }
2346
+ };
2347
+ };
2348
+
2320
2349
  // src/utils/recursiveMerge.ts
2321
2350
  function recursiveMerge(valueA, valueB) {
2322
2351
  if (valueA === null) {
@@ -2356,526 +2385,162 @@ function mergeArrays(valueA, valueB) {
2356
2385
  );
2357
2386
  }
2358
2387
 
2359
- // src/controller/getErrorMessage.ts
2360
- var getErrorMessage = (error) => {
2361
- return error instanceof Error ? error.message : typeof error === "string" ? error : `Unknown Error: type is ${typeof error}`;
2362
- };
2388
+ // src/utils/component-utils.ts
2389
+ var getSubmittableData = async (components) => Promise.all(components.map(async (component) => component.getSubmittableValue())).then(
2390
+ (values) => values.reduce((acc, value) => recursiveMerge(acc, value), null)
2391
+ );
2392
+ var getSubmittableDataSync = (components) => components.map((component) => component.getSubmittableValueSync()).reduce((acc, value) => recursiveMerge(acc, value), null);
2393
+ var getLocalValues = (components) => components.map((component) => component.getLocalValue()).reduce((acc, value) => recursiveMerge(acc, value), null);
2363
2394
 
2364
- // src/controller/response-utils.ts
2365
- var import_spec = require("@wise/dynamic-flow-types/spec");
2366
- var parseResponseBodyAsJsonElement = async (response) => {
2367
- assertResponseIsValid(response);
2368
- try {
2369
- return await response.json();
2370
- } catch (e) {
2371
- return null;
2372
- }
2373
- };
2374
- var parseResponseBodyAsText = async (response) => {
2375
- try {
2376
- return await response.text();
2377
- } catch (e) {
2378
- return null;
2379
- }
2395
+ // src/domain/components/step/StepDomainComponent.ts
2396
+ var createStepComponent = (stepProps) => {
2397
+ const _a = stepProps, { uid, stepPolling, stepRefreshAfter, stepPrefetch, onComponentUpdate } = _a, rest = __objRest(_a, ["uid", "stepPolling", "stepRefreshAfter", "stepPrefetch", "onComponentUpdate"]);
2398
+ const update = getInputUpdateFunction(onComponentUpdate);
2399
+ const component = __spreadProps(__spreadValues({
2400
+ uid
2401
+ }, rest), {
2402
+ type: "step",
2403
+ kind: "step",
2404
+ modals: [],
2405
+ requestCache: stepPrefetch.requestCache,
2406
+ dismissModal() {
2407
+ var _a2;
2408
+ (_a2 = this.modals.at(-1)) == null ? void 0 : _a2.close();
2409
+ },
2410
+ dismissAllModals() {
2411
+ this._update((draft) => {
2412
+ draft.modals = draft.modals.map((m) => __spreadProps(__spreadValues({}, m), { open: false }));
2413
+ });
2414
+ },
2415
+ showModal(modal) {
2416
+ this._update((draft) => {
2417
+ draft.modals = [...draft.modals, modal];
2418
+ });
2419
+ },
2420
+ _update(updateFn) {
2421
+ update(this, updateFn);
2422
+ },
2423
+ getChildren() {
2424
+ return this.externalConfirmation ? [...this.layoutComponents, this.externalConfirmation] : this.layoutComponents;
2425
+ },
2426
+ getModals() {
2427
+ return this.modals;
2428
+ },
2429
+ async getSubmittableValue() {
2430
+ return getSubmittableData(this.schemaComponents);
2431
+ },
2432
+ getSubmittableValueSync() {
2433
+ return getSubmittableDataSync(this.schemaComponents);
2434
+ },
2435
+ getLocalValue() {
2436
+ return getLocalValues(this.schemaComponents);
2437
+ },
2438
+ validate() {
2439
+ return this.schemaComponents.every(
2440
+ (inputComponent) => inputComponent.isSchemaReferencedInStep ? inputComponent.validate() : true
2441
+ );
2442
+ },
2443
+ setLoadingState(loadingState) {
2444
+ this._update((draft) => {
2445
+ draft.loadingState = loadingState;
2446
+ });
2447
+ },
2448
+ start() {
2449
+ stepPolling == null ? void 0 : stepPolling.start();
2450
+ stepRefreshAfter == null ? void 0 : stepRefreshAfter.start();
2451
+ stepPrefetch.start(this.getSubmittableValueSync());
2452
+ },
2453
+ stop() {
2454
+ stepPolling == null ? void 0 : stepPolling.stop();
2455
+ stepRefreshAfter == null ? void 0 : stepRefreshAfter.stop();
2456
+ stepPrefetch.stop();
2457
+ this._update((draft) => {
2458
+ draft.modals = [];
2459
+ });
2460
+ }
2461
+ });
2462
+ return component;
2380
2463
  };
2381
- function isActionResponseBody(body) {
2382
- return (0, import_spec.validateActionResponse)(body).valid;
2383
- }
2384
- function assertActionResponseBody(body) {
2385
- if (!isObject(body) || !isObject(body.action)) {
2386
- throw new Error(
2387
- "Incorrect response body in action response. Expected an object satisfying the type { action: Action }."
2388
- );
2464
+
2465
+ // src/domain/features/polling/getStepPolling.ts
2466
+ var getStepPolling = ({
2467
+ pollingConfig,
2468
+ logEvent,
2469
+ onBehavior,
2470
+ onPoll,
2471
+ registerSubmissionBehavior
2472
+ }) => {
2473
+ const { interval, delay = interval, maxAttempts, url, onError } = pollingConfig;
2474
+ let abortController = new AbortController();
2475
+ let intervalRef = null;
2476
+ if (delay == null) {
2477
+ throw new Error("Polling configuration must include delay or interval");
2389
2478
  }
2390
- }
2391
- function assertModalResponseBody(body) {
2392
- if (isObject(body)) {
2393
- if ("content" in body && isArray(body.content)) {
2479
+ const onErrorBehavior = getDomainLayerBehavior(onError, [], registerSubmissionBehavior);
2480
+ let attempts = 0;
2481
+ const poll = () => {
2482
+ attempts += 1;
2483
+ abortController.abort();
2484
+ abortController = new AbortController();
2485
+ const { signal } = abortController;
2486
+ onPoll(url, onErrorBehavior, signal).then((result) => {
2487
+ if (result) {
2488
+ stop();
2489
+ return;
2490
+ }
2491
+ if (attempts >= maxAttempts && !signal.aborted) {
2492
+ void onBehavior(onErrorBehavior);
2493
+ stop();
2494
+ }
2495
+ }).catch(() => {
2496
+ });
2497
+ };
2498
+ const start = () => {
2499
+ attempts = 0;
2500
+ intervalRef = setInterval(poll, delay * 1e3);
2501
+ poll();
2502
+ };
2503
+ const stop = () => {
2504
+ if (!intervalRef) {
2505
+ logEvent("warning", "Attempted to stop polling but it was not started");
2394
2506
  return;
2395
2507
  }
2396
- }
2397
- throw new Error(
2398
- "Incorrect response body in modal response. Expected an object satisfying the type { title?: string, components: Layout[] }."
2399
- );
2400
- }
2401
- function assertSubflowResponseBody(body) {
2402
- const { valid } = (0, import_spec.validateSubflowResponse)(body);
2403
- if (valid) {
2404
- return;
2405
- }
2406
- throw new Error("Incorrect response body in subflow response.");
2407
- }
2408
- function isErrorResponseBody(body) {
2409
- return Boolean(
2410
- isObject(body) && (body.refreshFormUrl || body.refreshUrl || body.validation || body.error || body.analytics)
2411
- );
2412
- }
2413
- function assertStepResponseBody(body) {
2414
- if (!isObject(body)) {
2415
- throw new Error("Incorrect response body in step response. Expected an object.");
2416
- }
2417
- }
2418
- var assertResponseIsValid = (response) => {
2419
- if (!isResponse(response)) {
2420
- throw new Error("Incorrect type of response from fetch. Expected object of type Response.");
2421
- }
2422
- if (response.bodyUsed) {
2423
- throw new Error(
2424
- "The body of the provided Response object has already been used. Every request must respond with a new Response object."
2425
- );
2426
- }
2508
+ clearTimeout(intervalRef);
2509
+ abortController.abort();
2510
+ };
2511
+ return { start, stop };
2427
2512
  };
2428
- var isResponse = (response) => typeof response === "object" && response !== null && "clone" in response && "bodyUsed" in response;
2429
2513
 
2430
- // src/controller/handleErrorResponse.ts
2431
- var handleErrorResponse = async (response, actionId, trackEvent) => {
2432
- const body = await parseResponseBodyAsJsonElement(response.clone());
2433
- if (isErrorResponseBody(body)) {
2434
- const refreshUrl = body.refreshUrl || body.refreshFormUrl;
2435
- const { error, validation, analytics } = body;
2436
- trackEvent("Action Failed", __spreadProps(__spreadValues({}, analytics), { actionId, statusCode: response.status }));
2437
- const errors = { error, validation };
2438
- return refreshUrl ? { type: "refresh", body: { refreshUrl, errors } } : {
2439
- type: "error",
2440
- body: { errors, analytics },
2441
- httpError: { statusCode: response.status }
2442
- };
2514
+ // src/domain/features/refreshAfter/getStepRefreshAfter.ts
2515
+ var ONE_SECOND = 1e3;
2516
+ var getStepRefreshAfter = ({
2517
+ refreshAfter,
2518
+ logEvent,
2519
+ onBehavior
2520
+ }) => {
2521
+ let timeout = null;
2522
+ const targetTime = new Date(refreshAfter).getTime();
2523
+ if (typeof refreshAfter !== "string" || Number.isNaN(targetTime)) {
2524
+ throw new Error(`Invalid refreshAfter value: ${String(refreshAfter)}`);
2443
2525
  }
2444
- trackEvent("Action Failed", { actionId, statusCode: response.status });
2445
- const errorMessage = await parseResponseBodyAsText(response);
2526
+ const start = () => {
2527
+ const timeLeft = Math.max(targetTime - Date.now(), ONE_SECOND);
2528
+ timeout = setTimeout(() => {
2529
+ void onBehavior({ type: "refresh", analytics: { schema: "refreshAfter" } });
2530
+ }, timeLeft);
2531
+ };
2446
2532
  return {
2447
- type: "error",
2448
- httpError: {
2449
- message: errorMessage || void 0,
2450
- statusCode: response.status
2533
+ start,
2534
+ stop: () => {
2535
+ if (!timeout) {
2536
+ logEvent("warning", "Attempted to stop refreshAfter but it was not started");
2537
+ return;
2538
+ }
2539
+ clearTimeout(timeout);
2451
2540
  }
2452
2541
  };
2453
2542
  };
2454
2543
 
2455
- // src/controller/getResponseType.ts
2456
- var responseTypes = ["step", "action", "exit", "modal", "subflow"];
2457
- var getResponseType = (headers, body) => {
2458
- const headerResponseType = getResponseTypeFromHeader(headers);
2459
- if (headerResponseType) {
2460
- return headerResponseType;
2461
- }
2462
- if (isObject(body) && body.action) {
2463
- return "action";
2464
- }
2465
- return "step";
2466
- };
2467
- var getResponseTypeFromHeader = (headers) => {
2468
- if (headers == null ? void 0 : headers.has("X-Df-Response-Type")) {
2469
- const type = headers.get("X-Df-Response-Type");
2470
- assertDFResponseType(type);
2471
- return type;
2472
- }
2473
- if (headers == null ? void 0 : headers.has("X-Df-Exit")) {
2474
- return "exit";
2475
- }
2476
- return void 0;
2477
- };
2478
- function assertDFResponseType(type) {
2479
- if (!responseTypes.includes(type)) {
2480
- throw new Error(
2481
- "Unsupported X-Df-Response-Type. Allowed values are 'step', 'action', 'exit', 'error', 'modal', 'subflow'."
2482
- );
2483
- }
2484
- }
2485
-
2486
- // src/controller/makeSafeHttpClient.ts
2487
- var makeSafeHttpClient = (httpClient) => async (...props) => {
2488
- try {
2489
- return await httpClient(...props);
2490
- } catch (e) {
2491
- return null;
2492
- }
2493
- };
2494
-
2495
- // src/controller/executeRequest.ts
2496
- var executeRequest = async (props) => {
2497
- const { exit, request, requestCache, httpClient, trackEvent, logEvent } = props;
2498
- const { url, method, body } = request;
2499
- const response = await getCachedOrFetch(
2500
- [
2501
- url,
2502
- {
2503
- method,
2504
- body: body ? JSON.stringify(body) : void 0,
2505
- headers: { "Content-Type": "application/json" }
2506
- }
2507
- ],
2508
- requestCache,
2509
- httpClient
2510
- );
2511
- if (!response) {
2512
- const extra = { errorMessage: "Network Error" };
2513
- trackEvent("Request Failed", extra);
2514
- logEvent("error", "Dynamic Flow - Request Failed Unexpectedly", extra);
2515
- return { type: "error" };
2516
- }
2517
- if (!response.ok) {
2518
- return handleErrorResponse(response, void 0, trackEvent);
2519
- }
2520
- const responseBody = await parseResponseBodyAsJsonElement(response);
2521
- const responseType = getResponseType(response.headers, responseBody);
2522
- if (exit) {
2523
- return { type: "complete", result: responseBody };
2524
- }
2525
- switch (responseType) {
2526
- case "step": {
2527
- const etag = response.headers.get("etag") || null;
2528
- assertStepResponseBody(responseBody);
2529
- return { type: "replace-step", step: responseBody, etag };
2530
- }
2531
- case "exit": {
2532
- return { type: "complete", result: responseBody };
2533
- }
2534
- case "action": {
2535
- assertActionResponseBody(responseBody);
2536
- return {
2537
- type: "behavior",
2538
- behavior: {
2539
- type: "action",
2540
- action: responseBody.action
2541
- }
2542
- };
2543
- }
2544
- case "subflow": {
2545
- assertSubflowResponseBody(responseBody);
2546
- return {
2547
- type: "behavior",
2548
- behavior: __spreadProps(__spreadValues({}, responseBody), {
2549
- type: "subflow",
2550
- onCompletion: responseBody.onCompletion ? normaliseBehavior(responseBody.onCompletion, []) : void 0,
2551
- onError: responseBody.onError ? normaliseBehavior(responseBody.onError, []) : void 0
2552
- })
2553
- };
2554
- }
2555
- case "modal": {
2556
- assertModalResponseBody(responseBody);
2557
- return { type: "behavior", behavior: __spreadProps(__spreadValues({}, responseBody), { type: "modal" }) };
2558
- }
2559
- default: {
2560
- throw new Error(`Unsupported response type: ${String(responseType)}`);
2561
- }
2562
- }
2563
- };
2564
- var getCachedOrFetch = async (requestParams, requestCache, httpClient) => {
2565
- const cachedPromise = requestCache.get(requestParams);
2566
- if (cachedPromise) {
2567
- const cachedResponse = await cachedPromise;
2568
- if (cachedResponse == null ? void 0 : cachedResponse.ok) {
2569
- return cachedResponse;
2570
- }
2571
- }
2572
- return makeSafeHttpClient(httpClient)(...requestParams);
2573
- };
2574
-
2575
- // src/controller/executeSubmission.ts
2576
- var executeSubmission = async (props) => {
2577
- const { httpClient, requestCache, trackEvent, logEvent } = props;
2578
- const triggerAction = async (action, model, isInitial) => {
2579
- var _a, _b;
2580
- const { exit, url, result = null, id: actionId } = action;
2581
- const trackSubmissionEvent = !isInitial ? trackEvent : () => {
2582
- };
2583
- trackSubmissionEvent("Action Triggered", { actionId });
2584
- if (exit && !url) {
2585
- trackSubmissionEvent("Action Succeeded", { actionId });
2586
- return { type: "complete", result };
2587
- }
2588
- try {
2589
- const command = await executeRequest({
2590
- exit,
2591
- request: createRequestFromAction(action, model),
2592
- requestCache,
2593
- httpClient,
2594
- trackEvent: (name, properties) => {
2595
- trackSubmissionEvent(name, __spreadProps(__spreadValues({}, properties), { actionId }));
2596
- },
2597
- logEvent
2598
- });
2599
- switch (command.type) {
2600
- case "error": {
2601
- trackSubmissionEvent("Action Failed", __spreadValues({
2602
- actionId,
2603
- statusCode: (_a = command.httpError) == null ? void 0 : _a.statusCode
2604
- }, (_b = command.body) == null ? void 0 : _b.analytics));
2605
- return command;
2606
- }
2607
- case "behavior": {
2608
- if (command.behavior.type === "action") {
2609
- trackSubmissionEvent("Action Succeeded", { actionId });
2610
- return await executeRequest({
2611
- request: createRequestFromAction(command.behavior.action, null),
2612
- requestCache,
2613
- httpClient,
2614
- trackEvent,
2615
- logEvent
2616
- });
2617
- }
2618
- trackSubmissionEvent("Action Succeeded", { actionId });
2619
- return command;
2620
- }
2621
- case "complete": {
2622
- trackSubmissionEvent("Action Succeeded", { actionId });
2623
- return __spreadProps(__spreadValues({}, command), { result: recursiveMerge(command.result, result) });
2624
- }
2625
- default: {
2626
- trackSubmissionEvent("Action Succeeded", { actionId });
2627
- return command;
2628
- }
2629
- }
2630
- } catch (error) {
2631
- const errorMessage = getErrorMessage(error);
2632
- trackSubmissionEvent("Action Failed", { actionId, errorMessage });
2633
- logEvent("error", "Dynamic Flow - Action Failed Unexpectedly", { actionId, errorMessage });
2634
- throw error;
2635
- }
2636
- };
2637
- return triggerAction(props.action, props.model, props.isInitial);
2638
- };
2639
- var createRequestFromAction = (action, model) => {
2640
- var _a, _b, _c;
2641
- return __spreadProps(__spreadValues({}, action), {
2642
- url: (_a = action.url) != null ? _a : "",
2643
- method: (_b = action.method) != null ? _b : "POST",
2644
- body: action.method === "GET" ? void 0 : recursiveMerge(model, (_c = action.data) != null ? _c : null)
2645
- });
2646
- };
2647
-
2648
- // src/domain/components/step/ExternalConfirmationComponent.ts
2649
- var createExternalConfirmation = (uid, url, onComponentUpdate) => {
2650
- const update = getInputUpdateFunction(onComponentUpdate);
2651
- return {
2652
- type: "external-confirmation",
2653
- kind: "layout",
2654
- uid,
2655
- url,
2656
- status: "initial",
2657
- onSuccess() {
2658
- update(this, (draft) => {
2659
- draft.status = "success";
2660
- });
2661
- },
2662
- onFailure() {
2663
- if (this.status === "initial") {
2664
- update(this, (draft) => {
2665
- draft.status = "failure";
2666
- });
2667
- }
2668
- },
2669
- onCancel() {
2670
- update(this, (draft) => {
2671
- draft.status = "dismissed";
2672
- });
2673
- }
2674
- };
2675
- };
2676
-
2677
- // src/utils/component-utils.ts
2678
- var getSubmittableData = async (components) => Promise.all(components.map(async (component) => component.getSubmittableValue())).then(
2679
- (values) => values.reduce((acc, value) => recursiveMerge(acc, value), null)
2680
- );
2681
- var getSubmittableDataSync = (components) => components.map((component) => component.getSubmittableValueSync()).reduce((acc, value) => recursiveMerge(acc, value), null);
2682
- var getLocalValues = (components) => components.map((component) => component.getLocalValue()).reduce((acc, value) => recursiveMerge(acc, value), null);
2683
-
2684
- // src/domain/components/step/StepDomainComponent.ts
2685
- var createStepComponent = (stepProps) => {
2686
- const _a = stepProps, { uid, stepPolling, stepRefreshAfter, onComponentUpdate } = _a, rest = __objRest(_a, ["uid", "stepPolling", "stepRefreshAfter", "onComponentUpdate"]);
2687
- const update = getInputUpdateFunction(onComponentUpdate);
2688
- const component = __spreadProps(__spreadValues({
2689
- uid
2690
- }, rest), {
2691
- type: "step",
2692
- kind: "step",
2693
- modals: [],
2694
- dismissModal() {
2695
- var _a2;
2696
- (_a2 = this.modals.at(-1)) == null ? void 0 : _a2.close();
2697
- },
2698
- dismissAllModals() {
2699
- this._update((draft) => {
2700
- draft.modals = draft.modals.map((m) => __spreadProps(__spreadValues({}, m), { open: false }));
2701
- });
2702
- },
2703
- showModal(modal) {
2704
- this._update((draft) => {
2705
- draft.modals = [...draft.modals, modal];
2706
- });
2707
- },
2708
- _update(updateFn) {
2709
- update(this, updateFn);
2710
- },
2711
- getChildren() {
2712
- return this.externalConfirmation ? [...this.layoutComponents, this.externalConfirmation] : this.layoutComponents;
2713
- },
2714
- getModals() {
2715
- return this.modals;
2716
- },
2717
- async getSubmittableValue() {
2718
- return getSubmittableData(this.schemaComponents);
2719
- },
2720
- getSubmittableValueSync() {
2721
- return getSubmittableDataSync(this.schemaComponents);
2722
- },
2723
- getLocalValue() {
2724
- return getLocalValues(this.schemaComponents);
2725
- },
2726
- validate() {
2727
- return this.schemaComponents.every(
2728
- (inputComponent) => inputComponent.isSchemaReferencedInStep ? inputComponent.validate() : true
2729
- );
2730
- },
2731
- setLoadingState(loadingState) {
2732
- this._update((draft) => {
2733
- draft.loadingState = loadingState;
2734
- });
2735
- },
2736
- start() {
2737
- stepPolling == null ? void 0 : stepPolling.start();
2738
- stepRefreshAfter == null ? void 0 : stepRefreshAfter.start();
2739
- },
2740
- stop() {
2741
- stepPolling == null ? void 0 : stepPolling.stop();
2742
- stepRefreshAfter == null ? void 0 : stepRefreshAfter.stop();
2743
- this._update((draft) => {
2744
- draft.modals = [];
2745
- });
2746
- }
2747
- });
2748
- return component;
2749
- };
2750
-
2751
- // src/domain/features/polling/getStepPolling.ts
2752
- var getStepPolling = ({
2753
- pollingConfig,
2754
- logEvent,
2755
- onBehavior,
2756
- onPoll,
2757
- registerSubmissionBehavior
2758
- }) => {
2759
- const { interval, delay = interval, maxAttempts, url, onError } = pollingConfig;
2760
- let abortController = new AbortController();
2761
- let intervalRef = null;
2762
- if (delay == null) {
2763
- throw new Error("Polling configuration must include delay or interval");
2764
- }
2765
- const onErrorBehavior = getDomainLayerBehavior(onError, [], registerSubmissionBehavior);
2766
- let attempts = 0;
2767
- const poll = () => {
2768
- attempts += 1;
2769
- abortController.abort();
2770
- abortController = new AbortController();
2771
- const { signal } = abortController;
2772
- onPoll(url, onErrorBehavior, signal).then((result) => {
2773
- if (result) {
2774
- stop();
2775
- return;
2776
- }
2777
- if (attempts >= maxAttempts && !signal.aborted) {
2778
- void onBehavior(onErrorBehavior);
2779
- stop();
2780
- }
2781
- }).catch(() => {
2782
- });
2783
- };
2784
- const start = () => {
2785
- attempts = 0;
2786
- intervalRef = setInterval(poll, delay * 1e3);
2787
- poll();
2788
- };
2789
- const stop = () => {
2790
- if (!intervalRef) {
2791
- logEvent("warning", "Attempted to stop polling but it was not started");
2792
- return;
2793
- }
2794
- clearTimeout(intervalRef);
2795
- abortController.abort();
2796
- };
2797
- return { start, stop };
2798
- };
2799
-
2800
- // src/domain/features/refreshAfter/getStepRefreshAfter.ts
2801
- var ONE_SECOND = 1e3;
2802
- var getStepRefreshAfter = ({
2803
- refreshAfter,
2804
- logEvent,
2805
- onBehavior
2806
- }) => {
2807
- let timeout = null;
2808
- const targetTime = new Date(refreshAfter).getTime();
2809
- if (typeof refreshAfter !== "string" || Number.isNaN(targetTime)) {
2810
- throw new Error(`Invalid refreshAfter value: ${String(refreshAfter)}`);
2811
- }
2812
- const start = () => {
2813
- const timeLeft = Math.max(targetTime - Date.now(), ONE_SECOND);
2814
- timeout = setTimeout(() => {
2815
- void onBehavior({ type: "refresh", analytics: { schema: "refreshAfter" } });
2816
- }, timeLeft);
2817
- };
2818
- return {
2819
- start,
2820
- stop: () => {
2821
- if (!timeout) {
2822
- logEvent("warning", "Attempted to stop refreshAfter but it was not started");
2823
- return;
2824
- }
2825
- clearTimeout(timeout);
2826
- }
2827
- };
2828
- };
2829
-
2830
- // src/domain/prefetching/request-cache.ts
2831
- var makeRequestCacheWithParent = (parent) => {
2832
- const map = /* @__PURE__ */ new Map();
2833
- const cache = {
2834
- get: (requestParams) => {
2835
- var _a;
2836
- const key = makeKey(requestParams);
2837
- const promise = (_a = map.get(key)) != null ? _a : parent == null ? void 0 : parent.get(requestParams);
2838
- map.delete(key);
2839
- return promise;
2840
- },
2841
- set: (requestParams, responsePromise) => {
2842
- return map.set(makeKey(requestParams), responsePromise);
2843
- }
2844
- };
2845
- return cache;
2846
- };
2847
- var makeRequestCache = (initialValues = []) => {
2848
- const cache = makeRequestCacheWithParent(void 0);
2849
- initialValues.forEach(([requestParams, responsePromise]) => {
2850
- cache.set(requestParams, responsePromise);
2851
- });
2852
- return cache;
2853
- };
2854
- var normaliseRequestCache = (cache) => {
2855
- if (cache === void 0) {
2856
- return makeRequestCache();
2857
- }
2858
- if (isRequestCacheInstance(cache)) {
2859
- return cache;
2860
- }
2861
- return makeRequestCache(cache);
2862
- };
2863
- var isRequestCacheInstance = (cache) => {
2864
- return !cache || !Array.isArray(cache);
2865
- };
2866
- var makeKey = (requestParams) => {
2867
- var _a, _b;
2868
- const [input, init] = requestParams;
2869
- const url = typeof input === "string" || input instanceof URL ? input.toString() : input.url;
2870
- const key = JSON.stringify({
2871
- url,
2872
- method: (_a = init == null ? void 0 : init.method) != null ? _a : "GET",
2873
- headers: (init == null ? void 0 : init.headers) ? Array.from(new Headers(init.headers).entries()) : [],
2874
- body: (_b = init == null ? void 0 : init.body) != null ? _b : null
2875
- });
2876
- return key;
2877
- };
2878
-
2879
2544
  // src/domain/components/utils/isOrWasValid.ts
2880
2545
  var isOrWasValid = (getErrors, previous, current) => {
2881
2546
  const wasValid = getErrors(previous).length === 0 && previous !== null;
@@ -3354,6 +3019,72 @@ var getInitialValidationAsyncState = () => ({
3354
3019
  messages: {}
3355
3020
  });
3356
3021
 
3022
+ // src/controller/response-utils.ts
3023
+ var import_spec = require("@wise/dynamic-flow-types/spec");
3024
+ var parseResponseBodyAsJsonElement = async (response) => {
3025
+ assertResponseIsValid(response);
3026
+ try {
3027
+ return await response.json();
3028
+ } catch (e) {
3029
+ return null;
3030
+ }
3031
+ };
3032
+ var parseResponseBodyAsText = async (response) => {
3033
+ try {
3034
+ return await response.text();
3035
+ } catch (e) {
3036
+ return null;
3037
+ }
3038
+ };
3039
+ function isActionResponseBody(body) {
3040
+ return (0, import_spec.validateActionResponse)(body).valid;
3041
+ }
3042
+ function assertActionResponseBody(body) {
3043
+ if (!isObject(body) || !isObject(body.action)) {
3044
+ throw new Error(
3045
+ "Incorrect response body in action response. Expected an object satisfying the type { action: Action }."
3046
+ );
3047
+ }
3048
+ }
3049
+ function assertModalResponseBody(body) {
3050
+ if (isObject(body)) {
3051
+ if ("content" in body && isArray(body.content)) {
3052
+ return;
3053
+ }
3054
+ }
3055
+ throw new Error(
3056
+ "Incorrect response body in modal response. Expected an object satisfying the type { title?: string, components: Layout[] }."
3057
+ );
3058
+ }
3059
+ function assertSubflowResponseBody(body) {
3060
+ const { valid } = (0, import_spec.validateSubflowResponse)(body);
3061
+ if (valid) {
3062
+ return;
3063
+ }
3064
+ throw new Error("Incorrect response body in subflow response.");
3065
+ }
3066
+ function isErrorResponseBody(body) {
3067
+ return Boolean(
3068
+ isObject(body) && (body.refreshFormUrl || body.refreshUrl || body.validation || body.error || body.analytics)
3069
+ );
3070
+ }
3071
+ function assertStepResponseBody(body) {
3072
+ if (!isObject(body)) {
3073
+ throw new Error("Incorrect response body in step response. Expected an object.");
3074
+ }
3075
+ }
3076
+ var assertResponseIsValid = (response) => {
3077
+ if (!isResponse(response)) {
3078
+ throw new Error("Incorrect type of response from fetch. Expected object of type Response.");
3079
+ }
3080
+ if (response.bodyUsed) {
3081
+ throw new Error(
3082
+ "The body of the provided Response object has already been used. Every request must respond with a new Response object."
3083
+ );
3084
+ }
3085
+ };
3086
+ var isResponse = (response) => typeof response === "object" && response !== null && "clone" in response && "bodyUsed" in response;
3087
+
3357
3088
  // src/domain/features/utils/response-utils.ts
3358
3089
  var getAnalyticsFromErrorResponse = (json) => {
3359
3090
  if (!isErrorResponseBody(json)) {
@@ -5676,6 +5407,7 @@ var mapStringSchemaSuggestions = (suggestions, logEvent) => {
5676
5407
 
5677
5408
  // src/domain/mappers/schema/stringSchemaToComponent/stringSchemaToDateInputComponent.ts
5678
5409
  var stringSchemaToDateInputComponent = (schemaMapperProps, mapperProps) => {
5410
+ var _a;
5679
5411
  const { schema, localValue, model, required = false, onPersistAsync } = schemaMapperProps;
5680
5412
  const {
5681
5413
  autocompleteHint,
@@ -5691,7 +5423,7 @@ var stringSchemaToDateInputComponent = (schemaMapperProps, mapperProps) => {
5691
5423
  mapperProps
5692
5424
  );
5693
5425
  const validLocalValue = isString(localValue) ? localValue : null;
5694
- const validModel = isString(model) ? model : defaultValue != null ? defaultValue : null;
5426
+ const validModel = (_a = getValidDate(model)) != null ? _a : getValidDate(defaultValue != null ? defaultValue : null);
5695
5427
  const value = onPersistAsync ? validLocalValue : validModel;
5696
5428
  return createDateInputComponent(
5697
5429
  __spreadProps(__spreadValues({}, mapCommonSchemaProps(schemaMapperProps)), {
@@ -5714,6 +5446,21 @@ var stringSchemaToDateInputComponent = (schemaMapperProps, mapperProps) => {
5714
5446
  onComponentUpdate
5715
5447
  );
5716
5448
  };
5449
+ var getValidDate = (model) => {
5450
+ if (!isString(model)) {
5451
+ return null;
5452
+ }
5453
+ if (/^\d{4}-\d{2}$/.test(model)) {
5454
+ return model;
5455
+ }
5456
+ try {
5457
+ const date = new Date(model);
5458
+ const stringDate = date.toISOString();
5459
+ return stringDate.split("T")[0];
5460
+ } catch (e) {
5461
+ return null;
5462
+ }
5463
+ };
5717
5464
 
5718
5465
  // src/domain/mappers/schema/stringSchemaToComponent/stringSchemaToUploadInputComponent.ts
5719
5466
  var stringSchemaToUploadInputComponent = (schemaMapperProps, mapperProps) => {
@@ -5829,235 +5576,544 @@ var createTextInputComponent = (textInputProps, onComponentUpdate) => {
5829
5576
  this._update((draft) => {
5830
5577
  draft.errors = errors;
5831
5578
  });
5832
- return errors.length === 0;
5833
- }
5834
- }, rest);
5835
- return inputComponent;
5579
+ return errors.length === 0;
5580
+ }
5581
+ }, rest);
5582
+ return inputComponent;
5583
+ };
5584
+
5585
+ // src/domain/mappers/schema/stringSchemaToComponent/stringSchemaToTextInputComponent.ts
5586
+ var stringSchemaToTextInputComponent = (schemaMapperProps, mapperProps) => {
5587
+ const { schema, localValue, model, required = false, onPersistAsync } = schemaMapperProps;
5588
+ const {
5589
+ autocapitalization,
5590
+ autocompleteHint,
5591
+ control,
5592
+ default: defaultValue,
5593
+ displayFormat,
5594
+ format,
5595
+ maxLength,
5596
+ minLength,
5597
+ suggestions,
5598
+ validationMessages
5599
+ } = schema;
5600
+ const { getErrorMessageFunctions, onComponentUpdate, onBehavior, onValueChange, logEvent } = mapperProps;
5601
+ const controlForLegacyFormat = getControlForLegacyFormat(format);
5602
+ const errorMessageFunctions = getErrorMessageFunctions(validationMessages);
5603
+ const { performValidationAsync, validationAsyncState } = getValidationAsyncInitialState(
5604
+ schemaMapperProps,
5605
+ mapperProps
5606
+ );
5607
+ const validLocalValue = isString(localValue) ? localValue : null;
5608
+ const validModel = isString(model) ? model : defaultValue != null ? defaultValue : null;
5609
+ const value = onPersistAsync ? validLocalValue : validModel;
5610
+ return createTextInputComponent(
5611
+ __spreadProps(__spreadValues({}, mapCommonSchemaProps(schemaMapperProps)), {
5612
+ autocapitalization,
5613
+ autoComplete: getAutocompleteString(autocompleteHint),
5614
+ checks: schema.hidden ? [] : [
5615
+ getRequiredCheck(required, errorMessageFunctions),
5616
+ getAboveMaxLengthCheck(schema, errorMessageFunctions),
5617
+ getBelowMinLengthCheck(schema, errorMessageFunctions),
5618
+ getNotAdheringToPatternCheck(schema, errorMessageFunctions, { logEvent })
5619
+ ],
5620
+ control: control != null ? control : controlForLegacyFormat,
5621
+ displayFormat,
5622
+ maxLength,
5623
+ minLength,
5624
+ suggestions: mapStringSchemaSuggestions(suggestions, mapperProps.logEvent),
5625
+ value,
5626
+ validationAsyncState,
5627
+ schemaOnChange: getSchemaOnChange(schema, onBehavior),
5628
+ performValidationAsync,
5629
+ onValueChange
5630
+ }),
5631
+ onComponentUpdate
5632
+ );
5633
+ };
5634
+ var getControlForLegacyFormat = (format) => {
5635
+ if (format && ["numeric", "phone-number", "email", "password"].includes(format)) {
5636
+ return format;
5637
+ }
5638
+ return void 0;
5639
+ };
5640
+
5641
+ // src/domain/mappers/schema/stringSchemaToComponent/stringSchemaToComponent.ts
5642
+ var stringSchemaToComponent = (schemaMapperProps, mapperProps) => {
5643
+ const { schema } = schemaMapperProps;
5644
+ if (isStringSchemaWithBase64(schema)) {
5645
+ return stringSchemaToUploadInputComponent(__spreadProps(__spreadValues({}, schemaMapperProps), { schema }), mapperProps);
5646
+ }
5647
+ switch (schema.format) {
5648
+ case "date":
5649
+ return stringSchemaToDateInputComponent(schemaMapperProps, mapperProps);
5650
+ default:
5651
+ return stringSchemaToTextInputComponent(schemaMapperProps, mapperProps);
5652
+ }
5653
+ };
5654
+ var isStringSchemaWithBase64 = (schema) => {
5655
+ return schema.format === "base64url" && !("persistAsync" in schema);
5656
+ };
5657
+
5658
+ // src/domain/mappers/mapSchemaToComponent.ts
5659
+ var mapSchemaToComponent = (schemaMapperProps, mapperProps) => {
5660
+ const { uid, schema } = schemaMapperProps;
5661
+ if (isConstSchema(schema)) {
5662
+ return constSchemaToComponent(uid, __spreadProps(__spreadValues({}, schemaMapperProps), { schema }), mapperProps);
5663
+ }
5664
+ if (isSchemaWithPersistAsync(schema)) {
5665
+ return persistAsyncSchemaToComponent(__spreadProps(__spreadValues({}, schemaMapperProps), { schema }), mapperProps);
5666
+ }
5667
+ if (isAllOfSchema(schema)) {
5668
+ return allOfSchemaToComponent(__spreadProps(__spreadValues({}, schemaMapperProps), { schema }), mapperProps);
5669
+ }
5670
+ if (isOneOfSchema(schema)) {
5671
+ return oneOfSchemaToComponent(__spreadProps(__spreadValues({}, schemaMapperProps), { schema }), mapperProps);
5672
+ }
5673
+ if (isBooleanSchema(schema)) {
5674
+ return booleanSchemaToComponent(__spreadProps(__spreadValues({}, schemaMapperProps), { schema }), mapperProps);
5675
+ }
5676
+ if (isObjectSchema(schema)) {
5677
+ const { format } = schema;
5678
+ if (format === "money") {
5679
+ return objectSchemaToMoneyInputComponent(__spreadProps(__spreadValues({}, schemaMapperProps), { schema }), mapperProps);
5680
+ }
5681
+ if (format != null && Object.keys(schema.properties).length === 0) {
5682
+ return objectSchemaToFormattedValueComponent(
5683
+ __spreadProps(__spreadValues({}, schemaMapperProps), { schema: __spreadProps(__spreadValues({}, schema), { format }) }),
5684
+ mapperProps
5685
+ );
5686
+ }
5687
+ return objectSchemaToObjectComponent(__spreadProps(__spreadValues({}, schemaMapperProps), { schema }), mapperProps);
5688
+ }
5689
+ if (isIntegerSchema(schema)) {
5690
+ return integerSchemaToComponent(__spreadProps(__spreadValues({}, schemaMapperProps), { schema }), mapperProps);
5691
+ }
5692
+ if (isNumberSchema(schema)) {
5693
+ return numberSchemaToComponent(__spreadProps(__spreadValues({}, schemaMapperProps), { schema }), mapperProps);
5694
+ }
5695
+ if (isStringSchema(schema)) {
5696
+ return stringSchemaToComponent(__spreadProps(__spreadValues({}, schemaMapperProps), { schema }), mapperProps);
5697
+ }
5698
+ if (isArraySchema(schema)) {
5699
+ return arraySchemaToComponent(__spreadProps(__spreadValues({}, schemaMapperProps), { schema }), mapperProps);
5700
+ }
5701
+ if (isBlobSchema(schema)) {
5702
+ if (!schemaMapperProps.onPersistAsync) {
5703
+ throw new Error(
5704
+ "Blob schemas can only be used as the schema of a persist async configuration."
5705
+ );
5706
+ }
5707
+ return blobSchemaToComponent(__spreadProps(__spreadValues({}, schemaMapperProps), { schema }), mapperProps);
5708
+ }
5709
+ throw new Error("Not yet supported");
5710
+ };
5711
+
5712
+ // src/domain/mappers/mapStepSchemas.ts
5713
+ var mapStepSchemas = (uid, step, stepLocalValue, mapperProps, referencedSchemaIds) => {
5714
+ const isReferenced = (schemaId) => schemaId != null && referencedSchemaIds.includes(schemaId);
5715
+ return step.schemas.map((schema, i) => {
5716
+ var _a, _b;
5717
+ const schemaComponent = mapSchemaToComponent(
5718
+ {
5719
+ uid: `${uid}.schemas-${i}.${schema.$id}`,
5720
+ schemaId: schema.$id,
5721
+ schema,
5722
+ model: (_a = step.model) != null ? _a : null,
5723
+ localValue: stepLocalValue,
5724
+ validationErrors: (_b = step.errors) == null ? void 0 : _b.validation,
5725
+ required: true
5726
+ },
5727
+ mapperProps
5728
+ );
5729
+ return __spreadProps(__spreadValues({}, schemaComponent), {
5730
+ isSchemaReferencedInStep: isReferenced(schema.$id)
5731
+ });
5732
+ });
5733
+ };
5734
+
5735
+ // src/domain/mappers/mapToolbarToComponent.ts
5736
+ var mapToolbarToComponent = (uid, toolbar, mapperProps) => {
5737
+ if (!toolbar) {
5738
+ return void 0;
5739
+ }
5740
+ const { onBehavior } = mapperProps;
5741
+ return __spreadProps(__spreadValues({}, toolbar), {
5742
+ type: "toolbar",
5743
+ uid: `${uid}.toolbar`,
5744
+ tags: toolbar.tags,
5745
+ items: toolbar.items.map((item) => {
5746
+ const context = item.context ? mapLegacyContext(item.context) : void 0;
5747
+ const behavior = getDomainLayerBehavior(
5748
+ { behavior: item.behavior },
5749
+ [],
5750
+ mapperProps.registerSubmissionBehavior
5751
+ );
5752
+ return __spreadProps(__spreadValues({}, item), {
5753
+ context: context ? mapLegacyContext(context) : void 0,
5754
+ disabled: !!item.disabled,
5755
+ tags: item.tags,
5756
+ onClick: () => {
5757
+ void onBehavior(behavior);
5758
+ }
5759
+ });
5760
+ })
5761
+ });
5836
5762
  };
5837
5763
 
5838
- // src/domain/mappers/schema/stringSchemaToComponent/stringSchemaToTextInputComponent.ts
5839
- var stringSchemaToTextInputComponent = (schemaMapperProps, mapperProps) => {
5840
- const { schema, localValue, model, required = false, onPersistAsync } = schemaMapperProps;
5841
- const {
5842
- autocapitalization,
5843
- autocompleteHint,
5844
- control,
5845
- default: defaultValue,
5846
- displayFormat,
5847
- format,
5848
- maxLength,
5849
- minLength,
5850
- suggestions,
5851
- validationMessages
5852
- } = schema;
5853
- const { getErrorMessageFunctions, onComponentUpdate, onBehavior, onValueChange, logEvent } = mapperProps;
5854
- const controlForLegacyFormat = getControlForLegacyFormat(format);
5855
- const errorMessageFunctions = getErrorMessageFunctions(validationMessages);
5856
- const { performValidationAsync, validationAsyncState } = getValidationAsyncInitialState(
5857
- schemaMapperProps,
5858
- mapperProps
5859
- );
5860
- const validLocalValue = isString(localValue) ? localValue : null;
5861
- const validModel = isString(model) ? model : defaultValue != null ? defaultValue : null;
5862
- const value = onPersistAsync ? validLocalValue : validModel;
5863
- return createTextInputComponent(
5864
- __spreadProps(__spreadValues({}, mapCommonSchemaProps(schemaMapperProps)), {
5865
- autocapitalization,
5866
- autoComplete: getAutocompleteString(autocompleteHint),
5867
- checks: schema.hidden ? [] : [
5868
- getRequiredCheck(required, errorMessageFunctions),
5869
- getAboveMaxLengthCheck(schema, errorMessageFunctions),
5870
- getBelowMinLengthCheck(schema, errorMessageFunctions),
5871
- getNotAdheringToPatternCheck(schema, errorMessageFunctions, { logEvent })
5872
- ],
5873
- control: control != null ? control : controlForLegacyFormat,
5874
- displayFormat,
5875
- maxLength,
5876
- minLength,
5877
- suggestions: mapStringSchemaSuggestions(suggestions, mapperProps.logEvent),
5878
- value,
5879
- validationAsyncState,
5880
- schemaOnChange: getSchemaOnChange(schema, onBehavior),
5881
- performValidationAsync,
5882
- onValueChange
5883
- }),
5884
- onComponentUpdate
5885
- );
5764
+ // src/domain/mappers/utils/groupLayoutByPinned.ts
5765
+ var groupLayoutByPinned = (layouts) => {
5766
+ return layouts.reduce(groupLayout, { pinned: [], nonPinned: [] });
5886
5767
  };
5887
- var getControlForLegacyFormat = (format) => {
5888
- if (format && ["numeric", "phone-number", "email", "password"].includes(format)) {
5889
- return format;
5768
+ var groupLayout = (acc, layout) => {
5769
+ if (layout.type === "button" && layout.pinOrder !== void 0) {
5770
+ return {
5771
+ pinned: [...acc.pinned, layout],
5772
+ nonPinned: acc.nonPinned
5773
+ };
5890
5774
  }
5891
- return void 0;
5775
+ if (hasColumns(layout)) {
5776
+ const leftChildren = groupLayoutByPinned(layout.left);
5777
+ const rightChildren = groupLayoutByPinned(layout.right);
5778
+ return {
5779
+ pinned: [...acc.pinned, ...leftChildren.pinned, ...rightChildren.pinned],
5780
+ nonPinned: [
5781
+ ...acc.nonPinned,
5782
+ __spreadProps(__spreadValues({}, layout), {
5783
+ left: leftChildren.nonPinned,
5784
+ right: rightChildren.nonPinned
5785
+ })
5786
+ ]
5787
+ };
5788
+ }
5789
+ if (hasChildren(layout)) {
5790
+ const childComponents = groupLayoutByPinned(layout.components);
5791
+ return {
5792
+ pinned: [...acc.pinned, ...childComponents.pinned],
5793
+ nonPinned: [
5794
+ ...acc.nonPinned,
5795
+ __spreadProps(__spreadValues({}, layout), {
5796
+ components: childComponents.nonPinned
5797
+ })
5798
+ ]
5799
+ };
5800
+ }
5801
+ return {
5802
+ pinned: [...acc.pinned],
5803
+ nonPinned: [...acc.nonPinned, layout]
5804
+ };
5892
5805
  };
5806
+ var hasChildren = (component) => "components" in component;
5807
+ var hasColumns = (component) => "right" in component && "left" in component;
5893
5808
 
5894
- // src/domain/mappers/schema/stringSchemaToComponent/stringSchemaToComponent.ts
5895
- var stringSchemaToComponent = (schemaMapperProps, mapperProps) => {
5896
- const { schema } = schemaMapperProps;
5897
- if (isStringSchemaWithBase64(schema)) {
5898
- return stringSchemaToUploadInputComponent(__spreadProps(__spreadValues({}, schemaMapperProps), { schema }), mapperProps);
5809
+ // src/controller/getErrorMessage.ts
5810
+ var getErrorMessage = (error) => {
5811
+ return error instanceof Error ? error.message : typeof error === "string" ? error : `Unknown Error: type is ${typeof error}`;
5812
+ };
5813
+
5814
+ // src/controller/handleErrorResponse.ts
5815
+ var handleErrorResponse = async (response, actionId, trackEvent) => {
5816
+ const body = await parseResponseBodyAsJsonElement(response.clone());
5817
+ if (isErrorResponseBody(body)) {
5818
+ const refreshUrl = body.refreshUrl || body.refreshFormUrl;
5819
+ const { error, validation, analytics } = body;
5820
+ trackEvent("Action Failed", __spreadProps(__spreadValues({}, analytics), { actionId, statusCode: response.status }));
5821
+ const errors = { error, validation };
5822
+ return refreshUrl ? { type: "refresh", body: { refreshUrl, errors } } : {
5823
+ type: "error",
5824
+ body: { errors, analytics },
5825
+ httpError: { statusCode: response.status }
5826
+ };
5899
5827
  }
5900
- switch (schema.format) {
5901
- case "date":
5902
- return stringSchemaToDateInputComponent(schemaMapperProps, mapperProps);
5903
- default:
5904
- return stringSchemaToTextInputComponent(schemaMapperProps, mapperProps);
5828
+ trackEvent("Action Failed", { actionId, statusCode: response.status });
5829
+ const errorMessage = await parseResponseBodyAsText(response);
5830
+ return {
5831
+ type: "error",
5832
+ httpError: {
5833
+ message: errorMessage || void 0,
5834
+ statusCode: response.status
5835
+ }
5836
+ };
5837
+ };
5838
+
5839
+ // src/controller/getResponseType.ts
5840
+ var responseTypes = ["step", "action", "exit", "modal", "subflow"];
5841
+ var getResponseType = (headers, body) => {
5842
+ const headerResponseType = getResponseTypeFromHeader(headers);
5843
+ if (headerResponseType) {
5844
+ return headerResponseType;
5845
+ }
5846
+ if (isObject(body) && body.action) {
5847
+ return "action";
5905
5848
  }
5849
+ return "step";
5906
5850
  };
5907
- var isStringSchemaWithBase64 = (schema) => {
5908
- return schema.format === "base64url" && !("persistAsync" in schema);
5851
+ var getResponseTypeFromHeader = (headers) => {
5852
+ if (headers == null ? void 0 : headers.has("X-Df-Response-Type")) {
5853
+ const type = headers.get("X-Df-Response-Type");
5854
+ assertDFResponseType(type);
5855
+ return type;
5856
+ }
5857
+ if (headers == null ? void 0 : headers.has("X-Df-Exit")) {
5858
+ return "exit";
5859
+ }
5860
+ return void 0;
5909
5861
  };
5910
-
5911
- // src/domain/mappers/mapSchemaToComponent.ts
5912
- var mapSchemaToComponent = (schemaMapperProps, mapperProps) => {
5913
- const { uid, schema } = schemaMapperProps;
5914
- if (isConstSchema(schema)) {
5915
- return constSchemaToComponent(uid, __spreadProps(__spreadValues({}, schemaMapperProps), { schema }), mapperProps);
5862
+ function assertDFResponseType(type) {
5863
+ if (!responseTypes.includes(type)) {
5864
+ throw new Error(
5865
+ "Unsupported X-Df-Response-Type. Allowed values are 'step', 'action', 'exit', 'error', 'modal', 'subflow'."
5866
+ );
5916
5867
  }
5917
- if (isSchemaWithPersistAsync(schema)) {
5918
- return persistAsyncSchemaToComponent(__spreadProps(__spreadValues({}, schemaMapperProps), { schema }), mapperProps);
5868
+ }
5869
+
5870
+ // src/controller/makeSafeHttpClient.ts
5871
+ var makeSafeHttpClient = (httpClient) => async (...props) => {
5872
+ try {
5873
+ return await httpClient(...props);
5874
+ } catch (e) {
5875
+ return null;
5919
5876
  }
5920
- if (isAllOfSchema(schema)) {
5921
- return allOfSchemaToComponent(__spreadProps(__spreadValues({}, schemaMapperProps), { schema }), mapperProps);
5877
+ };
5878
+
5879
+ // src/controller/executeRequest.ts
5880
+ var executeRequest = async (props) => {
5881
+ const { exit, request, requestCache, httpClient, trackEvent, logEvent } = props;
5882
+ const { url, method, body } = request;
5883
+ const response = await getCachedOrFetch(
5884
+ [
5885
+ url,
5886
+ {
5887
+ method,
5888
+ body: body ? JSON.stringify(body) : void 0,
5889
+ headers: { "Content-Type": "application/json" }
5890
+ }
5891
+ ],
5892
+ requestCache,
5893
+ httpClient
5894
+ );
5895
+ if (!response) {
5896
+ const extra = { errorMessage: "Network Error" };
5897
+ trackEvent("Request Failed", extra);
5898
+ logEvent("error", "Dynamic Flow - Request Failed Unexpectedly", extra);
5899
+ return { type: "error" };
5922
5900
  }
5923
- if (isOneOfSchema(schema)) {
5924
- return oneOfSchemaToComponent(__spreadProps(__spreadValues({}, schemaMapperProps), { schema }), mapperProps);
5901
+ if (!response.ok) {
5902
+ return handleErrorResponse(response, void 0, trackEvent);
5925
5903
  }
5926
- if (isBooleanSchema(schema)) {
5927
- return booleanSchemaToComponent(__spreadProps(__spreadValues({}, schemaMapperProps), { schema }), mapperProps);
5904
+ const responseBody = await parseResponseBodyAsJsonElement(response);
5905
+ const responseType = getResponseType(response.headers, responseBody);
5906
+ if (exit) {
5907
+ return { type: "complete", result: responseBody };
5928
5908
  }
5929
- if (isObjectSchema(schema)) {
5930
- const { format } = schema;
5931
- if (format === "money") {
5932
- return objectSchemaToMoneyInputComponent(__spreadProps(__spreadValues({}, schemaMapperProps), { schema }), mapperProps);
5909
+ switch (responseType) {
5910
+ case "step": {
5911
+ const etag = response.headers.get("etag") || null;
5912
+ assertStepResponseBody(responseBody);
5913
+ return { type: "replace-step", step: responseBody, etag };
5914
+ }
5915
+ case "exit": {
5916
+ return { type: "complete", result: responseBody };
5917
+ }
5918
+ case "action": {
5919
+ assertActionResponseBody(responseBody);
5920
+ return {
5921
+ type: "behavior",
5922
+ behavior: {
5923
+ type: "action",
5924
+ action: responseBody.action
5925
+ }
5926
+ };
5927
+ }
5928
+ case "subflow": {
5929
+ assertSubflowResponseBody(responseBody);
5930
+ return {
5931
+ type: "behavior",
5932
+ behavior: __spreadProps(__spreadValues({}, responseBody), {
5933
+ type: "subflow",
5934
+ onCompletion: responseBody.onCompletion ? normaliseBehavior(responseBody.onCompletion, []) : void 0,
5935
+ onError: responseBody.onError ? normaliseBehavior(responseBody.onError, []) : void 0
5936
+ })
5937
+ };
5938
+ }
5939
+ case "modal": {
5940
+ assertModalResponseBody(responseBody);
5941
+ return { type: "behavior", behavior: __spreadProps(__spreadValues({}, responseBody), { type: "modal" }) };
5933
5942
  }
5934
- if (format != null && Object.keys(schema.properties).length === 0) {
5935
- return objectSchemaToFormattedValueComponent(
5936
- __spreadProps(__spreadValues({}, schemaMapperProps), { schema: __spreadProps(__spreadValues({}, schema), { format }) }),
5937
- mapperProps
5938
- );
5943
+ default: {
5944
+ throw new Error(`Unsupported response type: ${String(responseType)}`);
5939
5945
  }
5940
- return objectSchemaToObjectComponent(__spreadProps(__spreadValues({}, schemaMapperProps), { schema }), mapperProps);
5941
- }
5942
- if (isIntegerSchema(schema)) {
5943
- return integerSchemaToComponent(__spreadProps(__spreadValues({}, schemaMapperProps), { schema }), mapperProps);
5944
- }
5945
- if (isNumberSchema(schema)) {
5946
- return numberSchemaToComponent(__spreadProps(__spreadValues({}, schemaMapperProps), { schema }), mapperProps);
5947
- }
5948
- if (isStringSchema(schema)) {
5949
- return stringSchemaToComponent(__spreadProps(__spreadValues({}, schemaMapperProps), { schema }), mapperProps);
5950
5946
  }
5951
- if (isArraySchema(schema)) {
5952
- return arraySchemaToComponent(__spreadProps(__spreadValues({}, schemaMapperProps), { schema }), mapperProps);
5953
- }
5954
- if (isBlobSchema(schema)) {
5955
- if (!schemaMapperProps.onPersistAsync) {
5956
- throw new Error(
5957
- "Blob schemas can only be used as the schema of a persist async configuration."
5958
- );
5947
+ };
5948
+ var getCachedOrFetch = async (requestParams, requestCache, httpClient) => {
5949
+ const cachedPromise = requestCache.get(requestParams);
5950
+ if (cachedPromise) {
5951
+ const cachedResponse = await cachedPromise;
5952
+ if (cachedResponse == null ? void 0 : cachedResponse.ok) {
5953
+ return cachedResponse;
5959
5954
  }
5960
- return blobSchemaToComponent(__spreadProps(__spreadValues({}, schemaMapperProps), { schema }), mapperProps);
5961
5955
  }
5962
- throw new Error("Not yet supported");
5956
+ return makeSafeHttpClient(httpClient)(...requestParams);
5963
5957
  };
5964
5958
 
5965
- // src/domain/mappers/mapStepSchemas.ts
5966
- var mapStepSchemas = (uid, step, stepLocalValue, mapperProps, referencedSchemaIds) => {
5967
- const isReferenced = (schemaId) => schemaId != null && referencedSchemaIds.includes(schemaId);
5968
- return step.schemas.map((schema, i) => {
5959
+ // src/controller/executeSubmission.ts
5960
+ var executeSubmission = async (props) => {
5961
+ const { httpClient, requestCache, trackEvent, logEvent } = props;
5962
+ const triggerAction = async (action, model, isInitial) => {
5969
5963
  var _a, _b;
5970
- const schemaComponent = mapSchemaToComponent(
5971
- {
5972
- uid: `${uid}.schemas-${i}.${schema.$id}`,
5973
- schemaId: schema.$id,
5974
- schema,
5975
- model: (_a = step.model) != null ? _a : null,
5976
- localValue: stepLocalValue,
5977
- validationErrors: (_b = step.errors) == null ? void 0 : _b.validation,
5978
- required: true
5979
- },
5980
- mapperProps
5981
- );
5982
- return __spreadProps(__spreadValues({}, schemaComponent), {
5983
- isSchemaReferencedInStep: isReferenced(schema.$id)
5984
- });
5985
- });
5986
- };
5987
-
5988
- // src/domain/mappers/mapToolbarToComponent.ts
5989
- var mapToolbarToComponent = (uid, toolbar, mapperProps) => {
5990
- if (!toolbar) {
5991
- return void 0;
5992
- }
5993
- const { onBehavior } = mapperProps;
5994
- return __spreadProps(__spreadValues({}, toolbar), {
5995
- type: "toolbar",
5996
- uid: `${uid}.toolbar`,
5997
- tags: toolbar.tags,
5998
- items: toolbar.items.map((item) => {
5999
- const context = item.context ? mapLegacyContext(item.context) : void 0;
6000
- const behavior = getDomainLayerBehavior(
6001
- { behavior: item.behavior },
6002
- [],
6003
- mapperProps.registerSubmissionBehavior
6004
- );
6005
- return __spreadProps(__spreadValues({}, item), {
6006
- context: context ? mapLegacyContext(context) : void 0,
6007
- disabled: !!item.disabled,
6008
- tags: item.tags,
6009
- onClick: () => {
6010
- void onBehavior(behavior);
6011
- }
5964
+ const { exit, url, result = null, id: actionId } = action;
5965
+ const trackSubmissionEvent = !isInitial ? trackEvent : () => {
5966
+ };
5967
+ trackSubmissionEvent("Action Triggered", { actionId });
5968
+ if (exit && !url) {
5969
+ trackSubmissionEvent("Action Succeeded", { actionId });
5970
+ return { type: "complete", result };
5971
+ }
5972
+ try {
5973
+ const command = await executeRequest({
5974
+ exit,
5975
+ request: createRequestFromAction(action, model),
5976
+ requestCache,
5977
+ httpClient,
5978
+ trackEvent: (name, properties) => {
5979
+ trackSubmissionEvent(name, __spreadProps(__spreadValues({}, properties), { actionId }));
5980
+ },
5981
+ logEvent
6012
5982
  });
6013
- })
5983
+ switch (command.type) {
5984
+ case "error": {
5985
+ trackSubmissionEvent("Action Failed", __spreadValues({
5986
+ actionId,
5987
+ statusCode: (_a = command.httpError) == null ? void 0 : _a.statusCode
5988
+ }, (_b = command.body) == null ? void 0 : _b.analytics));
5989
+ return command;
5990
+ }
5991
+ case "behavior": {
5992
+ if (command.behavior.type === "action") {
5993
+ trackSubmissionEvent("Action Succeeded", { actionId });
5994
+ return await executeSubmission({
5995
+ action: command.behavior.action,
5996
+ isInitial: false,
5997
+ model: null,
5998
+ requestCache,
5999
+ httpClient,
6000
+ trackEvent,
6001
+ logEvent
6002
+ });
6003
+ }
6004
+ trackSubmissionEvent("Action Succeeded", { actionId });
6005
+ return command;
6006
+ }
6007
+ case "complete": {
6008
+ trackSubmissionEvent("Action Succeeded", { actionId });
6009
+ return __spreadProps(__spreadValues({}, command), { result: recursiveMerge(command.result, result) });
6010
+ }
6011
+ default: {
6012
+ trackSubmissionEvent("Action Succeeded", { actionId });
6013
+ return command;
6014
+ }
6015
+ }
6016
+ } catch (error) {
6017
+ const errorMessage = getErrorMessage(error);
6018
+ trackSubmissionEvent("Action Failed", { actionId, errorMessage });
6019
+ logEvent("error", "Dynamic Flow - Action Failed Unexpectedly", { actionId, errorMessage });
6020
+ throw error;
6021
+ }
6022
+ };
6023
+ return triggerAction(props.action, props.model, props.isInitial);
6024
+ };
6025
+ var createRequestFromAction = (action, model) => {
6026
+ var _a, _b, _c;
6027
+ return __spreadProps(__spreadValues({}, action), {
6028
+ url: (_a = action.url) != null ? _a : "",
6029
+ method: (_b = action.method) != null ? _b : "POST",
6030
+ body: action.method === "GET" ? void 0 : recursiveMerge(model, (_c = action.data) != null ? _c : null)
6014
6031
  });
6015
6032
  };
6016
6033
 
6017
- // src/domain/mappers/utils/groupLayoutByPinned.ts
6018
- var groupLayoutByPinned = (layouts) => {
6019
- return layouts.reduce(groupLayout, { pinned: [], nonPinned: [] });
6034
+ // src/domain/features/prefetch/request-cache.ts
6035
+ var makeRequestCacheWithParent = (parent) => {
6036
+ const map = /* @__PURE__ */ new Map();
6037
+ const cache = {
6038
+ get: (requestParams) => {
6039
+ var _a;
6040
+ const key = makeRequestCacheKey(requestParams);
6041
+ const promise = (_a = map.get(key)) != null ? _a : parent == null ? void 0 : parent.get(requestParams);
6042
+ map.delete(key);
6043
+ return promise;
6044
+ },
6045
+ set: (requestParams, responsePromise) => {
6046
+ return map.set(makeRequestCacheKey(requestParams), responsePromise);
6047
+ }
6048
+ };
6049
+ return cache;
6020
6050
  };
6021
- var groupLayout = (acc, layout) => {
6022
- if (layout.type === "button" && layout.pinOrder !== void 0) {
6023
- return {
6024
- pinned: [...acc.pinned, layout],
6025
- nonPinned: acc.nonPinned
6026
- };
6027
- }
6028
- if (hasColumns(layout)) {
6029
- const leftChildren = groupLayoutByPinned(layout.left);
6030
- const rightChildren = groupLayoutByPinned(layout.right);
6031
- return {
6032
- pinned: [...acc.pinned, ...leftChildren.pinned, ...rightChildren.pinned],
6033
- nonPinned: [
6034
- ...acc.nonPinned,
6035
- __spreadProps(__spreadValues({}, layout), {
6036
- left: leftChildren.nonPinned,
6037
- right: rightChildren.nonPinned
6038
- })
6039
- ]
6040
- };
6051
+ var makeRequestCache = (initialValues = []) => {
6052
+ const cache = makeRequestCacheWithParent(void 0);
6053
+ initialValues.forEach(([requestParams, responsePromise]) => {
6054
+ cache.set(requestParams, responsePromise);
6055
+ });
6056
+ return cache;
6057
+ };
6058
+ var normaliseRequestCache = (cache) => {
6059
+ if (cache === void 0) {
6060
+ return makeRequestCache();
6041
6061
  }
6042
- if (hasChildren(layout)) {
6043
- const childComponents = groupLayoutByPinned(layout.components);
6044
- return {
6045
- pinned: [...acc.pinned, ...childComponents.pinned],
6046
- nonPinned: [
6047
- ...acc.nonPinned,
6048
- __spreadProps(__spreadValues({}, layout), {
6049
- components: childComponents.nonPinned
6050
- })
6051
- ]
6052
- };
6062
+ if (isRequestCacheInstance(cache)) {
6063
+ return cache;
6053
6064
  }
6054
- return {
6055
- pinned: [...acc.pinned],
6056
- nonPinned: [...acc.nonPinned, layout]
6065
+ return makeRequestCache(cache);
6066
+ };
6067
+ var isRequestCacheInstance = (cache) => {
6068
+ return !cache || !Array.isArray(cache);
6069
+ };
6070
+ var makeRequestCacheKey = (requestParams) => {
6071
+ var _a, _b;
6072
+ const [input, init] = requestParams;
6073
+ const url = typeof input === "string" || input instanceof URL ? input.toString() : input.url;
6074
+ const key = JSON.stringify({
6075
+ url,
6076
+ method: (_a = init == null ? void 0 : init.method) != null ? _a : "GET",
6077
+ headers: (init == null ? void 0 : init.headers) ? Array.from(new Headers(init.headers).entries()) : [],
6078
+ body: (_b = init == null ? void 0 : init.body) != null ? _b : null
6079
+ });
6080
+ return key;
6081
+ };
6082
+
6083
+ // src/domain/features/prefetch/getStepPrefetch.ts
6084
+ var getStepPrefetch = (httpClient, flowRequestCache, submissionBehaviors) => {
6085
+ const requestCache = makeRequestCacheWithParent(flowRequestCache);
6086
+ const keys = /* @__PURE__ */ new Set();
6087
+ const start = (model) => {
6088
+ if (keys.size > 0) {
6089
+ return;
6090
+ }
6091
+ submissionBehaviors.forEach((behavior) => {
6092
+ const request = behavior.type === "action" ? createRequestFromAction(behavior.action, model) : behavior.launchConfig.request;
6093
+ const requestParams = [
6094
+ request.url,
6095
+ {
6096
+ body: JSON.stringify(request.body),
6097
+ method: request.method,
6098
+ headers: { "Content-Type": "application/json" }
6099
+ }
6100
+ ];
6101
+ try {
6102
+ const key = makeRequestCacheKey(requestParams);
6103
+ if (keys.has(key)) {
6104
+ return;
6105
+ }
6106
+ const responsePromise = httpClient(...requestParams).catch(() => null);
6107
+ requestCache.set(requestParams, responsePromise);
6108
+ keys.add(key);
6109
+ } catch (e) {
6110
+ }
6111
+ });
6057
6112
  };
6113
+ const stop = () => {
6114
+ };
6115
+ return { requestCache, start, stop };
6058
6116
  };
6059
- var hasChildren = (component) => "components" in component;
6060
- var hasColumns = (component) => "right" in component && "left" in component;
6061
6117
 
6062
6118
  // src/domain/mappers/mapStepToComponent.ts
6063
6119
  var mapStepToComponent = (_a) => {
@@ -6091,7 +6147,6 @@ var mapStepToComponent = (_a) => {
6091
6147
  title,
6092
6148
  tags
6093
6149
  } = step;
6094
- const requestCache = makeRequestCacheWithParent(flowRequestCache);
6095
6150
  const submissionBehaviors = [];
6096
6151
  const registerSubmissionBehavior = (behavior) => {
6097
6152
  if (behavior.type === "action" && behavior.action.prefetch) {
@@ -6115,6 +6170,7 @@ var mapStepToComponent = (_a) => {
6115
6170
  registerSubmissionBehavior
6116
6171
  }) : void 0;
6117
6172
  const stepRefreshAfter = refreshAfter ? getStepRefreshAfter({ refreshAfter, logEvent, onBehavior }) : void 0;
6173
+ const stepPrefetch = getStepPrefetch(restProps.httpClient, flowRequestCache, submissionBehaviors);
6118
6174
  const externalConfirmation = (external == null ? void 0 : external.url) ? createExternalConfirmation(`${uid}-external-confirmation`, external == null ? void 0 : external.url, onComponentUpdate) : void 0;
6119
6175
  const mapperProps = __spreadProps(__spreadValues({}, restProps), { trackEvent, onBehavior, registerSubmissionBehavior });
6120
6176
  const referencedSchemaIds = getReferencedSchemaId(step);
@@ -6151,18 +6207,12 @@ var mapStepToComponent = (_a) => {
6151
6207
  title,
6152
6208
  tags,
6153
6209
  stackBehavior: (_a2 = navigation == null ? void 0 : navigation.stackBehavior) != null ? _a2 : "default",
6154
- requestCache,
6210
+ stepPrefetch,
6155
6211
  step,
6156
6212
  onComponentUpdate,
6157
6213
  trackEvent,
6158
6214
  onBehavior
6159
6215
  });
6160
- executePrefetch({
6161
- httpClient: mapperProps.httpClient,
6162
- model: stepComponent.getSubmittableValueSync(),
6163
- behaviors: submissionBehaviors,
6164
- requestCache
6165
- });
6166
6216
  return stepComponent;
6167
6217
  };
6168
6218
  var getReferencedSchemaId = (step) => {
@@ -6183,25 +6233,6 @@ var mapBackNavigation = (navigation, onBehavior, isNativeBackEnabled) => {
6183
6233
  }
6184
6234
  } : void 0;
6185
6235
  };
6186
- var executePrefetch = (props) => {
6187
- const { httpClient, behaviors: submissionBehaviors, model, requestCache } = props;
6188
- submissionBehaviors.forEach((behavior) => {
6189
- const request = behavior.type === "action" ? createRequestFromAction(behavior.action, model) : behavior.launchConfig.request;
6190
- const requestParams = [
6191
- request.url,
6192
- {
6193
- body: JSON.stringify(request.body),
6194
- method: request.method,
6195
- headers: { "Content-Type": "application/json" }
6196
- }
6197
- ];
6198
- try {
6199
- const responsePromise = httpClient(...requestParams).catch(() => null);
6200
- requestCache.set(requestParams, responsePromise);
6201
- } catch (e) {
6202
- }
6203
- });
6204
- };
6205
6236
  var getLayoutAndFooter = (step, features) => {
6206
6237
  var _a;
6207
6238
  if (step.footer) {
@@ -6807,21 +6838,24 @@ var createFlowController = (props) => {
6807
6838
  return false;
6808
6839
  }
6809
6840
  };
6810
- let isInitialised = false;
6841
+ let initState = "initial";
6811
6842
  if (initialStep) {
6812
- isInitialised = true;
6843
+ initState = "created";
6813
6844
  trackEvent("Initiated");
6814
6845
  createStep(initialStep, null);
6815
6846
  trackEvent("Step Shown", { isFirstStep: true });
6816
6847
  }
6817
6848
  const start = () => {
6818
- if (!isInitialised && initialAction) {
6819
- isInitialised = true;
6849
+ if (initState === "initial" && initialAction) {
6850
+ initState = "created";
6820
6851
  trackEvent("Initiated");
6821
6852
  rootComponent.setLoadingState("submitting");
6822
6853
  void onAction(__spreadValues({ method: "GET" }, initialAction), null);
6823
6854
  }
6824
- rootComponent.start();
6855
+ if (initState === "created") {
6856
+ initState = "started";
6857
+ rootComponent.start();
6858
+ }
6825
6859
  };
6826
6860
  return {
6827
6861
  rootComponent,