{"version":3,"file":"api.mjs","names":[],"sources":["../src/api/common/schemas.ts","../src/api/common/utils.ts","../src/api/rest/openapi.ts","../src/api/rest/index.ts","../src/api/rpc/index.ts"],"sourcesContent":["import z from 'zod';\n\nexport const loggerSchema = z.union([z.enum(['debug', 'info', 'warn', 'error']).array(), z.function()]);\n\nconst fieldSlicingSchema = z.looseObject({\n    includedFilterKinds: z.string().array().optional(),\n    excludedFilterKinds: z.string().array().optional(),\n});\n\nconst modelSlicingSchema = z.looseObject({\n    includedOperations: z.array(z.string()).optional(),\n    excludedOperations: z.array(z.string()).optional(),\n    fields: z.record(z.string(), fieldSlicingSchema).optional(),\n});\n\nconst slicingSchema = z.looseObject({\n    includedModels: z.array(z.string()).optional(),\n    excludedModels: z.array(z.string()).optional(),\n    models: z.record(z.string(), modelSlicingSchema).optional(),\n    includedProcedures: z.array(z.string()).optional(),\n    excludedProcedures: z.array(z.string()).optional(),\n});\n\nexport const queryOptionsSchema = z.looseObject({\n    omit: z.record(z.string(), z.record(z.string(), z.boolean())).optional(),\n    slicing: slicingSchema.optional(),\n});\n","import SuperJSON from 'superjson';\n\n/**\n * Supports the SuperJSON request payload format used by api handlers\n * `{ meta: { serialization }, ...json }`.\n */\nexport async function processSuperJsonRequestPayload(payload: unknown) : Promise<{ result: unknown; error: string | undefined; }> {\n    if (!payload || typeof payload !== 'object' || Array.isArray(payload) || !('meta' in (payload as any))) {\n        return { result: payload, error: undefined };\n    }\n\n    const { meta, ...rest } = payload as any;\n    if (meta?.serialization) {\n        try {\n            return {\n                result: SuperJSON.deserialize({ json: rest, meta: meta.serialization }),\n                error: undefined,\n            };\n        } catch (err) {\n            return {\n                result: undefined,\n                error: `failed to deserialize request payload: ${(err as Error).message}`,\n            };\n        }\n    }\n\n    // drop meta when no serialization info is present\n    return { result: rest, error: undefined };\n}\n\n/**\n * Supports the SuperJSON query format used by api handlers:\n */\nexport function unmarshalQ(value: string, meta: string | undefined) {\n    let parsedValue: any;\n    try {\n        parsedValue = JSON.parse(value);\n    } catch {\n        throw new Error('invalid \"q\" query parameter');\n    }\n\n    if (meta) {\n        let parsedMeta: any;\n        try {\n            parsedMeta = JSON.parse(meta);\n        } catch {\n            throw new Error('invalid \"meta\" query parameter');\n        }\n\n        if (parsedMeta.serialization) {\n            return SuperJSON.deserialize({ json: parsedValue, meta: parsedMeta.serialization });\n        }\n    }\n\n    return parsedValue;\n}","import { lowerCaseFirst } from '@zenstackhq/common-helpers';\nimport type { EnumDef, FieldDef, ModelDef, SchemaDef, TypeDefDef } from '@zenstackhq/orm/schema';\nimport type { OpenAPIV3_1 } from 'openapi-types';\nimport { PROCEDURE_ROUTE_PREFIXES } from '../common/procedures';\nimport {\n    DEFAULT_SPEC_TITLE,\n    DEFAULT_SPEC_VERSION,\n    getIncludedModels,\n    getMetaDescription,\n    isFieldOmitted,\n    isFilterKindIncluded,\n    isModelIncluded,\n    isOperationIncluded,\n    isProcedureIncluded,\n    mayDenyAccess,\n} from '../common/spec-utils';\nimport type { OpenApiSpecOptions } from '../common/types';\nimport type { RestApiHandlerOptions } from '.';\n\ntype SchemaObject = OpenAPIV3_1.SchemaObject;\ntype ReferenceObject = OpenAPIV3_1.ReferenceObject;\ntype ParameterObject = OpenAPIV3_1.ParameterObject;\n\nfunction errorResponse(description: string): OpenAPIV3_1.ResponseObject {\n    return {\n        description,\n        content: {\n            'application/vnd.api+json': {\n                schema: { $ref: '#/components/schemas/_errorResponse' },\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');\n\nconst SCALAR_STRING_OPS = ['$contains', '$icontains', '$search', '$startsWith', '$endsWith'];\nconst SCALAR_COMPARABLE_OPS = ['$lt', '$lte', '$gt', '$gte'];\nconst SCALAR_ARRAY_OPS = ['$has', '$hasEvery', '$hasSome', '$isEmpty'];\n\nexport class RestApiSpecGenerator<Schema extends SchemaDef = SchemaDef> {\n    private specOptions?: OpenApiSpecOptions;\n\n    constructor(private readonly handlerOptions: RestApiHandlerOptions<Schema>) {}\n\n    private get schema(): SchemaDef {\n        return this.handlerOptions.schema;\n    }\n\n    private get modelNameMapping(): Record<string, string> {\n        const mapping: Record<string, string> = {};\n        if (this.handlerOptions.modelNameMapping) {\n            for (const [k, v] of Object.entries(this.handlerOptions.modelNameMapping)) {\n                mapping[lowerCaseFirst(k)] = v;\n            }\n        }\n        return mapping;\n    }\n\n    private get queryOptions() {\n        return this.handlerOptions?.queryOptions;\n    }\n\n    private get nestedRoutes(): boolean {\n        return this.handlerOptions.nestedRoutes ?? false;\n    }\n\n    generateSpec(options?: OpenApiSpecOptions): OpenAPIV3_1.Document {\n        this.specOptions = options;\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: this.generateSchemas(),\n                parameters: this.generateSharedParams(),\n            },\n        } as OpenAPIV3_1.Document;\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 getModelPath(modelName: string): string {\n        const lower = lowerCaseFirst(modelName);\n        return this.modelNameMapping[lower] ?? lower;\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 idFields = this.getIdFields(modelDef);\n            if (idFields.length === 0) continue;\n\n            const modelPath = this.getModelPath(modelName);\n            const tag = lowerCaseFirst(modelName);\n\n            // Collection: GET (list) + POST (create)\n            const collectionPath = this.buildCollectionPath(modelName, modelDef, tag);\n            if (Object.keys(collectionPath).length > 0) {\n                paths[`/${modelPath}`] = collectionPath;\n            }\n\n            // Single resource: GET + PATCH + DELETE\n            const singlePath = this.buildSinglePath(modelDef, tag);\n            if (Object.keys(singlePath).length > 0) {\n                paths[`/${modelPath}/{id}`] = singlePath;\n            }\n\n            // Relation paths\n            for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) {\n                if (!fieldDef.relation) continue;\n                if (!isModelIncluded(fieldDef.type, this.queryOptions)) continue;\n                const relModelDef = this.schema.models[fieldDef.type];\n                if (!relModelDef) continue;\n                const relIdFields = this.getIdFields(relModelDef);\n                if (relIdFields.length === 0) continue;\n\n                // GET /{model}/{id}/{field} — fetch related (+ nested create/update when nestedRoutes enabled)\n                paths[`/${modelPath}/{id}/${fieldName}`] = this.buildRelatedPath(\n                    modelName,\n                    fieldName,\n                    fieldDef,\n                    tag,\n                );\n\n                // Nested single resource path: /{model}/{id}/{field}/{childId}\n                if (this.nestedRoutes && fieldDef.array) {\n                    const nestedSinglePath = this.buildNestedSinglePath(\n                        modelName,\n                        fieldName,\n                        fieldDef,\n                        relModelDef,\n                        tag,\n                    );\n                    if (Object.keys(nestedSinglePath).length > 0) {\n                        paths[`/${modelPath}/{id}/${fieldName}/{childId}`] = nestedSinglePath;\n                    }\n                }\n\n                // Relationship management path\n                paths[`/${modelPath}/{id}/relationships/${fieldName}`] = this.buildRelationshipPath(\n                    modelDef,\n                    fieldName,\n                    fieldDef,\n                    tag,\n                );\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 isMutation = !!procDef.mutation;\n                if (isMutation) {\n                    paths[`/${PROCEDURE_ROUTE_PREFIXES}/${procName}`] = {\n                        post: this.buildProcedureOperation(procName, 'post'),\n                    } as OpenAPIV3_1.PathItemObject;\n                } else {\n                    paths[`/${PROCEDURE_ROUTE_PREFIXES}/${procName}`] = {\n                        get: this.buildProcedureOperation(procName, 'get'),\n                    } as OpenAPIV3_1.PathItemObject;\n                }\n            }\n        }\n\n        return paths;\n    }\n\n    private buildCollectionPath(modelName: string, modelDef: ModelDef, tag: string): Record<string, any> {\n        const filterParams = this.buildFilterParams(modelName, modelDef);\n\n        const listOp = {\n            tags: [tag],\n            summary: `List ${modelName} resources`,\n            operationId: `list${modelName}`,\n            parameters: [\n                { $ref: '#/components/parameters/include' },\n                { $ref: '#/components/parameters/sort' },\n                { $ref: '#/components/parameters/pageOffset' },\n                { $ref: '#/components/parameters/pageLimit' },\n                ...filterParams,\n            ],\n            responses: {\n                '200': {\n                    description: `List of ${modelName} resources`,\n                    content: {\n                        'application/vnd.api+json': {\n                            schema: { $ref: `#/components/schemas/${modelName}ListResponse` },\n                        },\n                    },\n                },\n                '400': ERROR_400,\n            },\n        };\n\n        const createOp = {\n            tags: [tag],\n            summary: `Create a ${modelName} resource`,\n            operationId: `create${modelName}`,\n            requestBody: {\n                required: true,\n                content: {\n                    'application/vnd.api+json': {\n                        schema: { $ref: `#/components/schemas/${modelName}CreateRequest` },\n                    },\n                },\n            },\n            responses: {\n                '201': {\n                    description: `Created ${modelName} resource`,\n                    content: {\n                        'application/vnd.api+json': {\n                            schema: { $ref: `#/components/schemas/${modelName}Response` },\n                        },\n                    },\n                },\n                '400': ERROR_400,\n                ...(mayDenyAccess(modelDef, 'create', this.specOptions?.respectAccessPolicies) && { '403': ERROR_403 }),\n                '422': ERROR_422,\n            },\n        };\n\n        const result: Record<string, any> = {};\n        if (isOperationIncluded(modelName, 'findMany', this.queryOptions)) {\n            result['get'] = listOp;\n        }\n        if (isOperationIncluded(modelName, 'create', this.queryOptions)) {\n            result['post'] = createOp;\n        }\n        return result;\n    }\n\n    private buildSinglePath(modelDef: ModelDef, tag: string): Record<string, any> {\n        const modelName = modelDef.name;\n        const idParam = { $ref: '#/components/parameters/id' };\n        const result: Record<string, any> = {};\n\n        if (isOperationIncluded(modelName, 'findUnique', this.queryOptions)) {\n            result['get'] = {\n                tags: [tag],\n                summary: `Get a ${modelName} resource by ID`,\n                operationId: `get${modelName}`,\n                parameters: [idParam, { $ref: '#/components/parameters/include' }],\n                responses: {\n                    '200': {\n                        description: `${modelName} resource`,\n                        content: {\n                            'application/vnd.api+json': {\n                                schema: { $ref: `#/components/schemas/${modelName}Response` },\n                            },\n                        },\n                    },\n                    '404': ERROR_404,\n                },\n            };\n        }\n\n        if (isOperationIncluded(modelName, 'update', this.queryOptions)) {\n            result['patch'] = {\n                tags: [tag],\n                summary: `Update a ${modelName} resource`,\n                operationId: `update${modelName}`,\n                parameters: [idParam],\n                requestBody: {\n                    required: true,\n                    content: {\n                        'application/vnd.api+json': {\n                            schema: { $ref: `#/components/schemas/${modelName}UpdateRequest` },\n                        },\n                    },\n                },\n                responses: {\n                    '200': {\n                        description: `Updated ${modelName} resource`,\n                        content: {\n                            'application/vnd.api+json': {\n                                schema: { $ref: `#/components/schemas/${modelName}Response` },\n                            },\n                        },\n                    },\n                    '400': ERROR_400,\n                    ...(mayDenyAccess(modelDef, 'update', this.specOptions?.respectAccessPolicies) && { '403': ERROR_403 }),\n                    '404': ERROR_404,\n                    '422': ERROR_422,\n                },\n            };\n        }\n\n        if (isOperationIncluded(modelName, 'delete', this.queryOptions)) {\n            result['delete'] = {\n                tags: [tag],\n                summary: `Delete a ${modelName} resource`,\n                operationId: `delete${modelName}`,\n                parameters: [idParam],\n                responses: {\n                    '200': { description: 'Deleted successfully' },\n                    ...(mayDenyAccess(modelDef, 'delete', this.specOptions?.respectAccessPolicies) && { '403': ERROR_403 }),\n                    '404': ERROR_404,\n                },\n            };\n        }\n\n        return result;\n    }\n\n    private buildRelatedPath(\n        modelName: string,\n        fieldName: string,\n        fieldDef: FieldDef,\n        tag: string,\n    ): Record<string, any> {\n        const isCollection = !!fieldDef.array;\n        const relModelDef = this.schema.models[fieldDef.type];\n        const params: any[] = [{ $ref: '#/components/parameters/id' }, { $ref: '#/components/parameters/include' }];\n\n        if (isCollection && relModelDef) {\n            params.push(\n                { $ref: '#/components/parameters/sort' },\n                { $ref: '#/components/parameters/pageOffset' },\n                { $ref: '#/components/parameters/pageLimit' },\n                ...this.buildFilterParams(fieldDef.type, relModelDef),\n            );\n        }\n\n        const pathItem: Record<string, any> = {\n            get: {\n                tags: [tag],\n                summary: `Fetch related ${fieldDef.type} for ${modelName}`,\n                operationId: `get${modelName}_${fieldName}`,\n                parameters: params,\n                responses: {\n                    '200': {\n                        description: `Related ${fieldDef.type} resource(s)`,\n                        content: {\n                            'application/vnd.api+json': {\n                                schema: isCollection\n                                    ? { $ref: `#/components/schemas/${fieldDef.type}ListResponse` }\n                                    : { $ref: `#/components/schemas/${fieldDef.type}Response` },\n                            },\n                        },\n                    },\n                    '404': ERROR_404,\n                },\n            },\n        };\n\n        if (this.nestedRoutes && relModelDef) {\n            const mayDeny = mayDenyAccess(relModelDef, isCollection ? 'create' : 'update', this.specOptions?.respectAccessPolicies);\n            if (isCollection && isOperationIncluded(fieldDef.type, 'create', this.queryOptions)) {\n                // POST /{model}/{id}/{field} — nested create\n                pathItem['post'] = {\n                    tags: [tag],\n                    summary: `Create a nested ${fieldDef.type} under ${modelName}`,\n                    operationId: `create${modelName}_${fieldName}`,\n                    parameters: [{ $ref: '#/components/parameters/id' }],\n                    requestBody: {\n                        required: true,\n                        content: {\n                            'application/vnd.api+json': {\n                                schema: { $ref: `#/components/schemas/${fieldDef.type}CreateRequest` },\n                            },\n                        },\n                    },\n                    responses: {\n                        '201': {\n                            description: `Created ${fieldDef.type} resource`,\n                            content: {\n                                'application/vnd.api+json': {\n                                    schema: { $ref: `#/components/schemas/${fieldDef.type}Response` },\n                                },\n                            },\n                        },\n                        '400': ERROR_400,\n                        ...(mayDeny && { '403': ERROR_403 }),\n                        '422': ERROR_422,\n                    },\n                };\n            } else if (!isCollection && isOperationIncluded(fieldDef.type, 'update', this.queryOptions)) {\n                // PATCH /{model}/{id}/{field} — nested to-one update\n                pathItem['patch'] = {\n                    tags: [tag],\n                    summary: `Update nested ${fieldDef.type} under ${modelName}`,\n                    operationId: `update${modelName}_${fieldName}`,\n                    parameters: [{ $ref: '#/components/parameters/id' }],\n                    requestBody: {\n                        required: true,\n                        content: {\n                            'application/vnd.api+json': {\n                                schema: { $ref: `#/components/schemas/${fieldDef.type}UpdateRequest` },\n                            },\n                        },\n                    },\n                    responses: {\n                        '200': {\n                            description: `Updated ${fieldDef.type} resource`,\n                            content: {\n                                'application/vnd.api+json': {\n                                    schema: { $ref: `#/components/schemas/${fieldDef.type}Response` },\n                                },\n                            },\n                        },\n                        '400': ERROR_400,\n                        ...(mayDeny && { '403': ERROR_403 }),\n                        '404': ERROR_404,\n                        '422': ERROR_422,\n                    },\n                };\n            }\n        }\n\n        return pathItem;\n    }\n\n    private buildNestedSinglePath(\n        modelName: string,\n        fieldName: string,\n        fieldDef: FieldDef,\n        relModelDef: ModelDef,\n        tag: string,\n    ): Record<string, any> {\n        const childIdParam = { name: 'childId', in: 'path', required: true, schema: { type: 'string' } };\n        const idParam = { $ref: '#/components/parameters/id' };\n        const mayDenyUpdate = mayDenyAccess(relModelDef, 'update', this.specOptions?.respectAccessPolicies);\n        const mayDenyDelete = mayDenyAccess(relModelDef, 'delete', this.specOptions?.respectAccessPolicies);\n        const result: Record<string, any> = {};\n\n        if (isOperationIncluded(fieldDef.type, 'findUnique', this.queryOptions)) {\n            result['get'] = {\n                tags: [tag],\n                summary: `Get a nested ${fieldDef.type} by ID under ${modelName}`,\n                operationId: `get${modelName}_${fieldName}_single`,\n                parameters: [idParam, childIdParam, { $ref: '#/components/parameters/include' }],\n                responses: {\n                    '200': {\n                        description: `${fieldDef.type} resource`,\n                        content: {\n                            'application/vnd.api+json': {\n                                schema: { $ref: `#/components/schemas/${fieldDef.type}Response` },\n                            },\n                        },\n                    },\n                    '404': ERROR_404,\n                },\n            };\n        }\n\n        if (isOperationIncluded(fieldDef.type, 'update', this.queryOptions)) {\n            result['patch'] = {\n                tags: [tag],\n                summary: `Update a nested ${fieldDef.type} by ID under ${modelName}`,\n                operationId: `update${modelName}_${fieldName}_single`,\n                parameters: [idParam, childIdParam],\n                requestBody: {\n                    required: true,\n                    content: {\n                        'application/vnd.api+json': {\n                            schema: { $ref: `#/components/schemas/${fieldDef.type}UpdateRequest` },\n                        },\n                    },\n                },\n                responses: {\n                    '200': {\n                        description: `Updated ${fieldDef.type} resource`,\n                        content: {\n                            'application/vnd.api+json': {\n                                schema: { $ref: `#/components/schemas/${fieldDef.type}Response` },\n                            },\n                        },\n                    },\n                    '400': ERROR_400,\n                    ...(mayDenyUpdate && { '403': ERROR_403 }),\n                    '404': ERROR_404,\n                    '422': ERROR_422,\n                },\n            };\n        }\n\n        if (isOperationIncluded(fieldDef.type, 'delete', this.queryOptions)) {\n            result['delete'] = {\n                tags: [tag],\n                summary: `Delete a nested ${fieldDef.type} by ID under ${modelName}`,\n                operationId: `delete${modelName}_${fieldName}_single`,\n                parameters: [idParam, childIdParam],\n                responses: {\n                    '200': { description: 'Deleted successfully' },\n                    ...(mayDenyDelete && { '403': ERROR_403 }),\n                    '404': ERROR_404,\n                },\n            };\n        }\n\n        return result;\n    }\n\n    private buildRelationshipPath(\n        modelDef: ModelDef,\n        fieldName: string,\n        fieldDef: FieldDef,\n        tag: string,\n    ): Record<string, any> {\n        const modelName = modelDef.name;\n        const isCollection = !!fieldDef.array;\n        const idParam = { $ref: '#/components/parameters/id' };\n        const relSchemaRef = isCollection\n            ? { $ref: '#/components/schemas/_toManyRelationshipWithLinks' }\n            : { $ref: '#/components/schemas/_toOneRelationshipWithLinks' };\n\n        const relRequestRef = isCollection\n            ? { $ref: '#/components/schemas/_toManyRelationshipRequest' }\n            : { $ref: '#/components/schemas/_toOneRelationshipRequest' };\n\n        const mayDeny = mayDenyAccess(modelDef, 'update', this.specOptions?.respectAccessPolicies);\n\n        const pathItem: Record<string, any> = {\n            get: {\n                tags: [tag],\n                summary: `Fetch ${fieldName} relationship`,\n                operationId: `get${modelName}_relationships_${fieldName}`,\n                parameters: [idParam],\n                responses: {\n                    '200': {\n                        description: `${fieldName} relationship`,\n                        content: { 'application/vnd.api+json': { schema: relSchemaRef } },\n                    },\n                    '404': ERROR_404,\n                },\n            },\n            put: {\n                tags: [tag],\n                summary: `Replace ${fieldName} relationship`,\n                operationId: `put${modelName}_relationships_${fieldName}`,\n                parameters: [idParam],\n                requestBody: {\n                    required: true,\n                    content: { 'application/vnd.api+json': { schema: relRequestRef } },\n                },\n                responses: {\n                    '200': { description: 'Relationship updated' },\n                    '400': ERROR_400,\n                    ...(mayDeny && { '403': ERROR_403 }),\n                },\n            },\n            patch: {\n                tags: [tag],\n                summary: `Update ${fieldName} relationship`,\n                operationId: `patch${modelName}_relationships_${fieldName}`,\n                parameters: [idParam],\n                requestBody: {\n                    required: true,\n                    content: { 'application/vnd.api+json': { schema: relRequestRef } },\n                },\n                responses: {\n                    '200': { description: 'Relationship updated' },\n                    '400': ERROR_400,\n                    ...(mayDeny && { '403': ERROR_403 }),\n                },\n            },\n        };\n\n        if (isCollection) {\n            pathItem['post'] = {\n                tags: [tag],\n                summary: `Add to ${fieldName} collection relationship`,\n                operationId: `post${modelName}_relationships_${fieldName}`,\n                parameters: [idParam],\n                requestBody: {\n                    required: true,\n                    content: {\n                        'application/vnd.api+json': {\n                            schema: { $ref: '#/components/schemas/_toManyRelationshipRequest' },\n                        },\n                    },\n                },\n                responses: {\n                    '200': { description: 'Added to relationship collection' },\n                    '400': ERROR_400,\n                    ...(mayDeny && { '403': ERROR_403 }),\n                },\n            };\n        }\n\n        return pathItem;\n    }\n\n    private buildProcedureOperation(procName: string, method: 'get' | 'post'): Record<string, any> {\n        const op: Record<string, any> = {\n            tags: ['$procs'],\n            summary: `Execute procedure ${procName}`,\n            operationId: `proc_${procName}`,\n            responses: {\n                '200': { description: `Result of ${procName}` },\n                '400': ERROR_400,\n            },\n        };\n\n        if (method === 'get') {\n            op['parameters'] = [\n                {\n                    name: 'q',\n                    in: 'query',\n                    description: 'Procedure arguments as JSON',\n                    schema: { type: 'string' },\n                },\n            ];\n        } else {\n            op['requestBody'] = {\n                content: {\n                    'application/json': {\n                        schema: { type: 'object' },\n                    },\n                },\n            };\n        }\n\n        return op;\n    }\n\n    private buildFilterParams(modelName: string, modelDef: ModelDef): ParameterObject[] {\n        const params: ParameterObject[] = [];\n        const idFieldNames = new Set(modelDef.idFields);\n\n        // id filter (Equality kind)\n        if (isFilterKindIncluded(modelName, 'id', 'Equality', this.queryOptions)) {\n            params.push({\n                name: 'filter[id]',\n                in: 'query',\n                schema: { type: 'string' },\n                description: `Filter by ${modelName} ID`,\n            });\n        }\n\n        for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) {\n            if (fieldDef.relation) continue;\n            if (idFieldNames.has(fieldName)) continue;\n\n            const type = fieldDef.type;\n\n            // Equality filter\n            if (isFilterKindIncluded(modelName, fieldName, 'Equality', this.queryOptions)) {\n                params.push({\n                    name: `filter[${fieldName}]`,\n                    in: 'query',\n                    schema: { type: 'string' },\n                    description: `Filter by ${fieldName}`,\n                });\n            }\n\n            if (type === 'String' && isFilterKindIncluded(modelName, fieldName, 'Like', this.queryOptions)) {\n                for (const op of SCALAR_STRING_OPS) {\n                    params.push({\n                        name: `filter[${fieldName}][${op}]`,\n                        in: 'query',\n                        schema: { type: 'string' },\n                    });\n                }\n            } else if (\n                (type === 'Int' ||\n                    type === 'Float' ||\n                    type === 'BigInt' ||\n                    type === 'Decimal' ||\n                    type === 'DateTime') &&\n                isFilterKindIncluded(modelName, fieldName, 'Range', this.queryOptions)\n            ) {\n                for (const op of SCALAR_COMPARABLE_OPS) {\n                    params.push({\n                        name: `filter[${fieldName}][${op}]`,\n                        in: 'query',\n                        schema: { type: 'string' },\n                    });\n                }\n            }\n\n            if (fieldDef.array && isFilterKindIncluded(modelName, fieldName, 'List', this.queryOptions)) {\n                for (const op of SCALAR_ARRAY_OPS) {\n                    params.push({\n                        name: `filter[${fieldName}][${op}]`,\n                        in: 'query',\n                        schema: { type: 'string' },\n                    });\n                }\n            }\n        }\n\n        return params;\n    }\n\n    private generateSchemas(): Record<string, SchemaObject | ReferenceObject> {\n        const schemas: Record<string, SchemaObject | ReferenceObject> = {};\n\n        // Shared JSON:API components\n        Object.assign(schemas, this.buildSharedSchemas());\n\n        // Per-enum schemas\n        if (this.schema.enums) {\n            for (const [_enumName, enumDef] of Object.entries(this.schema.enums)) {\n                schemas[_enumName] = this.buildEnumSchema(enumDef);\n            }\n        }\n\n        // Per-typeDef schemas\n        if (this.schema.typeDefs) {\n            for (const [typeName, typeDef] of Object.entries(this.schema.typeDefs)) {\n                schemas[typeName] = this.buildTypeDefSchema(typeDef);\n            }\n        }\n\n        // Per-model schemas\n        for (const modelName of getIncludedModels(this.schema, this.queryOptions)) {\n            const modelDef = this.schema.models[modelName]!;\n            const idFields = this.getIdFields(modelDef);\n            if (idFields.length === 0) continue;\n\n            schemas[modelName] = this.buildModelReadSchema(modelName, modelDef);\n            schemas[`${modelName}CreateRequest`] = this.buildCreateRequestSchema(modelName, modelDef);\n            schemas[`${modelName}UpdateRequest`] = this.buildUpdateRequestSchema(modelDef);\n            schemas[`${modelName}Response`] = this.buildModelResponseSchema(modelName);\n            schemas[`${modelName}ListResponse`] = this.buildModelListResponseSchema(modelName);\n        }\n\n        return schemas;\n    }\n\n    private buildSharedSchemas(): Record<string, SchemaObject> {\n        const nullableString: SchemaObject = { oneOf: [{ type: 'string' }, { type: 'null' }] };\n        return {\n            _jsonapi: {\n                type: 'object',\n                properties: {\n                    version: { type: 'string' },\n                    meta: { type: 'object' },\n                },\n            },\n            _meta: {\n                type: 'object',\n                additionalProperties: true,\n            },\n            _links: {\n                type: 'object',\n                properties: {\n                    self: { type: 'string' },\n                    related: { type: 'string' },\n                },\n            },\n            _pagination: {\n                type: 'object',\n                properties: {\n                    first: nullableString,\n                    last: nullableString,\n                    prev: nullableString,\n                    next: nullableString,\n                },\n            },\n            _errors: {\n                type: 'array',\n                items: {\n                    type: 'object',\n                    properties: {\n                        status: { type: 'integer' },\n                        code: { type: 'string' },\n                        title: { type: 'string' },\n                        detail: { type: 'string' },\n                    },\n                    required: ['status', 'title'],\n                },\n            },\n            _errorResponse: {\n                type: 'object',\n                properties: {\n                    errors: { $ref: '#/components/schemas/_errors' },\n                },\n                required: ['errors'],\n            },\n            _resourceIdentifier: {\n                type: 'object',\n                properties: {\n                    type: { type: 'string' },\n                    id: { type: 'string' },\n                },\n                required: ['type', 'id'],\n            },\n            _resource: {\n                type: 'object',\n                properties: {\n                    type: { type: 'string' },\n                    id: { type: 'string' },\n                    attributes: { type: 'object' },\n                    relationships: { type: 'object' },\n                    links: { $ref: '#/components/schemas/_links' },\n                    meta: { $ref: '#/components/schemas/_meta' },\n                },\n                required: ['type', 'id'],\n            },\n            _relationLinks: {\n                type: 'object',\n                properties: {\n                    self: { type: 'string' },\n                    related: { type: 'string' },\n                },\n            },\n            _pagedRelationLinks: {\n                type: 'object',\n                allOf: [{ $ref: '#/components/schemas/_relationLinks' }, { $ref: '#/components/schemas/_pagination' }],\n            },\n            _toOneRelationship: {\n                type: 'object',\n                properties: {\n                    data: {\n                        oneOf: [{ $ref: '#/components/schemas/_resourceIdentifier' }, { type: 'null' }],\n                    },\n                },\n            },\n            _toManyRelationship: {\n                type: 'object',\n                properties: {\n                    data: {\n                        type: 'array',\n                        items: { $ref: '#/components/schemas/_resourceIdentifier' },\n                    },\n                },\n            },\n            _toOneRelationshipWithLinks: {\n                type: 'object',\n                allOf: [\n                    { $ref: '#/components/schemas/_toOneRelationship' },\n                    {\n                        properties: {\n                            links: { $ref: '#/components/schemas/_relationLinks' },\n                        },\n                    },\n                ],\n            },\n            _toManyRelationshipWithLinks: {\n                type: 'object',\n                allOf: [\n                    { $ref: '#/components/schemas/_toManyRelationship' },\n                    {\n                        properties: {\n                            links: { $ref: '#/components/schemas/_pagedRelationLinks' },\n                        },\n                    },\n                ],\n            },\n            _toManyRelationshipRequest: {\n                type: 'object',\n                properties: {\n                    data: {\n                        type: 'array',\n                        items: { $ref: '#/components/schemas/_resourceIdentifier' },\n                    },\n                },\n                required: ['data'],\n            },\n            _toOneRelationshipRequest: {\n                type: 'object',\n                properties: {\n                    data: {\n                        oneOf: [{ $ref: '#/components/schemas/_resourceIdentifier' }, { type: 'null' }],\n                    },\n                },\n                required: ['data'],\n            },\n            _toManyRelationshipResponse: {\n                type: 'object',\n                properties: {\n                    data: {\n                        type: 'array',\n                        items: { $ref: '#/components/schemas/_resourceIdentifier' },\n                    },\n                    links: { $ref: '#/components/schemas/_pagedRelationLinks' },\n                    meta: { $ref: '#/components/schemas/_meta' },\n                },\n            },\n            _toOneRelationshipResponse: {\n                type: 'object',\n                properties: {\n                    data: {\n                        oneOf: [{ $ref: '#/components/schemas/_resourceIdentifier' }, { type: 'null' }],\n                    },\n                    links: { $ref: '#/components/schemas/_relationLinks' },\n                    meta: { $ref: '#/components/schemas/_meta' },\n                },\n            },\n        };\n    }\n\n    private buildEnumSchema(enumDef: EnumDef): SchemaObject {\n        return {\n            type: 'string',\n            enum: Object.values(enumDef.values),\n        };\n    }\n\n    private buildTypeDefSchema(typeDef: TypeDefDef): SchemaObject {\n        const properties: Record<string, SchemaObject | ReferenceObject> = {};\n        const required: string[] = [];\n\n        for (const [fieldName, fieldDef] of Object.entries(typeDef.fields)) {\n            properties[fieldName] = this.fieldToSchema(fieldDef);\n            if (!fieldDef.optional && !fieldDef.array) {\n                required.push(fieldName);\n            }\n        }\n\n        const result: SchemaObject = { type: 'object', properties };\n        if (required.length > 0) {\n            result.required = required;\n        }\n        return result;\n    }\n\n    private buildModelReadSchema(modelName: string, modelDef: ModelDef): SchemaObject {\n        const attrProperties: Record<string, SchemaObject | ReferenceObject> = {};\n        const attrRequired: string[] = [];\n        const relProperties: Record<string, SchemaObject | ReferenceObject> = {};\n\n        for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) {\n            if (fieldDef.omit) continue;\n            if (isFieldOmitted(modelName, fieldName, this.queryOptions)) continue;\n            if (fieldDef.relation && !isModelIncluded(fieldDef.type, this.queryOptions)) continue;\n\n            if (fieldDef.relation) {\n                const relRef: SchemaObject | ReferenceObject = fieldDef.array\n                    ? { $ref: '#/components/schemas/_toManyRelationshipWithLinks' }\n                    : { $ref: '#/components/schemas/_toOneRelationshipWithLinks' };\n                relProperties[fieldName] = fieldDef.optional ? { oneOf: [{ type: 'null' }, relRef] } : relRef;\n            } else {\n                const schema = this.fieldToSchema(fieldDef);\n                const fieldDescription = getMetaDescription(fieldDef.attributes);\n                if (fieldDescription && !('$ref' in schema)) {\n                    schema.description = fieldDescription;\n                }\n                attrProperties[fieldName] = schema;\n\n                if (!fieldDef.optional && !fieldDef.array) {\n                    attrRequired.push(fieldName);\n                }\n            }\n        }\n\n        const properties: Record<string, SchemaObject | ReferenceObject> = {};\n\n        if (Object.keys(attrProperties).length > 0) {\n            const attrSchema: SchemaObject = { type: 'object', properties: attrProperties };\n            if (attrRequired.length > 0) attrSchema.required = attrRequired;\n            properties['attributes'] = attrSchema;\n        }\n\n        if (Object.keys(relProperties).length > 0) {\n            properties['relationships'] = { type: 'object', properties: relProperties };\n        }\n\n        const result: SchemaObject = { type: 'object', properties };\n        const description = getMetaDescription(modelDef.attributes);\n        if (description) {\n            result.description = description;\n        }\n        return result;\n    }\n\n    private buildCreateRequestSchema(_modelName: string, modelDef: ModelDef): SchemaObject {\n        const idFieldNames = new Set(modelDef.idFields);\n        const attributes: Record<string, SchemaObject | ReferenceObject> = {};\n        const attrRequired: string[] = [];\n        const relationships: Record<string, SchemaObject | ReferenceObject> = {};\n\n        for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) {\n            if (fieldDef.updatedAt) continue;\n            if (fieldDef.foreignKeyFor) continue;\n            // Skip auto-generated id fields\n            if (idFieldNames.has(fieldName) && fieldDef.default !== undefined) continue;\n            if (fieldDef.relation && !isModelIncluded(fieldDef.type, this.queryOptions)) continue;\n\n            if (fieldDef.relation) {\n                relationships[fieldName] = fieldDef.array\n                    ? {\n                          type: 'object',\n                          properties: {\n                              data: {\n                                  type: 'array',\n                                  items: { $ref: '#/components/schemas/_resourceIdentifier' },\n                              },\n                          },\n                      }\n                    : {\n                          type: 'object',\n                          properties: {\n                              data: { $ref: '#/components/schemas/_resourceIdentifier' },\n                          },\n                      };\n            } else {\n                attributes[fieldName] = this.fieldToSchema(fieldDef);\n                if (!fieldDef.optional && fieldDef.default === undefined && !fieldDef.array) {\n                    attrRequired.push(fieldName);\n                }\n            }\n        }\n\n        const dataProperties: Record<string, SchemaObject | ReferenceObject> = {\n            type: { type: 'string' },\n        };\n\n        if (Object.keys(attributes).length > 0) {\n            const attrSchema: SchemaObject = { type: 'object', properties: attributes };\n            if (attrRequired.length > 0) attrSchema.required = attrRequired;\n            dataProperties['attributes'] = attrSchema;\n        }\n\n        if (Object.keys(relationships).length > 0) {\n            dataProperties['relationships'] = { type: 'object', properties: relationships };\n        }\n\n        return {\n            type: 'object',\n            properties: {\n                data: {\n                    type: 'object',\n                    properties: dataProperties,\n                    required: ['type'],\n                },\n            },\n            required: ['data'],\n        };\n    }\n\n    private buildUpdateRequestSchema(modelDef: ModelDef): SchemaObject {\n        const attributes: Record<string, SchemaObject | ReferenceObject> = {};\n        const relationships: Record<string, SchemaObject | ReferenceObject> = {};\n\n        for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) {\n            if (fieldDef.updatedAt) continue;\n            if (fieldDef.foreignKeyFor) continue;\n            if (fieldDef.relation && !isModelIncluded(fieldDef.type, this.queryOptions)) continue;\n\n            if (fieldDef.relation) {\n                relationships[fieldName] = fieldDef.array\n                    ? {\n                          type: 'object',\n                          properties: {\n                              data: {\n                                  type: 'array',\n                                  items: { $ref: '#/components/schemas/_resourceIdentifier' },\n                              },\n                          },\n                      }\n                    : {\n                          type: 'object',\n                          properties: {\n                              data: { $ref: '#/components/schemas/_resourceIdentifier' },\n                          },\n                      };\n            } else {\n                attributes[fieldName] = this.fieldToSchema(fieldDef);\n            }\n        }\n\n        const dataProperties: Record<string, SchemaObject | ReferenceObject> = {\n            type: { type: 'string' },\n            id: { type: 'string' },\n        };\n\n        if (Object.keys(attributes).length > 0) {\n            dataProperties['attributes'] = { type: 'object', properties: attributes };\n        }\n\n        if (Object.keys(relationships).length > 0) {\n            dataProperties['relationships'] = { type: 'object', properties: relationships };\n        }\n\n        return {\n            type: 'object',\n            properties: {\n                data: {\n                    type: 'object',\n                    properties: dataProperties,\n                    required: ['type', 'id'],\n                },\n            },\n            required: ['data'],\n        };\n    }\n\n    private buildModelResponseSchema(modelName: string): SchemaObject {\n        return {\n            type: 'object',\n            properties: {\n                jsonapi: { $ref: '#/components/schemas/_jsonapi' },\n                data: {\n                    allOf: [{ $ref: `#/components/schemas/${modelName}` }, { $ref: '#/components/schemas/_resource' }],\n                },\n                meta: { $ref: '#/components/schemas/_meta' },\n            },\n        };\n    }\n\n    private buildModelListResponseSchema(modelName: string): SchemaObject {\n        return {\n            type: 'object',\n            properties: {\n                jsonapi: { $ref: '#/components/schemas/_jsonapi' },\n                data: {\n                    type: 'array',\n                    items: {\n                        allOf: [\n                            { $ref: `#/components/schemas/${modelName}` },\n                            { $ref: '#/components/schemas/_resource' },\n                        ],\n                    },\n                },\n                links: {\n                    allOf: [{ $ref: '#/components/schemas/_pagination' }, { $ref: '#/components/schemas/_links' }],\n                },\n                meta: { $ref: '#/components/schemas/_meta' },\n            },\n        };\n    }\n\n    private generateSharedParams(): Record<string, ParameterObject> {\n        return {\n            id: {\n                name: 'id',\n                in: 'path',\n                required: true,\n                schema: { type: 'string' },\n                description: 'Resource ID',\n            },\n            include: {\n                name: 'include',\n                in: 'query',\n                schema: { type: 'string' },\n                description: 'Comma-separated list of relationships to include',\n            },\n            sort: {\n                name: 'sort',\n                in: 'query',\n                schema: { type: 'string' },\n                description: 'Comma-separated list of fields to sort by. Prefix with - for descending',\n            },\n            pageOffset: {\n                name: 'page[offset]',\n                in: 'query',\n                schema: { type: 'integer', minimum: 0 },\n                description: 'Page offset',\n            },\n            pageLimit: {\n                name: 'page[limit]',\n                in: 'query',\n                schema: { type: 'integer', minimum: 1 },\n                description: 'Page limit',\n            },\n        };\n    }\n\n    private fieldToSchema(fieldDef: FieldDef): SchemaObject | ReferenceObject {\n        const baseSchema = this.typeToSchema(fieldDef.type);\n        if (fieldDef.array) {\n            return { type: 'array', items: baseSchema };\n        }\n        if (fieldDef.optional) {\n            return { oneOf: [baseSchema, { type: 'null' }] };\n        }\n        return baseSchema;\n    }\n\n    private typeToSchema(type: string): SchemaObject | ReferenceObject {\n        switch (type) {\n            case 'String':\n                return { type: 'string' };\n            case 'Int':\n            case 'BigInt':\n                return { type: 'integer' };\n            case 'Float':\n                return { type: 'number' };\n            case 'Decimal':\n                return { oneOf: [{ type: 'number' }, { type: 'string' }] };\n            case 'Boolean':\n                return { type: 'boolean' };\n            case 'DateTime':\n                return { type: 'string', format: 'date-time' };\n            case 'Bytes':\n                return { type: 'string', format: 'byte' };\n            case 'Json':\n            case 'Unsupported':\n                return {};\n            default:\n                return { $ref: `#/components/schemas/${type}` };\n        }\n    }\n\n    private getIdFields(modelDef: ModelDef): FieldDef[] {\n        return modelDef.idFields.map((name) => modelDef.fields[name]).filter((f): f is FieldDef => f !== undefined);\n    }\n\n}\n","import { clone, enumerate, lowerCaseFirst, paramCase, safeJSONStringify } from '@zenstackhq/common-helpers';\nimport { ORMError, ORMErrorReason, type ClientContract } from '@zenstackhq/orm';\nimport type { FieldDef, ModelDef, SchemaDef } from '@zenstackhq/orm/schema';\nimport { Decimal } from 'decimal.js';\nimport SuperJSON from 'superjson';\nimport tsjapi, { type Linker, type Paginator, type Relator, type Serializer, type SerializerOptions } from 'ts-japi';\nimport { match } from 'ts-pattern';\nimport UrlPattern from 'url-pattern';\nimport z from 'zod';\nimport { fromError } from 'zod-validation-error/v4';\nimport type { ApiHandler, LogConfig, RequestContext, Response } from '../../types';\nimport { getProcedureDef, mapProcedureArgs } from '../common/procedures';\nimport { loggerSchema, queryOptionsSchema } from '../common/schemas';\nimport type { CommonHandlerOptions, OpenApiSpecGenerator, OpenApiSpecOptions } from '../common/types';\nimport { processSuperJsonRequestPayload } from '../common/utils';\nimport { getZodErrorMessage, log, registerCustomSerializers } from '../utils';\nimport { RestApiSpecGenerator } from './openapi';\n\n/**\n * Options for {@link RestApiHandler}\n */\nexport type RestApiHandlerOptions<Schema extends SchemaDef = SchemaDef> = {\n    /**\n     * The schema\n     */\n    schema: Schema;\n\n    /**\n     * Logging configuration\n     */\n    log?: LogConfig;\n\n    /**\n     * The base endpoint of the RESTful API, must be a valid URL\n     */\n    endpoint: string;\n\n    /**\n     * The default page size for limiting the number of results returned\n     * from collection queries, including resource collection, related data\n     * of collection types, and relationship of collection types.\n     *\n     * Defaults to 100. Set to Infinity to disable pagination.\n     */\n    pageSize?: number;\n\n    /**\n     * The divider used to separate compound ID fields in the URL.\n     * Defaults to '_'.\n     */\n    idDivider?: string;\n\n    /**\n     * The charset used for URL segment values. Defaults to `a-zA-Z0-9-_~ %`. You can change it if your entity's ID values\n     * allow different characters. Specifically, if your models use compound IDs and the idDivider is set to a different value,\n     * it should be included in the charset.\n     */\n    urlSegmentCharset?: string;\n\n    /**\n     * Mapping from model names to URL segment names.\n     */\n    modelNameMapping?: Record<string, string>;\n\n    /**\n     * Mapping from model names to unique field name to be used as resource's ID.\n     */\n    externalIdMapping?: Record<string, string>;\n\n    /**\n     * When `true`, enables nested route handling for all to-many relations:\n     * `/:parentType/:parentId/:relationName` (collection) and\n     * `/:parentType/:parentId/:relationName/:childId` (single).\n     *\n     * Defaults to `false`.\n     */\n    nestedRoutes?: boolean;\n} & CommonHandlerOptions<Schema>;\n\ntype RelationshipInfo = {\n    type: string;\n    idFields: FieldDef[];\n    isCollection: boolean;\n    isOptional: boolean;\n};\n\ntype ModelInfo = {\n    name: string;\n    idFields: FieldDef[];\n    fields: Record<string, FieldDef>;\n    relationships: Record<string, RelationshipInfo>;\n};\n\ntype Match = {\n    type: string;\n    id: string;\n    relationship: string;\n    childId?: string;\n};\n\nenum UrlPatterns {\n    SINGLE = 'single',\n    NESTED_SINGLE = 'nestedSingle',\n    FETCH_RELATIONSHIP = 'fetchRelationship',\n    RELATIONSHIP = 'relationship',\n    COLLECTION = 'collection',\n}\n\nclass InvalidValueError extends Error {\n    constructor(message: string) {\n        super(message);\n    }\n}\n\nconst DEFAULT_PAGE_SIZE = 100;\n\nconst FilterOperations = [\n    'lt',\n    'lte',\n    'gt',\n    'gte',\n    'between',\n    'contains',\n    'icontains',\n    'search',\n    'startsWith',\n    'endsWith',\n    'has',\n    'hasEvery',\n    'hasSome',\n    'isEmpty',\n] as const;\n\ntype FilterOperationType = (typeof FilterOperations)[number] | undefined;\n\nconst DEFAULT_ID_DIVIDER = '_';\n\nregisterCustomSerializers();\n\n/**\n * RESTful-style API request handler (compliant with JSON:API)\n */\nexport class RestApiHandler<Schema extends SchemaDef = SchemaDef> implements ApiHandler<Schema>, OpenApiSpecGenerator {\n    // resource serializers\n    private serializers = new Map<string, Serializer>();\n\n    // error responses\n    private readonly errors: Record<string, { status: number; title: string; detail?: string }> = {\n        unsupportedModel: {\n            status: 404,\n            title: 'Unsupported model type',\n            detail: 'The model type is not supported',\n        },\n        unsupportedRelationship: {\n            status: 400,\n            title: 'Unsupported relationship',\n            detail: 'The relationship is not supported',\n        },\n        invalidPath: {\n            status: 400,\n            title: 'The request path is invalid',\n        },\n        invalidVerb: {\n            status: 400,\n            title: 'The HTTP verb is not supported',\n        },\n        notFound: {\n            status: 404,\n            title: 'Resource not found',\n        },\n        noId: {\n            status: 400,\n            title: 'Model without an ID field is not supported',\n        },\n        invalidId: {\n            status: 400,\n            title: 'Resource ID is invalid',\n        },\n        invalidPayload: {\n            status: 400,\n            title: 'Invalid payload',\n        },\n        invalidRelationData: {\n            status: 400,\n            title: 'Invalid relation data',\n            detail: 'Invalid relationship data',\n        },\n        invalidRelation: {\n            status: 400,\n            title: 'Invalid relation',\n            detail: 'Invalid relationship',\n        },\n        invalidFilter: {\n            status: 400,\n            title: 'Invalid filter',\n        },\n        invalidSort: {\n            status: 400,\n            title: 'Invalid sort',\n        },\n        invalidValue: {\n            status: 400,\n            title: 'Invalid value for type',\n        },\n        duplicatedFieldsParameter: {\n            status: 400,\n            title: 'Fields Parameter Duplicated',\n        },\n        forbidden: {\n            status: 403,\n            title: 'Operation is forbidden',\n        },\n        validationError: {\n            status: 422,\n            title: 'Operation is unprocessable due to validation errors',\n        },\n        queryError: {\n            status: 400,\n            title: 'Error occurred while executing the query',\n        },\n        unknownError: {\n            status: 500,\n            title: 'Unknown error',\n        },\n    };\n\n    private filterParamPattern = new RegExp(/^filter(?<match>(\\[[^[\\]]+\\])+)$/);\n\n    // zod schema for payload of creating and updating a resource\n    private createUpdatePayloadSchema = z\n        .object({\n            data: z.object({\n                type: z.string(),\n                attributes: z.object({}).passthrough().optional(),\n                relationships: z\n                    .record(\n                        z.string(),\n                        z.object({\n                            data: z.union([\n                                z.object({ type: z.string(), id: z.union([z.string(), z.number()]) }),\n                                z.array(z.object({ type: z.string(), id: z.union([z.string(), z.number()]) })),\n                            ]),\n                        }),\n                    )\n                    .optional(),\n            }),\n            meta: z.object({}).passthrough().optional(),\n        })\n        .strict();\n\n    // zod schema for updating a single relationship\n    private updateSingleRelationSchema = z.object({\n        data: z.object({ type: z.string(), id: z.union([z.string(), z.number()]) }).nullable(),\n    });\n\n    // zod schema for updating collection relationship\n    private updateCollectionRelationSchema = z.object({\n        data: z.array(z.object({ type: z.string(), id: z.union([z.string(), z.number()]) })),\n    });\n\n    private upsertMetaSchema = z.object({\n        meta: z.object({\n            operation: z.literal('upsert'),\n            matchFields: z.array(z.string()).min(1),\n        }),\n    });\n\n    // all known types and their metadata\n    private typeMap: Record<string, ModelInfo> = {};\n\n    // divider used to separate compound ID fields\n    private idDivider;\n\n    private urlPatternMap: Record<UrlPatterns, UrlPattern>;\n    private modelNameMapping: Record<string, string>;\n    private reverseModelNameMapping: Record<string, string>;\n    private externalIdMapping: Record<string, string>;\n    private nestedRoutes: boolean;\n\n    constructor(private readonly options: RestApiHandlerOptions<Schema>) {\n        this.validateOptions(options);\n\n        this.idDivider = options.idDivider ?? DEFAULT_ID_DIVIDER;\n        const segmentCharset = options.urlSegmentCharset ?? 'a-zA-Z0-9-_~ %';\n\n        this.modelNameMapping = options.modelNameMapping ?? {};\n        this.modelNameMapping = Object.fromEntries(\n            Object.entries(this.modelNameMapping).map(([k, v]) => [lowerCaseFirst(k), v]),\n        );\n        this.reverseModelNameMapping = Object.fromEntries(\n            Object.entries(this.modelNameMapping).map(([k, v]) => [v, k]),\n        );\n\n        this.externalIdMapping = options.externalIdMapping ?? {};\n        this.externalIdMapping = Object.fromEntries(\n            Object.entries(this.externalIdMapping).map(([k, v]) => [lowerCaseFirst(k), v]),\n        );\n\n        this.nestedRoutes = options.nestedRoutes ?? false;\n\n        this.urlPatternMap = this.buildUrlPatternMap(segmentCharset);\n\n        this.buildTypeMap();\n        this.buildSerializers();\n    }\n\n    private validateOptions(options: RestApiHandlerOptions<Schema>) {\n        const schema = z.strictObject({\n            schema: z.object(),\n            log: loggerSchema.optional(),\n            endpoint: z.string().min(1),\n            pageSize: z.union([z.number().int().positive(), z.literal(Infinity)]).optional(),\n            idDivider: z.string().min(1).optional(),\n            urlSegmentCharset: z.string().min(1).optional(),\n            modelNameMapping: z.record(z.string(), z.string()).optional(),\n            externalIdMapping: z.record(z.string(), z.string()).optional(),\n            queryOptions: queryOptionsSchema.optional(),\n            nestedRoutes: z.boolean().optional(),\n        });\n        const parseResult = schema.safeParse(options);\n        if (!parseResult.success) {\n            throw new Error(`Invalid options: ${fromError(parseResult.error)}`);\n        }\n    }\n\n    get schema() {\n        return this.options.schema;\n    }\n\n    get log(): LogConfig | undefined {\n        return this.options.log;\n    }\n\n    private buildUrlPatternMap(urlSegmentNameCharset: string): Record<UrlPatterns, UrlPattern> {\n        const options = { segmentValueCharset: urlSegmentNameCharset };\n\n        const buildPath = (segments: string[]) => {\n            return '/' + segments.join('/');\n        };\n\n        return {\n            [UrlPatterns.SINGLE]: new UrlPattern(buildPath([':type', ':id']), options),\n            [UrlPatterns.NESTED_SINGLE]: new UrlPattern(\n                buildPath([':type', ':id', ':relationship', ':childId']),\n                options,\n            ),\n            [UrlPatterns.FETCH_RELATIONSHIP]: new UrlPattern(buildPath([':type', ':id', ':relationship']), options),\n            [UrlPatterns.RELATIONSHIP]: new UrlPattern(\n                buildPath([':type', ':id', 'relationships', ':relationship']),\n                options,\n            ),\n            [UrlPatterns.COLLECTION]: new UrlPattern(buildPath([':type']), options),\n        };\n    }\n\n    private mapModelName(modelName: string): string {\n        return this.modelNameMapping[modelName] ?? modelName;\n    }\n\n    /**\n     * Resolves child model type and reverse relation from a parent relation name.\n     * e.g. given parentType='user', parentRelation='posts', returns { childType:'post', reverseRelation:'author' }\n     */\n    private resolveNestedRelation(\n        parentType: string,\n        parentRelation: string,\n    ): { childType: string; reverseRelation: string; isCollection: boolean } | undefined {\n        const parentInfo = this.getModelInfo(parentType);\n        if (!parentInfo) return undefined;\n        const field: FieldDef | undefined = this.schema.models[parentInfo.name]?.fields[parentRelation];\n        if (!field?.relation) return undefined;\n        const reverseRelation = field.relation.opposite;\n        if (!reverseRelation) return undefined;\n        return { childType: lowerCaseFirst(field.type), reverseRelation, isCollection: !!field.array };\n    }\n\n    private mergeFilters(left: any, right: any) {\n        if (!left) {\n            return right;\n        }\n        if (!right) {\n            return left;\n        }\n        return { AND: [left, right] };\n    }\n\n    /**\n     * Builds a WHERE filter for the child model that constrains results to those belonging to the given parent.\n     * @param parentType  lowercased parent model name\n     * @param parentId    parent resource ID string\n     * @param parentRelation  relation field name on the parent model (e.g. 'posts')\n     */\n    private buildNestedParentFilter(parentType: string, parentId: string, parentRelation: string) {\n        const parentInfo = this.getModelInfo(parentType);\n        if (!parentInfo) {\n            return { filter: undefined, error: this.makeUnsupportedModelError(parentType) };\n        }\n\n        const resolved = this.resolveNestedRelation(parentType, parentRelation);\n        if (!resolved) {\n            return {\n                filter: undefined,\n                error: this.makeError(\n                    'invalidPath',\n                    `invalid nested route: cannot resolve relation \"${parentType}.${parentRelation}\"`,\n                ),\n            };\n        }\n\n        const { reverseRelation } = resolved;\n        const childInfo = this.getModelInfo(resolved.childType);\n        if (!childInfo) {\n            return { filter: undefined, error: this.makeUnsupportedModelError(resolved.childType) };\n        }\n\n        const reverseRelInfo = childInfo.relationships[reverseRelation];\n        const relationFilter = reverseRelInfo?.isCollection\n            ? { [reverseRelation]: { some: this.makeIdFilter(parentInfo.idFields, parentId, false) } }\n            : { [reverseRelation]: { is: this.makeIdFilter(parentInfo.idFields, parentId, false) } };\n\n        return { filter: relationFilter, error: undefined };\n    }\n\n    private matchUrlPattern(path: string, routeType: UrlPatterns): Match | undefined {\n        const pattern = this.urlPatternMap[routeType];\n        if (!pattern) {\n            throw new InvalidValueError(`Unknown route type: ${routeType}`);\n        }\n\n        const match = pattern.match(path);\n        if (!match) {\n            return;\n        }\n\n        if (match.type in this.modelNameMapping) {\n            throw new InvalidValueError(\n                `use the mapped model name: ${this.modelNameMapping[match.type]} and not ${match.type}`,\n            );\n        }\n\n        if (match.type in this.reverseModelNameMapping) {\n            match.type = this.reverseModelNameMapping[match.type];\n        }\n\n        return match;\n    }\n\n    async handleRequest({ client, method, path, query, requestBody }: RequestContext<Schema>): Promise<Response> {\n        method = method.toUpperCase();\n        if (!path.startsWith('/')) {\n            path = '/' + path;\n        }\n\n        try {\n            if (path.startsWith('/$procs/')) {\n                const proc = path.split('/')[2];\n                return await this.processProcedureRequest({ client, method, proc, query, requestBody });\n            }\n\n            switch (method) {\n                case 'GET': {\n                    let match = this.matchUrlPattern(path, UrlPatterns.SINGLE);\n                    if (match) {\n                        // single resource read\n                        return await this.processSingleRead(client, match.type, match.id, query);\n                    }\n                    match = this.matchUrlPattern(path, UrlPatterns.FETCH_RELATIONSHIP);\n                    if (match) {\n                        // fetch related resource(s)\n                        return await this.processFetchRelated(client, match.type, match.id, match.relationship, query);\n                    }\n\n                    match = this.matchUrlPattern(path, UrlPatterns.RELATIONSHIP);\n                    if (match) {\n                        // read relationship\n                        return await this.processReadRelationship(\n                            client,\n                            match.type,\n                            match.id,\n                            match.relationship,\n                            query,\n                        );\n                    }\n\n                    // /:type/:id/:relationship/:childId — nested single read\n                    match = this.matchUrlPattern(path, UrlPatterns.NESTED_SINGLE);\n                    if (match && this.nestedRoutes && this.resolveNestedRelation(match.type, match.relationship)?.isCollection) {\n                        return await this.processNestedSingleRead(\n                            client,\n                            match.type,\n                            match.id,\n                            match.relationship,\n                            match.childId!,\n                            query,\n                        );\n                    }\n                    match = this.matchUrlPattern(path, UrlPatterns.COLLECTION);\n                    if (match) {\n                        // collection read\n                        return await this.processCollectionRead(client, match.type, query);\n                    }\n\n                    return this.makeError('invalidPath');\n                }\n\n                case 'POST': {\n                    if (!requestBody) {\n                        return this.makeError('invalidPayload');\n                    }\n                    // /:type/:id/:relationship — nested create\n                    const nestedMatch = this.matchUrlPattern(path, UrlPatterns.FETCH_RELATIONSHIP);\n                    if (nestedMatch && this.nestedRoutes && this.resolveNestedRelation(nestedMatch.type, nestedMatch.relationship)?.isCollection) {\n                        return await this.processNestedCreate(\n                            client,\n                            nestedMatch.type,\n                            nestedMatch.id,\n                            nestedMatch.relationship,\n                            query,\n                            requestBody,\n                        );\n                    }\n                    let match = this.matchUrlPattern(path, UrlPatterns.COLLECTION);\n                    if (match) {\n                        const body = requestBody as any;\n                        const upsertMeta = this.upsertMetaSchema.safeParse(body);\n                        if (upsertMeta.success) {\n                            // resource upsert\n                            return await this.processUpsert(client, match.type, query, requestBody);\n                        } else {\n                            // resource creation\n                            return await this.processCreate(client, match.type, query, requestBody);\n                        }\n                    }\n                    match = this.matchUrlPattern(path, UrlPatterns.RELATIONSHIP);\n                    if (match) {\n                        // relationship creation (collection relationship only)\n                        return await this.processRelationshipCRUD(\n                            client,\n                            'create',\n                            match.type,\n                            match.id,\n                            match.relationship,\n                            query,\n                            requestBody,\n                        );\n                    }\n\n                    return this.makeError('invalidPath');\n                }\n\n                // TODO: PUT for full update\n                case 'PUT':\n                case 'PATCH': {\n                    if (!requestBody) {\n                        return this.makeError('invalidPayload');\n                    }\n                    // Check RELATIONSHIP before NESTED_SINGLE to avoid ambiguity on /:type/:id/relationships/:rel\n                    let match = this.matchUrlPattern(path, UrlPatterns.RELATIONSHIP);\n                    if (match) {\n                        // relationship update\n                        return await this.processRelationshipCRUD(\n                            client,\n                            'update',\n                            match.type,\n                            match.id,\n                            match.relationship as string,\n                            query,\n                            requestBody,\n                        );\n                    }\n                    // /:type/:id/:relationship — nested update (to-one)\n                    const nestedToOnePatchMatch = this.matchUrlPattern(path, UrlPatterns.FETCH_RELATIONSHIP);\n                    if (\n                        nestedToOnePatchMatch &&\n                        this.nestedRoutes &&\n                        this.resolveNestedRelation(nestedToOnePatchMatch.type, nestedToOnePatchMatch.relationship) &&\n                        !this.resolveNestedRelation(nestedToOnePatchMatch.type, nestedToOnePatchMatch.relationship)\n                            ?.isCollection\n                    ) {\n                        return await this.processNestedUpdate(\n                            client,\n                            nestedToOnePatchMatch.type,\n                            nestedToOnePatchMatch.id,\n                            nestedToOnePatchMatch.relationship,\n                            undefined,\n                            query,\n                            requestBody,\n                        );\n                    }\n                    // /:type/:id/:relationship/:childId — nested update (to-many)\n                    const nestedPatchMatch = this.matchUrlPattern(path, UrlPatterns.NESTED_SINGLE);\n                    if (\n                        nestedPatchMatch &&\n                        this.nestedRoutes &&\n                        this.resolveNestedRelation(nestedPatchMatch.type, nestedPatchMatch.relationship)?.isCollection\n                    ) {\n                        return await this.processNestedUpdate(\n                            client,\n                            nestedPatchMatch.type,\n                            nestedPatchMatch.id,\n                            nestedPatchMatch.relationship,\n                            nestedPatchMatch.childId!,\n                            query,\n                            requestBody,\n                        );\n                    }\n                    match = this.matchUrlPattern(path, UrlPatterns.SINGLE);\n                    if (match) {\n                        // resource update\n                        return await this.processUpdate(client, match.type, match.id, query, requestBody);\n                    }\n                    return this.makeError('invalidPath');\n                }\n\n                case 'DELETE': {\n                    // Check RELATIONSHIP before NESTED_SINGLE to avoid ambiguity on /:type/:id/relationships/:rel\n                    let match = this.matchUrlPattern(path, UrlPatterns.RELATIONSHIP);\n                    if (match) {\n                        // relationship deletion (collection relationship only)\n                        return await this.processRelationshipCRUD(\n                            client,\n                            'delete',\n                            match.type,\n                            match.id,\n                            match.relationship as string,\n                            query,\n                            requestBody,\n                        );\n                    }\n                    // /:type/:id/:relationship/:childId — nested delete (one-to-many child)\n                    const nestedDeleteMatch = this.matchUrlPattern(path, UrlPatterns.NESTED_SINGLE);\n                    if (\n                        nestedDeleteMatch &&\n                        this.nestedRoutes &&\n                        this.resolveNestedRelation(nestedDeleteMatch.type, nestedDeleteMatch.relationship)?.isCollection\n                    ) {\n                        return await this.processNestedDelete(\n                            client,\n                            nestedDeleteMatch.type,\n                            nestedDeleteMatch.id,\n                            nestedDeleteMatch.relationship,\n                            nestedDeleteMatch.childId!,\n                        );\n                    }\n                    match = this.matchUrlPattern(path, UrlPatterns.SINGLE);\n                    if (match) {\n                        // resource deletion\n                        return await this.processDelete(client, match.type, match.id);\n                    }\n                    return this.makeError('invalidPath');\n                }\n\n                default:\n                    return this.makeError('invalidPath');\n            }\n        } catch (err) {\n            if (err instanceof InvalidValueError) {\n                return this.makeError('invalidValue', err.message);\n            } else if (err instanceof ORMError) {\n                return this.handleORMError(err);\n            } else {\n                return this.handleGenericError(err);\n            }\n        }\n    }\n\n    private handleGenericError(err: unknown): Response | PromiseLike<Response> {\n        const resp = this.makeError('unknownError', err instanceof Error ? `${err.message}` : 'Unknown error');\n        log(\n            this.options.log,\n            'debug',\n            () => `sending error response: ${safeJSONStringify(resp)}${err instanceof Error ? '\\n' + err.stack : ''}`,\n        );\n        return resp;\n    }\n\n    private async processProcedureRequest({\n        client,\n        method,\n        proc,\n        query,\n        requestBody,\n    }: {\n        client: ClientContract<Schema>;\n        method: string;\n        proc?: string;\n        query?: Record<string, string | string[]>;\n        requestBody?: unknown;\n    }): Promise<Response> {\n        if (!proc) {\n            return this.makeProcBadInputErrorResponse('missing procedure name');\n        }\n\n        const procDef = getProcedureDef(this.schema, proc);\n        if (!procDef) {\n            return this.makeProcBadInputErrorResponse(`unknown procedure: ${proc}`);\n        }\n\n        const isMutation = !!procDef.mutation;\n        if (isMutation) {\n            if (method !== 'POST') {\n                return this.makeProcBadInputErrorResponse('invalid request method, only POST is supported');\n            }\n        } else {\n            if (method !== 'GET') {\n                return this.makeProcBadInputErrorResponse('invalid request method, only GET is supported');\n            }\n        }\n\n        const argsPayload = method === 'POST' ? requestBody : query;\n\n        // support SuperJSON request payload format\n        const { result: processedArgsPayload, error } = await processSuperJsonRequestPayload(argsPayload);\n        if (error) {\n            return this.makeProcBadInputErrorResponse(error);\n        }\n\n        let procInput: unknown;\n        try {\n            procInput = mapProcedureArgs(procDef, processedArgsPayload);\n        } catch (err) {\n            return this.makeProcBadInputErrorResponse(\n                err instanceof Error ? err.message : 'invalid procedure arguments',\n            );\n        }\n\n        try {\n            log(this.log, 'debug', () => `handling \"$procs.${proc}\" request`);\n\n            const clientResult = await (client as any).$procs?.[proc](procInput);\n            const toSerialize = this.toPlainObject(clientResult);\n\n            const { json, meta } = SuperJSON.serialize(toSerialize);\n            const responseBody: any = { data: json };\n            if (meta) {\n                responseBody.meta = { serialization: meta };\n            }\n\n            return { status: 200, body: responseBody };\n        } catch (err) {\n            log(this.log, 'error', `error occurred when handling \"$procs.${proc}\" request`, err);\n            if (err instanceof ORMError) {\n                throw err; // top-level handler will take care of it\n            }\n            return this.makeProcGenericErrorResponse(err);\n        }\n    }\n\n    private makeProcBadInputErrorResponse(message: string): Response {\n        const resp = this.makeError('invalidPayload', message, 400);\n        log(this.log, 'debug', () => `sending error response: ${safeJSONStringify(resp)}`);\n        return resp;\n    }\n\n    private makeProcGenericErrorResponse(err: unknown): Response {\n        const message = err instanceof Error ? err.message : 'unknown error';\n        const resp = this.makeError('unknownError', message, 500);\n        log(\n            this.log,\n            'debug',\n            () => `sending error response: ${safeJSONStringify(resp)}${err instanceof Error ? '\\n' + err.stack : ''}`,\n        );\n        return resp;\n    }\n\n    /**\n     * Builds the ORM `args` object (include, select) shared by single-read operations.\n     * Returns the args to pass to findUnique/findFirst and the resolved `include` list for serialization,\n     * or an error response if query params are invalid.\n     */\n    private buildSingleReadArgs(\n        type: string,\n        query: Record<string, string | string[]> | undefined,\n    ): { args: any; include: string[] | undefined; error?: Response } {\n        const args: any = {};\n\n        // include IDs of relation fields so that they can be serialized\n        this.includeRelationshipIds(type, args, 'include');\n\n        // handle \"include\" query parameter\n        let include: string[] | undefined;\n        if (query?.['include']) {\n            const { select, error, allIncludes } = this.buildRelationSelect(type, query['include'], query);\n            if (error) {\n                return { args, include, error };\n            }\n            if (select) {\n                args.include = { ...args.include, ...select };\n            }\n            include = allIncludes;\n        }\n\n        // handle partial results for requested type\n        const { select, error } = this.buildPartialSelect(type, query);\n        if (error) return { args, include, error };\n        if (select) {\n            args.select = { ...select, ...args.select };\n            if (args.include) {\n                args.select = { ...args.select, ...args.include };\n                args.include = undefined;\n            }\n        }\n\n        return { args, include };\n    }\n\n    private async processSingleRead(\n        client: ClientContract<Schema>,\n        type: string,\n        resourceId: string,\n        query: Record<string, string | string[]> | undefined,\n    ): Promise<Response> {\n        const typeInfo = this.getModelInfo(type);\n        if (!typeInfo) {\n            return this.makeUnsupportedModelError(type);\n        }\n\n        const { args, include, error } = this.buildSingleReadArgs(type, query);\n        if (error) return error;\n\n        args.where = this.makeIdFilter(typeInfo.idFields, resourceId);\n\n        const entity = await (client as any)[type].findUnique(args);\n\n        if (entity) {\n            return {\n                status: 200,\n                body: await this.serializeItems(type, entity, { include }),\n            };\n        } else {\n            return this.makeError('notFound');\n        }\n    }\n\n    private async processFetchRelated(\n        client: ClientContract<Schema>,\n        type: string,\n        resourceId: string,\n        relationship: string,\n        query: Record<string, string | string[]> | undefined,\n    ): Promise<Response> {\n        const typeInfo = this.getModelInfo(type);\n        if (!typeInfo) {\n            return this.makeUnsupportedModelError(type);\n        }\n\n        const relationInfo = typeInfo.relationships[relationship];\n        if (!relationInfo) {\n            return this.makeUnsupportedRelationshipError(type, relationship, 404);\n        }\n\n        let select: any;\n\n        // handle \"include\" query parameter\n        let include: string[] | undefined;\n        if (query?.['include']) {\n            const {\n                select: relationSelect,\n                error,\n                allIncludes,\n            } = this.buildRelationSelect(type, query['include'], query);\n            if (error) {\n                return error;\n            }\n            // trim the leading `$relationship.` from the include paths\n            include = allIncludes\n                .filter((i) => i.startsWith(`${relationship}.`))\n                .map((i) => i.substring(`${relationship}.`.length));\n            select = relationSelect;\n        }\n\n        // handle partial results for requested type\n        if (!select) {\n            const { select: partialFields, error } = this.buildPartialSelect(lowerCaseFirst(relationInfo.type), query);\n            if (error) return error;\n\n            select = partialFields ? { [relationship]: { select: { ...partialFields } } } : { [relationship]: true };\n        }\n\n        const args: any = {\n            where: this.makeIdFilter(typeInfo.idFields, resourceId),\n            select,\n        };\n\n        if (relationInfo.isCollection) {\n            // if related data is a collection, it can be filtered, sorted, and paginated\n            const error = this.injectRelationQuery(relationInfo.type, select, relationship, query);\n            if (error) {\n                return error;\n            }\n        }\n\n        const entity: any = await (client as any)[type].findUnique(args);\n\n        let paginator: Paginator<any> | undefined;\n\n        if (entity?._count?.[relationship] !== undefined) {\n            // build up paginator\n            const total = entity?._count?.[relationship] as number;\n            const url = this.makeNormalizedUrl(`/${type}/${resourceId}/${relationship}`, query);\n            const { offset, limit } = this.getPagination(query);\n            paginator = this.makePaginator(url, offset, limit, total);\n        }\n\n        if (entity?.[relationship]) {\n            const mappedType = this.mapModelName(type);\n            return {\n                status: 200,\n                body: await this.serializeItems(relationInfo.type, entity[relationship], {\n                    linkers: {\n                        document: new tsjapi.Linker(() =>\n                            this.makeLinkUrl(`/${mappedType}/${resourceId}/${relationship}`),\n                        ),\n                        paginator,\n                    },\n                    include,\n                }),\n            };\n        } else {\n            return this.makeError('notFound');\n        }\n    }\n\n    private async processReadRelationship(\n        client: ClientContract<Schema>,\n        type: string,\n        resourceId: string,\n        relationship: string,\n        query: Record<string, string | string[]> | undefined,\n    ): Promise<Response> {\n        const typeInfo = this.getModelInfo(type);\n        if (!typeInfo) {\n            return this.makeUnsupportedModelError(type);\n        }\n\n        const relationInfo = typeInfo.relationships[relationship];\n        if (!relationInfo) {\n            return this.makeUnsupportedRelationshipError(type, relationship, 404);\n        }\n\n        const args: any = {\n            where: this.makeIdFilter(typeInfo.idFields, resourceId),\n            select: this.makeIdSelect(typeInfo.idFields),\n        };\n\n        // include IDs of relation fields so that they can be serialized\n        args.select = { ...args.select, [relationship]: { select: this.makeIdSelect(relationInfo.idFields) } };\n\n        let paginator: Paginator<any> | undefined;\n\n        if (relationInfo.isCollection) {\n            // if related data is a collection, it can be filtered, sorted, and paginated\n            const error = this.injectRelationQuery(relationInfo.type, args.select, relationship, query);\n            if (error) {\n                return error;\n            }\n        }\n\n        const entity: any = await (client as any)[type].findUnique(args);\n        const mappedType = this.mapModelName(type);\n\n        if (entity?._count?.[relationship] !== undefined) {\n            // build up paginator\n            const total = entity?._count?.[relationship] as number;\n            const url = this.makeNormalizedUrl(`/${mappedType}/${resourceId}/relationships/${relationship}`, query);\n            const { offset, limit } = this.getPagination(query);\n            paginator = this.makePaginator(url, offset, limit, total);\n        }\n\n        if (entity?.[relationship]) {\n            const serialized: any = await this.serializeItems(relationInfo.type, entity[relationship], {\n                linkers: {\n                    document: new tsjapi.Linker(() =>\n                        this.makeLinkUrl(`/${mappedType}/${resourceId}/relationships/${relationship}`),\n                    ),\n                    paginator,\n                },\n                onlyIdentifier: true,\n            });\n\n            return {\n                status: 200,\n                body: serialized,\n            };\n        } else {\n            return this.makeError('notFound');\n        }\n    }\n\n    private async processCollectionRead(\n        client: ClientContract<Schema>,\n        type: string,\n        query: Record<string, string | string[]> | undefined,\n    ): Promise<Response> {\n        const typeInfo = this.getModelInfo(type);\n        if (!typeInfo) {\n            return this.makeUnsupportedModelError(type);\n        }\n\n        const args: any = {};\n\n        // add filter\n        const { filter, error: filterError } = this.buildFilter(type, query);\n        if (filterError) {\n            return filterError;\n        }\n        if (filter) {\n            args.where = filter;\n        }\n\n        const { sort, error: sortError } = this.buildSort(type, query);\n        if (sortError) {\n            return sortError;\n        }\n        if (sort) {\n            args.orderBy = sort;\n        }\n\n        // include IDs of relation fields so that they can be serialized\n        this.includeRelationshipIds(type, args, 'include');\n\n        // handle \"include\" query parameter\n        let include: string[] | undefined;\n        if (query?.['include']) {\n            const { select, error, allIncludes } = this.buildRelationSelect(type, query['include'], query);\n            if (error) {\n                return error;\n            }\n            if (select) {\n                args.include = { ...args.include, ...select };\n            }\n            include = allIncludes;\n        }\n\n        // handle partial results for requested type\n        const { select, error } = this.buildPartialSelect(type, query);\n        if (error) return error;\n        if (select) {\n            args.select = { ...select, ...args.select };\n            if (args.include) {\n                args.select = {\n                    ...args.select,\n                    ...args.include,\n                };\n                args.include = undefined;\n            }\n        }\n\n        const { offset, limit } = this.getPagination(query);\n        if (offset > 0) {\n            args.skip = offset;\n        }\n\n        if (limit === Infinity) {\n            const entities = await (client as any)[type].findMany(args);\n\n            const mappedType = this.mapModelName(type);\n            const body = await this.serializeItems(type, entities, {\n                include,\n                linkers: {\n                    document: new tsjapi.Linker(() => this.makeLinkUrl(`/${mappedType}`)),\n                },\n            });\n            const total = entities.length;\n            body.meta = this.addTotalCountToMeta(body.meta, total);\n\n            return {\n                status: 200,\n                body: body,\n            };\n        } else {\n            args.take = limit;\n\n            const [entities, count] = await Promise.all([\n                (client as any)[type].findMany(args),\n                (client as any)[type].count({ where: args.where ?? {} }),\n            ]);\n            const total = count as number;\n\n            const mappedType = this.mapModelName(type);\n            const url = this.makeNormalizedUrl(`/${mappedType}`, query);\n            const options: Partial<SerializerOptions> = {\n                include,\n                linkers: {\n                    document: new tsjapi.Linker(() => this.makeLinkUrl(`/${mappedType}`)),\n                    paginator: this.makePaginator(url, offset, limit, total),\n                },\n            };\n            const body = await this.serializeItems(type, entities, options);\n            body.meta = this.addTotalCountToMeta(body.meta, total);\n\n            return {\n                status: 200,\n                body: body,\n            };\n        }\n    }\n\n    /**\n     * Builds link URL for a nested resource using parent type, parent ID, relation name, and optional child ID.\n     * Uses the parent model name mapping for the parent segment; the relation name is used as-is.\n     */\n    private makeNestedLinkUrl(parentType: string, parentId: string, parentRelation: string, childId?: string) {\n        const mappedParentType = this.mapModelName(parentType);\n        const base = `/${mappedParentType}/${parentId}/${parentRelation}`;\n        return childId ? `${base}/${childId}` : base;\n    }\n\n    private async processNestedSingleRead(\n        client: ClientContract<Schema>,\n        parentType: string,\n        parentId: string,\n        parentRelation: string,\n        childId: string,\n        query: Record<string, string | string[]> | undefined,\n    ): Promise<Response> {\n        const resolved = this.resolveNestedRelation(parentType, parentRelation);\n        if (!resolved) {\n            return this.makeError('invalidPath');\n        }\n\n        const { filter: nestedFilter, error: nestedError } = this.buildNestedParentFilter(\n            parentType,\n            parentId,\n            parentRelation,\n        );\n        if (nestedError) return nestedError;\n\n        const childType = resolved.childType;\n        const typeInfo = this.getModelInfo(childType)!;\n\n        const { args, include, error } = this.buildSingleReadArgs(childType, query);\n        if (error) return error;\n\n        args.where = this.mergeFilters(this.makeIdFilter(typeInfo.idFields, childId), nestedFilter);\n\n        const entity = await (client as any)[childType].findFirst(args);\n        if (!entity) return this.makeError('notFound');\n\n        const linkUrl = this.makeLinkUrl(this.makeNestedLinkUrl(parentType, parentId, parentRelation, childId));\n        const nestedLinker = new tsjapi.Linker(() => linkUrl);\n        return {\n            status: 200,\n            body: await this.serializeItems(childType, entity, {\n                include,\n                linkers: { document: nestedLinker, resource: nestedLinker },\n            }),\n        };\n    }\n\n    private async processNestedCreate(\n        client: ClientContract<Schema>,\n        parentType: string,\n        parentId: string,\n        parentRelation: string,\n        _query: Record<string, string | string[]> | undefined,\n        requestBody: unknown,\n    ): Promise<Response> {\n        const resolved = this.resolveNestedRelation(parentType, parentRelation);\n        if (!resolved) {\n            return this.makeError('invalidPath');\n        }\n\n        const parentInfo = this.getModelInfo(parentType)!;\n        const childType = resolved.childType;\n        const childInfo = this.getModelInfo(childType)!;\n\n        const { attributes, relationships, error } = this.processRequestBody(requestBody);\n        if (error) return error;\n\n        const createData: any = { ...attributes };\n\n        // Turn relationship payload into `connect` objects, rejecting the parent relation\n        if (relationships) {\n            for (const [key, data] of Object.entries<any>(relationships)) {\n                if (!data?.data) {\n                    return this.makeError('invalidRelationData');\n                }\n                if (key === resolved.reverseRelation) {\n                    return this.makeError(\n                        'invalidPayload',\n                        `Relation \"${key}\" is controlled by the parent route and cannot be set in the request payload`,\n                    );\n                }\n                const relationInfo = childInfo.relationships[key];\n                if (!relationInfo) {\n                    return this.makeUnsupportedRelationshipError(childType, key, 400);\n                }\n                if (relationInfo.isCollection) {\n                    createData[key] = {\n                        connect: enumerate(data.data).map((item: any) =>\n                            this.makeIdConnect(relationInfo.idFields, item.id),\n                        ),\n                    };\n                } else {\n                    if (typeof data.data !== 'object') {\n                        return this.makeError('invalidRelationData');\n                    }\n                    createData[key] = { connect: this.makeIdConnect(relationInfo.idFields, data.data.id) };\n                }\n            }\n        }\n\n        // Reject scalar FK fields in attributes that would override the parent relation\n        const parentFkFields = Object.values(childInfo.fields).filter((f) =>\n            f.foreignKeyFor?.includes(resolved.reverseRelation),\n        );\n        if (parentFkFields.some((f) => Object.prototype.hasOwnProperty.call(createData, f.name))) {\n            return this.makeError(\n                'invalidPayload',\n                `Relation \"${resolved.reverseRelation}\" is controlled by the parent route and cannot be set in the request payload`,\n            );\n        }\n\n        // Atomically create child nested in parent update; ORM throws NOT_FOUND if parent doesn't exist\n        await (client as any)[parentType].update({\n            where: this.makeIdFilter(parentInfo.idFields, parentId),\n            data: { [parentRelation]: { create: createData } },\n        });\n\n        // Fetch the created child — most recently created for this parent\n        const { filter: nestedFilter, error: filterError } = this.buildNestedParentFilter(\n            parentType,\n            parentId,\n            parentRelation,\n        );\n        if (filterError) return filterError;\n\n        const fetchArgs: any = { where: nestedFilter };\n        this.includeRelationshipIds(childType, fetchArgs, 'include');\n        if (childInfo.idFields[0]) {\n            fetchArgs.orderBy = { [childInfo.idFields[0].name]: 'desc' };\n        }\n\n        const entity = await (client as any)[childType].findFirst(fetchArgs);\n        if (!entity) return this.makeError('notFound');\n\n        const collectionPath = this.makeNestedLinkUrl(parentType, parentId, parentRelation);\n        const resourceLinker = new tsjapi.Linker((item: any) =>\n            this.makeLinkUrl(`${collectionPath}/${this.getId(childInfo.name, item)}`),\n        );\n        return {\n            status: 201,\n            body: await this.serializeItems(childType, entity, {\n                linkers: { document: resourceLinker, resource: resourceLinker },\n            }),\n        };\n    }\n\n    /**\n     * Builds the ORM `data` payload for a nested update, shared by both to-many (childId present)\n     * and to-one (childId absent) variants.  Returns either `{ updateData }` or `{ error }`.\n     */\n    private buildNestedUpdatePayload(\n        childType: string,\n        typeInfo: ReturnType<RestApiHandler<Schema>['getModelInfo']>,\n        rev: string,\n        requestBody: unknown,\n    ): { updateData: any; error?: never } | { updateData?: never; error: Response } {\n        const { attributes, relationships, error } = this.processRequestBody(requestBody);\n        if (error) return { error };\n\n        const updateData: any = { ...attributes };\n\n        // Reject attempts to change the parent relation via the nested endpoint\n        if (relationships && Object.prototype.hasOwnProperty.call(relationships, rev)) {\n            return { error: this.makeError('invalidPayload', `Relation \"${rev}\" cannot be changed via a nested route`) };\n        }\n        const fkFields = Object.values(typeInfo!.fields).filter((f) => f.foreignKeyFor?.includes(rev));\n        if (fkFields.some((f) => Object.prototype.hasOwnProperty.call(updateData, f.name))) {\n            return { error: this.makeError('invalidPayload', `Relation \"${rev}\" cannot be changed via a nested route`) };\n        }\n\n        // Turn relationship payload into connect/set objects\n        if (relationships) {\n            for (const [key, data] of Object.entries<any>(relationships)) {\n                if (!data?.data) {\n                    return { error: this.makeError('invalidRelationData') };\n                }\n                const relationInfo = typeInfo!.relationships[key];\n                if (!relationInfo) {\n                    return { error: this.makeUnsupportedRelationshipError(childType, key, 400) };\n                }\n                if (relationInfo.isCollection) {\n                    updateData[key] = {\n                        set: enumerate(data.data).map((item: any) => ({\n                            [this.makeDefaultIdKey(relationInfo.idFields)]: item.id,\n                        })),\n                    };\n                } else {\n                    if (typeof data.data !== 'object') {\n                        return { error: this.makeError('invalidRelationData') };\n                    }\n                    updateData[key] = {\n                        connect: { [this.makeDefaultIdKey(relationInfo.idFields)]: data.data.id },\n                    };\n                }\n            }\n        }\n\n        return { updateData };\n    }\n\n    /**\n     * Handles PATCH /:type/:id/:relationship/:childId (to-many) and\n     * PATCH /:type/:id/:relationship (to-one, childId undefined).\n     */\n    private async processNestedUpdate(\n        client: ClientContract<Schema>,\n        parentType: string,\n        parentId: string,\n        parentRelation: string,\n        childId: string | undefined,\n        _query: Record<string, string | string[]> | undefined,\n        requestBody: unknown,\n    ): Promise<Response> {\n        const resolved = this.resolveNestedRelation(parentType, parentRelation);\n        if (!resolved) {\n            return this.makeError('invalidPath');\n        }\n\n        const parentInfo = this.getModelInfo(parentType)!;\n        const childType = resolved.childType;\n        const typeInfo = this.getModelInfo(childType)!;\n\n        const { updateData, error } = this.buildNestedUpdatePayload(childType, typeInfo, resolved.reverseRelation, requestBody);\n        if (error) return error;\n\n        if (childId) {\n            // to-many: ORM requires a where filter to identify the child within the collection\n            await (client as any)[parentType].update({\n                where: this.makeIdFilter(parentInfo.idFields, parentId),\n                data: { [parentRelation]: { update: { where: this.makeIdFilter(typeInfo.idFields, childId), data: updateData } } },\n            });\n            const fetchArgs: any = { where: this.makeIdFilter(typeInfo.idFields, childId) };\n            this.includeRelationshipIds(childType, fetchArgs, 'include');\n            const entity = await (client as any)[childType].findUnique(fetchArgs);\n            if (!entity) return this.makeError('notFound');\n            const linkUrl = this.makeLinkUrl(this.makeNestedLinkUrl(parentType, parentId, parentRelation, childId));\n            const nestedLinker = new tsjapi.Linker(() => linkUrl);\n            return { status: 200, body: await this.serializeItems(childType, entity, { linkers: { document: nestedLinker, resource: nestedLinker } }) };\n        } else {\n            // to-one: no where filter needed; fetch via parent select\n            await (client as any)[parentType].update({\n                where: this.makeIdFilter(parentInfo.idFields, parentId),\n                data: { [parentRelation]: { update: updateData } },\n            });\n            const childIncludeArgs: any = {};\n            this.includeRelationshipIds(childType, childIncludeArgs, 'include');\n            const fetchArgs: any = {\n                where: this.makeIdFilter(parentInfo.idFields, parentId),\n                select: { [parentRelation]: childIncludeArgs.include ? { include: childIncludeArgs.include } : true },\n            };\n            const parent = await (client as any)[parentType].findUnique(fetchArgs);\n            const entity = parent?.[parentRelation];\n            if (!entity) return this.makeError('notFound');\n            const linkUrl = this.makeLinkUrl(this.makeNestedLinkUrl(parentType, parentId, parentRelation));\n            const nestedLinker = new tsjapi.Linker(() => linkUrl);\n            return { status: 200, body: await this.serializeItems(childType, entity, { linkers: { document: nestedLinker, resource: nestedLinker } }) };\n        }\n    }\n\n    private async processNestedDelete(\n        client: ClientContract<Schema>,\n        parentType: string,\n        parentId: string,\n        parentRelation: string,\n        childId: string,\n    ): Promise<Response> {\n        const resolved = this.resolveNestedRelation(parentType, parentRelation);\n        if (!resolved) {\n            return this.makeError('invalidPath');\n        }\n\n        const parentInfo = this.getModelInfo(parentType)!;\n        const typeInfo = this.getModelInfo(resolved.childType)!;\n\n        // Atomically delete child scoped to parent; ORM throws NOT_FOUND if parent or child-belongs-to-parent check fails\n        await (client as any)[parentType].update({\n            where: this.makeIdFilter(parentInfo.idFields, parentId),\n            data: { [parentRelation]: { delete: this.makeIdFilter(typeInfo.idFields, childId) } },\n        });\n\n        return { status: 200, body: { meta: {} } };\n    }\n\n    private buildPartialSelect(type: string, query: Record<string, string | string[]> | undefined) {\n        const selectFieldsQuery = query?.[`fields[${type}]`];\n        if (!selectFieldsQuery) {\n            return { select: undefined, error: undefined };\n        }\n\n        if (Array.isArray(selectFieldsQuery)) {\n            return {\n                select: undefined,\n                error: this.makeError('duplicatedFieldsParameter', `duplicated fields query for type ${type}`),\n            };\n        }\n\n        const typeInfo = this.getModelInfo(type);\n        if (!typeInfo) {\n            return { select: undefined, error: this.makeUnsupportedModelError(type) };\n        }\n\n        const selectFieldNames = selectFieldsQuery.split(',').filter((i) => i);\n\n        const fields = selectFieldNames.reduce((acc, curr) => ({ ...acc, [curr]: true }), {});\n\n        return {\n            select: { ...this.makeIdSelect(typeInfo.idFields), ...fields },\n        };\n    }\n\n    private addTotalCountToMeta(meta: any, total: any) {\n        return meta ? Object.assign(meta, { total }) : Object.assign({}, { total });\n    }\n\n    private makePaginator(baseUrl: string, offset: number, limit: number, total: number) {\n        if (limit === Infinity) {\n            return undefined;\n        }\n\n        const totalPages = Math.ceil(total / limit);\n\n        return new tsjapi.Paginator(() => ({\n            first: this.replaceURLSearchParams(baseUrl, { 'page[limit]': limit }),\n            last: this.replaceURLSearchParams(baseUrl, {\n                'page[offset]': (totalPages - 1) * limit,\n            }),\n            prev:\n                offset - limit >= 0 && offset - limit <= total - 1\n                    ? this.replaceURLSearchParams(baseUrl, {\n                          'page[offset]': offset - limit,\n                          'page[limit]': limit,\n                      })\n                    : null,\n            next:\n                offset + limit <= total - 1\n                    ? this.replaceURLSearchParams(baseUrl, {\n                          'page[offset]': offset + limit,\n                          'page[limit]': limit,\n                      })\n                    : null,\n        }));\n    }\n\n    private processRequestBody(requestBody: unknown) {\n        let body: any = requestBody;\n        if (body.meta?.serialization) {\n            // superjson deserialize body if a serialization meta is provided\n            body = SuperJSON.deserialize({ json: body, meta: body.meta.serialization });\n        }\n\n        const parseResult = this.createUpdatePayloadSchema.safeParse(body);\n        if (!parseResult.success) {\n            return {\n                attributes: undefined,\n                relationships: undefined,\n                error: this.makeError('invalidPayload', getZodErrorMessage(parseResult.error)),\n            };\n        }\n\n        return {\n            attributes: parseResult.data.data.attributes,\n            relationships: parseResult.data.data.relationships,\n            error: undefined,\n        };\n    }\n\n    private async processCreate(\n        client: ClientContract<Schema>,\n        type: string,\n        _query: Record<string, string | string[]> | undefined,\n        requestBody: unknown,\n    ): Promise<Response> {\n        const typeInfo = this.getModelInfo(type);\n        if (!typeInfo) {\n            return this.makeUnsupportedModelError(type);\n        }\n\n        const { attributes, relationships, error } = this.processRequestBody(requestBody);\n        if (error) {\n            return error;\n        }\n\n        const createPayload: any = { data: { ...attributes } };\n\n        // turn relationship payload into `connect` objects\n        if (relationships) {\n            for (const [key, data] of Object.entries<any>(relationships)) {\n                if (!data?.data) {\n                    return this.makeError('invalidRelationData');\n                }\n\n                const relationInfo = typeInfo.relationships[key];\n                if (!relationInfo) {\n                    return this.makeUnsupportedRelationshipError(type, key, 400);\n                }\n\n                if (relationInfo.isCollection) {\n                    createPayload.data[key] = {\n                        connect: enumerate(data.data).map((item: any) =>\n                            this.makeIdConnect(relationInfo.idFields, item.id),\n                        ),\n                    };\n                } else {\n                    if (typeof data.data !== 'object') {\n                        return this.makeError('invalidRelationData');\n                    }\n                    createPayload.data[key] = {\n                        connect: this.makeIdConnect(relationInfo.idFields, data.data.id),\n                    };\n                }\n\n                // make sure ID fields are included for result serialization\n                createPayload.include = {\n                    ...createPayload.include,\n                    [key]: { select: { [this.makeDefaultIdKey(relationInfo.idFields)]: true } },\n                };\n            }\n        }\n\n        // include IDs of relation fields so that they can be serialized.\n        this.includeRelationshipIds(type, createPayload, 'include');\n\n        const entity = await (client as any)[type].create(createPayload);\n        return {\n            status: 201,\n            body: await this.serializeItems(type, entity),\n        };\n    }\n\n    private async processUpsert(\n        client: ClientContract<Schema>,\n        type: string,\n        _query: Record<string, string | string[]> | undefined,\n        requestBody: unknown,\n    ) {\n        const typeInfo = this.getModelInfo(type);\n        if (!typeInfo) {\n            return this.makeUnsupportedModelError(type);\n        }\n\n        const modelName = typeInfo.name;\n        const { attributes, relationships, error } = this.processRequestBody(requestBody);\n        if (error) {\n            return error;\n        }\n\n        const parseResult = this.upsertMetaSchema.safeParse(requestBody);\n        if (parseResult.error) {\n            return this.makeError('invalidPayload', getZodErrorMessage(parseResult.error));\n        }\n        const matchFields = parseResult.data.meta.matchFields;\n        const uniqueFieldSets = this.getUniqueFieldSets(modelName);\n\n        if (!uniqueFieldSets.some((set) => set.every((field) => matchFields.includes(field)))) {\n            return this.makeError('invalidPayload', 'Match fields must be unique fields', 400);\n        }\n\n        const upsertPayload: any = {\n            where: this.makeUpsertWhere(matchFields, attributes, typeInfo),\n            create: { ...attributes },\n            update: {\n                ...Object.fromEntries(Object.entries(attributes ?? {}).filter((e) => !matchFields.includes(e[0]))),\n            },\n        };\n\n        if (relationships) {\n            for (const [key, data] of Object.entries<any>(relationships)) {\n                if (!data?.data) {\n                    return this.makeError('invalidRelationData');\n                }\n\n                const relationInfo = typeInfo.relationships[key];\n                if (!relationInfo) {\n                    return this.makeUnsupportedRelationshipError(modelName, key, 400);\n                }\n\n                if (relationInfo.isCollection) {\n                    upsertPayload.create[key] = {\n                        connect: enumerate(data.data).map((item: any) =>\n                            this.makeIdConnect(relationInfo.idFields, item.id),\n                        ),\n                    };\n                    upsertPayload.update[key] = {\n                        set: enumerate(data.data).map((item: any) =>\n                            this.makeIdConnect(relationInfo.idFields, item.id),\n                        ),\n                    };\n                } else {\n                    if (typeof data.data !== 'object') {\n                        return this.makeError('invalidRelationData');\n                    }\n                    upsertPayload.create[key] = {\n                        connect: this.makeIdConnect(relationInfo.idFields, data.data.id),\n                    };\n                    upsertPayload.update[key] = {\n                        connect: this.makeIdConnect(relationInfo.idFields, data.data.id),\n                    };\n                }\n            }\n        }\n\n        // include IDs of relation fields so that they can be serialized.\n        this.includeRelationshipIds(modelName, upsertPayload, 'include');\n\n        const entity = await (client as any)[modelName].upsert(upsertPayload);\n\n        return {\n            status: 201,\n            body: await this.serializeItems(modelName, entity),\n        };\n    }\n\n    private getUniqueFieldSets(type: string) {\n        const modelDef = this.requireModel(type);\n        return Object.entries(modelDef.uniqueFields).map(\n            ([k, v]) =>\n                typeof v.type === 'string'\n                    ? [k] // single unique field\n                    : Object.keys(v), // compound unique fields\n        );\n    }\n\n    private async processRelationshipCRUD(\n        client: ClientContract<Schema>,\n        mode: 'create' | 'update' | 'delete',\n        type: string,\n        resourceId: string,\n        relationship: string,\n        _query: Record<string, string | string[]> | undefined,\n        requestBody: unknown,\n    ): Promise<Response> {\n        const typeInfo = this.getModelInfo(type);\n        if (!typeInfo) {\n            return this.makeUnsupportedModelError(type);\n        }\n\n        const relationInfo = typeInfo.relationships[relationship];\n        if (!relationInfo) {\n            return this.makeUnsupportedRelationshipError(type, relationship, 404);\n        }\n\n        if (!relationInfo.isCollection && mode !== 'update') {\n            // to-one relation can only be updated\n            return this.makeError('invalidVerb');\n        }\n\n        const updateArgs: any = {\n            where: this.makeIdFilter(typeInfo.idFields, resourceId),\n            select: {\n                ...typeInfo.idFields.reduce((acc, field) => ({ ...acc, [field.name]: true }), {}),\n                [relationship]: { select: this.makeIdSelect(relationInfo.idFields) },\n            },\n        };\n\n        if (!relationInfo.isCollection) {\n            // zod-parse payload\n            const parsed = this.updateSingleRelationSchema.safeParse(requestBody);\n            if (!parsed.success) {\n                return this.makeError('invalidPayload', getZodErrorMessage(parsed.error));\n            }\n\n            if (parsed.data.data === null) {\n                if (!relationInfo.isOptional) {\n                    // cannot disconnect a required relation\n                    return this.makeError('invalidPayload');\n                }\n                // set null -> disconnect\n                updateArgs.data = {\n                    [relationship]: {\n                        disconnect: true,\n                    },\n                };\n            } else {\n                updateArgs.data = {\n                    [relationship]: {\n                        connect: this.makeIdConnect(relationInfo.idFields, parsed.data.data.id),\n                    },\n                };\n            }\n        } else {\n            // zod-parse payload\n            const parsed = this.updateCollectionRelationSchema.safeParse(requestBody);\n            if (!parsed.success) {\n                return this.makeError('invalidPayload', getZodErrorMessage(parsed.error));\n            }\n\n            // create -> connect, delete -> disconnect, update -> set\n            const relationVerb = mode === 'create' ? 'connect' : mode === 'delete' ? 'disconnect' : 'set';\n\n            updateArgs.data = {\n                [relationship]: {\n                    [relationVerb]: enumerate(parsed.data.data).map((item: any) =>\n                        this.makeIdFilter(relationInfo.idFields, item.id),\n                    ),\n                },\n            };\n        }\n\n        const entity: any = await (client as any)[type].update(updateArgs);\n\n        const mappedType = this.mapModelName(type);\n\n        const serialized: any = await this.serializeItems(relationInfo.type, entity[relationship], {\n            linkers: {\n                document: new tsjapi.Linker(() =>\n                    this.makeLinkUrl(`/${mappedType}/${resourceId}/relationships/${relationship}`),\n                ),\n            },\n            onlyIdentifier: true,\n        });\n\n        return {\n            status: 200,\n            body: serialized,\n        };\n    }\n\n    private async processUpdate(\n        client: ClientContract<Schema>,\n        type: any,\n        resourceId: string,\n        _query: Record<string, string | string[]> | undefined,\n        requestBody: unknown,\n    ): Promise<Response> {\n        const typeInfo = this.getModelInfo(type);\n        if (!typeInfo) {\n            return this.makeUnsupportedModelError(type);\n        }\n\n        const { attributes, relationships, error } = this.processRequestBody(requestBody);\n        if (error) {\n            return error;\n        }\n\n        const updatePayload: any = {\n            where: this.makeIdFilter(typeInfo.idFields, resourceId),\n            data: { ...attributes },\n        };\n\n        // turn relationships into query payload\n        if (relationships) {\n            for (const [key, data] of Object.entries<any>(relationships)) {\n                if (!data?.data) {\n                    return this.makeError('invalidRelationData');\n                }\n\n                const relationInfo = typeInfo.relationships[key];\n                if (!relationInfo) {\n                    return this.makeUnsupportedRelationshipError(type, key, 400);\n                }\n\n                if (relationInfo.isCollection) {\n                    updatePayload.data[key] = {\n                        set: enumerate(data.data).map((item: any) => ({\n                            [this.makeDefaultIdKey(relationInfo.idFields)]: item.id,\n                        })),\n                    };\n                } else {\n                    if (typeof data.data !== 'object') {\n                        return this.makeError('invalidRelationData');\n                    }\n                    updatePayload.data[key] = {\n                        connect: {\n                            [this.makeDefaultIdKey(relationInfo.idFields)]: data.data.id,\n                        },\n                    };\n                }\n                updatePayload.include = {\n                    ...updatePayload.include,\n                    [key]: { select: { [this.makeDefaultIdKey(relationInfo.idFields)]: true } },\n                };\n            }\n        }\n\n        // include IDs of relation fields so that they can be serialized.\n        this.includeRelationshipIds(type, updatePayload, 'include');\n\n        const entity = await (client as any)[type].update(updatePayload);\n        return {\n            status: 200,\n            body: await this.serializeItems(type, entity),\n        };\n    }\n\n    private async processDelete(client: ClientContract<Schema>, type: any, resourceId: string): Promise<Response> {\n        const typeInfo = this.getModelInfo(type);\n        if (!typeInfo) {\n            return this.makeUnsupportedModelError(type);\n        }\n\n        await (client as any)[type].delete({\n            where: this.makeIdFilter(typeInfo.idFields, resourceId),\n        });\n        return {\n            status: 200,\n            body: { meta: {} },\n        };\n    }\n\n    //#region utilities\n\n    private requireModel(model: string): ModelDef {\n        const modelDef = this.schema.models[model];\n        if (!modelDef) {\n            throw new Error(`Model ${model} is not defined in the schema`);\n        }\n        return modelDef;\n    }\n\n    private getIdFields(model: string): FieldDef[] {\n        const modelDef = this.requireModel(model);\n        const modelLower = lowerCaseFirst(model);\n        if (!(modelLower in this.externalIdMapping)) {\n            return Object.values(modelDef.fields).filter((f) => modelDef.idFields.includes(f.name));\n        }\n\n        // map external ID name to unique constraint field\n        const externalIdName = this.externalIdMapping[modelLower];\n        for (const [name, info] of Object.entries(modelDef.uniqueFields)) {\n            if (name === externalIdName) {\n                if (typeof info.type === 'string') {\n                    // single unique field\n                    return [this.requireField(model, name)];\n                } else {\n                    // compound unique fields\n                    return Object.keys(info).map((f) => this.requireField(model, f));\n                }\n            }\n        }\n\n        throw new Error(`Model ${model} does not have unique key ${externalIdName}`);\n    }\n\n    private requireField(model: string, field: string): FieldDef {\n        const modelDef = this.requireModel(model);\n        const fieldDef = modelDef.fields[field];\n        if (!fieldDef) {\n            throw new Error(`Field ${field} is not defined in model ${model}`);\n        }\n        return fieldDef;\n    }\n\n    private buildTypeMap() {\n        this.typeMap = {};\n        for (const [model, { fields }] of Object.entries(this.schema.models)) {\n            const idFields = this.getIdFields(model);\n            if (idFields.length === 0) {\n                log(this.options.log, 'warn', `Not including model ${model} in the API because it has no ID field`);\n                continue;\n            }\n\n            const modelInfo: ModelInfo = (this.typeMap[lowerCaseFirst(model)] = {\n                name: model,\n                idFields,\n                relationships: {},\n                fields,\n            });\n\n            for (const [field, fieldInfo] of Object.entries(fields)) {\n                if (!fieldInfo.relation) {\n                    continue;\n                }\n                const fieldTypeIdFields = this.getIdFields(fieldInfo.type);\n                if (fieldTypeIdFields.length === 0) {\n                    log(\n                        this.options.log,\n                        'warn',\n                        `Not including relation ${model}.${field} in the API because it has no ID field`,\n                    );\n                    continue;\n                }\n\n                modelInfo.relationships[field] = {\n                    type: fieldInfo.type,\n                    idFields: fieldTypeIdFields,\n                    isCollection: !!fieldInfo.array,\n                    isOptional: !!fieldInfo.optional,\n                };\n            }\n        }\n    }\n\n    private getModelInfo(model: string): ModelInfo | undefined {\n        return this.typeMap[lowerCaseFirst(model)];\n    }\n\n    private makeLinkUrl(path: string) {\n        return `${this.options.endpoint}${path}`;\n    }\n\n    private buildSerializers() {\n        const linkers: Record<string, Linker<any>> = {};\n\n        for (const model of Object.keys(this.schema.models)) {\n            const ids = this.getIdFields(model);\n            const modelLower = lowerCaseFirst(model);\n            const mappedModel = this.mapModelName(modelLower);\n\n            if (ids.length < 1) {\n                continue;\n            }\n\n            const linker = new tsjapi.Linker((items) =>\n                Array.isArray(items)\n                    ? this.makeLinkUrl(`/${mappedModel}`)\n                    : this.makeLinkUrl(`/${mappedModel}/${this.getId(model, items)}`),\n            );\n            linkers[modelLower] = linker;\n\n            let projection: Record<string, 0> | null = {};\n            const modelDef = this.requireModel(model);\n            for (const [field, fieldDef] of Object.entries(modelDef.fields)) {\n                if (fieldDef.relation) {\n                    projection[field] = 0;\n                }\n            }\n            if (Object.keys(projection).length === 0) {\n                projection = null;\n            }\n\n            const serializer = new tsjapi.Serializer(model, {\n                version: '1.1',\n                idKey: this.makeIdKey(ids),\n                linkers: {\n                    resource: linker,\n                    document: linker,\n                },\n                projection,\n            });\n            this.serializers.set(modelLower, serializer);\n        }\n\n        // set relators\n        for (const model of Object.keys(this.schema.models)) {\n            const modelLower = lowerCaseFirst(model);\n            const serializer = this.serializers.get(modelLower);\n            if (!serializer) {\n                continue;\n            }\n\n            const relators: Record<string, Relator<any>> = {};\n            const modelDef = this.requireModel(model);\n            for (const [field, fieldDef] of Object.entries(modelDef.fields)) {\n                if (!fieldDef.relation) {\n                    continue;\n                }\n                const fieldSerializer = this.serializers.get(lowerCaseFirst(fieldDef.type));\n                if (!fieldSerializer) {\n                    continue;\n                }\n                const fieldIds = this.getIdFields(fieldDef.type);\n                if (fieldIds.length > 0) {\n                    const mappedModel = this.mapModelName(modelLower);\n\n                    const relator = new tsjapi.Relator(\n                        async (data) => {\n                            return (data as any)[field];\n                        },\n                        fieldSerializer,\n                        {\n                            relatedName: field,\n                            linkers: {\n                                related: new tsjapi.Linker((primary) =>\n                                    this.makeLinkUrl(`/${mappedModel}/${this.getId(model, primary)}/${field}`),\n                                ),\n                                relationship: new tsjapi.Linker((primary) =>\n                                    this.makeLinkUrl(\n                                        `/${mappedModel}/${this.getId(model, primary)}/relationships/${field}`,\n                                    ),\n                                ),\n                            },\n                        },\n                    );\n                    relators[field] = relator;\n                }\n            }\n            serializer.setRelators(relators);\n        }\n    }\n\n    private getId(model: string, data: any) {\n        if (!data) {\n            return undefined;\n        }\n        const ids = this.getIdFields(model);\n        if (ids.length === 0) {\n            return undefined;\n        } else {\n            return data[this.makeIdKey(ids)];\n        }\n    }\n\n    private async serializeItems(model: string, items: unknown, options?: Partial<SerializerOptions<any>>) {\n        model = lowerCaseFirst(model);\n        const serializer = this.serializers.get(model);\n        if (!serializer) {\n            throw new Error(`serializer not found for model ${model}`);\n        }\n\n        const itemsWithId = clone(items);\n        this.injectCompoundId(model, itemsWithId);\n\n        // serialize to JSON:API structure\n        const serialized = await serializer.serialize(itemsWithId, options);\n\n        // convert the serialization result to plain object otherwise SuperJSON won't work\n        const plainResult = this.toPlainObject(serialized);\n\n        // superjson serialize the result\n        const { json, meta } = SuperJSON.serialize(plainResult);\n\n        const result: any = json;\n        if (meta) {\n            result.meta = { ...result.meta, serialization: meta };\n        }\n\n        return result;\n    }\n\n    private injectCompoundId(model: string, items: unknown) {\n        const typeInfo = this.getModelInfo(model);\n        if (!typeInfo) {\n            return;\n        }\n\n        // recursively traverse the entity to create synthetic ID field for models with compound ID\n        enumerate(items).forEach((item: any) => {\n            if (!item) {\n                return;\n            }\n\n            if (typeInfo.idFields.length > 1) {\n                item[this.makeIdKey(typeInfo.idFields)] = this.makeCompoundId(typeInfo.idFields, item);\n            }\n\n            for (const [key, value] of Object.entries(item)) {\n                if (typeInfo.relationships[key]) {\n                    // field is a relationship, recurse\n                    this.injectCompoundId(typeInfo.relationships[key].type, value);\n                }\n            }\n        });\n    }\n\n    private toPlainObject(data: any): any {\n        if (data === undefined || data === null) {\n            return data;\n        }\n\n        if (Array.isArray(data)) {\n            return data.map((item: any) => this.toPlainObject(item));\n        }\n\n        if (typeof data === 'object') {\n            if (typeof data.toJSON === 'function') {\n                // custom toJSON function\n                return data.toJSON();\n            }\n            const result: any = {};\n            for (const [field, value] of Object.entries(data)) {\n                if (value === undefined || typeof value === 'function') {\n                    // trim undefined and functions\n                    continue;\n                } else if (field === 'attributes') {\n                    // don't visit into entity data\n                    result[field] = value;\n                } else {\n                    result[field] = this.toPlainObject(value);\n                }\n            }\n            return result;\n        }\n\n        return data;\n    }\n\n    private replaceURLSearchParams(url: string, params: Record<string, string | number>) {\n        const r = new URL(url);\n        for (const [key, value] of Object.entries(params)) {\n            r.searchParams.set(key, value.toString());\n        }\n        return r.toString();\n    }\n\n    private makeIdFilter(idFields: FieldDef[], resourceId: string, nested: boolean = true) {\n        const decodedId = decodeURIComponent(resourceId);\n        if (idFields.length === 1) {\n            return { [idFields[0]!.name]: this.coerce(idFields[0]!, decodedId) };\n        } else if (nested) {\n            return {\n                // TODO: support `@@id` with custom name\n                [idFields.map((idf) => idf.name).join(DEFAULT_ID_DIVIDER)]: idFields.reduce(\n                    (acc, curr, idx) => ({\n                        ...acc,\n                        [curr.name]: this.coerce(curr, decodedId.split(this.idDivider)[idx]),\n                    }),\n                    {},\n                ),\n            };\n        } else {\n            return idFields.reduce(\n                (acc, curr, idx) => ({\n                    ...acc,\n                    [curr.name]: this.coerce(curr, decodedId.split(this.idDivider)[idx]),\n                }),\n                {},\n            );\n        }\n    }\n\n    private makeIdSelect(idFields: FieldDef[]) {\n        if (idFields.length === 0) {\n            throw this.errors['noId'];\n        }\n        return idFields.reduce((acc, curr) => ({ ...acc, [curr.name]: true }), {});\n    }\n\n    private makeIdConnect(idFields: FieldDef[], id: string | number) {\n        if (idFields.length === 1) {\n            return { [idFields[0]!.name]: this.coerce(idFields[0]!, id) };\n        } else {\n            return {\n                [this.makeDefaultIdKey(idFields)]: idFields.reduce(\n                    (acc, curr, idx) => ({\n                        ...acc,\n                        [curr.name]: this.coerce(curr, `${id}`.split(this.idDivider)[idx]),\n                    }),\n                    {},\n                ),\n            };\n        }\n    }\n\n    private makeIdKey(idFields: FieldDef[]) {\n        return idFields.map((idf) => idf.name).join(this.idDivider);\n    }\n\n    private makeDefaultIdKey(idFields: FieldDef[]) {\n        // TODO: support `@@id` with custom name\n        return idFields.map((idf) => idf.name).join(DEFAULT_ID_DIVIDER);\n    }\n\n    private makeCompoundId(idFields: FieldDef[], item: any) {\n        return idFields.map((idf) => item[idf.name]).join(this.idDivider);\n    }\n\n    private makeUpsertWhere(matchFields: any[], attributes: any, typeInfo: ModelInfo) {\n        const where = matchFields.reduce((acc: any, field: string) => {\n            acc[field] = attributes[field] ?? null;\n            return acc;\n        }, {});\n\n        if (\n            typeInfo.idFields.length > 1 &&\n            matchFields.some((mf) => typeInfo.idFields.map((idf) => idf.name).includes(mf))\n        ) {\n            return {\n                [this.makeDefaultIdKey(typeInfo.idFields)]: where,\n            };\n        }\n\n        return where;\n    }\n\n    private includeRelationshipIds(model: string, args: any, mode: 'select' | 'include') {\n        const typeInfo = this.getModelInfo(model);\n        if (!typeInfo) {\n            return;\n        }\n        for (const [relation, relationInfo] of Object.entries(typeInfo.relationships)) {\n            args[mode] = { ...args[mode], [relation]: { select: this.makeIdSelect(relationInfo.idFields) } };\n        }\n    }\n\n    private coerce(fieldDef: FieldDef, value: any) {\n        if (typeof value === 'string') {\n            if (fieldDef.attributes?.some((attr) => attr.name === '@json')) {\n                try {\n                    return JSON.parse(value);\n                } catch {\n                    throw new InvalidValueError(`invalid JSON value: ${value}`);\n                }\n            }\n\n            const type = fieldDef.type;\n            if (type === 'Int') {\n                const parsed = parseInt(value);\n                if (isNaN(parsed)) {\n                    throw new InvalidValueError(`invalid ${type} value: ${value}`);\n                }\n                return parsed;\n            } else if (type === 'BigInt') {\n                try {\n                    return BigInt(value);\n                } catch {\n                    throw new InvalidValueError(`invalid ${type} value: ${value}`);\n                }\n            } else if (type === 'Float') {\n                const parsed = parseFloat(value);\n                if (isNaN(parsed)) {\n                    throw new InvalidValueError(`invalid ${type} value: ${value}`);\n                }\n                return parsed;\n            } else if (type === 'Decimal') {\n                try {\n                    return new Decimal(value);\n                } catch {\n                    throw new InvalidValueError(`invalid ${type} value: ${value}`);\n                }\n            } else if (type === 'Boolean') {\n                if (value === 'true') {\n                    return true;\n                } else if (value === 'false') {\n                    return false;\n                } else {\n                    throw new InvalidValueError(`invalid ${type} value: ${value}`);\n                }\n            }\n        }\n        return value;\n    }\n\n    private makeNormalizedUrl(path: string, query: Record<string, string | string[]> | undefined) {\n        const url = new URL(this.makeLinkUrl(path));\n        for (const [key, value] of Object.entries(query ?? {})) {\n            if (\n                key.startsWith('filter[') ||\n                key.startsWith('sort[') ||\n                key === 'include' ||\n                key.startsWith('include[') ||\n                key.startsWith('fields[')\n            ) {\n                for (const v of enumerate(value)) {\n                    url.searchParams.append(key, v);\n                }\n            }\n        }\n        return url.toString();\n    }\n\n    private getPagination(query: Record<string, string | string[]> | undefined) {\n        if (!query) {\n            return { offset: 0, limit: this.options.pageSize ?? DEFAULT_PAGE_SIZE };\n        }\n\n        let offset = 0;\n        if (query['page[offset]']) {\n            const value = query['page[offset]'];\n            const offsetText = Array.isArray(value) ? value[value.length - 1]! : value;\n            offset = parseInt(offsetText);\n            if (isNaN(offset) || offset < 0) {\n                offset = 0;\n            }\n        }\n\n        let pageSizeOption = this.options.pageSize ?? DEFAULT_PAGE_SIZE;\n        if (pageSizeOption <= 0) {\n            pageSizeOption = DEFAULT_PAGE_SIZE;\n        }\n\n        let limit = pageSizeOption;\n        if (query['page[limit]']) {\n            const value = query['page[limit]'];\n            const limitText = Array.isArray(value) ? value[value.length - 1]! : value;\n            limit = parseInt(limitText);\n            if (isNaN(limit) || limit <= 0) {\n                limit = pageSizeOption;\n            }\n            limit = Math.min(pageSizeOption, limit);\n        }\n\n        return { offset, limit };\n    }\n\n    private buildFilter(\n        type: string,\n        query: Record<string, string | string[]> | undefined,\n    ): { filter: any; error: any } {\n        if (!query) {\n            return { filter: undefined, error: undefined };\n        }\n\n        const typeInfo = this.getModelInfo(type);\n        if (!typeInfo) {\n            return { filter: undefined, error: this.makeUnsupportedModelError(type) };\n        }\n\n        const items: any[] = [];\n\n        for (const [key, value] of Object.entries(query)) {\n            if (!value) {\n                continue;\n            }\n\n            // try matching query parameter key as \"filter[x][y]...\"\n            const match = key.match(this.filterParamPattern);\n            if (!match || !match.groups || !match.groups['match']) {\n                continue;\n            }\n\n            const filterKeys = match.groups['match']\n                .replaceAll(/[[\\]]/g, ' ')\n                .split(' ')\n                .filter((i) => i);\n\n            if (!filterKeys.length) {\n                continue;\n            }\n\n            // turn filter into a nested query object\n\n            const item: any = {};\n            let curr = item;\n            let currType = typeInfo;\n\n            for (const filterValue of enumerate(value)) {\n                for (let i = 0; i < filterKeys.length; i++) {\n                    // extract filter operation from (optional) trailing $op\n                    let filterKey = filterKeys[i]!;\n                    let filterOp: FilterOperationType | undefined;\n                    const pos = filterKey.indexOf('$');\n                    if (pos > 0) {\n                        filterOp = filterKey.substring(pos + 1) as FilterOperationType;\n                        filterKey = filterKey.substring(0, pos);\n                    }\n\n                    if (!!filterOp && !FilterOperations.includes(filterOp)) {\n                        return {\n                            filter: undefined,\n                            error: this.makeError('invalidFilter', `invalid filter operation: ${filterOp}`),\n                        };\n                    }\n\n                    const idFields = this.getIdFields(currType.name);\n                    const fieldDef =\n                        filterKey === 'id'\n                            ? Object.values(currType.fields).find((f) => idFields.some((idf) => idf.name === f.name))\n                            : currType.fields[filterKey];\n                    if (!fieldDef) {\n                        return { filter: undefined, error: this.makeError('invalidFilter') };\n                    }\n\n                    if (!fieldDef.relation) {\n                        // regular field\n                        if (i !== filterKeys.length - 1) {\n                            // must be the last segment of a filter\n                            return { filter: undefined, error: this.makeError('invalidFilter') };\n                        }\n                        curr[fieldDef.name] = this.makeFilterValue(fieldDef, filterValue, filterOp);\n                    } else {\n                        // relation field\n                        if (i === filterKeys.length - 1) {\n                            curr[fieldDef.name] = this.makeFilterValue(fieldDef, filterValue, filterOp);\n                        } else {\n                            // keep going\n                            if (fieldDef.array) {\n                                // collection filtering implies \"some\" operation\n                                curr[fieldDef.name] = { some: {} };\n                                curr = curr[fieldDef.name].some;\n                            } else {\n                                curr = curr[fieldDef.name] = {};\n                            }\n                            currType = this.getModelInfo(fieldDef.type)!;\n                        }\n                    }\n                }\n                items.push(item);\n            }\n        }\n\n        if (items.length === 0) {\n            return { filter: undefined, error: undefined };\n        } else {\n            // combine filters with AND\n            return { filter: items.length === 1 ? items[0] : { AND: items }, error: undefined };\n        }\n    }\n\n    private buildSort(type: string, query: Record<string, string | string[]> | undefined) {\n        if (!query?.['sort']) {\n            return { sort: undefined, error: undefined };\n        }\n\n        const typeInfo = this.getModelInfo(type);\n        if (!typeInfo) {\n            return { sort: undefined, error: this.makeUnsupportedModelError(type) };\n        }\n\n        const result: any[] = [];\n\n        for (const sortSpec of enumerate(query['sort'])) {\n            const sortFields = sortSpec.split(',').filter((i) => i);\n\n            for (const sortField of sortFields) {\n                const dir = sortField.startsWith('-') ? 'desc' : 'asc';\n                const cleanedSortField = sortField.startsWith('-') ? sortField.substring(1) : sortField;\n                const parts = cleanedSortField.split('.').filter((i) => i);\n\n                const sortItem: any = {};\n                let curr = sortItem;\n                let currType = typeInfo;\n\n                for (let i = 0; i < parts.length; i++) {\n                    const part = parts[i]!;\n\n                    const fieldInfo = currType.fields[part];\n                    if (!fieldInfo || fieldInfo.array) {\n                        return {\n                            sort: undefined,\n                            error: this.makeError('invalidSort', 'sorting by array field is not supported'),\n                        };\n                    }\n\n                    if (i === parts.length - 1) {\n                        if (fieldInfo.relation) {\n                            // relation field: sort by id\n                            const relationType = this.getModelInfo(fieldInfo.type);\n                            if (!relationType) {\n                                return { sort: undefined, error: this.makeUnsupportedModelError(fieldInfo.type) };\n                            }\n                            curr[fieldInfo.name] = relationType.idFields.reduce((acc: any, idField: FieldDef) => {\n                                acc[idField.name] = dir;\n                                return acc;\n                            }, {});\n                        } else {\n                            // regular field\n                            curr[fieldInfo.name] = dir;\n                        }\n                    } else {\n                        if (!fieldInfo.relation) {\n                            // must be a relation field\n                            return {\n                                sort: undefined,\n                                error: this.makeError(\n                                    'invalidSort',\n                                    'intermediate sort segments must be relationships',\n                                ),\n                            };\n                        }\n                        // keep going\n                        curr = curr[fieldInfo.name] = {};\n                        currType = this.getModelInfo(fieldInfo.type)!;\n                        if (!currType) {\n                            return { sort: undefined, error: this.makeUnsupportedModelError(fieldInfo.type) };\n                        }\n                    }\n                }\n\n                result.push(sortItem);\n            }\n        }\n\n        return { sort: result, error: undefined };\n    }\n\n    private buildRelationSelect(\n        type: string,\n        include: string | string[],\n        query: Record<string, string | string[]> | undefined,\n    ) {\n        const typeInfo = this.getModelInfo(type);\n        if (!typeInfo) {\n            return { select: undefined, error: this.makeUnsupportedModelError(type) };\n        }\n\n        const result: any = {};\n        const allIncludes: string[] = [];\n\n        for (const includeItem of enumerate(include)) {\n            const inclusions = includeItem.split(',').filter((i) => i);\n            for (const inclusion of inclusions) {\n                allIncludes.push(inclusion);\n\n                const parts = inclusion.split('.');\n                let currPayload = result;\n                let currType = typeInfo;\n\n                for (let i = 0; i < parts.length; i++) {\n                    const relation = parts[i]!;\n                    const relationInfo = currType.relationships[relation];\n                    if (!relationInfo) {\n                        return { select: undefined, error: this.makeUnsupportedRelationshipError(type, relation, 400) };\n                    }\n\n                    currType = this.getModelInfo(relationInfo.type)!;\n                    if (!currType) {\n                        return { select: undefined, error: this.makeUnsupportedModelError(relationInfo.type) };\n                    }\n\n                    // handle partial results for requested type\n                    const { select, error } = this.buildPartialSelect(lowerCaseFirst(relationInfo.type), query);\n                    if (error) return { select: undefined, error };\n\n                    if (i !== parts.length - 1) {\n                        if (select) {\n                            currPayload[relation] = { select: { ...select } };\n                            currPayload = currPayload[relation].select;\n                        } else {\n                            currPayload[relation] = { include: { ...currPayload[relation]?.include } };\n                            currPayload = currPayload[relation].include;\n                        }\n                    } else {\n                        currPayload[relation] = select\n                            ? {\n                                  select: { ...select },\n                              }\n                            : true;\n                    }\n                }\n            }\n        }\n\n        return { select: result, error: undefined, allIncludes };\n    }\n\n    private makeFilterValue(fieldDef: FieldDef, value: string, op: FilterOperationType): any {\n        // TODO: inequality filters?\n        if (fieldDef.relation) {\n            // relation filter is converted to an ID filter\n            const info = this.getModelInfo(fieldDef.type)!;\n            if (fieldDef.array) {\n                // filtering a to-many relation, imply 'some' operator\n                const values = value.split(',').filter((i) => i);\n                const filterValue =\n                    values.length > 1\n                        ? { OR: values.map((v) => this.makeIdFilter(info.idFields, v, false)) }\n                        : this.makeIdFilter(info.idFields, value, false);\n                return { some: filterValue };\n            } else {\n                const values = value.split(',').filter((i) => i);\n                if (values.length > 1) {\n                    return { OR: values.map((v) => this.makeIdFilter(info.idFields, v, false)) };\n                } else {\n                    return { is: this.makeIdFilter(info.idFields, value, false) };\n                }\n            }\n        } else {\n            if (op === 'between') {\n                const parts = value.split(',').map((v) => this.coerce(fieldDef, v));\n                if (parts.length !== 2) {\n                    throw new InvalidValueError(`\"between\" expects exactly 2 comma-separated values`);\n                }\n                return { between: [parts[0]!, parts[1]!] };\n            }\n            const coerced = this.coerce(fieldDef, value);\n            switch (op) {\n                case 'icontains':\n                    return { contains: coerced, mode: 'insensitive' };\n                case 'hasSome':\n                case 'hasEvery': {\n                    const values = value\n                        .split(',')\n                        .filter((i) => i)\n                        .map((v) => this.coerce(fieldDef, v));\n                    return { [op]: values };\n                }\n                case 'isEmpty':\n                    if (value !== 'true' && value !== 'false') {\n                        throw new InvalidValueError(`Not a boolean: ${value}`);\n                    }\n                    return { isEmpty: value === 'true' ? true : false };\n                default:\n                    if (op === undefined) {\n                        if (fieldDef.attributes?.some((attr) => attr.name === '@json')) {\n                            // handle JSON value equality filter\n                            return { equals: coerced };\n                        }\n\n                        // regular filter, split value by comma\n                        const values = value\n                            .split(',')\n                            .filter((i) => i)\n                            .map((v) => this.coerce(fieldDef, v));\n                        return values.length > 1 ? { in: values } : { equals: values[0] };\n                    } else {\n                        return { [op]: coerced };\n                    }\n            }\n        }\n    }\n\n    private injectRelationQuery(\n        type: string,\n        injectTarget: any,\n        injectKey: string,\n        query: Record<string, string | string[]> | undefined,\n    ) {\n        const { filter, error: filterError } = this.buildFilter(type, query);\n        if (filterError) {\n            return filterError;\n        }\n\n        if (filter) {\n            injectTarget[injectKey] = { ...injectTarget[injectKey], where: filter };\n        }\n\n        const { sort, error: sortError } = this.buildSort(type, query);\n        if (sortError) {\n            return sortError;\n        }\n        if (sort) {\n            injectTarget[injectKey] = { ...injectTarget[injectKey], orderBy: sort };\n        }\n\n        const pagination = this.getPagination(query);\n        const offset = pagination.offset;\n        if (offset > 0) {\n            // inject skip\n            injectTarget[injectKey] = { ...injectTarget[injectKey], skip: offset };\n        }\n        const limit = pagination.limit;\n        if (limit !== Infinity) {\n            // inject take\n            injectTarget[injectKey] = { ...injectTarget[injectKey], take: limit };\n\n            // include a count query  for the relationship\n            injectTarget._count = { select: { [injectKey]: true } };\n        }\n    }\n\n    private handleORMError(err: ORMError) {\n        return match(err.reason)\n            .with(ORMErrorReason.INVALID_INPUT, () => {\n                return this.makeError('validationError', err.message, 422);\n            })\n            .with(ORMErrorReason.REJECTED_BY_POLICY, () => {\n                return this.makeError('forbidden', err.message, 403, { reason: err.rejectedByPolicyReason });\n            })\n            .with(ORMErrorReason.NOT_FOUND, () => {\n                return this.makeError('notFound', err.message, 404);\n            })\n            .with(ORMErrorReason.DB_QUERY_ERROR, () => {\n                return this.makeError('queryError', err.message, 400, {\n                    dbErrorCode: err.dbErrorCode,\n                });\n            })\n            .otherwise(() => {\n                return this.makeError('unknownError', err.message);\n            });\n    }\n\n    private makeError(\n        code: keyof typeof this.errors,\n        detail?: string,\n        status?: number,\n        otherFields: Record<string, any> = {},\n    ) {\n        status = status ?? this.errors[code]?.status ?? 500;\n        const error: any = {\n            status,\n            code: paramCase(code),\n            title: this.errors[code]?.title,\n        };\n\n        if (detail) {\n            error.detail = detail;\n        }\n\n        Object.assign(error, otherFields);\n\n        return {\n            status,\n            body: {\n                errors: [error],\n            },\n        };\n    }\n\n    private makeUnsupportedModelError(model: string) {\n        return this.makeError('unsupportedModel', `Model ${model} doesn't exist`);\n    }\n\n    private makeUnsupportedRelationshipError(model: string, relationship: string, status: number) {\n        return this.makeError('unsupportedRelationship', `Relationship ${model}.${relationship} doesn't exist`, status);\n    }\n\n    //#endregion\n\n    async generateSpec(options?: OpenApiSpecOptions) {\n        const generator = new RestApiSpecGenerator(this.options);\n        return generator.generateSpec(options);\n    }\n}\n\nexport { RestApiSpecGenerator } from './openapi';\n","import { lowerCaseFirst, safeJSONStringify } from '@zenstackhq/common-helpers';\nimport { CoreCrudOperations, ORMError, ORMErrorReason, type ClientContract } from '@zenstackhq/orm';\nimport type { SchemaDef } from '@zenstackhq/orm/schema';\nimport SuperJSON from 'superjson';\nimport { match } from 'ts-pattern';\nimport z from 'zod';\nimport { fromError } from 'zod-validation-error/v4';\nimport type { ApiHandler, LogConfig, RequestContext, Response } from '../../types';\nimport { getProcedureDef, mapProcedureArgs, PROCEDURE_ROUTE_PREFIXES } from '../common/procedures';\nimport { loggerSchema, queryOptionsSchema } from '../common/schemas';\nimport type { CommonHandlerOptions, OpenApiSpecGenerator, OpenApiSpecOptions } from '../common/types';\nimport { processSuperJsonRequestPayload, unmarshalQ } from '../common/utils';\nimport { log, registerCustomSerializers } from '../utils';\n\nconst TRANSACTION_ROUTE_PREFIX = '$transaction' as const;\nconst VALID_OPS = new Set(CoreCrudOperations as unknown as string[]);\n\nregisterCustomSerializers();\n\n/**\n * Options for {@link RPCApiHandler}\n */\nexport type RPCApiHandlerOptions<Schema extends SchemaDef = SchemaDef> = {\n    /**\n     * The schema\n     */\n    schema: Schema;\n\n    /**\n     * Logging configuration\n     */\n    log?: LogConfig;\n} & CommonHandlerOptions<Schema>;\n\n/**\n * RPC style API request handler that mirrors the ZenStackClient API\n */\nexport class RPCApiHandler<Schema extends SchemaDef = SchemaDef> implements ApiHandler<Schema>, OpenApiSpecGenerator {\n    constructor(private readonly options: RPCApiHandlerOptions<Schema>) {\n        this.validateOptions(options);\n    }\n\n    private validateOptions(options: RPCApiHandlerOptions<Schema>) {\n        const schema = z.strictObject({\n            schema: z.object(),\n            log: loggerSchema.optional(),\n            queryOptions: queryOptionsSchema.optional(),\n        });\n        const parseResult = schema.safeParse(options);\n        if (!parseResult.success) {\n            throw new Error(`Invalid options: ${fromError(parseResult.error)}`);\n        }\n    }\n\n    get schema(): Schema {\n        return this.options.schema;\n    }\n\n    get log(): LogConfig | undefined {\n        return this.options.log;\n    }\n\n    async handleRequest({ client, method, path, query, requestBody }: RequestContext<Schema>): Promise<Response> {\n        const parts = path.split('/').filter((p) => !!p);\n        const op = parts.pop();\n        let model = parts.pop();\n\n        if (parts.length !== 0 || !op || !model) {\n            return this.makeBadInputErrorResponse('invalid request path');\n        }\n\n        if (model === PROCEDURE_ROUTE_PREFIXES) {\n            return this.handleProcedureRequest({\n                client,\n                method: method.toUpperCase(),\n                proc: op,\n                query,\n                requestBody,\n            });\n        }\n\n        if (model === TRANSACTION_ROUTE_PREFIX) {\n            return this.handleTransaction({\n                client,\n                method: method.toUpperCase(),\n                type: op,\n                requestBody,\n            });\n        }\n\n        model = lowerCaseFirst(model);\n        method = method.toUpperCase();\n        let args: unknown;\n        let resCode = 200;\n\n        switch (op) {\n            case 'create':\n            case 'createMany':\n            case 'createManyAndReturn':\n            case 'upsert':\n                if (method !== 'POST') {\n                    return this.makeBadInputErrorResponse('invalid request method, only POST is supported');\n                }\n                if (!requestBody) {\n                    return this.makeBadInputErrorResponse('missing request body');\n                }\n\n                args = requestBody;\n                resCode = 201;\n                break;\n\n            case 'findFirst':\n            case 'findUnique':\n            case 'findMany':\n            case 'aggregate':\n            case 'groupBy':\n            case 'count':\n            case 'exists':\n                if (method !== 'GET') {\n                    return this.makeBadInputErrorResponse('invalid request method, only GET is supported');\n                }\n                try {\n                    args = query?.['q'] ? unmarshalQ(query['q'] as string, query['meta'] as string | undefined) : {};\n                } catch {\n                    return this.makeBadInputErrorResponse('invalid \"q\" query parameter');\n                }\n                break;\n\n            case 'update':\n            case 'updateMany':\n            case 'updateManyAndReturn':\n                if (method !== 'PUT' && method !== 'PATCH') {\n                    return this.makeBadInputErrorResponse('invalid request method, only PUT or PATCH are supported');\n                }\n                if (!requestBody) {\n                    return this.makeBadInputErrorResponse('missing request body');\n                }\n\n                args = requestBody;\n                break;\n\n            case 'delete':\n            case 'deleteMany':\n                if (method !== 'DELETE') {\n                    return this.makeBadInputErrorResponse('invalid request method, only DELETE is supported');\n                }\n                try {\n                    args = query?.['q'] ? unmarshalQ(query['q'] as string, query['meta'] as string | undefined) : {};\n                } catch (err) {\n                    return this.makeBadInputErrorResponse(\n                        err instanceof Error ? err.message : 'invalid \"q\" query parameter',\n                    );\n                }\n                break;\n\n            default:\n                return this.makeBadInputErrorResponse('invalid operation: ' + op);\n        }\n\n        const { result: processedArgs, error } = await this.processRequestPayload(args);\n        if (error) {\n            return this.makeBadInputErrorResponse(error);\n        }\n\n        try {\n            if (!this.isValidModel(client, model)) {\n                return this.makeBadInputErrorResponse(`unknown model name: ${model}`);\n            }\n\n            log(\n                this.options.log,\n                'debug',\n                () => `handling \"${model}.${op}\" request with args: ${safeJSONStringify(processedArgs)}`,\n            );\n\n            const clientResult = await (client as any)[model][op](processedArgs);\n            let responseBody: any = { data: clientResult };\n\n            // superjson serialize response\n            if (clientResult) {\n                const { json, meta } = SuperJSON.serialize(clientResult);\n                responseBody = { data: json };\n                if (meta) {\n                    responseBody.meta = { serialization: meta };\n                }\n            }\n\n            const response = { status: resCode, body: responseBody };\n            log(\n                this.options.log,\n                'debug',\n                () => `sending response for \"${model}.${op}\" request: ${safeJSONStringify(response)}`,\n            );\n            return response;\n        } catch (err) {\n            log(this.options.log, 'error', `error occurred when handling \"${model}.${op}\" request`, err);\n            if (err instanceof ORMError) {\n                return this.makeORMErrorResponse(err);\n            } else {\n                return this.makeGenericErrorResponse(err);\n            }\n        }\n    }\n\n    private async handleTransaction({\n        client,\n        method,\n        type,\n        requestBody,\n    }: {\n        client: ClientContract<Schema>;\n        method: string;\n        type: string;\n        requestBody?: unknown;\n    }): Promise<Response> {\n        if (method !== 'POST') {\n            return this.makeBadInputErrorResponse('invalid request method, only POST is supported');\n        }\n\n        if (type !== 'sequential') {\n            return this.makeBadInputErrorResponse(`unsupported transaction type: ${type}`);\n        }\n\n        if (!requestBody || !Array.isArray(requestBody) || requestBody.length === 0) {\n            return this.makeBadInputErrorResponse('request body must be a non-empty array of operations');\n        }\n\n        const processedOps: Array<{ model: string; op: string; args: unknown }> = [];\n\n        for (let i = 0; i < requestBody.length; i++) {\n            const item = requestBody[i];\n            if (!item || typeof item !== 'object') {\n                return this.makeBadInputErrorResponse(`operation at index ${i} must be an object`);\n            }\n            const { model: itemModel, op: itemOp, args: itemArgs } = item as any;\n            if (!itemModel || typeof itemModel !== 'string') {\n                return this.makeBadInputErrorResponse(`operation at index ${i} is missing a valid \"model\" field`);\n            }\n            if (!itemOp || typeof itemOp !== 'string') {\n                return this.makeBadInputErrorResponse(`operation at index ${i} is missing a valid \"op\" field`);\n            }\n            if (!VALID_OPS.has(itemOp)) {\n                return this.makeBadInputErrorResponse(`operation at index ${i} has invalid op: ${itemOp}`);\n            }\n            if (!this.isValidModel(client, lowerCaseFirst(itemModel))) {\n                return this.makeBadInputErrorResponse(`operation at index ${i} has unknown model: ${itemModel}`);\n            }\n            if (\n                itemArgs !== undefined &&\n                itemArgs !== null &&\n                (typeof itemArgs !== 'object' || Array.isArray(itemArgs))\n            ) {\n                return this.makeBadInputErrorResponse(`operation at index ${i} has invalid \"args\" field`);\n            }\n\n            const { result: processedArgs, error: argsError } = await this.processRequestPayload(itemArgs ?? {});\n            if (argsError) {\n                return this.makeBadInputErrorResponse(`operation at index ${i}: ${argsError}`);\n            }\n            processedOps.push({ model: lowerCaseFirst(itemModel), op: itemOp, args: processedArgs });\n        }\n\n        try {\n            const promises = processedOps.map(({ model, op, args }) => {\n                return (client as any)[model][op](args);\n            });\n\n            log(this.options.log, 'debug', () => `handling \"$transaction\" request with ${promises.length} operations`);\n\n            const clientResult = await client.$transaction(promises as any);\n\n            const { json, meta } = SuperJSON.serialize(clientResult);\n            const responseBody: any = { data: json };\n            if (meta) {\n                responseBody.meta = { serialization: meta };\n            }\n\n            const response = { status: 200, body: responseBody };\n            log(\n                this.options.log,\n                'debug',\n                () => `sending response for \"$transaction\" request: ${safeJSONStringify(response)}`,\n            );\n            return response;\n        } catch (err) {\n            log(this.options.log, 'error', `error occurred when handling \"$transaction\" request`, err);\n            if (err instanceof ORMError) {\n                return this.makeORMErrorResponse(err);\n            }\n            return this.makeGenericErrorResponse(err);\n        }\n    }\n\n    private async handleProcedureRequest({\n        client,\n        method,\n        proc,\n        query,\n        requestBody,\n    }: {\n        client: ClientContract<Schema>;\n        method: string;\n        proc?: string;\n        query?: Record<string, string | string[]>;\n        requestBody?: unknown;\n    }): Promise<Response> {\n        if (!proc) {\n            return this.makeBadInputErrorResponse('missing procedure name');\n        }\n\n        const procDef = getProcedureDef(this.options.schema, proc);\n        if (!procDef) {\n            return this.makeBadInputErrorResponse(`unknown procedure: ${proc}`);\n        }\n\n        const isMutation = !!procDef.mutation;\n\n        if (isMutation) {\n            if (method !== 'POST') {\n                return this.makeBadInputErrorResponse('invalid request method, only POST is supported');\n            }\n        } else {\n            if (method !== 'GET') {\n                return this.makeBadInputErrorResponse('invalid request method, only GET is supported');\n            }\n        }\n\n        let argsPayload = method === 'POST' ? requestBody : undefined;\n        if (method === 'GET') {\n            try {\n                argsPayload = query?.['q']\n                    ? unmarshalQ(query['q'] as string, query['meta'] as string | undefined)\n                    : undefined;\n            } catch (err) {\n                return this.makeBadInputErrorResponse(\n                    err instanceof Error ? err.message : 'invalid \"q\" query parameter',\n                );\n            }\n        }\n\n        const { result: processedArgsPayload, error } = await processSuperJsonRequestPayload(argsPayload);\n        if (error) {\n            return this.makeBadInputErrorResponse(error);\n        }\n\n        let procInput: unknown;\n        try {\n            procInput = mapProcedureArgs(procDef, processedArgsPayload);\n        } catch (err) {\n            return this.makeBadInputErrorResponse(err instanceof Error ? err.message : 'invalid procedure arguments');\n        }\n\n        try {\n            log(this.options.log, 'debug', () => `handling \"$procs.${proc}\" request`);\n\n            const clientResult = await (client as any).$procs?.[proc](procInput);\n\n            const { json, meta } = SuperJSON.serialize(clientResult);\n            const responseBody: any = { data: json };\n            if (meta) {\n                responseBody.meta = { serialization: meta };\n            }\n\n            const response = { status: 200, body: responseBody };\n            log(\n                this.options.log,\n                'debug',\n                () => `sending response for \"$procs.${proc}\" request: ${safeJSONStringify(response)}`,\n            );\n            return response;\n        } catch (err) {\n            log(this.options.log, 'error', `error occurred when handling \"$procs.${proc}\" request`, err);\n            if (err instanceof ORMError) {\n                return this.makeORMErrorResponse(err);\n            }\n            return this.makeGenericErrorResponse(err);\n        }\n    }\n\n    private isValidModel(client: ClientContract<Schema>, model: string) {\n        return Object.keys(client.$schema.models).some((m) => lowerCaseFirst(m) === lowerCaseFirst(model));\n    }\n\n    private makeBadInputErrorResponse(message: string) {\n        const resp = {\n            status: 400,\n            body: { error: { message } },\n        };\n        log(this.options.log, 'debug', () => `sending error response: ${safeJSONStringify(resp)}`);\n        return resp;\n    }\n\n    private makeGenericErrorResponse(err: unknown) {\n        const resp = {\n            status: 500,\n            body: { error: { message: err instanceof Error ? err.message : 'unknown error' } },\n        };\n        log(\n            this.options.log,\n            'debug',\n            () => `sending error response: ${safeJSONStringify(resp)}${err instanceof Error ? '\\n' + err.stack : ''}`,\n        );\n        return resp;\n    }\n\n    private makeORMErrorResponse(err: ORMError) {\n        let status = 400;\n        const error: any = { message: err.message, reason: err.reason };\n\n        match(err.reason)\n            .with(ORMErrorReason.NOT_FOUND, () => {\n                status = 404;\n                error.model = err.model;\n            })\n            .with(ORMErrorReason.INVALID_INPUT, () => {\n                status = 422;\n                error.rejectedByValidation = true;\n                error.model = err.model;\n            })\n            .with(ORMErrorReason.REJECTED_BY_POLICY, () => {\n                status = 403;\n                error.rejectedByPolicy = true;\n                error.model = err.model;\n                error.rejectReason = err.rejectedByPolicyReason;\n            })\n            .with(ORMErrorReason.DB_QUERY_ERROR, () => {\n                status = 400;\n                error.dbErrorCode = err.dbErrorCode;\n            })\n            .otherwise(() => {});\n\n        const resp = { status, body: { error } };\n        log(this.options.log, 'debug', () => `sending error response: ${safeJSONStringify(resp)}`);\n        return resp;\n    }\n\n    async generateSpec(options?: OpenApiSpecOptions) {\n        const { RPCApiSpecGenerator } = await import('./openapi');\n        const generator = new RPCApiSpecGenerator(this.options);\n        return generator.generateSpec(options);\n    }\n\n    private async processRequestPayload(args: any) {\n        const { meta, ...rest } = args ?? {};\n        if (meta?.serialization) {\n            try {\n                // superjson deserialization\n                args = SuperJSON.deserialize({ json: rest, meta: meta.serialization });\n            } catch (err) {\n                return { result: undefined, error: `failed to deserialize request payload: ${(err as Error).message}` };\n            }\n        } else {\n            // drop meta when no serialization info is present\n            args = rest;\n        }\n        return { result: args, error: undefined };\n    }\n}\n"],"mappings":"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"}