@reform-society/agera-core 0.3.0 → 0.5.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.d.ts CHANGED
@@ -274,6 +274,10 @@ type CrmFetchResult = {
274
274
  ok: boolean;
275
275
  status: number;
276
276
  data: Record<string, unknown> | null;
277
+ raw?: unknown;
278
+ error?: unknown;
279
+ cancelled?: boolean;
280
+ normalized?: unknown;
277
281
  };
278
282
  type CrmCommand = {
279
283
  client: string;
@@ -317,6 +321,158 @@ declare function executeCrm(gateway: CrmGateway, command: CrmCommand, options?:
317
321
  signal?: AbortSignal;
318
322
  }): Promise<CrmOutcome>;
319
323
  //#endregion
324
+ //#region src/lifecycle.d.ts
325
+ type NormalizedResult = {
326
+ delivery: "observed" | "unobserved";
327
+ operation: string;
328
+ operationStatus: "acknowledged" | "pending" | "completed" | "rejected" | "unknown";
329
+ contactStatus: "created" | "updated" | "unknown";
330
+ contactEvidence: "provider" | "inferred" | "unknown";
331
+ paymentStatus: "unknown" | "pending" | "succeeded" | "failed";
332
+ paymentEvidence: "provider" | "inferred" | "unknown";
333
+ nextAction?: {
334
+ type: "redirect" | "poll" | "verify";
335
+ url?: string;
336
+ };
337
+ outcome?: string;
338
+ extensions?: Record<string, unknown>;
339
+ };
340
+ type EventSourceKind = "form-submit" | "element-action";
341
+ type EventSource = {
342
+ client: string;
343
+ integration?: string;
344
+ kind?: EventSourceKind;
345
+ formId?: string;
346
+ triggerId?: string;
347
+ pagePath: string;
348
+ };
349
+ type RequestSnapshot = {
350
+ fields: Record<string, unknown>;
351
+ context: Record<string, unknown>;
352
+ config: Record<string, unknown>;
353
+ method: string;
354
+ delivery: "wait" | "background";
355
+ body?: unknown;
356
+ };
357
+ type EventEnvelope = {
358
+ schemaVersion: 1;
359
+ eventId: string;
360
+ occurredAt: string;
361
+ source: EventSource;
362
+ context: Record<string, unknown>;
363
+ result: NormalizedResult;
364
+ submissionId?: string;
365
+ flowId?: string;
366
+ attemptId?: string;
367
+ conversionId?: string;
368
+ request?: RequestSnapshot;
369
+ };
370
+ type LifecycleEvent = EventEnvelope & ({
371
+ type: "crm.dispatched";
372
+ submissionId: string;
373
+ request: RequestSnapshot;
374
+ } | {
375
+ type: "crm.response";
376
+ submissionId: string;
377
+ request: RequestSnapshot;
378
+ response: {
379
+ httpStatus: number;
380
+ raw: unknown;
381
+ };
382
+ } | {
383
+ type: "crm.failed" | "crm.cancelled";
384
+ submissionId: string;
385
+ request: RequestSnapshot;
386
+ } | {
387
+ type: "element.entered" | "element.clicked" | "element.viewed" | "step.changed";
388
+ } | {
389
+ type: "flow.started" | "flow.returned" | "flow.verified" | "flow.failed";
390
+ flowId: string;
391
+ attemptId: string;
392
+ });
393
+ type LifecycleType = LifecycleEvent["type"];
394
+ declare function unknownResult(delivery?: NormalizedResult["delivery"]): NormalizedResult;
395
+ /** Serializable copies omit functions, DOM handles, and cyclic references. */
396
+ declare function snapshot<T>(value: T): T;
397
+ declare function createLifecycleBus(onError?: () => void): {
398
+ on: <T extends LifecycleType>(type: T | "*", listener: (event: LifecycleEvent & {
399
+ type: T;
400
+ }) => unknown) => () => void;
401
+ emit: (event: LifecycleEvent) => void;
402
+ clear(): void;
403
+ };
404
+ declare function normalizeResult(value: unknown, httpStatus?: number): NormalizedResult;
405
+ //#endregion
406
+ //#region src/tracking.d.ts
407
+ type ValueResolver = string | number | boolean | null | undefined | ValueResolver[] | {
408
+ [key: string]: ValueResolver;
409
+ } | ((event: LifecycleEvent) => unknown);
410
+ type TrackingConfig = {
411
+ destination: string | ((payload: Record<string, unknown>, event: LifecycleEvent) => unknown);
412
+ eventKey?: string;
413
+ reset?: Record<string, unknown>;
414
+ events: Partial<Record<LifecycleType, (event: LifecycleEvent) => string | null | undefined>>;
415
+ payload?: Record<string, ValueResolver>;
416
+ userData?: {
417
+ key: string;
418
+ fields: Record<string, string[] | ((event: LifecycleEvent) => unknown)>;
419
+ };
420
+ consent?: (event: LifecycleEvent) => boolean;
421
+ dedupe?: {
422
+ key: (event: LifecycleEvent, name: string) => string | undefined;
423
+ ttlMs: number;
424
+ maxEntries?: number;
425
+ };
426
+ envelope?: (payload: Record<string, unknown>, event: LifecycleEvent) => Record<string, unknown> | null;
427
+ };
428
+ declare function firstDefined(values: unknown[]): unknown;
429
+ declare function mapTrackingEvent(config: TrackingConfig, event: LifecycleEvent): {
430
+ name: string;
431
+ payload: any;
432
+ } | null;
433
+ declare function createTrackingConsumer(options: {
434
+ config: TrackingConfig;
435
+ now: () => number;
436
+ queue: (name: string, payload: Record<string, unknown>) => void;
437
+ diagnostic?: (status: "queued" | "submitted" | "deduplicated" | "failed") => void;
438
+ }): (event: LifecycleEvent) => void;
439
+ //#endregion
440
+ //#region src/flow-attempts.d.ts
441
+ type FlowAttempt = {
442
+ schemaVersion: 1;
443
+ flowId: string;
444
+ attemptId: string;
445
+ submissionId?: string;
446
+ token: string;
447
+ expectedReturn: string;
448
+ expiresAt: number;
449
+ acknowledged: boolean;
450
+ source: EventSource;
451
+ context: Record<string, unknown>;
452
+ request?: RequestSnapshot;
453
+ };
454
+ type AttemptStorage = {
455
+ getItem(key: string): string | null;
456
+ setItem(key: string, value: string): void;
457
+ removeItem(key: string): void;
458
+ };
459
+ declare function createAttemptStore(options: {
460
+ namespace: string;
461
+ storage: AttemptStorage;
462
+ now: () => number;
463
+ id: () => string;
464
+ ttlMs: number;
465
+ maxEntries?: number;
466
+ diagnostic?: () => void;
467
+ }): {
468
+ begin: (input: Omit<FlowAttempt, "schemaVersion" | "attemptId" | "token" | "expiresAt" | "acknowledged">) => FlowAttempt | null;
469
+ acknowledge: (token: string) => boolean;
470
+ consume: (token: string, destination: string) => FlowAttempt | null;
471
+ cancel: (token: string) => boolean;
472
+ read: (token: string) => FlowAttempt | null;
473
+ purge: () => void;
474
+ };
475
+ //#endregion
320
476
  //#region src/utm.d.ts
