@prolibu-suite/cobalt-form-core 0.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.
@@ -0,0 +1,35 @@
1
+ import type { FieldDescriptor, FormControllerOptions, FormSchemaLike, FormState, FormStateListener, SubmitResult, Unsubscribe } from './types.js';
2
+ export declare class FormController {
3
+ fields: FieldDescriptor[];
4
+ state: FormState;
5
+ private schemaInstance;
6
+ private readonly initialValues;
7
+ private readonly validateOn;
8
+ private readonly listeners;
9
+ private notifyScheduled;
10
+ constructor(options: FormControllerOptions);
11
+ private collectDefaults;
12
+ getValue(name: string): any;
13
+ setValue(name: string, value: any): void;
14
+ setValues(partial: Record<string, any>): void;
15
+ validate(): boolean;
16
+ /** Mark a single field as touched. */
17
+ touch(name: string): void;
18
+ /** Mark every field as touched. Useful right before showing errors on submit. */
19
+ touchAll(): void;
20
+ /**
21
+ * Swap the underlying schema instance (e.g. on locale change) while preserving
22
+ * the current values and touched map. Re-derives the field descriptors and
23
+ * re-runs validation against the new instance.
24
+ */
25
+ setSchema(instance: FormSchemaLike): void;
26
+ submit(): Promise<SubmitResult>;
27
+ reset(values?: Record<string, any>): void;
28
+ subscribe(listener: FormStateListener): Unsubscribe;
29
+ private commit;
30
+ private runValidation;
31
+ private computeDirty;
32
+ private scheduleNotify;
33
+ }
34
+ export declare function createForm(options: FormControllerOptions): FormController;
35
+ //# sourceMappingURL=controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../src/controller.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,eAAe,EACf,qBAAqB,EACrB,cAAc,EACd,SAAS,EACT,iBAAiB,EACjB,YAAY,EACZ,WAAW,EACZ,MAAM,YAAY,CAAC;AAWpB,qBAAa,cAAc;IACzB,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,KAAK,EAAE,SAAS,CAAC;IAEjB,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAsB;IACpD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAmD;IAC9E,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAgC;IAC1D,OAAO,CAAC,eAAe,CAAS;gBAEpB,OAAO,EAAE,qBAAqB;IAuB1C,OAAO,CAAC,eAAe;IAUvB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG;IAI3B,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,IAAI;IAaxC,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAS7C,QAAQ,IAAI,OAAO;IAKnB,sCAAsC;IACtC,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAKzB,iFAAiF;IACjF,QAAQ,IAAI,IAAI;IAMhB;;;;OAIG;IACH,SAAS,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI;IAOnC,MAAM,IAAI,OAAO,CAAC,YAAY,CAAC;IAcrC,KAAK,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAUzC,SAAS,CAAC,QAAQ,EAAE,iBAAiB,GAAG,WAAW;IAOnD,OAAO,CAAC,MAAM;IAKd,OAAO,CAAC,aAAa;IAWrB,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,cAAc;CAUvB;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,qBAAqB,GAAG,cAAc,CAEzE"}
@@ -0,0 +1,201 @@
1
+ import { describeFields } from './describeField.js';
2
+ import { groupErrorsByField, normalizeForValidation } from './normalizeValues.js';
3
+ import { resolveSchema } from './schemaLoader.js';
4
+ const EMPTY_STATE = Object.freeze({
5
+ values: {},
6
+ errors: {},
7
+ touched: {},
8
+ isValid: true,
9
+ isDirty: false,
10
+ isSubmitting: false,
11
+ });
12
+ export class FormController {
13
+ constructor(options) {
14
+ Object.defineProperty(this, "fields", {
15
+ enumerable: true,
16
+ configurable: true,
17
+ writable: true,
18
+ value: void 0
19
+ });
20
+ Object.defineProperty(this, "state", {
21
+ enumerable: true,
22
+ configurable: true,
23
+ writable: true,
24
+ value: void 0
25
+ });
26
+ Object.defineProperty(this, "schemaInstance", {
27
+ enumerable: true,
28
+ configurable: true,
29
+ writable: true,
30
+ value: void 0
31
+ });
32
+ Object.defineProperty(this, "initialValues", {
33
+ enumerable: true,
34
+ configurable: true,
35
+ writable: true,
36
+ value: void 0
37
+ });
38
+ Object.defineProperty(this, "validateOn", {
39
+ enumerable: true,
40
+ configurable: true,
41
+ writable: true,
42
+ value: void 0
43
+ });
44
+ Object.defineProperty(this, "listeners", {
45
+ enumerable: true,
46
+ configurable: true,
47
+ writable: true,
48
+ value: new Set()
49
+ });
50
+ Object.defineProperty(this, "notifyScheduled", {
51
+ enumerable: true,
52
+ configurable: true,
53
+ writable: true,
54
+ value: false
55
+ });
56
+ this.schemaInstance = resolveSchema(options.schema);
57
+ this.fields = describeFields(this.schemaInstance.formSchema.properties);
58
+ this.validateOn = options.validateOn ?? 'change';
59
+ // Merge schema defaults under user-provided initialValues so explicit
60
+ // values always win, but unset fields fall back to their `default`.
61
+ const defaults = this.collectDefaults();
62
+ const userInitial = options.initialValues ?? {};
63
+ const initial = { ...defaults, ...userInitial };
64
+ this.initialValues = { ...initial };
65
+ this.state = {
66
+ ...EMPTY_STATE,
67
+ values: initial,
68
+ };
69
+ // Run a first validation so consumers see initial errors (matches the
70
+ // behavior of `useFormValidation` in suite-v2, which validates with
71
+ // `immediate: true`).
72
+ this.runValidation();
73
+ }
74
+ collectDefaults() {
75
+ const out = {};
76
+ for (const f of this.fields) {
77
+ const def = f.originalAttrs?.default;
78
+ if (def === undefined)
79
+ continue;
80
+ out[f.name] = typeof def === 'function' ? def() : def;
81
+ }
82
+ return out;
83
+ }
84
+ getValue(name) {
85
+ return this.state.values[name];
86
+ }
87
+ setValue(name, value) {
88
+ const nextValues = { ...this.state.values, [name]: value };
89
+ const nextTouched = this.state.touched[name]
90
+ ? this.state.touched
91
+ : { ...this.state.touched, [name]: true };
92
+ this.commit({
93
+ values: nextValues,
94
+ touched: nextTouched,
95
+ isDirty: this.computeDirty(nextValues),
96
+ });
97
+ if (this.validateOn === 'change')
98
+ this.runValidation();
99
+ }
100
+ setValues(partial) {
101
+ const nextValues = { ...this.state.values, ...partial };
102
+ this.commit({
103
+ values: nextValues,
104
+ isDirty: this.computeDirty(nextValues),
105
+ });
106
+ if (this.validateOn === 'change')
107
+ this.runValidation();
108
+ }
109
+ validate() {
110
+ this.runValidation();
111
+ return this.state.isValid;
112
+ }
113
+ /** Mark a single field as touched. */
114
+ touch(name) {
115
+ if (this.state.touched[name])
116
+ return;
117
+ this.commit({ touched: { ...this.state.touched, [name]: true } });
118
+ }
119
+ /** Mark every field as touched. Useful right before showing errors on submit. */
120
+ touchAll() {
121
+ const touched = { ...this.state.touched };
122
+ for (const f of this.fields)
123
+ touched[f.name] = true;
124
+ this.commit({ touched });
125
+ }
126
+ /**
127
+ * Swap the underlying schema instance (e.g. on locale change) while preserving
128
+ * the current values and touched map. Re-derives the field descriptors and
129
+ * re-runs validation against the new instance.
130
+ */
131
+ setSchema(instance) {
132
+ this.schemaInstance = instance;
133
+ this.fields = describeFields(instance.formSchema.properties);
134
+ this.runValidation();
135
+ this.scheduleNotify();
136
+ }
137
+ async submit() {
138
+ this.commit({ isSubmitting: true });
139
+ try {
140
+ const isValid = this.validate();
141
+ return {
142
+ values: this.state.values,
143
+ isValid,
144
+ errors: this.state.errors,
145
+ };
146
+ }
147
+ finally {
148
+ this.commit({ isSubmitting: false });
149
+ }
150
+ }
151
+ reset(values) {
152
+ const next = values ? { ...values } : { ...this.initialValues };
153
+ this.state = {
154
+ ...EMPTY_STATE,
155
+ values: next,
156
+ };
157
+ this.runValidation();
158
+ this.scheduleNotify();
159
+ }
160
+ subscribe(listener) {
161
+ this.listeners.add(listener);
162
+ return () => {
163
+ this.listeners.delete(listener);
164
+ };
165
+ }
166
+ commit(patch) {
167
+ this.state = { ...this.state, ...patch };
168
+ this.scheduleNotify();
169
+ }
170
+ runValidation() {
171
+ const properties = this.schemaInstance.formSchema.properties || {};
172
+ const normalized = normalizeForValidation(this.state.values, properties);
173
+ this.schemaInstance.validate(normalized);
174
+ const list = this.schemaInstance.validator?.errors || [];
175
+ const errors = list.length === 0 ? {} : groupErrorsByField(list);
176
+ const isValid = Object.keys(errors).length === 0;
177
+ this.commit({ errors, isValid });
178
+ }
179
+ computeDirty(values) {
180
+ // Cheap enough for typical form sizes (<200 fields). If this becomes a
181
+ // hot spot we can switch to per-field tracking.
182
+ return JSON.stringify(values) !== JSON.stringify(this.initialValues);
183
+ }
184
+ scheduleNotify() {
185
+ if (this.notifyScheduled)
186
+ return;
187
+ if (this.listeners.size === 0)
188
+ return;
189
+ this.notifyScheduled = true;
190
+ queueMicrotask(() => {
191
+ this.notifyScheduled = false;
192
+ const snapshot = this.state;
193
+ for (const listener of this.listeners)
194
+ listener(snapshot);
195
+ });
196
+ }
197
+ }
198
+ export function createForm(options) {
199
+ return new FormController(options);
200
+ }
201
+ //# sourceMappingURL=controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"controller.js","sourceRoot":"","sources":["../src/controller.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { FieldDescriptor } from './types.js';
2
+ export declare function labelFromName(name: string): string;
3
+ export declare function describeField(name: string, ajvProperty: any): FieldDescriptor | null;
4
+ export declare function describeFields(properties: Record<string, any>): FieldDescriptor[];
5
+ //# sourceMappingURL=describeField.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"describeField.d.ts","sourceRoot":"","sources":["../src/describeField.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMlD;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,GAAG,eAAe,GAAG,IAAI,CAkBpF;AAED,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,eAAe,EAAE,CAOjF"}
@@ -0,0 +1,37 @@
1
+ import { resolveFieldKind } from './resolveFieldKind.js';
2
+ export function labelFromName(name) {
3
+ return String(name)
4
+ .replace(/([a-z])([A-Z])/g, '$1 $2')
5
+ .replace(/_/g, ' ')
6
+ .toLowerCase()
7
+ .replace(/^./, (c) => c.toUpperCase());
8
+ }
9
+ export function describeField(name, ajvProperty) {
10
+ const orig = ajvProperty?.originalAttrs || {};
11
+ const kind = resolveFieldKind(ajvProperty);
12
+ if (kind === null)
13
+ return null;
14
+ return {
15
+ name,
16
+ kind,
17
+ label: orig.label || labelFromName(name),
18
+ placeholder: orig.placeholder || orig.eg || '',
19
+ required: !!orig.required,
20
+ disabled: !!(orig.readOnly || orig.disabled),
21
+ hidden: !!orig.hidden,
22
+ fullWidth: !!orig.full,
23
+ helperText: orig.helperText || orig.description || '',
24
+ originalAttrs: orig,
25
+ ajvProperty,
26
+ };
27
+ }
28
+ export function describeFields(properties) {
29
+ const out = [];
30
+ for (const [name, property] of Object.entries(properties)) {
31
+ const desc = describeField(name, property);
32
+ if (desc)
33
+ out.push(desc);
34
+ }
35
+ return out;
36
+ }
37
+ //# sourceMappingURL=describeField.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"describeField.js","sourceRoot":"","sources":["../src/describeField.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAGzD,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,OAAO,MAAM,CAAC,IAAI,CAAC;SAChB,OAAO,CAAC,iBAAiB,EAAE,OAAO,CAAC;SACnC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC;SAClB,WAAW,EAAE;SACb,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,WAAgB;IAC1D,MAAM,IAAI,GAAwB,WAAW,EAAE,aAAa,IAAI,EAAE,CAAC;IACnE,MAAM,IAAI,GAAG,gBAAgB,CAAC,WAAW,CAAC,CAAC;IAC3C,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAE/B,OAAO;QACL,IAAI;QACJ,IAAI;QACJ,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,aAAa,CAAC,IAAI,CAAC;QACxC,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,EAAE,IAAI,EAAE;QAC9C,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ;QACzB,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC;QAC5C,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM;QACrB,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI;QACtB,UAAU,EAAE,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,WAAW,IAAI,EAAE;QACrD,aAAa,EAAE,IAAI;QACnB,WAAW;KACZ,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,UAA+B;IAC5D,MAAM,GAAG,GAAsB,EAAE,CAAC;IAClC,KAAK,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;QAC1D,MAAM,IAAI,GAAG,aAAa,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC3C,IAAI,IAAI;YAAE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,9 @@
1
+ export { FormController, createForm } from './controller.js';
2
+ export { describeField, describeFields, labelFromName } from './describeField.js';
3
+ export { resolveFieldKind } from './resolveFieldKind.js';
4
+ export { extractFieldName, groupErrorsByField, normalizeForValidation } from './normalizeValues.js';
5
+ export { clearSchemaCache, configureFormSchemaBuilder, resolveSchema, wrapRawSchema } from './schemaLoader.js';
6
+ export type { FormSchemaBuilder } from './schemaLoader.js';
7
+ export { createInlineValidator, mongooseToJsonSchema } from './inlineValidator.js';
8
+ export type { FieldDescriptor, FieldKind, FormControllerOptions, FormSchemaInput, FormSchemaLike, FormState, FormStateListener, Locale, RefFieldOption, RefResolver, RefResolverArgs, RefResolverResult, SubmitResult, Unsubscribe, } from './types.js';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAClF,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AACpG,OAAO,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAC/G,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACnF,YAAY,EACV,eAAe,EACf,SAAS,EACT,qBAAqB,EACrB,eAAe,EACf,cAAc,EACd,SAAS,EACT,iBAAiB,EACjB,MAAM,EACN,cAAc,EACd,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,YAAY,EACZ,WAAW,GACZ,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
1
+ export { FormController, createForm } from './controller.js';
2
+ export { describeField, describeFields, labelFromName } from './describeField.js';
3
+ export { resolveFieldKind } from './resolveFieldKind.js';
4
+ export { extractFieldName, groupErrorsByField, normalizeForValidation } from './normalizeValues.js';
5
+ export { clearSchemaCache, configureFormSchemaBuilder, resolveSchema, wrapRawSchema } from './schemaLoader.js';
6
+ export { createInlineValidator, mongooseToJsonSchema } from './inlineValidator.js';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAClF,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AACpG,OAAO,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAE/G,OAAO,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { FormSchemaLike, Locale } from './types.js';
2
+ export declare function mongooseToJsonSchema(modelSchema: Record<string, any>): Record<string, any>;
3
+ /**
4
+ * Build a {@link FormSchemaLike} backed by AJV + ajv-formats + ajv-i18n.
5
+ * The returned object has the same shape as a `FormSchemaWeb` instance,
6
+ * so it plugs straight into `FormController` and downstream rendering.
7
+ */
8
+ export declare function createInlineValidator(modelSchema: Record<string, any>, locale?: Locale): FormSchemaLike;
9
+ //# sourceMappingURL=inlineValidator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inlineValidator.d.ts","sourceRoot":"","sources":["../src/inlineValidator.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAmEzD,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAgB1F;AAqBD;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAChC,MAAM,GAAE,MAAa,GACpB,cAAc,CA4BhB"}
@@ -0,0 +1,136 @@
1
+ import Ajv from 'ajv';
2
+ import addFormats from 'ajv-formats';
3
+ import localizeEs from 'ajv-i18n/localize/es';
4
+ import localizeEn from 'ajv-i18n/localize/en';
5
+ import localizePtBr from 'ajv-i18n/localize/pt-BR';
6
+ const LOCALIZERS = {
7
+ en: localizeEn,
8
+ es: localizeEs,
9
+ pt: localizePtBr,
10
+ };
11
+ /**
12
+ * Convert a single Mongoose-style field definition into JSON Schema. Handles
13
+ * the common subset of attributes that appear in Prolibu schemas: type, enum,
14
+ * min/max, minLength/maxLength, format, regex, ref.
15
+ *
16
+ * Anything that doesn't map cleanly is dropped — AJV will validate what we
17
+ * give it. Custom Prolibu keywords (originalAttrs, arrayRules, etc.) are NOT
18
+ * handled here; for full Prolibu validation use FormSchemaWeb via
19
+ * configureFormSchemaBuilder.
20
+ */
21
+ function fieldToJsonSchema(def) {
22
+ const out = {};
23
+ // Type — Mongoose uses PascalCase, JSON Schema uses lowercase.
24
+ const t = typeof def.type === 'string' ? def.type.toLowerCase() : def.type;
25
+ switch (t) {
26
+ case 'string':
27
+ case 'objectid':
28
+ out.type = 'string';
29
+ break;
30
+ case 'number':
31
+ case 'integer':
32
+ out.type = 'number';
33
+ break;
34
+ case 'boolean':
35
+ out.type = 'boolean';
36
+ break;
37
+ case 'date':
38
+ out.type = 'string';
39
+ out.format = 'date-time';
40
+ break;
41
+ case 'mixed':
42
+ // no constraint
43
+ break;
44
+ default:
45
+ if (Array.isArray(def.type)) {
46
+ const inner = typeof def.type[0] === 'string' ? def.type[0].toLowerCase() : 'string';
47
+ out.type = 'array';
48
+ out.items = { type: inner === 'number' ? 'number' : 'string' };
49
+ }
50
+ }
51
+ if (Array.isArray(def.enum) && def.enum.length > 0)
52
+ out.enum = def.enum;
53
+ if (typeof def.min === 'number')
54
+ out.minimum = def.min;
55
+ if (typeof def.max === 'number')
56
+ out.maximum = def.max;
57
+ if (typeof def.minLength === 'number')
58
+ out.minLength = def.minLength;
59
+ if (typeof def.maxLength === 'number')
60
+ out.maxLength = def.maxLength;
61
+ const pattern = def.regex ?? def.match;
62
+ if (pattern instanceof RegExp)
63
+ out.pattern = pattern.source;
64
+ else if (typeof pattern === 'string')
65
+ out.pattern = pattern;
66
+ if (typeof def.format === 'string')
67
+ out.format = def.format;
68
+ return out;
69
+ }
70
+ export function mongooseToJsonSchema(modelSchema) {
71
+ const properties = {};
72
+ const required = [];
73
+ for (const [name, def] of Object.entries(modelSchema)) {
74
+ if (!def || typeof def !== 'object')
75
+ continue;
76
+ properties[name] = fieldToJsonSchema(def);
77
+ if (def.required)
78
+ required.push(name);
79
+ }
80
+ return {
81
+ type: 'object',
82
+ properties,
83
+ required,
84
+ additionalProperties: true,
85
+ };
86
+ }
87
+ const ajvCache = new WeakMap();
88
+ function compile(modelSchema) {
89
+ const cached = ajvCache.get(modelSchema);
90
+ if (cached)
91
+ return cached;
92
+ const ajv = new Ajv({
93
+ allErrors: true,
94
+ strict: false,
95
+ validateFormats: true,
96
+ });
97
+ addFormats(ajv);
98
+ const jsonSchema = mongooseToJsonSchema(modelSchema);
99
+ const validate = ajv.compile(jsonSchema);
100
+ ajvCache.set(modelSchema, validate);
101
+ return validate;
102
+ }
103
+ /**
104
+ * Build a {@link FormSchemaLike} backed by AJV + ajv-formats + ajv-i18n.
105
+ * The returned object has the same shape as a `FormSchemaWeb` instance,
106
+ * so it plugs straight into `FormController` and downstream rendering.
107
+ */
108
+ export function createInlineValidator(modelSchema, locale = 'es') {
109
+ // Property table — same shape `describeField` and `resolveFieldKind` expect.
110
+ // Each property carries `originalAttrs` as the side-channel for UI metadata.
111
+ const properties = {};
112
+ for (const [name, def] of Object.entries(modelSchema)) {
113
+ if (!def || typeof def !== 'object')
114
+ continue;
115
+ const originalAttrs = { ...def };
116
+ if (typeof originalAttrs.type === 'string') {
117
+ originalAttrs.type = originalAttrs.type.toLowerCase();
118
+ }
119
+ properties[name] = { originalAttrs };
120
+ }
121
+ const validateFn = compile(modelSchema);
122
+ const localize = LOCALIZERS[locale] || LOCALIZERS.es;
123
+ const instance = {
124
+ formSchema: { properties },
125
+ validator: { errors: [] },
126
+ validate(data) {
127
+ validateFn(data);
128
+ const errs = validateFn.errors ?? [];
129
+ if (errs.length > 0)
130
+ localize(errs);
131
+ instance.validator.errors = errs;
132
+ },
133
+ };
134
+ return instance;
135
+ }
136
+ //# sourceMappingURL=inlineValidator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inlineValidator.js","sourceRoot":"","sources":["../src/inlineValidator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Strip populated ref objects down to their `_id` so AJV's `objectid` format
3
+ * validator (which only accepts hex strings) doesn't reject loaded records.
4
+ */
5
+ export declare function normalizeForValidation(data: Record<string, any>, properties: Record<string, any>): Record<string, any>;
6
+ interface AjvError {
7
+ keyword?: string;
8
+ instancePath?: string;
9
+ params?: {
10
+ missingProperty?: string;
11
+ };
12
+ message?: string;
13
+ }
14
+ /** Map an AJV error to the field name it belongs to. */
15
+ export declare function extractFieldName(err: AjvError): string | null;
16
+ export declare function groupErrorsByField(errors: AjvError[]): Record<string, string[]>;
17
+ export {};
18
+ //# sourceMappingURL=normalizeValues.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalizeValues.d.ts","sourceRoot":"","sources":["../src/normalizeValues.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACzB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAC9B,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAcrB;AAED,UAAU,QAAQ;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE;QAAE,eAAe,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wDAAwD;AACxD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,QAAQ,GAAG,MAAM,GAAG,IAAI,CAS7D;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAS/E"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Strip populated ref objects down to their `_id` so AJV's `objectid` format
3
+ * validator (which only accepts hex strings) doesn't reject loaded records.
4
+ */
5
+ export function normalizeForValidation(data, properties) {
6
+ const out = { ...data };
7
+ for (const [name, def] of Object.entries(properties)) {
8
+ if (!def?.originalAttrs?.ref)
9
+ continue;
10
+ const v = out[name];
11
+ if (Array.isArray(v)) {
12
+ out[name] = v.map((item) => item && typeof item === 'object' && item._id ? item._id : item);
13
+ }
14
+ else if (v && typeof v === 'object' && v._id) {
15
+ out[name] = v._id;
16
+ }
17
+ }
18
+ return out;
19
+ }
20
+ /** Map an AJV error to the field name it belongs to. */
21
+ export function extractFieldName(err) {
22
+ if (err.keyword === 'required' && err.params?.missingProperty) {
23
+ return err.params.missingProperty;
24
+ }
25
+ if (typeof err.instancePath === 'string' && err.instancePath.length > 0) {
26
+ const segments = err.instancePath.split('/').filter(Boolean);
27
+ return segments[0] || null;
28
+ }
29
+ return null;
30
+ }
31
+ export function groupErrorsByField(errors) {
32
+ const out = {};
33
+ for (const err of errors) {
34
+ const field = extractFieldName(err);
35
+ if (!field)
36
+ continue;
37
+ if (!out[field])
38
+ out[field] = [];
39
+ out[field].push(err.message || 'Invalid value');
40
+ }
41
+ return out;
42
+ }
43
+ //# sourceMappingURL=normalizeValues.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalizeValues.js","sourceRoot":"","sources":["../src/normalizeValues.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CACpC,IAAyB,EACzB,UAA+B;IAE/B,MAAM,GAAG,GAAwB,EAAE,GAAG,IAAI,EAAE,CAAC;IAC7C,KAAK,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;QACrD,IAAI,CAAE,GAAW,EAAE,aAAa,EAAE,GAAG;YAAE,SAAS;QAChD,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC;QACpB,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;YACrB,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CACzB,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAC/D,CAAC;QACJ,CAAC;aAAM,IAAI,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,GAAG,EAAE,CAAC;YAC/C,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC;QACpB,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AASD,wDAAwD;AACxD,MAAM,UAAU,gBAAgB,CAAC,GAAa;IAC5C,IAAI,GAAG,CAAC,OAAO,KAAK,UAAU,IAAI,GAAG,CAAC,MAAM,EAAE,eAAe,EAAE,CAAC;QAC9D,OAAO,GAAG,CAAC,MAAM,CAAC,eAAe,CAAC;IACpC,CAAC;IACD,IAAI,OAAO,GAAG,CAAC,YAAY,KAAK,QAAQ,IAAI,GAAG,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxE,MAAM,QAAQ,GAAG,GAAG,CAAC,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC7D,OAAO,QAAQ,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;IAC7B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,MAAkB;IACnD,MAAM,GAAG,GAA6B,EAAE,CAAC;IACzC,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;QACpC,IAAI,CAAC,KAAK;YAAE,SAAS;QACrB,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;YAAE,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;QACjC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,IAAI,eAAe,CAAC,CAAC;IAClD,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { FieldKind } from './types.js';
2
+ export declare function resolveFieldKind(ajvProperty: any): FieldKind | null;
3
+ //# sourceMappingURL=resolveFieldKind.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveFieldKind.d.ts","sourceRoot":"","sources":["../src/resolveFieldKind.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAmB5C,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,GAAG,GAAG,SAAS,GAAG,IAAI,CAUnE"}
@@ -0,0 +1,26 @@
1
+ // Order matters — first non-undefined wins. `null` means "skip this field".
2
+ const RESOLVERS = [
3
+ (orig) => (orig.hidden ? null : undefined),
4
+ (orig) => (orig.uiCom === 'TextArea' ? 'textarea' : undefined),
5
+ (orig) => (orig.uiCom === 'HtmlEditor' ? 'html' : undefined),
6
+ (orig) => (orig.ref ? 'ref' : undefined),
7
+ (orig) => (Array.isArray(orig.enum) ? 'select' : undefined),
8
+ (orig) => (orig.type === 'boolean' ? 'boolean' : undefined),
9
+ (orig) => (orig.type === 'number' || orig.type === 'integer' ? 'number' : undefined),
10
+ (orig) => (orig.type === 'date' ? 'date' : undefined),
11
+ (orig) => (orig.type === 'string' ? 'text' : undefined),
12
+ ];
13
+ export function resolveFieldKind(ajvProperty) {
14
+ const orig = ajvProperty?.originalAttrs;
15
+ if (!orig)
16
+ return null;
17
+ for (const resolve of RESOLVERS) {
18
+ const result = resolve(orig);
19
+ if (result === null)
20
+ return null;
21
+ if (result !== undefined)
22
+ return result;
23
+ }
24
+ return 'text';
25
+ }
26
+ //# sourceMappingURL=resolveFieldKind.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveFieldKind.js","sourceRoot":"","sources":["../src/resolveFieldKind.ts"],"names":[],"mappings":"AAMA,4EAA4E;AAC5E,MAAM,SAAS,GAAe;IAC5B,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;IAC1C,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC;IAC9D,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,KAAK,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;IAC5D,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IACxC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;IAC3D,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;IAC3D,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;IACpF,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;IACrD,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;CACxD,CAAC;AAEF,MAAM,UAAU,gBAAgB,CAAC,WAAgB;IAC/C,MAAM,IAAI,GAAG,WAAW,EAAE,aAA0C,CAAC;IACrE,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IAEvB,KAAK,MAAM,OAAO,IAAI,SAAS,EAAE,CAAC;QAChC,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAC7B,IAAI,MAAM,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QACjC,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO,MAAM,CAAC;IAC1C,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,39 @@
1
+ import type { FormSchemaInput, FormSchemaLike, Locale } from './types.js';
2
+ /**
3
+ * Constructor signature for `FormSchemaWeb` when consumers want us to build
4
+ * the instance from a raw Mongoose-style modelSchema. We accept this via
5
+ * dependency injection (see {@link configureFormSchemaBuilder}) so that
6
+ * `form-core` itself stays free of a hard dependency on `@skemify/cases`.
7
+ */
8
+ export type FormSchemaBuilder = (modelSchema: Record<string, any>, locale: Locale) => FormSchemaLike;
9
+ /**
10
+ * Register the FormSchemaWeb builder once, at application bootstrap.
11
+ *
12
+ * @example
13
+ * import { configureFormSchemaBuilder } from '@prolibu-suite/cobalt-form-core'
14
+ * import { FormSchemaWeb } from '@skemify/cases/schemas'
15
+ *
16
+ * configureFormSchemaBuilder((modelSchema, locale) => {
17
+ * const inst = new FormSchemaWeb(modelSchema, locale)
18
+ * inst.buildAvjSchema()
19
+ * return inst
20
+ * })
21
+ */
22
+ export declare function configureFormSchemaBuilder(fn: FormSchemaBuilder): void;
23
+ export declare function resolveSchema(input: FormSchemaInput): FormSchemaLike;
24
+ export declare function clearSchemaCache(): void;
25
+ /**
26
+ * Wrap a raw Mongoose/Prolibu-style modelSchema as a {@link FormSchemaLike}
27
+ * with a no-op validator.
28
+ *
29
+ * Useful for the `<co-form>` Web Component on the CDN, where the host page
30
+ * cannot ship the private `@skemify/cases` SDK. Fields render and values are
31
+ * tracked; validation is the caller's responsibility (use `coSubmit` and
32
+ * validate before persisting, or register a real builder).
33
+ *
34
+ * The raw schema must look like `{ fieldName: { type, required, ... } }`.
35
+ * Each entry becomes a property whose `originalAttrs` is the entry itself,
36
+ * which is the shape `describeField` / `resolveFieldKind` already expect.
37
+ */
38
+ export declare function wrapRawSchema(modelSchema: Record<string, any>): FormSchemaLike;
39
+ //# sourceMappingURL=schemaLoader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemaLoader.d.ts","sourceRoot":"","sources":["../src/schemaLoader.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAE1E;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAC9B,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAChC,MAAM,EAAE,MAAM,KACX,cAAc,CAAC;AAIpB;;;;;;;;;;;;GAYG;AACH,wBAAgB,0BAA0B,CAAC,EAAE,EAAE,iBAAiB,GAAG,IAAI,CAEtE;AAQD,wBAAgB,aAAa,CAAC,KAAK,EAAE,eAAe,GAAG,cAAc,CAgBpE;AAED,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,cAAc,CAoB9E"}
@@ -0,0 +1,78 @@
1
+ import { createInlineValidator } from './inlineValidator.js';
2
+ let builder = null;
3
+ /**
4
+ * Register the FormSchemaWeb builder once, at application bootstrap.
5
+ *
6
+ * @example
7
+ * import { configureFormSchemaBuilder } from '@prolibu-suite/cobalt-form-core'
8
+ * import { FormSchemaWeb } from '@skemify/cases/schemas'
9
+ *
10
+ * configureFormSchemaBuilder((modelSchema, locale) => {
11
+ * const inst = new FormSchemaWeb(modelSchema, locale)
12
+ * inst.buildAvjSchema()
13
+ * return inst
14
+ * })
15
+ */
16
+ export function configureFormSchemaBuilder(fn) {
17
+ builder = fn;
18
+ }
19
+ const cache = new Map();
20
+ function cacheKey(modelSchema, locale) {
21
+ return `${locale}::${Object.keys(modelSchema).sort().join(',')}`;
22
+ }
23
+ export function resolveSchema(input) {
24
+ if ('instance' in input)
25
+ return input.instance;
26
+ const { modelSchema, locale = 'es' } = input;
27
+ const key = cacheKey(modelSchema, locale);
28
+ const cached = cache.get(key);
29
+ if (cached)
30
+ return cached;
31
+ // Use the host-registered builder (e.g. FormSchemaWeb) if available, else
32
+ // fall back to the bundled AJV-based inline validator. Means
33
+ // `createForm({ schema: { modelSchema } })` "just works" without any
34
+ // bootstrap step, while hosts that want full Prolibu validation can opt-in
35
+ // via configureFormSchemaBuilder().
36
+ const built = builder ? builder(modelSchema, locale) : createInlineValidator(modelSchema, locale);
37
+ cache.set(key, built);
38
+ return built;
39
+ }
40
+ export function clearSchemaCache() {
41
+ cache.clear();
42
+ }
43
+ /**
44
+ * Wrap a raw Mongoose/Prolibu-style modelSchema as a {@link FormSchemaLike}
45
+ * with a no-op validator.
46
+ *
47
+ * Useful for the `<co-form>` Web Component on the CDN, where the host page
48
+ * cannot ship the private `@skemify/cases` SDK. Fields render and values are
49
+ * tracked; validation is the caller's responsibility (use `coSubmit` and
50
+ * validate before persisting, or register a real builder).
51
+ *
52
+ * The raw schema must look like `{ fieldName: { type, required, ... } }`.
53
+ * Each entry becomes a property whose `originalAttrs` is the entry itself,
54
+ * which is the shape `describeField` / `resolveFieldKind` already expect.
55
+ */
56
+ export function wrapRawSchema(modelSchema) {
57
+ const properties = {};
58
+ for (const [name, def] of Object.entries(modelSchema)) {
59
+ if (!def || typeof def !== 'object')
60
+ continue;
61
+ const originalAttrs = { ...def };
62
+ // Normalize Mongoose-style type strings ('String') to JSON-Schema style ('string')
63
+ // so resolveFieldKind matches them. Keep the original casing on the side-channel
64
+ // in case downstream code cares.
65
+ if (typeof originalAttrs.type === 'string') {
66
+ originalAttrs.type = originalAttrs.type.toLowerCase();
67
+ }
68
+ properties[name] = { originalAttrs };
69
+ }
70
+ return {
71
+ formSchema: { properties },
72
+ validate: () => {
73
+ /* no-op */
74
+ },
75
+ validator: { errors: [] },
76
+ };
77
+ }
78
+ //# sourceMappingURL=schemaLoader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemaLoader.js","sourceRoot":"","sources":["../src/schemaLoader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAc7D,IAAI,OAAO,GAA6B,IAAI,CAAC;AAE7C;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,0BAA0B,CAAC,EAAqB;IAC9D,OAAO,GAAG,EAAE,CAAC;AACf,CAAC;AAED,MAAM,KAAK,GAAG,IAAI,GAAG,EAA0B,CAAC;AAEhD,SAAS,QAAQ,CAAC,WAAgC,EAAE,MAAc;IAChE,OAAO,GAAG,MAAM,KAAK,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;AACnE,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAsB;IAClD,IAAI,UAAU,IAAI,KAAK;QAAE,OAAO,KAAK,CAAC,QAAQ,CAAC;IAE/C,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;IAC7C,MAAM,GAAG,GAAG,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC9B,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAE1B,0EAA0E;IAC1E,6DAA6D;IAC7D,qEAAqE;IACrE,2EAA2E;IAC3E,oCAAoC;IACpC,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,qBAAqB,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IAClG,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACtB,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,KAAK,CAAC,KAAK,EAAE,CAAC;AAChB,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,aAAa,CAAC,WAAgC;IAC5D,MAAM,UAAU,GAAwB,EAAE,CAAC;IAC3C,KAAK,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;QACtD,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;YAAE,SAAS;QAC9C,MAAM,aAAa,GAAG,EAAE,GAAG,GAAG,EAAE,CAAC;QACjC,mFAAmF;QACnF,iFAAiF;QACjF,iCAAiC;QACjC,IAAI,OAAO,aAAa,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC3C,aAAa,CAAC,IAAI,GAAG,aAAa,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;QACxD,CAAC;QACD,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,aAAa,EAAE,CAAC;IACvC,CAAC;IACD,OAAO;QACL,UAAU,EAAE,EAAE,UAAU,EAAE;QAC1B,QAAQ,EAAE,GAAG,EAAE;YACb,WAAW;QACb,CAAC;QACD,SAAS,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;KAC1B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,82 @@
1
+ export type Locale = 'en' | 'es' | 'pt';
2
+ export type FieldKind = 'text' | 'textarea' | 'number' | 'date' | 'boolean' | 'select' | 'ref' | 'html' | 'custom';
3
+ export interface FieldDescriptor {
4
+ name: string;
5
+ kind: FieldKind;
6
+ label: string;
7
+ placeholder: string;
8
+ required: boolean;
9
+ disabled: boolean;
10
+ hidden: boolean;
11
+ fullWidth: boolean;
12
+ helperText: string;
13
+ originalAttrs: Record<string, any>;
14
+ ajvProperty: Record<string, any>;
15
+ }
16
+ export interface FormState {
17
+ values: Record<string, any>;
18
+ errors: Record<string, string[]>;
19
+ touched: Record<string, boolean>;
20
+ isValid: boolean;
21
+ isDirty: boolean;
22
+ isSubmitting: boolean;
23
+ }
24
+ export interface SubmitResult {
25
+ values: Record<string, any>;
26
+ isValid: boolean;
27
+ errors: Record<string, string[]>;
28
+ }
29
+ /**
30
+ * Structural type for a `FormSchemaWeb` instance from `@skemify/cases`.
31
+ * Defined structurally so we don't impose a hard runtime dep on the SDK.
32
+ */
33
+ export interface FormSchemaLike {
34
+ formSchema: {
35
+ properties: Record<string, any>;
36
+ };
37
+ validate: (data: Record<string, any>) => void;
38
+ validator?: {
39
+ errors?: any[];
40
+ };
41
+ }
42
+ export type FormSchemaInput = {
43
+ instance: FormSchemaLike;
44
+ } | {
45
+ modelSchema: Record<string, any>;
46
+ locale?: Locale;
47
+ };
48
+ export interface FormControllerOptions {
49
+ schema: FormSchemaInput;
50
+ initialValues?: Record<string, any>;
51
+ validateOn?: 'change' | 'blur' | 'submit';
52
+ }
53
+ export type FormStateListener = (state: FormState) => void;
54
+ export type Unsubscribe = () => void;
55
+ /** A single selectable record returned by a {@link RefResolver}. */
56
+ export interface RefFieldOption {
57
+ value: string;
58
+ label: string;
59
+ meta?: Record<string, any>;
60
+ }
61
+ /**
62
+ * Arguments handed to a {@link RefResolver}. The host inspects them and
63
+ * decides what to fetch.
64
+ *
65
+ * - `query`/`page` is the live-search case (user typing or scrolling).
66
+ * - `ids` is the hydration case (form opened with raw `_id` values; we need
67
+ * labels for the chips).
68
+ */
69
+ export interface RefResolverArgs {
70
+ model: string;
71
+ query?: string;
72
+ page?: number;
73
+ pageSize?: number;
74
+ ids?: string[];
75
+ }
76
+ export interface RefResolverResult {
77
+ options: RefFieldOption[];
78
+ total?: number;
79
+ hasMore?: boolean;
80
+ }
81
+ export type RefResolver = (args: RefResolverArgs) => Promise<RefResolverResult>;
82
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@prolibu-suite/cobalt-form-core",
3
+ "version": "0.1.0",
4
+ "description": "Cobalt Form — framework-agnostic core. Schema-driven form controller backed by AJV via FormSchemaWeb.",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "module": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/index.js",
12
+ "types": "./dist/index.d.ts"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "keywords": [
19
+ "form",
20
+ "schema",
21
+ "ajv",
22
+ "cobalt",
23
+ "prolibu",
24
+ "headless"
25
+ ],
26
+ "author": "Prolibu <contact@prolibu.com>",
27
+ "license": "MIT",
28
+ "dependencies": {
29
+ "ajv": "^8.17.1",
30
+ "ajv-formats": "^3.0.1",
31
+ "ajv-i18n": "^4.2.0"
32
+ },
33
+ "devDependencies": {
34
+ "typescript": "^6.0.3",
35
+ "vitest": "^4.1.4"
36
+ },
37
+ "publishConfig": {
38
+ "access": "public"
39
+ },
40
+ "scripts": {
41
+ "build": "tsc -p tsconfig.json",
42
+ "dev": "tsc -p tsconfig.json --watch",
43
+ "clean": "rm -rf dist",
44
+ "test": "vitest run",
45
+ "test:watch": "vitest"
46
+ }
47
+ }