@flopay/shared 1.3.4 → 1.4.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/index.mjs CHANGED
@@ -45,6 +45,300 @@ function networkError(message) {
45
45
  return new FloPayError(message, "network_error");
46
46
  }
47
47
 
48
+ // src/telemetry.ts
49
+ var TELEMETRY_SCHEMA_VERSION = 1;
50
+ var TELEMETRY_SDK_PACKAGES = [
51
+ "@flopay/shared",
52
+ "@flopay/js",
53
+ "@flopay/react"
54
+ ];
55
+ var TELEMETRY_MAX_BATCH_BYTES = 32 * 1024;
56
+ var TELEMETRY_MAX_BATCH_EVENTS = 20;
57
+ var TELEMETRY_PROVIDERS = ["stripe", "paypal"];
58
+ var TELEMETRY_PAYMENT_METHOD_CATEGORIES = [
59
+ "card",
60
+ "wallet",
61
+ "paypal",
62
+ "apm",
63
+ "saved",
64
+ "unknown"
65
+ ];
66
+ var TELEMETRY_STAGES = [
67
+ "callback",
68
+ "sdk_initialize",
69
+ "checkout_mount",
70
+ "session_create",
71
+ "session_read",
72
+ "session_first_byte",
73
+ "session_complete",
74
+ "checkout_data_ready",
75
+ "checkout_render",
76
+ "checkout_interactive",
77
+ "provider_load",
78
+ "provider_ready",
79
+ "overlay_open",
80
+ "overlay_return",
81
+ "redirect",
82
+ "redirect_resume",
83
+ "vault_request",
84
+ "vault_mount",
85
+ "vault_ready",
86
+ "vault_submit",
87
+ "tokenization",
88
+ "three_ds_handoff",
89
+ "three_ds_return",
90
+ "processing",
91
+ "recovery",
92
+ "completion",
93
+ "unmount",
94
+ "total_journey"
95
+ ];
96
+ var TELEMETRY_ERROR_CODES = [
97
+ "CALLBACK_FAILED",
98
+ "CHECKOUT_SESSION_CREATE_FAILED",
99
+ "CONFIGURATION_INVALID",
100
+ "INTERNAL_SDK_ERROR",
101
+ "NETWORK_REQUEST_FAILED",
102
+ "PAYMENT_PROCESSING_FAILED",
103
+ "POPUP_BLOCKED",
104
+ "PROVIDER_LOAD_FAILED",
105
+ "PROVIDER_RUNTIME_FAILED",
106
+ "RECOVERY_FAILED",
107
+ "REDIRECT_RESUME_FAILED",
108
+ "REQUEST_TIMEOUT",
109
+ "SDK_INITIALIZATION_FAILED",
110
+ "THREE_DS_FAILED",
111
+ "TOKENIZATION_FAILED",
112
+ "VAULT_LOAD_FAILED",
113
+ "VAULT_SUBMIT_FAILED"
114
+ ];
115
+ var TELEMETRY_LOG_NAMES = [
116
+ "sdk.initialize.started",
117
+ "sdk.initialize.ready",
118
+ "sdk.cache.hit",
119
+ "sdk.cache.miss",
120
+ "checkout.mount",
121
+ "session.create.started",
122
+ "session.read.started",
123
+ "session.request.first_byte",
124
+ "session.request.completed",
125
+ "checkout.data.ready",
126
+ "checkout.rendered",
127
+ "checkout.interactive",
128
+ "checkout.recovery.started",
129
+ "checkout.recovery.completed",
130
+ "checkout.unmount",
131
+ "provider.load.started",
132
+ "provider.eligibility.checked",
133
+ "provider.availability.checked",
134
+ "provider.ready",
135
+ "provider.popup.opened",
136
+ "provider.overlay.opened",
137
+ "provider.overlay.returned",
138
+ "provider.redirect.started",
139
+ "provider.redirect.resumed",
140
+ "vault.capture.requested",
141
+ "vault.widget.mounted",
142
+ "vault.widget.ready",
143
+ "vault.submission.started",
144
+ "vault.action.required",
145
+ "vault.three_ds.handoff",
146
+ "vault.three_ds.returned",
147
+ "vault.terminal",
148
+ "payment.method.selected",
149
+ "payment.intent.started",
150
+ "payment.intent.completed",
151
+ "payment.tokenization.started",
152
+ "payment.tokenization.completed",
153
+ "payment.processing.started",
154
+ "payment.processing.completed",
155
+ "payment.three_ds.handoff",
156
+ "payment.three_ds.returned",
157
+ "operation.retry",
158
+ "operation.deduplicated",
159
+ "operation.fallback",
160
+ "operation.cache.hit",
161
+ "operation.cache.miss",
162
+ "operation.recovery.started",
163
+ "operation.recovery.completed",
164
+ "operation.state_transition"
165
+ ];
166
+ var TELEMETRY_REQUEST_CATEGORIES = [
167
+ "session_create",
168
+ "session_read",
169
+ "intent_create",
170
+ "process_payment",
171
+ "vault_capture",
172
+ "account_snapshot",
173
+ "provider_sdk",
174
+ "other"
175
+ ];
176
+ var TELEMETRY_STATUS_CLASSES = [
177
+ "2xx",
178
+ "3xx",
179
+ "4xx",
180
+ "5xx",
181
+ "network_error",
182
+ "timeout",
183
+ "unknown"
184
+ ];
185
+ var TELEMETRY_CHECKOUT_MODES = ["full", "auto", "confirm", "unknown"];
186
+ var TELEMETRY_LAYOUTS = ["embedded", "buttons", "automatic", "unknown"];
187
+ var TELEMETRY_DURATION_MODES = ["machine", "buyer", "total"];
188
+ var TELEMETRY_EXPECTED_OUTCOMES = [
189
+ "action_required",
190
+ "customer_abandoned",
191
+ "payment_cancelled",
192
+ "payment_declined",
193
+ "payment_succeeded",
194
+ "validation_rejected"
195
+ ];
196
+ var UUID_V4 = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
197
+ var SDK_VERSION = /^\d{1,4}\.\d{1,4}\.\d{1,4}(?:-[0-9A-Za-z.-]{1,32})?$/;
198
+ var ERROR_CODES = new Set(TELEMETRY_ERROR_CODES);
199
+ var STAGES = new Set(TELEMETRY_STAGES);
200
+ var PROVIDERS = new Set(TELEMETRY_PROVIDERS);
201
+ var PAYMENT_METHODS = new Set(TELEMETRY_PAYMENT_METHOD_CATEGORIES);
202
+ var LOG_NAMES = new Set(TELEMETRY_LOG_NAMES);
203
+ var CHECKOUT_MODES = new Set(TELEMETRY_CHECKOUT_MODES);
204
+ var LAYOUTS = new Set(TELEMETRY_LAYOUTS);
205
+ var REQUEST_CATEGORIES = new Set(TELEMETRY_REQUEST_CATEGORIES);
206
+ var STATUS_CLASSES = new Set(TELEMETRY_STATUS_CLASSES);
207
+ var DURATION_MODES = new Set(TELEMETRY_DURATION_MODES);
208
+ var EXPECTED_OUTCOMES = new Set(TELEMETRY_EXPECTED_OUTCOMES);
209
+ var SDK_PACKAGES = new Set(TELEMETRY_SDK_PACKAGES);
210
+ function enumOr(value, allowed, fallback) {
211
+ return typeof value === "string" && allowed.has(value) ? value : fallback;
212
+ }
213
+ function createUuidV4() {
214
+ try {
215
+ const id = globalThis.crypto.randomUUID();
216
+ if (UUID_V4.test(id)) return id;
217
+ } catch {
218
+ }
219
+ const bytes = new Uint8Array(16);
220
+ try {
221
+ globalThis.crypto.getRandomValues(bytes);
222
+ } catch {
223
+ for (let index = 0; index < bytes.length; index += 1) {
224
+ bytes[index] = Math.floor(Math.random() * 256);
225
+ }
226
+ }
227
+ bytes[6] = bytes[6] & 15 | 64;
228
+ bytes[8] = bytes[8] & 63 | 128;
229
+ const hex = [...bytes].map((byte) => byte.toString(16).padStart(2, "0")).join("");
230
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
231
+ }
232
+ function safeUuid(value) {
233
+ return typeof value === "string" && UUID_V4.test(value) ? value : createUuidV4();
234
+ }
235
+ function safeAttempt(value) {
236
+ return typeof value === "number" && Number.isInteger(value) && value >= 0 && value <= 100 ? value : void 0;
237
+ }
238
+ function safeSequence(value) {
239
+ return Number.isSafeInteger(value) && value >= 0 ? Math.min(value, 1e6) : 0;
240
+ }
241
+ function safeDuration(value) {
242
+ if (!Number.isFinite(value) || value < 0) return 0;
243
+ return Math.min(Math.round(value), 12e4);
244
+ }
245
+ function addCommonFields(event, input) {
246
+ const attempt = safeAttempt(input.attempt);
247
+ if (input.provider && PROVIDERS.has(input.provider)) event.provider = input.provider;
248
+ if (attempt !== void 0) event.attempt = attempt;
249
+ if (input.statusClass) event.statusClass = enumOr(input.statusClass, STATUS_CLASSES, "unknown");
250
+ if (input.requestCategory) {
251
+ event.requestCategory = enumOr(input.requestCategory, REQUEST_CATEGORIES, "other");
252
+ }
253
+ if (input.paymentMethodCategory) {
254
+ event.paymentMethodCategory = enumOr(
255
+ input.paymentMethodCategory,
256
+ PAYMENT_METHODS,
257
+ "unknown"
258
+ );
259
+ }
260
+ if (input.checkoutMode) {
261
+ event.checkoutMode = enumOr(input.checkoutMode, CHECKOUT_MODES, "unknown");
262
+ }
263
+ if (input.layout) event.layout = enumOr(input.layout, LAYOUTS, "unknown");
264
+ return event;
265
+ }
266
+ function buildTelemetryErrorEvent(input) {
267
+ return addCommonFields(
268
+ {
269
+ eventId: safeUuid(input.eventId),
270
+ class: "technical_error",
271
+ code: enumOr(input.errorCode, ERROR_CODES, "INTERNAL_SDK_ERROR"),
272
+ stage: enumOr(input.stage, STAGES, "sdk_initialize"),
273
+ sequence: safeSequence(input.sequence)
274
+ },
275
+ input
276
+ );
277
+ }
278
+ function buildTelemetryLogEvent(input) {
279
+ return addCommonFields(
280
+ {
281
+ eventId: safeUuid(input.eventId),
282
+ class: "lifecycle",
283
+ name: enumOr(input.name, LOG_NAMES, "operation.retry"),
284
+ stage: enumOr(input.stage, STAGES, "sdk_initialize"),
285
+ sequence: safeSequence(input.sequence)
286
+ },
287
+ input
288
+ );
289
+ }
290
+ function buildTelemetryTerminalEvent(input) {
291
+ const commonInput = {
292
+ ...input,
293
+ stage: input.stage ?? "completion"
294
+ };
295
+ return addCommonFields(
296
+ {
297
+ eventId: safeUuid(input.eventId),
298
+ class: "expected_outcome",
299
+ outcome: enumOr(input.outcome, EXPECTED_OUTCOMES, "customer_abandoned"),
300
+ stage: enumOr(input.stage, STAGES, "completion"),
301
+ sequence: safeSequence(input.sequence)
302
+ },
303
+ commonInput
304
+ );
305
+ }
306
+ function buildTelemetryPerformanceEvent(input) {
307
+ return addCommonFields(
308
+ {
309
+ eventId: safeUuid(input.eventId),
310
+ class: "performance",
311
+ stage: enumOr(input.stage, STAGES, "sdk_initialize"),
312
+ sequence: safeSequence(input.sequence),
313
+ durationMs: safeDuration(input.durationMs),
314
+ durationMode: enumOr(input.durationMode, DURATION_MODES, "machine")
315
+ },
316
+ input
317
+ );
318
+ }
319
+ function serializeTelemetryBatch(events, options) {
320
+ const sanitizedEvents = events.slice(0, TELEMETRY_MAX_BATCH_EVENTS).flatMap((event) => {
321
+ if (event.class === "technical_error") {
322
+ return [buildTelemetryErrorEvent({ ...event, errorCode: event.code })];
323
+ }
324
+ if (event.class === "lifecycle") return [buildTelemetryLogEvent(event)];
325
+ if (event.class === "expected_outcome") return [buildTelemetryTerminalEvent(event)];
326
+ if (event.class === "performance") return [buildTelemetryPerformanceEvent(event)];
327
+ return [];
328
+ });
329
+ const envelope = {
330
+ schemaVersion: TELEMETRY_SCHEMA_VERSION,
331
+ batchId: safeUuid(options.batchId),
332
+ correlationId: safeUuid(options.correlationId),
333
+ sdk: {
334
+ package: enumOr(options.sdkPackage, SDK_PACKAGES, "@flopay/shared"),
335
+ version: SDK_VERSION.test(options.sdkVersion) ? options.sdkVersion : "0.0.0"
336
+ },
337
+ events: sanitizedEvents
338
+ };
339
+ return JSON.stringify(envelope);
340
+ }
341
+
48
342
  // src/config.ts