321
477
  declare const UTM_KEYS: readonly ["source", "campaign", "medium", "content", "term", "wec"];
322
478
  type Utms = Partial<Record<(typeof UTM_KEYS)[number], string>>;
@@ -459,5 +615,5 @@ declare function assembleCrmRequest({
459
615
  //#region src/polling.d.ts
460
616
  declare function matchesFormat(example: unknown, value: unknown): boolean;
461
617
  //#endregion
462
- export { type AssembleCrmRequestParams, type BandQuizResults, CRM_CONTACT_KEYS, type CompositePredicate, type CounterDisplayConfig, type CounterPayload, type CounterResponse, type CounterUpdateConfig, type CrmCommand, type CrmConfig, type CrmContactKey, type CrmDispatch, type CrmFetchOptions, type CrmFetchResult, type CrmFrontendKey, type CrmGateway, type CrmGatewayResult, type CrmGroupedAnswer, type CrmJsonGroups, type CrmOutcome, type CrmV2PatchRequest, type CrmV2Payload, type CrmV2Request, type DeviceInput, type DeviceType, type ErrorMessages, type FetchBasinJWTOptions, type InsertDirective, type JsonValue, type JwtPayload, type MemoryCache, type MemoryCacheOptions, type MemoryCacheSetOptions, type PassQuizResults, type PlacesMessageKey, type PlacesMessages, type Predicate, type PredicateOp, type ProgressInfo, type ProgressModeInfo, type QuestionMetrics, type QuizBandDefinition, type QuizConfig, type QuizOutcomeModel, type QuizPassFailConfig, type QuizQuestionInput, type QuizQuestionModel, type QuizQuestionResult, type QuizQuestionState, type QuizResults, type QuizScoringModel, type QuizSectionConfig, type QuizSectionResults, type ResolveValueSources, type ScoreQuizResults, type SessionState, type ShareConfig, type SimplePredicate, type SplitConfig, type StepState, type StorageAccessor, type SurveyOptions, type Utms, VISITOR_ID_STORAGE_KEY, type ValidationRule, type Validators, type WeightedQuizResults, aggregateWeightedScores, answersChanged, assembleCrmRequest, buildContext, buildCounterPayload, buildFcrmUtms, calculateScoreResults, calculateSectionResults, calculateWinner, computeAutoTarget, createMemoryCache, createSessionStore, createStepsStore, crmFetch, decodeJwtPayload, deriveBandResults, derivePassResults, deriveQuestionState, detectDeviceType, errorMessages, evaluateNextMap, evaluatePredicate, evaluateShowIf, executeCrm, extractUtms, fetchBasinJWT, fetchCounter, flattenObject, formatCounterValue, getErrorMessagesForLanguage, getOrCreateVisitorId, getPhoneExample, getPlacesMessagesForLanguage, getPostalExample, groupCrmAnswers, inferCounterName, isCounterResponse, isCrmContactKey, isJwtExpired, isSafeRedirectUrl, matchesFormat, mergeAnswers, parseCounterUpdateAttr, parseInsertDirective, parseInsertDirectives, resolveValue, scoreExactQuestion, scorePartialQuestion, scoreQuiz, scoreQuizQuestions, serializeCrmJsonGroups, updateUrlWithParams, validators };
618
+ export { type AssembleCrmRequestParams, type AttemptStorage, type BandQuizResults, CRM_CONTACT_KEYS, type CompositePredicate, type CounterDisplayConfig, type CounterPayload, type CounterResponse, type CounterUpdateConfig, type CrmCommand, type CrmConfig, type CrmContactKey, type CrmDispatch, type CrmFetchOptions, type CrmFetchResult, type CrmFrontendKey, type CrmGateway, type CrmGatewayResult, type CrmGroupedAnswer, type CrmJsonGroups, type CrmOutcome, type CrmV2PatchRequest, type CrmV2Payload, type CrmV2Request, type DeviceInput, type DeviceType, type ErrorMessages, type EventSource, type EventSourceKind, type FetchBasinJWTOptions, type FlowAttempt, type InsertDirective, type JsonValue, type JwtPayload, type LifecycleEvent, type LifecycleType, type MemoryCache, type MemoryCacheOptions, type MemoryCacheSetOptions, type NormalizedResult, type PassQuizResults, type PlacesMessageKey, type PlacesMessages, type Predicate, type PredicateOp, type ProgressInfo, type ProgressModeInfo, type QuestionMetrics, type QuizBandDefinition, type QuizConfig, type QuizOutcomeModel, type QuizPassFailConfig, type QuizQuestionInput, type QuizQuestionModel, type QuizQuestionResult, type QuizQuestionState, type QuizResults, type QuizScoringModel, type QuizSectionConfig, type QuizSectionResults, type RequestSnapshot, type ResolveValueSources, type ScoreQuizResults, type SessionState, type ShareConfig, type SimplePredicate, type SplitConfig, type StepState, type StorageAccessor, type SurveyOptions, type TrackingConfig, type Utms, VISITOR_ID_STORAGE_KEY, type ValidationRule, type Validators, type ValueResolver, type WeightedQuizResults, aggregateWeightedScores, answersChanged, assembleCrmRequest, buildContext, buildCounterPayload, buildFcrmUtms, calculateScoreResults, calculateSectionResults, calculateWinner, computeAutoTarget, createAttemptStore, createLifecycleBus, createMemoryCache, createSessionStore, createStepsStore, createTrackingConsumer, crmFetch, decodeJwtPayload, deriveBandResults, derivePassResults, deriveQuestionState, detectDeviceType, errorMessages, evaluateNextMap, evaluatePredicate, evaluateShowIf, executeCrm, extractUtms, fetchBasinJWT, fetchCounter, firstDefined, flattenObject, formatCounterValue, getErrorMessagesForLanguage, getOrCreateVisitorId, getPhoneExample, getPlacesMessagesForLanguage, getPostalExample, groupCrmAnswers, inferCounterName, isCounterResponse, isCrmContactKey, isJwtExpired, isSafeRedirectUrl, mapTrackingEvent, matchesFormat, mergeAnswers, normalizeResult, parseCounterUpdateAttr, parseInsertDirective, parseInsertDirectives, resolveValue, scoreExactQuestion, scorePartialQuestion, scoreQuiz, scoreQuizQuestions, serializeCrmJsonGroups, snapshot, unknownResult, updateUrlWithParams, validators };
463
619
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -789,6 +789,277 @@ async function executeCrm(gateway, command, options = {}) {
789
789
  }
790
790
  }
791
791
  //#endregion
792
+ //#region src/lifecycle.ts
793
+ function unknownResult(delivery = "unobserved") {
794
+ return {
795
+ delivery,
796
+ operation: "unknown",
797
+ operationStatus: "unknown",
798
+ contactStatus: "unknown",
799
+ contactEvidence: "unknown",
800
+ paymentStatus: "unknown",
801
+ paymentEvidence: "unknown"
802
+ };
803
+ }
804
+ /** Serializable copies omit functions, DOM handles, and cyclic references. */
805
+ function snapshot(value) {
806
+ const seen = /* @__PURE__ */ new WeakSet();
807
+ function copy(input) {
808
+ if (input === null || typeof input === "string" || typeof input === "boolean") return input;
809
+ if (typeof input === "number") return Number.isFinite(input) ? input : null;
810
+ if (typeof input !== "object" || seen.has(input)) return void 0;
811
+ if (!Array.isArray(input) && Object.getPrototypeOf(input) !== Object.prototype && Object.getPrototypeOf(input) !== null) return void 0;
812
+ seen.add(input);
813
+ const result = Array.isArray(input) ? input.map(copy) : Object.fromEntries(Object.entries(input).map(([key, item]) => [key, copy(item)]).filter(([, item]) => item !== void 0));
814
+ seen.delete(input);
815
+ return result;
816
+ }
817
+ return copy(value);
818
+ }
819
+ function createLifecycleBus(onError = () => {}) {
820
+ const listeners = /* @__PURE__ */ new Map();
821
+ function report() {
822
+ try {
823
+ onError();
824
+ } catch {}
825
+ }
826
+ function on(type, listener) {
827
+ const set = listeners.get(type) ?? /* @__PURE__ */ new Set();
828
+ set.add(listener);
829
+ listeners.set(type, set);
830
+ return () => {
831
+ set.delete(listener);
832
+ };
833
+ }
834
+ function emit(event) {
835
+ const captured = snapshot(event);
836
+ for (const listener of [...listeners.get(event.type) ?? [], ...listeners.get("*") ?? []]) try {
837
+ Promise.resolve(listener(snapshot(captured))).catch(report);
838
+ } catch {
839
+ report();
840
+ }
841
+ }
842
+ return {
843
+ on,
844
+ emit,
845
+ clear() {
846
+ listeners.clear();
847
+ }
848
+ };
849
+ }
850
+ function normalizeResult(value, httpStatus) {
851
+ const result = unknownResult(httpStatus === void 0 ? "unobserved" : "observed");
852
+ if (httpStatus !== void 0 && httpStatus >= 400) result.operationStatus = "rejected";
853
+ if (!value || typeof value !== "object" || Array.isArray(value)) return result;
854
+ const record = value;
855
+ if (typeof record.operation === "string") result.operation = record.operation;
856
+ for (const [key, allowed] of Object.entries({
857
+ operationStatus: [
858
+ "acknowledged",
859
+ "pending",
860
+ "completed",
861
+ "rejected",
862
+ "unknown"
863
+ ],
864
+ contactStatus: [
865
+ "created",
866
+ "updated",
867
+ "unknown"
868
+ ],
869
+ contactEvidence: [
870
+ "provider",
871
+ "inferred",
872
+ "unknown"
873
+ ],
874
+ paymentStatus: [
875
+ "unknown",
876
+ "pending",
877
+ "succeeded",
878
+ "failed"
879
+ ],
880
+ paymentEvidence: [
881
+ "provider",
882
+ "inferred",
883
+ "unknown"
884
+ ]
885
+ })) if (typeof record[key] === "string" && allowed.includes(record[key])) Object.assign(result, { [key]: record[key] });
886
+ if (record.nextAction && typeof record.nextAction === "object") {
887
+ const action = record.nextAction;
888
+ if (action.type === "redirect" || action.type === "poll" || action.type === "verify") result.nextAction = {
889
+ type: action.type,
890
+ ...typeof action.url === "string" ? { url: action.url } : {}
891
+ };
892
+ }
893
+ if (record.extensions && typeof record.extensions === "object" && !Array.isArray(record.extensions)) result.extensions = snapshot(record.extensions);
894
+ return result;
895
+ }
896
+ //#endregion
897
+ //#region src/tracking.ts
898
+ function firstDefined(values) {
899
+ return values.find((value) => value !== void 0 && value !== "");
900
+ }
901
+ function resolveValue$1(value, event) {
902
+ if (typeof value === "function") return value(snapshot(event));
903
+ if (Array.isArray(value)) return value.map((item) => resolveValue$1(item, event));
904
+ if (value && typeof value === "object") return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, resolveValue$1(item, event)]).filter(([, item]) => item !== void 0));
905
+ return value;
906
+ }
907
+ function mapTrackingEvent(config, event) {
908
+ if (config.consent && !config.consent(snapshot(event))) return null;
909
+ const name = config.events[event.type]?.(snapshot(event));
910
+ if (typeof name !== "string" || name === "") return null;
911
+ const payload = Object.fromEntries(Object.entries(config.payload ?? {}).map(([key, value]) => [key, resolveValue$1(value, event)]).filter(([, value]) => value !== void 0));
912
+ payload[config.eventKey ?? "event"] = name;
913
+ if (config.userData) {
914
+ const fields = event.request?.fields ?? {};
915
+ const eligible = event.type.startsWith("crm.") || event.type.startsWith("flow.");
916
+ payload[config.userData.key] = Object.fromEntries(Object.entries(config.userData.fields).map(([key, aliases]) => {
917
+ return [key, !eligible ? void 0 : typeof aliases === "function" ? aliases(snapshot(event)) : firstDefined(aliases.map((alias) => fields[alias]))];
918
+ }).filter(([, value]) => value !== void 0 && value !== null && value !== ""));
919
+ }
920
+ const output = config.envelope ? config.envelope(snapshot(payload), snapshot(event)) : payload;
921
+ return output ? {
922
+ name,
923
+ payload: snapshot(output)
924
+ } : null;
925
+ }
926
+ function createTrackingConsumer(options) {
927
+ const seen = /* @__PURE__ */ new Map();
928
+ function report(status) {
929
+ try {
930
+ options.diagnostic?.(status);
931
+ } catch {}
932
+ }
933
+ return function consume(event) {
934
+ let key;
935
+ try {
936
+ const { config } = options;
937
+ const mapped = mapTrackingEvent(config, event);
938
+ if (!mapped) return;
939
+ const now = options.now();
940
+ for (const [key, expires] of seen) if (expires <= now) seen.delete(key);
941
+ key = config.dedupe?.key(snapshot(event), mapped.name);
942
+ if (key !== void 0 && seen.has(key)) {
943
+ report("deduplicated");
944
+ return;
945
+ }
946
+ if (key !== void 0 && config.dedupe && config.dedupe.ttlMs > 0) {
947
+ while (seen.size >= Math.max(1, config.dedupe.maxEntries ?? 1e3)) seen.delete(seen.keys().next().value);
948
+ seen.set(key, now + config.dedupe.ttlMs);
949
+ }
950
+ if (typeof config.destination === "string") {
951
+ if (config.reset) options.queue(config.destination, snapshot(config.reset));
952
+ options.queue(config.destination, mapped.payload);
953
+ report("queued");
954
+ } else Promise.resolve(config.destination(mapped.payload, snapshot(event))).then(() => report("submitted"), () => {
955
+ if (key !== void 0) seen.delete(key);
956
+ report("failed");
957
+ });
958
+ } catch {
959
+ if (key !== void 0) seen.delete(key);
960
+ report("failed");
961
+ }
962
+ };
963
+ }
964
+ //#endregion
965
+ //#region src/flow-attempts.ts
966
+ function createAttemptStore(options) {
967
+ const prefix = `agera:attempts:${options.namespace}:`;
968
+ const indexKey = `${prefix}index`;
969
+ function report() {
970
+ try {
971
+ options.diagnostic?.();
972
+ } catch {}
973
+ }
974
+ function readIds() {
975
+ try {
976
+ const ids = JSON.parse(options.storage.getItem(indexKey) ?? "[]");
977
+ return Array.isArray(ids) ? ids.filter((id) => typeof id === "string").slice(-Math.max(1, options.maxEntries ?? 20)) : [];
978
+ } catch {
979
+ report();
980
+ return [];
981
+ }
982
+ }
983
+ function read(token) {
984
+ try {
985
+ const value = JSON.parse(options.storage.getItem(prefix + token) ?? "null");
986
+ if (!value || typeof value !== "object") return null;
987
+ const item = value;
988
+ if (item.schemaVersion !== 1 || item.token !== token || typeof item.attemptId !== "string" || typeof item.flowId !== "string" || typeof item.expectedReturn !== "string" || typeof item.expiresAt !== "number" || !Number.isFinite(item.expiresAt) || item.expiresAt <= options.now() || typeof item.acknowledged !== "boolean" || !item.source || typeof item.source.client !== "string" || !item.context || typeof item.context !== "object") {
989
+ options.storage.removeItem(prefix + token);
990
+ return null;
991
+ }
992
+ return snapshot(item);
993
+ } catch {
994
+ report();
995
+ return null;
996
+ }
997
+ }
998
+ function remove(token) {
999
+ try {
1000
+ options.storage.removeItem(prefix + token);
1001
+ return true;
1002
+ } catch {
1003
+ report();
1004
+ return false;
1005
+ }
1006
+ }
1007
+ function write(item) {
1008
+ try {
1009
+ options.storage.setItem(prefix + item.token, JSON.stringify(item));
1010
+ return true;
1011
+ } catch {
1012
+ report();
1013
+ return false;
1014
+ }
1015
+ }
1016
+ function begin(input) {
1017
+ if (!Number.isFinite(options.ttlMs) || options.ttlMs <= 0) return null;
1018
+ const attempt = {
1019
+ ...snapshot(input),
1020
+ schemaVersion: 1,
1021
+ attemptId: options.id(),
1022
+ token: options.id(),
1023
+ expiresAt: options.now() + options.ttlMs,
1024
+ acknowledged: false
1025
+ };
1026
+ const ids = readIds().filter((token) => read(token) !== null);
1027
+ while (ids.length >= Math.max(1, options.maxEntries ?? 20)) remove(ids.shift());
1028
+ if (!write(attempt)) return null;
1029
+ try {
1030
+ options.storage.setItem(indexKey, JSON.stringify([...ids, attempt.token]));
1031
+ } catch {
1032
+ remove(attempt.token);
1033
+ report();
1034
+ return null;
1035
+ }
1036
+ return snapshot(attempt);
1037
+ }
1038
+ function acknowledge(token) {
1039
+ const attempt = read(token);
1040
+ return attempt ? write({
1041
+ ...attempt,
1042
+ acknowledged: true
1043
+ }) : false;
1044
+ }
1045
+ function consume(token, destination) {
1046
+ const attempt = read(token);
1047
+ if (!attempt?.acknowledged || attempt.expectedReturn !== destination) return null;
1048
+ return remove(token) ? attempt : null;
1049
+ }
1050
+ function purge() {
1051
+ for (const token of readIds()) read(token);
1052
+ }
1053
+ return {
1054
+ begin,
1055
+ acknowledge,
1056
+ consume,
1057
+ cancel: remove,
1058
+ read,
1059
+ purge
1060
+ };
1061
+ }
1062
+ //#endregion
792
1063
  //#region src/utm.ts
