@getrheo/flow-runtime 1.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.
- package/dist/agentPrompt/index.d.ts +72 -0
- package/dist/agentPrompt/index.js +739 -0
- package/dist/agentPrompt/index.js.map +1 -0
- package/dist/aiFlowGenerationMerge.d.ts +32 -0
- package/dist/aiFlowGenerationMerge.js +120 -0
- package/dist/aiFlowGenerationMerge.js.map +1 -0
- package/dist/animations.d.ts +110 -0
- package/dist/animations.js +312 -0
- package/dist/animations.js.map +1 -0
- package/dist/assignment.d.ts +7 -0
- package/dist/assignment.js +25 -0
- package/dist/assignment.js.map +1 -0
- package/dist/brandGradient.d.ts +57 -0
- package/dist/brandGradient.js +137 -0
- package/dist/brandGradient.js.map +1 -0
- package/dist/brandGradientManifestIssues.d.ts +11 -0
- package/dist/brandGradientManifestIssues.js +302 -0
- package/dist/brandGradientManifestIssues.js.map +1 -0
- package/dist/buildFlowPreview.d.ts +7 -0
- package/dist/buildFlowPreview.js +81 -0
- package/dist/buildFlowPreview.js.map +1 -0
- package/dist/buttonVariantChrome.d.ts +26 -0
- package/dist/buttonVariantChrome.js +59 -0
- package/dist/buttonVariantChrome.js.map +1 -0
- package/dist/checkboxGlyphStyle.d.ts +31 -0
- package/dist/checkboxGlyphStyle.js +241 -0
- package/dist/checkboxGlyphStyle.js.map +1 -0
- package/dist/choiceOptionSelection.d.ts +11 -0
- package/dist/choiceOptionSelection.js +120 -0
- package/dist/choiceOptionSelection.js.map +1 -0
- package/dist/colorAlpha.d.ts +8 -0
- package/dist/colorAlpha.js +48 -0
- package/dist/colorAlpha.js.map +1 -0
- package/dist/counterLayer.d.ts +42 -0
- package/dist/counterLayer.js +95 -0
- package/dist/counterLayer.js.map +1 -0
- package/dist/decisionEval.d.ts +27 -0
- package/dist/decisionEval.js +197 -0
- package/dist/decisionEval.js.map +1 -0
- package/dist/dropShadow.d.ts +26 -0
- package/dist/dropShadow.js +76 -0
- package/dist/dropShadow.js.map +1 -0
- package/dist/emailPasswordAuthValidation.d.ts +16 -0
- package/dist/emailPasswordAuthValidation.js +25 -0
- package/dist/emailPasswordAuthValidation.js.map +1 -0
- package/dist/flowBuilderRules.d.ts +15 -0
- package/dist/flowBuilderRules.js +368 -0
- package/dist/flowBuilderRules.js.map +1 -0
- package/dist/flowGraph.d.ts +19 -0
- package/dist/flowGraph.js +373 -0
- package/dist/flowGraph.js.map +1 -0
- package/dist/hyperlinkLabel.d.ts +19 -0
- package/dist/hyperlinkLabel.js +232 -0
- package/dist/hyperlinkLabel.js.map +1 -0
- package/dist/index.d.ts +48 -0
- package/dist/index.js +4200 -0
- package/dist/index.js.map +1 -0
- package/dist/interpolateTemplate.d.ts +44 -0
- package/dist/interpolateTemplate.js +188 -0
- package/dist/interpolateTemplate.js.map +1 -0
- package/dist/layerRotate.d.ts +10 -0
- package/dist/layerRotate.js +9 -0
- package/dist/layerRotate.js.map +1 -0
- package/dist/layerTypography.d.ts +36 -0
- package/dist/layerTypography.js +68 -0
- package/dist/layerTypography.js.map +1 -0
- package/dist/layers.d.ts +69 -0
- package/dist/layers.js +257 -0
- package/dist/layers.js.map +1 -0
- package/dist/layout/index.d.ts +57 -0
- package/dist/layout/index.js +151 -0
- package/dist/layout/index.js.map +1 -0
- package/dist/manifestBillingSlice.d.ts +17 -0
- package/dist/manifestBillingSlice.js +102 -0
- package/dist/manifestBillingSlice.js.map +1 -0
- package/dist/prepareAiGeneratedScreen.d.ts +17 -0
- package/dist/prepareAiGeneratedScreen.js +99 -0
- package/dist/prepareAiGeneratedScreen.js.map +1 -0
- package/dist/publish-exports.json +166 -0
- package/dist/responsive/breakpoints.d.ts +34 -0
- package/dist/responsive/breakpoints.js +52 -0
- package/dist/responsive/breakpoints.js.map +1 -0
- package/dist/responsive/index.d.ts +8 -0
- package/dist/responsive/index.js +307 -0
- package/dist/responsive/index.js.map +1 -0
- package/dist/responsive/layerResolve.d.ts +43 -0
- package/dist/responsive/layerResolve.js +168 -0
- package/dist/responsive/layerResolve.js.map +1 -0
- package/dist/responsive/merge.d.ts +19 -0
- package/dist/responsive/merge.js +74 -0
- package/dist/responsive/merge.js.map +1 -0
- package/dist/responsive/previewSafeAreaInsets.d.ts +14 -0
- package/dist/responsive/previewSafeAreaInsets.js +24 -0
- package/dist/responsive/previewSafeAreaInsets.js.map +1 -0
- package/dist/responsive/screenContainerResolve.d.ts +11 -0
- package/dist/responsive/screenContainerResolve.js +122 -0
- package/dist/responsive/screenContainerResolve.js.map +1 -0
- package/dist/responsive/screenShellInsets.d.ts +11 -0
- package/dist/responsive/screenShellInsets.js +26 -0
- package/dist/responsive/screenShellInsets.js.map +1 -0
- package/dist/restingMotion.d.ts +167 -0
- package/dist/restingMotion.js +484 -0
- package/dist/restingMotion.js.map +1 -0
- package/dist/rheoAgentManifestMerge.d.ts +33 -0
- package/dist/rheoAgentManifestMerge.js +55 -0
- package/dist/rheoAgentManifestMerge.js.map +1 -0
- package/dist/scaleInputStyle.d.ts +35 -0
- package/dist/scaleInputStyle.js +77 -0
- package/dist/scaleInputStyle.js.map +1 -0
- package/dist/scaleValidation.d.ts +9 -0
- package/dist/scaleValidation.js +21 -0
- package/dist/scaleValidation.js.map +1 -0
- package/dist/stateMachine.d.ts +105 -0
- package/dist/stateMachine.js +674 -0
- package/dist/stateMachine.js.map +1 -0
- package/dist/stepResponse-BXgoZ7o-.d.ts +112 -0
- package/dist/textInputValidation.d.ts +14 -0
- package/dist/textInputValidation.js +46 -0
- package/dist/textInputValidation.js.map +1 -0
- package/dist/translationPlaceholders.d.ts +9 -0
- package/dist/translationPlaceholders.js +52 -0
- package/dist/translationPlaceholders.js.map +1 -0
- package/dist/validation.d.ts +31 -0
- package/dist/validation.js +233 -0
- package/dist/validation.js.map +1 -0
- package/package.json +242 -0
|
@@ -0,0 +1,674 @@
|
|
|
1
|
+
import { permissionCaptureFieldKey, appReviewCaptureFieldKey, oauthLoginResponseKey, emailPasswordAuthResponseKey, OS_PERMISSION_OUTCOME_END, OS_PERMISSION_OUTCOME_CONTINUE, isInputLayer } from '@getrheo/contracts/layers';
|
|
2
|
+
import '@getrheo/contracts/localized';
|
|
3
|
+
import { EXTERNAL_SURFACE_NO_NEXT } from '@getrheo/contracts/decisions';
|
|
4
|
+
|
|
5
|
+
// src/stateMachine/stepResponse.ts
|
|
6
|
+
var externalSurfaceResponseKey = (nodeId) => `surface_${nodeId}`;
|
|
7
|
+
var isEligibleConsumedDraft = (r) => {
|
|
8
|
+
switch (r.kind) {
|
|
9
|
+
case "text":
|
|
10
|
+
case "choice":
|
|
11
|
+
case "multiChoice":
|
|
12
|
+
case "scale":
|
|
13
|
+
case "cta":
|
|
14
|
+
case "carousel":
|
|
15
|
+
return true;
|
|
16
|
+
default:
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// src/stateMachine/flowSession.ts
|
|
22
|
+
var findScreen = (manifest, screenId) => manifest.screens.find((s) => s.id === screenId);
|
|
23
|
+
var findExternalSurface = (manifest, nodeId) => (
|
|
24
|
+
// Older / hand-constructed manifests may omit `externalSurfaceNodes` entirely;
|
|
25
|
+
// treat that as "no surfaces" rather than crashing the state machine.
|
|
26
|
+
(manifest.externalSurfaceNodes ?? []).find((n) => n.id === nodeId)
|
|
27
|
+
);
|
|
28
|
+
var initFlowState = (manifest, sessionPartial) => ({
|
|
29
|
+
manifest,
|
|
30
|
+
currentScreenId: null,
|
|
31
|
+
pendingExternalSurface: null,
|
|
32
|
+
history: [],
|
|
33
|
+
responses: {},
|
|
34
|
+
session: {
|
|
35
|
+
locale: sessionPartial?.locale ?? manifest.defaultLocale,
|
|
36
|
+
platform: sessionPartial?.platform ?? "unknown",
|
|
37
|
+
sdkAttributes: sessionPartial?.sdkAttributes ?? {}
|
|
38
|
+
},
|
|
39
|
+
status: "idle",
|
|
40
|
+
startedAt: null,
|
|
41
|
+
completedAt: null
|
|
42
|
+
});
|
|
43
|
+
var walkLayers = (root, fn) => {
|
|
44
|
+
const visit = (l, depth) => {
|
|
45
|
+
fn(l, depth);
|
|
46
|
+
if (l.kind === "stack") l.children.forEach((c) => visit(c, depth + 1));
|
|
47
|
+
else if (l.kind === "carousel") l.slides.forEach((c) => visit(c, depth + 1));
|
|
48
|
+
else if (l.kind === "button") l.children.forEach((c) => visit(c, depth + 1));
|
|
49
|
+
else if (l.kind === "back_button") l.children.forEach((c) => visit(c, depth + 1));
|
|
50
|
+
else if (l.kind === "hyperlink") l.children.forEach((c) => visit(c, depth + 1));
|
|
51
|
+
else if (l.kind === "single_choice" || l.kind === "multiple_choice") {
|
|
52
|
+
l.children.forEach((c) => visit(c, depth + 1));
|
|
53
|
+
} else if (l.kind === "text_input" || l.kind === "scale_input") {
|
|
54
|
+
l.children?.forEach((c) => visit(c, depth + 1));
|
|
55
|
+
} else if (l.kind === "oauth_login") {
|
|
56
|
+
l.children.forEach((c) => visit(c, depth + 1));
|
|
57
|
+
} else if (l.kind === "oauth_provider" && l.variant === "custom") {
|
|
58
|
+
l.children.forEach((c) => visit(c, depth + 1));
|
|
59
|
+
} else if (l.kind === "email_password_auth") {
|
|
60
|
+
l.children.forEach((c) => visit(c, depth + 1));
|
|
61
|
+
} else if (l.kind === "email_password_field") {
|
|
62
|
+
l.children?.forEach((c) => visit(c, depth + 1));
|
|
63
|
+
} else if (l.kind === "email_password_submit") {
|
|
64
|
+
l.children.forEach((c) => visit(c, depth + 1));
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
visit(root, 0);
|
|
68
|
+
};
|
|
69
|
+
var walkScreen = (screen, fn) => {
|
|
70
|
+
if (screen.regions.header) walkLayers(screen.regions.header, fn);
|
|
71
|
+
walkLayers(screen.regions.body, fn);
|
|
72
|
+
if (screen.regions.footer) walkLayers(screen.regions.footer, fn);
|
|
73
|
+
};
|
|
74
|
+
var findInputLayer = (screen) => {
|
|
75
|
+
let found = null;
|
|
76
|
+
walkScreen(screen, (l) => {
|
|
77
|
+
if (!found && isInputLayer(l)) found = l;
|
|
78
|
+
});
|
|
79
|
+
return found;
|
|
80
|
+
};
|
|
81
|
+
var findManualSubmitInputLayer = (screen) => {
|
|
82
|
+
const input = findInputLayer(screen);
|
|
83
|
+
if (!input) return null;
|
|
84
|
+
if (input.kind === "multiple_choice" || input.kind === "text_input" || input.kind === "scale_input") {
|
|
85
|
+
return input;
|
|
86
|
+
}
|
|
87
|
+
return null;
|
|
88
|
+
};
|
|
89
|
+
var findLayerById = (screen, id) => {
|
|
90
|
+
let found = null;
|
|
91
|
+
walkScreen(screen, (l) => {
|
|
92
|
+
if (!found && l.id === id) found = l;
|
|
93
|
+
});
|
|
94
|
+
return found;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
// src/decisionEval.ts
|
|
98
|
+
var findDecisionNode = (manifest, id) => (manifest.decisionNodes ?? []).find((d) => d.id === id);
|
|
99
|
+
var stableSerialize = (value) => {
|
|
100
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
101
|
+
if (Array.isArray(value)) return `[${value.map(stableSerialize).join(",")}]`;
|
|
102
|
+
const keys = Object.keys(value).sort();
|
|
103
|
+
const parts = keys.map((k) => `${JSON.stringify(k)}:${stableSerialize(value[k])}`);
|
|
104
|
+
return `{${parts.join(",")}}`;
|
|
105
|
+
};
|
|
106
|
+
var digestDecisionExpression = (expr) => {
|
|
107
|
+
const s = stableSerialize(expr);
|
|
108
|
+
let h = 5381;
|
|
109
|
+
for (let i = 0; i < s.length; i += 1) {
|
|
110
|
+
h = h * 33 ^ s.charCodeAt(i);
|
|
111
|
+
}
|
|
112
|
+
return `d${(h >>> 0).toString(16)}`;
|
|
113
|
+
};
|
|
114
|
+
var responseForField = (fieldKey, responses) => responses[fieldKey];
|
|
115
|
+
var normalizeResponseValue = (r) => {
|
|
116
|
+
if (!r || typeof r !== "object") return void 0;
|
|
117
|
+
const o = r;
|
|
118
|
+
switch (o.kind) {
|
|
119
|
+
case "choice":
|
|
120
|
+
return typeof o.choiceId === "string" ? o.choiceId : void 0;
|
|
121
|
+
case "multiChoice":
|
|
122
|
+
return Array.isArray(o.choiceIds) ? o.choiceIds : void 0;
|
|
123
|
+
case "text":
|
|
124
|
+
return typeof o.value === "string" ? o.value : void 0;
|
|
125
|
+
case "scale":
|
|
126
|
+
return typeof o.value === "number" ? o.value : void 0;
|
|
127
|
+
case "checkbox":
|
|
128
|
+
return typeof o.value === "boolean" ? o.value : void 0;
|
|
129
|
+
default:
|
|
130
|
+
return void 0;
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
var normalizeScalarForStringPred = (raw) => {
|
|
134
|
+
if (raw === void 0 || raw === null) return void 0;
|
|
135
|
+
if (typeof raw === "string") return raw;
|
|
136
|
+
if (typeof raw === "number" && Number.isFinite(raw)) return String(raw);
|
|
137
|
+
return void 0;
|
|
138
|
+
};
|
|
139
|
+
var normalizeNumber = (raw) => {
|
|
140
|
+
if (typeof raw !== "number" || !Number.isFinite(raw)) return void 0;
|
|
141
|
+
return raw;
|
|
142
|
+
};
|
|
143
|
+
var normalizeChoiceId = (raw) => typeof raw === "string" && raw.length > 0 ? raw : void 0;
|
|
144
|
+
var normalizeChoiceIds = (raw) => {
|
|
145
|
+
if (!Array.isArray(raw)) return void 0;
|
|
146
|
+
const ids = raw.filter((x) => typeof x === "string" && x.length > 0);
|
|
147
|
+
return ids;
|
|
148
|
+
};
|
|
149
|
+
var normalizeBoolean = (raw) => {
|
|
150
|
+
if (typeof raw === "boolean") return raw;
|
|
151
|
+
if (typeof raw === "number" && Number.isFinite(raw)) return raw !== 0;
|
|
152
|
+
if (typeof raw === "string") {
|
|
153
|
+
const s = raw.trim().toLowerCase();
|
|
154
|
+
if (s === "true" || s === "1" || s === "yes") return true;
|
|
155
|
+
if (s === "false" || s === "0" || s === "no") return false;
|
|
156
|
+
}
|
|
157
|
+
return void 0;
|
|
158
|
+
};
|
|
159
|
+
var resolveVariableValue = (variable, ctx) => {
|
|
160
|
+
if (variable.kind === "builtin") {
|
|
161
|
+
if (variable.name === "locale") return ctx.locale;
|
|
162
|
+
return ctx.platform;
|
|
163
|
+
}
|
|
164
|
+
if (variable.kind === "sdk") return ctx.sdkAttributes[variable.key];
|
|
165
|
+
const r = responseForField(variable.fieldKey, ctx.responses);
|
|
166
|
+
return normalizeResponseValue(r);
|
|
167
|
+
};
|
|
168
|
+
var evalStringPred = (left, pred) => {
|
|
169
|
+
switch (pred.op) {
|
|
170
|
+
case "eq":
|
|
171
|
+
return left === pred.value;
|
|
172
|
+
case "neq":
|
|
173
|
+
return left !== pred.value;
|
|
174
|
+
case "contains":
|
|
175
|
+
return left.includes(pred.value);
|
|
176
|
+
default:
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
var evalNumberPred = (left, pred) => {
|
|
181
|
+
switch (pred.op) {
|
|
182
|
+
case "eq":
|
|
183
|
+
return left === pred.value;
|
|
184
|
+
case "neq":
|
|
185
|
+
return left !== pred.value;
|
|
186
|
+
case "lt":
|
|
187
|
+
return left < pred.value;
|
|
188
|
+
case "lte":
|
|
189
|
+
return left <= pred.value;
|
|
190
|
+
case "gt":
|
|
191
|
+
return left > pred.value;
|
|
192
|
+
case "gte":
|
|
193
|
+
return left >= pred.value;
|
|
194
|
+
default:
|
|
195
|
+
return false;
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
var evalChoicePred = (choiceId, pred) => {
|
|
199
|
+
if (pred.op === "eq") return choiceId === pred.optionId;
|
|
200
|
+
return pred.optionIds.includes(choiceId);
|
|
201
|
+
};
|
|
202
|
+
var setIntersect = (a, b) => {
|
|
203
|
+
const bs = new Set(b);
|
|
204
|
+
return a.filter((x) => bs.has(x));
|
|
205
|
+
};
|
|
206
|
+
var evalBooleanPred = (left, pred) => {
|
|
207
|
+
if (pred.op === "eq") return left === pred.value;
|
|
208
|
+
return left !== pred.value;
|
|
209
|
+
};
|
|
210
|
+
var evalMultiPred = (selected, pred) => {
|
|
211
|
+
const required = pred.optionIds;
|
|
212
|
+
switch (pred.op) {
|
|
213
|
+
case "intersects":
|
|
214
|
+
return setIntersect(selected, required).length > 0;
|
|
215
|
+
case "contains_all": {
|
|
216
|
+
const sel = new Set(selected);
|
|
217
|
+
return required.every((id) => sel.has(id));
|
|
218
|
+
}
|
|
219
|
+
case "subset_of": {
|
|
220
|
+
const allow = new Set(required);
|
|
221
|
+
return selected.every((id) => allow.has(id));
|
|
222
|
+
}
|
|
223
|
+
default:
|
|
224
|
+
return false;
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
var evaluateDecisionExpression = (expr, ctx) => {
|
|
228
|
+
if (expr.kind === "empty") return false;
|
|
229
|
+
if (expr.kind === "group") {
|
|
230
|
+
if (expr.op === "and") {
|
|
231
|
+
for (const c of expr.children) {
|
|
232
|
+
if (!evaluateDecisionExpression(c, ctx)) return false;
|
|
233
|
+
}
|
|
234
|
+
return true;
|
|
235
|
+
}
|
|
236
|
+
for (const c of expr.children) {
|
|
237
|
+
if (evaluateDecisionExpression(c, ctx)) return true;
|
|
238
|
+
}
|
|
239
|
+
return false;
|
|
240
|
+
}
|
|
241
|
+
const raw = resolveVariableValue(expr.variable, ctx);
|
|
242
|
+
const { predicate } = expr;
|
|
243
|
+
switch (predicate.type) {
|
|
244
|
+
case "string": {
|
|
245
|
+
const s = normalizeScalarForStringPred(raw);
|
|
246
|
+
if (s === void 0) return false;
|
|
247
|
+
return evalStringPred(s, predicate.pred);
|
|
248
|
+
}
|
|
249
|
+
case "number": {
|
|
250
|
+
const n = normalizeNumber(raw);
|
|
251
|
+
if (n === void 0) return false;
|
|
252
|
+
return evalNumberPred(n, predicate.pred);
|
|
253
|
+
}
|
|
254
|
+
case "choice": {
|
|
255
|
+
const id = normalizeChoiceId(raw);
|
|
256
|
+
if (!id) return false;
|
|
257
|
+
return evalChoicePred(id, predicate.pred);
|
|
258
|
+
}
|
|
259
|
+
case "multi": {
|
|
260
|
+
const ids = normalizeChoiceIds(raw);
|
|
261
|
+
if (!ids) return false;
|
|
262
|
+
return evalMultiPred(ids, predicate.pred);
|
|
263
|
+
}
|
|
264
|
+
case "boolean": {
|
|
265
|
+
const b = normalizeBoolean(raw);
|
|
266
|
+
if (b === void 0) return false;
|
|
267
|
+
return evalBooleanPred(b, predicate.pred);
|
|
268
|
+
}
|
|
269
|
+
default:
|
|
270
|
+
return false;
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
var evaluateDecisionNode = (node, ctx) => {
|
|
274
|
+
for (const c of node.cases) {
|
|
275
|
+
if (evaluateDecisionExpression(c.expression, ctx)) {
|
|
276
|
+
return {
|
|
277
|
+
matchedCaseId: c.id,
|
|
278
|
+
next: c.next,
|
|
279
|
+
clauseDigest: digestDecisionExpression(c.expression)
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
return {
|
|
284
|
+
matchedCaseId: null,
|
|
285
|
+
next: node.elseNext,
|
|
286
|
+
clauseDigest: "else"
|
|
287
|
+
};
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
// src/stateMachine/graphLanding.ts
|
|
291
|
+
var resolveOsPermissionDestination = (screen, response) => {
|
|
292
|
+
const layer = findLayerById(screen, response.layerId);
|
|
293
|
+
if (!layer || layer.kind !== "button" || layer.action.kind !== "request_os_permission")
|
|
294
|
+
return null;
|
|
295
|
+
if (layer.action.permissionKey !== response.permissionKey) return null;
|
|
296
|
+
const target = layer.action.outcomes[response.outcome];
|
|
297
|
+
if (target === OS_PERMISSION_OUTCOME_END) return null;
|
|
298
|
+
if (target === OS_PERMISSION_OUTCOME_CONTINUE) return screen.next.default ?? null;
|
|
299
|
+
return target;
|
|
300
|
+
};
|
|
301
|
+
var resolveNextScreenId = (screen, response) => {
|
|
302
|
+
if (response.kind === "screen_commit") {
|
|
303
|
+
return resolveNextScreenId(screen, response.primary);
|
|
304
|
+
}
|
|
305
|
+
if (response.kind === "go_to_screen") return response.screenId;
|
|
306
|
+
if (response.kind === "permission_outcome") {
|
|
307
|
+
const nextId = resolveOsPermissionDestination(screen, response);
|
|
308
|
+
return nextId ?? screen.next.default ?? null;
|
|
309
|
+
}
|
|
310
|
+
if (response.kind === "app_review_outcome") {
|
|
311
|
+
const layer = findLayerById(screen, response.layerId);
|
|
312
|
+
if (!layer || layer.kind !== "button" || layer.action.kind !== "request_app_review") {
|
|
313
|
+
return screen.next.default ?? null;
|
|
314
|
+
}
|
|
315
|
+
return screen.next.default ?? null;
|
|
316
|
+
}
|
|
317
|
+
if (response.kind === "oauth_login_resolve") {
|
|
318
|
+
return screen.next.default ?? null;
|
|
319
|
+
}
|
|
320
|
+
if (response.kind === "email_password_auth_resolve") {
|
|
321
|
+
return screen.next.default ?? null;
|
|
322
|
+
}
|
|
323
|
+
const input = findInputLayer(screen);
|
|
324
|
+
if (input && (input.kind === "single_choice" || input.kind === "multiple_choice") && input.branching.enabled) {
|
|
325
|
+
if (response.kind === "choice") {
|
|
326
|
+
const m = input.branching.conditions.find((c) => c.choiceId === response.choiceId);
|
|
327
|
+
if (m) return m.goTo;
|
|
328
|
+
} else if (response.kind === "multiChoice") {
|
|
329
|
+
const m = input.branching.conditions.find((c) => response.choiceIds.includes(c.choiceId));
|
|
330
|
+
if (m) return m.goTo;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
return screen.next.default ?? null;
|
|
334
|
+
};
|
|
335
|
+
var resolveThroughGraph = (manifest, cursor, responses, session, onDecisionEvaluated) => {
|
|
336
|
+
let cur = cursor;
|
|
337
|
+
const evalCtx = {
|
|
338
|
+
locale: session.locale,
|
|
339
|
+
platform: session.platform,
|
|
340
|
+
sdkAttributes: session.sdkAttributes,
|
|
341
|
+
responses
|
|
342
|
+
};
|
|
343
|
+
while (cur) {
|
|
344
|
+
const dn = findDecisionNode(manifest, cur);
|
|
345
|
+
if (!dn) break;
|
|
346
|
+
const evalResult = evaluateDecisionNode(dn, evalCtx);
|
|
347
|
+
onDecisionEvaluated?.({
|
|
348
|
+
decisionNodeId: dn.id,
|
|
349
|
+
matchedCaseId: evalResult.matchedCaseId,
|
|
350
|
+
clauseDigest: evalResult.clauseDigest
|
|
351
|
+
});
|
|
352
|
+
cur = evalResult.next;
|
|
353
|
+
if (cur == null) break;
|
|
354
|
+
}
|
|
355
|
+
if (cur == null) return { kind: "end" };
|
|
356
|
+
if (findExternalSurface(manifest, cur)) return { kind: "surface", nodeId: cur };
|
|
357
|
+
return { kind: "screen", screenId: cur };
|
|
358
|
+
};
|
|
359
|
+
var responseKeyFor = (screen, response) => {
|
|
360
|
+
if (response.kind === "text" || response.kind === "choice" || response.kind === "multiChoice" || response.kind === "scale" || response.kind === "checkbox") {
|
|
361
|
+
const input = findInputLayer(screen);
|
|
362
|
+
if (input) return input.fieldKey;
|
|
363
|
+
}
|
|
364
|
+
if (response.kind === "permission_outcome") return permissionCaptureFieldKey(response.permissionKey);
|
|
365
|
+
if (response.kind === "app_review_outcome") return appReviewCaptureFieldKey(response.layerId);
|
|
366
|
+
if (response.kind === "checkbox") return response.fieldKey;
|
|
367
|
+
if (response.kind === "oauth_login_resolve") return oauthLoginResponseKey(response.layerId);
|
|
368
|
+
if (response.kind === "email_password_auth_resolve") {
|
|
369
|
+
return emailPasswordAuthResponseKey(response.layerId);
|
|
370
|
+
}
|
|
371
|
+
return screen.id;
|
|
372
|
+
};
|
|
373
|
+
var applyGraphLanding = (base, landing, nextResponses, now) => {
|
|
374
|
+
if (landing.kind === "end") {
|
|
375
|
+
return {
|
|
376
|
+
...base,
|
|
377
|
+
responses: nextResponses,
|
|
378
|
+
currentScreenId: null,
|
|
379
|
+
pendingExternalSurface: null,
|
|
380
|
+
status: "completed",
|
|
381
|
+
completedAt: now
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
if (landing.kind === "surface") {
|
|
385
|
+
return {
|
|
386
|
+
...base,
|
|
387
|
+
responses: nextResponses,
|
|
388
|
+
currentScreenId: null,
|
|
389
|
+
pendingExternalSurface: { nodeId: landing.nodeId },
|
|
390
|
+
history: [...base.history, landing.nodeId]
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
return {
|
|
394
|
+
...base,
|
|
395
|
+
responses: nextResponses,
|
|
396
|
+
currentScreenId: landing.screenId,
|
|
397
|
+
pendingExternalSurface: null,
|
|
398
|
+
history: [...base.history, landing.screenId]
|
|
399
|
+
};
|
|
400
|
+
};
|
|
401
|
+
var startFlow = (state, second) => {
|
|
402
|
+
const opts = typeof second === "string" ? { now: second } : second ?? {};
|
|
403
|
+
const now = opts.now ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
404
|
+
const entry = state.manifest.entryScreenId;
|
|
405
|
+
if (entry == null) {
|
|
406
|
+
return {
|
|
407
|
+
...state,
|
|
408
|
+
status: "idle",
|
|
409
|
+
currentScreenId: null,
|
|
410
|
+
pendingExternalSurface: null,
|
|
411
|
+
history: [],
|
|
412
|
+
startedAt: null,
|
|
413
|
+
completedAt: null
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
const landing = resolveThroughGraph(
|
|
417
|
+
state.manifest,
|
|
418
|
+
entry,
|
|
419
|
+
{},
|
|
420
|
+
{
|
|
421
|
+
...state.session
|
|
422
|
+
},
|
|
423
|
+
opts.onDecisionEvaluated
|
|
424
|
+
);
|
|
425
|
+
if (landing.kind === "end") {
|
|
426
|
+
return {
|
|
427
|
+
...state,
|
|
428
|
+
status: "completed",
|
|
429
|
+
currentScreenId: null,
|
|
430
|
+
pendingExternalSurface: null,
|
|
431
|
+
history: [entry],
|
|
432
|
+
startedAt: now,
|
|
433
|
+
completedAt: now
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
if (landing.kind === "surface") {
|
|
437
|
+
return {
|
|
438
|
+
...state,
|
|
439
|
+
status: "running",
|
|
440
|
+
currentScreenId: null,
|
|
441
|
+
pendingExternalSurface: { nodeId: landing.nodeId },
|
|
442
|
+
history: [landing.nodeId],
|
|
443
|
+
startedAt: now
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
return {
|
|
447
|
+
...state,
|
|
448
|
+
status: "running",
|
|
449
|
+
currentScreenId: landing.screenId,
|
|
450
|
+
pendingExternalSurface: null,
|
|
451
|
+
history: [landing.screenId],
|
|
452
|
+
startedAt: now
|
|
453
|
+
};
|
|
454
|
+
};
|
|
455
|
+
var submitResponse = (state, response, third) => {
|
|
456
|
+
const opts = typeof third === "string" ? { now: third } : third ?? {};
|
|
457
|
+
const now = opts.now ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
458
|
+
if (state.status !== "running") return state;
|
|
459
|
+
if (response.kind === "external_surface_outcome") {
|
|
460
|
+
const pending = state.pendingExternalSurface;
|
|
461
|
+
if (!pending || pending.nodeId !== response.nodeId) return state;
|
|
462
|
+
const surface = findExternalSurface(state.manifest, pending.nodeId);
|
|
463
|
+
if (!surface) return state;
|
|
464
|
+
const nextSession = response.sdkKeyPatch ? {
|
|
465
|
+
...state.session,
|
|
466
|
+
sdkAttributes: { ...state.session.sdkAttributes, ...response.sdkKeyPatch }
|
|
467
|
+
} : state.session;
|
|
468
|
+
const target = surface.outcomes[response.outcome] ?? surface.fallback;
|
|
469
|
+
const nextResponses2 = {
|
|
470
|
+
...state.responses,
|
|
471
|
+
[externalSurfaceResponseKey(pending.nodeId)]: response
|
|
472
|
+
};
|
|
473
|
+
if (target === EXTERNAL_SURFACE_NO_NEXT) {
|
|
474
|
+
return {
|
|
475
|
+
...state,
|
|
476
|
+
session: nextSession,
|
|
477
|
+
responses: nextResponses2,
|
|
478
|
+
pendingExternalSurface: null,
|
|
479
|
+
currentScreenId: null,
|
|
480
|
+
status: "completed",
|
|
481
|
+
completedAt: now
|
|
482
|
+
};
|
|
483
|
+
}
|
|
484
|
+
const landing2 = resolveThroughGraph(
|
|
485
|
+
state.manifest,
|
|
486
|
+
target,
|
|
487
|
+
nextResponses2,
|
|
488
|
+
nextSession,
|
|
489
|
+
opts.onDecisionEvaluated
|
|
490
|
+
);
|
|
491
|
+
return applyGraphLanding(
|
|
492
|
+
{ ...state, session: nextSession },
|
|
493
|
+
landing2,
|
|
494
|
+
nextResponses2,
|
|
495
|
+
now
|
|
496
|
+
);
|
|
497
|
+
}
|
|
498
|
+
if (!state.currentScreenId) return state;
|
|
499
|
+
const screen = findScreen(state.manifest, state.currentScreenId);
|
|
500
|
+
if (!screen) return state;
|
|
501
|
+
if (response.kind === "screen_commit") {
|
|
502
|
+
const mergedResponses = { ...state.responses };
|
|
503
|
+
for (const [fk, value] of Object.entries(response.checkboxValues)) {
|
|
504
|
+
mergedResponses[fk] = { kind: "checkbox", fieldKey: fk, value };
|
|
505
|
+
}
|
|
506
|
+
if (response.capturedDraft) {
|
|
507
|
+
mergedResponses[responseKeyFor(screen, response.capturedDraft)] = response.capturedDraft;
|
|
508
|
+
}
|
|
509
|
+
return submitResponse({ ...state, responses: mergedResponses }, response.primary, opts);
|
|
510
|
+
}
|
|
511
|
+
if (response.kind === "go_back") {
|
|
512
|
+
const fallback = response.fallbackScreenId;
|
|
513
|
+
if (state.history.length > 1) {
|
|
514
|
+
const nextHistory = state.history.slice(0, -1);
|
|
515
|
+
const prevId = nextHistory[nextHistory.length - 1];
|
|
516
|
+
if (!prevId) return state;
|
|
517
|
+
return {
|
|
518
|
+
...state,
|
|
519
|
+
currentScreenId: prevId,
|
|
520
|
+
history: nextHistory
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
if (fallback && findScreen(state.manifest, fallback)) {
|
|
524
|
+
return {
|
|
525
|
+
...state,
|
|
526
|
+
currentScreenId: fallback,
|
|
527
|
+
history: [fallback]
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
return state;
|
|
531
|
+
}
|
|
532
|
+
if (response.kind === "oauth_login_resolve" && !response.success) {
|
|
533
|
+
const key2 = oauthLoginResponseKey(response.layerId);
|
|
534
|
+
return {
|
|
535
|
+
...state,
|
|
536
|
+
responses: { ...state.responses, [key2]: response }
|
|
537
|
+
};
|
|
538
|
+
}
|
|
539
|
+
if (response.kind === "email_password_auth_resolve" && !response.success) {
|
|
540
|
+
const key2 = emailPasswordAuthResponseKey(response.layerId);
|
|
541
|
+
return {
|
|
542
|
+
...state,
|
|
543
|
+
responses: { ...state.responses, [key2]: response }
|
|
544
|
+
};
|
|
545
|
+
}
|
|
546
|
+
if (response.kind === "end_flow") {
|
|
547
|
+
const nextResponses2 = { ...state.responses };
|
|
548
|
+
if (response.consumedDraft) {
|
|
549
|
+
nextResponses2[responseKeyFor(screen, response.consumedDraft)] = response.consumedDraft;
|
|
550
|
+
}
|
|
551
|
+
nextResponses2[responseKeyFor(screen, { kind: "end_flow" })] = { kind: "end_flow" };
|
|
552
|
+
return {
|
|
553
|
+
...state,
|
|
554
|
+
responses: nextResponses2,
|
|
555
|
+
currentScreenId: null,
|
|
556
|
+
status: "completed",
|
|
557
|
+
completedAt: now
|
|
558
|
+
};
|
|
559
|
+
}
|
|
560
|
+
if (response.kind === "skip") {
|
|
561
|
+
const nextResponses2 = { ...state.responses };
|
|
562
|
+
const manualInput = findManualSubmitInputLayer(screen);
|
|
563
|
+
if (manualInput) {
|
|
564
|
+
nextResponses2[manualInput.fieldKey] = { kind: "bypass_input", via: "skip" };
|
|
565
|
+
}
|
|
566
|
+
nextResponses2[responseKeyFor(screen, { kind: "skip" })] = { kind: "skip" };
|
|
567
|
+
const nextRaw2 = resolveNextScreenId(screen, { kind: "skip" });
|
|
568
|
+
const landing2 = resolveThroughGraph(
|
|
569
|
+
state.manifest,
|
|
570
|
+
nextRaw2,
|
|
571
|
+
nextResponses2,
|
|
572
|
+
state.session,
|
|
573
|
+
opts.onDecisionEvaluated
|
|
574
|
+
);
|
|
575
|
+
return applyGraphLanding(state, landing2, nextResponses2, now);
|
|
576
|
+
}
|
|
577
|
+
const key = responseKeyFor(screen, response);
|
|
578
|
+
const nextResponses = { ...state.responses, [key]: response };
|
|
579
|
+
if (response.kind === "go_to_screen") {
|
|
580
|
+
const manualInput = findManualSubmitInputLayer(screen);
|
|
581
|
+
if (manualInput) {
|
|
582
|
+
nextResponses[manualInput.fieldKey] = { kind: "bypass_input", via: "go_to_screen" };
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
const nextRaw = resolveNextScreenId(screen, response);
|
|
586
|
+
const landing = resolveThroughGraph(
|
|
587
|
+
state.manifest,
|
|
588
|
+
nextRaw,
|
|
589
|
+
nextResponses,
|
|
590
|
+
state.session,
|
|
591
|
+
opts.onDecisionEvaluated
|
|
592
|
+
);
|
|
593
|
+
return applyGraphLanding(state, landing, nextResponses, now);
|
|
594
|
+
};
|
|
595
|
+
|
|
596
|
+
// src/stateMachine/flowTerminal.ts
|
|
597
|
+
var TERMINAL_EXPORT_AUTH_RESPONSE_KEY_PREFIXES = ["oauth:", "email_pw:"];
|
|
598
|
+
var isAuthTerminalExportResponseKey = (key) => TERMINAL_EXPORT_AUTH_RESPONSE_KEY_PREFIXES.some((prefix) => key.startsWith(prefix));
|
|
599
|
+
var stripAuthResponsesForTerminalExport = (responses) => {
|
|
600
|
+
const out = {};
|
|
601
|
+
for (const [k, v] of Object.entries(responses)) {
|
|
602
|
+
if (isAuthTerminalExportResponseKey(k)) continue;
|
|
603
|
+
out[k] = v;
|
|
604
|
+
}
|
|
605
|
+
return out;
|
|
606
|
+
};
|
|
607
|
+
var stepResponseToCompletionValue = (r) => {
|
|
608
|
+
if (r.kind === "screen_commit") return void 0;
|
|
609
|
+
switch (r.kind) {
|
|
610
|
+
case "choice":
|
|
611
|
+
return r.choiceId;
|
|
612
|
+
case "multiChoice":
|
|
613
|
+
return r.choiceIds;
|
|
614
|
+
case "text":
|
|
615
|
+
return { value: r.value, classification: r.classification };
|
|
616
|
+
case "scale":
|
|
617
|
+
return r.value;
|
|
618
|
+
case "checkbox":
|
|
619
|
+
return r.value;
|
|
620
|
+
case "cta":
|
|
621
|
+
return r.action;
|
|
622
|
+
case "carousel":
|
|
623
|
+
return "carousel";
|
|
624
|
+
case "end_flow":
|
|
625
|
+
return "end_flow";
|
|
626
|
+
case "skip":
|
|
627
|
+
return "skip";
|
|
628
|
+
case "permission_outcome":
|
|
629
|
+
return r.outcome;
|
|
630
|
+
case "app_review_outcome":
|
|
631
|
+
return r.outcome;
|
|
632
|
+
case "oauth_login_resolve":
|
|
633
|
+
return {
|
|
634
|
+
success: r.success,
|
|
635
|
+
customerExternalId: r.customerExternalId,
|
|
636
|
+
provider: r.provider
|
|
637
|
+
};
|
|
638
|
+
case "email_password_auth_resolve":
|
|
639
|
+
return {
|
|
640
|
+
success: r.success,
|
|
641
|
+
mode: r.mode,
|
|
642
|
+
email: r.email
|
|
643
|
+
};
|
|
644
|
+
case "bypass_input":
|
|
645
|
+
return { bypassed: true, via: r.via };
|
|
646
|
+
case "external_surface_outcome":
|
|
647
|
+
return { outcome: r.outcome };
|
|
648
|
+
case "go_to_screen":
|
|
649
|
+
return { goToScreen: r.screenId };
|
|
650
|
+
case "go_back":
|
|
651
|
+
return void 0;
|
|
652
|
+
default: {
|
|
653
|
+
const _never = r;
|
|
654
|
+
return _never;
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
};
|
|
658
|
+
var buildCompletionResponses = (state) => {
|
|
659
|
+
const out = {};
|
|
660
|
+
for (const [key, r] of Object.entries(state.responses)) {
|
|
661
|
+
const v = stepResponseToCompletionValue(r);
|
|
662
|
+
if (v !== void 0) out[key] = v;
|
|
663
|
+
}
|
|
664
|
+
return out;
|
|
665
|
+
};
|
|
666
|
+
var abandonFlow = (state, now = (/* @__PURE__ */ new Date()).toISOString()) => ({
|
|
667
|
+
...state,
|
|
668
|
+
status: "abandoned",
|
|
669
|
+
completedAt: now
|
|
670
|
+
});
|
|
671
|
+
|
|
672
|
+
export { abandonFlow, applyGraphLanding, buildCompletionResponses, externalSurfaceResponseKey, findExternalSurface, findScreen, initFlowState, isAuthTerminalExportResponseKey, isEligibleConsumedDraft, resolveNextScreenId, resolveThroughGraph, responseKeyFor, startFlow, stepResponseToCompletionValue, stripAuthResponsesForTerminalExport, submitResponse };
|
|
673
|
+
//# sourceMappingURL=stateMachine.js.map
|
|
674
|
+
//# sourceMappingURL=stateMachine.js.map
|