@form-engine-ts/core 2.5.0 → 2.6.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.cts CHANGED
@@ -1,3 +1,90 @@
1
+ type Result<T, E> = {
2
+ readonly success: true;
3
+ readonly value: T;
4
+ } | {
5
+ readonly success: false;
6
+ readonly error: E;
7
+ };
8
+ type FormVersionStatus = "draft" | "published" | "archived";
9
+ interface FormVersionRecord extends ExtensibleNode {
10
+ readonly formId: string;
11
+ readonly version: number;
12
+ readonly status: FormVersionStatus;
13
+ readonly schema: FormSchema;
14
+ readonly revision: number;
15
+ readonly createdFromVersion?: number;
16
+ readonly createdAt: string;
17
+ readonly publishedAt?: string;
18
+ readonly archivedAt?: string;
19
+ }
20
+ interface FormVersionState {
21
+ readonly formId: string;
22
+ readonly draftVersion?: number;
23
+ readonly publishedVersion?: number;
24
+ readonly nextVersion: number;
25
+ readonly revision: number;
26
+ }
27
+ type VersionTransitionError = {
28
+ readonly type: "draft_already_exists";
29
+ readonly currentDraftVersion: number;
30
+ } | {
31
+ readonly type: "draft_not_found";
32
+ } | {
33
+ readonly type: "revision_conflict";
34
+ readonly expectedRevision: number;
35
+ readonly actualRevision: number;
36
+ } | {
37
+ readonly type: "invalid_source_version";
38
+ readonly requestedVersion: number;
39
+ readonly publishedVersion?: number;
40
+ } | {
41
+ readonly type: "version_immutable";
42
+ readonly status: FormVersionStatus;
43
+ } | {
44
+ readonly type: "max_version_exceeded";
45
+ readonly max: number;
46
+ } | {
47
+ readonly type: "validation_failed";
48
+ readonly issues: readonly SchemaIssue[];
49
+ };
50
+ interface CloneVersionOptions {
51
+ readonly maxVersions?: number;
52
+ readonly expectedRevision?: number;
53
+ /** Additional known published versions that may be used as a clone source. */
54
+ readonly allowedSourceVersions?: readonly number[];
55
+ }
56
+ interface PublishDraftOptions {
57
+ readonly expectedRevision?: number;
58
+ readonly currentPublishedRecord?: FormVersionRecord;
59
+ readonly validate?: (schema: FormSchema) => boolean | Promise<boolean> | readonly SchemaIssue[] | Promise<readonly SchemaIssue[]>;
60
+ readonly publishedAt?: string;
61
+ /** @deprecated Use publishedAt. */
62
+ readonly timestamp?: string;
63
+ }
64
+ interface DeleteDraftOptions {
65
+ readonly expectedRevision?: number;
66
+ }
67
+ interface PublishDraftResult {
68
+ readonly nextState: FormVersionState;
69
+ readonly publishedRecord: FormVersionRecord;
70
+ readonly archivedRecords: readonly FormVersionRecord[];
71
+ /** @deprecated Read archivedRecords instead. */
72
+ readonly archivedVersion?: number;
73
+ }
74
+ declare function cloneVersionToDraft(state: FormVersionState, sourceSchema: FormSchema, options?: CloneVersionOptions): Result<{
75
+ readonly nextState: FormVersionState;
76
+ readonly draftSchema: FormSchema;
77
+ }, VersionTransitionError>;
78
+ declare function publishDraft(state: FormVersionState, draftSchema: FormSchema, options?: PublishDraftOptions): Promise<Result<PublishDraftResult, VersionTransitionError>>;
79
+ declare function createPublishTransitionPlan(state: FormVersionState, draftRecord: FormVersionRecord, options?: PublishDraftOptions): Promise<Result<{
80
+ readonly nextState: FormVersionState;
81
+ readonly plan: VersionTransitionPlan;
82
+ }, VersionTransitionError>>;
83
+ declare function deleteDraft(state: FormVersionState, options?: DeleteDraftOptions): Result<{
84
+ readonly nextState: FormVersionState;
85
+ }, VersionTransitionError>;
86
+ declare function assertVersionMutable(status: FormVersionStatus): void;
87
+
1
88
  type FieldType = "text" | "textarea" | "number" | "rating" | "select" | "multi-select" | "checkbox" | "radio";
