@finsys/core 1.0.1 → 1.1.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/catalogs.d.ts +13 -0
- package/dist/catalogs.js +35 -0
- package/dist/catalogs.test.d.ts +1 -0
- package/dist/catalogs.test.js +207 -0
- package/dist/data/form-field-base-specs.json +7353 -0
- package/dist/data/form-field-types.json +83 -0
- package/dist/data/form-field-validators.json +341 -0
- package/dist/form-field-category.d.ts +12 -0
- package/dist/form-field-category.js +21 -0
- package/dist/form-field-validator.d.ts +18 -0
- package/dist/form-field-validator.js +41 -0
- package/dist/form-field.d.ts +81 -0
- package/dist/form-field.js +197 -0
- package/dist/form-field.test.d.ts +1 -0
- package/dist/form-field.test.js +482 -0
- package/dist/form-spec.d.ts +39 -0
- package/dist/form-spec.js +278 -0
- package/dist/form-spec.test.d.ts +1 -0
- package/dist/form-spec.test.js +322 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +7 -0
- package/package.json +4 -2
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { FieldData, Category } from "./survey-generator.js";
|
|
2
|
+
import type { FormFieldTypeDefinitions } from "./form-field.js";
|
|
3
|
+
import type { FormValidatorDefinitions } from "./form-field-validator.js";
|
|
4
|
+
export declare const BASE_FIELD_SPECS: {
|
|
5
|
+
schemaVersion: string;
|
|
6
|
+
categories: Category[];
|
|
7
|
+
fields: FieldData[];
|
|
8
|
+
};
|
|
9
|
+
export declare const FIELD_TYPE_DEFINITIONS: FormFieldTypeDefinitions;
|
|
10
|
+
export declare const DEFAULT_VALIDATOR_DEFINITIONS: FormValidatorDefinitions;
|
|
11
|
+
export declare function getBaseFieldSpecs(): FieldData[];
|
|
12
|
+
export declare function getBaseCategories(): Category[];
|
|
13
|
+
export declare function getBaseFieldNames(): string[];
|
package/dist/catalogs.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import FormField from "./form-field.js";
|
|
2
|
+
import baseSpecsData from "./data/form-field-base-specs.json" with { type: "json" };
|
|
3
|
+
import typeDefsData from "./data/form-field-types.json" with { type: "json" };
|
|
4
|
+
import validatorDefsData from "./data/form-field-validators.json" with { type: "json" };
|
|
5
|
+
export const BASE_FIELD_SPECS = baseSpecsData;
|
|
6
|
+
export const FIELD_TYPE_DEFINITIONS = typeDefsData;
|
|
7
|
+
export const DEFAULT_VALIDATOR_DEFINITIONS = {
|
|
8
|
+
version: validatorDefsData.version,
|
|
9
|
+
options: validatorDefsData.options,
|
|
10
|
+
};
|
|
11
|
+
export function getBaseFieldSpecs() {
|
|
12
|
+
return BASE_FIELD_SPECS.fields;
|
|
13
|
+
}
|
|
14
|
+
export function getBaseCategories() {
|
|
15
|
+
return BASE_FIELD_SPECS.categories;
|
|
16
|
+
}
|
|
17
|
+
let cachedFieldNames = null;
|
|
18
|
+
export function getBaseFieldNames() {
|
|
19
|
+
if (cachedFieldNames) {
|
|
20
|
+
return cachedFieldNames;
|
|
21
|
+
}
|
|
22
|
+
const fields = BASE_FIELD_SPECS.fields;
|
|
23
|
+
const names = [];
|
|
24
|
+
for (const field of fields) {
|
|
25
|
+
try {
|
|
26
|
+
const formField = FormField.fromObject(field);
|
|
27
|
+
names.push(...formField.getFieldNames());
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
// Skip fields that fail to parse
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
cachedFieldNames = [...new Set(names)];
|
|
34
|
+
return cachedFieldNames;
|
|
35
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { generateRHFSchema } from "./rhf-generator.js";
|
|
3
|
+
import { BASE_FIELD_SPECS, FIELD_TYPE_DEFINITIONS, DEFAULT_VALIDATOR_DEFINITIONS, getBaseFieldSpecs, getBaseCategories, getBaseFieldNames, } from "./catalogs.js";
|
|
4
|
+
describe("BASE_FIELD_SPECS", () => {
|
|
5
|
+
it("has schemaVersion, categories, and fields", () => {
|
|
6
|
+
expect(BASE_FIELD_SPECS.schemaVersion).toBeDefined();
|
|
7
|
+
expect(Array.isArray(BASE_FIELD_SPECS.categories)).toBe(true);
|
|
8
|
+
expect(Array.isArray(BASE_FIELD_SPECS.fields)).toBe(true);
|
|
9
|
+
expect(BASE_FIELD_SPECS.categories.length).toBeGreaterThan(0);
|
|
10
|
+
expect(BASE_FIELD_SPECS.fields.length).toBeGreaterThan(0);
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
describe("FIELD_TYPE_DEFINITIONS", () => {
|
|
14
|
+
it("has version, types, and input_types", () => {
|
|
15
|
+
expect(FIELD_TYPE_DEFINITIONS.version).toBeDefined();
|
|
16
|
+
expect(Array.isArray(FIELD_TYPE_DEFINITIONS.types)).toBe(true);
|
|
17
|
+
expect(Array.isArray(FIELD_TYPE_DEFINITIONS.input_types)).toBe(true);
|
|
18
|
+
expect(FIELD_TYPE_DEFINITIONS.types.length).toBeGreaterThan(0);
|
|
19
|
+
expect(FIELD_TYPE_DEFINITIONS.input_types.length).toBeGreaterThan(0);
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
describe("DEFAULT_VALIDATOR_DEFINITIONS", () => {
|
|
23
|
+
it("has version and options", () => {
|
|
24
|
+
expect(DEFAULT_VALIDATOR_DEFINITIONS.version).toBeDefined();
|
|
25
|
+
expect(Array.isArray(DEFAULT_VALIDATOR_DEFINITIONS.options)).toBe(true);
|
|
26
|
+
expect(DEFAULT_VALIDATOR_DEFINITIONS.options.length).toBeGreaterThan(0);
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
describe("getBaseFieldSpecs", () => {
|
|
30
|
+
it("returns field array", () => {
|
|
31
|
+
const fields = getBaseFieldSpecs();
|
|
32
|
+
expect(Array.isArray(fields)).toBe(true);
|
|
33
|
+
expect(fields.length).toBeGreaterThan(0);
|
|
34
|
+
expect(fields[0].name).toBeDefined();
|
|
35
|
+
expect(fields[0].type).toBeDefined();
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
describe("getBaseCategories", () => {
|
|
39
|
+
it("returns category array", () => {
|
|
40
|
+
const categories = getBaseCategories();
|
|
41
|
+
expect(Array.isArray(categories)).toBe(true);
|
|
42
|
+
expect(categories.length).toBeGreaterThan(0);
|
|
43
|
+
expect(categories[0].id).toBeDefined();
|
|
44
|
+
expect(categories[0].name).toBeDefined();
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
describe("getBaseFieldNames", () => {
|
|
48
|
+
it("returns unique field names", () => {
|
|
49
|
+
const names = getBaseFieldNames();
|
|
50
|
+
expect(Array.isArray(names)).toBe(true);
|
|
51
|
+
expect(names.length).toBeGreaterThan(0);
|
|
52
|
+
// Should be unique
|
|
53
|
+
expect(new Set(names).size).toBe(names.length);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
describe("Base Specs Zod Validation", () => {
|
|
57
|
+
it("all field definitions should be valid for RHF schema generation", () => {
|
|
58
|
+
const fields = BASE_FIELD_SPECS.fields;
|
|
59
|
+
const categories = BASE_FIELD_SPECS.categories;
|
|
60
|
+
const failedFields = [];
|
|
61
|
+
fields.forEach((field) => {
|
|
62
|
+
try {
|
|
63
|
+
const config = {
|
|
64
|
+
schemaVersion: "v2.0.0",
|
|
65
|
+
displayName: "Test",
|
|
66
|
+
categories: categories,
|
|
67
|
+
fields: {
|
|
68
|
+
[field.name]: field,
|
|
69
|
+
},
|
|
70
|
+
pages: [
|
|
71
|
+
{
|
|
72
|
+
id: "test-page",
|
|
73
|
+
fields: [field.name],
|
|
74
|
+
},
|
|
75
|
+
],
|
|
76
|
+
};
|
|
77
|
+
const { zodSchema, defaultValues } = generateRHFSchema(config);
|
|
78
|
+
const result = zodSchema.safeParse(defaultValues);
|
|
79
|
+
if (!result.success) {
|
|
80
|
+
const hasRequirementError = result.error.issues.some((i) => i.message === "This field is required" || i.code === "too_small");
|
|
81
|
+
const isRequired = field.isRequired !== false && field.required !== false;
|
|
82
|
+
if (!(isRequired && hasRequirementError && !field.defaultValue)) {
|
|
83
|
+
failedFields.push({
|
|
84
|
+
name: field.name,
|
|
85
|
+
error: `Validation failed: ${JSON.stringify(result.error.issues)}`,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
failedFields.push({
|
|
92
|
+
name: field.name,
|
|
93
|
+
error: `Exception: ${error.message}`,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
if (failedFields.length > 0) {
|
|
98
|
+
const errorMsg = failedFields.map((f) => `[${f.name}]: ${f.error}`).join("\n");
|
|
99
|
+
expect.unreachable(`Found ${failedFields.length} invalid field definitions:\n${errorMsg.substring(0, 2000)}`);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
describe("Field Types Zod Validation", () => {
|
|
104
|
+
it("all supported type combinations should be valid for RHF schema generation", () => {
|
|
105
|
+
const types = FIELD_TYPE_DEFINITIONS.types;
|
|
106
|
+
const inputTypes = FIELD_TYPE_DEFINITIONS.input_types;
|
|
107
|
+
const failedCombinations = [];
|
|
108
|
+
for (const typeObj of types) {
|
|
109
|
+
const baseType = typeObj.name;
|
|
110
|
+
const targetInputTypes = baseType === "text" ? inputTypes : [{ name: undefined }];
|
|
111
|
+
for (const inputTypeObj of targetInputTypes) {
|
|
112
|
+
const inputType = inputTypeObj.name;
|
|
113
|
+
try {
|
|
114
|
+
const field = {
|
|
115
|
+
name: "testField",
|
|
116
|
+
displayName: "Test Field",
|
|
117
|
+
category: "1",
|
|
118
|
+
type: baseType,
|
|
119
|
+
};
|
|
120
|
+
if (inputType)
|
|
121
|
+
field.inputType = inputType;
|
|
122
|
+
const config = {
|
|
123
|
+
schemaVersion: "v2.0.0",
|
|
124
|
+
displayName: "Test",
|
|
125
|
+
categories: [{ id: "1", name: "Test" }],
|
|
126
|
+
fields: { [field.name]: field },
|
|
127
|
+
pages: [{ id: "test-page", fields: [field.name] }],
|
|
128
|
+
};
|
|
129
|
+
const { zodSchema, defaultValues } = generateRHFSchema(config);
|
|
130
|
+
const result = zodSchema.safeParse(defaultValues);
|
|
131
|
+
if (!result.success) {
|
|
132
|
+
const errors = result.error.issues.filter((i) => i.message !== "This field is required" && i.code !== "too_small");
|
|
133
|
+
if (errors.length > 0) {
|
|
134
|
+
failedCombinations.push({
|
|
135
|
+
type: baseType,
|
|
136
|
+
inputType,
|
|
137
|
+
error: `Validation failed: ${JSON.stringify(errors)}`,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
failedCombinations.push({
|
|
144
|
+
type: baseType,
|
|
145
|
+
inputType,
|
|
146
|
+
error: `Exception: ${error.message}`,
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
if (failedCombinations.length > 0) {
|
|
152
|
+
const errorMsg = failedCombinations
|
|
153
|
+
.map((c) => `[${c.type}${c.inputType ? "/" + c.inputType : ""}]: ${c.error}`)
|
|
154
|
+
.join("\n");
|
|
155
|
+
expect.unreachable(`Found ${failedCombinations.length} invalid type combinations:\n${errorMsg}`);
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
describe("Field Validators Zod Validation", () => {
|
|
160
|
+
it("all shared validator definitions should be valid for RHF schema generation", () => {
|
|
161
|
+
const options = DEFAULT_VALIDATOR_DEFINITIONS.options;
|
|
162
|
+
const failedValidators = [];
|
|
163
|
+
options.forEach((option) => {
|
|
164
|
+
try {
|
|
165
|
+
const field = {
|
|
166
|
+
name: "testField",
|
|
167
|
+
displayName: "Test Field",
|
|
168
|
+
category: "1",
|
|
169
|
+
type: "text",
|
|
170
|
+
validators: option.validators || [],
|
|
171
|
+
};
|
|
172
|
+
if (option.validators?.some((v) => v.type === "numeric")) {
|
|
173
|
+
field.type = "number";
|
|
174
|
+
field.inputType = "number";
|
|
175
|
+
}
|
|
176
|
+
const config = {
|
|
177
|
+
schemaVersion: "v2.0.0",
|
|
178
|
+
displayName: "Test",
|
|
179
|
+
categories: [{ id: "1", name: "Test" }],
|
|
180
|
+
fields: { [field.name]: field },
|
|
181
|
+
pages: [{ id: "test-page", fields: [field.name] }],
|
|
182
|
+
};
|
|
183
|
+
const { zodSchema, defaultValues } = generateRHFSchema(config);
|
|
184
|
+
const result = zodSchema.safeParse(defaultValues);
|
|
185
|
+
if (!result.success) {
|
|
186
|
+
const errors = result.error.issues.filter((i) => i.message !== "This field is required");
|
|
187
|
+
if (errors.length > 0) {
|
|
188
|
+
failedValidators.push({
|
|
189
|
+
name: option.displayName,
|
|
190
|
+
error: `Validation failed: ${JSON.stringify(errors)}`,
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
catch (error) {
|
|
196
|
+
failedValidators.push({
|
|
197
|
+
name: option.displayName,
|
|
198
|
+
error: `Exception: ${error.message}`,
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
if (failedValidators.length > 0) {
|
|
203
|
+
const errorMsg = failedValidators.map((f) => `[${f.name}]: ${f.error}`).join("\n");
|
|
204
|
+
expect.unreachable(`Found ${failedValidators.length} invalid validator definitions:\n${errorMsg.substring(0, 2000)}`);
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
});
|