@frt-platform/report-core 1.2.1 → 1.4.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.mts CHANGED
@@ -68,80 +68,36 @@ declare const ReportTemplateSchemaValidator: z.ZodObject<{
68
68
  }>;
69
69
  type ReportTemplateSchema = z.infer<typeof ReportTemplateSchemaValidator>;
70
70
 
71
- declare const DEFAULT_FIELD_LABEL = "Untitled question";
72
- declare const CORE_FIELD_DEFAULTS: Record<ReportTemplateFieldType, Record<string, unknown>>;
73
-
74
- declare function createUniqueId(prefix: string, existing: Iterable<string>): string;
75
-
76
71
  declare function migrateLegacySchema(raw: unknown): unknown;
77
72
 
78
73
  declare function normalizeReportTemplateSchema(schema: ReportTemplateSchema): ReportTemplateSchema;
79
74
  declare function parseReportTemplateSchema(raw: unknown): ReportTemplateSchema;
80
75
  declare function parseReportTemplateSchemaFromString(raw: string): ReportTemplateSchema;
81
- declare function serializeReportTemplateSchema(schema: ReportTemplateSchema): string;
82
-
83
- declare function buildBaseFieldSchema(field: ReportTemplateField): ZodTypeAny;
84
- declare function buildResponseSchemaWithConditions(template: ReportTemplateSchema, response: Record<string, any>): z.ZodObject<Record<string, ZodTypeAny>>;
85
- declare function validateReportResponse(template: ReportTemplateSchema, data: unknown): Record<string, unknown>;
86
- type FieldErrorCode = "response.invalid_root" | "field.required" | "field.invalid_type" | "field.too_small" | "field.too_big" | "field.invalid_option" | "field.custom";
87
- interface ResponseFieldError {
88
- /** field id (template-level id) */
89
- fieldId: string;
90
- /** section id that owns this field (if known) */
91
- sectionId?: string;
92
- /** section title (if available in template) */
93
- sectionTitle?: string;
94
- /** human label of the field */
95
- label?: string;
96
- /** normalized error code */
97
- code: FieldErrorCode;
98
- /** human-readable message (already enriched with section / label) */
99
- message: string;
100
- /** original Zod issue (for debugging / logging) */
101
- rawIssue?: ZodIssue;
76
+ interface SerializeOptions {
77
+ /**
78
+ * If true (default), output human-readable JSON with 2-space indentation.
79
+ * If false, output a compact single-line JSON string.
80
+ */
81
+ pretty?: boolean;
82
+ /**
83
+ * If true, sections will be sorted by their `id` before serialization.
84
+ * This is useful for deterministic diffs across environments.
85
+ */
86
+ sortSectionsById?: boolean;
87
+ /**
88
+ * If true, fields within each section will be sorted by their `id`
89
+ * before serialization. Also useful for stable diffs.
90
+ */
91
+ sortFieldsById?: boolean;
102
92
  }
103
93
  /**
104
- * Validates a response against a template, but instead of throwing,
105
- * returns a structured error object with:
106
- * - section title
107
- * - field label
108
- * - normalized error code
94
+ * Serialize a template schema into JSON.
109
95
  *
110
- * Ideal for UI error display.
96
+ * - Optional pretty-printing (default: true)
97
+ * - Optional deterministic sorting of sections and fields by ID
98
+ * to make git diffs and code reviews cleaner.
111
99
  */
112
- declare function validateReportResponseDetailed(template: ReportTemplateSchema, data: unknown): {
113
- success: true;
114
- value: Record<string, unknown>;
115
- } | {
116
- success: false;
117
- errors: ResponseFieldError[];
118
- };
119
- type TemplateFieldUnion<TTemplate> = TTemplate extends {
120
- sections: readonly (infer S)[];
121
- } ? S extends {
122
- fields: readonly (infer F)[];
123
- } ? F : never : never;
124
- type BaseFieldValue<TField extends {
125
- type: ReportTemplateFieldType;
126
- required?: boolean;
127
- options?: readonly string[] | string[];
128
- }> = TField["type"] extends "shortText" | "longText" ? string : TField["type"] extends "number" ? number : TField["type"] extends "date" ? string : TField["type"] extends "checkbox" ? boolean : TField["type"] extends "singleSelect" ? (TField["options"] extends readonly (infer O)[] ? O : TField["options"] extends (infer O)[] ? O : string) : TField["type"] extends "multiSelect" ? (TField["options"] extends readonly (infer O)[] ? O[] : TField["options"] extends (infer O)[] ? O[] : string[]) : unknown;
129
- type FieldResponseValue<TField extends {
130
- type: ReportTemplateFieldType;
131
- required?: boolean;
132
- }> = TField["required"] extends true ? BaseFieldValue<TField> : BaseFieldValue<TField> | undefined;
133
- type InferResponse<TTemplate extends {
134
- sections: readonly {
135
- fields: readonly {
136
- id: string;
137
- type: ReportTemplateFieldType;
138
- required?: boolean;
139
- options?: readonly string[] | string[];
140
- }[];
141
- }[];
142
- }> = {
143
- [F in TemplateFieldUnion<TTemplate> as F["id"]]: FieldResponseValue<F>;
144
- };
100
+ declare function serializeReportTemplateSchema(schema: ReportTemplateSchema, options?: SerializeOptions): string;
145
101
 
146
102
  interface TemplateDiff {
147
103
  addedSections: Array<{
@@ -201,6 +157,53 @@ interface TemplateDiff {
201
157
  }
202
158
  declare function diffTemplates(before: ReportTemplateSchema, after: ReportTemplateSchema): TemplateDiff;
203
159
 
160
+ /**
161
+ * Minimal JSON Schema type for our purposes.
162
+ * Flexible, with an index signature to allow vendor extensions (x-frt-*).
163
+ */
164
+ interface JSONSchema {
165
+ $schema?: string;
166
+ $id?: string;
167
+ type?: "object" | "string" | "number" | "boolean" | "array" | "null";
168
+ properties?: Record<string, JSONSchema>;
169
+ items?: JSONSchema;
170
+ required?: string[];
171
+ enum?: any[];
172
+ minLength?: number;
173
+ maxLength?: number;
174
+ minimum?: number;
175
+ maximum?: number;
176
+ minItems?: number;
177
+ maxItems?: number;
178
+ description?: string;
179
+ title?: string;
180
+ default?: any;
181
+ format?: string;
182
+ additionalProperties?: boolean;
183
+ [key: string]: any;
184
+ }
185
+ /**
186
+ * Export a report template as a JSON Schema "object" definition.
187
+ *
188
+ * - Each field becomes a property keyed by its `id`
189
+ * - Unconditional `required: true` fields are added to the JSON Schema `required` array
190
+ * - Conditional logic is preserved via `x-frt-visibleIf` / `x-frt-requiredIf`
191
+ * but NOT enforced in the core JSON Schema (since it's beyond standard JSON Schema).
192
+ */
193
+ declare function exportJSONSchema(template: ReportTemplateSchema): JSONSchema;
194
+
195
+ declare const DEFAULT_FIELD_LABEL = "Untitled question";
196
+ declare const CORE_FIELD_DEFAULTS: Record<ReportTemplateFieldType, Record<string, unknown>>;
197
+
198
+ /**
199
+ * Helper for generating a unique id in a *local* namespace, typically in
200
+ * UI/builders when adding new sections/fields client-side.
201
+ *
202
+ * Note: Core template normalization uses its own normalizeId/ensureUniqueId
203
+ * logic so that persisted IDs stay stable and backwards compatible.
204
+ */
205
+ declare function createUniqueId(prefix: string, existing: Iterable<string>): string;
206
+
204
207
  /** -------------------------------------------------------------
205
208
  * FieldRegistryEntry
206
209
  * --------------------------------------------------------------
@@ -250,39 +253,90 @@ declare const FieldRegistry: FieldRegistryClass;
250
253
  */
251
254
  declare function evaluateCondition(condition: SimpleCondition, response: Record<string, any>): boolean;
252
255
 
256
+ declare function buildBaseFieldSchema(field: ReportTemplateField): ZodTypeAny;
257
+ declare function buildResponseSchemaWithConditions(template: ReportTemplateSchema, response: Record<string, any>): z.ZodObject<Record<string, ZodTypeAny>>;
253
258
  /**
254
- * Minimal JSON Schema type for our purposes.
255
- * Flexible, with an index signature to allow vendor extensions (x-frt-*).
259
+ * Build a Zod object schema for a template *without* needing a response object.
260
+ *
261
+ * Notes:
262
+ * - All conditional logic is evaluated against an empty response `{}`.
263
+ * - This means:
264
+ * - `visibleIf` / `requiredIf` that depend on other fields will typically
265
+ * evaluate to false.
266
+ *
267
+ * This is mainly useful for:
268
+ * - Static type inference
269
+ * - Generic tooling / OpenAPI style usage
270
+ * - Situations where you just want the overall "shape" of a response.
256
271
  */
257
- interface JSONSchema {
258
- $schema?: string;
259
- $id?: string;
260
- type?: "object" | "string" | "number" | "boolean" | "array" | "null";
261
- properties?: Record<string, JSONSchema>;
262
- items?: JSONSchema;
263
- required?: string[];
264
- enum?: any[];
265
- minLength?: number;
266
- maxLength?: number;
267
- minimum?: number;
268
- maximum?: number;
269
- minItems?: number;
270
- maxItems?: number;
271
- description?: string;
272
- title?: string;
273
- default?: any;
274
- format?: string;
275
- additionalProperties?: boolean;
276
- [key: string]: any;
272
+ declare function buildResponseSchema(template: ReportTemplateSchema): z.ZodObject<Record<string, ZodTypeAny>>;
273
+ declare function validateReportResponse(template: ReportTemplateSchema, data: unknown): Record<string, unknown>;
274
+ type FieldErrorCode = "response.invalid_root" | "field.required" | "field.invalid_type" | "field.too_small" | "field.too_big" | "field.invalid_option" | "field.custom";
275
+ interface ResponseFieldError {
276
+ /** field id (template-level id) */
277
+ fieldId: string;
278
+ /** section id that owns this field (if known) */
279
+ sectionId?: string;
280
+ /** section title (if available in template) */
281
+ sectionTitle?: string;
282
+ /** human label of the field */
283
+ label?: string;
284
+ /** normalized error code */
285
+ code: FieldErrorCode;
286
+ /** human-readable message (already enriched with section / label) */
287
+ message: string;
288
+ /** original Zod issue (for debugging / logging) */
289
+ rawIssue?: ZodIssue;
277
290
  }
278
291
  /**
279
- * Export a report template as a JSON Schema "object" definition.
292
+ * Validates a response against a template, but instead of throwing,
293
+ * returns a structured error object with:
294
+ * - section title
295
+ * - field label
296
+ * - normalized error code
280
297
  *
281
- * - Each field becomes a property keyed by its `id`
282
- * - Unconditional `required: true` fields are added to the JSON Schema `required` array
283
- * - Conditional logic is preserved via `x-frt-visibleIf` / `x-frt-requiredIf`
284
- * but NOT enforced in the core JSON Schema (since it's beyond standard JSON Schema).
298
+ * Ideal for UI error display.
285
299
  */
286
- declare function exportJSONSchema(template: ReportTemplateSchema): JSONSchema;
300
+ declare function validateReportResponseDetailed(template: ReportTemplateSchema, data: unknown): {
301
+ success: true;
302
+ value: Record<string, unknown>;
303
+ } | {
304
+ success: false;
305
+ errors: ResponseFieldError[];
306
+ };
307
+ /**
308
+ * Helper to turn a thrown ZodError (e.g. from validateReportResponse)
309
+ * into the same ResponseFieldError[] shape used by
310
+ * validateReportResponseDetailed.
311
+ *
312
+ * Returns null if the error is not a ZodError.
313
+ */
314
+ declare function explainValidationError(template: ReportTemplateSchema, error: unknown): ResponseFieldError[] | null;
315
+ type TemplateFieldUnion<TTemplate> = TTemplate extends {
316
+ sections: readonly (infer S)[];
317
+ } ? S extends {
318
+ fields: readonly (infer F)[];
319
+ } ? F : never : never;
320
+ type BaseFieldValue<TField extends {
321
+ type: ReportTemplateFieldType;
322
+ required?: boolean;
323
+ options?: readonly string[] | string[];
324
+ }> = TField["type"] extends "shortText" | "longText" ? string : TField["type"] extends "number" ? number : TField["type"] extends "date" ? string : TField["type"] extends "checkbox" ? boolean : TField["type"] extends "singleSelect" ? (TField["options"] extends readonly (infer O)[] ? O : TField["options"] extends (infer O)[] ? O : string) : TField["type"] extends "multiSelect" ? (TField["options"] extends readonly (infer O)[] ? O[] : TField["options"] extends (infer O)[] ? O[] : string[]) : TField["type"] extends "repeatGroup" ? Array<Record<string, unknown>> : unknown;
325
+ type FieldResponseValue<TField extends {
326
+ type: ReportTemplateFieldType;
327
+ required?: boolean;
328
+ }> = TField["required"] extends true ? BaseFieldValue<TField> : BaseFieldValue<TField> | undefined;
329
+ type InferResponse<TTemplate extends {
330
+ sections: readonly {
331
+ fields: readonly {
332
+ id: string;
333
+ type: ReportTemplateFieldType;
334
+ required?: boolean;
335
+ options?: readonly string[] | string[];
336
+ }[];
337
+ }[];
338
+ }> = {
339
+ [F in TemplateFieldUnion<TTemplate> as F["id"]]: FieldResponseValue<F>;
340
+ };
287
341
 
288
- export { CORE_FIELD_DEFAULTS, Condition, DEFAULT_FIELD_LABEL, type FieldErrorCode, FieldRegistry, type FieldRegistryEntry, type InferResponse, type JSONSchema, REPORT_TEMPLATE_FIELD_TYPES, REPORT_TEMPLATE_VERSION, RepeatGroupFieldSchema, type ReportTemplateField, ReportTemplateFieldSchema, type ReportTemplateFieldType, type ReportTemplateSchema, ReportTemplateSchemaValidator, type ReportTemplateSection, ReportTemplateSectionSchema, type ResponseFieldError, type SimpleCondition, type TemplateDiff, buildBaseFieldSchema, buildResponseSchemaWithConditions, createUniqueId, diffTemplates, evaluateCondition, exportJSONSchema, migrateLegacySchema, normalizeReportTemplateSchema, parseReportTemplateSchema, parseReportTemplateSchemaFromString, serializeReportTemplateSchema, validateReportResponse, validateReportResponseDetailed };
342
+ export { CORE_FIELD_DEFAULTS, Condition, DEFAULT_FIELD_LABEL, type FieldErrorCode, FieldRegistry, type FieldRegistryEntry, type InferResponse, type JSONSchema, REPORT_TEMPLATE_FIELD_TYPES, REPORT_TEMPLATE_VERSION, RepeatGroupFieldSchema, type ReportTemplateField, ReportTemplateFieldSchema, type ReportTemplateFieldType, type ReportTemplateSchema, ReportTemplateSchemaValidator, type ReportTemplateSection, ReportTemplateSectionSchema, type ResponseFieldError, type SerializeOptions, type SimpleCondition, type TemplateDiff, buildBaseFieldSchema, buildResponseSchema, buildResponseSchemaWithConditions, createUniqueId, diffTemplates, evaluateCondition, explainValidationError, exportJSONSchema, migrateLegacySchema, normalizeReportTemplateSchema, parseReportTemplateSchema, parseReportTemplateSchemaFromString, serializeReportTemplateSchema, validateReportResponse, validateReportResponseDetailed };
package/dist/index.d.ts CHANGED
@@ -68,80 +68,36 @@ declare const ReportTemplateSchemaValidator: z.ZodObject<{
68
68
  }>;
69
69
  type ReportTemplateSchema = z.infer<typeof ReportTemplateSchemaValidator>;
70
70
 
71
- declare const DEFAULT_FIELD_LABEL = "Untitled question";
72
- declare const CORE_FIELD_DEFAULTS: Record<ReportTemplateFieldType, Record<string, unknown>>;
73
-
74
- declare function createUniqueId(prefix: string, existing: Iterable<string>): string;
75
-
76
71
  declare function migrateLegacySchema(raw: unknown): unknown;
77
72
 
78
73
  declare function normalizeReportTemplateSchema(schema: ReportTemplateSchema): ReportTemplateSchema;
79
74
  declare function parseReportTemplateSchema(raw: unknown): ReportTemplateSchema;
80
75
  declare function parseReportTemplateSchemaFromString(raw: string): ReportTemplateSchema;
81
- declare function serializeReportTemplateSchema(schema: ReportTemplateSchema): string;
82
-
83
- declare function buildBaseFieldSchema(field: ReportTemplateField): ZodTypeAny;
84
- declare function buildResponseSchemaWithConditions(template: ReportTemplateSchema, response: Record<string, any>): z.ZodObject<Record<string, ZodTypeAny>>;
85
- declare function validateReportResponse(template: ReportTemplateSchema, data: unknown): Record<string, unknown>;
86
- type FieldErrorCode = "response.invalid_root" | "field.required" | "field.invalid_type" | "field.too_small" | "field.too_big" | "field.invalid_option" | "field.custom";
87
- interface ResponseFieldError {
88
- /** field id (template-level id) */
89
- fieldId: string;
90
- /** section id that owns this field (if known) */
91
- sectionId?: string;
92
- /** section title (if available in template) */
93
- sectionTitle?: string;
94
- /** human label of the field */
95
- label?: string;
96
- /** normalized error code */
97
- code: FieldErrorCode;
98
- /** human-readable message (already enriched with section / label) */
99
- message: string;
100
- /** original Zod issue (for debugging / logging) */
101
- rawIssue?: ZodIssue;
76
+ interface SerializeOptions {
77
+ /**
78
+ * If true (default), output human-readable JSON with 2-space indentation.
79
+ * If false, output a compact single-line JSON string.
80
+ */
81
+ pretty?: boolean;
82
+ /**
83
+ * If true, sections will be sorted by their `id` before serialization.
84
+ * This is useful for deterministic diffs across environments.
85
+ */
86
+ sortSectionsById?: boolean;
87
+ /**
88
+ * If true, fields within each section will be sorted by their `id`
89
+ * before serialization. Also useful for stable diffs.
90
+ */
91
+ sortFieldsById?: boolean;
102
92
  }
103
93
  /**
104
- * Validates a response against a template, but instead of throwing,
105
- * returns a structured error object with:
106
- * - section title
107
- * - field label
108
- * - normalized error code
94
+ * Serialize a template schema into JSON.
109
95
  *
110
- * Ideal for UI error display.
96
+ * - Optional pretty-printing (default: true)
97
+ * - Optional deterministic sorting of sections and fields by ID
98
+ * to make git diffs and code reviews cleaner.
111
99
  */
112
- declare function validateReportResponseDetailed(template: ReportTemplateSchema, data: unknown): {
113
- success: true;
114
- value: Record<string, unknown>;
115
- } | {
116
- success: false;
117
- errors: ResponseFieldError[];
118
- };
119
- type TemplateFieldUnion<TTemplate> = TTemplate extends {
120
- sections: readonly (infer S)[];
121
- } ? S extends {
122
- fields: readonly (infer F)[];
123
- } ? F : never : never;
124
- type BaseFieldValue<TField extends {
125
- type: ReportTemplateFieldType;
126
- required?: boolean;
127
- options?: readonly string[] | string[];
128
- }> = TField["type"] extends "shortText" | "longText" ? string : TField["type"] extends "number" ? number : TField["type"] extends "date" ? string : TField["type"] extends "checkbox" ? boolean : TField["type"] extends "singleSelect" ? (TField["options"] extends readonly (infer O)[] ? O : TField["options"] extends (infer O)[] ? O : string) : TField["type"] extends "multiSelect" ? (TField["options"] extends readonly (infer O)[] ? O[] : TField["options"] extends (infer O)[] ? O[] : string[]) : unknown;
129
- type FieldResponseValue<TField extends {
130
- type: ReportTemplateFieldType;
131
- required?: boolean;
132
- }> = TField["required"] extends true ? BaseFieldValue<TField> : BaseFieldValue<TField> | undefined;
133
- type InferResponse<TTemplate extends {
134
- sections: readonly {
135
- fields: readonly {
136
- id: string;
137
- type: ReportTemplateFieldType;
138
- required?: boolean;
139
- options?: readonly string[] | string[];
140
- }[];
141
- }[];
142
- }> = {
143
- [F in TemplateFieldUnion<TTemplate> as F["id"]]: FieldResponseValue<F>;
144
- };
100
+ declare function serializeReportTemplateSchema(schema: ReportTemplateSchema, options?: SerializeOptions): string;
145
101
 
146
102
  interface TemplateDiff {
147
103
  addedSections: Array<{
@@ -201,6 +157,53 @@ interface TemplateDiff {
201
157
  }
202
158
  declare function diffTemplates(before: ReportTemplateSchema, after: ReportTemplateSchema): TemplateDiff;
203
159
 
160
+ /**
161
+ * Minimal JSON Schema type for our purposes.
162
+ * Flexible, with an index signature to allow vendor extensions (x-frt-*).
163
+ */
164
+ interface JSONSchema {
165
+ $schema?: string;
166
+ $id?: string;
167
+ type?: "object" | "string" | "number" | "boolean" | "array" | "null";
168
+ properties?: Record<string, JSONSchema>;
169
+ items?: JSONSchema;
170
+ required?: string[];
171
+ enum?: any[];
172
+ minLength?: number;
173
+ maxLength?: number;
174
+ minimum?: number;
175
+ maximum?: number;
176
+ minItems?: number;
177
+ maxItems?: number;
178
+ description?: string;
179
+ title?: string;
180
+ default?: any;
181
+ format?: string;
182
+ additionalProperties?: boolean;
183
+ [key: string]: any;
184
+ }
185
+ /**
186
+ * Export a report template as a JSON Schema "object" definition.
187
+ *
188
+ * - Each field becomes a property keyed by its `id`
189
+ * - Unconditional `required: true` fields are added to the JSON Schema `required` array
190
+ * - Conditional logic is preserved via `x-frt-visibleIf` / `x-frt-requiredIf`
191
+ * but NOT enforced in the core JSON Schema (since it's beyond standard JSON Schema).
192
+ */
193
+ declare function exportJSONSchema(template: ReportTemplateSchema): JSONSchema;
194
+
195
+ declare const DEFAULT_FIELD_LABEL = "Untitled question";
196
+ declare const CORE_FIELD_DEFAULTS: Record<ReportTemplateFieldType, Record<string, unknown>>;
197
+
198
+ /**
199
+ * Helper for generating a unique id in a *local* namespace, typically in
200
+ * UI/builders when adding new sections/fields client-side.
201
+ *
202
+ * Note: Core template normalization uses its own normalizeId/ensureUniqueId
203
+ * logic so that persisted IDs stay stable and backwards compatible.
204
+ */
205
+ declare function createUniqueId(prefix: string, existing: Iterable<string>): string;
206
+
204
207
  /** -------------------------------------------------------------
205
208
  * FieldRegistryEntry
206
209
  * --------------------------------------------------------------
@@ -250,39 +253,90 @@ declare const FieldRegistry: FieldRegistryClass;
250
253
  */
251
254
  declare function evaluateCondition(condition: SimpleCondition, response: Record<string, any>): boolean;
252
255
 
256
+ declare function buildBaseFieldSchema(field: ReportTemplateField): ZodTypeAny;
257
+ declare function buildResponseSchemaWithConditions(template: ReportTemplateSchema, response: Record<string, any>): z.ZodObject<Record<string, ZodTypeAny>>;
253
258
  /**
254
- * Minimal JSON Schema type for our purposes.
255
- * Flexible, with an index signature to allow vendor extensions (x-frt-*).
259
+ * Build a Zod object schema for a template *without* needing a response object.
260
+ *
261
+ * Notes:
262
+ * - All conditional logic is evaluated against an empty response `{}`.
263
+ * - This means:
264
+ * - `visibleIf` / `requiredIf` that depend on other fields will typically
265
+ * evaluate to false.
266
+ *
267
+ * This is mainly useful for:
268
+ * - Static type inference
269
+ * - Generic tooling / OpenAPI style usage
270
+ * - Situations where you just want the overall "shape" of a response.
256
271
  */
257
- interface JSONSchema {
258
- $schema?: string;
259
- $id?: string;
260
- type?: "object" | "string" | "number" | "boolean" | "array" | "null";
261
- properties?: Record<string, JSONSchema>;
262
- items?: JSONSchema;
263
- required?: string[];
264
- enum?: any[];
265
- minLength?: number;
266
- maxLength?: number;
267
- minimum?: number;
268
- maximum?: number;
269
- minItems?: number;
270
- maxItems?: number;
271
- description?: string;
272
- title?: string;
273
- default?: any;
274
- format?: string;
275
- additionalProperties?: boolean;
276
- [key: string]: any;
272
+ declare function buildResponseSchema(template: ReportTemplateSchema): z.ZodObject<Record<string, ZodTypeAny>>;
273
+ declare function validateReportResponse(template: ReportTemplateSchema, data: unknown): Record<string, unknown>;
274
+ type FieldErrorCode = "response.invalid_root" | "field.required" | "field.invalid_type" | "field.too_small" | "field.too_big" | "field.invalid_option" | "field.custom";
275
+ interface ResponseFieldError {
276
+ /** field id (template-level id) */
277
+ fieldId: string;
278
+ /** section id that owns this field (if known) */
279
+ sectionId?: string;
280
+ /** section title (if available in template) */
281
+ sectionTitle?: string;
282
+ /** human label of the field */
283
+ label?: string;
284
+ /** normalized error code */
285
+ code: FieldErrorCode;
286
+ /** human-readable message (already enriched with section / label) */
287
+ message: string;
288
+ /** original Zod issue (for debugging / logging) */
289
+ rawIssue?: ZodIssue;
277
290
  }
278
291
  /**
279
- * Export a report template as a JSON Schema "object" definition.
292
+ * Validates a response against a template, but instead of throwing,
293
+ * returns a structured error object with:
294
+ * - section title
295
+ * - field label
296
+ * - normalized error code
280
297
  *
281
- * - Each field becomes a property keyed by its `id`
282
- * - Unconditional `required: true` fields are added to the JSON Schema `required` array
283
- * - Conditional logic is preserved via `x-frt-visibleIf` / `x-frt-requiredIf`
284
- * but NOT enforced in the core JSON Schema (since it's beyond standard JSON Schema).
298
+ * Ideal for UI error display.
285
299
  */
286
- declare function exportJSONSchema(template: ReportTemplateSchema): JSONSchema;
300
+ declare function validateReportResponseDetailed(template: ReportTemplateSchema, data: unknown): {
301
+ success: true;
302
+ value: Record<string, unknown>;
303
+ } | {
304
+ success: false;
305
+ errors: ResponseFieldError[];
306
+ };
307
+ /**
308
+ * Helper to turn a thrown ZodError (e.g. from validateReportResponse)
309
+ * into the same ResponseFieldError[] shape used by
310
+ * validateReportResponseDetailed.
311
+ *
312
+ * Returns null if the error is not a ZodError.
313
+ */
314
+ declare function explainValidationError(template: ReportTemplateSchema, error: unknown): ResponseFieldError[] | null;
315
+ type TemplateFieldUnion<TTemplate> = TTemplate extends {
316
+ sections: readonly (infer S)[];
317
+ } ? S extends {
318
+ fields: readonly (infer F)[];
319
+ } ? F : never : never;
320
+ type BaseFieldValue<TField extends {
321
+ type: ReportTemplateFieldType;
322
+ required?: boolean;
323
+ options?: readonly string[] | string[];
324
+ }> = TField["type"] extends "shortText" | "longText" ? string : TField["type"] extends "number" ? number : TField["type"] extends "date" ? string : TField["type"] extends "checkbox" ? boolean : TField["type"] extends "singleSelect" ? (TField["options"] extends readonly (infer O)[] ? O : TField["options"] extends (infer O)[] ? O : string) : TField["type"] extends "multiSelect" ? (TField["options"] extends readonly (infer O)[] ? O[] : TField["options"] extends (infer O)[] ? O[] : string[]) : TField["type"] extends "repeatGroup" ? Array<Record<string, unknown>> : unknown;
325
+ type FieldResponseValue<TField extends {
326
+ type: ReportTemplateFieldType;
327
+ required?: boolean;
328
+ }> = TField["required"] extends true ? BaseFieldValue<TField> : BaseFieldValue<TField> | undefined;
329
+ type InferResponse<TTemplate extends {
330
+ sections: readonly {
331
+ fields: readonly {
332
+ id: string;
333
+ type: ReportTemplateFieldType;
334
+ required?: boolean;
335
+ options?: readonly string[] | string[];
336
+ }[];
337
+ }[];
338
+ }> = {
339
+ [F in TemplateFieldUnion<TTemplate> as F["id"]]: FieldResponseValue<F>;
340
+ };
287
341
 
288
- export { CORE_FIELD_DEFAULTS, Condition, DEFAULT_FIELD_LABEL, type FieldErrorCode, FieldRegistry, type FieldRegistryEntry, type InferResponse, type JSONSchema, REPORT_TEMPLATE_FIELD_TYPES, REPORT_TEMPLATE_VERSION, RepeatGroupFieldSchema, type ReportTemplateField, ReportTemplateFieldSchema, type ReportTemplateFieldType, type ReportTemplateSchema, ReportTemplateSchemaValidator, type ReportTemplateSection, ReportTemplateSectionSchema, type ResponseFieldError, type SimpleCondition, type TemplateDiff, buildBaseFieldSchema, buildResponseSchemaWithConditions, createUniqueId, diffTemplates, evaluateCondition, exportJSONSchema, migrateLegacySchema, normalizeReportTemplateSchema, parseReportTemplateSchema, parseReportTemplateSchemaFromString, serializeReportTemplateSchema, validateReportResponse, validateReportResponseDetailed };
342
+ export { CORE_FIELD_DEFAULTS, Condition, DEFAULT_FIELD_LABEL, type FieldErrorCode, FieldRegistry, type FieldRegistryEntry, type InferResponse, type JSONSchema, REPORT_TEMPLATE_FIELD_TYPES, REPORT_TEMPLATE_VERSION, RepeatGroupFieldSchema, type ReportTemplateField, ReportTemplateFieldSchema, type ReportTemplateFieldType, type ReportTemplateSchema, ReportTemplateSchemaValidator, type ReportTemplateSection, ReportTemplateSectionSchema, type ResponseFieldError, type SerializeOptions, type SimpleCondition, type TemplateDiff, buildBaseFieldSchema, buildResponseSchema, buildResponseSchemaWithConditions, createUniqueId, diffTemplates, evaluateCondition, explainValidationError, exportJSONSchema, migrateLegacySchema, normalizeReportTemplateSchema, parseReportTemplateSchema, parseReportTemplateSchemaFromString, serializeReportTemplateSchema, validateReportResponse, validateReportResponseDetailed };