@form-engine-ts/core 2.8.0 → 2.9.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/README.md +5 -0
- package/dist/index.cjs +61 -2
- package/dist/index.d.cts +15 -1
- package/dist/index.d.ts +15 -1
- package/dist/index.js +60 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -104,4 +104,9 @@ may push supported nodes to their native query language while preserving identic
|
|
|
104
104
|
implement `listTextAnswerPage` expose stable cursor pagination over individual text answers.
|
|
105
105
|
`TextAnswerPageQueryOptions.fieldIds` can select multiple free-text fields for item-level paging.
|
|
106
106
|
|
|
107
|
+
`iterateSubmissionPages(adapter, formId, query, options)` safely traverses every page as an async generator. It supports
|
|
108
|
+
`pageSize`, `maxItems`, and `AbortSignal`, continues through empty pages with a next cursor, and rejects missing or cyclic
|
|
109
|
+
cursors instead of looping indefinitely. Publish transition validation also rejects mismatched form IDs, non-Published
|
|
110
|
+
records, and an unexpected current record with typed errors.
|
|
111
|
+
|
|
107
112
|
See the [project documentation](https://github.com/nitta-a/form-engine-ts#readme) for the complete schema and API guide.
|
package/dist/index.cjs
CHANGED
|
@@ -46,6 +46,7 @@ __export(index_exports, {
|
|
|
46
46
|
exportResponsesToCsvStream: () => exportResponsesToCsvStream,
|
|
47
47
|
isDisplayConditionSatisfied: () => isDisplayConditionSatisfied,
|
|
48
48
|
isQuestionVisible: () => isQuestionVisible,
|
|
49
|
+
iterateSubmissionPages: () => iterateSubmissionPages,
|
|
49
50
|
jsonValuesEqual: () => jsonValuesEqual,
|
|
50
51
|
matchesSubmissionFilter: () => matchesSubmissionFilter,
|
|
51
52
|
matchesSubmissionPageFilters: () => matchesSubmissionPageFilters,
|
|
@@ -1523,6 +1524,54 @@ function transformFieldType(field, nextType) {
|
|
|
1523
1524
|
}
|
|
1524
1525
|
|
|
1525
1526
|
// src/pagination.ts
|
|
1527
|
+
function asFormResponse2(submission) {
|
|
1528
|
+
return {
|
|
1529
|
+
responseId: submission.id,
|
|
1530
|
+
formId: submission.formId,
|
|
1531
|
+
formVersion: submission.formVersion,
|
|
1532
|
+
sourceLocale: submission.locale,
|
|
1533
|
+
answers: submission.values,
|
|
1534
|
+
submittedAt: submission.submittedAt,
|
|
1535
|
+
...submission.metadata === void 0 ? {} : { metadata: submission.metadata }
|
|
1536
|
+
};
|
|
1537
|
+
}
|
|
1538
|
+
async function* iterateSubmissionPages(adapter, formId, queryOptions = {}, options = {}) {
|
|
1539
|
+
const pageSize = normalizeSubmissionPageSize(options.pageSize ?? queryOptions.pageSize);
|
|
1540
|
+
const maxItems = options.maxItems ?? Number.POSITIVE_INFINITY;
|
|
1541
|
+
if (maxItems !== Number.POSITIVE_INFINITY && (!Number.isSafeInteger(maxItems) || maxItems < 0)) {
|
|
1542
|
+
throw new TypeError("maxItems must be a non-negative safe integer.");
|
|
1543
|
+
}
|
|
1544
|
+
if (maxItems === 0) return;
|
|
1545
|
+
const seenCursors = /* @__PURE__ */ new Set();
|
|
1546
|
+
let cursor = queryOptions.cursor;
|
|
1547
|
+
const { cursor: _initialCursor, pageSize: _initialPageSize, ...baseQueryOptions } = queryOptions;
|
|
1548
|
+
if (cursor !== void 0) seenCursors.add(cursor);
|
|
1549
|
+
let emitted = 0;
|
|
1550
|
+
while (emitted < maxItems) {
|
|
1551
|
+
options.signal?.throwIfAborted();
|
|
1552
|
+
const remaining = maxItems - emitted;
|
|
1553
|
+
const requestedPageSize = Number.isFinite(remaining) ? Math.min(pageSize, remaining) : pageSize;
|
|
1554
|
+
const page = await adapter.listSubmissionPage(formId, {
|
|
1555
|
+
...baseQueryOptions,
|
|
1556
|
+
pageSize: requestedPageSize,
|
|
1557
|
+
...cursor === void 0 ? {} : { cursor }
|
|
1558
|
+
});
|
|
1559
|
+
options.signal?.throwIfAborted();
|
|
1560
|
+
const available = Number.isFinite(remaining) ? page.items.slice(0, remaining) : page.items;
|
|
1561
|
+
if (available.length > 0) {
|
|
1562
|
+
emitted += available.length;
|
|
1563
|
+
yield available.map(asFormResponse2);
|
|
1564
|
+
}
|
|
1565
|
+
if (!page.hasMore || emitted >= maxItems) return;
|
|
1566
|
+
const nextCursor = page.nextCursor;
|
|
1567
|
+
if (nextCursor === void 0 || nextCursor.length === 0) {
|
|
1568
|
+
throw new Error("Submission pagination returned hasMore without a next cursor.");
|
|
1569
|
+
}
|
|
1570
|
+
if (seenCursors.has(nextCursor)) throw new Error(`Submission pagination cursor cycle detected: ${nextCursor}`);
|
|
1571
|
+
seenCursors.add(nextCursor);
|
|
1572
|
+
cursor = nextCursor;
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1526
1575
|
var BASE64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
1527
1576
|
function encodeBase64(bytes) {
|
|
1528
1577
|
let result = "";
|
|
@@ -2203,14 +2252,23 @@ function createCloneTransitionPlan(state, sourceRecord, options = {}) {
|
|
|
2203
2252
|
};
|
|
2204
2253
|
}
|
|
2205
2254
|
function validatePublishedRecord(state, record) {
|
|
2206
|
-
if (state.publishedVersion
|
|
2255
|
+
if (state.publishedVersion === void 0) {
|
|
2256
|
+
return record === void 0 ? void 0 : { success: false, error: { type: "unexpected_published_record" } };
|
|
2257
|
+
}
|
|
2258
|
+
if (record !== void 0 && record.formId !== state.formId) {
|
|
2259
|
+
return { success: false, error: { type: "form_id_mismatch" } };
|
|
2260
|
+
}
|
|
2261
|
+
if (record !== void 0 && record.status !== "published") {
|
|
2262
|
+
return { success: false, error: { type: "invalid_published_status" } };
|
|
2263
|
+
}
|
|
2264
|
+
if (record?.version !== state.publishedVersion) {
|
|
2207
2265
|
return {
|
|
2208
2266
|
success: false,
|
|
2209
2267
|
error: { type: "missing_published_record", expectedVersion: state.publishedVersion }
|
|
2210
2268
|
};
|
|
2211
2269
|
}
|
|
2212
2270
|
if (record === void 0) return void 0;
|
|
2213
|
-
if (record.
|
|
2271
|
+
if (record.schema.id !== record.formId || record.schema.version !== record.version) {
|
|
2214
2272
|
throw new TypeError("currentPublishedRecord must match the state's published version.");
|
|
2215
2273
|
}
|
|
2216
2274
|
return void 0;
|
|
@@ -2386,6 +2444,7 @@ function assertVersionMutable(status) {
|
|
|
2386
2444
|
exportResponsesToCsvStream,
|
|
2387
2445
|
isDisplayConditionSatisfied,
|
|
2388
2446
|
isQuestionVisible,
|
|
2447
|
+
iterateSubmissionPages,
|
|
2389
2448
|
jsonValuesEqual,
|
|
2390
2449
|
matchesSubmissionFilter,
|
|
2391
2450
|
matchesSubmissionPageFilters,
|
package/dist/index.d.cts
CHANGED
|
@@ -40,6 +40,12 @@ type VersionTransitionError = {
|
|
|
40
40
|
} | {
|
|
41
41
|
readonly type: "missing_published_record";
|
|
42
42
|
readonly expectedVersion: number;
|
|
43
|
+
} | {
|
|
44
|
+
readonly type: "form_id_mismatch";
|
|
45
|
+
} | {
|
|
46
|
+
readonly type: "invalid_published_status";
|
|
47
|
+
} | {
|
|
48
|
+
readonly type: "unexpected_published_record";
|
|
43
49
|
} | {
|
|
44
50
|
readonly type: "revision_conflict";
|
|
45
51
|
readonly expectedRevision: number;
|
|
@@ -354,6 +360,8 @@ type StorageCommitError = {
|
|
|
354
360
|
} | {
|
|
355
361
|
readonly type: "draft_already_exists";
|
|
356
362
|
readonly currentDraftVersion: number;
|
|
363
|
+
} | {
|
|
364
|
+
readonly type: "transaction_unsupported";
|
|
357
365
|
} | {
|
|
358
366
|
readonly type: "invalid_transition";
|
|
359
367
|
readonly message: string;
|
|
@@ -523,6 +531,12 @@ declare function dispatchWebhook<T>(event: FormEvent<T>, config: WebhookConfig,
|
|
|
523
531
|
*/
|
|
524
532
|
declare function transformFieldType(field: FormField, nextType: QuestionType): FormField;
|
|
525
533
|
|
|
534
|
+
interface PaginationIteratorOptions {
|
|
535
|
+
readonly pageSize?: number;
|
|
536
|
+
readonly maxItems?: number;
|
|
537
|
+
readonly signal?: AbortSignal;
|
|
538
|
+
}
|
|
539
|
+
declare function iterateSubmissionPages(adapter: PagedSubmissionStorageAdapter, formId: string, queryOptions?: SubmissionPageQueryOptions, options?: PaginationIteratorOptions): AsyncIterable<readonly FormResponse[]>;
|
|
526
540
|
interface SubmissionCursorValue {
|
|
527
541
|
readonly submittedAt: string;
|
|
528
542
|
readonly responseId: string;
|
|
@@ -613,4 +627,4 @@ declare function calculatePageVisibility(schema: FormSchema, currentAnswers: Rea
|
|
|
613
627
|
declare function calculateFieldVisibility(schema: FormSchema, currentAnswers: Readonly<Record<string, unknown>>): Readonly<Record<string, boolean>>;
|
|
614
628
|
declare function selectVisibleAnswers(schema: FormSchema, currentAnswers: FormValues): FormValues;
|
|
615
629
|
|
|
616
|
-
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 StorageCommitError, type StreamCsvOptions, type SubmissionCursorValue, type SubmissionFilter, type SubmissionPage, type SubmissionPageQueryOptions, type SubmissionQueryOptions, type TextAnswerCursorValue, type TextAnswerItem, type TextAnswerPage, type TextAnswerPageQueryOptions, type TextField, type TextQuestionAggregate, type TranslationAdapter, type TranslationReport, type TranslationSlot, type ValidateFormSchemaOptions, type ValidationCode, type ValidationError, type ValidationIssue, type VersionTransitionError, type VersionTransitionEvent, type VersionTransitionPlan, type VersionedFormStorageAdapter, type WebhookConfig, type WebhookDispatchResult, aggregateResponses, assertValidFormSchema, assertVersionMutable, calculateChoiceDistribution, calculateCrossTabulation, calculateFieldVisibility, calculateNumericSummary, calculatePageVisibility, cloneVersionToDraft, collectSchemaLocales, createCloneTransitionPlan, createDeleteDraftTransitionPlan, createPublishTransitionPlan, createResponseAccumulator, createSubmission, decodeSubmissionCursor, decodeTextAnswerCursor, deleteDraft, dispatchWebhook, encodeSubmissionCursor, encodeTextAnswerCursor, escapeCsvCell, exportResponsesToCsv, exportResponsesToCsvStream, isDisplayConditionSatisfied, isQuestionVisible, jsonValuesEqual, matchesSubmissionFilter, matchesSubmissionPageFilters, normalizeSubmissionPageSize, pipeResponsesToCsvStream, populateSchemaTranslations, publishDraft, resolveFormTranslation, resolveLocalizedSchema, sanitizeSchema, selectVisibleAnswers, transformFieldType, validateAnswers, validateFormSchema, validatePageAnswers, validateSchemaStructure };
|
|
630
|
+
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 PaginationIteratorOptions, 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 StorageCommitError, type StreamCsvOptions, type SubmissionCursorValue, type SubmissionFilter, type SubmissionPage, type SubmissionPageQueryOptions, type SubmissionQueryOptions, type TextAnswerCursorValue, type TextAnswerItem, type TextAnswerPage, type TextAnswerPageQueryOptions, type TextField, type TextQuestionAggregate, type TranslationAdapter, type TranslationReport, type TranslationSlot, type ValidateFormSchemaOptions, type ValidationCode, type ValidationError, type ValidationIssue, type VersionTransitionError, type VersionTransitionEvent, type VersionTransitionPlan, type VersionedFormStorageAdapter, type WebhookConfig, type WebhookDispatchResult, aggregateResponses, assertValidFormSchema, assertVersionMutable, calculateChoiceDistribution, calculateCrossTabulation, calculateFieldVisibility, calculateNumericSummary, calculatePageVisibility, cloneVersionToDraft, collectSchemaLocales, createCloneTransitionPlan, createDeleteDraftTransitionPlan, createPublishTransitionPlan, createResponseAccumulator, createSubmission, decodeSubmissionCursor, decodeTextAnswerCursor, deleteDraft, dispatchWebhook, encodeSubmissionCursor, encodeTextAnswerCursor, escapeCsvCell, exportResponsesToCsv, exportResponsesToCsvStream, isDisplayConditionSatisfied, isQuestionVisible, iterateSubmissionPages, jsonValuesEqual, matchesSubmissionFilter, matchesSubmissionPageFilters, normalizeSubmissionPageSize, pipeResponsesToCsvStream, populateSchemaTranslations, publishDraft, resolveFormTranslation, resolveLocalizedSchema, sanitizeSchema, selectVisibleAnswers, transformFieldType, validateAnswers, validateFormSchema, validatePageAnswers, validateSchemaStructure };
|
package/dist/index.d.ts
CHANGED
|
@@ -40,6 +40,12 @@ type VersionTransitionError = {
|
|
|
40
40
|
} | {
|
|
41
41
|
readonly type: "missing_published_record";
|
|
42
42
|
readonly expectedVersion: number;
|
|
43
|
+
} | {
|
|
44
|
+
readonly type: "form_id_mismatch";
|
|
45
|
+
} | {
|
|
46
|
+
readonly type: "invalid_published_status";
|
|
47
|
+
} | {
|
|
48
|
+
readonly type: "unexpected_published_record";
|
|
43
49
|
} | {
|
|
44
50
|
readonly type: "revision_conflict";
|
|
45
51
|
readonly expectedRevision: number;
|
|
@@ -354,6 +360,8 @@ type StorageCommitError = {
|
|
|
354
360
|
} | {
|
|
355
361
|
readonly type: "draft_already_exists";
|
|
356
362
|
readonly currentDraftVersion: number;
|
|
363
|
+
} | {
|
|
364
|
+
readonly type: "transaction_unsupported";
|
|
357
365
|
} | {
|
|
358
366
|
readonly type: "invalid_transition";
|
|
359
367
|
readonly message: string;
|
|
@@ -523,6 +531,12 @@ declare function dispatchWebhook<T>(event: FormEvent<T>, config: WebhookConfig,
|
|
|
523
531
|
*/
|
|
524
532
|
declare function transformFieldType(field: FormField, nextType: QuestionType): FormField;
|
|
525
533
|
|
|
534
|
+
interface PaginationIteratorOptions {
|
|
535
|
+
readonly pageSize?: number;
|
|
536
|
+
readonly maxItems?: number;
|
|
537
|
+
readonly signal?: AbortSignal;
|
|
538
|
+
}
|
|
539
|
+
declare function iterateSubmissionPages(adapter: PagedSubmissionStorageAdapter, formId: string, queryOptions?: SubmissionPageQueryOptions, options?: PaginationIteratorOptions): AsyncIterable<readonly FormResponse[]>;
|
|
526
540
|
interface SubmissionCursorValue {
|
|
527
541
|
readonly submittedAt: string;
|
|
528
542
|
readonly responseId: string;
|
|
@@ -613,4 +627,4 @@ declare function calculatePageVisibility(schema: FormSchema, currentAnswers: Rea
|
|
|
613
627
|
declare function calculateFieldVisibility(schema: FormSchema, currentAnswers: Readonly<Record<string, unknown>>): Readonly<Record<string, boolean>>;
|
|
614
628
|
declare function selectVisibleAnswers(schema: FormSchema, currentAnswers: FormValues): FormValues;
|
|
615
629
|
|
|
616
|
-
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 StorageCommitError, type StreamCsvOptions, type SubmissionCursorValue, type SubmissionFilter, type SubmissionPage, type SubmissionPageQueryOptions, type SubmissionQueryOptions, type TextAnswerCursorValue, type TextAnswerItem, type TextAnswerPage, type TextAnswerPageQueryOptions, type TextField, type TextQuestionAggregate, type TranslationAdapter, type TranslationReport, type TranslationSlot, type ValidateFormSchemaOptions, type ValidationCode, type ValidationError, type ValidationIssue, type VersionTransitionError, type VersionTransitionEvent, type VersionTransitionPlan, type VersionedFormStorageAdapter, type WebhookConfig, type WebhookDispatchResult, aggregateResponses, assertValidFormSchema, assertVersionMutable, calculateChoiceDistribution, calculateCrossTabulation, calculateFieldVisibility, calculateNumericSummary, calculatePageVisibility, cloneVersionToDraft, collectSchemaLocales, createCloneTransitionPlan, createDeleteDraftTransitionPlan, createPublishTransitionPlan, createResponseAccumulator, createSubmission, decodeSubmissionCursor, decodeTextAnswerCursor, deleteDraft, dispatchWebhook, encodeSubmissionCursor, encodeTextAnswerCursor, escapeCsvCell, exportResponsesToCsv, exportResponsesToCsvStream, isDisplayConditionSatisfied, isQuestionVisible, jsonValuesEqual, matchesSubmissionFilter, matchesSubmissionPageFilters, normalizeSubmissionPageSize, pipeResponsesToCsvStream, populateSchemaTranslations, publishDraft, resolveFormTranslation, resolveLocalizedSchema, sanitizeSchema, selectVisibleAnswers, transformFieldType, validateAnswers, validateFormSchema, validatePageAnswers, validateSchemaStructure };
|
|
630
|
+
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 PaginationIteratorOptions, 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 StorageCommitError, type StreamCsvOptions, type SubmissionCursorValue, type SubmissionFilter, type SubmissionPage, type SubmissionPageQueryOptions, type SubmissionQueryOptions, type TextAnswerCursorValue, type TextAnswerItem, type TextAnswerPage, type TextAnswerPageQueryOptions, type TextField, type TextQuestionAggregate, type TranslationAdapter, type TranslationReport, type TranslationSlot, type ValidateFormSchemaOptions, type ValidationCode, type ValidationError, type ValidationIssue, type VersionTransitionError, type VersionTransitionEvent, type VersionTransitionPlan, type VersionedFormStorageAdapter, type WebhookConfig, type WebhookDispatchResult, aggregateResponses, assertValidFormSchema, assertVersionMutable, calculateChoiceDistribution, calculateCrossTabulation, calculateFieldVisibility, calculateNumericSummary, calculatePageVisibility, cloneVersionToDraft, collectSchemaLocales, createCloneTransitionPlan, createDeleteDraftTransitionPlan, createPublishTransitionPlan, createResponseAccumulator, createSubmission, decodeSubmissionCursor, decodeTextAnswerCursor, deleteDraft, dispatchWebhook, encodeSubmissionCursor, encodeTextAnswerCursor, escapeCsvCell, exportResponsesToCsv, exportResponsesToCsvStream, isDisplayConditionSatisfied, isQuestionVisible, iterateSubmissionPages, jsonValuesEqual, matchesSubmissionFilter, matchesSubmissionPageFilters, normalizeSubmissionPageSize, pipeResponsesToCsvStream, populateSchemaTranslations, publishDraft, resolveFormTranslation, resolveLocalizedSchema, sanitizeSchema, selectVisibleAnswers, transformFieldType, validateAnswers, validateFormSchema, validatePageAnswers, validateSchemaStructure };
|
package/dist/index.js
CHANGED
|
@@ -1456,6 +1456,54 @@ function transformFieldType(field, nextType) {
|
|
|
1456
1456
|
}
|
|
1457
1457
|
|
|
1458
1458
|
// src/pagination.ts
|
|
1459
|
+
function asFormResponse2(submission) {
|
|
1460
|
+
return {
|
|
1461
|
+
responseId: submission.id,
|
|
1462
|
+
formId: submission.formId,
|
|
1463
|
+
formVersion: submission.formVersion,
|
|
1464
|
+
sourceLocale: submission.locale,
|
|
1465
|
+
answers: submission.values,
|
|
1466
|
+
submittedAt: submission.submittedAt,
|
|
1467
|
+
...submission.metadata === void 0 ? {} : { metadata: submission.metadata }
|
|
1468
|
+
};
|
|
1469
|
+
}
|
|
1470
|
+
async function* iterateSubmissionPages(adapter, formId, queryOptions = {}, options = {}) {
|
|
1471
|
+
const pageSize = normalizeSubmissionPageSize(options.pageSize ?? queryOptions.pageSize);
|
|
1472
|
+
const maxItems = options.maxItems ?? Number.POSITIVE_INFINITY;
|
|
1473
|
+
if (maxItems !== Number.POSITIVE_INFINITY && (!Number.isSafeInteger(maxItems) || maxItems < 0)) {
|
|
1474
|
+
throw new TypeError("maxItems must be a non-negative safe integer.");
|
|
1475
|
+
}
|
|
1476
|
+
if (maxItems === 0) return;
|
|
1477
|
+
const seenCursors = /* @__PURE__ */ new Set();
|
|
1478
|
+
let cursor = queryOptions.cursor;
|
|
1479
|
+
const { cursor: _initialCursor, pageSize: _initialPageSize, ...baseQueryOptions } = queryOptions;
|
|
1480
|
+
if (cursor !== void 0) seenCursors.add(cursor);
|
|
1481
|
+
let emitted = 0;
|
|
1482
|
+
while (emitted < maxItems) {
|
|
1483
|
+
options.signal?.throwIfAborted();
|
|
1484
|
+
const remaining = maxItems - emitted;
|
|
1485
|
+
const requestedPageSize = Number.isFinite(remaining) ? Math.min(pageSize, remaining) : pageSize;
|
|
1486
|
+
const page = await adapter.listSubmissionPage(formId, {
|
|
1487
|
+
...baseQueryOptions,
|
|
1488
|
+
pageSize: requestedPageSize,
|
|
1489
|
+
...cursor === void 0 ? {} : { cursor }
|
|
1490
|
+
});
|
|
1491
|
+
options.signal?.throwIfAborted();
|
|
1492
|
+
const available = Number.isFinite(remaining) ? page.items.slice(0, remaining) : page.items;
|
|
1493
|
+
if (available.length > 0) {
|
|
1494
|
+
emitted += available.length;
|
|
1495
|
+
yield available.map(asFormResponse2);
|
|
1496
|
+
}
|
|
1497
|
+
if (!page.hasMore || emitted >= maxItems) return;
|
|
1498
|
+
const nextCursor = page.nextCursor;
|
|
1499
|
+
if (nextCursor === void 0 || nextCursor.length === 0) {
|
|
1500
|
+
throw new Error("Submission pagination returned hasMore without a next cursor.");
|
|
1501
|
+
}
|
|
1502
|
+
if (seenCursors.has(nextCursor)) throw new Error(`Submission pagination cursor cycle detected: ${nextCursor}`);
|
|
1503
|
+
seenCursors.add(nextCursor);
|
|
1504
|
+
cursor = nextCursor;
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1459
1507
|
var BASE64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
1460
1508
|
function encodeBase64(bytes) {
|
|
1461
1509
|
let result = "";
|
|
@@ -2136,14 +2184,23 @@ function createCloneTransitionPlan(state, sourceRecord, options = {}) {
|
|
|
2136
2184
|
};
|
|
2137
2185
|
}
|
|
2138
2186
|
function validatePublishedRecord(state, record) {
|
|
2139
|
-
if (state.publishedVersion
|
|
2187
|
+
if (state.publishedVersion === void 0) {
|
|
2188
|
+
return record === void 0 ? void 0 : { success: false, error: { type: "unexpected_published_record" } };
|
|
2189
|
+
}
|
|
2190
|
+
if (record !== void 0 && record.formId !== state.formId) {
|
|
2191
|
+
return { success: false, error: { type: "form_id_mismatch" } };
|
|
2192
|
+
}
|
|
2193
|
+
if (record !== void 0 && record.status !== "published") {
|
|
2194
|
+
return { success: false, error: { type: "invalid_published_status" } };
|
|
2195
|
+
}
|
|
2196
|
+
if (record?.version !== state.publishedVersion) {
|
|
2140
2197
|
return {
|
|
2141
2198
|
success: false,
|
|
2142
2199
|
error: { type: "missing_published_record", expectedVersion: state.publishedVersion }
|
|
2143
2200
|
};
|
|
2144
2201
|
}
|
|
2145
2202
|
if (record === void 0) return void 0;
|
|
2146
|
-
if (record.
|
|
2203
|
+
if (record.schema.id !== record.formId || record.schema.version !== record.version) {
|
|
2147
2204
|
throw new TypeError("currentPublishedRecord must match the state's published version.");
|
|
2148
2205
|
}
|
|
2149
2206
|
return void 0;
|
|
@@ -2318,6 +2375,7 @@ export {
|
|
|
2318
2375
|
exportResponsesToCsvStream,
|
|
2319
2376
|
isDisplayConditionSatisfied,
|
|
2320
2377
|
isQuestionVisible,
|
|
2378
|
+
iterateSubmissionPages,
|
|
2321
2379
|
jsonValuesEqual,
|
|
2322
2380
|
matchesSubmissionFilter,
|
|
2323
2381
|
matchesSubmissionPageFilters,
|