793
1064
  const UTM_KEYS = [
794
1065
  "source",
@@ -1260,6 +1531,6 @@ function matchesFormat(example, value) {
1260
1531
  return example === value;
1261
1532
  }
1262
1533
  //#endregion
1263
- export { CRM_CONTACT_KEYS, VISITOR_ID_STORAGE_KEY, aggregateWeightedScores, answersChanged, assembleCrmRequest, buildContext, buildCounterPayload, buildFcrmUtms, calculateScoreResults, calculateSectionResults, calculateWinner, computeAutoTarget, createMemoryCache, createSessionStore, createStepsStore, crmFetch, decodeJwtPayload, deriveBandResults, derivePassResults, deriveQuestionState, detectDeviceType, errorMessages, evaluateNextMap, evaluatePredicate, evaluateShowIf, executeCrm, extractUtms, fetchBasinJWT, fetchCounter, flattenObject, formatCounterValue, getErrorMessagesForLanguage, getOrCreateVisitorId, getPhoneExample, getPlacesMessagesForLanguage, getPostalExample, groupCrmAnswers, inferCounterName, isCounterResponse, isCrmContactKey, isJwtExpired, isSafeRedirectUrl, matchesFormat, mergeAnswers, parseCounterUpdateAttr, parseInsertDirective, parseInsertDirectives, resolveValue, scoreExactQuestion, scorePartialQuestion, scoreQuiz, scoreQuizQuestions, serializeCrmJsonGroups, updateUrlWithParams, validators };
1534
+ export { CRM_CONTACT_KEYS, VISITOR_ID_STORAGE_KEY, aggregateWeightedScores, answersChanged, assembleCrmRequest, buildContext, buildCounterPayload, buildFcrmUtms, calculateScoreResults, calculateSectionResults, calculateWinner, computeAutoTarget, createAttemptStore, createLifecycleBus, createMemoryCache, createSessionStore, createStepsStore, createTrackingConsumer, crmFetch, decodeJwtPayload, deriveBandResults, derivePassResults, deriveQuestionState, detectDeviceType, errorMessages, evaluateNextMap, evaluatePredicate, evaluateShowIf, executeCrm, extractUtms, fetchBasinJWT, fetchCounter, firstDefined, flattenObject, formatCounterValue, getErrorMessagesForLanguage, getOrCreateVisitorId, getPhoneExample, getPlacesMessagesForLanguage, getPostalExample, groupCrmAnswers, inferCounterName, isCounterResponse, isCrmContactKey, isJwtExpired, isSafeRedirectUrl, mapTrackingEvent, matchesFormat, mergeAnswers, normalizeResult, parseCounterUpdateAttr, parseInsertDirective, parseInsertDirectives, resolveValue, scoreExactQuestion, scorePartialQuestion, scoreQuiz, scoreQuizQuestions, serializeCrmJsonGroups, snapshot, unknownResult, updateUrlWithParams, validators };
1264
1535
 
1265
1536
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reform-society/agera-core",
3
- "version": "0.3.0",
3
+ "version": "0.5.0",
4
4
  "description": "DOM-free core logic for Agera",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",