@palmares/schemas
Version:
This defines a default schema definition for validation of data, it abstract popular schema validation libraries like zod, yup, valibot and others"
136 lines • 8.61 kB
TypeScript
import { ArraySchema } from './schema/array';
import { ObjectSchema } from './schema/object';
import type { Schema } from './schema/schema';
import type { DefinitionsOfSchemaType, ExtractTypeFromObjectOfSchemas } from './schema/types';
import type { InferModel, Model, ModelFields } from '@palmares/databases';
/**
* Different from other schemas, this function is a factory function that returns either an ObjectSchema or an
* ArraySchema. The idea is to build the schema of a model dynamically based on its fields.
*
* Another feature is that it can automatically add the foreign key relation to the schema, but for that you need to
* define the fields of the related model in the fields object.
*
* For example: A User model have a field `companyId` that is a ForeignKeyField to the Company model. The `relationName`
* is the direct relation from the User model to the Company model, and the `relatedName` is the reverse relation from
* the Company model to the User model. If you define the fieldName as either the relatedName or the relationName it
* will fetch the data automatically.
*
* **Important**: We build the schema dynamically but also lazily, if you don't try to parse or validate the schema, it
* won't be built. After the first time it's built, it's cached and never built again.
*
* **Important 2**: If you want to use the automatic relation feature, you need to define guarantee that the foreignKey
* field fieldName exists on `show` array, or that it doesn't exist on `omit` array.
*
* Like: `{ options: { show: ['id', 'name', 'companyId'] }}` or `{ options: { omit: ['id'] }}` it **will work**.
*
* If you do `{ options: { show: ['id', 'name'] }}` or `{ options: { omit: ['companyId']} }` it **won't work**.
*
* **Important 3**: If you want to return an array instead of an object, you need to pass the `many` option as true.
*
* @example
* ```typescript
* import { auto, choice, foreignKey, Model, define } from '@palmares/databases';
* import * as p from '@palmares/schemas';
*
* const Company = define('Company', {
* fields: {
* id: auto(),
* name: text(),
* },
* options: {
* tableName: 'company',
* }
* });
*
* class User extends Model<User>() {
* fields = {
* id: auto(),
* type: choice({ choices: ['user', 'admin'] }),
* companyId: foreignKey({
* relatedTo: Company,
* relationName: 'company',
* relatedName: 'usersOfCompany',
* toField: 'id',
* onDelete: 'CASCADE',
* }),
* }
*
* options = {
* tableName: 'user',
* }
* }
*
* const userSchema = p.modelSchema(User, {
* fields: {
* company: p.modelSchema(Company).optional({ outputOnly: true });
* },
* show: ['type', 'companyId'], // 'companyId' is required for the automatic relation to work, otherwise it won't show
* omitRelation: ['company']
* });
*
* const companySchema = p.modelSchema(Company, {
* fields: {
* usersOfCompany: p.modelSchema(User, { many: true }).optional({ outputOnly: true });
* },
* // The `companyId` field on the 'User' model is tied to the `id` field on the 'Company' model so 'id' is required.
* show: ['id', 'type'] * });
*```
* @param model - The model that you want to build the schema from.
* @param options - The options to build the schema.
* @param options.ignoreExtraneousFields - If you want to ignore extraneous fields set this to true.
* @param options.engineInstance - What engine instance you want to use to fetch the data. Defaults to the first one.
* @param options.omitRelation - Fields that you want to omit from the relation. For example, on the example above, on
* the `userSchema` you can omit the `companyId` field from the relation by just passing `['company']`, on the
* `companySchema` you can omit the `id` field from company by passing `['usersOfCompany']`.
*
* @param options.fields - Extra fields that you want to add to the schema. If it has the same name as the model field,
* We will not create a schema for that field and use the one you have defined here.
* @param options.omit - Fields that you want to omit from the schema. If that is defined, we ignore `show` option.
* @param options.show - Fields that you want to show on the schema. If that is defined, we ignore `omit` option.
* @param options.many - If you want to return an array instead of an object, set this to true. With that we create
* an ArraySchema instead of an ObjectSchema.
*
* @returns - If you pass the `many` option as true, we return an ArraySchema, otherwise we return an ObjectSchema.
*/
export declare function modelSchema<TModel extends ReturnType<typeof Model>, const TOmit extends readonly (keyof ModelFields<InstanceType<TModel>>)[] | undefined[] = undefined[], const TShow extends readonly (keyof ModelFields<InstanceType<TModel>>)[] | undefined[] = undefined[], TMany extends boolean = false, TFields extends Record<any, Schema<any, DefinitionsOfSchemaType>> | undefined = undefined, TAllModelFieldsRead = InferModel<InstanceType<TModel>, 'read'>, TAllModelFieldsCreate = InferModel<InstanceType<TModel>, 'create'>, TDefinitionsOfSchemaType extends DefinitionsOfSchemaType = DefinitionsOfSchemaType, TFieldsOnModelRead = TOmit extends undefined[] ? TShow extends undefined[] ? TAllModelFieldsRead : Pick<TAllModelFieldsRead, TShow[number] extends keyof TAllModelFieldsRead ? TShow[number] : never> : Omit<TAllModelFieldsRead, TOmit[number] extends keyof TAllModelFieldsRead ? TOmit[number] : never>, TFieldsOnModelCreateOrUpdate = TOmit extends undefined[] ? TShow extends undefined[] ? TAllModelFieldsCreate : Pick<TAllModelFieldsCreate, TShow[number] extends keyof TAllModelFieldsCreate ? TShow[number] : never> : Omit<TAllModelFieldsCreate, TOmit[number] extends keyof TAllModelFieldsCreate ? TOmit[number] : never>, TReturnType extends {
input: any;
output: any;
validate: any;
internal: any;
representation: any;
} = {
input: TFields extends undefined ? TFieldsOnModelCreateOrUpdate : Omit<TFieldsOnModelCreateOrUpdate, keyof ExtractTypeFromObjectOfSchemas<TFields extends undefined ? {} : TFields, 'input'>> & ExtractTypeFromObjectOfSchemas<TFields extends undefined ? {} : TFields, 'input'>;
output: TFields extends undefined ? TFieldsOnModelRead : Omit<TFieldsOnModelRead, keyof ExtractTypeFromObjectOfSchemas<TFields extends undefined ? {} : TFields, 'output'>> & ExtractTypeFromObjectOfSchemas<TFields extends undefined ? {} : TFields, 'output'>;
internal: TFields extends undefined ? TFieldsOnModelCreateOrUpdate : Omit<TFieldsOnModelCreateOrUpdate, keyof ExtractTypeFromObjectOfSchemas<TFields extends undefined ? {} : TFields, 'internal'>> & ExtractTypeFromObjectOfSchemas<TFields extends undefined ? {} : TFields, 'internal'>;
representation: TFields extends undefined ? TFieldsOnModelRead : Omit<TFieldsOnModelRead, keyof ExtractTypeFromObjectOfSchemas<TFields extends Record<any, Schema<any, DefinitionsOfSchemaType>> ? TFields : {}, 'representation'>> & ExtractTypeFromObjectOfSchemas<TFields extends Record<any, Schema<any, DefinitionsOfSchemaType>> ? TFields : {}, 'representation'>;
validate: TFields extends undefined ? TFieldsOnModelCreateOrUpdate : Omit<TFieldsOnModelCreateOrUpdate, keyof ExtractTypeFromObjectOfSchemas<TFields extends Record<any, Schema<any, DefinitionsOfSchemaType>> ? TFields : {}, 'validate'>> & ExtractTypeFromObjectOfSchemas<TFields extends Record<any, Schema<any, DefinitionsOfSchemaType>> ? TFields : {}, 'validate'>;
}>(model: TModel, options?: {
ignoreExtraneousFields?: boolean;
engineInstance?: string;
fields?: TFields;
omit?: TOmit;
show?: TShow;
omitRelation?: readonly (keyof TFields)[];
many?: TMany;
}): TMany extends true ? ArraySchema<{
input: TReturnType['input'][];
output: TReturnType['output'][];
internal: TReturnType['internal'][];
representation: TReturnType['representation'][];
validate: TReturnType['validate'][];
}, TDefinitionsOfSchemaType, [
ObjectSchema<{
input: TReturnType['input'];
output: TReturnType['output'];
internal: TReturnType['internal'];
representation: TReturnType['representation'];
validate: TReturnType['validate'];
}, TDefinitionsOfSchemaType, Record<any, any>>
]> : ObjectSchema<{
input: TReturnType['input'];
output: TReturnType['output'];
internal: TReturnType['internal'];
representation: TReturnType['representation'];
validate: TReturnType['validate'];
}, TDefinitionsOfSchemaType, Record<any, any>>;
//# sourceMappingURL=model.d.ts.map