import { JSONSchema } from '@sitecore/byoc' import { mergeDeep, assignDeep } from '../utils/object.js' import { Optional } from '../utils/typescript.js' import type { SDKModel, SDKModelSubclass } from './model.js' export interface SDKSchema { definitions?: Record properties: Partial<{ [key in keyof I]: any }> required?: (keyof I)[] type: 'object' | 'array' | 'null' | 'string' | 'number' | 'boolean' description: string } export type SDKSchemaType = T extends SDKModelSchema ? I : never export interface SDKModelSchema extends SDKSchema {} export class SDKModelSchema< M extends SDKModelSubclass, I = M extends (...args: any[]) => SDKModel ? I : never > { model: M constructor(model: M, schema: any) { Object.defineProperty(this, 'model', { value: model, enumerable: false }) if (schema.type != 'array') { this.required = [] this.properties = {} } assignDeep(this, schema) this.definitions = this.mergeDefinitions() } mergeDefinitions() { const definitions: Record = {} function traverseSchema(schema: any) { if (schema.definitions) { Object.assign(definitions, schema.definitions) } if (schema.type === 'object') { for (const key in schema.properties) { const property = schema.properties[key] if ( property.type === 'object' || (property.type === 'array' && property.items && property.items.type === 'object') ) { traverseSchema(property) } } } else if (schema.type === 'array' && schema.items && schema.items.type === 'object') { traverseSchema(schema.items) } } traverseSchema(this) return definitions } optional(props: Props) { return new SDKModelSchema>(this.model, { ...this, required: this.required.filter((prop) => !props.includes(prop)) }) } exclude(props: Props) { const result = this.optional(props) props.forEach((prop) => delete result.properties[prop]) return result } merge(props: Partial>) { return new SDKModelSchema(this.model, mergeDeep(this, props)) } addProperties>(properties: C) { return new SDKModelSchema< M, Omit & { properties: Partial<{ [key in keyof I & keyof C]: any }> } >( this.model, mergeDeep(this, { properties: properties }) ) } array() { return new SDKModelSchema(this.model, { type: 'array', items: this }) } generate(schema: any = this): any { if (schema.type === 'object') { const data: any = {} for (const key in schema.properties) { if (schema.properties[key].default !== undefined) { data[key] = schema.properties[key].default } else { data[key] = this.generate(schema.properties[key]) } } return data } else if (schema.type === 'array') { const data: any[] = [] const itemsSchema = schema.items const itemCount = Math.floor(Math.random() * 5) + 1 // Max 5 items for (let i = 0; i < itemCount; i++) { data.push(this.generate(itemsSchema)) } return data } else { // Handle other types such as string, number, boolean, etc. if (schema.example !== undefined) { return schema.example } switch (schema.type) { case 'string': function generateRandomString(length: number): string { const loremIpsum = `Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.` let generatedString = '' while (generatedString.length < length) { generatedString += loremIpsum.slice(0, length - generatedString.length) } return generatedString.slice(0, length) } if (schema.enum && schema.enum.length > 0) { return schema.enum[Math.floor(Math.random() * schema.enum.length)] } if (schema.default !== undefined) { return schema.default } if (schema.minLength !== undefined && schema.maxLength !== undefined) { const length = Math.floor(Math.random() * (schema.maxLength - schema.minLength + 1)) + schema.minLength return generateRandomString(length) } return generateRandomString(26) case 'number': if (schema.default !== undefined) { return schema.default } if (schema.minimum !== undefined && schema.maximum !== undefined) { return Math.random() * (schema.maximum - schema.minimum) + schema.minimum } return Math.random() * 100 case 'boolean': if (schema.default !== undefined) { return schema.default } return Math.random() > 0.5 case 'integer': if (schema.default !== undefined) { return schema.default } if (schema.minimum !== undefined && schema.maximum !== undefined) { return Math.floor(Math.random() * (schema.maximum - schema.minimum + 1)) + schema.minimum } return Math.floor(Math.random() * 100) case 'null': return null default: return null } } } }