@form-engine-ts/core 2.7.0 → 2.8.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 CHANGED
@@ -79,6 +79,9 @@ Results are ordered by `submittedAt`, then submission ID. Both boundaries are in
79
79
  `cloneVersionToDraft`, asynchronous `publishDraft`, and `deleteDraft` implement revision-checked version transitions as
80
80
  pure functions. `createCloneTransitionPlan`, `createPublishTransitionPlan`, and `createDeleteDraftTransitionPlan` produce
81
81
  complete persistence plans with the next state, affected records, and immutable audit events.
82
+ Publishing when state already identifies a Published version requires its matching `currentPublishedRecord`; omission or
83
+ a version mismatch returns the typed `missing_published_record` error. The resulting archive preserves the original
84
+ schema, creation timestamp, and metadata.
82
85
  Clone/delete operations accept `expectedRevision`; cloning rejects non-published sources, publish validation failures are
83
86
  returned as typed `validation_failed` issues, and successful publishing archives only a supplied actual published record,
84
87
  preserving its schema and metadata. `createPublishTransitionPlan` returns complete records plus expected/next revisions for
@@ -99,5 +102,6 @@ cursor combines `submittedAt` and response ID, so equal timestamps do not produc
99
102
  and `filter` are applied before page sizing. `filter` accepts a composable `eq`/`in`/`range`/`exists` and/or AST; adapters
100
103
  may push supported nodes to their native query language while preserving identical client-side semantics. Adapters that
101
104
  implement `listTextAnswerPage` expose stable cursor pagination over individual text answers.
105
+ `TextAnswerPageQueryOptions.fieldIds` can select multiple free-text fields for item-level paging.
102
106
 
103
107
  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
@@ -2203,10 +2203,17 @@ function createCloneTransitionPlan(state, sourceRecord, options = {}) {
2203
2203
  };
2204
2204
  }