2
89
  interface FormPolicy {
3
90
  readonly allowedFieldTypes?: readonly FieldType[];
@@ -170,6 +257,8 @@ interface SubmissionPageQueryOptions {
170
257
  readonly since?: string;
171
258
  readonly until?: string;
172
259
  readonly locale?: string;
260
+ readonly filter?: (submission: FormSubmission) => boolean;
261
+ readonly metadataFilters?: Readonly<Record<string, JsonValue>>;
173
262
  }
174
263
  interface SubmissionPage {
175
264
  readonly items: readonly FormSubmission[];
@@ -179,6 +268,22 @@ interface SubmissionPage {
179
268
  interface PagedSubmissionStorageAdapter extends FormStorageAdapter {
180
269
  listSubmissionPage(formId: string, options?: SubmissionPageQueryOptions): Promise<SubmissionPage>;
181
270
  }
271
+ interface VersionTransitionPlan {
272
+ readonly formId: string;
273
+ readonly expectedRevision: number;
274
+ readonly nextRevision: number;
275
+ readonly draftToCreate?: FormVersionRecord;
276
+ readonly draftToDeleteVersion?: number;
277
+ readonly publishedRecordToSave?: FormVersionRecord;
278
+ readonly archivedRecordsToSave?: readonly FormVersionRecord[];
279
+ readonly timestamp: string;
280
+ }
281
+ interface VersionedFormStorageAdapter extends FormStorageAdapter {
282
+ commitVersionTransition(plan: VersionTransitionPlan): Promise<{
283
+ readonly success: boolean;
284
+ readonly error?: string;
285
+ }>;
286
+ }
182
287
  interface BaseQuestionAggregate {
183
288
  readonly fieldId: string;
184
289
  readonly answeredCount: number;
@@ -223,6 +328,7 @@ type ChoiceOption = FieldOption;
223
328
  interface FormResponse extends ExtensibleNode {
224
329
  readonly responseId: string;
225
330
  readonly formId: string;
331
+ readonly formVersion?: number;
226
332
  readonly sourceLocale?: string;
227
333
  readonly answers: Readonly<Record<string, unknown>>;
228
334
  readonly submittedAt: string;
@@ -251,14 +357,25 @@ declare function calculateNumericSummary(responses: readonly FormSubmission[], q
251
357
  declare function calculateCrossTabulation(responses: readonly FormSubmission[], rowQuestionId: string, colQuestionId: string): CrossTabulationResult;
252
358
  declare function aggregateResponses(schema: FormSchema, submissions: readonly FormSubmission[]): FormAnalytics;
253
359
  type AccumulatorResponse = FormSubmission | FormResponse;
360
+ type AccumulatorSkipReason = "form_id_mismatch" | "version_mismatch" | "invalid_structure";
361
+ interface AccumulatorReport {
362
+ readonly processedCount: number;
363
+ readonly skippedCount: number;
364
+ readonly skipReasons: readonly {
365
+ readonly responseId: string;
366
+ readonly reason: AccumulatorSkipReason;
367
+ }[];
368
+ }
254
369
  interface ResponseAccumulator {
255
370
  add(submission: AccumulatorResponse): {
256
371
  readonly success: boolean;
372
+ readonly skipped?: boolean;
257
373
  readonly error?: string;
258
374
  };
259
- addMany(submissions: Iterable<AccumulatorResponse>): void;
375
+ addMany(submissions: Iterable<AccumulatorResponse>): AccumulatorReport;
260
376
  merge(other: ResponseAccumulator): ResponseAccumulator;
261
377
  finalize(): FormAnalytics;
378
+ getReport(): AccumulatorReport;
262
379
  }
263
380
  interface ResponseAccumulatorOptions {
264
381
  readonly mode?: "strict" | "lenient";
@@ -271,13 +388,27 @@ interface CsvExportOptions {
271
388
  }
272
389
  interface CsvColumnDef {
273
390
  readonly header: string;
274
- readonly getValue: (submission: FormResponse) => string | number | boolean | null | undefined;
391
+ readonly getValue: (context: CsvColumnContext) => string | number | boolean | null | undefined | Promise<string | number | boolean | null | undefined>;
392
+ }
393
+ interface CsvColumnContext extends FormResponse {
394
+ readonly submission: FormResponse;
395
+ readonly formVersion: number;
396
+ readonly schema: FormSchema;
275
397
  }
276
398
  interface StreamCsvOptions extends CsvExportOptions {
277
399
  readonly columns?: readonly CsvColumnDef[];
278
400
  readonly includeDefaultColumns?: boolean;
279
401
  }
280
402
  declare function exportResponsesToCsvStream(schema: FormSchema, submissions: AsyncIterable<AccumulatorResponse>, options?: StreamCsvOptions): AsyncIterable<string>;
403
+ interface NodeWritableStream {
404
+ write(chunk: Uint8Array): boolean;
405
+ once(event: "drain", listener: () => void): unknown;
406
+ once(event: "error", listener: (error: Error) => void): unknown;
407
+ removeListener(event: "drain", listener: () => void): unknown;
408
+ removeListener(event: "error", listener: (error: Error) => void): unknown;
409
+ end(callback: () => void): unknown;
410
+ }
411
+ declare function pipeResponsesToCsvStream(schema: FormSchema, submissions: AsyncIterable<AccumulatorResponse>, writable: WritableStream<Uint8Array> | NodeWritableStream, options?: StreamCsvOptions): Promise<void>;
281
412
  declare function exportResponsesToCsv(schema: FormSchema, responses: readonly FormSubmission[], options?: CsvExportOptions): string;
282
413
 
283
414
  type FormEventType = "response.submitted" | "schema.updated";
@@ -314,6 +445,7 @@ interface SubmissionCursorValue {
314
445
  declare function encodeSubmissionCursor(value: SubmissionCursorValue): string;
315
446
  declare function decodeSubmissionCursor(cursor: string): SubmissionCursorValue;
316
447
  declare function normalizeSubmissionPageSize(pageSize: number | undefined, fallback?: number): number;
448
+ declare function matchesSubmissionPageFilters(submission: FormSubmission, options: Pick<SubmissionPageQueryOptions, "filter" | "metadataFilters">): boolean;
317
449
 
318
450
  interface CollectedLocales {
319
451
  readonly defaultLocale?: string;
@@ -382,73 +514,10 @@ declare function resolveFormTranslation(schema: FormSchema, adapter: AsyncTransl
382
514
  declare function validateAnswers(schema: FormSchema, values: FormValues): AnswerValidationResult;
383
515
  declare function validatePageAnswers(schema: FormSchema, pageIndex: number, values: FormValues): AnswerValidationResult;
384
516
 
385
- type Result<T, E> = {
386
- readonly success: true;
387
- readonly value: T;
388
- } | {
389
- readonly success: false;
390
- readonly error: E;
391
- };
392
- type FormVersionStatus = "draft" | "published" | "archived";
393
- interface FormVersionRecord {
394
- readonly formId: string;
395
- readonly version: number;
396
- readonly status: FormVersionStatus;
397
- readonly schema: FormSchema;
398
- readonly createdAt: string;
399
- readonly publishedAt?: string;
400
- readonly archivedAt?: string;
401
- }
402
- interface FormVersionState {
403
- readonly formId: string;
404
- readonly draftVersion?: number;
405
- readonly publishedVersion?: number;
406
- readonly nextVersion: number;
407
- readonly revision: number;
408
- }
409
- type VersionTransitionError = {
410
- readonly type: "draft_already_exists";
411
- readonly currentDraftVersion: number;
412
- } | {
413
- readonly type: "draft_not_found";
414
- } | {
415
- readonly type: "revision_conflict";
416
- readonly expectedRevision: number;
417
- readonly actualRevision: number;
418
- } | {
419
- readonly type: "version_immutable";
420
- readonly status: FormVersionStatus;
421
- } | {
422
- readonly type: "max_version_exceeded";
423
- readonly max: number;
424
- };
425
- interface CloneVersionOptions {
426
- readonly maxVersions?: number;
427
- }
428
- interface PublishDraftOptions {
429
- readonly expectedRevision?: number;
430
- readonly validate?: (schema: FormSchema) => boolean;
431
- /** Supplies deterministic record timestamps while keeping the transition pure. */
432
- readonly timestamp?: string;
433
- }
434
- declare function cloneVersionToDraft(state: FormVersionState, sourceSchema: FormSchema, options?: CloneVersionOptions): Result<{
435
- readonly nextState: FormVersionState;
436
- readonly draftSchema: FormSchema;
437
- }, VersionTransitionError>;
438
- declare function publishDraft(state: FormVersionState, draftSchema: FormSchema, options?: PublishDraftOptions): Result<{
439
- readonly nextState: FormVersionState;
440
- readonly publishedRecord: FormVersionRecord;
441
- readonly archivedVersion?: number;
442
- }, VersionTransitionError>;
443
- declare function deleteDraft(state: FormVersionState): Result<{
444
- readonly nextState: FormVersionState;
445
- }, VersionTransitionError>;
446
- declare function assertVersionMutable(status: FormVersionStatus): void;
447
-
448
517
  declare function isQuestionVisible(question: FormField, currentAnswers: Readonly<Record<string, unknown>>): boolean;
449
518
  declare function isDisplayConditionSatisfied(condition: DisplayCondition | undefined, currentAnswers: Readonly<Record<string, unknown>>): boolean;
450
519
  declare function calculatePageVisibility(schema: FormSchema, currentAnswers: Readonly<Record<string, unknown>>): Readonly<Record<string, boolean>>;
451
520
  declare function calculateFieldVisibility(schema: FormSchema, currentAnswers: Readonly<Record<string, unknown>>): Readonly<Record<string, boolean>>;
452
521
  declare function selectVisibleAnswers(schema: FormSchema, currentAnswers: FormValues): FormValues;
453
522
 
454
- export { type AccumulatorResponse, type AnswerValidationResult, type AsyncTranslationAdapter, type BaseField, type CheckboxField, type CheckboxQuestionAggregate, type ChoiceDistributionEntry, type ChoiceOption, type ChoiceQuestionAggregate, type CloneVersionOptions, type CollectedLocales, type ConditionOperator, type ConditionValue, type CreateSubmissionOptions, type CrossTabulationResult, type CsvColumnDef, type CsvExportOptions, type DisplayCondition, type ExtensibleNode, type FieldOption, type FieldType, type FormAnalytics, type FormEvent, type FormEventType, type FormField, type FormPage, type FormPolicy, type FormResponse, type FormSchema, type FormStorageAdapter, type FormSubmission, type FormValue, type FormValues, type FormVersionRecord, type FormVersionState, type FormVersionStatus, type JsonValue, type LocalizedText, type MultiSelectField, type NumberField, type NumberQuestionAggregate, type NumericSummary, type OptionAggregate, type PagedSubmissionStorageAdapter, type PopulateTranslationOptions, type PublishDraftOptions, type Question, type QuestionAggregate, type QuestionType, type RatingField, type ResponseAccumulator, type ResponseAccumulatorOptions, type Result, type SchemaIssue, type SchemaStructureIssue, type SchemaStructureIssueType, type SchemaTranslations, type SchemaValidationResult, type SelectField, type StorageAdapter, type StreamCsvOptions, type SubmissionCursorValue, type SubmissionPage, type SubmissionPageQueryOptions, type SubmissionQueryOptions, type TextField, type TextQuestionAggregate, type TranslationAdapter, type TranslationReport, type TranslationSlot, type ValidateFormSchemaOptions, type ValidationCode, type ValidationError, type ValidationIssue, type VersionTransitionError, type WebhookConfig, type WebhookDispatchResult, aggregateResponses, assertValidFormSchema, assertVersionMutable, calculateChoiceDistribution, calculateCrossTabulation, calculateFieldVisibility, calculateNumericSummary, calculatePageVisibility, cloneVersionToDraft, collectSchemaLocales, createResponseAccumulator, createSubmission, decodeSubmissionCursor, deleteDraft, dispatchWebhook, encodeSubmissionCursor, escapeCsvCell, exportResponsesToCsv, exportResponsesToCsvStream, isDisplayConditionSatisfied, isQuestionVisible, normalizeSubmissionPageSize, populateSchemaTranslations, publishDraft, resolveFormTranslation, resolveLocalizedSchema, sanitizeSchema, selectVisibleAnswers, transformFieldType, validateAnswers, validateFormSchema, validatePageAnswers, validateSchemaStructure };
523
+ export { type AccumulatorReport, type AccumulatorResponse, type AccumulatorSkipReason, type AnswerValidationResult, type AsyncTranslationAdapter, type BaseField, type CheckboxField, type CheckboxQuestionAggregate, type ChoiceDistributionEntry, type ChoiceOption, type ChoiceQuestionAggregate, type CloneVersionOptions, type CollectedLocales, type ConditionOperator, type ConditionValue, type CreateSubmissionOptions, type CrossTabulationResult, type CsvColumnContext, type CsvColumnDef, type CsvExportOptions, type DeleteDraftOptions, type DisplayCondition, type ExtensibleNode, type FieldOption, type FieldType, type FormAnalytics, type FormEvent, type FormEventType, type FormField, type FormPage, type FormPolicy, type FormResponse, type FormSchema, type FormStorageAdapter, type FormSubmission, type FormValue, type FormValues, type FormVersionRecord, type FormVersionState, type FormVersionStatus, type JsonValue, type LocalizedText, type MultiSelectField, type NodeWritableStream, type NumberField, type NumberQuestionAggregate, type NumericSummary, type OptionAggregate, type PagedSubmissionStorageAdapter, type PopulateTranslationOptions, type PublishDraftOptions, type PublishDraftResult, type Question, type QuestionAggregate, type QuestionType, type RatingField, type ResponseAccumulator, type ResponseAccumulatorOptions, type Result, type SchemaIssue, type SchemaStructureIssue, type SchemaStructureIssueType, type SchemaTranslations, type SchemaValidationResult, type SelectField, type StorageAdapter, type StreamCsvOptions, type SubmissionCursorValue, type SubmissionPage, type SubmissionPageQueryOptions, type SubmissionQueryOptions, type TextField, type TextQuestionAggregate, type TranslationAdapter, type TranslationReport, type TranslationSlot, type ValidateFormSchemaOptions, type ValidationCode, type ValidationError, type ValidationIssue, type VersionTransitionError, type VersionTransitionPlan, type VersionedFormStorageAdapter, type WebhookConfig, type WebhookDispatchResult, aggregateResponses, assertValidFormSchema, assertVersionMutable, calculateChoiceDistribution, calculateCrossTabulation, calculateFieldVisibility, calculateNumericSummary, calculatePageVisibility, cloneVersionToDraft, collectSchemaLocales, createPublishTransitionPlan, createResponseAccumulator, createSubmission, decodeSubmissionCursor, deleteDraft, dispatchWebhook, encodeSubmissionCursor, escapeCsvCell, exportResponsesToCsv, exportResponsesToCsvStream, isDisplayConditionSatisfied, isQuestionVisible, matchesSubmissionPageFilters, normalizeSubmissionPageSize, pipeResponsesToCsvStream, populateSchemaTranslations, publishDraft, resolveFormTranslation, resolveLocalizedSchema, sanitizeSchema, selectVisibleAnswers, transformFieldType, validateAnswers, validateFormSchema, validatePageAnswers, validateSchemaStructure };
package/dist/index.d.ts CHANGED
@@ -1,3 +1,90 @@
1
+ type Result<T, E> = {
2
+ readonly success: true;
3
+ readonly value: T;
4
+ } | {
5
+ readonly success: false;
6
+ readonly error: E;
7
+ };
8
+ type FormVersionStatus = "draft" | "published" | "archived";
9
+ interface FormVersionRecord extends ExtensibleNode {
10
+ readonly formId: string;
11
+ readonly version: number;
12
+ readonly status: FormVersionStatus;
13
+ readonly schema: FormSchema;
14
+ readonly revision: number;
15
+ readonly createdFromVersion?: number;
16
+ readonly createdAt: string;
17
+ readonly publishedAt?: string;
18
+ readonly archivedAt?: string;
19
+ }
20
+ interface FormVersionState {
21
+ readonly formId: string;
22
+ readonly draftVersion?: number;
23
+ readonly publishedVersion?: number;
24
+ readonly nextVersion: number;
25
+ readonly revision: number;
26
+ }
27
+ type VersionTransitionError = {
28
+ readonly type: "draft_already_exists";
29
+ readonly currentDraftVersion: number;
30
+ } | {
31
+ readonly type: "draft_not_found";
32
+ } | {
33
+ readonly type: "revision_conflict";
34
+ readonly expectedRevision: number;
35
+ readonly actualRevision: number;
36
+ } | {
37
+ readonly type: "invalid_source_version";
38
+ readonly requestedVersion: number;
39
+ readonly publishedVersion?: number;
40
+ } | {
41
+ readonly type: "version_immutable";
42
+ readonly status: FormVersionStatus;
43
+ } | {
44
+ readonly type: "max_version_exceeded";
45
+ readonly max: number;
46
+ } | {
47
+ readonly type: "validation_failed";
48
+ readonly issues: readonly SchemaIssue[];
49
+ };
50
+ interface CloneVersionOptions {
51
+ readonly maxVersions?: number;
52
+ readonly expectedRevision?: number;
53
+ /** Additional known published versions that may be used as a clone source. */
54
+ readonly allowedSourceVersions?: readonly number[];
55
+ }
56
+ interface PublishDraftOptions {
57
+ readonly expectedRevision?: number;
58
+ readonly currentPublishedRecord?: FormVersionRecord;
59
+ readonly validate?: (schema: FormSchema) => boolean | Promise<boolean> | readonly SchemaIssue[] | Promise<readonly SchemaIssue[]>;
60
+ readonly publishedAt?: string;
61
+ /** @deprecated Use publishedAt. */
62
+ readonly timestamp?: string;
63
+ }
64
+ interface DeleteDraftOptions {
65
+ readonly expectedRevision?: number;
66
+ }
67
+ interface PublishDraftResult {
68
+ readonly nextState: FormVersionState;
69
+ readonly publishedRecord: FormVersionRecord;
70
+ readonly archivedRecords: readonly FormVersionRecord[];
71
+ /** @deprecated Read archivedRecords instead. */
72
+ readonly archivedVersion?: number;
73
+ }
74
+ declare function cloneVersionToDraft(state: FormVersionState, sourceSchema: FormSchema, options?: CloneVersionOptions): Result<{
75
+ readonly nextState: FormVersionState;
76
+ readonly draftSchema: FormSchema;
77
+ }, VersionTransitionError>;
78
+ declare function publishDraft(state: FormVersionState, draftSchema: FormSchema, options?: PublishDraftOptions): Promise<Result<PublishDraftResult, VersionTransitionError>>;
79
+ declare function createPublishTransitionPlan(state: FormVersionState, draftRecord: FormVersionRecord, options?: PublishDraftOptions): Promise<Result<{
80
+ readonly nextState: FormVersionState;
81
+ readonly plan: VersionTransitionPlan;
82
+ }, VersionTransitionError>>;
83
+ declare function deleteDraft(state: FormVersionState, options?: DeleteDraftOptions): Result<{
84
+ readonly nextState: FormVersionState;
85
+ }, VersionTransitionError>;
86
+ declare function assertVersionMutable(status: FormVersionStatus): void;
87
+
1
88
  type FieldType = "text" | "textarea" | "number" | "rating" | "select" | "multi-select" | "checkbox" | "radio";
2
89
  interface FormPolicy {
3
90
  readonly allowedFieldTypes?: readonly FieldType[];
@@ -170,6 +257,8 @@ interface SubmissionPageQueryOptions {
170
257
  readonly since?: string;
171
258
  readonly until?: string;
172
259
  readonly locale?: string;
260
+ readonly filter?: (submission: FormSubmission) => boolean;
261
+ readonly metadataFilters?: Readonly<Record<string, JsonValue>>;
173
262
  }
174
263
  interface SubmissionPage {
175
264
  readonly items: readonly FormSubmission[];
@@ -179,6 +268,22 @@ interface SubmissionPage {
179
268
  interface PagedSubmissionStorageAdapter extends FormStorageAdapter {
180
269
  listSubmissionPage(formId: string, options?: SubmissionPageQueryOptions): Promise<SubmissionPage>;
181
270
  }
271
+ interface VersionTransitionPlan {
272
+ readonly formId: string;
273
+ readonly expectedRevision: number;
274
+ readonly nextRevision: number;
275
+ readonly draftToCreate?: FormVersionRecord;
276
+ readonly draftToDeleteVersion?: number;
277
+ readonly publishedRecordToSave?: FormVersionRecord;
278
+ readonly archivedRecordsToSave?: readonly FormVersionRecord[];
279
+ readonly timestamp: string;
280
+ }
281
+ interface VersionedFormStorageAdapter extends FormStorageAdapter {
282
+ commitVersionTransition(plan: VersionTransitionPlan): Promise<{
283
+ readonly success: boolean;
284
+ readonly error?: string;
285
+ }>;
286
+ }
182
287
  interface BaseQuestionAggregate {
183
288
  readonly fieldId: string;
184
289
  readonly answeredCount: number;
@@ -223,6 +328,7 @@ type ChoiceOption = FieldOption;
223
328
  interface FormResponse extends ExtensibleNode {
224
329
  readonly responseId: string;
225
330
  readonly formId: string;
331
+ readonly formVersion?: number;
226
332
  readonly sourceLocale?: string;
227
333
  readonly answers: Readonly<Record<string, unknown>>;
228
334
  readonly submittedAt: string;
@@ -251,14 +357,25 @@ declare function calculateNumericSummary(responses: readonly FormSubmission[], q
251
357
  declare function calculateCrossTabulation(responses: readonly FormSubmission[], rowQuestionId: string, colQuestionId: string): CrossTabulationResult;
252
358
  declare function aggregateResponses(schema: FormSchema, submissions: readonly FormSubmission[]): FormAnalytics;
253
359
  type AccumulatorResponse = FormSubmission | FormResponse;
360
+ type AccumulatorSkipReason = "form_id_mismatch" | "version_mismatch" | "invalid_structure";
361
+ interface AccumulatorReport {
362
+ readonly processedCount: number;
363
+ readonly skippedCount: number;
364
+ readonly skipReasons: readonly {
365
+ readonly responseId: string;
366
+ readonly reason: AccumulatorSkipReason;
367
+ }[];
368
+ }
254
369
  interface ResponseAccumulator {
255
370
  add(submission: AccumulatorResponse): {
256
371
  readonly success: boolean;
372
+ readonly skipped?: boolean;
257
373
  readonly error?: string;
258
374
  };
259
- addMany(submissions: Iterable<AccumulatorResponse>): void;
375
+ addMany(submissions: Iterable<AccumulatorResponse>): AccumulatorReport;
260
376
  merge(other: ResponseAccumulator): ResponseAccumulator;
261
377
  finalize(): FormAnalytics;
378
+ getReport(): AccumulatorReport;
262
379
  }
263
380
  interface ResponseAccumulatorOptions {
264
381
  readonly mode?: "strict" | "lenient";
@@ -271,13 +388,27 @@ interface CsvExportOptions {
271
388
  }
272
389
  interface CsvColumnDef {
273
390
  readonly header: string;
274
- readonly getValue: (submission: FormResponse) => string | number | boolean | null | undefined;
391
+ readonly getValue: (context: CsvColumnContext) => string | number | boolean | null | undefined | Promise<string | number | boolean | null | undefined>;
392
+ }
393
+ interface CsvColumnContext extends FormResponse {
394
+ readonly submission: FormResponse;
395
+ readonly formVersion: number;
396
+ readonly schema: FormSchema;
275
397
  }
276
398
  interface StreamCsvOptions extends CsvExportOptions {
277
399
  readonly columns?: readonly CsvColumnDef[];
278
400
  readonly includeDefaultColumns?: boolean;
279
401
  }
280
402
  declare function exportResponsesToCsvStream(schema: FormSchema, submissions: AsyncIterable<AccumulatorResponse>, options?: StreamCsvOptions): AsyncIterable<string>;
403
+ interface NodeWritableStream {
404
+ write(chunk: Uint8Array): boolean;
405
+ once(event: "drain", listener: () => void): unknown;
406
+ once(event: "error", listener: (error: Error) => void): unknown;
407
+ removeListener(event: "drain", listener: () => void): unknown;
408
+ removeListener(event: "error", listener: (error: Error) => void): unknown;
409
+ end(callback: () => void): unknown;
410
+ }
411
+ declare function pipeResponsesToCsvStream(schema: FormSchema, submissions: AsyncIterable<AccumulatorResponse>, writable: WritableStream<Uint8Array> | NodeWritableStream, options?: StreamCsvOptions): Promise<void>;
281
412
  declare function exportResponsesToCsv(schema: FormSchema, responses: readonly FormSubmission[], options?: CsvExportOptions): string;
282
413
 
283
414
  type FormEventType = "response.submitted" | "schema.updated";
@@ -314,6 +445,7 @@ interface SubmissionCursorValue {
314
445
  declare function encodeSubmissionCursor(value: SubmissionCursorValue): string;
315
446
  declare function decodeSubmissionCursor(cursor: string): SubmissionCursorValue;
316
447
  declare function normalizeSubmissionPageSize(pageSize: number | undefined, fallback?: number): number;
448
+ declare function matchesSubmissionPageFilters(submission: FormSubmission, options: Pick<SubmissionPageQueryOptions, "filter" | "metadataFilters">): boolean;
317
449
 
318
450
  interface CollectedLocales {
319
451
  readonly defaultLocale?: string;
@@ -382,73 +514,10 @@ declare function resolveFormTranslation(schema: FormSchema, adapter: AsyncTransl
382
514
  declare function validateAnswers(schema: FormSchema, values: FormValues): AnswerValidationResult;
383
515
  declare function validatePageAnswers(schema: FormSchema, pageIndex: number, values: FormValues): AnswerValidationResult;
384
516
 
385
- type Result<T, E> = {
386
- readonly success: true;
387
- readonly value: T;
388
- } | {
389
- readonly success: false;
390
- readonly error: E;
391
- };
392
- type FormVersionStatus = "draft" | "published" | "archived";
393
- interface FormVersionRecord {
394
- readonly formId: string;
395
- readonly version: number;
396
- readonly status: FormVersionStatus;
397
- readonly schema: FormSchema;
398
- readonly createdAt: string;
399
- readonly publishedAt?: string;
400
- readonly archivedAt?: string;
401
- }
402
- interface FormVersionState {
403
- readonly formId: string;
404
- readonly draftVersion?: number;
405
- readonly publishedVersion?: number;
406
- readonly nextVersion: number;
407
- readonly revision: number;
408
- }
409
- type VersionTransitionError = {
410
- readonly type: "draft_already_exists";
411
- readonly currentDraftVersion: number;
412
- } | {
413
- readonly type: "draft_not_found";
414
- } | {
415
- readonly type: "revision_conflict";
416
- readonly expectedRevision: number;
417
- readonly actualRevision: number;
418
- } | {
419
- readonly type: "version_immutable";
420
- readonly status: FormVersionStatus;
421
- } | {
422
- readonly type: "max_version_exceeded";
423
- readonly max: number;
424
- };
425
- interface CloneVersionOptions {
426
- readonly maxVersions?: number;
427
- }
428
- interface PublishDraftOptions {
429
- readonly expectedRevision?: number;
430
- readonly validate?: (schema: FormSchema) => boolean;
431
- /** Supplies deterministic record timestamps while keeping the transition pure. */
432
- readonly timestamp?: string;
433
- }
434
- declare function cloneVersionToDraft(state: FormVersionState, sourceSchema: FormSchema, options?: CloneVersionOptions): Result<{
435
- readonly nextState: FormVersionState;
436
- readonly draftSchema: FormSchema;
437
- }, VersionTransitionError>;
438
- declare function publishDraft(state: FormVersionState, draftSchema: FormSchema, options?: PublishDraftOptions): Result<{
439
- readonly nextState: FormVersionState;
440
- readonly publishedRecord: FormVersionRecord;
441
- readonly archivedVersion?: number;
442
- }, VersionTransitionError>;
443
- declare function deleteDraft(state: FormVersionState): Result<{
444
- readonly nextState: FormVersionState;
445
- }, VersionTransitionError>;
446
- declare function assertVersionMutable(status: FormVersionStatus): void;
447
-
448
517
  declare function isQuestionVisible(question: FormField, currentAnswers: Readonly<Record<string, unknown>>): boolean;
449
518
  declare function isDisplayConditionSatisfied(condition: DisplayCondition | undefined, currentAnswers: Readonly<Record<string, unknown>>): boolean;
450
519
  declare function calculatePageVisibility(schema: FormSchema, currentAnswers: Readonly<Record<string, unknown>>): Readonly<Record<string, boolean>>;
451
520
  declare function calculateFieldVisibility(schema: FormSchema, currentAnswers: Readonly<Record<string, unknown>>): Readonly<Record<string, boolean>>;
452
521
  declare function selectVisibleAnswers(schema: FormSchema, currentAnswers: FormValues): FormValues;
453
522
 
454
- export { type AccumulatorResponse, type AnswerValidationResult, type AsyncTranslationAdapter, type BaseField, type CheckboxField, type CheckboxQuestionAggregate, type ChoiceDistributionEntry, type ChoiceOption, type ChoiceQuestionAggregate, type CloneVersionOptions, type CollectedLocales, type ConditionOperator, type ConditionValue, type CreateSubmissionOptions, type CrossTabulationResult, type CsvColumnDef, type CsvExportOptions, type DisplayCondition, type ExtensibleNode, type FieldOption, type FieldType, type FormAnalytics, type FormEvent, type FormEventType, type FormField, type FormPage, type FormPolicy, type FormResponse, type FormSchema, type FormStorageAdapter, type FormSubmission, type FormValue, type FormValues, type FormVersionRecord, type FormVersionState, type FormVersionStatus, type JsonValue, type LocalizedText, type MultiSelectField, type NumberField, type NumberQuestionAggregate, type NumericSummary, type OptionAggregate, type PagedSubmissionStorageAdapter, type PopulateTranslationOptions, type PublishDraftOptions, type Question, type QuestionAggregate, type QuestionType, type RatingField, type ResponseAccumulator, type ResponseAccumulatorOptions, type Result, type SchemaIssue, type SchemaStructureIssue, type SchemaStructureIssueType, type SchemaTranslations, type SchemaValidationResult, type SelectField, type StorageAdapter, type StreamCsvOptions, type SubmissionCursorValue, type SubmissionPage, type SubmissionPageQueryOptions, type SubmissionQueryOptions, type TextField, type TextQuestionAggregate, type TranslationAdapter, type TranslationReport, type TranslationSlot, type ValidateFormSchemaOptions, type ValidationCode, type ValidationError, type ValidationIssue, type VersionTransitionError, type WebhookConfig, type WebhookDispatchResult, aggregateResponses, assertValidFormSchema, assertVersionMutable, calculateChoiceDistribution, calculateCrossTabulation, calculateFieldVisibility, calculateNumericSummary, calculatePageVisibility, cloneVersionToDraft, collectSchemaLocales, createResponseAccumulator, createSubmission, decodeSubmissionCursor, deleteDraft, dispatchWebhook, encodeSubmissionCursor, escapeCsvCell, exportResponsesToCsv, exportResponsesToCsvStream, isDisplayConditionSatisfied, isQuestionVisible, normalizeSubmissionPageSize, populateSchemaTranslations, publishDraft, resolveFormTranslation, resolveLocalizedSchema, sanitizeSchema, selectVisibleAnswers, transformFieldType, validateAnswers, validateFormSchema, validatePageAnswers, validateSchemaStructure };
523
+ export { type AccumulatorReport, type AccumulatorResponse, type AccumulatorSkipReason, type AnswerValidationResult, type AsyncTranslationAdapter, type BaseField, type CheckboxField, type CheckboxQuestionAggregate, type ChoiceDistributionEntry, type ChoiceOption, type ChoiceQuestionAggregate, type CloneVersionOptions, type CollectedLocales, type ConditionOperator, type ConditionValue, type CreateSubmissionOptions, type CrossTabulationResult, type CsvColumnContext, type CsvColumnDef, type CsvExportOptions, type DeleteDraftOptions, type DisplayCondition, type ExtensibleNode, type FieldOption, type FieldType, type FormAnalytics, type FormEvent, type FormEventType, type FormField, type FormPage, type FormPolicy, type FormResponse, type FormSchema, type FormStorageAdapter, type FormSubmission, type FormValue, type FormValues, type FormVersionRecord, type FormVersionState, type FormVersionStatus, type JsonValue, type LocalizedText, type MultiSelectField, type NodeWritableStream, type NumberField, type NumberQuestionAggregate, type NumericSummary, type OptionAggregate, type PagedSubmissionStorageAdapter, type PopulateTranslationOptions, type PublishDraftOptions, type PublishDraftResult, type Question, type QuestionAggregate, type QuestionType, type RatingField, type ResponseAccumulator, type ResponseAccumulatorOptions, type Result, type SchemaIssue, type SchemaStructureIssue, type SchemaStructureIssueType, type SchemaTranslations, type SchemaValidationResult, type SelectField, type StorageAdapter, type StreamCsvOptions, type SubmissionCursorValue, type SubmissionPage, type SubmissionPageQueryOptions, type SubmissionQueryOptions, type TextField, type TextQuestionAggregate, type TranslationAdapter, type TranslationReport, type TranslationSlot, type ValidateFormSchemaOptions, type ValidationCode, type ValidationError, type ValidationIssue, type VersionTransitionError, type VersionTransitionPlan, type VersionedFormStorageAdapter, type WebhookConfig, type WebhookDispatchResult, aggregateResponses, assertValidFormSchema, assertVersionMutable, calculateChoiceDistribution, calculateCrossTabulation, calculateFieldVisibility, calculateNumericSummary, calculatePageVisibility, cloneVersionToDraft, collectSchemaLocales, createPublishTransitionPlan, createResponseAccumulator, createSubmission, decodeSubmissionCursor, deleteDraft, dispatchWebhook, encodeSubmissionCursor, escapeCsvCell, exportResponsesToCsv, exportResponsesToCsvStream, isDisplayConditionSatisfied, isQuestionVisible, matchesSubmissionPageFilters, normalizeSubmissionPageSize, pipeResponsesToCsvStream, populateSchemaTranslations, publishDraft, resolveFormTranslation, resolveLocalizedSchema, sanitizeSchema, selectVisibleAnswers, transformFieldType, validateAnswers, validateFormSchema, validatePageAnswers, validateSchemaStructure };