@form-engine-ts/core 1.0.0 → 2.0.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 +34 -0
- package/dist/index.cjs +586 -57
- package/dist/index.d.cts +107 -9
- package/dist/index.d.ts +107 -9
- package/dist/index.js +579 -57
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,17 +1,33 @@
|
|
|
1
1
|
type FieldType = "text" | "textarea" | "number" | "rating" | "select" | "multi-select" | "checkbox" | "radio";
|
|
2
2
|
type ConditionOperator = "equals" | "not_equals" | "contains" | "not_empty";
|
|
3
3
|
type ConditionValue = string | number | boolean;
|
|
4
|
+
type JsonValue = string | number | boolean | null | readonly JsonValue[] | {
|
|
5
|
+
readonly [key: string]: JsonValue;
|
|
6
|
+
};
|
|
7
|
+
/** Arbitrary, JSON-serializable data preserved by every form-engine operation. */
|
|
8
|
+
interface ExtensibleNode {
|
|
9
|
+
readonly metadata?: Readonly<Record<string, JsonValue>>;
|
|
10
|
+
/** Locale -> translated property -> metadata created for that translation. */
|
|
11
|
+
readonly translationMetadata?: Readonly<Record<string, Readonly<Record<string, Readonly<Record<string, JsonValue>>>>>>;
|
|
12
|
+
}
|
|
4
13
|
interface DisplayCondition {
|
|
5
14
|
readonly questionId: string;
|
|
6
15
|
readonly operator: ConditionOperator;
|
|
7
16
|
readonly value?: ConditionValue;
|
|
8
17
|
}
|
|
18
|
+
interface LocalizedText {
|
|
19
|
+
readonly title?: string;
|
|
20
|
+
readonly description?: string;
|
|
21
|
+
readonly completionMessage?: string;
|
|
22
|
+
}
|
|
23
|
+
type SchemaTranslations = Readonly<Record<string, LocalizedText>>;
|
|
9
24
|
type ValidationCode = "required" | "invalid_type" | "min_length" | "max_length" | "pattern" | "min" | "max" | "step" | "invalid_option" | "min_selections" | "max_selections" | "unknown_field";
|
|
10
|
-
interface FieldOption {
|
|
25
|
+
interface FieldOption extends ExtensibleNode {
|
|
11
26
|
readonly id: string;
|
|
12
27
|
readonly label: string;
|
|
28
|
+
readonly translations?: Readonly<Record<string, string>>;
|
|
13
29
|
}
|
|
14
|
-
interface BaseField {
|
|
30
|
+
interface BaseField extends ExtensibleNode {
|
|
15
31
|
readonly id: string;
|
|
16
32
|
readonly type: FieldType;
|
|
17
33
|
readonly title: string;
|
|
@@ -20,6 +36,7 @@ interface BaseField {
|
|
|
20
36
|
readonly required: boolean;
|
|
21
37
|
readonly messages?: Partial<Record<ValidationCode, string>>;
|
|
22
38
|
readonly displayCondition?: DisplayCondition;
|
|
39
|
+
readonly translations?: SchemaTranslations;
|
|
23
40
|
}
|
|
24
41
|
interface TextField extends BaseField {
|
|
25
42
|
readonly type: "text" | "textarea";
|
|
@@ -54,13 +71,26 @@ interface CheckboxField extends BaseField {
|
|
|
54
71
|
readonly type: "checkbox";
|
|
55
72
|
}
|
|
56
73
|
type FormField = TextField | NumberField | RatingField | SelectField | MultiSelectField | CheckboxField;
|
|
57
|
-
interface
|
|
74
|
+
interface FormPage extends ExtensibleNode {
|
|
75
|
+
readonly id: string;
|
|
76
|
+
readonly title?: string;
|
|
77
|
+
readonly description?: string;
|
|
78
|
+
readonly questionIds: readonly string[];
|
|
79
|
+
readonly displayCondition?: DisplayCondition;
|
|
80
|
+
readonly translations?: SchemaTranslations;
|
|
81
|
+
}
|
|
82
|
+
interface FormSchema extends ExtensibleNode {
|
|
58
83
|
readonly id: string;
|
|
59
84
|
readonly version: number;
|
|
60
85
|
readonly title: string;
|
|
61
86
|
readonly description?: string;
|
|
87
|
+
readonly completionMessage?: string;
|
|
62
88
|
readonly submitLabelKey?: string;
|
|
89
|
+
readonly defaultLocale?: string;
|
|
90
|
+
readonly supportedLocales?: readonly string[];
|
|
91
|
+
readonly translations?: SchemaTranslations;
|
|
63
92
|
readonly fields: readonly FormField[];
|
|
93
|
+
readonly pages?: readonly FormPage[];
|
|
64
94
|
}
|
|
65
95
|
type FormValue = string | number | boolean | readonly string[] | undefined;
|
|
66
96
|
type FormValues = Readonly<Record<string, FormValue>>;
|
|
@@ -83,6 +113,7 @@ interface ValidationIssue {
|
|
|
83
113
|
readonly messageKey: string;
|
|
84
114
|
readonly params: Readonly<Record<string, string | number>>;
|
|
85
115
|
}
|
|
116
|
+
type ValidationError = ValidationIssue;
|
|
86
117
|
type AnswerValidationResult = {
|
|
87
118
|
readonly valid: true;
|
|
88
119
|
readonly issues: readonly [];
|
|
@@ -90,7 +121,7 @@ type AnswerValidationResult = {
|
|
|
90
121
|
readonly valid: false;
|
|
91
122
|
readonly issues: readonly ValidationIssue[];
|
|
92
123
|
};
|
|
93
|
-
interface FormSubmission {
|
|
124
|
+
interface FormSubmission extends ExtensibleNode {
|
|
94
125
|
readonly id: string;
|
|
95
126
|
readonly formId: string;
|
|
96
127
|
readonly formVersion: number;
|
|
@@ -105,9 +136,13 @@ interface AsyncTranslationAdapter {
|
|
|
105
136
|
translateText(text: string, targetLocale: string, sourceLocale?: string): Promise<string>;
|
|
106
137
|
translateBatch(texts: readonly string[], targetLocale: string, sourceLocale?: string): Promise<readonly string[]>;
|
|
107
138
|
}
|
|
139
|
+
interface SubmissionQueryOptions {
|
|
140
|
+
readonly since?: string;
|
|
141
|
+
readonly until?: string;
|
|
142
|
+
}
|
|
108
143
|
interface StorageAdapter {
|
|
109
144
|
saveSubmission(submission: FormSubmission): Promise<void>;
|
|
110
|
-
listSubmissions(formId: string, formVersion?: number): Promise<readonly FormSubmission[]>;
|
|
145
|
+
listSubmissions(formId: string, formVersion?: number, options?: SubmissionQueryOptions): Promise<readonly FormSubmission[]>;
|
|
111
146
|
clearResponses?(formId: string): Promise<void>;
|
|
112
147
|
clear(): Promise<void>;
|
|
113
148
|
}
|
|
@@ -159,7 +194,21 @@ interface FormAnalytics {
|
|
|
159
194
|
type Question = FormField;
|
|
160
195
|
type QuestionType = FieldType;
|
|
161
196
|
type ChoiceOption = FieldOption;
|
|
162
|
-
|
|
197
|
+
interface FormResponse extends ExtensibleNode {
|
|
198
|
+
readonly responseId: string;
|
|
199
|
+
readonly formId: string;
|
|
200
|
+
readonly sourceLocale?: string;
|
|
201
|
+
readonly answers: Readonly<Record<string, unknown>>;
|
|
202
|
+
readonly submittedAt: string;
|
|
203
|
+
}
|
|
204
|
+
interface CrossTabulationResult {
|
|
205
|
+
readonly rowQuestionId: string;
|
|
206
|
+
readonly colQuestionId: string;
|
|
207
|
+
readonly matrix: Readonly<Record<string, Readonly<Record<string, number>>>>;
|
|
208
|
+
readonly rowTotals: Readonly<Record<string, number>>;
|
|
209
|
+
readonly colTotals: Readonly<Record<string, number>>;
|
|
210
|
+
readonly grandTotal: number;
|
|
211
|
+
}
|
|
163
212
|
|
|
164
213
|
interface ChoiceDistributionEntry {
|
|
165
214
|
readonly count: number;
|
|
@@ -173,13 +222,36 @@ interface NumericSummary {
|
|
|
173
222
|
}
|
|
174
223
|
declare function calculateChoiceDistribution(responses: readonly FormSubmission[], questionId: string): Record<string, ChoiceDistributionEntry>;
|
|
175
224
|
declare function calculateNumericSummary(responses: readonly FormSubmission[], questionId: string): NumericSummary;
|
|
225
|
+
declare function calculateCrossTabulation(responses: readonly FormSubmission[], rowQuestionId: string, colQuestionId: string): CrossTabulationResult;
|
|
176
226
|
declare function aggregateResponses(schema: FormSchema, submissions: readonly FormSubmission[]): FormAnalytics;
|
|
177
|
-
declare function escapeCsvCell(value: string | number | null | undefined): string;
|
|
227
|
+
declare function escapeCsvCell(value: string | number | boolean | null | undefined, neutralizeFormulas?: boolean): string;
|
|
178
228
|
interface CsvExportOptions {
|
|
179
229
|
readonly withBom?: boolean;
|
|
230
|
+
readonly neutralizeFormulas?: boolean;
|
|
180
231
|
}
|
|
181
232
|
declare function exportResponsesToCsv(schema: FormSchema, responses: readonly FormSubmission[], options?: CsvExportOptions): string;
|
|
182
233
|
|
|
234
|
+
type FormEventType = "response.submitted" | "schema.updated";
|
|
235
|
+
interface FormEvent<T = unknown> {
|
|
236
|
+
readonly id: string;
|
|
237
|
+
readonly type: FormEventType;
|
|
238
|
+
readonly formId: string;
|
|
239
|
+
readonly timestamp: string;
|
|
240
|
+
readonly payload: T;
|
|
241
|
+
}
|
|
242
|
+
interface WebhookConfig {
|
|
243
|
+
readonly url: string;
|
|
244
|
+
readonly secret?: string;
|
|
245
|
+
readonly headers?: Readonly<Record<string, string>>;
|
|
246
|
+
readonly timeoutMs?: number;
|
|
247
|
+
}
|
|
248
|
+
interface WebhookDispatchResult {
|
|
249
|
+
readonly success: boolean;
|
|
250
|
+
readonly status?: number;
|
|
251
|
+
readonly error?: string;
|
|
252
|
+
}
|
|
253
|
+
declare function dispatchWebhook<T>(event: FormEvent<T>, config: WebhookConfig, fetchImpl?: typeof fetch): Promise<WebhookDispatchResult>;
|
|
254
|
+
|
|
183
255
|
type SchemaStructureIssueType = "dangling_condition_reference" | "duplicate_question_id" | "duplicate_choice_id" | "self_condition_reference" | "cyclic_condition_reference";
|
|
184
256
|
interface SchemaStructureIssue {
|
|
185
257
|
readonly type: SchemaStructureIssueType;
|
|
@@ -193,19 +265,45 @@ declare function sanitizeSchema(schema: FormSchema): FormSchema;
|
|
|
193
265
|
declare function validateFormSchema(input: unknown): SchemaValidationResult;
|
|
194
266
|
declare function assertValidFormSchema(input: unknown): asserts input is FormSchema;
|
|
195
267
|
|
|
196
|
-
interface CreateSubmissionOptions {
|
|
268
|
+
interface CreateSubmissionOptions extends ExtensibleNode {
|
|
197
269
|
readonly id: string;
|
|
198
270
|
readonly locale: string;
|
|
199
271
|
readonly submittedAt: string;
|
|
200
272
|
}
|
|
201
273
|
declare function createSubmission(schema: FormSchema, values: FormValues, options: CreateSubmissionOptions): FormSubmission;
|
|
202
274
|
|
|
275
|
+
interface TranslationSlot {
|
|
276
|
+
readonly kind: "form" | "page" | "field" | "option";
|
|
277
|
+
readonly nodeId: string;
|
|
278
|
+
readonly property: "title" | "description" | "label" | "completionMessage";
|
|
279
|
+
readonly locale: string;
|
|
280
|
+
readonly sourceText: string;
|
|
281
|
+
readonly existingText?: string;
|
|
282
|
+
readonly metadata?: Readonly<Record<string, JsonValue>>;
|
|
283
|
+
}
|
|
284
|
+
interface PopulateTranslationOptions {
|
|
285
|
+
readonly overwrite?: "missing-only" | "all";
|
|
286
|
+
readonly shouldOverwrite?: (slot: TranslationSlot) => boolean;
|
|
287
|
+
readonly createMetadata?: (slot: TranslationSlot, translatedText: string) => Readonly<Record<string, JsonValue>>;
|
|
288
|
+
}
|
|
289
|
+
interface TranslationReport {
|
|
290
|
+
readonly updatedSlots: readonly TranslationSlot[];
|
|
291
|
+
readonly skippedSlots: readonly TranslationSlot[];
|
|
292
|
+
}
|
|
293
|
+
declare function resolveLocalizedSchema(schema: FormSchema, targetLocale: string): FormSchema;
|
|
294
|
+
declare function populateSchemaTranslations(schema: FormSchema, targetLocales: readonly string[], adapter: AsyncTranslationAdapter, options?: PopulateTranslationOptions): Promise<{
|
|
295
|
+
readonly schema: FormSchema;
|
|
296
|
+
readonly report: TranslationReport;
|
|
297
|
+
}>;
|
|
203
298
|
declare function resolveFormTranslation(schema: FormSchema, adapter: AsyncTranslationAdapter, targetLocale: string, sourceLocale?: string): Promise<FormSchema>;
|
|
204
299
|
|
|
205
300
|
declare function validateAnswers(schema: FormSchema, values: FormValues): AnswerValidationResult;
|
|
301
|
+
declare function validatePageAnswers(schema: FormSchema, pageIndex: number, values: FormValues): AnswerValidationResult;
|
|
206
302
|
|
|
207
303
|
declare function isQuestionVisible(question: FormField, currentAnswers: Readonly<Record<string, unknown>>): boolean;
|
|
304
|
+
declare function isDisplayConditionSatisfied(condition: DisplayCondition | undefined, currentAnswers: Readonly<Record<string, unknown>>): boolean;
|
|
305
|
+
declare function calculatePageVisibility(schema: FormSchema, currentAnswers: Readonly<Record<string, unknown>>): Readonly<Record<string, boolean>>;
|
|
208
306
|
declare function calculateFieldVisibility(schema: FormSchema, currentAnswers: Readonly<Record<string, unknown>>): Readonly<Record<string, boolean>>;
|
|
209
307
|
declare function selectVisibleAnswers(schema: FormSchema, currentAnswers: FormValues): FormValues;
|
|
210
308
|
|
|
211
|
-
export { type AnswerValidationResult, type AsyncTranslationAdapter, type BaseField, type CheckboxField, type CheckboxQuestionAggregate, type ChoiceDistributionEntry, type ChoiceOption, type ChoiceQuestionAggregate, type ConditionOperator, type ConditionValue, type CreateSubmissionOptions, type CsvExportOptions, type DisplayCondition, type FieldOption, type FieldType, type FormAnalytics, type FormField, type FormResponse, type FormSchema, type FormStorageAdapter, type FormSubmission, type FormValue, type FormValues, type MultiSelectField, type NumberField, type NumberQuestionAggregate, type NumericSummary, type OptionAggregate, type Question, type QuestionAggregate, type QuestionType, type RatingField, type SchemaIssue, type SchemaStructureIssue, type SchemaStructureIssueType, type SchemaValidationResult, type SelectField, type StorageAdapter, type TextField, type TextQuestionAggregate, type TranslationAdapter, type ValidationCode, type ValidationIssue, aggregateResponses, assertValidFormSchema, calculateChoiceDistribution, calculateFieldVisibility, calculateNumericSummary, createSubmission, escapeCsvCell, exportResponsesToCsv, isQuestionVisible, resolveFormTranslation, sanitizeSchema, selectVisibleAnswers, validateAnswers, validateFormSchema, validateSchemaStructure };
|
|
309
|
+
export { type AnswerValidationResult, type AsyncTranslationAdapter, type BaseField, type CheckboxField, type CheckboxQuestionAggregate, type ChoiceDistributionEntry, type ChoiceOption, type ChoiceQuestionAggregate, type ConditionOperator, type ConditionValue, type CreateSubmissionOptions, type CrossTabulationResult, type CsvExportOptions, type DisplayCondition, type ExtensibleNode, type FieldOption, type FieldType, type FormAnalytics, type FormEvent, type FormEventType, type FormField, type FormPage, type FormResponse, type FormSchema, type FormStorageAdapter, type FormSubmission, type FormValue, type FormValues, type JsonValue, type LocalizedText, type MultiSelectField, type NumberField, type NumberQuestionAggregate, type NumericSummary, type OptionAggregate, type PopulateTranslationOptions, type Question, type QuestionAggregate, type QuestionType, type RatingField, type SchemaIssue, type SchemaStructureIssue, type SchemaStructureIssueType, type SchemaTranslations, type SchemaValidationResult, type SelectField, type StorageAdapter, type SubmissionQueryOptions, type TextField, type TextQuestionAggregate, type TranslationAdapter, type TranslationReport, type TranslationSlot, type ValidationCode, type ValidationError, type ValidationIssue, type WebhookConfig, type WebhookDispatchResult, aggregateResponses, assertValidFormSchema, calculateChoiceDistribution, calculateCrossTabulation, calculateFieldVisibility, calculateNumericSummary, calculatePageVisibility, createSubmission, dispatchWebhook, escapeCsvCell, exportResponsesToCsv, isDisplayConditionSatisfied, isQuestionVisible, populateSchemaTranslations, resolveFormTranslation, resolveLocalizedSchema, sanitizeSchema, selectVisibleAnswers, validateAnswers, validateFormSchema, validatePageAnswers, validateSchemaStructure };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,17 +1,33 @@
|
|
|
1
1
|
type FieldType = "text" | "textarea" | "number" | "rating" | "select" | "multi-select" | "checkbox" | "radio";
|
|
2
2
|
type ConditionOperator = "equals" | "not_equals" | "contains" | "not_empty";
|
|
3
3
|
type ConditionValue = string | number | boolean;
|
|
4
|
+
type JsonValue = string | number | boolean | null | readonly JsonValue[] | {
|
|
5
|
+
readonly [key: string]: JsonValue;
|
|
6
|
+
};
|
|
7
|
+
/** Arbitrary, JSON-serializable data preserved by every form-engine operation. */
|
|
8
|
+
interface ExtensibleNode {
|
|
9
|
+
readonly metadata?: Readonly<Record<string, JsonValue>>;
|
|
10
|
+
/** Locale -> translated property -> metadata created for that translation. */
|
|
11
|
+
readonly translationMetadata?: Readonly<Record<string, Readonly<Record<string, Readonly<Record<string, JsonValue>>>>>>;
|
|
12
|
+
}
|
|
4
13
|
interface DisplayCondition {
|
|
5
14
|
readonly questionId: string;
|
|
6
15
|
readonly operator: ConditionOperator;
|
|
7
16
|
readonly value?: ConditionValue;
|
|
8
17
|
}
|
|
18
|
+
interface LocalizedText {
|
|
19
|
+
readonly title?: string;
|
|
20
|
+
readonly description?: string;
|
|
21
|
+
readonly completionMessage?: string;
|
|
22
|
+
}
|
|
23
|
+
type SchemaTranslations = Readonly<Record<string, LocalizedText>>;
|
|
9
24
|
type ValidationCode = "required" | "invalid_type" | "min_length" | "max_length" | "pattern" | "min" | "max" | "step" | "invalid_option" | "min_selections" | "max_selections" | "unknown_field";
|
|
10
|
-
interface FieldOption {
|
|
25
|
+
interface FieldOption extends ExtensibleNode {
|
|
11
26
|
readonly id: string;
|
|
12
27
|
readonly label: string;
|
|
28
|
+
readonly translations?: Readonly<Record<string, string>>;
|
|
13
29
|
}
|
|
14
|
-
interface BaseField {
|
|
30
|
+
interface BaseField extends ExtensibleNode {
|
|
15
31
|
readonly id: string;
|
|
16
32
|
readonly type: FieldType;
|
|
17
33
|
readonly title: string;
|
|
@@ -20,6 +36,7 @@ interface BaseField {
|
|
|
20
36
|
readonly required: boolean;
|
|
21
37
|
readonly messages?: Partial<Record<ValidationCode, string>>;
|
|
22
38
|
readonly displayCondition?: DisplayCondition;
|
|
39
|
+
readonly translations?: SchemaTranslations;
|
|
23
40
|
}
|
|
24
41
|
interface TextField extends BaseField {
|
|
25
42
|
readonly type: "text" | "textarea";
|
|
@@ -54,13 +71,26 @@ interface CheckboxField extends BaseField {
|
|
|
54
71
|
readonly type: "checkbox";
|
|
55
72
|
}
|
|
56
73
|
type FormField = TextField | NumberField | RatingField | SelectField | MultiSelectField | CheckboxField;
|
|
57
|
-
interface
|
|
74
|
+
interface FormPage extends ExtensibleNode {
|
|
75
|
+
readonly id: string;
|
|
76
|
+
readonly title?: string;
|
|
77
|
+
readonly description?: string;
|
|
78
|
+
readonly questionIds: readonly string[];
|
|
79
|
+
readonly displayCondition?: DisplayCondition;
|
|
80
|
+
readonly translations?: SchemaTranslations;
|
|
81
|
+
}
|
|
82
|
+
interface FormSchema extends ExtensibleNode {
|
|
58
83
|
readonly id: string;
|
|
59
84
|
readonly version: number;
|
|
60
85
|
readonly title: string;
|
|
61
86
|
readonly description?: string;
|
|
87
|
+
readonly completionMessage?: string;
|
|
62
88
|
readonly submitLabelKey?: string;
|
|
89
|
+
readonly defaultLocale?: string;
|
|
90
|
+
readonly supportedLocales?: readonly string[];
|
|
91
|
+
readonly translations?: SchemaTranslations;
|
|
63
92
|
readonly fields: readonly FormField[];
|
|
93
|
+
readonly pages?: readonly FormPage[];
|
|
64
94
|
}
|
|
65
95
|
type FormValue = string | number | boolean | readonly string[] | undefined;
|
|
66
96
|
type FormValues = Readonly<Record<string, FormValue>>;
|
|
@@ -83,6 +113,7 @@ interface ValidationIssue {
|
|
|
83
113
|
readonly messageKey: string;
|
|
84
114
|
readonly params: Readonly<Record<string, string | number>>;
|
|
85
115
|
}
|
|
116
|
+
type ValidationError = ValidationIssue;
|
|
86
117
|
type AnswerValidationResult = {
|
|
87
118
|
readonly valid: true;
|
|
88
119
|
readonly issues: readonly [];
|
|
@@ -90,7 +121,7 @@ type AnswerValidationResult = {
|
|
|
90
121
|
readonly valid: false;
|
|
91
122
|
readonly issues: readonly ValidationIssue[];
|
|
92
123
|
};
|
|
93
|
-
interface FormSubmission {
|
|
124
|
+
interface FormSubmission extends ExtensibleNode {
|
|
94
125
|
readonly id: string;
|
|
95
126
|
readonly formId: string;
|
|
96
127
|
readonly formVersion: number;
|
|
@@ -105,9 +136,13 @@ interface AsyncTranslationAdapter {
|
|
|
105
136
|
translateText(text: string, targetLocale: string, sourceLocale?: string): Promise<string>;
|
|
106
137
|
translateBatch(texts: readonly string[], targetLocale: string, sourceLocale?: string): Promise<readonly string[]>;
|
|
107
138
|
}
|
|
139
|
+
interface SubmissionQueryOptions {
|
|
140
|
+
readonly since?: string;
|
|
141
|
+
readonly until?: string;
|
|
142
|
+
}
|
|
108
143
|
interface StorageAdapter {
|
|
109
144
|
saveSubmission(submission: FormSubmission): Promise<void>;
|
|
110
|
-
listSubmissions(formId: string, formVersion?: number): Promise<readonly FormSubmission[]>;
|
|
145
|
+
listSubmissions(formId: string, formVersion?: number, options?: SubmissionQueryOptions): Promise<readonly FormSubmission[]>;
|
|
111
146
|
clearResponses?(formId: string): Promise<void>;
|
|
112
147
|
clear(): Promise<void>;
|
|
113
148
|
}
|
|
@@ -159,7 +194,21 @@ interface FormAnalytics {
|
|
|
159
194
|
type Question = FormField;
|
|
160
195
|
type QuestionType = FieldType;
|
|
161
196
|
type ChoiceOption = FieldOption;
|
|
162
|
-
|
|
197
|
+
interface FormResponse extends ExtensibleNode {
|
|
198
|
+
readonly responseId: string;
|
|
199
|
+
readonly formId: string;
|
|
200
|
+
readonly sourceLocale?: string;
|
|
201
|
+
readonly answers: Readonly<Record<string, unknown>>;
|
|
202
|
+
readonly submittedAt: string;
|
|
203
|
+
}
|
|
204
|
+
interface CrossTabulationResult {
|
|
205
|
+
readonly rowQuestionId: string;
|
|
206
|
+
readonly colQuestionId: string;
|
|
207
|
+
readonly matrix: Readonly<Record<string, Readonly<Record<string, number>>>>;
|
|
208
|
+
readonly rowTotals: Readonly<Record<string, number>>;
|
|
209
|
+
readonly colTotals: Readonly<Record<string, number>>;
|
|
210
|
+
readonly grandTotal: number;
|
|
211
|
+
}
|
|
163
212
|
|
|
164
213
|
interface ChoiceDistributionEntry {
|
|
165
214
|
readonly count: number;
|
|
@@ -173,13 +222,36 @@ interface NumericSummary {
|
|
|
173
222
|
}
|
|
174
223
|
declare function calculateChoiceDistribution(responses: readonly FormSubmission[], questionId: string): Record<string, ChoiceDistributionEntry>;
|
|
175
224
|
declare function calculateNumericSummary(responses: readonly FormSubmission[], questionId: string): NumericSummary;
|
|
225
|
+
declare function calculateCrossTabulation(responses: readonly FormSubmission[], rowQuestionId: string, colQuestionId: string): CrossTabulationResult;
|
|
176
226
|
declare function aggregateResponses(schema: FormSchema, submissions: readonly FormSubmission[]): FormAnalytics;
|
|
177
|
-
declare function escapeCsvCell(value: string | number | null | undefined): string;
|
|
227
|
+
declare function escapeCsvCell(value: string | number | boolean | null | undefined, neutralizeFormulas?: boolean): string;
|
|
178
228
|
interface CsvExportOptions {
|
|
179
229
|
readonly withBom?: boolean;
|
|
230
|
+
readonly neutralizeFormulas?: boolean;
|
|
180
231
|
}
|
|
181
232
|
declare function exportResponsesToCsv(schema: FormSchema, responses: readonly FormSubmission[], options?: CsvExportOptions): string;
|
|
182
233
|
|
|
234
|
+
type FormEventType = "response.submitted" | "schema.updated";
|
|
235
|
+
interface FormEvent<T = unknown> {
|
|
236
|
+
readonly id: string;
|
|
237
|
+
readonly type: FormEventType;
|
|
238
|
+
readonly formId: string;
|
|
239
|
+
readonly timestamp: string;
|
|
240
|
+
readonly payload: T;
|
|
241
|
+
}
|
|
242
|
+
interface WebhookConfig {
|
|
243
|
+
readonly url: string;
|
|
244
|
+
readonly secret?: string;
|
|
245
|
+
readonly headers?: Readonly<Record<string, string>>;
|
|
246
|
+
readonly timeoutMs?: number;
|
|
247
|
+
}
|
|
248
|
+
interface WebhookDispatchResult {
|
|
249
|
+
readonly success: boolean;
|
|
250
|
+
readonly status?: number;
|
|
251
|
+
readonly error?: string;
|
|
252
|
+
}
|
|
253
|
+
declare function dispatchWebhook<T>(event: FormEvent<T>, config: WebhookConfig, fetchImpl?: typeof fetch): Promise<WebhookDispatchResult>;
|
|
254
|
+
|
|
183
255
|
type SchemaStructureIssueType = "dangling_condition_reference" | "duplicate_question_id" | "duplicate_choice_id" | "self_condition_reference" | "cyclic_condition_reference";
|
|
184
256
|
interface SchemaStructureIssue {
|
|
185
257
|
readonly type: SchemaStructureIssueType;
|
|
@@ -193,19 +265,45 @@ declare function sanitizeSchema(schema: FormSchema): FormSchema;
|
|
|
193
265
|
declare function validateFormSchema(input: unknown): SchemaValidationResult;
|
|
194
266
|
declare function assertValidFormSchema(input: unknown): asserts input is FormSchema;
|
|
195
267
|
|
|
196
|
-
interface CreateSubmissionOptions {
|
|
268
|
+
interface CreateSubmissionOptions extends ExtensibleNode {
|
|
197
269
|
readonly id: string;
|
|
198
270
|
readonly locale: string;
|
|
199
271
|
readonly submittedAt: string;
|
|
200
272
|
}
|
|
201
273
|
declare function createSubmission(schema: FormSchema, values: FormValues, options: CreateSubmissionOptions): FormSubmission;
|
|
202
274
|
|
|
275
|
+
interface TranslationSlot {
|
|
276
|
+
readonly kind: "form" | "page" | "field" | "option";
|
|
277
|
+
readonly nodeId: string;
|
|
278
|
+
readonly property: "title" | "description" | "label" | "completionMessage";
|
|
279
|
+
readonly locale: string;
|
|
280
|
+
readonly sourceText: string;
|
|
281
|
+
readonly existingText?: string;
|
|
282
|
+
readonly metadata?: Readonly<Record<string, JsonValue>>;
|
|
283
|
+
}
|
|
284
|
+
interface PopulateTranslationOptions {
|
|
285
|
+
readonly overwrite?: "missing-only" | "all";
|
|
286
|
+
readonly shouldOverwrite?: (slot: TranslationSlot) => boolean;
|
|
287
|
+
readonly createMetadata?: (slot: TranslationSlot, translatedText: string) => Readonly<Record<string, JsonValue>>;
|
|
288
|
+
}
|
|
289
|
+
interface TranslationReport {
|
|
290
|
+
readonly updatedSlots: readonly TranslationSlot[];
|
|
291
|
+
readonly skippedSlots: readonly TranslationSlot[];
|
|
292
|
+
}
|
|
293
|
+
declare function resolveLocalizedSchema(schema: FormSchema, targetLocale: string): FormSchema;
|
|
294
|
+
declare function populateSchemaTranslations(schema: FormSchema, targetLocales: readonly string[], adapter: AsyncTranslationAdapter, options?: PopulateTranslationOptions): Promise<{
|
|
295
|
+
readonly schema: FormSchema;
|
|
296
|
+
readonly report: TranslationReport;
|
|
297
|
+
}>;
|
|
203
298
|
declare function resolveFormTranslation(schema: FormSchema, adapter: AsyncTranslationAdapter, targetLocale: string, sourceLocale?: string): Promise<FormSchema>;
|
|
204
299
|
|
|
205
300
|
declare function validateAnswers(schema: FormSchema, values: FormValues): AnswerValidationResult;
|
|
301
|
+
declare function validatePageAnswers(schema: FormSchema, pageIndex: number, values: FormValues): AnswerValidationResult;
|
|
206
302
|
|
|
207
303
|
declare function isQuestionVisible(question: FormField, currentAnswers: Readonly<Record<string, unknown>>): boolean;
|
|
304
|
+
declare function isDisplayConditionSatisfied(condition: DisplayCondition | undefined, currentAnswers: Readonly<Record<string, unknown>>): boolean;
|
|
305
|
+
declare function calculatePageVisibility(schema: FormSchema, currentAnswers: Readonly<Record<string, unknown>>): Readonly<Record<string, boolean>>;
|
|
208
306
|
declare function calculateFieldVisibility(schema: FormSchema, currentAnswers: Readonly<Record<string, unknown>>): Readonly<Record<string, boolean>>;
|
|
209
307
|
declare function selectVisibleAnswers(schema: FormSchema, currentAnswers: FormValues): FormValues;
|
|
210
308
|
|
|
211
|
-
export { type AnswerValidationResult, type AsyncTranslationAdapter, type BaseField, type CheckboxField, type CheckboxQuestionAggregate, type ChoiceDistributionEntry, type ChoiceOption, type ChoiceQuestionAggregate, type ConditionOperator, type ConditionValue, type CreateSubmissionOptions, type CsvExportOptions, type DisplayCondition, type FieldOption, type FieldType, type FormAnalytics, type FormField, type FormResponse, type FormSchema, type FormStorageAdapter, type FormSubmission, type FormValue, type FormValues, type MultiSelectField, type NumberField, type NumberQuestionAggregate, type NumericSummary, type OptionAggregate, type Question, type QuestionAggregate, type QuestionType, type RatingField, type SchemaIssue, type SchemaStructureIssue, type SchemaStructureIssueType, type SchemaValidationResult, type SelectField, type StorageAdapter, type TextField, type TextQuestionAggregate, type TranslationAdapter, type ValidationCode, type ValidationIssue, aggregateResponses, assertValidFormSchema, calculateChoiceDistribution, calculateFieldVisibility, calculateNumericSummary, createSubmission, escapeCsvCell, exportResponsesToCsv, isQuestionVisible, resolveFormTranslation, sanitizeSchema, selectVisibleAnswers, validateAnswers, validateFormSchema, validateSchemaStructure };
|
|
309
|
+
export { type AnswerValidationResult, type AsyncTranslationAdapter, type BaseField, type CheckboxField, type CheckboxQuestionAggregate, type ChoiceDistributionEntry, type ChoiceOption, type ChoiceQuestionAggregate, type ConditionOperator, type ConditionValue, type CreateSubmissionOptions, type CrossTabulationResult, type CsvExportOptions, type DisplayCondition, type ExtensibleNode, type FieldOption, type FieldType, type FormAnalytics, type FormEvent, type FormEventType, type FormField, type FormPage, type FormResponse, type FormSchema, type FormStorageAdapter, type FormSubmission, type FormValue, type FormValues, type JsonValue, type LocalizedText, type MultiSelectField, type NumberField, type NumberQuestionAggregate, type NumericSummary, type OptionAggregate, type PopulateTranslationOptions, type Question, type QuestionAggregate, type QuestionType, type RatingField, type SchemaIssue, type SchemaStructureIssue, type SchemaStructureIssueType, type SchemaTranslations, type SchemaValidationResult, type SelectField, type StorageAdapter, type SubmissionQueryOptions, type TextField, type TextQuestionAggregate, type TranslationAdapter, type TranslationReport, type TranslationSlot, type ValidationCode, type ValidationError, type ValidationIssue, type WebhookConfig, type WebhookDispatchResult, aggregateResponses, assertValidFormSchema, calculateChoiceDistribution, calculateCrossTabulation, calculateFieldVisibility, calculateNumericSummary, calculatePageVisibility, createSubmission, dispatchWebhook, escapeCsvCell, exportResponsesToCsv, isDisplayConditionSatisfied, isQuestionVisible, populateSchemaTranslations, resolveFormTranslation, resolveLocalizedSchema, sanitizeSchema, selectVisibleAnswers, validateAnswers, validateFormSchema, validatePageAnswers, validateSchemaStructure };
|