@reform-society/agera-core 0.1.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.
Files changed (3) hide show
  1. package/dist/index.d.ts +385 -0
  2. package/dist/index.js +1122 -0
  3. package/package.json +45 -0
@@ -0,0 +1,385 @@
1
+ import * as _$nanostores from "nanostores";
2
+
3
+ //#region src/types.d.ts
4
+ type PredicateOp = "eq" | "neq" | "in" | "nin" | "gt" | "gte" | "lt" | "lte" | "exists" | "truthy" | "falsy" | "contains" | "starts_with" | "ends_with";
5
+ type SimplePredicate = {
6
+ field: string;
7
+ op: PredicateOp;
8
+ value?: unknown;
9
+ };
10
+ type CompositePredicate = {
11
+ all?: Predicate[];
12
+ any?: Predicate[];
13
+ not?: Predicate;
14
+ };
15
+ type Predicate = SimplePredicate | CompositePredicate;
16
+ type Validators = {
17
+ required(val: string): boolean;
18
+ email(val: string): boolean;
19
+ name(val: string): boolean;
20
+ pattern(val: string, re: string): boolean;
21
+ min(val: string, n: string): boolean;
22
+ max(val: string, n: string): boolean;
23
+ };
24
+ type QuestionMetrics = {
25
+ displayedAt: Date;
26
+ firstFocusedAt?: Date;
27
+ firstAnsweredAt?: Date;
28
+ lastEditedAt?: Date;
29
+ };
30
+ type QuizQuestionModel = "single_select" | "multi_select";
31
+ type QuizScoringModel = "weighted" | "exact" | "partial";
32
+ type QuizOutcomeModel = "score" | "weighted" | "pass" | "band" | "sections";
33
+ type QuizQuestionState = "unanswered" | "correct" | "partial" | "incorrect";
34
+ type QuizQuestionResult = {
35
+ key: string;
36
+ model: QuizQuestionModel;
37
+ section: string | null;
38
+ eligible: boolean;
39
+ answeredValues: string[];
40
+ answeredLabels: string[];
41
+ expectedValues: string[] | null;
42
+ expectedLabels: string[] | null;
43
+ state: QuizQuestionState;
44
+ earnedPoints: number;
45
+ possiblePoints: number;
46
+ };
47
+ type ScoreQuizResults = {
48
+ earnedPoints: number;
49
+ possiblePoints: number;
50
+ percent: number;
51
+ eligibleCount: number;
52
+ correctCount: number;
53
+ partialCount: number;
54
+ incorrectCount: number;
55
+ unansweredCount: number;
56
+ };
57
+ type WeightedQuizResults = {
58
+ scores: Record<string, number>;
59
+ winner: string | null;
60
+ winnerScore: number;
61
+ ties: string[];
62
+ };
63
+ type PassQuizResults = {
64
+ passed: boolean;
65
+ label: "pass" | "fail";
66
+ };
67
+ type BandQuizResults = {
68
+ id: string | null;
69
+ label: string | null;
70
+ };
71
+ type QuizSectionResults = {
72
+ score: ScoreQuizResults | null;
73
+ weighted: WeightedQuizResults | null;
74
+ pass: PassQuizResults | null;
75
+ band: BandQuizResults | null;
76
+ };
77
+ type QuizResults = {
78
+ activeQuestionModels: QuizQuestionModel[];
79
+ activeScoringModels: QuizScoringModel[];
80
+ activeOutcomes: QuizOutcomeModel[];
81
+ questions: Record<string, QuizQuestionResult>;
82
+ score: ScoreQuizResults | null;
83
+ weighted: WeightedQuizResults | null;
84
+ pass: PassQuizResults | null;
85
+ band: BandQuizResults | null;
86
+ sections: Record<string, QuizSectionResults>;
87
+ };
88
+ type QuizPassFailConfig = {
89
+ percentGte: number;
90
+ };
91
+ type QuizBandDefinition = {
92
+ id: string;
93
+ label: string;
94
+ minPercent?: number;
95
+ maxPercent?: number;
96
+ };
97
+ type QuizSectionConfig = {
98
+ passFail?: QuizPassFailConfig | null;
99
+ bands?: QuizBandDefinition[] | null;
100
+ };
101
+ type QuizConfig = {
102
+ passFail?: QuizPassFailConfig | null;
103
+ bands?: QuizBandDefinition[] | null;
104
+ sections?: Record<string, QuizSectionConfig> | null;
105
+ };
106
+ type QuizQuestionInput = {
107
+ key: string;
108
+ model: QuizQuestionModel;
109
+ section: string | null;
110
+ eligible: boolean;
111
+ invalid?: boolean;
112
+ answeredValues: string[];
113
+ answeredLabels: string[];
114
+ expectedValues: string[] | null;
115
+ expectedLabels: string[] | null;
116
+ scoringModel: Exclude<QuizScoringModel, "weighted"> | null;
117
+ usesWeightedScoring: boolean;
118
+ weightedScores: Record<string, number>;
119
+ };
120
+ type SessionState = {
121
+ id: string;
122
+ clientId?: string;
123
+ surveyId?: string;
124
+ answers: Record<string, unknown>;
125
+ quiz?: QuizResults | WeightedQuizResults;
126
+ anonymousEmail?: string;
127
+ startedAt: Date;
128
+ };
129
+ type StepState = {
130
+ current: string;
131
+ path: string[];
132
+ };
133
+ type SurveyOptions = {
134
+ siteId?: string;
135
+ debug?: boolean;
136
+ };
137
+ type ProgressModeInfo = {
138
+ current: number;
139
+ total: number;
140
+ percent: number;
141
+ };
142
+ type ProgressInfo = {
143
+ viewing: ProgressModeInfo;
144
+ completed: ProgressModeInfo;
145
+ };
146
+ type ValidationRule = "required" | "email" | "name" | "phone" | "pattern" | "min" | "max" | "minValue" | "maxValue";
147
+ type ErrorMessages = Record<ValidationRule, string>;
148
+ //#endregion
149
+ //#region src/stores.d.ts
150
+ declare function createSessionStore(initial?: Partial<SessionState>): _$nanostores.PreinitializedWritableAtom<SessionState> & object;
151
+ declare function createStepsStore(initial?: Partial<StepState>): _$nanostores.PreinitializedWritableAtom<StepState> & object;
152
+ //#endregion
153
+ //#region src/resolve.d.ts
154
+ type ResolveValueSources = {
155
+ queryParams?: URLSearchParams;
156
+ storage?: Record<string, string>;
157
+ crmResponse?: Record<string, unknown>;
158
+ env?: {
159
+ device?: "mobile" | "tablet" | "desktop" | "tv";
160
+ utm?: Record<string, string>;
161
+ };
162
+ };
163
+ declare function resolveValue(field: string, answers: Record<string, unknown>, sources?: ResolveValueSources): unknown;
164
+ //#endregion
165
+ //#region src/answers.d.ts
166
+ declare function mergeAnswers(previous: Record<string, unknown>, dom: Record<string, unknown>, preserveKeys?: Set<string>): Record<string, unknown>;
167
+ declare function answersChanged(previous: Record<string, unknown>, next: Record<string, unknown>): boolean;
168
+ //#endregion
169
+ //#region src/predicates.d.ts
170
+ declare function evaluatePredicate(predicate: Predicate, answers: Record<string, unknown>, sources?: ResolveValueSources): boolean;
171
+ declare function evaluateShowIf(predicateJson: string, answers: Record<string, unknown>, sources?: ResolveValueSources): boolean;
172
+ declare function evaluateNextMap(nextMapJson: string, answers: Record<string, unknown>, sources?: ResolveValueSources): string | null;
173
+ //#endregion
174
+ //#region src/validators.d.ts
175
+ declare const validators: Validators;
176
+ //#endregion
177
+ //#region src/validation-messages.d.ts
178
+ type PlacesMessageKey = "hint" | "noResults" | "validate" | "manual" | "backToSearch" | "manualValidate" | "postalErr";
179
+ type PlacesMessages = Record<PlacesMessageKey, string>;
180
+ declare const errorMessages: Record<string, ErrorMessages>;
181
+ declare function getPhoneExample(region?: string, format?: string): string;
182
+ declare function getPostalExample(region?: string): string;
183
+ declare function getPlacesMessagesForLanguage(lang?: string, region?: string): PlacesMessages;
184
+ /**
185
+ * Gets error messages for a given language tag.
186
+ * Falls back to English if language is not found.
187
+ */
188
+ declare function getErrorMessagesForLanguage(lang?: string): ErrorMessages;
189
+ //#endregion
190
+ //#region src/quiz.d.ts
191
+ /**
192
+ * Calculate the winner from scores, handling ties
193
+ */
194
+ declare function calculateWinner(scores: Record<string, number>): WeightedQuizResults;
195
+ declare function deriveQuestionState(answeredValues: string[], earnedPoints: number, possiblePoints: number): QuizQuestionState;
196
+ declare function scoreExactQuestion(question: QuizQuestionInput): QuizQuestionResult | null;
197
+ declare function scorePartialQuestion(question: QuizQuestionInput): QuizQuestionResult | null;
198
+ declare function scoreQuizQuestions(questions: QuizQuestionInput[]): Record<string, QuizQuestionResult>;
199
+ declare function calculateScoreResults(questionResults: QuizQuestionResult[]): ScoreQuizResults | null;
200
+ declare function aggregateWeightedScores(questions: QuizQuestionInput[]): WeightedQuizResults | null;
201
+ declare function derivePassResults(scoreResults: ScoreQuizResults | null, config?: QuizConfig["passFail"]): PassQuizResults | null;
202
+ declare function deriveBandResults(scoreResults: ScoreQuizResults | null, bands?: QuizBandDefinition[] | null): BandQuizResults | null;
203
+ declare function calculateSectionResults(questions: QuizQuestionInput[], questionResults: Record<string, QuizQuestionResult>, config?: QuizConfig): Record<string, QuizSectionResults>;
204
+ declare function scoreQuiz(questions: QuizQuestionInput[], config?: QuizConfig): QuizResults;
205
+ //#endregion
206
+ //#region src/basin-client.d.ts
207
+ /** Check if JWT is expired (with 60s buffer) */
208
+ declare function isJwtExpired(jwt: string): boolean;
209
+ type StorageAccessor = {
210
+ getItem(key: string): string | null;
211
+ setItem(key: string, value: string): void;
212
+ removeItem(key: string): void;
213
+ };
214
+ declare function fetchBasinJWT(endpoint: string, storage: StorageAccessor, storageKey: string): Promise<string>;
215
+ //#endregion
216
+ //#region src/crm-types.d.ts
217
+ type CounterUpdateConfig = {
218
+ name: string;
219
+ add_amount?: number;
220
+ add_amount_field?: string;
221
+ };
222
+ type CounterDisplayConfig = {
223
+ target?: number;
224
+ auto_target?: boolean;
225
+ hide_below?: number;
226
+ remove_below?: number;
227
+ locale?: string;
228
+ notation?: "standard" | "compact";
229
+ use_grouping?: boolean;
230
+ };
231
+ type ShareConfig = {
232
+ platform: "facebook" | "twitter" | "linkedin" | "email" | "copy" | "native";
233
+ url?: string;
234
+ text?: string;
235
+ hashtags?: string;
236
+ };
237
+ type SplitConfig = {
238
+ variants: string[];
239
+ weights?: number[];
240
+ storage_key?: string;
241
+ };
242
+ type CrmFrontendKey = "wait_for_response" | "show_success" | "redirect_url" | "redirect_utm" | "redirect_params" | "follow_redirect" | "json_groups" | "counter_update" | "method";
243
+ type CrmConfig = {
244
+ wait_for_response?: boolean;
245
+ show_success?: boolean;
246
+ redirect_url?: string;
247
+ redirect_utm?: boolean;
248
+ redirect_params?: boolean;
249
+ follow_redirect?: boolean;
250
+ json_groups?: string[];
251
+ counter_update?: CounterUpdateConfig[];
252
+ method?: "POST" | "PATCH" | "PUT";
253
+ [key: string]: unknown;
254
+ };
255
+ type CrmV2Request = {
256
+ body: Record<string, unknown>;
257
+ source: string;
258
+ utms?: Record<string, string>;
259
+ query_params?: Record<string, string>;
260
+ context?: Record<string, unknown>;
261
+ };
262
+ type CrmV2PatchRequest = CrmV2Request & {
263
+ response: Record<string, unknown>;
264
+ };
265
+ type CrmFetchResult = {
266
+ ok: boolean;
267
+ status: number;
268
+ data: Record<string, unknown> | null;
269
+ };
270
+ //#endregion
271
+ //#region src/utm.d.ts
272
+ declare const UTM_KEYS: readonly ["source", "campaign", "medium", "content", "term", "wec"];
273
+ type Utms = Partial<Record<(typeof UTM_KEYS)[number], string>>;
274
+ declare function extractUtms(search: string): Utms;
275
+ declare function buildFcrmUtms(utms: Utms): Record<string, string>;
276
+ //#endregion
277
+ //#region src/url-utils.d.ts
278
+ /** Appends query params to a URL without overriding existing ones. */
279
+ declare function updateUrlWithParams(url: string, params: URLSearchParams, base?: string): string;
280
+ //#endregion
281
+ //#region src/memory-cache.d.ts
282
+ type MemoryCacheOptions = {
283
+ max?: number;
284
+ ttlMs?: number;
285
+ now?: () => number;
286
+ };
287
+ type MemoryCacheSetOptions = {
288
+ ttlMs?: number;
289
+ };
290
+ type MemoryCache<Key, Value> = {
291
+ get: (key: Key) => Value | undefined;
292
+ set: (key: Key, value: Value, options?: MemoryCacheSetOptions) => Value;
293
+ has: (key: Key) => boolean;
294
+ delete: (key: Key) => boolean;
295
+ clear: () => void;
296
+ size: () => number;
297
+ };
298
+ declare function createMemoryCache<Key, Value>(options?: MemoryCacheOptions): MemoryCache<Key, Value>;
299
+ //#endregion
300
+ //#region src/flatten.d.ts
301
+ declare function flattenObject(obj: Record<string, unknown>, prefix?: string): Record<string, unknown>;
302
+ //#endregion
303
+ //#region src/counter.d.ts
304
+ declare function inferCounterName(client: string, pathname: string): string;
305
+ declare function parseCounterUpdateAttr(value: string | null, client: string, pathname: string): CounterUpdateConfig[];
306
+ type CounterResponse = {
307
+ count: number;
308
+ name: string;
309
+ };
310
+ type CounterPayload = {
311
+ name: string;
312
+ body: Record<string, unknown>;
313
+ };
314
+ declare function buildCounterPayload(config: CounterUpdateConfig, context?: {
315
+ source_url?: string;
316
+ }): CounterPayload;
317
+ //#endregion
318
+ //#region src/counter-display.d.ts
319
+ declare function computeAutoTarget(current: number): number;
320
+ declare function formatCounterValue(value: number, locale?: string, notation?: "standard" | "compact", useGrouping?: boolean): string;
321
+ //#endregion
322
+ //#region src/insert.d.ts
323
+ type InsertDirective = {
324
+ source: string;
325
+ key: string;
326
+ };
327
+ declare function parseInsertDirective(value: string): InsertDirective | null;
328
+ declare function parseInsertDirectives(value: string): InsertDirective[];
329
+ //#endregion
330
+ //#region src/crm-context.d.ts
331
+ declare function buildContext(config: Partial<CrmConfig>, frontendKeys: ReadonlySet<string>, counters?: CounterUpdateConfig[]): Record<string, unknown>;
332
+ //#endregion
333
+ //#region src/crm-utils.d.ts
334
+ declare function isCounterResponse(data: Record<string, unknown>): boolean;
335
+ declare function isSafeRedirectUrl(url: string): boolean;
336
+ //#endregion
337
+ //#region src/counter-fetch.d.ts
338
+ declare function fetchCounter(name: string, siteId: string, apiBaseUrl: string, sourceUrl: string): Promise<CounterResponse>;
339
+ //#endregion
340
+ //#region src/device.d.ts
341
+ type DeviceType = "mobile" | "tablet" | "desktop";
342
+ type DeviceInput = {
343
+ userAgent?: string;
344
+ maxTouchPoints?: number;
345
+ screenWidth?: number;
346
+ uaDataMobile?: boolean;
347
+ };
348
+ declare function detectDeviceType(input: DeviceInput): DeviceType;
349
+ //#endregion
350
+ //#region src/crm-fetch.d.ts
351
+ type CrmFetchOptions = {
352
+ waitForResponse?: boolean;
353
+ sourceUrl?: string;
354
+ deviceType?: DeviceType;
355
+ method?: "POST" | "PATCH" | "PUT";
356
+ };
357
+ declare function crmFetch(url: string, payload: Record<string, unknown> | object, options?: CrmFetchOptions): Promise<CrmFetchResult>;
358
+ //#endregion
359
+ //#region src/crm-request.d.ts
360
+ type AssembleCrmRequestParams = {
361
+ body: Record<string, unknown>;
362
+ config: Partial<CrmConfig>;
363
+ frontendKeys: ReadonlySet<string>;
364
+ utms: Utms;
365
+ queryParams: Record<string, string>;
366
+ sourceUrl: string;
367
+ counters?: CounterUpdateConfig[];
368
+ jsonGroups?: Record<string, Record<string, string>>;
369
+ };
370
+ declare function assembleCrmRequest({
371
+ body: rawBody,
372
+ config,
373
+ frontendKeys,
374
+ utms,
375
+ queryParams,
376
+ sourceUrl,
377
+ counters,
378
+ jsonGroups
379
+ }: AssembleCrmRequestParams): CrmV2Request;
380
+ //#endregion
381
+ //#region src/polling.d.ts
382
+ declare function matchesFormat(example: unknown, value: unknown): boolean;
383
+ //#endregion
384
+ export { type AssembleCrmRequestParams, type BandQuizResults, type CompositePredicate, type CounterDisplayConfig, type CounterPayload, type CounterResponse, type CounterUpdateConfig, type CrmConfig, type CrmFetchOptions, type CrmFetchResult, type CrmFrontendKey, type CrmV2PatchRequest, type CrmV2Request, type DeviceInput, type DeviceType, type ErrorMessages, type InsertDirective, 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, type ValidationRule, type Validators, type WeightedQuizResults, aggregateWeightedScores, answersChanged, assembleCrmRequest, buildContext, buildCounterPayload, buildFcrmUtms, calculateScoreResults, calculateSectionResults, calculateWinner, computeAutoTarget, createMemoryCache, createSessionStore, createStepsStore, crmFetch, deriveBandResults, derivePassResults, deriveQuestionState, detectDeviceType, errorMessages, evaluateNextMap, evaluatePredicate, evaluateShowIf, extractUtms, fetchBasinJWT, fetchCounter, flattenObject, formatCounterValue, getErrorMessagesForLanguage, getPhoneExample, getPlacesMessagesForLanguage, getPostalExample, inferCounterName, isCounterResponse, isJwtExpired, isSafeRedirectUrl, matchesFormat, mergeAnswers, parseCounterUpdateAttr, parseInsertDirective, parseInsertDirectives, resolveValue, scoreExactQuestion, scorePartialQuestion, scoreQuiz, scoreQuizQuestions, updateUrlWithParams, validators };
385
+ //# sourceMappingURL=index.d.ts.map