49
343
  var ENV_URL_MAP = {
50
344
  local: "https://flo.ngrok.pro",
@@ -79,7 +373,7 @@ var PAYMENT_METHOD_LOGOS = {
79
373
  };
80
374
 
81
375
  // src/constants.ts
82
- var SDK_VERSION = "1.3.4";
376
+ var SDK_VERSION2 = "1.4.0";
83
377
  var FLO_SDK_VERSION_HEADER = "x-flo-sdk-version";
84
378
  var BILLING_API_URL_STAGING = "https://api.stage.flopay.com";
85
379
  var BILLING_API_URL_PRODUCTION = "https://api.flopay.com";
@@ -2235,13 +2529,19 @@ export {
2235
2529
  MODERN_DARK_APPEARANCE,
2236
2530
  MODERN_LIGHT_APPEARANCE,
2237
2531
  NIGHT_APPEARANCE,
2238
- SDK_VERSION,
2532
+ SDK_VERSION2 as SDK_VERSION,
2239
2533
  STRIPE_EXPRESS_METHODS,
2240
2534
  STRIPE_METHOD_AMOUNT_LIMITS,
2241
2535
  STRIPE_METHOD_COUNTRIES,
2242
2536
  STRIPE_METHOD_CURRENCIES,
2243
2537
  STRIPE_METHOD_MATRIX,
2244
2538
  SUPPORTED_CARD_BRANDS,
2539
+ TELEMETRY_ERROR_CODES,
2540
+ TELEMETRY_LOG_NAMES,
2541
+ TELEMETRY_MAX_BATCH_BYTES,
2542
+ TELEMETRY_MAX_BATCH_EVENTS,
2543
+ TELEMETRY_SCHEMA_VERSION,
2544
+ TELEMETRY_SDK_PACKAGES,
2245
2545
  THEMES,
2246
2546
  US_STATES,
2247
2547
  apiError,
@@ -2250,6 +2550,10 @@ export {
2250
2550
  buildItemPayload,
2251
2551
  buildProductPayload,
2252
2552
  buildSubscriptionPayload,
2553
+ buildTelemetryErrorEvent,
2554
+ buildTelemetryLogEvent,
2555
+ buildTelemetryPerformanceEvent,
2556
+ buildTelemetryTerminalEvent,
2253
2557
  configureFlopay,
2254
2558
  filterStripeMethodsByAmount,
2255
2559
  filterStripeMethodsByCountry,
@@ -2286,6 +2590,7 @@ export {
2286
2590
  resolveSessionCurrency,
2287
2591
  resolveStripeMethodBrandVariant,
2288
2592
  resolveTheme,
2593
+ serializeTelemetryBatch,
2289
2594
  stripeExpressMethodToOptionKey,
2290
2595
  validationError
2291
2596
  };