@frt-platform/report-core 1.4.0 → 1.5.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 +210 -134
- package/dist/index.d.ts +210 -134
- package/dist/index.js +542 -367
- package/dist/index.mjs +542 -370
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -7,7 +7,9 @@ declare const Condition: z.ZodType<any>;
|
|
|
7
7
|
type SimpleCondition = z.infer<typeof Condition>;
|
|
8
8
|
declare const RepeatGroupFieldSchema: z.ZodType<any>;
|
|
9
9
|
declare const ReportTemplateFieldSchema: z.ZodType<any>;
|
|
10
|
-
type ReportTemplateField = z.infer<typeof ReportTemplateFieldSchema
|
|
10
|
+
type ReportTemplateField = z.infer<typeof ReportTemplateFieldSchema> & {
|
|
11
|
+
computed?: string;
|
|
12
|
+
};
|
|
11
13
|
declare const ReportTemplateSectionSchema: z.ZodObject<{
|
|
12
14
|
id: z.ZodString;
|
|
13
15
|
title: z.ZodOptional<z.ZodString>;
|
|
@@ -68,7 +70,25 @@ declare const ReportTemplateSchemaValidator: z.ZodObject<{
|
|
|
68
70
|
}>;
|
|
69
71
|
type ReportTemplateSchema = z.infer<typeof ReportTemplateSchemaValidator>;
|
|
70
72
|
|
|
71
|
-
|
|
73
|
+
/**
|
|
74
|
+
* Helper for generating a unique id in a *local* namespace, typically in
|
|
75
|
+
* UI/builders when adding new sections/fields client-side.
|
|
76
|
+
*
|
|
77
|
+
* Note:
|
|
78
|
+
* - This is deliberately simple and deterministic.
|
|
79
|
+
* - Core template normalization uses its own normalizeId/ensureUniqueId logic
|
|
80
|
+
* so that persisted IDs stay stable and backwards compatible.
|
|
81
|
+
*/
|
|
82
|
+
declare function createUniqueId(prefix: string, existing: Iterable<string>): string;
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Migrate a legacy flat { fields: [...] } structure or partially-upgraded
|
|
86
|
+
* schema into the current { sections: [...] } shape.
|
|
87
|
+
*
|
|
88
|
+
* This is intentionally loose: it accepts `unknown` and only normalizes
|
|
89
|
+
* what we care about. The full Zod validation happens later.
|
|
90
|
+
*/
|
|
91
|
+
declare function migrateLegacySchema(raw: unknown): ReportTemplateSchema | any;
|
|
72
92
|
|
|
73
93
|
declare function normalizeReportTemplateSchema(schema: ReportTemplateSchema): ReportTemplateSchema;
|
|
74
94
|
declare function parseReportTemplateSchema(raw: unknown): ReportTemplateSchema;
|
|
@@ -99,61 +119,55 @@ interface SerializeOptions {
|
|
|
99
119
|
*/
|
|
100
120
|
declare function serializeReportTemplateSchema(schema: ReportTemplateSchema, options?: SerializeOptions): string;
|
|
101
121
|
|
|
122
|
+
interface SectionPropertyChange {
|
|
123
|
+
key: string;
|
|
124
|
+
before: unknown;
|
|
125
|
+
after: unknown;
|
|
126
|
+
}
|
|
127
|
+
interface ModifiedSection {
|
|
128
|
+
sectionId: string;
|
|
129
|
+
changes: SectionPropertyChange[];
|
|
130
|
+
}
|
|
131
|
+
interface ModifiedField {
|
|
132
|
+
sectionId: string;
|
|
133
|
+
fieldId: string;
|
|
134
|
+
changes: SectionPropertyChange[];
|
|
135
|
+
}
|
|
136
|
+
interface SectionAddRemove {
|
|
137
|
+
sectionId: string;
|
|
138
|
+
index: number;
|
|
139
|
+
}
|
|
140
|
+
interface SectionReorder {
|
|
141
|
+
sectionId: string;
|
|
142
|
+
from: number;
|
|
143
|
+
to: number;
|
|
144
|
+
}
|
|
145
|
+
interface FieldAddRemove {
|
|
146
|
+
sectionId: string;
|
|
147
|
+
fieldId: string;
|
|
148
|
+
index: number;
|
|
149
|
+
}
|
|
150
|
+
interface FieldReorder {
|
|
151
|
+
sectionId: string;
|
|
152
|
+
fieldId: string;
|
|
153
|
+
from: number;
|
|
154
|
+
to: number;
|
|
155
|
+
}
|
|
156
|
+
interface NestedFieldDiff {
|
|
157
|
+
sectionId: string;
|
|
158
|
+
groupId: string;
|
|
159
|
+
diffs: TemplateDiff;
|
|
160
|
+
}
|
|
102
161
|
interface TemplateDiff {
|
|
103
|
-
addedSections:
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
sectionId: string;
|
|
113
|
-
from: number;
|
|
114
|
-
to: number;
|
|
115
|
-
}>;
|
|
116
|
-
modifiedSections: Array<{
|
|
117
|
-
sectionId: string;
|
|
118
|
-
changes: Array<{
|
|
119
|
-
key: string;
|
|
120
|
-
before: any;
|
|
121
|
-
after: any;
|
|
122
|
-
}>;
|
|
123
|
-
}>;
|
|
124
|
-
addedFields: Array<{
|
|
125
|
-
sectionId: string;
|
|
126
|
-
fieldId: string;
|
|
127
|
-
index: number;
|
|
128
|
-
}>;
|
|
129
|
-
removedFields: Array<{
|
|
130
|
-
sectionId: string;
|
|
131
|
-
fieldId: string;
|
|
132
|
-
index: number;
|
|
133
|
-
}>;
|
|
134
|
-
reorderedFields: Array<{
|
|
135
|
-
sectionId: string;
|
|
136
|
-
fieldId: string;
|
|
137
|
-
from: number;
|
|
138
|
-
to: number;
|
|
139
|
-
}>;
|
|
140
|
-
modifiedFields: Array<{
|
|
141
|
-
sectionId: string;
|
|
142
|
-
fieldId: string;
|
|
143
|
-
before: Record<string, any>;
|
|
144
|
-
after: Record<string, any>;
|
|
145
|
-
changes: Array<{
|
|
146
|
-
key: string;
|
|
147
|
-
before: any;
|
|
148
|
-
after: any;
|
|
149
|
-
}>;
|
|
150
|
-
}>;
|
|
151
|
-
/** NEW: repeatGroup nested diffs */
|
|
152
|
-
nestedFieldDiffs: Array<{
|
|
153
|
-
sectionId: string;
|
|
154
|
-
groupId: string;
|
|
155
|
-
diffs: TemplateDiff;
|
|
156
|
-
}>;
|
|
162
|
+
addedSections: SectionAddRemove[];
|
|
163
|
+
removedSections: SectionAddRemove[];
|
|
164
|
+
reorderedSections: SectionReorder[];
|
|
165
|
+
modifiedSections: ModifiedSection[];
|
|
166
|
+
addedFields: FieldAddRemove[];
|
|
167
|
+
removedFields: FieldAddRemove[];
|
|
168
|
+
reorderedFields: FieldReorder[];
|
|
169
|
+
modifiedFields: ModifiedField[];
|
|
170
|
+
nestedFieldDiffs: NestedFieldDiff[];
|
|
157
171
|
}
|
|
158
172
|
declare function diffTemplates(before: ReportTemplateSchema, after: ReportTemplateSchema): TemplateDiff;
|
|
159
173
|
|
|
@@ -192,85 +206,33 @@ interface JSONSchema {
|
|
|
192
206
|
*/
|
|
193
207
|
declare function exportJSONSchema(template: ReportTemplateSchema): JSONSchema;
|
|
194
208
|
|
|
195
|
-
declare const DEFAULT_FIELD_LABEL = "Untitled question";
|
|
196
|
-
declare const CORE_FIELD_DEFAULTS: Record<ReportTemplateFieldType, Record<string, unknown>>;
|
|
197
|
-
|
|
198
209
|
/**
|
|
199
|
-
*
|
|
200
|
-
* UI/builders when adding new sections/fields client-side.
|
|
210
|
+
* Evaluate a SimpleCondition against a flat response object.
|
|
201
211
|
*
|
|
202
|
-
*
|
|
203
|
-
*
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
/** -------------------------------------------------------------
|
|
208
|
-
* FieldRegistryEntry
|
|
209
|
-
* --------------------------------------------------------------
|
|
210
|
-
* Represents metadata + behavior for a single field type.
|
|
211
|
-
* -------------------------------------------------------------- */
|
|
212
|
-
interface FieldRegistryEntry {
|
|
213
|
-
/** Default field-level properties merged when creating new fields */
|
|
214
|
-
defaults?: Record<string, unknown>;
|
|
215
|
-
/**
|
|
216
|
-
* Build a Zod schema for validating the *response value* of this field.
|
|
217
|
-
* If not provided, the core engine falls back to the built-in handler.
|
|
218
|
-
*/
|
|
219
|
-
buildResponseSchema?: (field: ReportTemplateField) => ZodTypeAny;
|
|
220
|
-
/**
|
|
221
|
-
* Optional UI metadata for @frt/report-react
|
|
222
|
-
* (icon, color, description, grouping, etc.)
|
|
223
|
-
*/
|
|
224
|
-
ui?: Record<string, any>;
|
|
225
|
-
}
|
|
226
|
-
/** -------------------------------------------------------------
|
|
227
|
-
* FieldRegistry
|
|
228
|
-
* --------------------------------------------------------------
|
|
229
|
-
* Central store of all field types (built-in + custom).
|
|
230
|
-
* -------------------------------------------------------------- */
|
|
231
|
-
declare class FieldRegistryClass {
|
|
232
|
-
private registry;
|
|
233
|
-
/** Register or override a field type. */
|
|
234
|
-
register(type: string, entry: FieldRegistryEntry): void;
|
|
235
|
-
/** Get registry entry for a field type. */
|
|
236
|
-
get(type: string): FieldRegistryEntry | undefined;
|
|
237
|
-
/** Check if field type is registered. */
|
|
238
|
-
has(type: string): boolean;
|
|
239
|
-
/** Return all field types currently registered. */
|
|
240
|
-
list(): string[];
|
|
241
|
-
}
|
|
242
|
-
/** Singleton instance */
|
|
243
|
-
declare const FieldRegistry: FieldRegistryClass;
|
|
244
|
-
|
|
245
|
-
/**
|
|
246
|
-
* Evaluate a conditional rule against a submitted response object.
|
|
212
|
+
* Supported structure:
|
|
213
|
+
* - { equals: { fieldId: value } }
|
|
214
|
+
* - { any: [cond, cond, ...] }
|
|
215
|
+
* - { all: [cond, cond, ...] }
|
|
216
|
+
* - { not: cond }
|
|
247
217
|
*
|
|
248
|
-
*
|
|
249
|
-
*
|
|
250
|
-
*
|
|
251
|
-
* { all: [cond, cond] }
|
|
252
|
-
* { not: cond }
|
|
218
|
+
* Notes:
|
|
219
|
+
* - We intentionally keep this evaluation shallow and deterministic.
|
|
220
|
+
* - No special array semantics (e.g. "contains") yet — it's strict equality.
|
|
253
221
|
*/
|
|
254
|
-
declare function evaluateCondition(condition: SimpleCondition, response: Record<string, any>): boolean;
|
|
222
|
+
declare function evaluateCondition(condition: SimpleCondition | undefined, response: Record<string, any>): boolean;
|
|
255
223
|
|
|
256
|
-
declare function buildBaseFieldSchema(field: ReportTemplateField): ZodTypeAny;
|
|
257
|
-
declare function buildResponseSchemaWithConditions(template: ReportTemplateSchema, response: Record<string, any>): z.ZodObject<Record<string, ZodTypeAny>>;
|
|
258
224
|
/**
|
|
259
|
-
* Build
|
|
225
|
+
* Build the base Zod schema for a field, WITHOUT:
|
|
226
|
+
* - visibleIf
|
|
227
|
+
* - requiredIf
|
|
228
|
+
* - computed fields
|
|
229
|
+
* - repeatGroup logic
|
|
260
230
|
*
|
|
261
|
-
*
|
|
262
|
-
*
|
|
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.
|
|
231
|
+
* This is the lowest-level “field → Zod” mapping.
|
|
232
|
+
* All conditional logic is layered on top in conditionalSchema.ts.
|
|
271
233
|
*/
|
|
272
|
-
declare function
|
|
273
|
-
|
|
234
|
+
declare function buildBaseFieldSchema(field: ReportTemplateField): ZodTypeAny;
|
|
235
|
+
|
|
274
236
|
type FieldErrorCode = "response.invalid_root" | "field.required" | "field.invalid_type" | "field.too_small" | "field.too_big" | "field.invalid_option" | "field.custom";
|
|
275
237
|
interface ResponseFieldError {
|
|
276
238
|
/** field id (template-level id) */
|
|
@@ -288,6 +250,27 @@ interface ResponseFieldError {
|
|
|
288
250
|
/** original Zod issue (for debugging / logging) */
|
|
289
251
|
rawIssue?: ZodIssue;
|
|
290
252
|
}
|
|
253
|
+
/**
|
|
254
|
+
* Helper to turn a thrown ZodError (e.g. from validateReportResponse)
|
|
255
|
+
* into the same ResponseFieldError[] shape used by
|
|
256
|
+
* validateReportResponseDetailed.
|
|
257
|
+
*
|
|
258
|
+
* Returns null if the error is not a ZodError.
|
|
259
|
+
*/
|
|
260
|
+
declare function explainValidationError(template: ReportTemplateSchema, error: unknown): ResponseFieldError[] | null;
|
|
261
|
+
|
|
262
|
+
declare function buildResponseSchemaWithConditions(template: ReportTemplateSchema, response: Record<string, any>): z.ZodObject<Record<string, ZodTypeAny>>;
|
|
263
|
+
/**
|
|
264
|
+
* Build a Zod object schema for a template *without* needing a response object.
|
|
265
|
+
*
|
|
266
|
+
* Notes:
|
|
267
|
+
* - All conditional logic is evaluated against an empty response `{}`.
|
|
268
|
+
* - This is mainly useful for:
|
|
269
|
+
* - Static type inference
|
|
270
|
+
* - Generic tooling / OpenAPI-style usage
|
|
271
|
+
*/
|
|
272
|
+
declare function buildResponseSchema(template: ReportTemplateSchema): z.ZodObject<Record<string, ZodTypeAny>>;
|
|
273
|
+
declare function validateReportResponse(template: ReportTemplateSchema, data: unknown): Record<string, unknown>;
|
|
291
274
|
/**
|
|
292
275
|
* Validates a response against a template, but instead of throwing,
|
|
293
276
|
* returns a structured error object with:
|
|
@@ -304,28 +287,66 @@ declare function validateReportResponseDetailed(template: ReportTemplateSchema,
|
|
|
304
287
|
success: false;
|
|
305
288
|
errors: ResponseFieldError[];
|
|
306
289
|
};
|
|
290
|
+
|
|
307
291
|
/**
|
|
308
|
-
*
|
|
309
|
-
* into the same ResponseFieldError[] shape used by
|
|
310
|
-
* validateReportResponseDetailed.
|
|
292
|
+
* Extracts the union of all field configs from a template type.
|
|
311
293
|
*
|
|
312
|
-
*
|
|
294
|
+
* Given:
|
|
295
|
+
* {
|
|
296
|
+
* sections: [
|
|
297
|
+
* { fields: [F1, F2] },
|
|
298
|
+
* { fields: [F3] }
|
|
299
|
+
* ]
|
|
300
|
+
* }
|
|
301
|
+
*
|
|
302
|
+
* → TemplateFieldUnion<TTemplate> = F1 | F2 | F3
|
|
313
303
|
*/
|
|
314
|
-
declare function explainValidationError(template: ReportTemplateSchema, error: unknown): ResponseFieldError[] | null;
|
|
315
304
|
type TemplateFieldUnion<TTemplate> = TTemplate extends {
|
|
316
305
|
sections: readonly (infer S)[];
|
|
317
306
|
} ? S extends {
|
|
318
307
|
fields: readonly (infer F)[];
|
|
319
308
|
} ? F : never : never;
|
|
309
|
+
/**
|
|
310
|
+
* Base value type for a field, ignoring `required`.
|
|
311
|
+
* This is deliberately simple and only keyed off `type` + `options`.
|
|
312
|
+
*/
|
|
320
313
|
type BaseFieldValue<TField extends {
|
|
321
314
|
type: ReportTemplateFieldType;
|
|
322
315
|
required?: boolean;
|
|
323
316
|
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" ?
|
|
317
|
+
}> = 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;
|
|
318
|
+
/**
|
|
319
|
+
* Wrap base value in optionality depending on `required`.
|
|
320
|
+
*/
|
|
325
321
|
type FieldResponseValue<TField extends {
|
|
326
322
|
type: ReportTemplateFieldType;
|
|
327
323
|
required?: boolean;
|
|
328
324
|
}> = TField["required"] extends true ? BaseFieldValue<TField> : BaseFieldValue<TField> | undefined;
|
|
325
|
+
/**
|
|
326
|
+
* Infer the response shape from a *const* template definition.
|
|
327
|
+
*
|
|
328
|
+
* Example:
|
|
329
|
+
*
|
|
330
|
+
* export const myTemplate = {
|
|
331
|
+
* version: 1,
|
|
332
|
+
* sections: [
|
|
333
|
+
* {
|
|
334
|
+
* id: "main",
|
|
335
|
+
* fields: [
|
|
336
|
+
* { id: "title", type: "shortText", required: true },
|
|
337
|
+
* { id: "tags", type: "multiSelect", options: ["A", "B"] },
|
|
338
|
+
* ]
|
|
339
|
+
* }
|
|
340
|
+
* ]
|
|
341
|
+
* } as const;
|
|
342
|
+
*
|
|
343
|
+
* type MyResponse = InferResponse<typeof myTemplate>;
|
|
344
|
+
*
|
|
345
|
+
* // {
|
|
346
|
+
* // title: string;
|
|
347
|
+
* // tags?: ("A" | "B")[];
|
|
348
|
+
* // }
|
|
349
|
+
*/
|
|
329
350
|
type InferResponse<TTemplate extends {
|
|
330
351
|
sections: readonly {
|
|
331
352
|
fields: readonly {
|
|
@@ -339,4 +360,59 @@ type InferResponse<TTemplate extends {
|
|
|
339
360
|
[F in TemplateFieldUnion<TTemplate> as F["id"]]: FieldResponseValue<F>;
|
|
340
361
|
};
|
|
341
362
|
|
|
342
|
-
|
|
363
|
+
/** -------------------------------------------------------------
|
|
364
|
+
* FieldRegistryEntry
|
|
365
|
+
* --------------------------------------------------------------
|
|
366
|
+
* Represents metadata + behavior for a single field type.
|
|
367
|
+
* -------------------------------------------------------------- */
|
|
368
|
+
interface FieldRegistryEntry {
|
|
369
|
+
/** Default field-level properties merged when creating new fields */
|
|
370
|
+
defaults?: Record<string, unknown>;
|
|
371
|
+
/**
|
|
372
|
+
* Build a Zod schema for validating the *response value* of this field.
|
|
373
|
+
* If not provided, the core engine falls back to the built-in handler.
|
|
374
|
+
*/
|
|
375
|
+
buildResponseSchema?: (field: ReportTemplateField) => ZodTypeAny;
|
|
376
|
+
/**
|
|
377
|
+
* Optional UI metadata for @frt/report-react
|
|
378
|
+
* (icon, color, description, grouping, etc.)
|
|
379
|
+
*/
|
|
380
|
+
ui?: Record<string, any>;
|
|
381
|
+
}
|
|
382
|
+
/** -------------------------------------------------------------
|
|
383
|
+
* FieldRegistry
|
|
384
|
+
* --------------------------------------------------------------
|
|
385
|
+
* Central store of all field types (built-in + custom).
|
|
386
|
+
* -------------------------------------------------------------- */
|
|
387
|
+
declare class FieldRegistryClass {
|
|
388
|
+
private registry;
|
|
389
|
+
/** Register or override a field type. */
|
|
390
|
+
register(type: string, entry: FieldRegistryEntry): void;
|
|
391
|
+
/** Get registry entry for a field type. */
|
|
392
|
+
get(type: string): FieldRegistryEntry | undefined;
|
|
393
|
+
/** Check if field type is registered. */
|
|
394
|
+
has(type: string): boolean;
|
|
395
|
+
/** Return all field types currently registered. */
|
|
396
|
+
list(): string[];
|
|
397
|
+
}
|
|
398
|
+
/** Singleton instance */
|
|
399
|
+
declare const FieldRegistry: FieldRegistryClass;
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* Shared default label used for all core field types.
|
|
403
|
+
*/
|
|
404
|
+
declare const DEFAULT_FIELD_LABEL = "Untitled field";
|
|
405
|
+
/**
|
|
406
|
+
* Shape of the core defaults map.
|
|
407
|
+
* We keep values loose (Record<string, any>) because different field
|
|
408
|
+
* types have different shapes, and these are just "seed" objects.
|
|
409
|
+
*/
|
|
410
|
+
type CoreFieldDefaults = Record<ReportTemplateFieldType, Record<string, any>>;
|
|
411
|
+
/**
|
|
412
|
+
* Default configs for every core field type.
|
|
413
|
+
* These are *not* full fields (no id), just starter values that
|
|
414
|
+
* template builders / UIs can merge into new fields.
|
|
415
|
+
*/
|
|
416
|
+
declare const CORE_FIELD_DEFAULTS: CoreFieldDefaults;
|
|
417
|
+
|
|
418
|
+
export { CORE_FIELD_DEFAULTS, Condition, type CoreFieldDefaults, DEFAULT_FIELD_LABEL, type FieldAddRemove, type FieldErrorCode, FieldRegistry, type FieldRegistryEntry, type FieldReorder, type InferResponse, type JSONSchema, type ModifiedField, type ModifiedSection, type NestedFieldDiff, REPORT_TEMPLATE_FIELD_TYPES, REPORT_TEMPLATE_VERSION, RepeatGroupFieldSchema, type ReportTemplateField, ReportTemplateFieldSchema, type ReportTemplateFieldType, type ReportTemplateSchema, ReportTemplateSchemaValidator, type ReportTemplateSection, ReportTemplateSectionSchema, type ResponseFieldError, type SectionAddRemove, type SectionPropertyChange, type SectionReorder, type SerializeOptions, type SimpleCondition, type TemplateDiff, buildBaseFieldSchema, buildResponseSchema, buildResponseSchemaWithConditions, createUniqueId, diffTemplates, evaluateCondition, explainValidationError, exportJSONSchema, migrateLegacySchema, normalizeReportTemplateSchema, parseReportTemplateSchema, parseReportTemplateSchemaFromString, serializeReportTemplateSchema, validateReportResponse, validateReportResponseDetailed };
|