@inploi/flows 0.0.0

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.
@@ -0,0 +1,234 @@
1
+ import { FlowNode } from '@inploi/core/flows';
2
+ import { ApiClient, AnalyticsService, Logger } from '@inploi/sdk';
3
+ import { F as FlowSubmissions, a as FlowInput, R as Result, I as Issues } from './result-6033e9fc.js';
4
+ import * as _inploi_i18n_translation from '@inploi/i18n/translation';
5
+ import { LinkedList } from './linked-list.mjs';
6
+
7
+ declare const useTranslation: <T extends {
8
+ readonly submission_redirect_message: "Almost there! Please complete your submission here:";
9
+ readonly complete_submission: "Complete submission";
10
+ readonly submission_completed: "Submission completed!";
11
+ readonly submission_failed: "Failed to submit";
12
+ readonly maximize: "Maximise";
13
+ readonly minimize: "Minimise";
14
+ readonly close_application: "Close application";
15
+ readonly applying_for: "Applying for “{{title}}”";
16
+ /** When an application is at an invalid state, the user will get this error. */
17
+ readonly invalid_state: "Invalid application state";
18
+ readonly redirect_url_error: "Couldn’t get the redirect URL.";
19
+ readonly upload_file: {
20
+ readonly one: "Select file to upload";
21
+ readonly other: "Select files to upload";
22
+ };
23
+ readonly file_max_size: "max {{size}}";
24
+ readonly file_extensions: "Accepted file extensions";
25
+ readonly address_error: "Something went wrong! Plase continue manually";
26
+ readonly address_search: "Type and search for places…";
27
+ readonly address_manual: "Fill in manually";
28
+ readonly back: "Back";
29
+ readonly search: "Search";
30
+ readonly unknown_error: "An error occurred";
31
+ readonly line1: "Line 1";
32
+ readonly line2: "Line 2";
33
+ readonly line3: "Line 3";
34
+ readonly city: "City";
35
+ readonly state: "State";
36
+ readonly postcode: "Postcode";
37
+ readonly country: "Country";
38
+ readonly select_country: "Select a country";
39
+ readonly validation_empty: "Please enter a value";
40
+ readonly validation_email: "That doesn’t look like a valid email address";
41
+ readonly validation_url: "That doesn’t look like a valid URL";
42
+ readonly validation_max_chars: "Please enter no more than {{count}} characters";
43
+ readonly validation_min_chars: "Please enter {{count}} or more characters";
44
+ readonly validation_phone: "Please enter a valid phone number";
45
+ readonly validation_country_code: "Please select a country code";
46
+ readonly validation_number: "Please enter a valid number";
47
+ readonly validation_number_min: "Please enter a number greater than or equal to {{min}}";
48
+ readonly validation_number_max: "Please enter a number less than or equal to {{max}}";
49
+ readonly validation_number_decimal_cases: "Please enter a number with at most {{count}} decimal cases";
50
+ readonly validation_file: "Please select a file";
51
+ readonly validation_file_ext: "Please only upload {{ext}} files";
52
+ readonly validation_file_min: {
53
+ readonly one: "Please upload at least one file";
54
+ readonly other: "Please only upload at least {{count}} files";
55
+ };
56
+ readonly validation_file_max: {
57
+ readonly one: "Please only upload one file";
58
+ readonly other: "Please only upload up to {{count}} files";
59
+ };
60
+ readonly validation_file_size: "Your file is too big. Please upload a file smaller than {{size}}";
61
+ } = {
62
+ readonly submission_redirect_message: "Almost there! Please complete your submission here:";
63
+ readonly complete_submission: "Complete submission";
64
+ readonly submission_completed: "Submission completed!";
65
+ readonly submission_failed: "Failed to submit";
66
+ readonly maximize: "Maximise";
67
+ readonly minimize: "Minimise";
68
+ readonly close_application: "Close application";
69
+ readonly applying_for: "Applying for “{{title}}”";
70
+ /** When an application is at an invalid state, the user will get this error. */
71
+ readonly invalid_state: "Invalid application state";
72
+ readonly redirect_url_error: "Couldn’t get the redirect URL.";
73
+ readonly upload_file: {
74
+ readonly one: "Select file to upload";
75
+ readonly other: "Select files to upload";
76
+ };
77
+ readonly file_max_size: "max {{size}}";
78
+ readonly file_extensions: "Accepted file extensions";
79
+ readonly address_error: "Something went wrong! Plase continue manually";
80
+ readonly address_search: "Type and search for places…";
81
+ readonly address_manual: "Fill in manually";
82
+ readonly back: "Back";
83
+ readonly search: "Search";
84
+ readonly unknown_error: "An error occurred";
85
+ readonly line1: "Line 1";
86
+ readonly line2: "Line 2";
87
+ readonly line3: "Line 3";
88
+ readonly city: "City";
89
+ readonly state: "State";
90
+ readonly postcode: "Postcode";
91
+ readonly country: "Country";
92
+ readonly select_country: "Select a country";
93
+ readonly validation_empty: "Please enter a value";
94
+ readonly validation_email: "That doesn’t look like a valid email address";
95
+ readonly validation_url: "That doesn’t look like a valid URL";
96
+ readonly validation_max_chars: "Please enter no more than {{count}} characters";
97
+ readonly validation_min_chars: "Please enter {{count}} or more characters";
98
+ readonly validation_phone: "Please enter a valid phone number";
99
+ readonly validation_country_code: "Please select a country code";
100
+ readonly validation_number: "Please enter a valid number";
101
+ readonly validation_number_min: "Please enter a number greater than or equal to {{min}}";
102
+ readonly validation_number_max: "Please enter a number less than or equal to {{max}}";
103
+ readonly validation_number_decimal_cases: "Please enter a number with at most {{count}} decimal cases";
104
+ readonly validation_file: "Please select a file";
105
+ readonly validation_file_ext: "Please only upload {{ext}} files";
106
+ readonly validation_file_min: {
107
+ readonly one: "Please upload at least one file";
108
+ readonly other: "Please only upload at least {{count}} files";
109
+ };
110
+ readonly validation_file_max: {
111
+ readonly one: "Please only upload one file";
112
+ readonly other: "Please only upload up to {{count}} files";
113
+ };
114
+ readonly validation_file_size: "Your file is too big. Please upload a file smaller than {{size}}";
115
+ }>() => {
116
+ t: _inploi_i18n_translation.TFn<T>;
117
+ locale: string | undefined;
118
+ };
119
+ type TFunction = ReturnType<typeof useTranslation>['t'];
120
+
121
+ type MaybePromise<T> = T | Promise<T>;
122
+ type FlowInterpreterYield = {
123
+ type: 'submissions';
124
+ submissions: FlowSubmissions;
125
+ } | {
126
+ type: 'state';
127
+ state: 'loading' | 'idle';
128
+ } | {
129
+ type: 'error';
130
+ message: string;
131
+ } | {
132
+ type: 'info';
133
+ message: string;
134
+ } | {
135
+ type: 'success';
136
+ message: string;
137
+ } | {
138
+ type: 'text';
139
+ author: 'user' | 'bot';
140
+ message: string;
141
+ } | {
142
+ type: 'image';
143
+ url: string;
144
+ height: number;
145
+ width: number;
146
+ } | {
147
+ type: 'link';
148
+ href: string;
149
+ message: string;
150
+ } | {
151
+ type: 'end';
152
+ } | {
153
+ type: 'input';
154
+ input: {
155
+ [I in FlowInput['type']]: {
156
+ type: I;
157
+ config: (FlowInput & {
158
+ type: I;
159
+ })['config'];
160
+ validate: (input: NonNullable<(FlowInput & {
161
+ type: I;
162
+ })['submission']>['value'] | null) => MaybePromise<Result<NonNullable<(FlowInput & {
163
+ type: I;
164
+ })['submission']>['value'] | null, Issues>>;
165
+ };
166
+ }[FlowInput['type']];
167
+ };
168
+ type FlowInterpreterParams = {
169
+ apiClient: ApiClient;
170
+ analytics: {
171
+ service: AnalyticsService;
172
+ customProperties?: Record<string, unknown>;
173
+ };
174
+ logger: Logger;
175
+ t: TFunction;
176
+ };
177
+ type FlowActions = {
178
+ error: ({ message }: {
179
+ message: string;
180
+ }) => FlowInterpreterYield;
181
+ info: ({ message }: {
182
+ message: string;
183
+ }) => FlowInterpreterYield;
184
+ success: ({ message }: {
185
+ message: string;
186
+ }) => FlowInterpreterYield;
187
+ text: ({ message, author }: {
188
+ message: string;
189
+ author: 'bot' | 'user';
190
+ }) => FlowInterpreterYield;
191
+ image: ({ url, height, width }: {
192
+ url: string;
193
+ height: number;
194
+ width: number;
195
+ }) => FlowInterpreterYield;
196
+ link: ({ href, message }: {
197
+ href: string;
198
+ message: string;
199
+ }) => FlowInterpreterYield;
200
+ submissions: (submissions: FlowSubmissions) => FlowInterpreterYield;
201
+ state: (state: 'loading' | 'idle') => FlowInterpreterYield;
202
+ input: <T extends FlowInput['type'], Input extends FlowInput & {
203
+ type: T;
204
+ }>(type: T, params: {
205
+ config: Input['config'];
206
+ validate: (input: NonNullable<Input['submission']>['value'] | null) => MaybePromise<Result<NonNullable<Input['submission']>['value'] | null, Issues>>;
207
+ }) => FlowInterpreterYield;
208
+ };
209
+ declare const createFlowInterpreter: (params: FlowInterpreterParams) => {
210
+ interpret: ({ nodes, context, }: {
211
+ nodes: LinkedList<FlowNode>;
212
+ context: Record<string, unknown>;
213
+ }) => AsyncGenerator<FlowInterpreterYield>;
214
+ };
215
+ type InterpretNodeParams<TNodeType extends FlowNode['type']> = {
216
+ node: FlowNode & {
217
+ type: TNodeType;
218
+ };
219
+ config: FlowInterpreterParams & {
220
+ submissions: FlowSubmissions;
221
+ context: Record<string, unknown>;
222
+ next: (nextId: string | undefined) => {
223
+ type: 'next';
224
+ nodeId: string | undefined;
225
+ };
226
+ actions: FlowActions;
227
+ };
228
+ };
229
+ type InterpretNodeReturn = AsyncGenerator<FlowInterpreterYield, {
230
+ type: 'next';
231
+ nodeId: string | undefined;
232
+ }>;
233
+
234
+ export { FlowActions, FlowInterpreterParams, InterpretNodeParams, InterpretNodeReturn, createFlowInterpreter };
@@ -0,0 +1,2 @@
1
+ import{A as m,B as f,C as J,E as Z,F as _,G as j,H as ee,I as O,J as te,a as L,b as q,c as K,d as $,e as p,f as h,g as B,h as T,i as G,j as R,k as F,l as I,m as A,n as V,o as g,p as Q,q as v,r as D,s as E,t as U,u as x,v as W,w as k,x as X,y as Y,z as H}from"./chunk-3QWHH45C.mjs";var z=K(B());var ae=({condition:r,context:e,submissions:u,ifBlock:s})=>{let[i,...n]=r.compareKey.split(".");if(!i)return!1;let a=j({context:e,key:i,path:n,submissions:u});if(!a)return!1;switch(a.type){case"address":{let t=(0,z.default)(a.value,n.join("."));switch(r.compare){case"equals":return t===r.compareValue;case"contains":return t?t.includes(r.compareValue):!1;case"notEquals":return t!==r.compareValue;case"notContains":return t?!t.includes(r.compareValue):!0}break}case"integration":{if(typeof a.value!="object"||Array.isArray(a.value))return!1;let t=(0,z.default)(a.value,n.join(".")),o=q(L({},s),{data:q(L({},s.data),{compareKey:"_temp"})});switch(typeof t){case"boolean":return C(o,{submissions:{_temp:{value:t,type:"boolean"}},context:e});case"string":return C(o,{submissions:{_temp:{value:t,type:"string"}},context:e});case"number":return C(o,{submissions:{_temp:{value:t,type:"number"}},context:e});case"object":return Array.isArray(t)&&t.every(l=>typeof l=="string")?C(o,{submissions:{_temp:{value:t,type:"enum"}},context:e}):!1}break}case"boolean":{let t=r.compareValue==="true";switch(r.compare){case"equals":return a.value===t;case"notEquals":return a.value!==t}break}case"phone":case"string":{let t=a.type==="phone"?a.value.countryCode+a.value.phoneNumber:a.value;switch(r.compare){case"equals":return t===r.compareValue;case"contains":return t?t.includes(r.compareValue):!1;case"notEquals":return t!==r.compareValue;case"notContains":return t?!t.includes(r.compareValue):!0}break}case"number":{try{let t=Number(r.compareValue);switch(r.compare){case"equals":return a.value===t;case"notEquals":return a.value!==t;case"greaterThan":return a.value>t;case"greaterThanOrEqualTo":return a.value>=t;case"lessThan":return a.value<t;case"lessThanOrEqualTo":return a.value<=t}}catch(t){return console.error(`Failed to parse number in if-block ${s.id}`,a.value),!1}break}case"enum":switch(r.compare){case"equals":return a.value.length===1&&a.value[0]===r.compareValue;case"notEquals":return a.value.length===1&&a.value[0]!==r.compareValue;case"contains":return a.value.includes(r.compareValue);case"notContains":return!a.value.includes(r.compareValue)}break;case"file":break;default:break}},C=(r,{context:e,submissions:u})=>{let s="combinator"in r.data?r.data.conditions:[r.data];if(("combinator"in r.data?r.data.combinator:"and")==="or"){for(let n of s)if(ae({condition:n,context:e,submissions:u,ifBlock:r}))return!0;return!1}else{for(let n of s)if(!ae({condition:n,context:e,submissions:u,ifBlock:r}))return!1;return!0}};var re=K(B());var ye=/{{\s*([^}]+?)\s*(?:\|\s*([^}]+?)\s*)?}}/g,N=(r,{context:e,submissions:u})=>r.replace(ye,(s,i,n="")=>{let[a,...t]=i.trim().split("."),o=j({key:a,path:t,submissions:u,context:e});if(!o)return n;switch(o.type){case"boolean":return o.value===!0?"true":"false";case"file":return o.value.map(l=>`${l.name} (${O(l.sizeKb)})`).join(", ");case"enum":return o.value.join(", ");case"address":return Object.values(o.value).filter(l=>l&&l.trim().length>0).join(", ");case"number":case"string":return o.value?o.value.toString():n;case"phone":return te(o.value);case"integration":{if(typeof o.value!="object"||Array.isArray(o.value))break;let l=(0,re.default)(o.value,t.join("."));switch(typeof l){case"boolean":return l===!0?"true":"false";case"string":return l;case"number":return l.toString();case"object":if(Array.isArray(l)&&l.every(d=>typeof d=="string"))return l.join(", ")}break}default:}return n});function ne(r){return p(this,null,function*(){let{node:e,config:{logger:u,analytics:s,submissions:i,next:n}}=r;return s.service.log({event:"IDENTIFY",properties:{identifier:_({key:e.data.key,submissions:i}).toString(),first_name:e.data.firstName?_({key:e.data.firstName,submissions:i}).toString():void 0,last_name:e.data.lastName?_({key:e.data.lastName,submissions:i}).toString():void 0,email:e.data.email?_({key:e.data.email,submissions:i}).toString():void 0,phone_number:e.data.phoneNumber?_({key:e.data.phoneNumber,submissions:i}).toString():void 0,custom_traits:e.data.customTraits?Object.fromEntries(e.data.customTraits.map(({key:a,value:t})=>{var o;return[a,(o=i[t])==null?void 0:o.value]})):void 0}}).catch(u.error),n(e.nextId)})}var ge=I({success:G(),integration_response:I({service:A(g()),status:F(),data:Q(),error:R(I({message:g(),data:Q()}))})});function oe(r){return p(this,null,function*(){var l;let{node:e,config:{apiClient:u,submissions:s,actions:i,next:n,analytics:a,logger:t,context:o}}=r;return e.data.skipConfirmation!==!0&&(yield i.input("submit",{config:{key:(l=e.data.key)!=null?l:"_SUBMIT",label:e.data.submitLabel},validate:()=>$(this,null,function*(){let c=J(a.service.getSessionInfo)();c.err&&t.error(c.val.originalError);try{let y=yield u.fetch("/flow/submit",{method:"POST",body:JSON.stringify({log_submit:!1,integration_id:e.data.integrationId,anonymous_id:c.ok?c.val.anonymous_id:void 0,session_id:c.ok?c.val.session_id:void 0,job:o.job,submissions:Z(s)})}),b=v(ge,y);return b.success===!1?f(b.issues):m(b.output)}catch(y){let b=[{input:y,origin:"value",reason:"unknown",validation:"API error",message:y instanceof Error?y.message:"toString"in y?y.toString():"Unknown error"}];return f(b)}})})),n(e.nextId)})}var S=R(A(g())),ve=({node:r})=>{var u,s,i,n,a,t,o;let e=r.data.keys;return I({[(u=e.line1)!=null?u:"line1"]:S,[(s=e.line2)!=null?s:"line2"]:S,[(i=e.line3)!=null?i:"line3"]:S,[(n=e.city)!=null?n:"city"]:S,[(a=e.country)!=null?a:"country"]:S,[(t=e.postcode)!=null?t:"postcode"]:S,[(o=e.state)!=null?o:"state"]:S})};function se(r){return p(this,null,function*(){let{node:e,config:{submissions:u,actions:s,next:i}}=r;return yield s.text({author:"bot",message:e.data.question}),yield s.input("address",{config:{key:e.data.key,keys:e.data.keys,placeholder:e.data.placeholder,optional:e.data.optional},validate:n=>{if(e.data.optional&&n===null)return m(n);let a=ve(r),t=v(a,n);return t.success===!1?f(t.issues):(u[e.data.key]={type:"address",value:t.output},m(n))}}),i(e.nextId)})}var be=["true","false"],he=V(be);function ie(r){return p(this,null,function*(){let{node:e,config:{submissions:u,actions:s,next:i}}=r;return yield s.text({author:"bot",message:e.data.question}),yield s.input("boolean",{config:{key:e.data.key,labels:{false:e.data.falseLabel,true:e.data.trueLabel},optional:e.data.optional},validate:n=>{if(e.data.optional&&n===null)return m(n);let a=v(he,n);return a.success===!1?f(a.issues):(u[e.data.key]={type:"boolean",value:a.output==="true"},m(n))}}),i(e.nextId)})}function ue(r){return p(this,null,function*(){let{node:e,config:{submissions:u,actions:s,next:i}}=r;yield s.text({author:"bot",message:e.data.question});let n=T(V(e.data.options.map(a=>a.value)));return yield s.input("multiple-choice",{config:{key:e.data.key,options:e.data.options,maxSelected:e.data.maxSelected,minSelected:e.data.minSelected},validate:a=>{if(e.data.minSelected===0&&a===null)return m(a);let t=v(n,a);return t.success===!1?f(t.issues):(u[e.data.key]={type:"enum",value:t.output},m(a))}}),i(e.nextId)})}function le(r){return p(this,null,function*(){let{node:e,config:{submissions:u,actions:s,next:i,t:n}}=r;return yield s.text({author:"bot",message:e.data.question}),yield s.input("file",{config:{key:e.data.key,allowMultiple:e.data.multiple===!0,extensions:e.data.extensions,fileSizeLimitKib:e.data.maxSizeKb,optional:e.data.optional},validate:a=>{var b;if(e.data.optional&&a===null)return m(a);let t=e.data.optional?0:1,o=e.data.multiple?Number.POSITIVE_INFINITY:1,l=(b=e.data.maxSizeKb)!=null?b:0,d=e.data.extensions.map(P=>P.toLowerCase()),c=T(I({name:g(n("validation_empty"),[E(P=>{let M=ee(P);return M.ok===!1?!1:d.includes(M.val.toLowerCase())},n("validation_file_ext",{ext:d.join(", ")}))]),data:g(),sizeKb:F()}),[k(t,n("validation_file_min",{count:t})),x(o,n("validation_file_max",{count:o})),E(P=>P.reduce((pe,fe)=>pe+fe.sizeKb,0)<=l,n("validation_file_size",{size:O(l)}))]),y=v(c,a);return y.success===!1?f(y.issues):(u[e.data.key]={type:"file",value:y.output},m(a))}}),i(e.nextId)})}var Ie=({node:r,config:{t:e}})=>{var n,a,t;let u=(n=r.data.min)!=null?n:Number.MIN_SAFE_INTEGER,s=(a=r.data.max)!=null?a:Number.MAX_SAFE_INTEGER,i=(t=r.data.decimalCases)!=null?t:0;return F(e("validation_number"),[X(u,e("validation_number_min",{min:u})),W(s,e("validation_number_max",{max:s})),E(o=>o===Number(o.toFixed(i)),e("validation_number_decimal_cases",{count:i}))])};function de(r){return p(this,null,function*(){let{node:e,config:{submissions:u,actions:s,next:i}}=r;yield s.text({author:"bot",message:e.data.question});let n=u[e.data.key];return yield s.input("number",{config:{key:e.data.key,placeholder:e.data.placeholder,optional:e.data.optional,decimalCases:e.data.decimalCases,max:e.data.max,min:e.data.min,defaultValue:(n==null?void 0:n.type)==="number"?n.value.toString():void 0},validate:a=>{if(e.data.optional&&a===null)return m(a);let t=Ie(r),o=v(t,a);return o.success===!1?f(o.issues):(u[e.data.key]={type:"number",value:o.output},m(a))}}),i(e.nextId)})}var xe=({node:r,config:{t:e}})=>I({countryCode:g(e("validation_country_code"),[Y(/^\+?[0-9 -]+$/,e("validation_country_code"))]),phoneNumber:D(g(e("validation_phone"),[Y(/^\+?[0-9 -]+$/,e("validation_phone")),k(r.data.minChars,e("validation_min_chars",{count:r.data.minChars})),x(r.data.maxChars,e("validation_max_chars",{count:r.data.maxChars}))]),u=>u.replace(/[^0-9]/g,""),[])});function me(r){return p(this,null,function*(){let{node:e,config:{actions:u,next:s,submissions:i}}=r;yield u.text({author:"bot",message:e.data.question});let n=i[e.data.key];return yield u.input("phone",{config:{key:e.data.key,minChars:e.data.minChars,maxChars:e.data.maxChars,defaultValue:(n==null?void 0:n.type)==="phone"?n.value:{countryCode:e.data.defaultCountryCode},placeholder:e.data.placeholder,submissionFormat:"phone",optional:e.data.optional},validate:a=>{if(e.data.optional&&a===null)return m(a);let t=xe(r),o=v(t,a);return o.success===!1?f(o.issues):(i[e.data.key]={type:"address",value:o.output},m(a))}}),s(e.nextId)})}var ke=({node:r,config:{t:e,logger:u}})=>{var i,n,a,t,o,l,d,c,y,b;let s={email:e("validation_email"),url:e("validation_url"),maxLength:e("validation_max_chars",{count:(i=r.data.maxChars)!=null?i:999}),minLength:e("validation_min_chars",{count:(n=r.data.minChars)!=null?n:1})};switch(r.data.format){case"email":return g(s.email,[U(s.email),k((a=r.data.minChars)!=null?a:1,s.minLength),x((t=r.data.maxChars)!=null?t:1/0,s.maxLength)]);case"text":return g([k((o=r.data.minChars)!=null?o:1,s.minLength),x((l=r.data.maxChars)!=null?l:1/0,s.maxLength)]);case"url":return g([H(s.url),k((d=r.data.minChars)!=null?d:1,s.minLength),x((c=r.data.maxChars)!=null?c:1/0,s.maxLength)]);case"phone":return g([k((y=r.data.minChars)!=null?y:1,s.minLength),x((b=r.data.maxChars)!=null?b:1/0,s.maxLength)]);default:return r.data.format,u.error(`Unsupported question-text format: ${r.data.format}`),null}};function ce(r){return p(this,null,function*(){let{node:e,config:{submissions:u,actions:s,next:i}}=r;yield s.text({author:"bot",message:e.data.question});let n=u[e.data.key];return yield s.input("text",{config:{key:e.data.key,maxChars:e.data.maxChars,minChars:e.data.minChars,placeholder:e.data.placeholder,format:e.data.format,optional:e.data.optional,defaultValue:(n==null?void 0:n.type)==="string"?n.value:void 0},validate:a=>{if(e.data.optional&&a===null)return m(a);let t=ke(r);if(t===null)return m(a);let o=v(t,a);return o.success===!1?f(o.issues):(u[e.data.key]={type:"string",value:o.output},m(a))}}),i(e.nextId)})}var ft=r=>{let e={};return{interpret:function(n){return p(this,arguments,function*({nodes:s,context:i}){let a={error:({message:d})=>({type:"error",message:N(d,{submissions:e,context:i})}),info:({message:d})=>({type:"info",message:N(d,{submissions:e,context:i})}),success:({message:d})=>({type:"success",message:N(d,{submissions:e,context:i})}),text:({message:d,author:c})=>({type:"text",author:c,message:N(d,{submissions:e,context:i})}),image:({url:d,height:c,width:y})=>({type:"image",url:N(d,{submissions:e,context:i}),height:c,width:y}),state:d=>({type:"state",state:d}),link:({href:d,message:c})=>({type:"link",href:N(d,{submissions:e,context:i}),message:N(c,{submissions:e,context:i})}),submissions:d=>({type:"submissions",submissions:d}),input:(d,c)=>({type:"input",input:{type:d,config:c.config,validate:c.validate}})};if(!s.headId)return{type:"error",message:"No head node found"};let t=s.items[s.headId],o=d=>{if(!d)return t=void 0,{type:"next",nodeId:void 0};let c=s.items[d];if(!c)throw new Error(`Next node with id ${d} not found`);return t=c,{type:"next",nodeId:d}},l=q(L({},r),{context:i,submissions:e,next:o,actions:a});for(;t;){switch(t.type){case"text":yield a.text({author:"bot",message:t.data.text}),o(t.nextId);break;case"image":yield a.image(t.data),o(t.nextId);break;case"link":yield a.link({href:t.data.href,message:t.data.cta}),o(t.nextId);break;case"add-submission":e[t.data.key]={type:"string",value:t.data.value},o(t.nextId);break;case"jump":o(t.data.targetId);break;case"question-text":yield*h(ce({config:l,node:t}));break;case"question-phone":yield*h(me({config:l,node:t}));break;case"question-boolean":yield*h(ie({config:l,node:t}));break;case"question-number":yield*h(de({config:l,node:t}));break;case"question-address":yield*h(se({config:l,node:t}));break;case"question-enum":yield*h(ue({config:l,node:t}));break;case"question-file":yield*h(le({config:l,node:t}));break;case"identify":{yield*h(ne({config:l,node:t}));break}case"if-block":{let d=C(t,{context:l.context,submissions:e})?t.branchId:t.nextId;o(d);break}case"integration-application-submit":yield*h(oe({config:l,node:t}));break;case"feedback":yield a.error({message:"Not implemented"});break;case"integration-workflow-get":yield a.error({message:"This message should never be reached"});break;case"end-flow":t=void 0;break}yield a.submissions(e)}yield{type:"end"}})}}};export{ft as createFlowInterpreter};
2
+ //# sourceMappingURL=interpreter.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/conditions.ts","../src/interpolation.ts","../src/interpreter.identify.ts","../src/interpreter.integration-application-submit.ts","../src/interpreter.question-address.ts","../src/interpreter.question-boolean.ts","../src/interpreter.question-enum.ts","../src/interpreter.question-file.ts","../src/interpreter.question-number.ts","../src/interpreter.question-phone.ts","../src/interpreter.question-text.ts","../src/interpreter.ts"],"sourcesContent":["import { IfBlockNode, IfBlockNodeCondition } from '@inploi/core/flows';\nimport get from 'lodash/get';\n\nimport { FlowSubmissions } from './flow.types';\nimport { getSubmissionValueToCheck } from './utils';\n\nconst isConditionMet = ({\n\tcondition,\n\tcontext,\n\tsubmissions,\n\tifBlock,\n}: {\n\tcontext: Record<string, unknown>;\n\tcondition: IfBlockNodeCondition;\n\tsubmissions: FlowSubmissions;\n\tifBlock: IfBlockNode;\n}) => {\n\tconst [firstSegment, ...path] = condition.compareKey.split('.');\n\tif (!firstSegment) return false;\n\n\tconst answer = getSubmissionValueToCheck({ context, key: firstSegment, path, submissions });\n\tif (!answer) return false;\n\n\tswitch (answer.type) {\n\t\tcase 'address': {\n\t\t\tconst value = get(answer.value, path.join('.'));\n\t\t\tswitch (condition.compare) {\n\t\t\t\tcase 'equals':\n\t\t\t\t\treturn value === condition.compareValue;\n\t\t\t\tcase 'contains':\n\t\t\t\t\tif (!value) return false;\n\t\t\t\t\treturn value.includes(condition.compareValue);\n\t\t\t\tcase 'notEquals':\n\t\t\t\t\treturn value !== condition.compareValue;\n\t\t\t\tcase 'notContains':\n\t\t\t\t\tif (!value) return true;\n\t\t\t\t\treturn !value.includes(condition.compareValue);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 'integration': {\n\t\t\t/** We only handle objects as integration submissions for now. */\n\t\t\tif (typeof answer.value !== 'object') return false;\n\t\t\tif (Array.isArray(answer.value)) return false;\n\n\t\t\tconst value = get(answer.value, path.join('.'));\n\t\t\tconst newIfBlock = { ...ifBlock, data: { ...ifBlock.data, compareKey: '_temp' } };\n\t\t\tswitch (typeof value) {\n\t\t\t\tcase 'boolean':\n\t\t\t\t\treturn isIfBlockConditionMet(newIfBlock, {\n\t\t\t\t\t\tsubmissions: { ['_temp']: { value: value, type: 'boolean' } },\n\t\t\t\t\t\tcontext,\n\t\t\t\t\t});\n\t\t\t\tcase 'string':\n\t\t\t\t\treturn isIfBlockConditionMet(newIfBlock, {\n\t\t\t\t\t\tsubmissions: { ['_temp']: { value: value, type: 'string' } },\n\t\t\t\t\t\tcontext,\n\t\t\t\t\t});\n\t\t\t\tcase 'number':\n\t\t\t\t\treturn isIfBlockConditionMet(newIfBlock, {\n\t\t\t\t\t\tsubmissions: { ['_temp']: { value: value, type: 'number' } },\n\t\t\t\t\t\tcontext,\n\t\t\t\t\t});\n\t\t\t\tcase 'object':\n\t\t\t\t\t/** We only handle enums if the result is an array of strings */\n\t\t\t\t\tif (Array.isArray(value) && value.every((value): value is string => typeof value === 'string')) {\n\t\t\t\t\t\treturn isIfBlockConditionMet(newIfBlock, {\n\t\t\t\t\t\t\tsubmissions: { ['_temp']: { value: value, type: 'enum' } },\n\t\t\t\t\t\t\tcontext,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\treturn false;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 'boolean': {\n\t\t\tconst compareBoolean = condition.compareValue === 'true';\n\t\t\tswitch (condition.compare) {\n\t\t\t\tcase 'equals':\n\t\t\t\t\treturn answer.value === compareBoolean;\n\t\t\t\tcase 'notEquals':\n\t\t\t\t\treturn answer.value !== compareBoolean;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 'phone':\n\t\tcase 'string': {\n\t\t\tconst value = answer.type === 'phone' ? answer.value.countryCode + answer.value.phoneNumber : answer.value;\n\t\t\tswitch (condition.compare) {\n\t\t\t\tcase 'equals':\n\t\t\t\t\treturn value === condition.compareValue;\n\t\t\t\tcase 'contains':\n\t\t\t\t\tif (!value) return false;\n\t\t\t\t\treturn value.includes(condition.compareValue);\n\t\t\t\tcase 'notEquals':\n\t\t\t\t\treturn value !== condition.compareValue;\n\t\t\t\tcase 'notContains':\n\t\t\t\t\tif (!value) return true;\n\t\t\t\t\treturn !value.includes(condition.compareValue);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 'number': {\n\t\t\ttry {\n\t\t\t\tconst compareNumber = Number(condition.compareValue);\n\t\t\t\tswitch (condition.compare) {\n\t\t\t\t\tcase 'equals':\n\t\t\t\t\t\treturn answer.value === compareNumber;\n\t\t\t\t\tcase 'notEquals':\n\t\t\t\t\t\treturn answer.value !== compareNumber;\n\t\t\t\t\tcase 'greaterThan':\n\t\t\t\t\t\treturn answer.value > compareNumber;\n\t\t\t\t\tcase 'greaterThanOrEqualTo':\n\t\t\t\t\t\treturn answer.value >= compareNumber;\n\t\t\t\t\tcase 'lessThan':\n\t\t\t\t\t\treturn answer.value < compareNumber;\n\t\t\t\t\tcase 'lessThanOrEqualTo':\n\t\t\t\t\t\treturn answer.value <= compareNumber;\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\tconsole.error(`Failed to parse number in if-block ${ifBlock.id}`, answer.value);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 'enum':\n\t\t\tswitch (condition.compare) {\n\t\t\t\tcase 'equals':\n\t\t\t\t\treturn answer.value.length === 1 && answer.value[0] === condition.compareValue;\n\t\t\t\tcase 'notEquals':\n\t\t\t\t\treturn answer.value.length === 1 && answer.value[0] !== condition.compareValue;\n\t\t\t\tcase 'contains':\n\t\t\t\t\treturn answer.value.includes(condition.compareValue);\n\t\t\t\tcase 'notContains':\n\t\t\t\t\treturn !answer.value.includes(condition.compareValue);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase 'file':\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tanswer satisfies never;\n\t\t\tbreak;\n\t}\n};\n\nexport const isIfBlockConditionMet = (\n\tifBlock: IfBlockNode,\n\t{ context, submissions }: { submissions: FlowSubmissions; context: Record<string, unknown> },\n): boolean => {\n\tconst conditions = 'combinator' in ifBlock.data ? ifBlock.data.conditions : [ifBlock.data];\n\tconst combinator = 'combinator' in ifBlock.data ? ifBlock.data.combinator : 'and';\n\n\tif (combinator === 'or') {\n\t\tfor (const condition of conditions) {\n\t\t\tconst isMet = isConditionMet({ condition, context, submissions, ifBlock });\n\t\t\tif (isMet) return true;\n\t\t}\n\t\treturn false;\n\t} else {\n\t\tfor (const condition of conditions) {\n\t\t\tconst isMet = isConditionMet({ condition, context, submissions, ifBlock });\n\t\t\tif (!isMet) return false;\n\t\t}\n\t\treturn true;\n\t}\n};\n","import get from 'lodash/get';\n\nimport { FlowSubmissions } from './flow.types';\nimport { formatPhoneNumber, getSubmissionValueToCheck, kbToReadableSize } from './utils';\n\nconst HANDLEBARS_REGEXP = /{{\\s*([^}]+?)\\s*(?:\\|\\s*([^}]+?)\\s*)?}}/g;\n\nexport const interpolateWithData = (\n\tstr: string,\n\t{ context, submissions }: { submissions: FlowSubmissions; context: Record<string, unknown> },\n) => {\n\treturn str.replace(HANDLEBARS_REGEXP, (_, key, defaultValue = '') => {\n\t\tconst [firstSegment, ...path] = key.trim().split('.');\n\t\tconst entity = getSubmissionValueToCheck({ key: firstSegment, path, submissions, context });\n\t\tif (!entity) return defaultValue;\n\n\t\tswitch (entity.type) {\n\t\t\tcase 'boolean':\n\t\t\t\treturn entity.value === true ? 'true' : 'false';\n\t\t\tcase 'file':\n\t\t\t\treturn entity.value.map(file => `${file.name} (${kbToReadableSize(file.sizeKb)})`).join(', ');\n\t\t\tcase 'enum':\n\t\t\t\treturn entity.value.join(', ');\n\t\t\tcase 'address':\n\t\t\t\treturn Object.values(entity.value)\n\t\t\t\t\t.filter(line => line && line.trim().length > 0)\n\t\t\t\t\t.join(', ');\n\t\t\tcase 'number':\n\t\t\tcase 'string':\n\t\t\t\tif (!entity.value) return defaultValue;\n\t\t\t\treturn entity.value.toString();\n\t\t\tcase 'phone':\n\t\t\t\treturn formatPhoneNumber(entity.value);\n\t\t\tcase 'integration': {\n\t\t\t\t/** We only handle objects as integration submissions for now. */\n\t\t\t\tif (typeof entity.value !== 'object') break;\n\t\t\t\tif (Array.isArray(entity.value)) break;\n\n\t\t\t\tconst value = get(entity.value, path.join('.'));\n\t\t\t\tswitch (typeof value) {\n\t\t\t\t\tcase 'boolean':\n\t\t\t\t\t\treturn value === true ? 'true' : 'false';\n\t\t\t\t\tcase 'string':\n\t\t\t\t\t\treturn value;\n\t\t\t\t\tcase 'number':\n\t\t\t\t\t\treturn value.toString();\n\t\t\t\t\tcase 'object':\n\t\t\t\t\t\t/** We only handle enums if the result is an array of strings */\n\t\t\t\t\t\tif (Array.isArray(value) && value.every((i): i is string => typeof i === 'string')) {\n\t\t\t\t\t\t\treturn value.join(', ');\n\t\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\tentity satisfies never;\n\t\t}\n\t\treturn defaultValue;\n\t});\n};\n","import { InterpretNodeParams } from './interpreter';\nimport { getSubmissionValue } from './utils';\n\nexport async function* interpretIdentifyNode(params: InterpretNodeParams<'identify'>) {\n\tconst {\n\t\tnode,\n\t\tconfig: { logger, analytics, submissions, next },\n\t} = params;\n\n\tanalytics.service\n\t\t.log({\n\t\t\tevent: 'IDENTIFY',\n\t\t\tproperties: {\n\t\t\t\tidentifier: getSubmissionValue({ key: node.data.key, submissions }).toString(),\n\t\t\t\tfirst_name:\n\t\t\t\t\tnode.data.firstName ? getSubmissionValue({ key: node.data.firstName, submissions }).toString() : undefined,\n\t\t\t\tlast_name:\n\t\t\t\t\tnode.data.lastName ? getSubmissionValue({ key: node.data.lastName, submissions }).toString() : undefined,\n\t\t\t\temail: node.data.email ? getSubmissionValue({ key: node.data.email, submissions }).toString() : undefined,\n\t\t\t\tphone_number:\n\t\t\t\t\tnode.data.phoneNumber ?\n\t\t\t\t\t\tgetSubmissionValue({ key: node.data.phoneNumber, submissions }).toString()\n\t\t\t\t\t:\tundefined,\n\t\t\t\tcustom_traits:\n\t\t\t\t\tnode.data.customTraits ?\n\t\t\t\t\t\tObject.fromEntries(node.data.customTraits.map(({ key, value }) => [key, submissions[value]?.value]))\n\t\t\t\t\t:\tundefined,\n\t\t\t},\n\t\t})\n\t\t.catch(logger.error);\n\n\treturn next(node.nextId);\n}\n","import * as v from 'valibot';\n\nimport { InterpretNodeParams, InterpretNodeReturn } from './interpreter';\nimport { Err, Ok, tryCatch } from './result';\nimport { getFlowSubmissionsPayload } from './utils';\n\nconst responseSchema = v.object({\n\t/** Not necessarily true when we receive a positive response because the API considers only 200 as success */\n\tsuccess: v.boolean(),\n\tintegration_response: v.object({\n\t\tservice: v.optional(v.string()),\n\t\tstatus: v.number(),\n\t\tdata: v.unknown(),\n\t\terror: v.nullable(v.object({ message: v.string(), data: v.unknown() })),\n\t}),\n});\nexport type IntegrationResponse = v.Output<typeof responseSchema>;\n\nexport async function* interpretIntegrationApplicationSubmitNode(\n\tparams: InterpretNodeParams<'integration-application-submit'>,\n): InterpretNodeReturn {\n\tconst {\n\t\tnode,\n\t\tconfig: { apiClient, submissions, actions, next, analytics, logger, context },\n\t} = params;\n\n\tif (node.data.skipConfirmation !== true) {\n\t\tyield actions.input('submit', {\n\t\t\tconfig: {\n\t\t\t\tkey: node.data.key ?? '_SUBMIT',\n\t\t\t\tlabel: node.data.submitLabel,\n\t\t\t},\n\t\t\t/** move all submitting logic to the validate, makes much more sense */\n\t\t\tvalidate: async () => {\n\t\t\t\tconst getSessionInfoSafe = tryCatch(analytics.service.getSessionInfo);\n\t\t\t\tconst sessionInfo = getSessionInfoSafe();\n\t\t\t\tif (sessionInfo.err) logger.error(sessionInfo.val.originalError);\n\n\t\t\t\ttry {\n\t\t\t\t\tconst response = await apiClient.fetch(`/flow/submit`, {\n\t\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\t\t\tlog_submit: false,\n\t\t\t\t\t\t\tintegration_id: node.data.integrationId,\n\t\t\t\t\t\t\tanonymous_id: sessionInfo.ok ? sessionInfo.val.anonymous_id : undefined,\n\t\t\t\t\t\t\tsession_id: sessionInfo.ok ? sessionInfo.val.session_id : undefined,\n\t\t\t\t\t\t\tjob: context.job,\n\t\t\t\t\t\t\tsubmissions: getFlowSubmissionsPayload(submissions),\n\t\t\t\t\t\t}),\n\t\t\t\t\t});\n\n\t\t\t\t\tconst parsed = v.safeParse(responseSchema, response);\n\t\t\t\t\tif (parsed.success === false) return Err(parsed.issues);\n\t\t\t\t\treturn Ok(parsed.output);\n\t\t\t\t} catch (e) {\n\t\t\t\t\tconst issues: v.Issues = [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tinput: e,\n\t\t\t\t\t\t\torigin: 'value',\n\t\t\t\t\t\t\treason: 'unknown',\n\t\t\t\t\t\t\tvalidation: 'API error',\n\t\t\t\t\t\t\tmessage:\n\t\t\t\t\t\t\t\te instanceof Error ? e.message\n\t\t\t\t\t\t\t\t: 'toString' in (e as any) ? (e as any).toString()\n\t\t\t\t\t\t\t\t: 'Unknown error',\n\t\t\t\t\t\t},\n\t\t\t\t\t];\n\t\t\t\t\treturn Err(issues);\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t}\n\n\treturn next(node.nextId);\n}\n","import * as v from 'valibot';\n\nimport { InterpretNodeParams, InterpretNodeReturn } from './interpreter';\nimport { Err, Ok } from './result';\n\nconst fieldValueSchema = v.nullable(v.optional(v.string()));\nconst getValidationSchema = ({ node }: InterpretNodeParams<'question-address'>) => {\n\tconst keys = node.data.keys;\n\treturn v.object({\n\t\t[keys.line1 ?? 'line1']: fieldValueSchema,\n\t\t[keys.line2 ?? 'line2']: fieldValueSchema,\n\t\t[keys.line3 ?? 'line3']: fieldValueSchema,\n\t\t[keys.city ?? 'city']: fieldValueSchema,\n\t\t[keys.country ?? 'country']: fieldValueSchema,\n\t\t[keys.postcode ?? 'postcode']: fieldValueSchema,\n\t\t[keys.state ?? 'state']: fieldValueSchema,\n\t});\n};\n\nexport async function* interpretQuestionAddressNode(\n\tparams: InterpretNodeParams<'question-address'>,\n): InterpretNodeReturn {\n\tconst {\n\t\tnode,\n\t\tconfig: { submissions, actions, next },\n\t} = params;\n\tyield actions.text({ author: 'bot', message: node.data.question });\n\n\tyield actions.input('address', {\n\t\tconfig: {\n\t\t\tkey: node.data.key,\n\t\t\tkeys: node.data.keys,\n\t\t\tplaceholder: node.data.placeholder,\n\t\t\toptional: node.data.optional,\n\t\t},\n\t\tvalidate: submission => {\n\t\t\tif (node.data.optional && submission === null) return Ok(submission);\n\t\t\tconst schema = getValidationSchema(params);\n\t\t\tconst parsed = v.safeParse(schema, submission);\n\t\t\tif (parsed.success === false) return Err(parsed.issues);\n\t\t\tsubmissions[node.data.key] = { type: 'address', value: parsed.output };\n\t\t\treturn Ok(submission);\n\t\t},\n\t});\n\n\treturn next(node.nextId);\n}\n","import * as v from 'valibot';\n\nimport { InterpretNodeParams, InterpretNodeReturn } from './interpreter';\nimport { Err, Ok } from './result';\n\nconst options = ['true', 'false'] as const;\nconst schema = v.picklist(options);\n\nexport async function* interpretQuestionBooleanNode(\n\tparams: InterpretNodeParams<'question-boolean'>,\n): InterpretNodeReturn {\n\tconst {\n\t\tnode,\n\t\tconfig: { submissions, actions, next },\n\t} = params;\n\tyield actions.text({ author: 'bot', message: node.data.question });\n\n\tyield actions.input('boolean', {\n\t\tconfig: {\n\t\t\tkey: node.data.key,\n\t\t\tlabels: {\n\t\t\t\tfalse: node.data.falseLabel,\n\t\t\t\ttrue: node.data.trueLabel,\n\t\t\t},\n\t\t\toptional: node.data.optional,\n\t\t},\n\t\tvalidate: submission => {\n\t\t\tif (node.data.optional && submission === null) return Ok(submission);\n\t\t\tconst parsed = v.safeParse(schema, submission);\n\t\t\tif (parsed.success === false) return Err(parsed.issues);\n\t\t\tsubmissions[node.data.key] = { type: 'boolean', value: parsed.output === 'true' };\n\t\t\treturn Ok(submission);\n\t\t},\n\t});\n\n\treturn next(node.nextId);\n}\n","import { NonEmptyArray } from '@inploi/core/common';\nimport * as v from 'valibot';\n\nimport { InterpretNodeParams, InterpretNodeReturn } from './interpreter';\nimport { Err, Ok } from './result';\n\nexport async function* interpretQuestionEnumNode(params: InterpretNodeParams<'question-enum'>): InterpretNodeReturn {\n\tconst {\n\t\tnode,\n\t\tconfig: { submissions, actions, next },\n\t} = params;\n\tyield actions.text({ author: 'bot', message: node.data.question });\n\n\tconst schema = v.array(v.picklist(node.data.options.map(o => o.value) as NonEmptyArray<string>));\n\tyield actions.input('multiple-choice', {\n\t\tconfig: {\n\t\t\tkey: node.data.key,\n\t\t\toptions: node.data.options,\n\t\t\tmaxSelected: node.data.maxSelected,\n\t\t\tminSelected: node.data.minSelected,\n\t\t},\n\t\tvalidate: submission => {\n\t\t\tif (node.data.minSelected === 0 && submission === null) return Ok(submission);\n\t\t\tconst parsed = v.safeParse(schema, submission);\n\t\t\tif (parsed.success === false) return Err(parsed.issues);\n\t\t\tsubmissions[node.data.key] = { type: 'enum', value: parsed.output };\n\t\t\treturn Ok(submission);\n\t\t},\n\t});\n\n\treturn next(node.nextId);\n}\n","import * as v from 'valibot';\n\nimport { InterpretNodeParams, InterpretNodeReturn } from './interpreter';\nimport { Err, Ok } from './result';\nimport { getFileExtension, kbToReadableSize } from './utils';\n\nexport async function* interpretQuestionFileNode(params: InterpretNodeParams<'question-file'>): InterpretNodeReturn {\n\tconst {\n\t\tnode,\n\t\tconfig: { submissions, actions, next, t },\n\t} = params;\n\tyield actions.text({ author: 'bot', message: node.data.question });\n\n\tyield actions.input('file', {\n\t\tconfig: {\n\t\t\tkey: node.data.key,\n\t\t\tallowMultiple: node.data.multiple === true,\n\t\t\textensions: node.data.extensions,\n\t\t\tfileSizeLimitKib: node.data.maxSizeKb,\n\t\t\toptional: node.data.optional,\n\t\t},\n\t\tvalidate: submission => {\n\t\t\tif (node.data.optional && submission === null) return Ok(submission);\n\t\t\tconst minFiles = node.data.optional ? 0 : 1;\n\t\t\tconst maxFiles = node.data.multiple ? Number.POSITIVE_INFINITY : 1;\n\t\t\tconst maxSize = node.data.maxSizeKb ?? 0;\n\t\t\tconst allowedExtensions = node.data.extensions.map(ext => ext.toLowerCase());\n\t\t\tconst schema = v.array(\n\t\t\t\tv.object({\n\t\t\t\t\tname: v.string(t('validation_empty'), [\n\t\t\t\t\t\tv.custom(\n\t\t\t\t\t\t\tfilename => {\n\t\t\t\t\t\t\t\tconst extension = getFileExtension(filename);\n\t\t\t\t\t\t\t\tif (extension.ok === false) return false;\n\t\t\t\t\t\t\t\treturn allowedExtensions.includes(extension.val.toLowerCase());\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tt('validation_file_ext', { ext: allowedExtensions.join(', ') }),\n\t\t\t\t\t\t),\n\t\t\t\t\t]),\n\t\t\t\t\tdata: v.string(),\n\t\t\t\t\tsizeKb: v.number(),\n\t\t\t\t}),\n\t\t\t\t[\n\t\t\t\t\tv.minLength(minFiles, t('validation_file_min', { count: minFiles })),\n\t\t\t\t\tv.maxLength(maxFiles, t('validation_file_max', { count: maxFiles })),\n\t\t\t\t\tv.custom(\n\t\t\t\t\t\tfiles => {\n\t\t\t\t\t\t\tconst totalSize = files.reduce((acc, cur) => acc + cur.sizeKb, 0);\n\t\t\t\t\t\t\treturn totalSize <= maxSize;\n\t\t\t\t\t\t},\n\t\t\t\t\t\tt('validation_file_size', { size: kbToReadableSize(maxSize) }),\n\t\t\t\t\t),\n\t\t\t\t],\n\t\t\t);\n\n\t\t\tconst parsed = v.safeParse(schema, submission);\n\t\t\tif (parsed.success === false) return Err(parsed.issues);\n\t\t\tsubmissions[node.data.key] = { type: 'file', value: parsed.output };\n\t\t\treturn Ok(submission);\n\t\t},\n\t});\n\n\treturn next(node.nextId);\n}\n","import * as v from 'valibot';\n\nimport { InterpretNodeParams, InterpretNodeReturn } from './interpreter';\nimport { Err, Ok } from './result';\n\nconst getValidationSchema = ({ node, config: { t } }: InterpretNodeParams<'question-number'>) => {\n\tconst min = node.data.min ?? Number.MIN_SAFE_INTEGER;\n\tconst max = node.data.max ?? Number.MAX_SAFE_INTEGER;\n\tconst decimalCases = node.data.decimalCases ?? 0;\n\n\treturn v.number(t('validation_number'), [\n\t\tv.minValue(min, t('validation_number_min', { min })),\n\t\tv.maxValue(max, t('validation_number_max', { max })),\n\t\tv.custom(\n\t\t\tvalue => {\n\t\t\t\treturn value === Number(value.toFixed(decimalCases));\n\t\t\t},\n\t\t\tt('validation_number_decimal_cases', { count: decimalCases }),\n\t\t),\n\t]);\n};\n\nexport async function* interpretQuestionNumberNode(\n\tparams: InterpretNodeParams<'question-number'>,\n): InterpretNodeReturn {\n\tconst {\n\t\tnode,\n\t\tconfig: { submissions, actions, next },\n\t} = params;\n\tyield actions.text({ author: 'bot', message: node.data.question });\n\n\tconst thisSubmission = submissions[node.data.key];\n\tyield actions.input('number', {\n\t\tconfig: {\n\t\t\tkey: node.data.key,\n\t\t\tplaceholder: node.data.placeholder,\n\t\t\toptional: node.data.optional,\n\t\t\tdecimalCases: node.data.decimalCases,\n\t\t\tmax: node.data.max,\n\t\t\tmin: node.data.min,\n\t\t\tdefaultValue: thisSubmission?.type === 'number' ? thisSubmission.value.toString() : undefined,\n\t\t},\n\t\tvalidate: submission => {\n\t\t\tif (node.data.optional && submission === null) return Ok(submission);\n\t\t\tconst schema = getValidationSchema(params);\n\t\t\tconst parsed = v.safeParse(schema, submission);\n\t\t\tif (parsed.success === false) return Err(parsed.issues);\n\t\t\tsubmissions[node.data.key] = { type: 'number', value: parsed.output };\n\t\t\treturn Ok(submission);\n\t\t},\n\t});\n\n\treturn next(node.nextId);\n}\n","import * as v from 'valibot';\n\nimport { InterpretNodeParams, InterpretNodeReturn } from './interpreter';\nimport { Err, Ok } from './result';\n\nconst getValidationSchema = ({ node, config: { t } }: InterpretNodeParams<'question-phone'>) => {\n\treturn v.object({\n\t\tcountryCode: v.string(t('validation_country_code'), [v.regex(/^\\+?[0-9 -]+$/, t('validation_country_code'))]),\n\t\tphoneNumber: v.transform(\n\t\t\tv.string(t('validation_phone'), [\n\t\t\t\tv.regex(/^\\+?[0-9 -]+$/, t('validation_phone')),\n\t\t\t\tv.minLength(node.data.minChars, t('validation_min_chars', { count: node.data.minChars })),\n\t\t\t\tv.maxLength(node.data.maxChars, t('validation_max_chars', { count: node.data.maxChars })),\n\t\t\t]),\n\t\t\tvalue => value.replace(/[^0-9]/g, ''),\n\t\t\t[],\n\t\t),\n\t});\n};\n\nexport async function* interpretQuestionPhoneNode(params: InterpretNodeParams<'question-phone'>): InterpretNodeReturn {\n\tconst {\n\t\tnode,\n\t\tconfig: { actions, next, submissions },\n\t} = params;\n\tyield actions.text({ author: 'bot', message: node.data.question });\n\n\tconst thisSubmission = submissions[node.data.key];\n\tyield actions.input('phone', {\n\t\tconfig: {\n\t\t\tkey: node.data.key,\n\t\t\tminChars: node.data.minChars,\n\t\t\tmaxChars: node.data.maxChars,\n\t\t\tdefaultValue:\n\t\t\t\tthisSubmission?.type === 'phone' ?\n\t\t\t\t\tthisSubmission.value\n\t\t\t\t:\t{\n\t\t\t\t\t\tcountryCode: node.data.defaultCountryCode,\n\t\t\t\t\t},\n\t\t\tplaceholder: node.data.placeholder,\n\t\t\tsubmissionFormat: 'phone',\n\t\t\toptional: node.data.optional,\n\t\t},\n\t\tvalidate: submission => {\n\t\t\tif (node.data.optional && submission === null) return Ok(submission);\n\t\t\tconst schema = getValidationSchema(params);\n\t\t\tconst parsed = v.safeParse(schema, submission);\n\t\t\tif (parsed.success === false) return Err(parsed.issues);\n\t\t\tsubmissions[node.data.key] = { type: 'address', value: parsed.output };\n\t\t\treturn Ok(submission);\n\t\t},\n\t});\n\n\treturn next(node.nextId);\n}\n","import * as v from 'valibot';\n\nimport { InterpretNodeParams, InterpretNodeReturn } from './interpreter';\nimport { Err, Ok } from './result';\n\nconst getValidationSchema = ({ node, config: { t, logger } }: InterpretNodeParams<'question-text'>) => {\n\tconst errors = {\n\t\temail: t('validation_email'),\n\t\turl: t('validation_url'),\n\t\tmaxLength: t('validation_max_chars', { count: node.data.maxChars ?? 999 }),\n\t\tminLength: t('validation_min_chars', { count: node.data.minChars ?? 1 }),\n\t};\n\n\tswitch (node.data.format) {\n\t\tcase 'email':\n\t\t\treturn v.string(errors.email, [\n\t\t\t\tv.email(errors.email),\n\t\t\t\tv.minLength(node.data.minChars ?? 1, errors.minLength),\n\t\t\t\tv.maxLength(node.data.maxChars ?? Infinity, errors.maxLength),\n\t\t\t]);\n\t\tcase 'text':\n\t\t\treturn v.string([\n\t\t\t\tv.minLength(node.data.minChars ?? 1, errors.minLength),\n\t\t\t\tv.maxLength(node.data.maxChars ?? Infinity, errors.maxLength),\n\t\t\t]);\n\t\tcase 'url':\n\t\t\treturn v.string([\n\t\t\t\tv.url(errors.url),\n\t\t\t\tv.minLength(node.data.minChars ?? 1, errors.minLength),\n\t\t\t\tv.maxLength(node.data.maxChars ?? Infinity, errors.maxLength),\n\t\t\t]);\n\t\tcase 'phone':\n\t\t\treturn v.string([\n\t\t\t\tv.minLength(node.data.minChars ?? 1, errors.minLength),\n\t\t\t\tv.maxLength(node.data.maxChars ?? Infinity, errors.maxLength),\n\t\t\t]);\n\t\tdefault:\n\t\t\tnode.data.format satisfies never;\n\t\t\tlogger.error(`Unsupported question-text format: ${node.data.format}`);\n\t\t\treturn null;\n\t}\n};\n\nexport async function* interpretQuestionTextNode(params: InterpretNodeParams<'question-text'>): InterpretNodeReturn {\n\tconst {\n\t\tnode,\n\t\tconfig: { submissions, actions, next },\n\t} = params;\n\tyield actions.text({ author: 'bot', message: node.data.question });\n\n\tconst thisSubmission = submissions[node.data.key];\n\tyield actions.input('text', {\n\t\tconfig: {\n\t\t\tkey: node.data.key,\n\t\t\tmaxChars: node.data.maxChars,\n\t\t\tminChars: node.data.minChars,\n\t\t\tplaceholder: node.data.placeholder,\n\t\t\tformat: node.data.format,\n\t\t\toptional: node.data.optional,\n\t\t\tdefaultValue: thisSubmission?.type === 'string' ? thisSubmission.value : undefined,\n\t\t},\n\t\tvalidate: submission => {\n\t\t\tif (node.data.optional && submission === null) return Ok(submission);\n\t\t\tconst schema = getValidationSchema(params);\n\t\t\tif (schema === null) return Ok(submission);\n\t\t\tconst parsed = v.safeParse(schema, submission);\n\t\t\tif (parsed.success === false) return Err(parsed.issues);\n\t\t\tsubmissions[node.data.key] = { type: 'string', value: parsed.output };\n\t\t\treturn Ok(submission);\n\t\t},\n\t});\n\n\treturn next(node.nextId);\n}\n","import { FlowNode } from '@inploi/core/flows';\nimport { AnalyticsService, ApiClient, Logger } from '@inploi/sdk';\nimport { Issues } from 'valibot';\n\nimport { isIfBlockConditionMet } from './conditions';\nimport { FlowSubmissions } from './flow.types';\nimport { TFunction } from './i18n';\nimport { FlowInput } from './inputs';\nimport { interpolateWithData } from './interpolation';\nimport { interpretIdentifyNode } from './interpreter.identify';\nimport { interpretIntegrationApplicationSubmitNode } from './interpreter.integration-application-submit';\nimport { interpretQuestionAddressNode } from './interpreter.question-address';\nimport { interpretQuestionBooleanNode } from './interpreter.question-boolean';\nimport { interpretQuestionEnumNode } from './interpreter.question-enum';\nimport { interpretQuestionFileNode } from './interpreter.question-file';\nimport { interpretQuestionNumberNode } from './interpreter.question-number';\nimport { interpretQuestionPhoneNode } from './interpreter.question-phone';\nimport { interpretQuestionTextNode } from './interpreter.question-text';\nimport { LinkedList, LinkedListItem } from './linked-list';\nimport { Result } from './result';\n\ntype MaybePromise<T> = T | Promise<T>;\ntype FlowInterpreterYield =\n\t| { type: 'submissions'; submissions: FlowSubmissions }\n\t| { type: 'state'; state: 'loading' | 'idle' }\n\t| { type: 'error'; message: string }\n\t| { type: 'info'; message: string }\n\t| { type: 'success'; message: string }\n\t| { type: 'text'; author: 'user' | 'bot'; message: string }\n\t| { type: 'image'; url: string; height: number; width: number }\n\t| { type: 'link'; href: string; message: string }\n\t| { type: 'end' }\n\t| {\n\t\t\ttype: 'input';\n\t\t\tinput: {\n\t\t\t\t[I in FlowInput['type']]: {\n\t\t\t\t\ttype: I;\n\t\t\t\t\tconfig: (FlowInput & { type: I })['config'];\n\t\t\t\t\tvalidate: (\n\t\t\t\t\t\tinput: NonNullable<(FlowInput & { type: I })['submission']>['value'] | null,\n\t\t\t\t\t) => MaybePromise<Result<NonNullable<(FlowInput & { type: I })['submission']>['value'] | null, Issues>>;\n\t\t\t\t};\n\t\t\t}[FlowInput['type']];\n\t };\n\nexport type FlowInterpreterParams = {\n\tapiClient: ApiClient;\n\tanalytics: {\n\t\tservice: AnalyticsService;\n\t\tcustomProperties?: Record<string, unknown>;\n\t};\n\tlogger: Logger;\n\tt: TFunction;\n};\n\nexport type FlowActions = {\n\terror: ({ message }: { message: string }) => FlowInterpreterYield;\n\tinfo: ({ message }: { message: string }) => FlowInterpreterYield;\n\tsuccess: ({ message }: { message: string }) => FlowInterpreterYield;\n\ttext: ({ message, author }: { message: string; author: 'bot' | 'user' }) => FlowInterpreterYield;\n\timage: ({ url, height, width }: { url: string; height: number; width: number }) => FlowInterpreterYield;\n\tlink: ({ href, message }: { href: string; message: string }) => FlowInterpreterYield;\n\tsubmissions: (submissions: FlowSubmissions) => FlowInterpreterYield;\n\tstate: (state: 'loading' | 'idle') => FlowInterpreterYield;\n\tinput: <T extends FlowInput['type'], Input extends FlowInput & { type: T }>(\n\t\ttype: T,\n\t\tparams: {\n\t\t\tconfig: Input['config'];\n\t\t\tvalidate: (\n\t\t\t\tinput: NonNullable<Input['submission']>['value'] | null,\n\t\t\t) => MaybePromise<Result<NonNullable<Input['submission']>['value'] | null, Issues>>;\n\t\t},\n\t) => FlowInterpreterYield;\n};\n\nexport const createFlowInterpreter = (params: FlowInterpreterParams) => {\n\tconst submissions: FlowSubmissions = {};\n\n\treturn {\n\t\tinterpret: async function* interpret({\n\t\t\tnodes,\n\t\t\tcontext,\n\t\t}: {\n\t\t\tnodes: LinkedList<FlowNode>;\n\t\t\tcontext: Record<string, unknown>;\n\t\t}): AsyncGenerator<FlowInterpreterYield> {\n\t\t\tconst actions: FlowActions = {\n\t\t\t\terror: ({ message }) => ({ type: 'error', message: interpolateWithData(message, { submissions, context }) }),\n\t\t\t\tinfo: ({ message }) => ({ type: 'info', message: interpolateWithData(message, { submissions, context }) }),\n\t\t\t\tsuccess: ({ message }) => ({\n\t\t\t\t\ttype: 'success',\n\t\t\t\t\tmessage: interpolateWithData(message, { submissions, context }),\n\t\t\t\t}),\n\t\t\t\ttext: ({ message, author }) => ({\n\t\t\t\t\ttype: 'text',\n\t\t\t\t\tauthor,\n\t\t\t\t\tmessage: interpolateWithData(message, { submissions, context }),\n\t\t\t\t}),\n\t\t\t\timage: ({ url, height, width }) => ({\n\t\t\t\t\ttype: 'image',\n\t\t\t\t\turl: interpolateWithData(url, { submissions, context }),\n\t\t\t\t\theight,\n\t\t\t\t\twidth,\n\t\t\t\t}),\n\t\t\t\tstate: state => ({ type: 'state', state }),\n\t\t\t\tlink: ({ href, message }) => ({\n\t\t\t\t\ttype: 'link',\n\t\t\t\t\thref: interpolateWithData(href, { submissions, context }),\n\t\t\t\t\tmessage: interpolateWithData(message, { submissions, context }),\n\t\t\t\t}),\n\t\t\t\tsubmissions: submissions => ({ type: 'submissions', submissions }),\n\t\t\t\tinput: (type, params) => {\n\t\t\t\t\treturn { type: 'input', input: { type, config: params.config, validate: params.validate } as any };\n\t\t\t\t},\n\t\t\t};\n\t\t\tif (!nodes.headId) return { type: 'error', message: 'No head node found' };\n\t\t\tlet node: LinkedListItem<FlowNode> | undefined = nodes.items[nodes.headId];\n\t\t\tconst next = (nextId: string | undefined): { type: 'next'; nodeId: string | undefined } => {\n\t\t\t\tif (!nextId) {\n\t\t\t\t\tnode = undefined;\n\t\t\t\t\treturn { type: 'next', nodeId: undefined };\n\t\t\t\t}\n\t\t\t\tconst nextNode = nodes.items[nextId];\n\t\t\t\tif (!nextNode) throw new Error(`Next node with id ${nextId} not found`);\n\t\t\t\tnode = nextNode;\n\t\t\t\treturn { type: 'next', nodeId: nextId };\n\t\t\t};\n\t\t\tconst config = { ...params, context, submissions, next, actions };\n\n\t\t\twhile (node) {\n\t\t\t\tswitch (node.type) {\n\t\t\t\t\tcase 'text':\n\t\t\t\t\t\tyield actions.text({ author: 'bot', message: node.data.text });\n\t\t\t\t\t\tnext(node.nextId);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'image':\n\t\t\t\t\t\tyield actions.image(node.data);\n\t\t\t\t\t\tnext(node.nextId);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'link':\n\t\t\t\t\t\tyield actions.link({ href: node.data.href, message: node.data.cta });\n\t\t\t\t\t\tnext(node.nextId);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'add-submission':\n\t\t\t\t\t\tsubmissions[node.data.key] = { type: 'string', value: node.data.value };\n\t\t\t\t\t\tnext(node.nextId);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'jump':\n\t\t\t\t\t\tnext(node.data.targetId);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'question-text':\n\t\t\t\t\t\tyield* interpretQuestionTextNode({ config, node });\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'question-phone':\n\t\t\t\t\t\tyield* interpretQuestionPhoneNode({ config, node });\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'question-boolean':\n\t\t\t\t\t\tyield* interpretQuestionBooleanNode({ config, node });\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'question-number':\n\t\t\t\t\t\tyield* interpretQuestionNumberNode({ config, node });\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'question-address':\n\t\t\t\t\t\tyield* interpretQuestionAddressNode({ config, node });\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'question-enum':\n\t\t\t\t\t\tyield* interpretQuestionEnumNode({ config, node });\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'question-file':\n\t\t\t\t\t\tyield* interpretQuestionFileNode({ config, node });\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'identify': {\n\t\t\t\t\t\tyield* interpretIdentifyNode({ config, node });\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase 'if-block': {\n\t\t\t\t\t\tconst nextNodeId =\n\t\t\t\t\t\t\tisIfBlockConditionMet(node, { context: config.context, submissions }) ? node.branchId : node.nextId;\n\t\t\t\t\t\tnext(nextNodeId);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase 'integration-application-submit':\n\t\t\t\t\t\tyield* interpretIntegrationApplicationSubmitNode({ config, node });\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'feedback':\n\t\t\t\t\t\tyield actions.error({ message: 'Not implemented' });\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'integration-workflow-get':\n\t\t\t\t\t\tyield actions.error({ message: 'This message should never be reached' });\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'end-flow':\n\t\t\t\t\t\tnode = undefined;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tyield actions.submissions(submissions);\n\t\t\t}\n\t\t\tyield { type: 'end' };\n\t\t},\n\t};\n};\n\nexport type InterpretNodeParams<TNodeType extends FlowNode['type']> = {\n\tnode: FlowNode & { type: TNodeType };\n\tconfig: FlowInterpreterParams & {\n\t\tsubmissions: FlowSubmissions;\n\t\tcontext: Record<string, unknown>;\n\t\tnext: (nextId: string | undefined) => { type: 'next'; nodeId: string | undefined };\n\t\tactions: FlowActions;\n\t};\n};\n\nexport type InterpretNodeReturn = AsyncGenerator<FlowInterpreterYield, { type: 'next'; nodeId: string | undefined }>;\n"],"mappings":"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","names":["import_get","isConditionMet","condition","context","submissions","ifBlock","firstSegment","path","answer","getSubmissionValueToCheck","value","get","newIfBlock","__spreadProps","__spreadValues","isIfBlockConditionMet","compareBoolean","compareNumber","e","conditions","import_get","HANDLEBARS_REGEXP","interpolateWithData","str","context","submissions","_","key","defaultValue","firstSegment","path","entity","getSubmissionValueToCheck","file","kbToReadableSize","line","formatPhoneNumber","value","get","i","interpretIdentifyNode","params","__asyncGenerator","node","logger","analytics","submissions","next","getSubmissionValue","key","value","_a","responseSchema","object","boolean","optional","string","number","unknown","nullable","interpretIntegrationApplicationSubmitNode","params","__asyncGenerator","_a","node","apiClient","submissions","actions","next","analytics","logger","context","__async","sessionInfo","tryCatch","response","getFlowSubmissionsPayload","parsed","safeParse","Err","Ok","e","issues","fieldValueSchema","nullable","optional","string","getValidationSchema","node","_a","_b","_c","_d","_e","_f","_g","keys","object","interpretQuestionAddressNode","params","__asyncGenerator","submissions","actions","next","submission","Ok","schema","parsed","safeParse","Err","options","schema","picklist","interpretQuestionBooleanNode","params","__asyncGenerator","node","submissions","actions","next","submission","Ok","parsed","safeParse","Err","interpretQuestionEnumNode","params","__asyncGenerator","node","submissions","actions","next","schema","array","picklist","o","submission","Ok","parsed","safeParse","Err","interpretQuestionFileNode","params","__asyncGenerator","node","submissions","actions","next","t","submission","_a","Ok","minFiles","maxFiles","maxSize","allowedExtensions","ext","schema","array","object","string","custom","filename","extension","getFileExtension","number","minLength","maxLength","files","acc","cur","kbToReadableSize","parsed","safeParse","Err","getValidationSchema","node","t","_a","_b","_c","min","max","decimalCases","number","minValue","maxValue","custom","value","interpretQuestionNumberNode","params","__asyncGenerator","submissions","actions","next","thisSubmission","submission","Ok","schema","parsed","safeParse","Err","getValidationSchema","node","t","object","string","regex","transform","minLength","maxLength","value","interpretQuestionPhoneNode","params","__asyncGenerator","actions","next","submissions","thisSubmission","submission","Ok","schema","parsed","safeParse","Err","getValidationSchema","node","t","logger","_a","_b","_c","_d","_e","_f","_g","_h","_i","_j","errors","string","email","minLength","maxLength","url","interpretQuestionTextNode","params","__asyncGenerator","submissions","actions","next","thisSubmission","submission","Ok","schema","parsed","safeParse","Err","createFlowInterpreter","params","submissions","_0","__asyncGenerator","nodes","context","actions","message","interpolateWithData","author","url","height","width","state","href","type","node","next","nextId","nextNode","config","__spreadProps","__spreadValues","__yieldStar","interpretQuestionTextNode","interpretQuestionPhoneNode","interpretQuestionBooleanNode","interpretQuestionNumberNode","interpretQuestionAddressNode","interpretQuestionEnumNode","interpretQuestionFileNode","interpretIdentifyNode","nextNodeId","isIfBlockConditionMet","interpretIntegrationApplicationSubmitNode"]}
@@ -0,0 +1,28 @@
1
+ type LinkedListItem<T> = T & {
2
+ id: string;
3
+ nextId?: string;
4
+ prevId?: string;
5
+ };
6
+ type LinkedList<T> = {
7
+ headId: string | null;
8
+ items: Record<string, LinkedListItem<T>>;
9
+ };
10
+ declare const LinkedList: {
11
+ create: <T>() => LinkedList<T>;
12
+ addItem: <L extends LinkedList<any>>(list: L, payload: Omit<L['items'][keyof L['items']], 'id'>, options?: {
13
+ afterId?: string;
14
+ }) => L;
15
+ removeItem: <L_1 extends LinkedList<any>>(list: L_1, id: string) => L_1;
16
+ moveItem: <L_2 extends LinkedList<any>>(list: L_2, id: string, options: {
17
+ beforeId?: never;
18
+ afterId: string;
19
+ } | {
20
+ beforeId: string;
21
+ afterId?: never;
22
+ }) => L_2;
23
+ asArray: <T_1>(list: LinkedList<T_1>) => LinkedListItem<T_1>[];
24
+ getInvalidItemKeys: <T_2>(list: LinkedList<T_2>) => string[];
25
+ isLinkedList: (list: unknown) => list is LinkedList<unknown>;
26
+ };
27
+
28
+ export { LinkedList, LinkedListItem };
@@ -0,0 +1,2 @@
1
+ import{D as o,a as i,b as f}from"./chunk-3QWHH45C.mjs";var h={create:()=>({headId:null,items:{}}),addItem:(e,r,d={})=>{var I;let t=i({id:o()},r);if(!e.headId)return f(i({},e),{headId:t.id,items:{[t.id]:t}});if(d.afterId){let m=e.items[d.afterId];if(!m)throw new Error(`Item with afterId ${d.afterId} not found`);let a=i({},e.items);return t.prevId=d.afterId,t.nextId=m.nextId,a[d.afterId]=f(i({},m),{nextId:t.id}),m.nextId&&(a[m.nextId]=f(i({},a[m.nextId]),{prevId:t.id})),a[t.id]=t,f(i({},e),{items:a})}let s=e.headId;for(;s;){let m=(I=e.items[s])==null?void 0:I.nextId;if(!m)break;s=m}let n=f(i({},e.items[s]),{nextId:t.id});return t.prevId=s,f(i({},e),{items:f(i({},e.items),{[s]:n,[t.id]:t})})},removeItem:(e,r)=>{var s;let d=e.items[r];if(!d)throw new Error(`Item with id ${r} not found`);let t=i({},e.items);return delete t[r],d.prevId&&d.nextId?(t[d.prevId]=f(i({},t[d.prevId]),{nextId:d.nextId}),t[d.nextId]=f(i({},t[d.nextId]),{prevId:d.prevId})):d.prevId?t[d.prevId]=f(i({},t[d.prevId]),{nextId:void 0}):d.nextId&&(t[d.nextId]=f(i({},t[d.nextId]),{prevId:void 0})),f(i({},e),{headId:r===e.headId?(s=d.nextId)!=null?s:null:e.headId,items:t})},moveItem:(e,r,d)=>{let t=e.items[r];if(!t)throw new Error(`Item with id ${r} not found`);let s=h.removeItem(e,r);if(d.beforeId){let n=e.items[d.beforeId];if(!n)throw new Error(`Target item with id ${d.beforeId} not found`);let I=s.items;return I[r]=f(i({},t),{nextId:d.beforeId,prevId:n.prevId}),I[d.beforeId]=f(i({},n),{prevId:r,nextId:n.nextId===r?t.nextId:n.nextId}),n.prevId&&(I[n.prevId]=f(i({},I[n.prevId]),{nextId:r})),f(i({},e),{headId:n.prevId?s.headId:r,items:I})}else if(d.afterId){let n=e.items[d.afterId];if(!n)throw new Error(`Target item with id ${d.afterId} not found`);let I=i({},s.items);return I[r]=f(i({},t),{prevId:d.afterId,nextId:n.nextId}),I[d.afterId]=f(i({},n),{prevId:n.prevId===r?t.prevId:n.prevId,nextId:r}),n.nextId&&(I[n.nextId]=f(i({},I[n.nextId]),{prevId:r})),f(i({},e),{headId:s.headId,items:I})}throw new Error("Invalid options")},asArray:e=>{let r=[];if(!("headId"in e)||e.headId===null)return r;let d=new Set,t=e.headId;for(;t;){if(d.has(t))throw new Error(`Circular reference detected: item ${t} was encountered twice`);let s=e.items[t];if(!s)throw new Error(`Invalid list structure: item with id ${t} not found`);d.add(t),r.push(s),t=s.nextId}return r},getInvalidItemKeys:e=>{var s;let r=[],d=new Set,t=new Set;for(let[n,I]of Object.entries(e.items)){if(I.id!==n&&r.push(n),I.nextId&&!e.items[I.nextId]&&r.push(n),I.prevId&&!e.items[I.prevId]&&r.push(n),I.nextId){let m=e.items[I.nextId];m&&m.prevId!==I.id&&r.push(n)}if(I.prevId){let m=e.items[I.prevId];m&&m.nextId!==I.id&&r.push(n)}}if(e.headId)if(!e.items[e.headId])r.push(e.headId);else{let n=e.headId;for(;n;){if(t.has(n)){for(let I of t)r.push(I);break}t.add(n),d.add(n),n=(s=e.items[n])==null?void 0:s.nextId}}for(let n of Object.keys(e.items))d.has(n)||r.push(n);return[...new Set(r)]},isLinkedList:e=>e!==null&&typeof e=="object"&&"headId"in e&&"items"in e};export{h as LinkedList};
2
+ //# sourceMappingURL=linked-list.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/linked-list.ts"],"sourcesContent":["import { genId } from './utils';\n\nexport type LinkedListItem<T> = T & { id: string; nextId?: string; prevId?: string };\nexport type LinkedList<T> = { headId: string | null; items: Record<string, LinkedListItem<T>> };\n\nexport const LinkedList = {\n\tcreate: <T>(): LinkedList<T> => {\n\t\treturn { headId: null, items: {} };\n\t},\n\n\taddItem: <L extends LinkedList<any>>(\n\t\tlist: L,\n\t\tpayload: Omit<L['items'][keyof L['items']], 'id'>,\n\t\toptions: { afterId?: string } = {},\n\t): L => {\n\t\tconst newItem = {\n\t\t\tid: genId(),\n\t\t\t...payload,\n\t\t} as L['items'][keyof L['items']];\n\n\t\t// If list is empty, create first item\n\t\tif (!list.headId) {\n\t\t\treturn {\n\t\t\t\t...list,\n\t\t\t\theadId: newItem.id,\n\t\t\t\titems: { [newItem.id]: newItem },\n\t\t\t};\n\t\t}\n\n\t\t// If afterId is specified, insert after that item\n\t\tif (options.afterId) {\n\t\t\tconst afterItem = list.items[options.afterId];\n\t\t\tif (!afterItem) {\n\t\t\t\tthrow new Error(`Item with afterId ${options.afterId} not found`);\n\t\t\t}\n\t\t\tconst newItems = { ...list.items };\n\n\t\t\t// Update the new item's links\n\t\t\tnewItem.prevId = options.afterId;\n\t\t\tnewItem.nextId = afterItem.nextId;\n\n\t\t\t// Update the item we're inserting after\n\t\t\tnewItems[options.afterId] = {\n\t\t\t\t...afterItem,\n\t\t\t\tnextId: newItem.id,\n\t\t\t};\n\n\t\t\t// If there was a next item, update its prevId\n\t\t\tif (afterItem.nextId) {\n\t\t\t\tnewItems[afterItem.nextId] = {\n\t\t\t\t\t...newItems[afterItem.nextId],\n\t\t\t\t\tprevId: newItem.id,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Add the new item\n\t\t\tnewItems[newItem.id] = newItem;\n\n\t\t\treturn {\n\t\t\t\t...list,\n\t\t\t\titems: newItems,\n\t\t\t};\n\t\t}\n\n\t\t// If no afterId specified, add to end of list\n\t\tlet currentId: string = list.headId;\n\t\twhile (currentId) {\n\t\t\tconst newId = list.items[currentId]?.nextId;\n\t\t\tif (!newId) break;\n\t\t\tcurrentId = newId;\n\t\t}\n\n\t\t// Update the last item's nextId\n\t\tconst updatedLastItem = {\n\t\t\t...list.items[currentId],\n\t\t\tnextId: newItem.id,\n\t\t};\n\n\t\t// Add the new item with prevId pointing to the last item\n\t\tnewItem.prevId = currentId;\n\n\t\treturn {\n\t\t\t...list,\n\t\t\titems: {\n\t\t\t\t...list.items,\n\t\t\t\t[currentId]: updatedLastItem,\n\t\t\t\t[newItem.id]: newItem,\n\t\t\t},\n\t\t};\n\t},\n\n\tremoveItem: <L extends LinkedList<any>>(list: L, id: string): L => {\n\t\tconst item = list.items[id];\n\t\tif (!item) throw new Error(`Item with id ${id} not found`);\n\n\t\tconst newItems = { ...list.items };\n\t\tdelete newItems[id];\n\n\t\t// Update surrounding items\n\t\tif (item.prevId && item.nextId) {\n\t\t\t// Middle item\n\t\t\tnewItems[item.prevId] = {\n\t\t\t\t...newItems[item.prevId],\n\t\t\t\tnextId: item.nextId,\n\t\t\t};\n\n\t\t\tnewItems[item.nextId] = {\n\t\t\t\t...newItems[item.nextId],\n\t\t\t\tprevId: item.prevId,\n\t\t\t};\n\t\t} else if (item.prevId) {\n\t\t\t// Last item\n\t\t\tnewItems[item.prevId] = {\n\t\t\t\t...newItems[item.prevId],\n\t\t\t\tnextId: undefined,\n\t\t\t};\n\t\t} else if (item.nextId) {\n\t\t\t// First item\n\t\t\tnewItems[item.nextId] = {\n\t\t\t\t...newItems[item.nextId],\n\t\t\t\tprevId: undefined,\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\t...list,\n\t\t\theadId: id === list.headId ? item.nextId ?? null : list.headId,\n\t\t\titems: newItems,\n\t\t};\n\t},\n\n\tmoveItem: <L extends LinkedList<any>>(\n\t\tlist: L,\n\t\tid: string,\n\t\toptions: { beforeId?: never; afterId: string } | { beforeId: string; afterId?: never },\n\t): L => {\n\t\tconst itemToMove = list.items[id];\n\t\tif (!itemToMove) throw new Error(`Item with id ${id} not found`);\n\n\t\t// First remove the item from its current position\n\t\tconst listWithoutItem = LinkedList.removeItem(list, id);\n\n\t\tif (options.beforeId) {\n\t\t\tconst targetItem = list.items[options.beforeId];\n\t\t\tif (!targetItem) throw new Error(`Target item with id ${options.beforeId} not found`);\n\t\t\tconst newItems = listWithoutItem.items;\n\n\t\t\t// Update the moved item\n\t\t\tnewItems[id] = {\n\t\t\t\t...itemToMove,\n\t\t\t\tnextId: options.beforeId,\n\t\t\t\tprevId: targetItem.prevId,\n\t\t\t};\n\n\t\t\t// Update the target item\n\t\t\tnewItems[options.beforeId] = {\n\t\t\t\t...targetItem,\n\t\t\t\tprevId: id,\n\t\t\t\tnextId: targetItem.nextId === id ? itemToMove.nextId : targetItem.nextId,\n\t\t\t};\n\n\t\t\t// Update the previous item if it exists\n\t\t\tif (targetItem.prevId) {\n\t\t\t\tnewItems[targetItem.prevId] = {\n\t\t\t\t\t...newItems[targetItem.prevId],\n\t\t\t\t\tnextId: id,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\t...list,\n\t\t\t\theadId: targetItem.prevId ? listWithoutItem.headId : id,\n\t\t\t\titems: newItems,\n\t\t\t};\n\t\t} else if (options.afterId) {\n\t\t\tconst targetItem = list.items[options.afterId];\n\t\t\tif (!targetItem) throw new Error(`Target item with id ${options.afterId} not found`);\n\t\t\tconst newItems = { ...listWithoutItem.items };\n\n\t\t\t// Update the moved item\n\t\t\tnewItems[id] = {\n\t\t\t\t...itemToMove,\n\t\t\t\tprevId: options.afterId,\n\t\t\t\tnextId: targetItem.nextId,\n\t\t\t};\n\n\t\t\t// Update the target item\n\t\t\tnewItems[options.afterId!] = {\n\t\t\t\t...targetItem,\n\t\t\t\tprevId: targetItem.prevId === id ? itemToMove.prevId : targetItem.prevId,\n\t\t\t\tnextId: id,\n\t\t\t};\n\n\t\t\t// Update the next item if it exists\n\t\t\tif (targetItem.nextId) {\n\t\t\t\tnewItems[targetItem.nextId] = {\n\t\t\t\t\t...newItems[targetItem.nextId],\n\t\t\t\t\tprevId: id,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\t...list,\n\t\t\t\theadId: listWithoutItem.headId,\n\t\t\t\titems: newItems,\n\t\t\t};\n\t\t}\n\n\t\tthrow new Error('Invalid options');\n\t},\n\n\tasArray: <T>(list: LinkedList<T>): LinkedListItem<T>[] => {\n\t\tconst result: LinkedListItem<T>[] = [];\n\t\tif ('headId' in list === false || list.headId === null) return result;\n\n\t\tconst visited = new Set<string>();\n\t\tlet currentId: string | undefined = list.headId;\n\n\t\twhile (currentId) {\n\t\t\tif (visited.has(currentId))\n\t\t\t\tthrow new Error(`Circular reference detected: item ${currentId} was encountered twice`);\n\n\t\t\tconst currentItem: LinkedListItem<T> | undefined = list.items[currentId];\n\t\t\tif (!currentItem) {\n\t\t\t\tthrow new Error(`Invalid list structure: item with id ${currentId} not found`);\n\t\t\t}\n\t\t\tvisited.add(currentId);\n\t\t\tresult.push(currentItem);\n\t\t\tcurrentId = currentItem.nextId;\n\t\t}\n\n\t\treturn result;\n\t},\n\n\tgetInvalidItemKeys: <T>(list: LinkedList<T>): string[] => {\n\t\tconst invalidKeys: string[] = [];\n\t\tconst reachableIds = new Set<string>();\n\t\tconst visited = new Set<string>();\n\n\t\t// First pass: check for id mismatches and collect all ids\n\t\tfor (const [key, item] of Object.entries(list.items)) {\n\t\t\t// Check if item's id matches its key in the record\n\t\t\tif (item.id !== key) {\n\t\t\t\tinvalidKeys.push(key);\n\t\t\t}\n\n\t\t\t// Check for invalid nextId references\n\t\t\tif (item.nextId && !list.items[item.nextId]) {\n\t\t\t\tinvalidKeys.push(key);\n\t\t\t}\n\n\t\t\t// Check for invalid prevId references\n\t\t\tif (item.prevId && !list.items[item.prevId]) {\n\t\t\t\tinvalidKeys.push(key);\n\t\t\t}\n\n\t\t\t// Check for broken bidirectional links\n\t\t\tif (item.nextId) {\n\t\t\t\tconst nextItem = list.items[item.nextId];\n\t\t\t\tif (nextItem && nextItem.prevId !== item.id) {\n\t\t\t\t\tinvalidKeys.push(key);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (item.prevId) {\n\t\t\t\tconst prevItem = list.items[item.prevId];\n\t\t\t\tif (prevItem && prevItem.nextId !== item.id) {\n\t\t\t\t\tinvalidKeys.push(key);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Check if headId is valid\n\t\tif (list.headId) {\n\t\t\tif (!list.items[list.headId]) {\n\t\t\t\tinvalidKeys.push(list.headId);\n\t\t\t} else {\n\t\t\t\t// Second pass: traverse the list from head to find reachable nodes\n\t\t\t\tlet currentId: string | undefined = list.headId;\n\t\t\t\twhile (currentId) {\n\t\t\t\t\tif (visited.has(currentId)) {\n\t\t\t\t\t\t// We found a cycle - mark all items in the cycle as invalid\n\t\t\t\t\t\tfor (const visitedId of visited) {\n\t\t\t\t\t\t\tinvalidKeys.push(visitedId);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tvisited.add(currentId);\n\t\t\t\t\treachableIds.add(currentId);\n\t\t\t\t\tcurrentId = list.items[currentId]?.nextId;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Third pass: find items that aren't reachable from the head\n\t\tfor (const key of Object.keys(list.items)) {\n\t\t\tif (!reachableIds.has(key)) {\n\t\t\t\tinvalidKeys.push(key);\n\t\t\t}\n\t\t}\n\n\t\t// Remove duplicates and return\n\t\treturn [...new Set(invalidKeys)];\n\t},\n\n\tisLinkedList: (list: unknown): list is LinkedList<unknown> => {\n\t\treturn list !== null && typeof list === 'object' && 'headId' in list && 'items' in list;\n\t},\n};\n"],"mappings":"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","names":["LinkedList","list","payload","options","_a","newItem","__spreadValues","genId","__spreadProps","afterItem","newItems","currentId","newId","updatedLastItem","id","item","itemToMove","listWithoutItem","targetItem","result","visited","currentItem","invalidKeys","reachableIds","key","nextItem","prevItem","visitedId"]}