{"version":3,"file":"openapi-Cz9TYzzn.mjs","names":[],"sources":["../src/api/rpc/openapi.ts"],"sourcesContent":["import { lowerCaseFirst, upperCaseFirst } from '@zenstackhq/common-helpers';\nimport { CoreCrudOperations, createQuerySchemaFactory, type ZodSchemaFactory } from '@zenstackhq/orm';\nimport type { BuiltinType, EnumDef, ModelDef, ProcedureDef, SchemaDef, TypeDefDef } from '@zenstackhq/orm/schema';\nimport type { OpenAPIV3_1 } from 'openapi-types';\nimport type { RPCApiHandlerOptions } from '.';\nimport { PROCEDURE_ROUTE_PREFIXES } from '../common/procedures';\nimport {\n    DEFAULT_SPEC_TITLE,\n    DEFAULT_SPEC_VERSION,\n    getIncludedModels,\n    getMetaDescription,\n    isModelIncluded,\n    isOperationIncluded,\n    isProcedureIncluded,\n    mayDenyAccess,\n} from '../common/spec-utils';\nimport type { OpenApiSpecOptions } from '../common/types';\n\ntype SchemaObject = OpenAPIV3_1.SchemaObject;\ntype ReferenceObject = OpenAPIV3_1.ReferenceObject;\n\n// Operations that use GET with args in ?q= query parameter\nconst GET_OPERATIONS = new Set<string>([\n    'findFirst',\n    'findUnique',\n    'findMany',\n    'aggregate',\n    'groupBy',\n    'count',\n    'exists',\n]);\n// Operations that use POST with request body (201 on success)\nconst POST_OPERATIONS = new Set<string>(['create', 'createMany', 'createManyAndReturn', 'upsert']);\n// Operations that use PUT with request body\nconst PUT_OPERATIONS = new Set<string>(['update', 'updateMany', 'updateManyAndReturn']);\n// Operations that use DELETE with args in ?q= query parameter\nconst DELETE_OPERATIONS = new Set<string>(['delete', 'deleteMany']);\n\nconst JSON_CT = 'application/json';\n\ntype OperationInfo = {\n    summary: (modelName: string) => string;\n    dataSchema: (entityRef: ReferenceObject) => SchemaObject | ReferenceObject;\n};\n\n/**\n * Per-operation metadata: human-readable summary and response data schema shape.\n * Operations absent from this map (aggregate, groupBy, count) return a generic schema.\n */\nconst OPERATION_INFO: Record<string, OperationInfo> = {\n    findUnique: {\n        summary: (m) => `Find a unique ${m}`,\n        dataSchema: (ref) => ({ anyOf: [ref, { type: 'null' }] }),\n    },\n    findFirst: {\n        summary: (m) => `Find the first ${m}`,\n        dataSchema: (ref) => ({ anyOf: [ref, { type: 'null' }] }),\n    },\n    findMany: {\n        summary: (m) => `List ${m} entities`,\n        dataSchema: (ref) => ({ type: 'array', items: ref }),\n    },\n    create: {\n        summary: (m) => `Create a ${m}`,\n        dataSchema: (ref) => ref,\n    },\n    createMany: {\n        summary: (m) => `Create multiple ${m} entities`,\n        dataSchema: () => ({ type: 'object', properties: { count: { type: 'integer' } }, required: ['count'] }),\n    },\n    createManyAndReturn: {\n        summary: (m) => `Create multiple ${m}s and return them`,\n        dataSchema: (ref) => ({ type: 'array', items: ref }),\n    },\n    update: {\n        summary: (m) => `Update a ${m}`,\n        dataSchema: (ref) => ref,\n    },\n    updateMany: {\n        summary: (m) => `Update multiple ${m} entities`,\n        dataSchema: () => ({ type: 'object', properties: { count: { type: 'integer' } }, required: ['count'] }),\n    },\n    updateManyAndReturn: {\n        summary: (m) => `Update multiple ${m} entities and return them`,\n        dataSchema: (ref) => ({ type: 'array', items: ref }),\n    },\n    upsert: {\n        summary: (m) => `Upsert a ${m}`,\n        dataSchema: (ref) => ref,\n    },\n    delete: {\n        summary: (m) => `Delete a ${m}`,\n        dataSchema: (ref) => ref,\n    },\n    deleteMany: {\n        summary: (m) => `Delete multiple ${m} entities`,\n        dataSchema: () => ({ type: 'object', properties: { count: { type: 'integer' } }, required: ['count'] }),\n    },\n    exists: {\n        summary: (m) => `Check ${m} existence`,\n        dataSchema: () => ({ type: 'boolean' }),\n    },\n};\n\nfunction errorResponse(description: string): OpenAPIV3_1.ResponseObject {\n    return {\n        description,\n        content: {\n            [JSON_CT]: {\n                schema: { $ref: '#/components/schemas/_rpcErrorResponse' },\n            },\n        },\n    };\n}\n\nconst ERROR_400 = errorResponse('Error occurred while processing the request');\nconst ERROR_403 = errorResponse('Forbidden: insufficient permissions to perform this operation');\nconst ERROR_404 = errorResponse('Resource not found');\nconst ERROR_422 = errorResponse('Operation is unprocessable due to validation errors');\nconst ERROR_500 = errorResponse('Internal server error');\n\n// Operations that may throw NOT_FOUND when the target record does not exist\nconst NOT_FOUND_OPERATIONS = new Set<string>(['update', 'delete']);\n\n/**\n * Generates an OpenAPI v3.1 specification for the RPC-style API handler.\n */\nexport class RPCApiSpecGenerator<Schema extends SchemaDef = SchemaDef> {\n    private specOptions?: OpenApiSpecOptions;\n    private readonly factory: ZodSchemaFactory<Schema>;\n    /**\n     * Schemas extracted from the Zod registry, keyed by their registered ID, with\n     * all `$ref` values already rewritten to `#/components/schemas/<id>`.\n     */\n    private registrySchemas: Record<string, SchemaObject> = {};\n\n    constructor(private readonly handlerOptions: RPCApiHandlerOptions<Schema>) {\n        this.factory = createQuerySchemaFactory(handlerOptions.schema, handlerOptions.queryOptions);\n    }\n\n    private get schema(): SchemaDef {\n        return this.handlerOptions.schema;\n    }\n\n    private get queryOptions() {\n        return this.handlerOptions?.queryOptions;\n    }\n\n    generateSpec(options?: OpenApiSpecOptions): OpenAPIV3_1.Document {\n        this.specOptions = options;\n\n        // Build all model/procedure schemas eagerly and capture the full registry as\n        // JSON Schema, then transform bare-ID $refs to OpenAPI component paths.\n        const rawRegistry = this.factory.toJSONSchema();\n        this.registrySchemas = this.transformRegistrySchemas(rawRegistry.schemas);\n\n        return {\n            openapi: '3.1.0',\n            info: {\n                title: options?.title ?? DEFAULT_SPEC_TITLE,\n                version: options?.version ?? DEFAULT_SPEC_VERSION,\n                ...(options?.description && { description: options.description }),\n                ...(options?.summary && { summary: options.summary }),\n            },\n            tags: this.generateTags(),\n            paths: this.generatePaths(),\n            components: {\n                schemas: {\n                    ...this.registrySchemas,\n                    ...this.generateSharedSchemas(),\n                },\n            },\n        } as OpenAPIV3_1.Document;\n    }\n\n    /**\n     * Takes the raw `schemas` map from `z.toJSONSchema(registry)` and:\n     *  1. Rewrites bare-ID `$ref` values (e.g. `\"UserWhereInput\"`) to full\n     *     component paths (`\"#/components/schemas/UserWhereInput\"`).\n     *  2. Strips the `$schema` keyword from each top-level schema object, as it\n     *     is redundant inside an OpenAPI document.\n     *  3. Resolves Zod's auto-generated `__shared/$defs/schemaN` aliases.\n     *     When a `__shared/$defs/schemaN` entry is itself a plain `$ref` to a\n     *     named schema, every reference to it is rewritten to point directly at\n     *     the target schema, removing the double indirection. Any remaining\n     *     `__shared` entries (complex shared sub-schemas) are promoted to\n     *     top-level component schemas with stable names.\n     */\n    private transformRegistrySchemas(schemas: Record<string, unknown>): Record<string, SchemaObject> {\n        let result: Record<string, SchemaObject>;\n\n        // Step 1: rewrite bare-ID refs to full component paths, and replace repeated\n        // inline integer bound schemas with $refs to shared named schemas.\n        // Bare-ID refs produced by the Zod registry look like `\"$ref\":\"SomeName\"`.\n        // __shared cross-refs look like `\"$ref\":\"__shared#/$defs/schemaN\"` and are\n        // also rewritten here.\n        const INT_PATTERN = '{\"type\":\"integer\",\"minimum\":-9007199254740991,\"maximum\":9007199254740991}';\n        const NON_NEG_INT_PATTERN = '{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991}';\n        const serialized = JSON.stringify(schemas)\n            .replace(/\"(\\$ref)\":\"([^\"#][^\"]*)\"/g, (_, key, id) => `\"${key}\":\"#/components/schemas/${id}\"`)\n            .replaceAll(NON_NEG_INT_PATTERN, '{\"$ref\":\"#/components/schemas/_nonNegativeInteger\"}')\n            .replaceAll(INT_PATTERN, '{\"$ref\":\"#/components/schemas/_integer\"}');\n        result = JSON.parse(serialized) as Record<string, SchemaObject>;\n\n        // Step 2: resolve __shared/$defs aliases produced by Zod's deduplication\n        // of circular-reference lazy schemas.\n        const shared = result['__shared'] as { $defs?: Record<string, SchemaObject> } | undefined;\n        if (shared?.$defs) {\n            // Build a substitution map: __shared ref → direct target ref (for pure aliases)\n            // and collect complex entries that need promotion to top-level.\n            const refMap: Record<string, string> = {};\n            const promoted: Record<string, SchemaObject> = {};\n\n            for (const [key, entry] of Object.entries(shared.$defs)) {\n                const sharedRef = `#/components/schemas/__shared#/$defs/${key}`;\n                if (entry && typeof entry === 'object' && '$ref' in entry && Object.keys(entry).length === 1) {\n                    // Pure alias — map it straight to the target.\n                    refMap[sharedRef] = entry.$ref as string;\n                } else {\n                    // Complex sub-schema — promote to a top-level named schema.\n                    const promotedName = `_shared_${key}`;\n                    promoted[promotedName] = entry;\n                    refMap[sharedRef] = `#/components/schemas/${promotedName}`;\n                }\n            }\n\n            if (Object.keys(refMap).length > 0) {\n                // Replace all __shared refs in a single JSON round-trip.\n                const escapedKeys = Object.keys(refMap).map((k) => k.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'));\n                const pattern = new RegExp(`\"\\\\$ref\":\"(${escapedKeys.join('|')})\"`, 'g');\n                const resolved = JSON.stringify(result).replace(pattern, (_, ref) => `\"$ref\":\"${refMap[ref]}\"`);\n                result = JSON.parse(resolved) as Record<string, SchemaObject>;\n\n                // Remove __shared and add any promoted complex schemas.\n                delete result['__shared'];\n                Object.assign(result, promoted);\n            }\n        }\n\n        // Step 3: remove the $schema dialect keyword from each top-level entry.\n        for (const s of Object.values(result)) {\n            if (s && typeof s === 'object') {\n                delete (s as Record<string, unknown>)['$schema'];\n            }\n        }\n\n        return result;\n    }\n\n    private generateTags(): OpenAPIV3_1.TagObject[] {\n        return getIncludedModels(this.schema, this.queryOptions).map((modelName) => ({\n            name: lowerCaseFirst(modelName),\n            description: `${modelName} operations`,\n        }));\n    }\n\n    private generatePaths(): OpenAPIV3_1.PathsObject {\n        const paths: OpenAPIV3_1.PathsObject = {};\n\n        for (const modelName of getIncludedModels(this.schema, this.queryOptions)) {\n            const modelDef = this.schema.models[modelName]!;\n            const tag = lowerCaseFirst(modelName);\n\n            for (const op of CoreCrudOperations) {\n                if (!isOperationIncluded(modelName, op, this.queryOptions)) continue;\n                const method = this.getHttpMethod(op);\n                const operation = this.buildModelOperation(modelName, modelDef, op, tag);\n                paths[`/${lowerCaseFirst(modelName)}/${op}`] = {\n                    [method]: operation,\n                } as OpenAPIV3_1.PathItemObject;\n            }\n        }\n\n        // Procedure paths\n        if (this.schema.procedures) {\n            for (const [procName, procDef] of Object.entries(this.schema.procedures)) {\n                if (!isProcedureIncluded(procName, this.queryOptions)) continue;\n                const method = procDef.mutation ? 'post' : 'get';\n                paths[`/${PROCEDURE_ROUTE_PREFIXES}/${procName}`] = {\n                    [method]: this.buildProcedureOperation(procName, procDef, method),\n                } as OpenAPIV3_1.PathItemObject;\n            }\n        }\n\n        // Sequential transaction endpoint\n        paths['/$transaction/sequential'] = {\n            post: this.buildTransactionOperation(),\n        } as OpenAPIV3_1.PathItemObject;\n\n        return paths;\n    }\n\n    private getHttpMethod(op: string): string {\n        if (GET_OPERATIONS.has(op)) return 'get';\n        if (POST_OPERATIONS.has(op)) return 'post';\n        if (PUT_OPERATIONS.has(op)) return 'put';\n        if (DELETE_OPERATIONS.has(op)) return 'delete';\n        return 'post';\n    }\n\n    /**\n     * Returns a JSON Schema `$ref` pointing to the pre-built component schema for\n     * the given model+operation, or `undefined` if the schema was not registered\n     * (e.g. the operation is not supported for that model).\n     */\n    private getOperationInputSchemaRef(modelName: string, op: string): ReferenceObject | undefined {\n        const id = `${modelName}${upperCaseFirst(op)}Args`;\n        return id in this.registrySchemas ? { $ref: `#/components/schemas/${id}` } : undefined;\n    }\n\n    /**\n     * Maps an RPC operation name to its corresponding access policy operation type.\n     * Policy attributes use 'read', 'create', 'update', 'delete', 'all'.\n     */\n    private policyOp(op: string): string {\n        if (GET_OPERATIONS.has(op)) return 'read';\n        if (DELETE_OPERATIONS.has(op)) return 'delete';\n        if (PUT_OPERATIONS.has(op)) return 'update';\n        // create/createMany/createManyAndReturn/upsert → 'create'\n        return 'create';\n    }\n\n    private buildModelOperation(\n        modelName: string,\n        modelDef: ModelDef,\n        op: string,\n        tag: string,\n    ): Record<string, unknown> {\n        const isQueryOp = GET_OPERATIONS.has(op) || DELETE_OPERATIONS.has(op);\n        const successCode = POST_OPERATIONS.has(op) ? '201' : '200';\n        const inputSchemaRef = this.getOperationInputSchemaRef(modelName, op);\n\n        const operation: Record<string, unknown> = {\n            tags: [tag],\n            summary: OPERATION_INFO[op]?.summary(modelName) ?? `${modelName}.${op}`,\n            operationId: `${lowerCaseFirst(modelName)}_${op}`,\n            responses: {\n                [successCode]: {\n                    description: 'Operation succeeded',\n                    content: {\n                        [JSON_CT]: {\n                            schema: this.buildOperationSuccessSchema(modelName, op),\n                        },\n                    },\n                },\n                '400': ERROR_400,\n                ...(NOT_FOUND_OPERATIONS.has(op) && { '404': ERROR_404 }),\n                '422': ERROR_422,\n                '500': ERROR_500,\n                ...(mayDenyAccess(modelDef, this.policyOp(op), this.specOptions?.respectAccessPolicies) && {\n                    '403': ERROR_403,\n                }),\n            },\n        };\n\n        if (inputSchemaRef) {\n            if (isQueryOp) {\n                // `q` is required when the input schema has required fields (e.g. `where` for delete/findUnique).\n                // OAPI 3.1 supports content-typed parameters for structured query values.\n                // `meta` is an optional companion to `q` used to carry SuperJSON serialization\n                // metadata (see unmarshalQ in api/common/utils.ts).\n                const inputSchemaId = `${modelName}${upperCaseFirst(op)}Args`;\n                const inputSchema = this.registrySchemas[inputSchemaId];\n                const qRequired = Array.isArray(inputSchema?.required) && inputSchema.required.length > 0;\n                operation['parameters'] = [\n                    {\n                        name: 'q',\n                        in: 'query',\n                        ...(qRequired && { required: true }),\n                        description: `JSON-encoded arguments for ${modelName}.${op}`,\n                        content: {\n                            [JSON_CT]: { schema: inputSchemaRef },\n                        },\n                    },\n                    {\n                        name: 'meta',\n                        in: 'query',\n                        description: 'JSON-encoded SuperJSON serialization metadata for the \"q\" parameter',\n                        schema: { type: 'string' },\n                    },\n                ];\n            } else {\n                operation['requestBody'] = {\n                    required: true,\n                    content: {\n                        [JSON_CT]: { schema: inputSchemaRef },\n                    },\n                };\n            }\n        }\n\n        return operation;\n    }\n\n    private buildProcedureOperation(\n        procName: string,\n        procDef: ProcedureDef,\n        method: 'get' | 'post',\n    ): Record<string, unknown> {\n        const argsSchemaId = `${procName}ProcArgs`;\n        const argsSchemaRef: ReferenceObject | SchemaObject =\n            argsSchemaId in this.registrySchemas\n                ? { $ref: `#/components/schemas/${argsSchemaId}` }\n                : { type: 'object' };\n\n        // The RPC handler accepts { args: { param1: val, ... } } envelope.\n        // `args` is required when the procedure has at least one non-optional parameter\n        // (mapProcedureArgs throws 'missing procedure arguments' otherwise).\n        const hasRequiredParams = Object.values(procDef.params ?? {}).some((p) => !p.optional);\n        const envelopeSchema: SchemaObject = {\n            type: 'object',\n            properties: { args: argsSchemaRef },\n            ...(hasRequiredParams && { required: ['args'] }),\n        };\n\n        const op: Record<string, unknown> = {\n            tags: ['$procs'],\n            summary: `Execute procedure \\`${procName}\\``,\n            operationId: `proc_${procName}`,\n            responses: {\n                '200': {\n                    description: `Result of ${procName}`,\n                    content: {\n                        [JSON_CT]: {\n                            schema: {\n                                type: 'object',\n                                properties: {\n                                    data: this.getProcedureDataSchema(procDef),\n                                    meta: {\n                                        type: 'object',\n                                        properties: {\n                                            serialization: {},\n                                        },\n                                    },\n                                },\n                            },\n                        },\n                    },\n                },\n                '400': ERROR_400,\n                '403': ERROR_403,\n                '404': ERROR_404,\n                '422': ERROR_422,\n                '500': ERROR_500,\n            },\n        };\n\n        const hasParams = Object.keys(procDef.params ?? {}).length > 0;\n        if (method === 'get') {\n            if (hasParams) {\n                op['parameters'] = [\n                    {\n                        name: 'q',\n                        in: 'query',\n                        ...(hasRequiredParams && { required: true }),\n                        description: `JSON-encoded arguments for procedure ${procName}`,\n                        content: {\n                            [JSON_CT]: { schema: envelopeSchema },\n                        },\n                    },\n                    {\n                        name: 'meta',\n                        in: 'query',\n                        description: 'JSON-encoded SuperJSON serialization metadata for the \"q\" parameter',\n                        schema: { type: 'string' },\n                    },\n                ];\n            }\n        } else {\n            if (hasParams) {\n                op['requestBody'] = {\n                    ...(hasRequiredParams && { required: true }),\n                    content: {\n                        [JSON_CT]: { schema: envelopeSchema },\n                    },\n                };\n            }\n        }\n\n        return op;\n    }\n\n    private getProcedureDataSchema(procDef: ProcedureDef): SchemaObject | ReferenceObject {\n        const { returnType, returnArray } = procDef;\n        let base: SchemaObject | ReferenceObject;\n\n        if (this.isBuiltinType(returnType)) {\n            base = this.builtinTypeToJsonSchema(returnType as BuiltinType);\n        } else if (this.schema.models?.[returnType] && !isModelIncluded(returnType, this.queryOptions)) {\n            // Return type is a model that's sliced away — its entity schema isn't emitted,\n            // so reference it with a generic schema instead of a dangling `$ref`.\n            base = {};\n        } else if (\n            this.schema.enums?.[returnType] ||\n            this.schema.models?.[returnType] ||\n            this.schema.typeDefs?.[returnType]\n        ) {\n            base = { $ref: `#/components/schemas/${returnType}` };\n        } else {\n            base = {};\n        }\n\n        return returnArray ? { type: 'array', items: base } : base;\n    }\n\n    private buildTransactionOperation(): Record<string, unknown> {\n        return {\n            tags: ['$transaction'],\n            summary: 'Execute a sequential transaction',\n            operationId: 'transaction_sequential',\n            requestBody: {\n                required: true,\n                content: {\n                    [JSON_CT]: {\n                        schema: { $ref: '#/components/schemas/_rpcTransactionRequest' },\n                    },\n                },\n            },\n            responses: {\n                '200': {\n                    description: 'Transaction succeeded',\n                    content: {\n                        [JSON_CT]: {\n                            schema: { $ref: '#/components/schemas/_rpcSuccessResponse' },\n                        },\n                    },\n                },\n                '400': ERROR_400,\n                '403': ERROR_403,\n                '404': ERROR_404,\n                '422': ERROR_422,\n                '500': ERROR_500,\n            },\n        };\n    }\n\n    private generateSharedSchemas(): Record<string, SchemaObject> {\n        // Generate schemas for enums\n        const enumSchemas: Record<string, SchemaObject> = {};\n        for (const [enumName, enumDef] of Object.entries(this.schema.enums ?? {})) {\n            enumSchemas[enumName] = this.buildEnumSchema(enumDef);\n        }\n\n        // Generate schemas for typedefs (e.g. `type Address { city String }`)\n        const typeDefSchemas: Record<string, SchemaObject> = {};\n        for (const [typeName, typeDef] of Object.entries(this.schema.typeDefs ?? {})) {\n            typeDefSchemas[typeName] = this.buildTypeDefSchema(typeDef);\n        }\n\n        // Generate a response-side entity schema for every included model\n        const modelEntitySchemas: Record<string, SchemaObject> = {};\n        for (const modelName of getIncludedModels(this.schema as SchemaDef, this.queryOptions)) {\n            modelEntitySchemas[modelName] = this.buildModelEntitySchema(this.schema.models[modelName]!);\n        }\n\n        return {\n            ...enumSchemas,\n            ...typeDefSchemas,\n            ...modelEntitySchemas,\n            _integer: { type: 'integer', minimum: -9007199254740991, maximum: 9007199254740991 },\n            _nonNegativeInteger: { type: 'integer', minimum: 0, maximum: 9007199254740991 },\n            _rpcSuccessResponse: {\n                type: 'object',\n                properties: {\n                    data: {},\n                    meta: {\n                        type: 'object',\n                        properties: {\n                            serialization: {},\n                        },\n                    },\n                },\n            },\n            _rpcErrorResponse: {\n                type: 'object',\n                properties: {\n                    error: {\n                        type: 'object',\n                        properties: {\n                            message: { type: 'string' },\n                            reason: { type: 'string' },\n                            model: { type: 'string' },\n                            rejectedByPolicy: { type: 'boolean' },\n                            rejectedByValidation: { type: 'boolean' },\n                            rejectReason: { type: 'string' },\n                            dbErrorCode: { type: 'string' },\n                        },\n                        required: ['message'],\n                    },\n                },\n                required: ['error'],\n            },\n            _rpcTransactionRequest: {\n                type: 'array',\n                items: {\n                    type: 'object',\n                    properties: {\n                        model: { type: 'string' },\n                        op: {\n                            type: 'string',\n                            enum: [...CoreCrudOperations],\n                        },\n                        args: { type: 'object' },\n                    },\n                    required: ['model', 'op'],\n                },\n            },\n        };\n    }\n\n    private builtinTypeToJsonSchema(type: BuiltinType): SchemaObject {\n        switch (type) {\n            case 'String':\n                return { type: 'string' };\n            case 'Boolean':\n                return { type: 'boolean' };\n            case 'Int':\n                return { type: 'integer' };\n            case 'Float':\n                return { type: 'number' };\n            case 'BigInt':\n                return { type: 'integer' };\n            case 'Decimal':\n                return { type: 'string' };\n            case 'DateTime':\n                return { type: 'string', format: 'date-time' };\n            case 'Bytes':\n                return { type: 'string', format: 'byte' };\n            default:\n                // Json, Unsupported\n                return {};\n        }\n    }\n\n    private isBuiltinType(type: string): boolean {\n        return [\n            'String',\n            'Boolean',\n            'Int',\n            'Float',\n            'BigInt',\n            'Decimal',\n            'DateTime',\n            'Bytes',\n            'Json',\n            'Unsupported',\n        ].includes(type);\n    }\n\n    /**\n     * Builds a JSON Schema object describing a custom typedef\n     */\n    private buildEnumSchema(enumDef: EnumDef): SchemaObject {\n        return { type: 'string', enum: Object.values(enumDef.values) };\n    }\n\n    private buildTypeDefSchema(typeDef: TypeDefDef): SchemaObject {\n        const properties: Record<string, SchemaObject | ReferenceObject> = {};\n        const required: string[] = [];\n        for (const [fieldName, fieldDef] of Object.entries(typeDef.fields)) {\n            const isRef =\n                !this.isBuiltinType(fieldDef.type) &&\n                (this.schema.enums?.[fieldDef.type] || this.schema.typeDefs?.[fieldDef.type]);\n            const base: SchemaObject | ReferenceObject = this.isBuiltinType(fieldDef.type)\n                ? this.builtinTypeToJsonSchema(fieldDef.type as BuiltinType)\n                : isRef\n                  ? { $ref: `#/components/schemas/${fieldDef.type}` }\n                  : { type: 'object' as const };\n            const fieldDesc = getMetaDescription(fieldDef.attributes);\n            if (fieldDesc && !isRef) {\n                (base as SchemaObject).description = fieldDesc;\n            }\n            const typed: SchemaObject | ReferenceObject = fieldDef.array ? { type: 'array', items: base } : base;\n            properties[fieldName] = fieldDef.optional ? { anyOf: [typed, { type: 'null' }] } : typed;\n            if (!fieldDef.optional) required.push(fieldName);\n        }\n        const schema: SchemaObject = { type: 'object', properties };\n        if (required.length > 0) schema['required'] = required;\n        return schema;\n    }\n\n    /**\n     * Builds a JSON Schema object describing a model entity\n     */\n    private buildModelEntitySchema(modelDef: ModelDef): SchemaObject {\n        const properties: Record<string, SchemaObject | ReferenceObject> = {};\n        const required: string[] = [];\n\n        for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) {\n            if (fieldDef.omit) continue;\n\n            if (fieldDef.relation) {\n                // Skip relations pointing to a model that's sliced away — otherwise we'd emit\n                // a dangling `$ref` to a schema that's not in the spec.\n                if (!isModelIncluded(fieldDef.type, this.queryOptions)) continue;\n\n                // Relation fields appear only with `include` — mark as optional.\n                // To-one optional relations are nullable (the ORM returns null when not found).\n                const refSchema: ReferenceObject = { $ref: `#/components/schemas/${fieldDef.type}` };\n                const base: SchemaObject | ReferenceObject = fieldDef.array\n                    ? { type: 'array', items: refSchema }\n                    : refSchema;\n                properties[fieldName] =\n                    !fieldDef.array && fieldDef.optional ? { anyOf: [base, { type: 'null' }] } : base;\n            } else if (this.schema.enums?.[fieldDef.type]) {\n                // Enum field\n                const refSchema: ReferenceObject = { $ref: `#/components/schemas/${fieldDef.type}` };\n                const base: SchemaObject | ReferenceObject = fieldDef.array\n                    ? { type: 'array', items: refSchema }\n                    : refSchema;\n                properties[fieldName] = fieldDef.optional ? { anyOf: [base, { type: 'null' }] } : base;\n                required.push(fieldName);\n            } else if (this.isBuiltinType(fieldDef.type)) {\n                // Scalar builtin field\n                const base = this.builtinTypeToJsonSchema(fieldDef.type as BuiltinType);\n                const fieldDesc = getMetaDescription(fieldDef.attributes);\n                if (fieldDesc) base.description = fieldDesc;\n                const typed: SchemaObject = fieldDef.array ? { type: 'array', items: base } : base;\n                properties[fieldName] = fieldDef.optional ? { anyOf: [typed, { type: 'null' }] } : typed;\n                required.push(fieldName);\n            } else if (this.schema.typeDefs?.[fieldDef.type]) {\n                // TypeDef field — reference the registered typedef schema\n                const refSchema: ReferenceObject = { $ref: `#/components/schemas/${fieldDef.type}` };\n                const base: SchemaObject | ReferenceObject = fieldDef.array\n                    ? { type: 'array', items: refSchema }\n                    : refSchema;\n                properties[fieldName] = fieldDef.optional ? { anyOf: [base, { type: 'null' }] } : base;\n                required.push(fieldName);\n            } else {\n                // Unknown type — represent as a generic object\n                const typed: SchemaObject = fieldDef.array\n                    ? { type: 'array', items: { type: 'object' } }\n                    : { type: 'object' };\n                properties[fieldName] = typed;\n                required.push(fieldName);\n            }\n        }\n\n        const schema: SchemaObject = { type: 'object', properties };\n        if (required.length > 0) {\n            schema['required'] = required;\n        }\n        const modelDesc = getMetaDescription(modelDef.attributes);\n        if (modelDesc) schema.description = modelDesc;\n        return schema;\n    }\n\n    private buildOperationSuccessSchema(modelName: string, op: string): SchemaObject {\n        const entityRef: ReferenceObject = { $ref: `#/components/schemas/${modelName}` };\n        // aggregate, groupBy, count shapes depend on query args — leave generic ({})\n        const dataSchema = OPERATION_INFO[op]?.dataSchema(entityRef) ?? {};\n        return {\n            type: 'object',\n            properties: {\n                data: dataSchema,\n                meta: {\n                    type: 'object',\n                    properties: {\n                        serialization: {},\n                    },\n                },\n            },\n        };\n    }\n}\n"],"mappings":"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"}