102 lines
6.0 KiB
JavaScript
102 lines
6.0 KiB
JavaScript
import { z } from 'zod';
|
|
/**
|
|
* Manages a collection of Zod schema properties
|
|
* and combines them into a single Zod object schema.
|
|
*
|
|
* @template MetaType The type of metadata you want to store for each field.
|
|
* Defaults to Record<string, unknown> if not provided.
|
|
*/
|
|
export class ZodMetaMap {
|
|
fieldMap = new Map();
|
|
/**
|
|
* Adds a Zod schema under a specific key (property name),
|
|
* optionally attaching typed metadata.
|
|
*
|
|
* @param key - The name of the property in the root object.
|
|
* @param schema - The Zod schema for that property.
|
|
* @param metadata - Optional metadata object (type MetaType).
|
|
*/
|
|
add(key, schema, metadata) {
|
|
this.fieldMap.set(key, { schema, metadata });
|
|
return this;
|
|
}
|
|
/**
|
|
* Builds and returns a root Zod object
|
|
* that combines all properties which were added.
|
|
*/
|
|
root() {
|
|
const shape = {};
|
|
for (const [key, { schema }] of this.fieldMap.entries()) {
|
|
shape[key] = schema;
|
|
}
|
|
return z.object(shape);
|
|
}
|
|
/**
|
|
* Retrieves the metadata for a specific key, if any.
|
|
*/
|
|
getMetadata(key) {
|
|
return this.fieldMap.get(key)?.metadata;
|
|
}
|
|
/**
|
|
* Static factory method: creates a SchemaMetaManager
|
|
* while letting you optionally specify the MetaType.
|
|
*
|
|
* Usage:
|
|
* const manager = SchemaMetaManager.create<MyFieldMeta>();
|
|
*/
|
|
static create() {
|
|
return new ZodMetaMap();
|
|
}
|
|
/**
|
|
* Returns a basic UiSchema object that RJSF can use to render form controls.
|
|
*
|
|
* - Adds a top-level "ui:submitButtonOptions" (example).
|
|
* - For each field, we set `ui:title` (uppercase key),
|
|
* `ui:description` (from Zod's .describe() if available),
|
|
* and a naive placeholder from the default value (if parse(undefined) succeeds).
|
|
*/
|
|
getUISchema() {
|
|
// Start with some top-level UI schema config (optional)
|
|
const uiSchema = {
|
|
'ui:submitButtonOptions': {
|
|
props: {
|
|
disabled: false,
|
|
className: 'btn btn-info',
|
|
},
|
|
norender: false,
|
|
submitText: 'Submit',
|
|
},
|
|
};
|
|
for (const [key, { schema }] of this.fieldMap.entries()) {
|
|
let fieldUi = {};
|
|
// Use the Zod description if available
|
|
// (Accessing `._def.description` is private/hacky, but commonly done.)
|
|
const sAny = schema;
|
|
if (sAny?._def?.description) {
|
|
fieldUi['ui:description'] = sAny._def.description;
|
|
}
|
|
// RJSF usually reads 'title' from JSON schema. But if you want
|
|
// to override it in UI schema, you can do so:
|
|
fieldUi['ui:title'] = key[0].toUpperCase() + key.substr(1).toLowerCase();
|
|
// If the Zod schema allows a default, we can parse(undefined) to get it.
|
|
try {
|
|
const defaultVal = schema.parse(undefined);
|
|
// There's no official 'ui:default' in RJSF, but you could do a placeholder:
|
|
fieldUi['ui:placeholder'] = defaultVal;
|
|
}
|
|
catch {
|
|
// no default
|
|
}
|
|
if (key == 'path') {
|
|
debugger;
|
|
}
|
|
fieldUi = {
|
|
...fieldUi,
|
|
...this.getMetadata(key),
|
|
};
|
|
uiSchema[key] = fieldUi;
|
|
}
|
|
return uiSchema;
|
|
}
|
|
}
|
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiem9kX21hcC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zaGVtYXMvem9kX21hcC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsQ0FBQyxFQUF5QixNQUFNLEtBQUssQ0FBQztBQUUvQzs7Ozs7O0dBTUc7QUFDSCxNQUFNLE9BQU8sVUFBVTtJQUNYLFFBQVEsR0FBRyxJQUFJLEdBQUcsRUFHdkIsQ0FBQztJQUVKOzs7Ozs7O09BT0c7SUFDSCxHQUFHLENBQXVCLEdBQVcsRUFBRSxNQUFTLEVBQUUsUUFBbUI7UUFDakUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUM7UUFDN0MsT0FBTyxJQUFJLENBQUM7SUFDaEIsQ0FBQztJQUVEOzs7T0FHRztJQUNILElBQUk7UUFDQSxNQUFNLEtBQUssR0FBK0IsRUFBRSxDQUFDO1FBQzdDLEtBQUssTUFBTSxDQUFDLEdBQUcsRUFBRSxFQUFFLE1BQU0sRUFBRSxDQUFDLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsRUFBRTtZQUNyRCxLQUFLLENBQUMsR0FBRyxDQUFDLEdBQUcsTUFBTSxDQUFDO1NBQ3ZCO1FBQ0QsT0FBTyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzNCLENBQUM7SUFFRDs7T0FFRztJQUNILFdBQVcsQ0FBQyxHQUFXO1FBQ25CLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsUUFBUSxDQUFDO0lBQzVDLENBQUM7SUFFRDs7Ozs7O09BTUc7SUFDSCxNQUFNLENBQUMsTUFBTTtRQUNULE9BQU8sSUFBSSxVQUFVLEVBQU0sQ0FBQztJQUNoQyxDQUFDO0lBRUQ7Ozs7Ozs7T0FPRztJQUNILFdBQVc7UUFDUCx3REFBd0Q7UUFDeEQsTUFBTSxRQUFRLEdBQTRCO1lBQ3RDLHdCQUF3QixFQUFFO2dCQUN0QixLQUFLLEVBQUU7b0JBQ0gsUUFBUSxFQUFFLEtBQUs7b0JBQ2YsU0FBUyxFQUFFLGNBQWM7aUJBQzVCO2dCQUNELFFBQVEsRUFBRSxLQUFLO2dCQUNmLFVBQVUsRUFBRSxRQUFRO2FBQ3ZCO1NBQ0osQ0FBQztRQUVGLEtBQUssTUFBTSxDQUFDLEdBQUcsRUFBRSxFQUFFLE1BQU0sRUFBRSxDQUFDLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsRUFBRTtZQUNyRCxJQUFJLE9BQU8sR0FBNEIsRUFBRyxDQUFDO1lBQzNDLHVDQUF1QztZQUN2Qyx1RUFBdUU7WUFDdkUsTUFBTSxJQUFJLEdBQUcsTUFBYSxDQUFDO1lBQzNCLElBQUksSUFBSSxFQUFFLElBQUksRUFBRSxXQUFXLEVBQUU7Z0JBQ3pCLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDO2FBQ3JEO1lBRUQsK0RBQStEO1lBQy9ELDhDQUE4QztZQUM5QyxPQUFPLENBQUMsVUFBVSxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLFdBQVcsRUFBRSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUE7WUFFeEUseUVBQXlFO1lBQ3pFLElBQUk7Z0JBQ0EsTUFBTSxVQUFVLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsQ0FBQztnQkFDM0MsNEVBQTRFO2dCQUM1RSxPQUFPLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxVQUFVLENBQUM7YUFDMUM7WUFBQyxNQUFNO2dCQUNKLGFBQWE7YUFDaEI7WUFDRCxJQUFHLEdBQUcsSUFBRSxNQUFNLEVBQUM7Z0JBQ1gsUUFBUSxDQUFBO2FBQ1g7WUFDRCxPQUFPLEdBQUc7Z0JBQ04sR0FBRyxPQUFPO2dCQUNWLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUM7YUFDM0IsQ0FBQTtZQUNELFFBQVEsQ0FBQyxHQUFHLENBQUMsR0FBRyxPQUFPLENBQUM7U0FDM0I7UUFDRCxPQUFPLFFBQVEsQ0FBQztJQUNwQixDQUFDO0NBQ0oifQ==
|