2205
2205
  function validatePublishedRecord(state, record) {
2206
- if (record === void 0) return;
2207
- if (record.formId !== state.formId || record.version !== state.publishedVersion || record.status !== "published" || record.schema.id !== record.formId || record.schema.version !== record.version) {
2206
+ if (state.publishedVersion !== void 0 && record?.version !== state.publishedVersion) {
2207
+ return {
2208
+ success: false,
2209
+ error: { type: "missing_published_record", expectedVersion: state.publishedVersion }
2210
+ };
2211
+ }
2212
+ if (record === void 0) return void 0;
2213
+ if (record.formId !== state.formId || record.status !== "published" || record.schema.id !== record.formId || record.schema.version !== record.version) {
2208
2214
  throw new TypeError("currentPublishedRecord must match the state's published version.");
2209
2215
  }
2216
+ return void 0;
2210
2217
  }
2211
2218
  function transitionTimestamp(options) {
2212
2219
  return requireTimestamp(options.publishedAt ?? options.timestamp, "publishedAt");
@@ -2218,7 +2225,8 @@ async function publishDraft(state, draftSchema, options = {}) {
2218
2225
  if (state.draftVersion === void 0 || draftSchema.id !== state.formId || draftSchema.version !== state.draftVersion) {
2219
2226
  return { success: false, error: { type: "draft_not_found" } };
2220
2227
  }
2221
- validatePublishedRecord(state, options.currentPublishedRecord);
2228
+ const publishedRecordError = validatePublishedRecord(state, options.currentPublishedRecord);
2229
+ if (publishedRecordError !== void 0) return publishedRecordError;
2222
2230
  const validation = await options.validate?.(draftSchema);
2223
2231
  if (validation === false || Array.isArray(validation) && validation.length > 0) {
2224
2232
  return {
package/dist/index.d.cts CHANGED
@@ -37,6 +37,9 @@ type VersionTransitionError = {
37
37
  readonly currentDraftVersion: number;
38
38
  } | {
39
39
  readonly type: "draft_not_found";
40
+ } | {
41
+ readonly type: "missing_published_record";
42
+ readonly expectedVersion: number;
40
43
  } | {
41
44
  readonly type: "revision_conflict";
42
45
  readonly expectedRevision: number;
@@ -280,6 +283,9 @@ interface SubmissionPageQueryOptions {
280
283
  /** @deprecated Prefer the generic filter AST. */
281
284
  readonly metadataFilters?: Readonly<Record<string, JsonValue>>;
282
285
  }
286
+ interface TextAnswerPageQueryOptions extends SubmissionPageQueryOptions {
287
+ readonly fieldIds?: readonly string[];
288
+ }
283
289
  type SubmissionFilter = {
284
290
  readonly op: "eq";
285
291
  readonly path: string;
@@ -311,7 +317,7 @@ interface SubmissionPage {
311
317
  }
312
318
  interface PagedSubmissionStorageAdapter extends FormStorageAdapter {
313
319
  listSubmissionPage(formId: string, options?: SubmissionPageQueryOptions): Promise<SubmissionPage>;
314
- listTextAnswerPage?(formId: string, fieldId: string, options?: SubmissionPageQueryOptions): Promise<TextAnswerPage>;
320
+ listTextAnswerPage?(formId: string, fieldIdOrOptions?: string | TextAnswerPageQueryOptions, options?: TextAnswerPageQueryOptions): Promise<TextAnswerPage>;
315
321
  }
316
322
  interface TextAnswerItem {
317
323
  readonly responseId: string;
@@ -607,4 +613,4 @@ declare function calculatePageVisibility(schema: FormSchema, currentAnswers: Rea
607
613
  declare function calculateFieldVisibility(schema: FormSchema, currentAnswers: Readonly<Record<string, unknown>>): Readonly<Record<string, boolean>>;
608
614
  declare function selectVisibleAnswers(schema: FormSchema, currentAnswers: FormValues): FormValues;
609
615
 
610
- 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 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 };
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 };
package/dist/index.d.ts CHANGED
@@ -37,6 +37,9 @@ type VersionTransitionError = {
37
37
  readonly currentDraftVersion: number;
38
38
  } | {
39
39
  readonly type: "draft_not_found";
40
+ } | {
41
+ readonly type: "missing_published_record";
42
+ readonly expectedVersion: number;
40
43
  } | {
41
44
  readonly type: "revision_conflict";
42
45
  readonly expectedRevision: number;
@@ -280,6 +283,9 @@ interface SubmissionPageQueryOptions {
280
283
  /** @deprecated Prefer the generic filter AST. */
281
284
  readonly metadataFilters?: Readonly<Record<string, JsonValue>>;
282
285
  }
286
+ interface TextAnswerPageQueryOptions extends SubmissionPageQueryOptions {
287
+ readonly fieldIds?: readonly string[];
288
+ }
283
289
  type SubmissionFilter = {
284
290
  readonly op: "eq";
285
291
  readonly path: string;
@@ -311,7 +317,7 @@ interface SubmissionPage {
311
317
  }
312
318
  interface PagedSubmissionStorageAdapter extends FormStorageAdapter {
313
319
  listSubmissionPage(formId: string, options?: SubmissionPageQueryOptions): Promise<SubmissionPage>;
314
- listTextAnswerPage?(formId: string, fieldId: string, options?: SubmissionPageQueryOptions): Promise<TextAnswerPage>;
320
+ listTextAnswerPage?(formId: string, fieldIdOrOptions?: string | TextAnswerPageQueryOptions, options?: TextAnswerPageQueryOptions): Promise<TextAnswerPage>;
315
321
  }
316
322
  interface TextAnswerItem {
317
323
  readonly responseId: string;
@@ -607,4 +613,4 @@ declare function calculatePageVisibility(schema: FormSchema, currentAnswers: Rea
607
613
  declare function calculateFieldVisibility(schema: FormSchema, currentAnswers: Readonly<Record<string, unknown>>): Readonly<Record<string, boolean>>;
608
614
  declare function selectVisibleAnswers(schema: FormSchema, currentAnswers: FormValues): FormValues;
609
615
 
610
- 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 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 };
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 };
package/dist/index.js CHANGED
@@ -2136,10 +2136,17 @@ function createCloneTransitionPlan(state, sourceRecord, options = {}) {
2136
2136
  };
2137
2137
  }
2138
2138
  function validatePublishedRecord(state, record) {
2139
- if (record === void 0) return;
2140
- if (record.formId !== state.formId || record.version !== state.publishedVersion || record.status !== "published" || record.schema.id !== record.formId || record.schema.version !== record.version) {
2139
+ if (state.publishedVersion !== void 0 && record?.version !== state.publishedVersion) {
2140
+ return {
2141
+ success: false,
2142
+ error: { type: "missing_published_record", expectedVersion: state.publishedVersion }
2143
+ };
2144
+ }
2145
+ if (record === void 0) return void 0;
2146
+ if (record.formId !== state.formId || record.status !== "published" || record.schema.id !== record.formId || record.schema.version !== record.version) {
2141
2147
  throw new TypeError("currentPublishedRecord must match the state's published version.");
2142
2148
  }
2149
+ return void 0;
2143
2150
  }
2144
2151
  function transitionTimestamp(options) {
2145
2152
  return requireTimestamp(options.publishedAt ?? options.timestamp, "publishedAt");
@@ -2151,7 +2158,8 @@ async function publishDraft(state, draftSchema, options = {}) {
2151
2158
  if (state.draftVersion === void 0 || draftSchema.id !== state.formId || draftSchema.version !== state.draftVersion) {
2152
2159
  return { success: false, error: { type: "draft_not_found" } };
2153
2160
  }
2154
- validatePublishedRecord(state, options.currentPublishedRecord);
2161
+ const publishedRecordError = validatePublishedRecord(state, options.currentPublishedRecord);
2162
+ if (publishedRecordError !== void 0) return publishedRecordError;
2155
2163
  const validation = await options.validate?.(draftSchema);
2156
2164
  if (validation === false || Array.isArray(validation) && validation.length > 0) {
2157
2165
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@form-engine-ts/core",
3
- "version": "2.7.0",
3
+ "version": "2.8.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },