From 59e3c3a4d836689c13091c914986ce57772abf5f Mon Sep 17 00:00:00 2001 From: ymc9 <104139426+ymc9@users.noreply.github.com> Date: Wed, 18 Mar 2026 22:01:53 -0700 Subject: [PATCH 01/16] feat(server): add OpenAPI spec generation with filter kind slicing support Refactor REST and RPC API handlers to extract OpenAPI spec generation into dedicated classes (RestApiSpecGenerator, RPCApiSpecGenerator). Add support for queryOptions.slicing.fields with includedFilterKinds/excludedFilterKinds to control which filter operators appear in generated specs. REST generator controls individual filter query parameters; RPC generator controls per-operator properties in WhereInput schemas. Co-Authored-By: Claude Opus 4.6 --- packages/server/package.json | 1 + packages/server/src/api/common/spec-utils.ts | 98 + packages/server/src/api/common/types.ts | 32 + packages/server/src/api/index.ts | 1 + packages/server/src/api/rest/handler.ts | 2210 +++++++ packages/server/src/api/rest/index.ts | 2206 +------ packages/server/src/api/rest/openapi.ts | 926 +++ packages/server/src/api/rpc/handler.ts | 458 ++ packages/server/src/api/rpc/index.ts | 445 +- packages/server/src/api/rpc/openapi.ts | 768 +++ .../openapi/baseline/rest-3.1.0.baseline.yaml | 3279 +++++++++ .../rest-type-coverage-3.1.0.baseline.yaml | 876 +++ .../baseline/rpc-3.1.0-omit.baseline.yaml | 3058 +++++++++ .../openapi/baseline/rpc-3.1.0.baseline.yaml | 5853 +++++++++++++++++ .../rpc-type-coverage-3.1.0.baseline.yaml | 3174 +++++++++ .../baseline/rest-3.1.0.baseline.yaml | 3279 +++++++++ .../rest-type-coverage-3.1.0.baseline.yaml | 876 +++ .../baseline/rpc-3.1.0-omit.baseline.yaml | 3058 +++++++++ .../migrated/baseline/rpc-3.1.0.baseline.yaml | 5853 +++++++++++++++++ .../rpc-type-coverage-3.1.0.baseline.yaml | 3174 +++++++++ .../openapi/migrated/rest-migrated.test.ts | 220 + .../openapi/migrated/rpc-migrated.test.ts | 198 + .../server/test/openapi/rest-openapi.test.ts | 462 ++ .../server/test/openapi/rpc-openapi.test.ts | 445 ++ pnpm-lock.yaml | 10 +- 25 files changed, 38310 insertions(+), 2650 deletions(-) create mode 100644 packages/server/src/api/common/spec-utils.ts create mode 100644 packages/server/src/api/common/types.ts create mode 100644 packages/server/src/api/rest/handler.ts create mode 100644 packages/server/src/api/rest/openapi.ts create mode 100644 packages/server/src/api/rpc/handler.ts create mode 100644 packages/server/src/api/rpc/openapi.ts create mode 100644 packages/server/test/openapi/baseline/rest-3.1.0.baseline.yaml create mode 100644 packages/server/test/openapi/baseline/rest-type-coverage-3.1.0.baseline.yaml create mode 100644 packages/server/test/openapi/baseline/rpc-3.1.0-omit.baseline.yaml create mode 100644 packages/server/test/openapi/baseline/rpc-3.1.0.baseline.yaml create mode 100644 packages/server/test/openapi/baseline/rpc-type-coverage-3.1.0.baseline.yaml create mode 100644 packages/server/test/openapi/migrated/baseline/rest-3.1.0.baseline.yaml create mode 100644 packages/server/test/openapi/migrated/baseline/rest-type-coverage-3.1.0.baseline.yaml create mode 100644 packages/server/test/openapi/migrated/baseline/rpc-3.1.0-omit.baseline.yaml create mode 100644 packages/server/test/openapi/migrated/baseline/rpc-3.1.0.baseline.yaml create mode 100644 packages/server/test/openapi/migrated/baseline/rpc-type-coverage-3.1.0.baseline.yaml create mode 100644 packages/server/test/openapi/migrated/rest-migrated.test.ts create mode 100644 packages/server/test/openapi/migrated/rpc-migrated.test.ts create mode 100644 packages/server/test/openapi/rest-openapi.test.ts create mode 100644 packages/server/test/openapi/rpc-openapi.test.ts diff --git a/packages/server/package.json b/packages/server/package.json index 1f2acd1ce..b4904c31e 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -124,6 +124,7 @@ "@zenstackhq/common-helpers": "workspace:*", "@zenstackhq/orm": "workspace:*", "decimal.js": "catalog:", + "openapi-types": "^12.1.3", "superjson": "^2.2.3", "ts-japi": "^1.12.1", "ts-pattern": "catalog:", diff --git a/packages/server/src/api/common/spec-utils.ts b/packages/server/src/api/common/spec-utils.ts new file mode 100644 index 000000000..daaffd361 --- /dev/null +++ b/packages/server/src/api/common/spec-utils.ts @@ -0,0 +1,98 @@ +import { lowerCaseFirst } from '@zenstackhq/common-helpers'; +import type { QueryOptions } from '@zenstackhq/orm'; +import type { SchemaDef } from '@zenstackhq/orm/schema'; + +/** + * Checks if a model is included based on slicing options. + */ +export function isModelIncluded(modelName: string, queryOptions?: QueryOptions): boolean { + const slicing = queryOptions?.slicing; + if (!slicing) return true; + + const excluded = slicing.excludedModels as readonly string[] | undefined; + if (excluded?.includes(modelName)) return false; + + const included = slicing.includedModels as readonly string[] | undefined; + if (included && !included.includes(modelName)) return false; + + return true; +} + +/** + * Checks if a CRUD operation is included for a model based on slicing options. + */ +export function isOperationIncluded(modelName: string, op: string, queryOptions?: QueryOptions): boolean { + const slicing = queryOptions?.slicing; + if (!slicing?.models) return true; + + const modelKey = lowerCaseFirst(modelName); + const modelSlicing = (slicing.models as Record)[modelKey] ?? (slicing.models as any).$all; + if (!modelSlicing) return true; + + const excluded = modelSlicing.excludedOperations as readonly string[] | undefined; + if (excluded?.includes(op)) return false; + + const included = modelSlicing.includedOperations as readonly string[] | undefined; + if (included && !included.includes(op)) return false; + + return true; +} + +/** + * Checks if a procedure is included based on slicing options. + */ +export function isProcedureIncluded(procName: string, queryOptions?: QueryOptions): boolean { + const slicing = queryOptions?.slicing; + if (!slicing) return true; + + const excluded = slicing.excludedProcedures as readonly string[] | undefined; + if (excluded?.includes(procName)) return false; + + const included = slicing.includedProcedures as readonly string[] | undefined; + if (included && !included.includes(procName)) return false; + + return true; +} + +/** + * Checks if a field should be omitted from the output schema based on queryOptions.omit. + */ +export function isFieldOmitted(modelName: string, fieldName: string, queryOptions?: QueryOptions): boolean { + const omit = queryOptions?.omit as Record> | undefined; + return omit?.[modelName]?.[fieldName] === true; +} + +/** + * Returns the list of model names from the schema that pass the slicing filter. + */ +export function getIncludedModels(schema: SchemaDef, queryOptions?: QueryOptions): string[] { + return Object.keys(schema.models).filter((name) => isModelIncluded(name, queryOptions)); +} + +/** + * Checks if a filter kind is allowed for a specific field based on slicing options. + */ +export function isFilterKindIncluded( + modelName: string, + fieldName: string, + filterKind: string, + queryOptions?: QueryOptions, +): boolean { + const slicing = queryOptions?.slicing; + if (!slicing?.models) return true; + + const modelKey = lowerCaseFirst(modelName); + const modelSlicing = (slicing.models as Record)[modelKey] ?? (slicing.models as any).$all; + if (!modelSlicing?.fields) return true; + + const fieldSlicing = modelSlicing.fields[fieldName] ?? modelSlicing.fields.$all; + if (!fieldSlicing) return true; + + const excluded = fieldSlicing.excludedFilterKinds as readonly string[] | undefined; + if (excluded?.includes(filterKind)) return false; + + const included = fieldSlicing.includedFilterKinds as readonly string[] | undefined; + if (included && !included.includes(filterKind)) return false; + + return true; +} diff --git a/packages/server/src/api/common/types.ts b/packages/server/src/api/common/types.ts new file mode 100644 index 000000000..167ca17e5 --- /dev/null +++ b/packages/server/src/api/common/types.ts @@ -0,0 +1,32 @@ +import type { QueryOptions } from '@zenstackhq/orm'; +import type { SchemaDef } from '@zenstackhq/orm/schema'; +import type { OpenAPIV3_1 } from 'openapi-types'; + +export type CommonHandlerOptions = { + /** Query options that affect the behavior of the OpenAPI provider. */ + queryOptions?: QueryOptions; +}; + +export type OpenApiSpecOptions = { + /** Spec title. Defaults to 'ZenStack Generated API' */ + title?: string; + + /** Spec version. Defaults to '1.0.0' */ + version?: string; + + /** Spec description. */ + description?: string; + + /** Spec summary. */ + summary?: string; +}; + +/** + * Interface for generating OpenAPI specifications. + */ +export interface OpenApiSpecGenerator { + /** + * Generates an OpenAPI v3.1 specification document. + */ + generateSpec(options?: OpenApiSpecOptions): Promise; +} diff --git a/packages/server/src/api/index.ts b/packages/server/src/api/index.ts index 09d9700eb..3efdc460b 100644 --- a/packages/server/src/api/index.ts +++ b/packages/server/src/api/index.ts @@ -1,2 +1,3 @@ export { RestApiHandler, type RestApiHandlerOptions } from './rest'; export { RPCApiHandler, type RPCApiHandlerOptions } from './rpc'; +export type { OpenApiSpecGenerator, OpenApiSpecOptions } from './common/types'; diff --git a/packages/server/src/api/rest/handler.ts b/packages/server/src/api/rest/handler.ts new file mode 100644 index 000000000..7d2c676b8 --- /dev/null +++ b/packages/server/src/api/rest/handler.ts @@ -0,0 +1,2210 @@ +import { clone, enumerate, lowerCaseFirst, paramCase } from '@zenstackhq/common-helpers'; +import { ORMError, ORMErrorReason, type ClientContract } from '@zenstackhq/orm'; +import type { FieldDef, ModelDef, SchemaDef } from '@zenstackhq/orm/schema'; +import { Decimal } from 'decimal.js'; +import SuperJSON from 'superjson'; +import tsjapi, { type Linker, type Paginator, type Relator, type Serializer, type SerializerOptions } from 'ts-japi'; +import { match } from 'ts-pattern'; +import UrlPattern from 'url-pattern'; +import z from 'zod'; +import { fromError } from 'zod-validation-error/v4'; +import type { ApiHandler, LogConfig, RequestContext, Response } from '../../types'; +import { getProcedureDef, mapProcedureArgs } from '../common/procedures'; +import { loggerSchema } from '../common/schemas'; +import type { CommonHandlerOptions, OpenApiSpecGenerator, OpenApiSpecOptions } from '../common/types'; +import { processSuperJsonRequestPayload } from '../common/utils'; +import { getZodErrorMessage, log, registerCustomSerializers } from '../utils'; +import { RestApiSpecGenerator } from './openapi'; + +/** + * Options for {@link RestApiHandler} + */ +export type RestApiHandlerOptions = { + /** + * The schema + */ + schema: Schema; + + /** + * Logging configuration + */ + log?: LogConfig; + + /** + * The base endpoint of the RESTful API, must be a valid URL + */ + endpoint: string; + + /** + * The default page size for limiting the number of results returned + * from collection queries, including resource collection, related data + * of collection types, and relationship of collection types. + * + * Defaults to 100. Set to Infinity to disable pagination. + */ + pageSize?: number; + + /** + * The divider used to separate compound ID fields in the URL. + * Defaults to '_'. + */ + idDivider?: string; + + /** + * The charset used for URL segment values. Defaults to `a-zA-Z0-9-_~ %`. You can change it if your entity's ID values + * allow different characters. Specifically, if your models use compound IDs and the idDivider is set to a different value, + * it should be included in the charset. + */ + urlSegmentCharset?: string; + + /** + * Mapping from model names to URL segment names. + */ + modelNameMapping?: Record; + + /** + * Mapping from model names to unique field name to be used as resource's ID. + */ + externalIdMapping?: Record; +} & CommonHandlerOptions; + +type RelationshipInfo = { + type: string; + idFields: FieldDef[]; + isCollection: boolean; + isOptional: boolean; +}; + +type ModelInfo = { + name: string; + idFields: FieldDef[]; + fields: Record; + relationships: Record; +}; + +type Match = { + type: string; + id: string; + relationship: string; +}; + +enum UrlPatterns { + SINGLE = 'single', + FETCH_RELATIONSHIP = 'fetchRelationship', + RELATIONSHIP = 'relationship', + COLLECTION = 'collection', +} + +class InvalidValueError extends Error { + constructor(message: string) { + super(message); + } +} + +const DEFAULT_PAGE_SIZE = 100; + +const FilterOperations = [ + 'lt', + 'lte', + 'gt', + 'gte', + 'between', + 'contains', + 'icontains', + 'search', + 'startsWith', + 'endsWith', + 'has', + 'hasEvery', + 'hasSome', + 'isEmpty', +] as const; + +type FilterOperationType = (typeof FilterOperations)[number] | undefined; + +const DEFAULT_ID_DIVIDER = '_'; + +registerCustomSerializers(); + +/** + * RESTful-style API request handler (compliant with JSON:API) + */ +export class RestApiHandler implements ApiHandler, OpenApiSpecGenerator { + // resource serializers + private serializers = new Map(); + + // error responses + private readonly errors: Record = { + unsupportedModel: { + status: 404, + title: 'Unsupported model type', + detail: 'The model type is not supported', + }, + unsupportedRelationship: { + status: 400, + title: 'Unsupported relationship', + detail: 'The relationship is not supported', + }, + invalidPath: { + status: 400, + title: 'The request path is invalid', + }, + invalidVerb: { + status: 400, + title: 'The HTTP verb is not supported', + }, + notFound: { + status: 404, + title: 'Resource not found', + }, + noId: { + status: 400, + title: 'Model without an ID field is not supported', + }, + invalidId: { + status: 400, + title: 'Resource ID is invalid', + }, + invalidPayload: { + status: 400, + title: 'Invalid payload', + }, + invalidRelationData: { + status: 400, + title: 'Invalid relation data', + detail: 'Invalid relationship data', + }, + invalidRelation: { + status: 400, + title: 'Invalid relation', + detail: 'Invalid relationship', + }, + invalidFilter: { + status: 400, + title: 'Invalid filter', + }, + invalidSort: { + status: 400, + title: 'Invalid sort', + }, + invalidValue: { + status: 400, + title: 'Invalid value for type', + }, + duplicatedFieldsParameter: { + status: 400, + title: 'Fields Parameter Duplicated', + }, + forbidden: { + status: 403, + title: 'Operation is forbidden', + }, + validationError: { + status: 422, + title: 'Operation is unprocessable due to validation errors', + }, + queryError: { + status: 400, + title: 'Error occurred while executing the query', + }, + unknownError: { + status: 500, + title: 'Unknown error', + }, + }; + + private filterParamPattern = new RegExp(/^filter(?(\[[^[\]]+\])+)$/); + + // zod schema for payload of creating and updating a resource + private createUpdatePayloadSchema = z + .object({ + data: z.object({ + type: z.string(), + attributes: z.object({}).passthrough().optional(), + relationships: z + .record( + z.string(), + z.object({ + data: z.union([ + z.object({ type: z.string(), id: z.union([z.string(), z.number()]) }), + z.array(z.object({ type: z.string(), id: z.union([z.string(), z.number()]) })), + ]), + }), + ) + .optional(), + }), + meta: z.object({}).passthrough().optional(), + }) + .strict(); + + // zod schema for updating a single relationship + private updateSingleRelationSchema = z.object({ + data: z.object({ type: z.string(), id: z.union([z.string(), z.number()]) }).nullable(), + }); + + // zod schema for updating collection relationship + private updateCollectionRelationSchema = z.object({ + data: z.array(z.object({ type: z.string(), id: z.union([z.string(), z.number()]) })), + }); + + private upsertMetaSchema = z.object({ + meta: z.object({ + operation: z.literal('upsert'), + matchFields: z.array(z.string()).min(1), + }), + }); + + // all known types and their metadata + private typeMap: Record = {}; + + // divider used to separate compound ID fields + private idDivider; + + private urlPatternMap: Record; + private modelNameMapping: Record; + private reverseModelNameMapping: Record; + private externalIdMapping: Record; + + constructor(private readonly options: RestApiHandlerOptions) { + this.validateOptions(options); + + this.idDivider = options.idDivider ?? DEFAULT_ID_DIVIDER; + const segmentCharset = options.urlSegmentCharset ?? 'a-zA-Z0-9-_~ %'; + + this.modelNameMapping = options.modelNameMapping ?? {}; + this.modelNameMapping = Object.fromEntries( + Object.entries(this.modelNameMapping).map(([k, v]) => [lowerCaseFirst(k), v]), + ); + this.reverseModelNameMapping = Object.fromEntries( + Object.entries(this.modelNameMapping).map(([k, v]) => [v, k]), + ); + + this.externalIdMapping = options.externalIdMapping ?? {}; + this.externalIdMapping = Object.fromEntries( + Object.entries(this.externalIdMapping).map(([k, v]) => [lowerCaseFirst(k), v]), + ); + + this.urlPatternMap = this.buildUrlPatternMap(segmentCharset); + + this.buildTypeMap(); + this.buildSerializers(); + } + + private validateOptions(options: RestApiHandlerOptions) { + const schema = z.strictObject({ + schema: z.object(), + log: loggerSchema.optional(), + endpoint: z.string().min(1), + pageSize: z.union([z.number().int().positive(), z.literal(Infinity)]).optional(), + idDivider: z.string().min(1).optional(), + urlSegmentCharset: z.string().min(1).optional(), + modelNameMapping: z.record(z.string(), z.string()).optional(), + externalIdMapping: z.record(z.string(), z.string()).optional(), + queryOptions: z.object().optional(), + }); + const parseResult = schema.safeParse(options); + if (!parseResult.success) { + throw new Error(`Invalid options: ${fromError(parseResult.error)}`); + } + } + + get schema() { + return this.options.schema; + } + + get log(): LogConfig | undefined { + return this.options.log; + } + + private buildUrlPatternMap(urlSegmentNameCharset: string): Record { + const options = { segmentValueCharset: urlSegmentNameCharset }; + + const buildPath = (segments: string[]) => { + return '/' + segments.join('/'); + }; + + return { + [UrlPatterns.SINGLE]: new UrlPattern(buildPath([':type', ':id']), options), + [UrlPatterns.FETCH_RELATIONSHIP]: new UrlPattern(buildPath([':type', ':id', ':relationship']), options), + [UrlPatterns.RELATIONSHIP]: new UrlPattern( + buildPath([':type', ':id', 'relationships', ':relationship']), + options, + ), + [UrlPatterns.COLLECTION]: new UrlPattern(buildPath([':type']), options), + }; + } + + private mapModelName(modelName: string): string { + return this.modelNameMapping[modelName] ?? modelName; + } + + private matchUrlPattern(path: string, routeType: UrlPatterns): Match | undefined { + const pattern = this.urlPatternMap[routeType]; + if (!pattern) { + throw new InvalidValueError(`Unknown route type: ${routeType}`); + } + + const match = pattern.match(path); + if (!match) { + return; + } + + if (match.type in this.modelNameMapping) { + throw new InvalidValueError( + `use the mapped model name: ${this.modelNameMapping[match.type]} and not ${match.type}`, + ); + } + + if (match.type in this.reverseModelNameMapping) { + match.type = this.reverseModelNameMapping[match.type]; + } + + return match; + } + + async handleRequest({ client, method, path, query, requestBody }: RequestContext): Promise { + method = method.toUpperCase(); + if (!path.startsWith('/')) { + path = '/' + path; + } + + try { + if (path.startsWith('/$procs/')) { + const proc = path.split('/')[2]; + return await this.processProcedureRequest({ client, method, proc, query, requestBody }); + } + + switch (method) { + case 'GET': { + let match = this.matchUrlPattern(path, UrlPatterns.SINGLE); + if (match) { + // single resource read + return await this.processSingleRead(client, match.type, match.id, query); + } + match = this.matchUrlPattern(path, UrlPatterns.FETCH_RELATIONSHIP); + if (match) { + // fetch related resource(s) + return await this.processFetchRelated(client, match.type, match.id, match.relationship, query); + } + + match = this.matchUrlPattern(path, UrlPatterns.RELATIONSHIP); + if (match) { + // read relationship + return await this.processReadRelationship( + client, + match.type, + match.id, + match.relationship, + query, + ); + } + + match = this.matchUrlPattern(path, UrlPatterns.COLLECTION); + if (match) { + // collection read + return await this.processCollectionRead(client, match.type, query); + } + + return this.makeError('invalidPath'); + } + + case 'POST': { + if (!requestBody) { + return this.makeError('invalidPayload'); + } + let match = this.matchUrlPattern(path, UrlPatterns.COLLECTION); + if (match) { + const body = requestBody as any; + const upsertMeta = this.upsertMetaSchema.safeParse(body); + if (upsertMeta.success) { + // resource upsert + return await this.processUpsert(client, match.type, query, requestBody); + } else { + // resource creation + return await this.processCreate(client, match.type, query, requestBody); + } + } + match = this.matchUrlPattern(path, UrlPatterns.RELATIONSHIP); + if (match) { + // relationship creation (collection relationship only) + return await this.processRelationshipCRUD( + client, + 'create', + match.type, + match.id, + match.relationship, + query, + requestBody, + ); + } + + return this.makeError('invalidPath'); + } + + // TODO: PUT for full update + case 'PUT': + case 'PATCH': { + if (!requestBody) { + return this.makeError('invalidPayload'); + } + let match = this.matchUrlPattern(path, UrlPatterns.SINGLE); + if (match) { + // resource update + return await this.processUpdate(client, match.type, match.id, query, requestBody); + } + match = this.matchUrlPattern(path, UrlPatterns.RELATIONSHIP); + if (match) { + // relationship update + return await this.processRelationshipCRUD( + client, + 'update', + match.type, + match.id, + match.relationship as string, + query, + requestBody, + ); + } + + return this.makeError('invalidPath'); + } + + case 'DELETE': { + let match = this.matchUrlPattern(path, UrlPatterns.SINGLE); + if (match) { + // resource deletion + return await this.processDelete(client, match.type, match.id); + } + + match = this.matchUrlPattern(path, UrlPatterns.RELATIONSHIP); + if (match) { + // relationship deletion (collection relationship only) + return await this.processRelationshipCRUD( + client, + 'delete', + match.type, + match.id, + match.relationship as string, + query, + requestBody, + ); + } + + return this.makeError('invalidPath'); + } + + default: + return this.makeError('invalidPath'); + } + } catch (err) { + if (err instanceof InvalidValueError) { + return this.makeError('invalidValue', err.message); + } else if (err instanceof ORMError) { + return this.handleORMError(err); + } else { + return this.handleGenericError(err); + } + } + } + + private handleGenericError(err: unknown): Response | PromiseLike { + return this.makeError('unknownError', err instanceof Error ? `${err.message}\n${err.stack}` : 'Unknown error'); + } + + private async processProcedureRequest({ + client, + method, + proc, + query, + requestBody, + }: { + client: ClientContract; + method: string; + proc?: string; + query?: Record; + requestBody?: unknown; + }): Promise { + if (!proc) { + return this.makeProcBadInputErrorResponse('missing procedure name'); + } + + const procDef = getProcedureDef(this.schema, proc); + if (!procDef) { + return this.makeProcBadInputErrorResponse(`unknown procedure: ${proc}`); + } + + const isMutation = !!procDef.mutation; + if (isMutation) { + if (method !== 'POST') { + return this.makeProcBadInputErrorResponse('invalid request method, only POST is supported'); + } + } else { + if (method !== 'GET') { + return this.makeProcBadInputErrorResponse('invalid request method, only GET is supported'); + } + } + + const argsPayload = method === 'POST' ? requestBody : query; + + // support SuperJSON request payload format + const { result: processedArgsPayload, error } = await processSuperJsonRequestPayload(argsPayload); + if (error) { + return this.makeProcBadInputErrorResponse(error); + } + + let procInput: unknown; + try { + procInput = mapProcedureArgs(procDef, processedArgsPayload); + } catch (err) { + return this.makeProcBadInputErrorResponse( + err instanceof Error ? err.message : 'invalid procedure arguments', + ); + } + + try { + log(this.log, 'debug', () => `handling "$procs.${proc}" request`); + + const clientResult = await (client as any).$procs?.[proc](procInput); + const toSerialize = this.toPlainObject(clientResult); + + const { json, meta } = SuperJSON.serialize(toSerialize); + const responseBody: any = { data: json }; + if (meta) { + responseBody.meta = { serialization: meta }; + } + + return { status: 200, body: responseBody }; + } catch (err) { + log(this.log, 'error', `error occurred when handling "$procs.${proc}" request`, err); + if (err instanceof ORMError) { + throw err; // top-level handler will take care of it + } + return this.makeProcGenericErrorResponse(err); + } + } + + private makeProcBadInputErrorResponse(message: string): Response { + const resp = this.makeError('invalidPayload', message, 400); + log(this.log, 'debug', () => `sending error response: ${JSON.stringify(resp)}`); + return resp; + } + + private makeProcGenericErrorResponse(err: unknown): Response { + const message = err instanceof Error ? err.message : 'unknown error'; + const resp = this.makeError('unknownError', message, 500); + log(this.log, 'debug', () => `sending error response: ${JSON.stringify(resp)}`); + return resp; + } + + private async processSingleRead( + client: ClientContract, + type: string, + resourceId: string, + query: Record | undefined, + ): Promise { + const typeInfo = this.getModelInfo(type); + if (!typeInfo) { + return this.makeUnsupportedModelError(type); + } + + const args: any = { where: this.makeIdFilter(typeInfo.idFields, resourceId) }; + + // include IDs of relation fields so that they can be serialized + this.includeRelationshipIds(type, args, 'include'); + + // handle "include" query parameter + let include: string[] | undefined; + if (query?.['include']) { + const { select, error, allIncludes } = this.buildRelationSelect(type, query['include'], query); + if (error) { + return error; + } + if (select) { + args.include = { ...args.include, ...select }; + } + include = allIncludes; + } + + // handle partial results for requested type + const { select, error } = this.buildPartialSelect(type, query); + if (error) return error; + if (select) { + args.select = { ...select, ...args.select }; + if (args.include) { + args.select = { + ...args.select, + ...args.include, + }; + args.include = undefined; + } + } + + const entity = await (client as any)[type].findUnique(args); + + if (entity) { + return { + status: 200, + body: await this.serializeItems(type, entity, { include }), + }; + } else { + return this.makeError('notFound'); + } + } + + private async processFetchRelated( + client: ClientContract, + type: string, + resourceId: string, + relationship: string, + query: Record | undefined, + ): Promise { + const typeInfo = this.getModelInfo(type); + if (!typeInfo) { + return this.makeUnsupportedModelError(type); + } + + const relationInfo = typeInfo.relationships[relationship]; + if (!relationInfo) { + return this.makeUnsupportedRelationshipError(type, relationship, 404); + } + + let select: any; + + // handle "include" query parameter + let include: string[] | undefined; + if (query?.['include']) { + const { + select: relationSelect, + error, + allIncludes, + } = this.buildRelationSelect(type, query['include'], query); + if (error) { + return error; + } + // trim the leading `$relationship.` from the include paths + include = allIncludes + .filter((i) => i.startsWith(`${relationship}.`)) + .map((i) => i.substring(`${relationship}.`.length)); + select = relationSelect; + } + + // handle partial results for requested type + if (!select) { + const { select: partialFields, error } = this.buildPartialSelect(lowerCaseFirst(relationInfo.type), query); + if (error) return error; + + select = partialFields ? { [relationship]: { select: { ...partialFields } } } : { [relationship]: true }; + } + + const args: any = { + where: this.makeIdFilter(typeInfo.idFields, resourceId), + select, + }; + + if (relationInfo.isCollection) { + // if related data is a collection, it can be filtered, sorted, and paginated + const error = this.injectRelationQuery(relationInfo.type, select, relationship, query); + if (error) { + return error; + } + } + + const entity: any = await (client as any)[type].findUnique(args); + + let paginator: Paginator | undefined; + + if (entity?._count?.[relationship] !== undefined) { + // build up paginator + const total = entity?._count?.[relationship] as number; + const url = this.makeNormalizedUrl(`/${type}/${resourceId}/${relationship}`, query); + const { offset, limit } = this.getPagination(query); + paginator = this.makePaginator(url, offset, limit, total); + } + + if (entity?.[relationship]) { + const mappedType = this.mapModelName(type); + return { + status: 200, + body: await this.serializeItems(relationInfo.type, entity[relationship], { + linkers: { + document: new tsjapi.Linker(() => + this.makeLinkUrl(`/${mappedType}/${resourceId}/${relationship}`), + ), + paginator, + }, + include, + }), + }; + } else { + return this.makeError('notFound'); + } + } + + private async processReadRelationship( + client: ClientContract, + type: string, + resourceId: string, + relationship: string, + query: Record | undefined, + ): Promise { + const typeInfo = this.getModelInfo(type); + if (!typeInfo) { + return this.makeUnsupportedModelError(type); + } + + const relationInfo = typeInfo.relationships[relationship]; + if (!relationInfo) { + return this.makeUnsupportedRelationshipError(type, relationship, 404); + } + + const args: any = { + where: this.makeIdFilter(typeInfo.idFields, resourceId), + select: this.makeIdSelect(typeInfo.idFields), + }; + + // include IDs of relation fields so that they can be serialized + args.select = { ...args.select, [relationship]: { select: this.makeIdSelect(relationInfo.idFields) } }; + + let paginator: Paginator | undefined; + + if (relationInfo.isCollection) { + // if related data is a collection, it can be filtered, sorted, and paginated + const error = this.injectRelationQuery(relationInfo.type, args.select, relationship, query); + if (error) { + return error; + } + } + + const entity: any = await (client as any)[type].findUnique(args); + const mappedType = this.mapModelName(type); + + if (entity?._count?.[relationship] !== undefined) { + // build up paginator + const total = entity?._count?.[relationship] as number; + const url = this.makeNormalizedUrl(`/${mappedType}/${resourceId}/relationships/${relationship}`, query); + const { offset, limit } = this.getPagination(query); + paginator = this.makePaginator(url, offset, limit, total); + } + + if (entity?.[relationship]) { + const serialized: any = await this.serializeItems(relationInfo.type, entity[relationship], { + linkers: { + document: new tsjapi.Linker(() => + this.makeLinkUrl(`/${mappedType}/${resourceId}/relationships/${relationship}`), + ), + paginator, + }, + onlyIdentifier: true, + }); + + return { + status: 200, + body: serialized, + }; + } else { + return this.makeError('notFound'); + } + } + + private async processCollectionRead( + client: ClientContract, + type: string, + query: Record | undefined, + ): Promise { + const typeInfo = this.getModelInfo(type); + if (!typeInfo) { + return this.makeUnsupportedModelError(type); + } + + const args: any = {}; + + // add filter + const { filter, error: filterError } = this.buildFilter(type, query); + if (filterError) { + return filterError; + } + if (filter) { + args.where = filter; + } + + const { sort, error: sortError } = this.buildSort(type, query); + if (sortError) { + return sortError; + } + if (sort) { + args.orderBy = sort; + } + + // include IDs of relation fields so that they can be serialized + this.includeRelationshipIds(type, args, 'include'); + + // handle "include" query parameter + let include: string[] | undefined; + if (query?.['include']) { + const { select, error, allIncludes } = this.buildRelationSelect(type, query['include'], query); + if (error) { + return error; + } + if (select) { + args.include = { ...args.include, ...select }; + } + include = allIncludes; + } + + // handle partial results for requested type + const { select, error } = this.buildPartialSelect(type, query); + if (error) return error; + if (select) { + args.select = { ...select, ...args.select }; + if (args.include) { + args.select = { + ...args.select, + ...args.include, + }; + args.include = undefined; + } + } + + const { offset, limit } = this.getPagination(query); + if (offset > 0) { + args.skip = offset; + } + + if (limit === Infinity) { + const entities = await (client as any)[type].findMany(args); + + const body = await this.serializeItems(type, entities, { include }); + const total = entities.length; + body.meta = this.addTotalCountToMeta(body.meta, total); + + return { + status: 200, + body: body, + }; + } else { + args.take = limit; + + const [entities, count] = await Promise.all([ + (client as any)[type].findMany(args), + (client as any)[type].count({ where: args.where ?? {} }), + ]); + const total = count as number; + + const mappedType = this.mapModelName(type); + const url = this.makeNormalizedUrl(`/${mappedType}`, query); + const options: Partial = { + include, + linkers: { + paginator: this.makePaginator(url, offset, limit, total), + }, + }; + const body = await this.serializeItems(type, entities, options); + body.meta = this.addTotalCountToMeta(body.meta, total); + + return { + status: 200, + body: body, + }; + } + } + + private buildPartialSelect(type: string, query: Record | undefined) { + const selectFieldsQuery = query?.[`fields[${type}]`]; + if (!selectFieldsQuery) { + return { select: undefined, error: undefined }; + } + + if (Array.isArray(selectFieldsQuery)) { + return { + select: undefined, + error: this.makeError('duplicatedFieldsParameter', `duplicated fields query for type ${type}`), + }; + } + + const typeInfo = this.getModelInfo(type); + if (!typeInfo) { + return { select: undefined, error: this.makeUnsupportedModelError(type) }; + } + + const selectFieldNames = selectFieldsQuery.split(',').filter((i) => i); + + const fields = selectFieldNames.reduce((acc, curr) => ({ ...acc, [curr]: true }), {}); + + return { + select: { ...this.makeIdSelect(typeInfo.idFields), ...fields }, + }; + } + + private addTotalCountToMeta(meta: any, total: any) { + return meta ? Object.assign(meta, { total }) : Object.assign({}, { total }); + } + + private makePaginator(baseUrl: string, offset: number, limit: number, total: number) { + if (limit === Infinity) { + return undefined; + } + + const totalPages = Math.ceil(total / limit); + + return new tsjapi.Paginator(() => ({ + first: this.replaceURLSearchParams(baseUrl, { 'page[limit]': limit }), + last: this.replaceURLSearchParams(baseUrl, { + 'page[offset]': (totalPages - 1) * limit, + }), + prev: + offset - limit >= 0 && offset - limit <= total - 1 + ? this.replaceURLSearchParams(baseUrl, { + 'page[offset]': offset - limit, + 'page[limit]': limit, + }) + : null, + next: + offset + limit <= total - 1 + ? this.replaceURLSearchParams(baseUrl, { + 'page[offset]': offset + limit, + 'page[limit]': limit, + }) + : null, + })); + } + + private processRequestBody(requestBody: unknown) { + let body: any = requestBody; + if (body.meta?.serialization) { + // superjson deserialize body if a serialization meta is provided + body = SuperJSON.deserialize({ json: body, meta: body.meta.serialization }); + } + + const parseResult = this.createUpdatePayloadSchema.safeParse(body); + if (!parseResult.success) { + return { + attributes: undefined, + relationships: undefined, + error: this.makeError('invalidPayload', getZodErrorMessage(parseResult.error)), + }; + } + + return { + attributes: parseResult.data.data.attributes, + relationships: parseResult.data.data.relationships, + error: undefined, + }; + } + + private async processCreate( + client: ClientContract, + type: string, + _query: Record | undefined, + requestBody: unknown, + ): Promise { + const typeInfo = this.getModelInfo(type); + if (!typeInfo) { + return this.makeUnsupportedModelError(type); + } + + const { attributes, relationships, error } = this.processRequestBody(requestBody); + if (error) { + return error; + } + + const createPayload: any = { data: { ...attributes } }; + + // turn relationship payload into `connect` objects + if (relationships) { + for (const [key, data] of Object.entries(relationships)) { + if (!data?.data) { + return this.makeError('invalidRelationData'); + } + + const relationInfo = typeInfo.relationships[key]; + if (!relationInfo) { + return this.makeUnsupportedRelationshipError(type, key, 400); + } + + if (relationInfo.isCollection) { + createPayload.data[key] = { + connect: enumerate(data.data).map((item: any) => + this.makeIdConnect(relationInfo.idFields, item.id), + ), + }; + } else { + if (typeof data.data !== 'object') { + return this.makeError('invalidRelationData'); + } + createPayload.data[key] = { + connect: this.makeIdConnect(relationInfo.idFields, data.data.id), + }; + } + + // make sure ID fields are included for result serialization + createPayload.include = { + ...createPayload.include, + [key]: { select: { [this.makeDefaultIdKey(relationInfo.idFields)]: true } }, + }; + } + } + + // include IDs of relation fields so that they can be serialized. + this.includeRelationshipIds(type, createPayload, 'include'); + + const entity = await (client as any)[type].create(createPayload); + return { + status: 201, + body: await this.serializeItems(type, entity), + }; + } + + private async processUpsert( + client: ClientContract, + type: string, + _query: Record | undefined, + requestBody: unknown, + ) { + const typeInfo = this.getModelInfo(type); + if (!typeInfo) { + return this.makeUnsupportedModelError(type); + } + + const modelName = typeInfo.name; + const { attributes, relationships, error } = this.processRequestBody(requestBody); + if (error) { + return error; + } + + const parseResult = this.upsertMetaSchema.safeParse(requestBody); + if (parseResult.error) { + return this.makeError('invalidPayload', getZodErrorMessage(parseResult.error)); + } + const matchFields = parseResult.data.meta.matchFields; + const uniqueFieldSets = this.getUniqueFieldSets(modelName); + + if (!uniqueFieldSets.some((set) => set.every((field) => matchFields.includes(field)))) { + return this.makeError('invalidPayload', 'Match fields must be unique fields', 400); + } + + const upsertPayload: any = { + where: this.makeUpsertWhere(matchFields, attributes, typeInfo), + create: { ...attributes }, + update: { + ...Object.fromEntries(Object.entries(attributes ?? {}).filter((e) => !matchFields.includes(e[0]))), + }, + }; + + if (relationships) { + for (const [key, data] of Object.entries(relationships)) { + if (!data?.data) { + return this.makeError('invalidRelationData'); + } + + const relationInfo = typeInfo.relationships[key]; + if (!relationInfo) { + return this.makeUnsupportedRelationshipError(modelName, key, 400); + } + + if (relationInfo.isCollection) { + upsertPayload.create[key] = { + connect: enumerate(data.data).map((item: any) => + this.makeIdConnect(relationInfo.idFields, item.id), + ), + }; + upsertPayload.update[key] = { + set: enumerate(data.data).map((item: any) => + this.makeIdConnect(relationInfo.idFields, item.id), + ), + }; + } else { + if (typeof data.data !== 'object') { + return this.makeError('invalidRelationData'); + } + upsertPayload.create[key] = { + connect: this.makeIdConnect(relationInfo.idFields, data.data.id), + }; + upsertPayload.update[key] = { + connect: this.makeIdConnect(relationInfo.idFields, data.data.id), + }; + } + } + } + + // include IDs of relation fields so that they can be serialized. + this.includeRelationshipIds(modelName, upsertPayload, 'include'); + + const entity = await (client as any)[modelName].upsert(upsertPayload); + + return { + status: 201, + body: await this.serializeItems(modelName, entity), + }; + } + + private getUniqueFieldSets(type: string) { + const modelDef = this.requireModel(type); + return Object.entries(modelDef.uniqueFields).map( + ([k, v]) => + typeof v.type === 'string' + ? [k] // single unique field + : Object.keys(v), // compound unique fields + ); + } + + private async processRelationshipCRUD( + client: ClientContract, + mode: 'create' | 'update' | 'delete', + type: string, + resourceId: string, + relationship: string, + _query: Record | undefined, + requestBody: unknown, + ): Promise { + const typeInfo = this.getModelInfo(type); + if (!typeInfo) { + return this.makeUnsupportedModelError(type); + } + + const relationInfo = typeInfo.relationships[relationship]; + if (!relationInfo) { + return this.makeUnsupportedRelationshipError(type, relationship, 404); + } + + if (!relationInfo.isCollection && mode !== 'update') { + // to-one relation can only be updated + return this.makeError('invalidVerb'); + } + + const updateArgs: any = { + where: this.makeIdFilter(typeInfo.idFields, resourceId), + select: { + ...typeInfo.idFields.reduce((acc, field) => ({ ...acc, [field.name]: true }), {}), + [relationship]: { select: this.makeIdSelect(relationInfo.idFields) }, + }, + }; + + if (!relationInfo.isCollection) { + // zod-parse payload + const parsed = this.updateSingleRelationSchema.safeParse(requestBody); + if (!parsed.success) { + return this.makeError('invalidPayload', getZodErrorMessage(parsed.error)); + } + + if (parsed.data.data === null) { + if (!relationInfo.isOptional) { + // cannot disconnect a required relation + return this.makeError('invalidPayload'); + } + // set null -> disconnect + updateArgs.data = { + [relationship]: { + disconnect: true, + }, + }; + } else { + updateArgs.data = { + [relationship]: { + connect: this.makeIdConnect(relationInfo.idFields, parsed.data.data.id), + }, + }; + } + } else { + // zod-parse payload + const parsed = this.updateCollectionRelationSchema.safeParse(requestBody); + if (!parsed.success) { + return this.makeError('invalidPayload', getZodErrorMessage(parsed.error)); + } + + // create -> connect, delete -> disconnect, update -> set + const relationVerb = mode === 'create' ? 'connect' : mode === 'delete' ? 'disconnect' : 'set'; + + updateArgs.data = { + [relationship]: { + [relationVerb]: enumerate(parsed.data.data).map((item: any) => + this.makeIdFilter(relationInfo.idFields, item.id), + ), + }, + }; + } + + const entity: any = await (client as any)[type].update(updateArgs); + + const mappedType = this.mapModelName(type); + + const serialized: any = await this.serializeItems(relationInfo.type, entity[relationship], { + linkers: { + document: new tsjapi.Linker(() => + this.makeLinkUrl(`/${mappedType}/${resourceId}/relationships/${relationship}`), + ), + }, + onlyIdentifier: true, + }); + + return { + status: 200, + body: serialized, + }; + } + + private async processUpdate( + client: ClientContract, + type: any, + resourceId: string, + _query: Record | undefined, + requestBody: unknown, + ): Promise { + const typeInfo = this.getModelInfo(type); + if (!typeInfo) { + return this.makeUnsupportedModelError(type); + } + + const { attributes, relationships, error } = this.processRequestBody(requestBody); + if (error) { + return error; + } + + const updatePayload: any = { + where: this.makeIdFilter(typeInfo.idFields, resourceId), + data: { ...attributes }, + }; + + // turn relationships into query payload + if (relationships) { + for (const [key, data] of Object.entries(relationships)) { + if (!data?.data) { + return this.makeError('invalidRelationData'); + } + + const relationInfo = typeInfo.relationships[key]; + if (!relationInfo) { + return this.makeUnsupportedRelationshipError(type, key, 400); + } + + if (relationInfo.isCollection) { + updatePayload.data[key] = { + set: enumerate(data.data).map((item: any) => ({ + [this.makeDefaultIdKey(relationInfo.idFields)]: item.id, + })), + }; + } else { + if (typeof data.data !== 'object') { + return this.makeError('invalidRelationData'); + } + updatePayload.data[key] = { + connect: { + [this.makeDefaultIdKey(relationInfo.idFields)]: data.data.id, + }, + }; + } + updatePayload.include = { + ...updatePayload.include, + [key]: { select: { [this.makeDefaultIdKey(relationInfo.idFields)]: true } }, + }; + } + } + + // include IDs of relation fields so that they can be serialized. + this.includeRelationshipIds(type, updatePayload, 'include'); + + const entity = await (client as any)[type].update(updatePayload); + return { + status: 200, + body: await this.serializeItems(type, entity), + }; + } + + private async processDelete(client: ClientContract, type: any, resourceId: string): Promise { + const typeInfo = this.getModelInfo(type); + if (!typeInfo) { + return this.makeUnsupportedModelError(type); + } + + await (client as any)[type].delete({ + where: this.makeIdFilter(typeInfo.idFields, resourceId), + }); + return { + status: 200, + body: { meta: {} }, + }; + } + + //#region utilities + + private requireModel(model: string): ModelDef { + const modelDef = this.schema.models[model]; + if (!modelDef) { + throw new Error(`Model ${model} is not defined in the schema`); + } + return modelDef; + } + + private getIdFields(model: string): FieldDef[] { + const modelDef = this.requireModel(model); + const modelLower = lowerCaseFirst(model); + if (!(modelLower in this.externalIdMapping)) { + return Object.values(modelDef.fields).filter((f) => modelDef.idFields.includes(f.name)); + } + + // map external ID name to unique constraint field + const externalIdName = this.externalIdMapping[modelLower]; + for (const [name, info] of Object.entries(modelDef.uniqueFields)) { + if (name === externalIdName) { + if (typeof info.type === 'string') { + // single unique field + return [this.requireField(model, name)]; + } else { + // compound unique fields + return Object.keys(info).map((f) => this.requireField(model, f)); + } + } + } + + throw new Error(`Model ${model} does not have unique key ${externalIdName}`); + } + + private requireField(model: string, field: string): FieldDef { + const modelDef = this.requireModel(model); + const fieldDef = modelDef.fields[field]; + if (!fieldDef) { + throw new Error(`Field ${field} is not defined in model ${model}`); + } + return fieldDef; + } + + private buildTypeMap() { + this.typeMap = {}; + for (const [model, { fields }] of Object.entries(this.schema.models)) { + const idFields = this.getIdFields(model); + if (idFields.length === 0) { + log(this.options.log, 'warn', `Not including model ${model} in the API because it has no ID field`); + continue; + } + + const modelInfo: ModelInfo = (this.typeMap[lowerCaseFirst(model)] = { + name: model, + idFields, + relationships: {}, + fields, + }); + + for (const [field, fieldInfo] of Object.entries(fields)) { + if (!fieldInfo.relation) { + continue; + } + const fieldTypeIdFields = this.getIdFields(fieldInfo.type); + if (fieldTypeIdFields.length === 0) { + log( + this.options.log, + 'warn', + `Not including relation ${model}.${field} in the API because it has no ID field`, + ); + continue; + } + + modelInfo.relationships[field] = { + type: fieldInfo.type, + idFields: fieldTypeIdFields, + isCollection: !!fieldInfo.array, + isOptional: !!fieldInfo.optional, + }; + } + } + } + + private getModelInfo(model: string): ModelInfo | undefined { + return this.typeMap[lowerCaseFirst(model)]; + } + + private makeLinkUrl(path: string) { + return `${this.options.endpoint}${path}`; + } + + private buildSerializers() { + const linkers: Record> = {}; + + for (const model of Object.keys(this.schema.models)) { + const ids = this.getIdFields(model); + const modelLower = lowerCaseFirst(model); + const mappedModel = this.mapModelName(modelLower); + + if (ids.length < 1) { + continue; + } + + const linker = new tsjapi.Linker((items) => + Array.isArray(items) + ? this.makeLinkUrl(`/${mappedModel}`) + : this.makeLinkUrl(`/${mappedModel}/${this.getId(model, items)}`), + ); + linkers[modelLower] = linker; + + let projection: Record | null = {}; + const modelDef = this.requireModel(model); + for (const [field, fieldDef] of Object.entries(modelDef.fields)) { + if (fieldDef.relation) { + projection[field] = 0; + } + } + if (Object.keys(projection).length === 0) { + projection = null; + } + + const serializer = new tsjapi.Serializer(model, { + version: '1.1', + idKey: this.makeIdKey(ids), + linkers: { + resource: linker, + document: linker, + }, + projection, + }); + this.serializers.set(modelLower, serializer); + } + + // set relators + for (const model of Object.keys(this.schema.models)) { + const modelLower = lowerCaseFirst(model); + const serializer = this.serializers.get(modelLower); + if (!serializer) { + continue; + } + + const relators: Record> = {}; + const modelDef = this.requireModel(model); + for (const [field, fieldDef] of Object.entries(modelDef.fields)) { + if (!fieldDef.relation) { + continue; + } + const fieldSerializer = this.serializers.get(lowerCaseFirst(fieldDef.type)); + if (!fieldSerializer) { + continue; + } + const fieldIds = this.getIdFields(fieldDef.type); + if (fieldIds.length > 0) { + const mappedModel = this.mapModelName(modelLower); + + const relator = new tsjapi.Relator( + async (data) => { + return (data as any)[field]; + }, + fieldSerializer, + { + relatedName: field, + linkers: { + related: new tsjapi.Linker((primary) => + this.makeLinkUrl(`/${mappedModel}/${this.getId(model, primary)}/${field}`), + ), + relationship: new tsjapi.Linker((primary) => + this.makeLinkUrl( + `/${mappedModel}/${this.getId(model, primary)}/relationships/${field}`, + ), + ), + }, + }, + ); + relators[field] = relator; + } + } + serializer.setRelators(relators); + } + } + + private getId(model: string, data: any) { + if (!data) { + return undefined; + } + const ids = this.getIdFields(model); + if (ids.length === 0) { + return undefined; + } else { + return data[this.makeIdKey(ids)]; + } + } + + private async serializeItems(model: string, items: unknown, options?: Partial>) { + model = lowerCaseFirst(model); + const serializer = this.serializers.get(model); + if (!serializer) { + throw new Error(`serializer not found for model ${model}`); + } + + const itemsWithId = clone(items); + this.injectCompoundId(model, itemsWithId); + + // serialize to JSON:API structure + const serialized = await serializer.serialize(itemsWithId, options); + + // convert the serialization result to plain object otherwise SuperJSON won't work + const plainResult = this.toPlainObject(serialized); + + // superjson serialize the result + const { json, meta } = SuperJSON.serialize(plainResult); + + const result: any = json; + if (meta) { + result.meta = { ...result.meta, serialization: meta }; + } + + return result; + } + + private injectCompoundId(model: string, items: unknown) { + const typeInfo = this.getModelInfo(model); + if (!typeInfo) { + return; + } + + // recursively traverse the entity to create synthetic ID field for models with compound ID + enumerate(items).forEach((item: any) => { + if (!item) { + return; + } + + if (typeInfo.idFields.length > 1) { + item[this.makeIdKey(typeInfo.idFields)] = this.makeCompoundId(typeInfo.idFields, item); + } + + for (const [key, value] of Object.entries(item)) { + if (typeInfo.relationships[key]) { + // field is a relationship, recurse + this.injectCompoundId(typeInfo.relationships[key].type, value); + } + } + }); + } + + private toPlainObject(data: any): any { + if (data === undefined || data === null) { + return data; + } + + if (Array.isArray(data)) { + return data.map((item: any) => this.toPlainObject(item)); + } + + if (typeof data === 'object') { + if (typeof data.toJSON === 'function') { + // custom toJSON function + return data.toJSON(); + } + const result: any = {}; + for (const [field, value] of Object.entries(data)) { + if (value === undefined || typeof value === 'function') { + // trim undefined and functions + continue; + } else if (field === 'attributes') { + // don't visit into entity data + result[field] = value; + } else { + result[field] = this.toPlainObject(value); + } + } + return result; + } + + return data; + } + + private replaceURLSearchParams(url: string, params: Record) { + const r = new URL(url); + for (const [key, value] of Object.entries(params)) { + r.searchParams.set(key, value.toString()); + } + return r.toString(); + } + + private makeIdFilter(idFields: FieldDef[], resourceId: string, nested: boolean = true) { + const decodedId = decodeURIComponent(resourceId); + if (idFields.length === 1) { + return { [idFields[0]!.name]: this.coerce(idFields[0]!, decodedId) }; + } else if (nested) { + return { + // TODO: support `@@id` with custom name + [idFields.map((idf) => idf.name).join(DEFAULT_ID_DIVIDER)]: idFields.reduce( + (acc, curr, idx) => ({ + ...acc, + [curr.name]: this.coerce(curr, decodedId.split(this.idDivider)[idx]), + }), + {}, + ), + }; + } else { + return idFields.reduce( + (acc, curr, idx) => ({ + ...acc, + [curr.name]: this.coerce(curr, decodedId.split(this.idDivider)[idx]), + }), + {}, + ); + } + } + + private makeIdSelect(idFields: FieldDef[]) { + if (idFields.length === 0) { + throw this.errors['noId']; + } + return idFields.reduce((acc, curr) => ({ ...acc, [curr.name]: true }), {}); + } + + private makeIdConnect(idFields: FieldDef[], id: string | number) { + if (idFields.length === 1) { + return { [idFields[0]!.name]: this.coerce(idFields[0]!, id) }; + } else { + return { + [this.makeDefaultIdKey(idFields)]: idFields.reduce( + (acc, curr, idx) => ({ + ...acc, + [curr.name]: this.coerce(curr, `${id}`.split(this.idDivider)[idx]), + }), + {}, + ), + }; + } + } + + private makeIdKey(idFields: FieldDef[]) { + return idFields.map((idf) => idf.name).join(this.idDivider); + } + + private makeDefaultIdKey(idFields: FieldDef[]) { + // TODO: support `@@id` with custom name + return idFields.map((idf) => idf.name).join(DEFAULT_ID_DIVIDER); + } + + private makeCompoundId(idFields: FieldDef[], item: any) { + return idFields.map((idf) => item[idf.name]).join(this.idDivider); + } + + private makeUpsertWhere(matchFields: any[], attributes: any, typeInfo: ModelInfo) { + const where = matchFields.reduce((acc: any, field: string) => { + acc[field] = attributes[field] ?? null; + return acc; + }, {}); + + if ( + typeInfo.idFields.length > 1 && + matchFields.some((mf) => typeInfo.idFields.map((idf) => idf.name).includes(mf)) + ) { + return { + [this.makeDefaultIdKey(typeInfo.idFields)]: where, + }; + } + + return where; + } + + private includeRelationshipIds(model: string, args: any, mode: 'select' | 'include') { + const typeInfo = this.getModelInfo(model); + if (!typeInfo) { + return; + } + for (const [relation, relationInfo] of Object.entries(typeInfo.relationships)) { + args[mode] = { ...args[mode], [relation]: { select: this.makeIdSelect(relationInfo.idFields) } }; + } + } + + private coerce(fieldDef: FieldDef, value: any) { + if (typeof value === 'string') { + if (fieldDef.attributes?.some((attr) => attr.name === '@json')) { + try { + return JSON.parse(value); + } catch { + throw new InvalidValueError(`invalid JSON value: ${value}`); + } + } + + const type = fieldDef.type; + if (type === 'Int') { + const parsed = parseInt(value); + if (isNaN(parsed)) { + throw new InvalidValueError(`invalid ${type} value: ${value}`); + } + return parsed; + } else if (type === 'BigInt') { + try { + return BigInt(value); + } catch { + throw new InvalidValueError(`invalid ${type} value: ${value}`); + } + } else if (type === 'Float') { + const parsed = parseFloat(value); + if (isNaN(parsed)) { + throw new InvalidValueError(`invalid ${type} value: ${value}`); + } + return parsed; + } else if (type === 'Decimal') { + try { + return new Decimal(value); + } catch { + throw new InvalidValueError(`invalid ${type} value: ${value}`); + } + } else if (type === 'Boolean') { + if (value === 'true') { + return true; + } else if (value === 'false') { + return false; + } else { + throw new InvalidValueError(`invalid ${type} value: ${value}`); + } + } + } + return value; + } + + private makeNormalizedUrl(path: string, query: Record | undefined) { + const url = new URL(this.makeLinkUrl(path)); + for (const [key, value] of Object.entries(query ?? {})) { + if ( + key.startsWith('filter[') || + key.startsWith('sort[') || + key === 'include' || + key.startsWith('include[') || + key.startsWith('fields[') + ) { + for (const v of enumerate(value)) { + url.searchParams.append(key, v); + } + } + } + return url.toString(); + } + + private getPagination(query: Record | undefined) { + if (!query) { + return { offset: 0, limit: this.options.pageSize ?? DEFAULT_PAGE_SIZE }; + } + + let offset = 0; + if (query['page[offset]']) { + const value = query['page[offset]']; + const offsetText = Array.isArray(value) ? value[value.length - 1]! : value; + offset = parseInt(offsetText); + if (isNaN(offset) || offset < 0) { + offset = 0; + } + } + + let pageSizeOption = this.options.pageSize ?? DEFAULT_PAGE_SIZE; + if (pageSizeOption <= 0) { + pageSizeOption = DEFAULT_PAGE_SIZE; + } + + let limit = pageSizeOption; + if (query['page[limit]']) { + const value = query['page[limit]']; + const limitText = Array.isArray(value) ? value[value.length - 1]! : value; + limit = parseInt(limitText); + if (isNaN(limit) || limit <= 0) { + limit = pageSizeOption; + } + limit = Math.min(pageSizeOption, limit); + } + + return { offset, limit }; + } + + private buildFilter( + type: string, + query: Record | undefined, + ): { filter: any; error: any } { + if (!query) { + return { filter: undefined, error: undefined }; + } + + const typeInfo = this.getModelInfo(type); + if (!typeInfo) { + return { filter: undefined, error: this.makeUnsupportedModelError(type) }; + } + + const items: any[] = []; + + for (const [key, value] of Object.entries(query)) { + if (!value) { + continue; + } + + // try matching query parameter key as "filter[x][y]..." + const match = key.match(this.filterParamPattern); + if (!match || !match.groups || !match.groups['match']) { + continue; + } + + const filterKeys = match.groups['match'] + .replaceAll(/[[\]]/g, ' ') + .split(' ') + .filter((i) => i); + + if (!filterKeys.length) { + continue; + } + + // turn filter into a nested query object + + const item: any = {}; + let curr = item; + let currType = typeInfo; + + for (const filterValue of enumerate(value)) { + for (let i = 0; i < filterKeys.length; i++) { + // extract filter operation from (optional) trailing $op + let filterKey = filterKeys[i]!; + let filterOp: FilterOperationType | undefined; + const pos = filterKey.indexOf('$'); + if (pos > 0) { + filterOp = filterKey.substring(pos + 1) as FilterOperationType; + filterKey = filterKey.substring(0, pos); + } + + if (!!filterOp && !FilterOperations.includes(filterOp)) { + return { + filter: undefined, + error: this.makeError('invalidFilter', `invalid filter operation: ${filterOp}`), + }; + } + + const idFields = this.getIdFields(currType.name); + const fieldDef = + filterKey === 'id' + ? Object.values(currType.fields).find((f) => idFields.some((idf) => idf.name === f.name)) + : currType.fields[filterKey]; + if (!fieldDef) { + return { filter: undefined, error: this.makeError('invalidFilter') }; + } + + if (!fieldDef.relation) { + // regular field + if (i !== filterKeys.length - 1) { + // must be the last segment of a filter + return { filter: undefined, error: this.makeError('invalidFilter') }; + } + curr[fieldDef.name] = this.makeFilterValue(fieldDef, filterValue, filterOp); + } else { + // relation field + if (i === filterKeys.length - 1) { + curr[fieldDef.name] = this.makeFilterValue(fieldDef, filterValue, filterOp); + } else { + // keep going + if (fieldDef.array) { + // collection filtering implies "some" operation + curr[fieldDef.name] = { some: {} }; + curr = curr[fieldDef.name].some; + } else { + curr = curr[fieldDef.name] = {}; + } + currType = this.getModelInfo(fieldDef.type)!; + } + } + } + items.push(item); + } + } + + if (items.length === 0) { + return { filter: undefined, error: undefined }; + } else { + // combine filters with AND + return { filter: items.length === 1 ? items[0] : { AND: items }, error: undefined }; + } + } + + private buildSort(type: string, query: Record | undefined) { + if (!query?.['sort']) { + return { sort: undefined, error: undefined }; + } + + const typeInfo = this.getModelInfo(type); + if (!typeInfo) { + return { sort: undefined, error: this.makeUnsupportedModelError(type) }; + } + + const result: any[] = []; + + for (const sortSpec of enumerate(query['sort'])) { + const sortFields = sortSpec.split(',').filter((i) => i); + + for (const sortField of sortFields) { + const dir = sortField.startsWith('-') ? 'desc' : 'asc'; + const cleanedSortField = sortField.startsWith('-') ? sortField.substring(1) : sortField; + const parts = cleanedSortField.split('.').filter((i) => i); + + const sortItem: any = {}; + let curr = sortItem; + let currType = typeInfo; + + for (let i = 0; i < parts.length; i++) { + const part = parts[i]!; + + const fieldInfo = currType.fields[part]; + if (!fieldInfo || fieldInfo.array) { + return { + sort: undefined, + error: this.makeError('invalidSort', 'sorting by array field is not supported'), + }; + } + + if (i === parts.length - 1) { + if (fieldInfo.relation) { + // relation field: sort by id + const relationType = this.getModelInfo(fieldInfo.type); + if (!relationType) { + return { sort: undefined, error: this.makeUnsupportedModelError(fieldInfo.type) }; + } + curr[fieldInfo.name] = relationType.idFields.reduce((acc: any, idField: FieldDef) => { + acc[idField.name] = dir; + return acc; + }, {}); + } else { + // regular field + curr[fieldInfo.name] = dir; + } + } else { + if (!fieldInfo.relation) { + // must be a relation field + return { + sort: undefined, + error: this.makeError( + 'invalidSort', + 'intermediate sort segments must be relationships', + ), + }; + } + // keep going + curr = curr[fieldInfo.name] = {}; + currType = this.getModelInfo(fieldInfo.type)!; + if (!currType) { + return { sort: undefined, error: this.makeUnsupportedModelError(fieldInfo.type) }; + } + } + } + + result.push(sortItem); + } + } + + return { sort: result, error: undefined }; + } + + private buildRelationSelect( + type: string, + include: string | string[], + query: Record | undefined, + ) { + const typeInfo = this.getModelInfo(type); + if (!typeInfo) { + return { select: undefined, error: this.makeUnsupportedModelError(type) }; + } + + const result: any = {}; + const allIncludes: string[] = []; + + for (const includeItem of enumerate(include)) { + const inclusions = includeItem.split(',').filter((i) => i); + for (const inclusion of inclusions) { + allIncludes.push(inclusion); + + const parts = inclusion.split('.'); + let currPayload = result; + let currType = typeInfo; + + for (let i = 0; i < parts.length; i++) { + const relation = parts[i]!; + const relationInfo = currType.relationships[relation]; + if (!relationInfo) { + return { select: undefined, error: this.makeUnsupportedRelationshipError(type, relation, 400) }; + } + + currType = this.getModelInfo(relationInfo.type)!; + if (!currType) { + return { select: undefined, error: this.makeUnsupportedModelError(relationInfo.type) }; + } + + // handle partial results for requested type + const { select, error } = this.buildPartialSelect(lowerCaseFirst(relationInfo.type), query); + if (error) return { select: undefined, error }; + + if (i !== parts.length - 1) { + if (select) { + currPayload[relation] = { select: { ...select } }; + currPayload = currPayload[relation].select; + } else { + currPayload[relation] = { include: { ...currPayload[relation]?.include } }; + currPayload = currPayload[relation].include; + } + } else { + currPayload[relation] = select + ? { + select: { ...select }, + } + : true; + } + } + } + } + + return { select: result, error: undefined, allIncludes }; + } + + private makeFilterValue(fieldDef: FieldDef, value: string, op: FilterOperationType): any { + // TODO: inequality filters? + if (fieldDef.relation) { + // relation filter is converted to an ID filter + const info = this.getModelInfo(fieldDef.type)!; + if (fieldDef.array) { + // filtering a to-many relation, imply 'some' operator + const values = value.split(',').filter((i) => i); + const filterValue = + values.length > 1 + ? { OR: values.map((v) => this.makeIdFilter(info.idFields, v, false)) } + : this.makeIdFilter(info.idFields, value, false); + return { some: filterValue }; + } else { + const values = value.split(',').filter((i) => i); + if (values.length > 1) { + return { OR: values.map((v) => this.makeIdFilter(info.idFields, v, false)) }; + } else { + return { is: this.makeIdFilter(info.idFields, value, false) }; + } + } + } else { + if (op === 'between') { + const parts = value.split(',').map((v) => this.coerce(fieldDef, v)); + if (parts.length !== 2) { + throw new InvalidValueError(`"between" expects exactly 2 comma-separated values`); + } + return { between: [parts[0]!, parts[1]!] }; + } + const coerced = this.coerce(fieldDef, value); + switch (op) { + case 'icontains': + return { contains: coerced, mode: 'insensitive' }; + case 'hasSome': + case 'hasEvery': { + const values = value + .split(',') + .filter((i) => i) + .map((v) => this.coerce(fieldDef, v)); + return { [op]: values }; + } + case 'isEmpty': + if (value !== 'true' && value !== 'false') { + throw new InvalidValueError(`Not a boolean: ${value}`); + } + return { isEmpty: value === 'true' ? true : false }; + default: + if (op === undefined) { + if (fieldDef.attributes?.some((attr) => attr.name === '@json')) { + // handle JSON value equality filter + return { equals: coerced }; + } + + // regular filter, split value by comma + const values = value + .split(',') + .filter((i) => i) + .map((v) => this.coerce(fieldDef, v)); + return values.length > 1 ? { in: values } : { equals: values[0] }; + } else { + return { [op]: coerced }; + } + } + } + } + + private injectRelationQuery( + type: string, + injectTarget: any, + injectKey: string, + query: Record | undefined, + ) { + const { filter, error: filterError } = this.buildFilter(type, query); + if (filterError) { + return filterError; + } + + if (filter) { + injectTarget[injectKey] = { ...injectTarget[injectKey], where: filter }; + } + + const { sort, error: sortError } = this.buildSort(type, query); + if (sortError) { + return sortError; + } + if (sort) { + injectTarget[injectKey] = { ...injectTarget[injectKey], orderBy: sort }; + } + + const pagination = this.getPagination(query); + const offset = pagination.offset; + if (offset > 0) { + // inject skip + injectTarget[injectKey] = { ...injectTarget[injectKey], skip: offset }; + } + const limit = pagination.limit; + if (limit !== Infinity) { + // inject take + injectTarget[injectKey] = { ...injectTarget[injectKey], take: limit }; + + // include a count query for the relationship + injectTarget._count = { select: { [injectKey]: true } }; + } + } + + private handleORMError(err: ORMError) { + return match(err.reason) + .with(ORMErrorReason.INVALID_INPUT, () => { + return this.makeError('validationError', err.message, 422); + }) + .with(ORMErrorReason.REJECTED_BY_POLICY, () => { + return this.makeError('forbidden', err.message, 403, { reason: err.rejectedByPolicyReason }); + }) + .with(ORMErrorReason.NOT_FOUND, () => { + return this.makeError('notFound', err.message, 404); + }) + .with(ORMErrorReason.DB_QUERY_ERROR, () => { + return this.makeError('queryError', err.message, 400, { + dbErrorCode: err.dbErrorCode, + }); + }) + .otherwise(() => { + return this.makeError('unknownError', err.message); + }); + } + + private makeError( + code: keyof typeof this.errors, + detail?: string, + status?: number, + otherFields: Record = {}, + ) { + status = status ?? this.errors[code]?.status ?? 500; + const error: any = { + status, + code: paramCase(code), + title: this.errors[code]?.title, + }; + + if (detail) { + error.detail = detail; + } + + Object.assign(error, otherFields); + + return { + status, + body: { + errors: [error], + }, + }; + } + + private makeUnsupportedModelError(model: string) { + return this.makeError('unsupportedModel', `Model ${model} doesn't exist`); + } + + private makeUnsupportedRelationshipError(model: string, relationship: string, status: number) { + return this.makeError('unsupportedRelationship', `Relationship ${model}.${relationship} doesn't exist`, status); + } + + //#endregion + + async generateSpec(options?: OpenApiSpecOptions) { + const generator = new RestApiSpecGenerator(this.options); + return generator.generateSpec(options); + } +} diff --git a/packages/server/src/api/rest/index.ts b/packages/server/src/api/rest/index.ts index c2723f061..22b87a1fc 100644 --- a/packages/server/src/api/rest/index.ts +++ b/packages/server/src/api/rest/index.ts @@ -1,2204 +1,2 @@ -import { clone, enumerate, lowerCaseFirst, paramCase } from '@zenstackhq/common-helpers'; -import { ORMError, ORMErrorReason, type ClientContract } from '@zenstackhq/orm'; -import type { FieldDef, ModelDef, SchemaDef } from '@zenstackhq/orm/schema'; -import { Decimal } from 'decimal.js'; -import SuperJSON from 'superjson'; -import tsjapi, { type Linker, type Paginator, type Relator, type Serializer, type SerializerOptions } from 'ts-japi'; -import { match } from 'ts-pattern'; -import UrlPattern from 'url-pattern'; -import z from 'zod'; -import { fromError } from 'zod-validation-error/v4'; -import type { ApiHandler, LogConfig, RequestContext, Response } from '../../types'; -import { getProcedureDef, mapProcedureArgs } from '../common/procedures'; -import { loggerSchema } from '../common/schemas'; -import { processSuperJsonRequestPayload } from '../common/utils'; -import { getZodErrorMessage, log, registerCustomSerializers } from '../utils'; - -/** - * Options for {@link RestApiHandler} - */ -export type RestApiHandlerOptions = { - /** - * The schema - */ - schema: Schema; - - /** - * Logging configuration - */ - log?: LogConfig; - - /** - * The base endpoint of the RESTful API, must be a valid URL - */ - endpoint: string; - - /** - * The default page size for limiting the number of results returned - * from collection queries, including resource collection, related data - * of collection types, and relationship of collection types. - * - * Defaults to 100. Set to Infinity to disable pagination. - */ - pageSize?: number; - - /** - * The divider used to separate compound ID fields in the URL. - * Defaults to '_'. - */ - idDivider?: string; - - /** - * The charset used for URL segment values. Defaults to `a-zA-Z0-9-_~ %`. You can change it if your entity's ID values - * allow different characters. Specifically, if your models use compound IDs and the idDivider is set to a different value, - * it should be included in the charset. - */ - urlSegmentCharset?: string; - - /** - * Mapping from model names to URL segment names. - */ - modelNameMapping?: Record; - - /** - * Mapping from model names to unique field name to be used as resource's ID. - */ - externalIdMapping?: Record; -}; - -type RelationshipInfo = { - type: string; - idFields: FieldDef[]; - isCollection: boolean; - isOptional: boolean; -}; - -type ModelInfo = { - name: string; - idFields: FieldDef[]; - fields: Record; - relationships: Record; -}; - -type Match = { - type: string; - id: string; - relationship: string; -}; - -enum UrlPatterns { - SINGLE = 'single', - FETCH_RELATIONSHIP = 'fetchRelationship', - RELATIONSHIP = 'relationship', - COLLECTION = 'collection', -} - -class InvalidValueError extends Error { - constructor(message: string) { - super(message); - } -} - -const DEFAULT_PAGE_SIZE = 100; - -const FilterOperations = [ - 'lt', - 'lte', - 'gt', - 'gte', - 'between', - 'contains', - 'icontains', - 'search', - 'startsWith', - 'endsWith', - 'has', - 'hasEvery', - 'hasSome', - 'isEmpty', -] as const; - -type FilterOperationType = (typeof FilterOperations)[number] | undefined; - -const DEFAULT_ID_DIVIDER = '_'; - -registerCustomSerializers(); - -/** - * RESTful-style API request handler (compliant with JSON:API) - */ -export class RestApiHandler implements ApiHandler { - // resource serializers - private serializers = new Map(); - - // error responses - private readonly errors: Record = { - unsupportedModel: { - status: 404, - title: 'Unsupported model type', - detail: 'The model type is not supported', - }, - unsupportedRelationship: { - status: 400, - title: 'Unsupported relationship', - detail: 'The relationship is not supported', - }, - invalidPath: { - status: 400, - title: 'The request path is invalid', - }, - invalidVerb: { - status: 400, - title: 'The HTTP verb is not supported', - }, - notFound: { - status: 404, - title: 'Resource not found', - }, - noId: { - status: 400, - title: 'Model without an ID field is not supported', - }, - invalidId: { - status: 400, - title: 'Resource ID is invalid', - }, - invalidPayload: { - status: 400, - title: 'Invalid payload', - }, - invalidRelationData: { - status: 400, - title: 'Invalid relation data', - detail: 'Invalid relationship data', - }, - invalidRelation: { - status: 400, - title: 'Invalid relation', - detail: 'Invalid relationship', - }, - invalidFilter: { - status: 400, - title: 'Invalid filter', - }, - invalidSort: { - status: 400, - title: 'Invalid sort', - }, - invalidValue: { - status: 400, - title: 'Invalid value for type', - }, - duplicatedFieldsParameter: { - status: 400, - title: 'Fields Parameter Duplicated', - }, - forbidden: { - status: 403, - title: 'Operation is forbidden', - }, - validationError: { - status: 422, - title: 'Operation is unprocessable due to validation errors', - }, - queryError: { - status: 400, - title: 'Error occurred while executing the query', - }, - unknownError: { - status: 500, - title: 'Unknown error', - }, - }; - - private filterParamPattern = new RegExp(/^filter(?(\[[^[\]]+\])+)$/); - - // zod schema for payload of creating and updating a resource - private createUpdatePayloadSchema = z - .object({ - data: z.object({ - type: z.string(), - attributes: z.object({}).passthrough().optional(), - relationships: z - .record( - z.string(), - z.object({ - data: z.union([ - z.object({ type: z.string(), id: z.union([z.string(), z.number()]) }), - z.array(z.object({ type: z.string(), id: z.union([z.string(), z.number()]) })), - ]), - }), - ) - .optional(), - }), - meta: z.object({}).passthrough().optional(), - }) - .strict(); - - // zod schema for updating a single relationship - private updateSingleRelationSchema = z.object({ - data: z.object({ type: z.string(), id: z.union([z.string(), z.number()]) }).nullable(), - }); - - // zod schema for updating collection relationship - private updateCollectionRelationSchema = z.object({ - data: z.array(z.object({ type: z.string(), id: z.union([z.string(), z.number()]) })), - }); - - private upsertMetaSchema = z.object({ - meta: z.object({ - operation: z.literal('upsert'), - matchFields: z.array(z.string()).min(1), - }), - }); - - // all known types and their metadata - private typeMap: Record = {}; - - // divider used to separate compound ID fields - private idDivider; - - private urlPatternMap: Record; - private modelNameMapping: Record; - private reverseModelNameMapping: Record; - private externalIdMapping: Record; - - constructor(private readonly options: RestApiHandlerOptions) { - this.validateOptions(options); - - this.idDivider = options.idDivider ?? DEFAULT_ID_DIVIDER; - const segmentCharset = options.urlSegmentCharset ?? 'a-zA-Z0-9-_~ %'; - - this.modelNameMapping = options.modelNameMapping ?? {}; - this.modelNameMapping = Object.fromEntries( - Object.entries(this.modelNameMapping).map(([k, v]) => [lowerCaseFirst(k), v]), - ); - this.reverseModelNameMapping = Object.fromEntries( - Object.entries(this.modelNameMapping).map(([k, v]) => [v, k]), - ); - - this.externalIdMapping = options.externalIdMapping ?? {}; - this.externalIdMapping = Object.fromEntries( - Object.entries(this.externalIdMapping).map(([k, v]) => [lowerCaseFirst(k), v]), - ); - - this.urlPatternMap = this.buildUrlPatternMap(segmentCharset); - - this.buildTypeMap(); - this.buildSerializers(); - } - - private validateOptions(options: RestApiHandlerOptions) { - const schema = z.strictObject({ - schema: z.object(), - log: loggerSchema.optional(), - endpoint: z.string().min(1), - pageSize: z.union([z.number().int().positive(), z.literal(Infinity)]).optional(), - idDivider: z.string().min(1).optional(), - urlSegmentCharset: z.string().min(1).optional(), - modelNameMapping: z.record(z.string(), z.string()).optional(), - externalIdMapping: z.record(z.string(), z.string()).optional(), - }); - const parseResult = schema.safeParse(options); - if (!parseResult.success) { - throw new Error(`Invalid options: ${fromError(parseResult.error)}`); - } - } - - get schema() { - return this.options.schema; - } - - get log(): LogConfig | undefined { - return this.options.log; - } - - private buildUrlPatternMap(urlSegmentNameCharset: string): Record { - const options = { segmentValueCharset: urlSegmentNameCharset }; - - const buildPath = (segments: string[]) => { - return '/' + segments.join('/'); - }; - - return { - [UrlPatterns.SINGLE]: new UrlPattern(buildPath([':type', ':id']), options), - [UrlPatterns.FETCH_RELATIONSHIP]: new UrlPattern(buildPath([':type', ':id', ':relationship']), options), - [UrlPatterns.RELATIONSHIP]: new UrlPattern( - buildPath([':type', ':id', 'relationships', ':relationship']), - options, - ), - [UrlPatterns.COLLECTION]: new UrlPattern(buildPath([':type']), options), - }; - } - - private mapModelName(modelName: string): string { - return this.modelNameMapping[modelName] ?? modelName; - } - - private matchUrlPattern(path: string, routeType: UrlPatterns): Match | undefined { - const pattern = this.urlPatternMap[routeType]; - if (!pattern) { - throw new InvalidValueError(`Unknown route type: ${routeType}`); - } - - const match = pattern.match(path); - if (!match) { - return; - } - - if (match.type in this.modelNameMapping) { - throw new InvalidValueError( - `use the mapped model name: ${this.modelNameMapping[match.type]} and not ${match.type}`, - ); - } - - if (match.type in this.reverseModelNameMapping) { - match.type = this.reverseModelNameMapping[match.type]; - } - - return match; - } - - async handleRequest({ client, method, path, query, requestBody }: RequestContext): Promise { - method = method.toUpperCase(); - if (!path.startsWith('/')) { - path = '/' + path; - } - - try { - if (path.startsWith('/$procs/')) { - const proc = path.split('/')[2]; - return await this.processProcedureRequest({ client, method, proc, query, requestBody }); - } - - switch (method) { - case 'GET': { - let match = this.matchUrlPattern(path, UrlPatterns.SINGLE); - if (match) { - // single resource read - return await this.processSingleRead(client, match.type, match.id, query); - } - match = this.matchUrlPattern(path, UrlPatterns.FETCH_RELATIONSHIP); - if (match) { - // fetch related resource(s) - return await this.processFetchRelated(client, match.type, match.id, match.relationship, query); - } - - match = this.matchUrlPattern(path, UrlPatterns.RELATIONSHIP); - if (match) { - // read relationship - return await this.processReadRelationship( - client, - match.type, - match.id, - match.relationship, - query, - ); - } - - match = this.matchUrlPattern(path, UrlPatterns.COLLECTION); - if (match) { - // collection read - return await this.processCollectionRead(client, match.type, query); - } - - return this.makeError('invalidPath'); - } - - case 'POST': { - if (!requestBody) { - return this.makeError('invalidPayload'); - } - let match = this.matchUrlPattern(path, UrlPatterns.COLLECTION); - if (match) { - const body = requestBody as any; - const upsertMeta = this.upsertMetaSchema.safeParse(body); - if (upsertMeta.success) { - // resource upsert - return await this.processUpsert(client, match.type, query, requestBody); - } else { - // resource creation - return await this.processCreate(client, match.type, query, requestBody); - } - } - match = this.matchUrlPattern(path, UrlPatterns.RELATIONSHIP); - if (match) { - // relationship creation (collection relationship only) - return await this.processRelationshipCRUD( - client, - 'create', - match.type, - match.id, - match.relationship, - query, - requestBody, - ); - } - - return this.makeError('invalidPath'); - } - - // TODO: PUT for full update - case 'PUT': - case 'PATCH': { - if (!requestBody) { - return this.makeError('invalidPayload'); - } - let match = this.matchUrlPattern(path, UrlPatterns.SINGLE); - if (match) { - // resource update - return await this.processUpdate(client, match.type, match.id, query, requestBody); - } - match = this.matchUrlPattern(path, UrlPatterns.RELATIONSHIP); - if (match) { - // relationship update - return await this.processRelationshipCRUD( - client, - 'update', - match.type, - match.id, - match.relationship as string, - query, - requestBody, - ); - } - - return this.makeError('invalidPath'); - } - - case 'DELETE': { - let match = this.matchUrlPattern(path, UrlPatterns.SINGLE); - if (match) { - // resource deletion - return await this.processDelete(client, match.type, match.id); - } - - match = this.matchUrlPattern(path, UrlPatterns.RELATIONSHIP); - if (match) { - // relationship deletion (collection relationship only) - return await this.processRelationshipCRUD( - client, - 'delete', - match.type, - match.id, - match.relationship as string, - query, - requestBody, - ); - } - - return this.makeError('invalidPath'); - } - - default: - return this.makeError('invalidPath'); - } - } catch (err) { - if (err instanceof InvalidValueError) { - return this.makeError('invalidValue', err.message); - } else if (err instanceof ORMError) { - return this.handleORMError(err); - } else { - return this.handleGenericError(err); - } - } - } - - private handleGenericError(err: unknown): Response | PromiseLike { - return this.makeError('unknownError', err instanceof Error ? `${err.message}\n${err.stack}` : 'Unknown error'); - } - - private async processProcedureRequest({ - client, - method, - proc, - query, - requestBody, - }: { - client: ClientContract; - method: string; - proc?: string; - query?: Record; - requestBody?: unknown; - }): Promise { - if (!proc) { - return this.makeProcBadInputErrorResponse('missing procedure name'); - } - - const procDef = getProcedureDef(this.schema, proc); - if (!procDef) { - return this.makeProcBadInputErrorResponse(`unknown procedure: ${proc}`); - } - - const isMutation = !!procDef.mutation; - if (isMutation) { - if (method !== 'POST') { - return this.makeProcBadInputErrorResponse('invalid request method, only POST is supported'); - } - } else { - if (method !== 'GET') { - return this.makeProcBadInputErrorResponse('invalid request method, only GET is supported'); - } - } - - const argsPayload = method === 'POST' ? requestBody : query; - - // support SuperJSON request payload format - const { result: processedArgsPayload, error } = await processSuperJsonRequestPayload(argsPayload); - if (error) { - return this.makeProcBadInputErrorResponse(error); - } - - let procInput: unknown; - try { - procInput = mapProcedureArgs(procDef, processedArgsPayload); - } catch (err) { - return this.makeProcBadInputErrorResponse( - err instanceof Error ? err.message : 'invalid procedure arguments', - ); - } - - try { - log(this.log, 'debug', () => `handling "$procs.${proc}" request`); - - const clientResult = await (client as any).$procs?.[proc](procInput); - const toSerialize = this.toPlainObject(clientResult); - - const { json, meta } = SuperJSON.serialize(toSerialize); - const responseBody: any = { data: json }; - if (meta) { - responseBody.meta = { serialization: meta }; - } - - return { status: 200, body: responseBody }; - } catch (err) { - log(this.log, 'error', `error occurred when handling "$procs.${proc}" request`, err); - if (err instanceof ORMError) { - throw err; // top-level handler will take care of it - } - return this.makeProcGenericErrorResponse(err); - } - } - - private makeProcBadInputErrorResponse(message: string): Response { - const resp = this.makeError('invalidPayload', message, 400); - log(this.log, 'debug', () => `sending error response: ${JSON.stringify(resp)}`); - return resp; - } - - private makeProcGenericErrorResponse(err: unknown): Response { - const message = err instanceof Error ? err.message : 'unknown error'; - const resp = this.makeError('unknownError', message, 500); - log(this.log, 'debug', () => `sending error response: ${JSON.stringify(resp)}`); - return resp; - } - - private async processSingleRead( - client: ClientContract, - type: string, - resourceId: string, - query: Record | undefined, - ): Promise { - const typeInfo = this.getModelInfo(type); - if (!typeInfo) { - return this.makeUnsupportedModelError(type); - } - - const args: any = { where: this.makeIdFilter(typeInfo.idFields, resourceId) }; - - // include IDs of relation fields so that they can be serialized - this.includeRelationshipIds(type, args, 'include'); - - // handle "include" query parameter - let include: string[] | undefined; - if (query?.['include']) { - const { select, error, allIncludes } = this.buildRelationSelect(type, query['include'], query); - if (error) { - return error; - } - if (select) { - args.include = { ...args.include, ...select }; - } - include = allIncludes; - } - - // handle partial results for requested type - const { select, error } = this.buildPartialSelect(type, query); - if (error) return error; - if (select) { - args.select = { ...select, ...args.select }; - if (args.include) { - args.select = { - ...args.select, - ...args.include, - }; - args.include = undefined; - } - } - - const entity = await (client as any)[type].findUnique(args); - - if (entity) { - return { - status: 200, - body: await this.serializeItems(type, entity, { include }), - }; - } else { - return this.makeError('notFound'); - } - } - - private async processFetchRelated( - client: ClientContract, - type: string, - resourceId: string, - relationship: string, - query: Record | undefined, - ): Promise { - const typeInfo = this.getModelInfo(type); - if (!typeInfo) { - return this.makeUnsupportedModelError(type); - } - - const relationInfo = typeInfo.relationships[relationship]; - if (!relationInfo) { - return this.makeUnsupportedRelationshipError(type, relationship, 404); - } - - let select: any; - - // handle "include" query parameter - let include: string[] | undefined; - if (query?.['include']) { - const { - select: relationSelect, - error, - allIncludes, - } = this.buildRelationSelect(type, query['include'], query); - if (error) { - return error; - } - // trim the leading `$relationship.` from the include paths - include = allIncludes - .filter((i) => i.startsWith(`${relationship}.`)) - .map((i) => i.substring(`${relationship}.`.length)); - select = relationSelect; - } - - // handle partial results for requested type - if (!select) { - const { select: partialFields, error } = this.buildPartialSelect(lowerCaseFirst(relationInfo.type), query); - if (error) return error; - - select = partialFields ? { [relationship]: { select: { ...partialFields } } } : { [relationship]: true }; - } - - const args: any = { - where: this.makeIdFilter(typeInfo.idFields, resourceId), - select, - }; - - if (relationInfo.isCollection) { - // if related data is a collection, it can be filtered, sorted, and paginated - const error = this.injectRelationQuery(relationInfo.type, select, relationship, query); - if (error) { - return error; - } - } - - const entity: any = await (client as any)[type].findUnique(args); - - let paginator: Paginator | undefined; - - if (entity?._count?.[relationship] !== undefined) { - // build up paginator - const total = entity?._count?.[relationship] as number; - const url = this.makeNormalizedUrl(`/${type}/${resourceId}/${relationship}`, query); - const { offset, limit } = this.getPagination(query); - paginator = this.makePaginator(url, offset, limit, total); - } - - if (entity?.[relationship]) { - const mappedType = this.mapModelName(type); - return { - status: 200, - body: await this.serializeItems(relationInfo.type, entity[relationship], { - linkers: { - document: new tsjapi.Linker(() => - this.makeLinkUrl(`/${mappedType}/${resourceId}/${relationship}`), - ), - paginator, - }, - include, - }), - }; - } else { - return this.makeError('notFound'); - } - } - - private async processReadRelationship( - client: ClientContract, - type: string, - resourceId: string, - relationship: string, - query: Record | undefined, - ): Promise { - const typeInfo = this.getModelInfo(type); - if (!typeInfo) { - return this.makeUnsupportedModelError(type); - } - - const relationInfo = typeInfo.relationships[relationship]; - if (!relationInfo) { - return this.makeUnsupportedRelationshipError(type, relationship, 404); - } - - const args: any = { - where: this.makeIdFilter(typeInfo.idFields, resourceId), - select: this.makeIdSelect(typeInfo.idFields), - }; - - // include IDs of relation fields so that they can be serialized - args.select = { ...args.select, [relationship]: { select: this.makeIdSelect(relationInfo.idFields) } }; - - let paginator: Paginator | undefined; - - if (relationInfo.isCollection) { - // if related data is a collection, it can be filtered, sorted, and paginated - const error = this.injectRelationQuery(relationInfo.type, args.select, relationship, query); - if (error) { - return error; - } - } - - const entity: any = await (client as any)[type].findUnique(args); - const mappedType = this.mapModelName(type); - - if (entity?._count?.[relationship] !== undefined) { - // build up paginator - const total = entity?._count?.[relationship] as number; - const url = this.makeNormalizedUrl(`/${mappedType}/${resourceId}/relationships/${relationship}`, query); - const { offset, limit } = this.getPagination(query); - paginator = this.makePaginator(url, offset, limit, total); - } - - if (entity?.[relationship]) { - const serialized: any = await this.serializeItems(relationInfo.type, entity[relationship], { - linkers: { - document: new tsjapi.Linker(() => - this.makeLinkUrl(`/${mappedType}/${resourceId}/relationships/${relationship}`), - ), - paginator, - }, - onlyIdentifier: true, - }); - - return { - status: 200, - body: serialized, - }; - } else { - return this.makeError('notFound'); - } - } - - private async processCollectionRead( - client: ClientContract, - type: string, - query: Record | undefined, - ): Promise { - const typeInfo = this.getModelInfo(type); - if (!typeInfo) { - return this.makeUnsupportedModelError(type); - } - - const args: any = {}; - - // add filter - const { filter, error: filterError } = this.buildFilter(type, query); - if (filterError) { - return filterError; - } - if (filter) { - args.where = filter; - } - - const { sort, error: sortError } = this.buildSort(type, query); - if (sortError) { - return sortError; - } - if (sort) { - args.orderBy = sort; - } - - // include IDs of relation fields so that they can be serialized - this.includeRelationshipIds(type, args, 'include'); - - // handle "include" query parameter - let include: string[] | undefined; - if (query?.['include']) { - const { select, error, allIncludes } = this.buildRelationSelect(type, query['include'], query); - if (error) { - return error; - } - if (select) { - args.include = { ...args.include, ...select }; - } - include = allIncludes; - } - - // handle partial results for requested type - const { select, error } = this.buildPartialSelect(type, query); - if (error) return error; - if (select) { - args.select = { ...select, ...args.select }; - if (args.include) { - args.select = { - ...args.select, - ...args.include, - }; - args.include = undefined; - } - } - - const { offset, limit } = this.getPagination(query); - if (offset > 0) { - args.skip = offset; - } - - if (limit === Infinity) { - const entities = await (client as any)[type].findMany(args); - - const body = await this.serializeItems(type, entities, { include }); - const total = entities.length; - body.meta = this.addTotalCountToMeta(body.meta, total); - - return { - status: 200, - body: body, - }; - } else { - args.take = limit; - - const [entities, count] = await Promise.all([ - (client as any)[type].findMany(args), - (client as any)[type].count({ where: args.where ?? {} }), - ]); - const total = count as number; - - const mappedType = this.mapModelName(type); - const url = this.makeNormalizedUrl(`/${mappedType}`, query); - const options: Partial = { - include, - linkers: { - paginator: this.makePaginator(url, offset, limit, total), - }, - }; - const body = await this.serializeItems(type, entities, options); - body.meta = this.addTotalCountToMeta(body.meta, total); - - return { - status: 200, - body: body, - }; - } - } - - private buildPartialSelect(type: string, query: Record | undefined) { - const selectFieldsQuery = query?.[`fields[${type}]`]; - if (!selectFieldsQuery) { - return { select: undefined, error: undefined }; - } - - if (Array.isArray(selectFieldsQuery)) { - return { - select: undefined, - error: this.makeError('duplicatedFieldsParameter', `duplicated fields query for type ${type}`), - }; - } - - const typeInfo = this.getModelInfo(type); - if (!typeInfo) { - return { select: undefined, error: this.makeUnsupportedModelError(type) }; - } - - const selectFieldNames = selectFieldsQuery.split(',').filter((i) => i); - - const fields = selectFieldNames.reduce((acc, curr) => ({ ...acc, [curr]: true }), {}); - - return { - select: { ...this.makeIdSelect(typeInfo.idFields), ...fields }, - }; - } - - private addTotalCountToMeta(meta: any, total: any) { - return meta ? Object.assign(meta, { total }) : Object.assign({}, { total }); - } - - private makePaginator(baseUrl: string, offset: number, limit: number, total: number) { - if (limit === Infinity) { - return undefined; - } - - const totalPages = Math.ceil(total / limit); - - return new tsjapi.Paginator(() => ({ - first: this.replaceURLSearchParams(baseUrl, { 'page[limit]': limit }), - last: this.replaceURLSearchParams(baseUrl, { - 'page[offset]': (totalPages - 1) * limit, - }), - prev: - offset - limit >= 0 && offset - limit <= total - 1 - ? this.replaceURLSearchParams(baseUrl, { - 'page[offset]': offset - limit, - 'page[limit]': limit, - }) - : null, - next: - offset + limit <= total - 1 - ? this.replaceURLSearchParams(baseUrl, { - 'page[offset]': offset + limit, - 'page[limit]': limit, - }) - : null, - })); - } - - private processRequestBody(requestBody: unknown) { - let body: any = requestBody; - if (body.meta?.serialization) { - // superjson deserialize body if a serialization meta is provided - body = SuperJSON.deserialize({ json: body, meta: body.meta.serialization }); - } - - const parseResult = this.createUpdatePayloadSchema.safeParse(body); - if (!parseResult.success) { - return { - attributes: undefined, - relationships: undefined, - error: this.makeError('invalidPayload', getZodErrorMessage(parseResult.error)), - }; - } - - return { - attributes: parseResult.data.data.attributes, - relationships: parseResult.data.data.relationships, - error: undefined, - }; - } - - private async processCreate( - client: ClientContract, - type: string, - _query: Record | undefined, - requestBody: unknown, - ): Promise { - const typeInfo = this.getModelInfo(type); - if (!typeInfo) { - return this.makeUnsupportedModelError(type); - } - - const { attributes, relationships, error } = this.processRequestBody(requestBody); - if (error) { - return error; - } - - const createPayload: any = { data: { ...attributes } }; - - // turn relationship payload into `connect` objects - if (relationships) { - for (const [key, data] of Object.entries(relationships)) { - if (!data?.data) { - return this.makeError('invalidRelationData'); - } - - const relationInfo = typeInfo.relationships[key]; - if (!relationInfo) { - return this.makeUnsupportedRelationshipError(type, key, 400); - } - - if (relationInfo.isCollection) { - createPayload.data[key] = { - connect: enumerate(data.data).map((item: any) => - this.makeIdConnect(relationInfo.idFields, item.id), - ), - }; - } else { - if (typeof data.data !== 'object') { - return this.makeError('invalidRelationData'); - } - createPayload.data[key] = { - connect: this.makeIdConnect(relationInfo.idFields, data.data.id), - }; - } - - // make sure ID fields are included for result serialization - createPayload.include = { - ...createPayload.include, - [key]: { select: { [this.makeDefaultIdKey(relationInfo.idFields)]: true } }, - }; - } - } - - // include IDs of relation fields so that they can be serialized. - this.includeRelationshipIds(type, createPayload, 'include'); - - const entity = await (client as any)[type].create(createPayload); - return { - status: 201, - body: await this.serializeItems(type, entity), - }; - } - - private async processUpsert( - client: ClientContract, - type: string, - _query: Record | undefined, - requestBody: unknown, - ) { - const typeInfo = this.getModelInfo(type); - if (!typeInfo) { - return this.makeUnsupportedModelError(type); - } - - const modelName = typeInfo.name; - const { attributes, relationships, error } = this.processRequestBody(requestBody); - if (error) { - return error; - } - - const parseResult = this.upsertMetaSchema.safeParse(requestBody); - if (parseResult.error) { - return this.makeError('invalidPayload', getZodErrorMessage(parseResult.error)); - } - const matchFields = parseResult.data.meta.matchFields; - const uniqueFieldSets = this.getUniqueFieldSets(modelName); - - if (!uniqueFieldSets.some((set) => set.every((field) => matchFields.includes(field)))) { - return this.makeError('invalidPayload', 'Match fields must be unique fields', 400); - } - - const upsertPayload: any = { - where: this.makeUpsertWhere(matchFields, attributes, typeInfo), - create: { ...attributes }, - update: { - ...Object.fromEntries(Object.entries(attributes ?? {}).filter((e) => !matchFields.includes(e[0]))), - }, - }; - - if (relationships) { - for (const [key, data] of Object.entries(relationships)) { - if (!data?.data) { - return this.makeError('invalidRelationData'); - } - - const relationInfo = typeInfo.relationships[key]; - if (!relationInfo) { - return this.makeUnsupportedRelationshipError(modelName, key, 400); - } - - if (relationInfo.isCollection) { - upsertPayload.create[key] = { - connect: enumerate(data.data).map((item: any) => - this.makeIdConnect(relationInfo.idFields, item.id), - ), - }; - upsertPayload.update[key] = { - set: enumerate(data.data).map((item: any) => - this.makeIdConnect(relationInfo.idFields, item.id), - ), - }; - } else { - if (typeof data.data !== 'object') { - return this.makeError('invalidRelationData'); - } - upsertPayload.create[key] = { - connect: this.makeIdConnect(relationInfo.idFields, data.data.id), - }; - upsertPayload.update[key] = { - connect: this.makeIdConnect(relationInfo.idFields, data.data.id), - }; - } - } - } - - // include IDs of relation fields so that they can be serialized. - this.includeRelationshipIds(modelName, upsertPayload, 'include'); - - const entity = await (client as any)[modelName].upsert(upsertPayload); - - return { - status: 201, - body: await this.serializeItems(modelName, entity), - }; - } - - private getUniqueFieldSets(type: string) { - const modelDef = this.requireModel(type); - return Object.entries(modelDef.uniqueFields).map( - ([k, v]) => - typeof v.type === 'string' - ? [k] // single unique field - : Object.keys(v), // compound unique fields - ); - } - - private async processRelationshipCRUD( - client: ClientContract, - mode: 'create' | 'update' | 'delete', - type: string, - resourceId: string, - relationship: string, - _query: Record | undefined, - requestBody: unknown, - ): Promise { - const typeInfo = this.getModelInfo(type); - if (!typeInfo) { - return this.makeUnsupportedModelError(type); - } - - const relationInfo = typeInfo.relationships[relationship]; - if (!relationInfo) { - return this.makeUnsupportedRelationshipError(type, relationship, 404); - } - - if (!relationInfo.isCollection && mode !== 'update') { - // to-one relation can only be updated - return this.makeError('invalidVerb'); - } - - const updateArgs: any = { - where: this.makeIdFilter(typeInfo.idFields, resourceId), - select: { - ...typeInfo.idFields.reduce((acc, field) => ({ ...acc, [field.name]: true }), {}), - [relationship]: { select: this.makeIdSelect(relationInfo.idFields) }, - }, - }; - - if (!relationInfo.isCollection) { - // zod-parse payload - const parsed = this.updateSingleRelationSchema.safeParse(requestBody); - if (!parsed.success) { - return this.makeError('invalidPayload', getZodErrorMessage(parsed.error)); - } - - if (parsed.data.data === null) { - if (!relationInfo.isOptional) { - // cannot disconnect a required relation - return this.makeError('invalidPayload'); - } - // set null -> disconnect - updateArgs.data = { - [relationship]: { - disconnect: true, - }, - }; - } else { - updateArgs.data = { - [relationship]: { - connect: this.makeIdConnect(relationInfo.idFields, parsed.data.data.id), - }, - }; - } - } else { - // zod-parse payload - const parsed = this.updateCollectionRelationSchema.safeParse(requestBody); - if (!parsed.success) { - return this.makeError('invalidPayload', getZodErrorMessage(parsed.error)); - } - - // create -> connect, delete -> disconnect, update -> set - const relationVerb = mode === 'create' ? 'connect' : mode === 'delete' ? 'disconnect' : 'set'; - - updateArgs.data = { - [relationship]: { - [relationVerb]: enumerate(parsed.data.data).map((item: any) => - this.makeIdFilter(relationInfo.idFields, item.id), - ), - }, - }; - } - - const entity: any = await (client as any)[type].update(updateArgs); - - const mappedType = this.mapModelName(type); - - const serialized: any = await this.serializeItems(relationInfo.type, entity[relationship], { - linkers: { - document: new tsjapi.Linker(() => - this.makeLinkUrl(`/${mappedType}/${resourceId}/relationships/${relationship}`), - ), - }, - onlyIdentifier: true, - }); - - return { - status: 200, - body: serialized, - }; - } - - private async processUpdate( - client: ClientContract, - type: any, - resourceId: string, - _query: Record | undefined, - requestBody: unknown, - ): Promise { - const typeInfo = this.getModelInfo(type); - if (!typeInfo) { - return this.makeUnsupportedModelError(type); - } - - const { attributes, relationships, error } = this.processRequestBody(requestBody); - if (error) { - return error; - } - - const updatePayload: any = { - where: this.makeIdFilter(typeInfo.idFields, resourceId), - data: { ...attributes }, - }; - - // turn relationships into query payload - if (relationships) { - for (const [key, data] of Object.entries(relationships)) { - if (!data?.data) { - return this.makeError('invalidRelationData'); - } - - const relationInfo = typeInfo.relationships[key]; - if (!relationInfo) { - return this.makeUnsupportedRelationshipError(type, key, 400); - } - - if (relationInfo.isCollection) { - updatePayload.data[key] = { - set: enumerate(data.data).map((item: any) => ({ - [this.makeDefaultIdKey(relationInfo.idFields)]: item.id, - })), - }; - } else { - if (typeof data.data !== 'object') { - return this.makeError('invalidRelationData'); - } - updatePayload.data[key] = { - connect: { - [this.makeDefaultIdKey(relationInfo.idFields)]: data.data.id, - }, - }; - } - updatePayload.include = { - ...updatePayload.include, - [key]: { select: { [this.makeDefaultIdKey(relationInfo.idFields)]: true } }, - }; - } - } - - // include IDs of relation fields so that they can be serialized. - this.includeRelationshipIds(type, updatePayload, 'include'); - - const entity = await (client as any)[type].update(updatePayload); - return { - status: 200, - body: await this.serializeItems(type, entity), - }; - } - - private async processDelete(client: ClientContract, type: any, resourceId: string): Promise { - const typeInfo = this.getModelInfo(type); - if (!typeInfo) { - return this.makeUnsupportedModelError(type); - } - - await (client as any)[type].delete({ - where: this.makeIdFilter(typeInfo.idFields, resourceId), - }); - return { - status: 200, - body: { meta: {} }, - }; - } - - //#region utilities - - private requireModel(model: string): ModelDef { - const modelDef = this.schema.models[model]; - if (!modelDef) { - throw new Error(`Model ${model} is not defined in the schema`); - } - return modelDef; - } - - private getIdFields(model: string): FieldDef[] { - const modelDef = this.requireModel(model); - const modelLower = lowerCaseFirst(model); - if (!(modelLower in this.externalIdMapping)) { - return Object.values(modelDef.fields).filter((f) => modelDef.idFields.includes(f.name)); - } - - // map external ID name to unique constraint field - const externalIdName = this.externalIdMapping[modelLower]; - for (const [name, info] of Object.entries(modelDef.uniqueFields)) { - if (name === externalIdName) { - if (typeof info.type === 'string') { - // single unique field - return [this.requireField(model, name)]; - } else { - // compound unique fields - return Object.keys(info).map((f) => this.requireField(model, f)); - } - } - } - - throw new Error(`Model ${model} does not have unique key ${externalIdName}`); - } - - private requireField(model: string, field: string): FieldDef { - const modelDef = this.requireModel(model); - const fieldDef = modelDef.fields[field]; - if (!fieldDef) { - throw new Error(`Field ${field} is not defined in model ${model}`); - } - return fieldDef; - } - - private buildTypeMap() { - this.typeMap = {}; - for (const [model, { fields }] of Object.entries(this.schema.models)) { - const idFields = this.getIdFields(model); - if (idFields.length === 0) { - log(this.options.log, 'warn', `Not including model ${model} in the API because it has no ID field`); - continue; - } - - const modelInfo: ModelInfo = (this.typeMap[lowerCaseFirst(model)] = { - name: model, - idFields, - relationships: {}, - fields, - }); - - for (const [field, fieldInfo] of Object.entries(fields)) { - if (!fieldInfo.relation) { - continue; - } - const fieldTypeIdFields = this.getIdFields(fieldInfo.type); - if (fieldTypeIdFields.length === 0) { - log( - this.options.log, - 'warn', - `Not including relation ${model}.${field} in the API because it has no ID field`, - ); - continue; - } - - modelInfo.relationships[field] = { - type: fieldInfo.type, - idFields: fieldTypeIdFields, - isCollection: !!fieldInfo.array, - isOptional: !!fieldInfo.optional, - }; - } - } - } - - private getModelInfo(model: string): ModelInfo | undefined { - return this.typeMap[lowerCaseFirst(model)]; - } - - private makeLinkUrl(path: string) { - return `${this.options.endpoint}${path}`; - } - - private buildSerializers() { - const linkers: Record> = {}; - - for (const model of Object.keys(this.schema.models)) { - const ids = this.getIdFields(model); - const modelLower = lowerCaseFirst(model); - const mappedModel = this.mapModelName(modelLower); - - if (ids.length < 1) { - continue; - } - - const linker = new tsjapi.Linker((items) => - Array.isArray(items) - ? this.makeLinkUrl(`/${mappedModel}`) - : this.makeLinkUrl(`/${mappedModel}/${this.getId(model, items)}`), - ); - linkers[modelLower] = linker; - - let projection: Record | null = {}; - const modelDef = this.requireModel(model); - for (const [field, fieldDef] of Object.entries(modelDef.fields)) { - if (fieldDef.relation) { - projection[field] = 0; - } - } - if (Object.keys(projection).length === 0) { - projection = null; - } - - const serializer = new tsjapi.Serializer(model, { - version: '1.1', - idKey: this.makeIdKey(ids), - linkers: { - resource: linker, - document: linker, - }, - projection, - }); - this.serializers.set(modelLower, serializer); - } - - // set relators - for (const model of Object.keys(this.schema.models)) { - const modelLower = lowerCaseFirst(model); - const serializer = this.serializers.get(modelLower); - if (!serializer) { - continue; - } - - const relators: Record> = {}; - const modelDef = this.requireModel(model); - for (const [field, fieldDef] of Object.entries(modelDef.fields)) { - if (!fieldDef.relation) { - continue; - } - const fieldSerializer = this.serializers.get(lowerCaseFirst(fieldDef.type)); - if (!fieldSerializer) { - continue; - } - const fieldIds = this.getIdFields(fieldDef.type); - if (fieldIds.length > 0) { - const mappedModel = this.mapModelName(modelLower); - - const relator = new tsjapi.Relator( - async (data) => { - return (data as any)[field]; - }, - fieldSerializer, - { - relatedName: field, - linkers: { - related: new tsjapi.Linker((primary) => - this.makeLinkUrl(`/${mappedModel}/${this.getId(model, primary)}/${field}`), - ), - relationship: new tsjapi.Linker((primary) => - this.makeLinkUrl( - `/${mappedModel}/${this.getId(model, primary)}/relationships/${field}`, - ), - ), - }, - }, - ); - relators[field] = relator; - } - } - serializer.setRelators(relators); - } - } - - private getId(model: string, data: any) { - if (!data) { - return undefined; - } - const ids = this.getIdFields(model); - if (ids.length === 0) { - return undefined; - } else { - return data[this.makeIdKey(ids)]; - } - } - - private async serializeItems(model: string, items: unknown, options?: Partial>) { - model = lowerCaseFirst(model); - const serializer = this.serializers.get(model); - if (!serializer) { - throw new Error(`serializer not found for model ${model}`); - } - - const itemsWithId = clone(items); - this.injectCompoundId(model, itemsWithId); - - // serialize to JSON:API structure - const serialized = await serializer.serialize(itemsWithId, options); - - // convert the serialization result to plain object otherwise SuperJSON won't work - const plainResult = this.toPlainObject(serialized); - - // superjson serialize the result - const { json, meta } = SuperJSON.serialize(plainResult); - - const result: any = json; - if (meta) { - result.meta = { ...result.meta, serialization: meta }; - } - - return result; - } - - private injectCompoundId(model: string, items: unknown) { - const typeInfo = this.getModelInfo(model); - if (!typeInfo) { - return; - } - - // recursively traverse the entity to create synthetic ID field for models with compound ID - enumerate(items).forEach((item: any) => { - if (!item) { - return; - } - - if (typeInfo.idFields.length > 1) { - item[this.makeIdKey(typeInfo.idFields)] = this.makeCompoundId(typeInfo.idFields, item); - } - - for (const [key, value] of Object.entries(item)) { - if (typeInfo.relationships[key]) { - // field is a relationship, recurse - this.injectCompoundId(typeInfo.relationships[key].type, value); - } - } - }); - } - - private toPlainObject(data: any): any { - if (data === undefined || data === null) { - return data; - } - - if (Array.isArray(data)) { - return data.map((item: any) => this.toPlainObject(item)); - } - - if (typeof data === 'object') { - if (typeof data.toJSON === 'function') { - // custom toJSON function - return data.toJSON(); - } - const result: any = {}; - for (const [field, value] of Object.entries(data)) { - if (value === undefined || typeof value === 'function') { - // trim undefined and functions - continue; - } else if (field === 'attributes') { - // don't visit into entity data - result[field] = value; - } else { - result[field] = this.toPlainObject(value); - } - } - return result; - } - - return data; - } - - private replaceURLSearchParams(url: string, params: Record) { - const r = new URL(url); - for (const [key, value] of Object.entries(params)) { - r.searchParams.set(key, value.toString()); - } - return r.toString(); - } - - private makeIdFilter(idFields: FieldDef[], resourceId: string, nested: boolean = true) { - const decodedId = decodeURIComponent(resourceId); - if (idFields.length === 1) { - return { [idFields[0]!.name]: this.coerce(idFields[0]!, decodedId) }; - } else if (nested) { - return { - // TODO: support `@@id` with custom name - [idFields.map((idf) => idf.name).join(DEFAULT_ID_DIVIDER)]: idFields.reduce( - (acc, curr, idx) => ({ - ...acc, - [curr.name]: this.coerce(curr, decodedId.split(this.idDivider)[idx]), - }), - {}, - ), - }; - } else { - return idFields.reduce( - (acc, curr, idx) => ({ - ...acc, - [curr.name]: this.coerce(curr, decodedId.split(this.idDivider)[idx]), - }), - {}, - ); - } - } - - private makeIdSelect(idFields: FieldDef[]) { - if (idFields.length === 0) { - throw this.errors['noId']; - } - return idFields.reduce((acc, curr) => ({ ...acc, [curr.name]: true }), {}); - } - - private makeIdConnect(idFields: FieldDef[], id: string | number) { - if (idFields.length === 1) { - return { [idFields[0]!.name]: this.coerce(idFields[0]!, id) }; - } else { - return { - [this.makeDefaultIdKey(idFields)]: idFields.reduce( - (acc, curr, idx) => ({ - ...acc, - [curr.name]: this.coerce(curr, `${id}`.split(this.idDivider)[idx]), - }), - {}, - ), - }; - } - } - - private makeIdKey(idFields: FieldDef[]) { - return idFields.map((idf) => idf.name).join(this.idDivider); - } - - private makeDefaultIdKey(idFields: FieldDef[]) { - // TODO: support `@@id` with custom name - return idFields.map((idf) => idf.name).join(DEFAULT_ID_DIVIDER); - } - - private makeCompoundId(idFields: FieldDef[], item: any) { - return idFields.map((idf) => item[idf.name]).join(this.idDivider); - } - - private makeUpsertWhere(matchFields: any[], attributes: any, typeInfo: ModelInfo) { - const where = matchFields.reduce((acc: any, field: string) => { - acc[field] = attributes[field] ?? null; - return acc; - }, {}); - - if ( - typeInfo.idFields.length > 1 && - matchFields.some((mf) => typeInfo.idFields.map((idf) => idf.name).includes(mf)) - ) { - return { - [this.makeDefaultIdKey(typeInfo.idFields)]: where, - }; - } - - return where; - } - - private includeRelationshipIds(model: string, args: any, mode: 'select' | 'include') { - const typeInfo = this.getModelInfo(model); - if (!typeInfo) { - return; - } - for (const [relation, relationInfo] of Object.entries(typeInfo.relationships)) { - args[mode] = { ...args[mode], [relation]: { select: this.makeIdSelect(relationInfo.idFields) } }; - } - } - - private coerce(fieldDef: FieldDef, value: any) { - if (typeof value === 'string') { - if (fieldDef.attributes?.some((attr) => attr.name === '@json')) { - try { - return JSON.parse(value); - } catch { - throw new InvalidValueError(`invalid JSON value: ${value}`); - } - } - - const type = fieldDef.type; - if (type === 'Int') { - const parsed = parseInt(value); - if (isNaN(parsed)) { - throw new InvalidValueError(`invalid ${type} value: ${value}`); - } - return parsed; - } else if (type === 'BigInt') { - try { - return BigInt(value); - } catch { - throw new InvalidValueError(`invalid ${type} value: ${value}`); - } - } else if (type === 'Float') { - const parsed = parseFloat(value); - if (isNaN(parsed)) { - throw new InvalidValueError(`invalid ${type} value: ${value}`); - } - return parsed; - } else if (type === 'Decimal') { - try { - return new Decimal(value); - } catch { - throw new InvalidValueError(`invalid ${type} value: ${value}`); - } - } else if (type === 'Boolean') { - if (value === 'true') { - return true; - } else if (value === 'false') { - return false; - } else { - throw new InvalidValueError(`invalid ${type} value: ${value}`); - } - } - } - return value; - } - - private makeNormalizedUrl(path: string, query: Record | undefined) { - const url = new URL(this.makeLinkUrl(path)); - for (const [key, value] of Object.entries(query ?? {})) { - if ( - key.startsWith('filter[') || - key.startsWith('sort[') || - key === 'include' || - key.startsWith('include[') || - key.startsWith('fields[') - ) { - for (const v of enumerate(value)) { - url.searchParams.append(key, v); - } - } - } - return url.toString(); - } - - private getPagination(query: Record | undefined) { - if (!query) { - return { offset: 0, limit: this.options.pageSize ?? DEFAULT_PAGE_SIZE }; - } - - let offset = 0; - if (query['page[offset]']) { - const value = query['page[offset]']; - const offsetText = Array.isArray(value) ? value[value.length - 1]! : value; - offset = parseInt(offsetText); - if (isNaN(offset) || offset < 0) { - offset = 0; - } - } - - let pageSizeOption = this.options.pageSize ?? DEFAULT_PAGE_SIZE; - if (pageSizeOption <= 0) { - pageSizeOption = DEFAULT_PAGE_SIZE; - } - - let limit = pageSizeOption; - if (query['page[limit]']) { - const value = query['page[limit]']; - const limitText = Array.isArray(value) ? value[value.length - 1]! : value; - limit = parseInt(limitText); - if (isNaN(limit) || limit <= 0) { - limit = pageSizeOption; - } - limit = Math.min(pageSizeOption, limit); - } - - return { offset, limit }; - } - - private buildFilter( - type: string, - query: Record | undefined, - ): { filter: any; error: any } { - if (!query) { - return { filter: undefined, error: undefined }; - } - - const typeInfo = this.getModelInfo(type); - if (!typeInfo) { - return { filter: undefined, error: this.makeUnsupportedModelError(type) }; - } - - const items: any[] = []; - - for (const [key, value] of Object.entries(query)) { - if (!value) { - continue; - } - - // try matching query parameter key as "filter[x][y]..." - const match = key.match(this.filterParamPattern); - if (!match || !match.groups || !match.groups['match']) { - continue; - } - - const filterKeys = match.groups['match'] - .replaceAll(/[[\]]/g, ' ') - .split(' ') - .filter((i) => i); - - if (!filterKeys.length) { - continue; - } - - // turn filter into a nested query object - - const item: any = {}; - let curr = item; - let currType = typeInfo; - - for (const filterValue of enumerate(value)) { - for (let i = 0; i < filterKeys.length; i++) { - // extract filter operation from (optional) trailing $op - let filterKey = filterKeys[i]!; - let filterOp: FilterOperationType | undefined; - const pos = filterKey.indexOf('$'); - if (pos > 0) { - filterOp = filterKey.substring(pos + 1) as FilterOperationType; - filterKey = filterKey.substring(0, pos); - } - - if (!!filterOp && !FilterOperations.includes(filterOp)) { - return { - filter: undefined, - error: this.makeError('invalidFilter', `invalid filter operation: ${filterOp}`), - }; - } - - const idFields = this.getIdFields(currType.name); - const fieldDef = - filterKey === 'id' - ? Object.values(currType.fields).find((f) => idFields.some((idf) => idf.name === f.name)) - : currType.fields[filterKey]; - if (!fieldDef) { - return { filter: undefined, error: this.makeError('invalidFilter') }; - } - - if (!fieldDef.relation) { - // regular field - if (i !== filterKeys.length - 1) { - // must be the last segment of a filter - return { filter: undefined, error: this.makeError('invalidFilter') }; - } - curr[fieldDef.name] = this.makeFilterValue(fieldDef, filterValue, filterOp); - } else { - // relation field - if (i === filterKeys.length - 1) { - curr[fieldDef.name] = this.makeFilterValue(fieldDef, filterValue, filterOp); - } else { - // keep going - if (fieldDef.array) { - // collection filtering implies "some" operation - curr[fieldDef.name] = { some: {} }; - curr = curr[fieldDef.name].some; - } else { - curr = curr[fieldDef.name] = {}; - } - currType = this.getModelInfo(fieldDef.type)!; - } - } - } - items.push(item); - } - } - - if (items.length === 0) { - return { filter: undefined, error: undefined }; - } else { - // combine filters with AND - return { filter: items.length === 1 ? items[0] : { AND: items }, error: undefined }; - } - } - - private buildSort(type: string, query: Record | undefined) { - if (!query?.['sort']) { - return { sort: undefined, error: undefined }; - } - - const typeInfo = this.getModelInfo(type); - if (!typeInfo) { - return { sort: undefined, error: this.makeUnsupportedModelError(type) }; - } - - const result: any[] = []; - - for (const sortSpec of enumerate(query['sort'])) { - const sortFields = sortSpec.split(',').filter((i) => i); - - for (const sortField of sortFields) { - const dir = sortField.startsWith('-') ? 'desc' : 'asc'; - const cleanedSortField = sortField.startsWith('-') ? sortField.substring(1) : sortField; - const parts = cleanedSortField.split('.').filter((i) => i); - - const sortItem: any = {}; - let curr = sortItem; - let currType = typeInfo; - - for (let i = 0; i < parts.length; i++) { - const part = parts[i]!; - - const fieldInfo = currType.fields[part]; - if (!fieldInfo || fieldInfo.array) { - return { - sort: undefined, - error: this.makeError('invalidSort', 'sorting by array field is not supported'), - }; - } - - if (i === parts.length - 1) { - if (fieldInfo.relation) { - // relation field: sort by id - const relationType = this.getModelInfo(fieldInfo.type); - if (!relationType) { - return { sort: undefined, error: this.makeUnsupportedModelError(fieldInfo.type) }; - } - curr[fieldInfo.name] = relationType.idFields.reduce((acc: any, idField: FieldDef) => { - acc[idField.name] = dir; - return acc; - }, {}); - } else { - // regular field - curr[fieldInfo.name] = dir; - } - } else { - if (!fieldInfo.relation) { - // must be a relation field - return { - sort: undefined, - error: this.makeError( - 'invalidSort', - 'intermediate sort segments must be relationships', - ), - }; - } - // keep going - curr = curr[fieldInfo.name] = {}; - currType = this.getModelInfo(fieldInfo.type)!; - if (!currType) { - return { sort: undefined, error: this.makeUnsupportedModelError(fieldInfo.type) }; - } - } - } - - result.push(sortItem); - } - } - - return { sort: result, error: undefined }; - } - - private buildRelationSelect( - type: string, - include: string | string[], - query: Record | undefined, - ) { - const typeInfo = this.getModelInfo(type); - if (!typeInfo) { - return { select: undefined, error: this.makeUnsupportedModelError(type) }; - } - - const result: any = {}; - const allIncludes: string[] = []; - - for (const includeItem of enumerate(include)) { - const inclusions = includeItem.split(',').filter((i) => i); - for (const inclusion of inclusions) { - allIncludes.push(inclusion); - - const parts = inclusion.split('.'); - let currPayload = result; - let currType = typeInfo; - - for (let i = 0; i < parts.length; i++) { - const relation = parts[i]!; - const relationInfo = currType.relationships[relation]; - if (!relationInfo) { - return { select: undefined, error: this.makeUnsupportedRelationshipError(type, relation, 400) }; - } - - currType = this.getModelInfo(relationInfo.type)!; - if (!currType) { - return { select: undefined, error: this.makeUnsupportedModelError(relationInfo.type) }; - } - - // handle partial results for requested type - const { select, error } = this.buildPartialSelect(lowerCaseFirst(relationInfo.type), query); - if (error) return { select: undefined, error }; - - if (i !== parts.length - 1) { - if (select) { - currPayload[relation] = { select: { ...select } }; - currPayload = currPayload[relation].select; - } else { - currPayload[relation] = { include: { ...currPayload[relation]?.include } }; - currPayload = currPayload[relation].include; - } - } else { - currPayload[relation] = select - ? { - select: { ...select }, - } - : true; - } - } - } - } - - return { select: result, error: undefined, allIncludes }; - } - - private makeFilterValue(fieldDef: FieldDef, value: string, op: FilterOperationType): any { - // TODO: inequality filters? - if (fieldDef.relation) { - // relation filter is converted to an ID filter - const info = this.getModelInfo(fieldDef.type)!; - if (fieldDef.array) { - // filtering a to-many relation, imply 'some' operator - const values = value.split(',').filter((i) => i); - const filterValue = - values.length > 1 - ? { OR: values.map((v) => this.makeIdFilter(info.idFields, v, false)) } - : this.makeIdFilter(info.idFields, value, false); - return { some: filterValue }; - } else { - const values = value.split(',').filter((i) => i); - if (values.length > 1) { - return { OR: values.map((v) => this.makeIdFilter(info.idFields, v, false)) }; - } else { - return { is: this.makeIdFilter(info.idFields, value, false) }; - } - } - } else { - if (op === 'between') { - const parts = value - .split(',') - .map((v) => this.coerce(fieldDef, v)); - if (parts.length !== 2) { - throw new InvalidValueError(`"between" expects exactly 2 comma-separated values`); - } - return { between: [parts[0]!, parts[1]!] }; - } - const coerced = this.coerce(fieldDef, value); - switch (op) { - case 'icontains': - return { contains: coerced, mode: 'insensitive' }; - case 'hasSome': - case 'hasEvery': { - const values = value - .split(',') - .filter((i) => i) - .map((v) => this.coerce(fieldDef, v)); - return { [op]: values }; - } - case 'isEmpty': - if (value !== 'true' && value !== 'false') { - throw new InvalidValueError(`Not a boolean: ${value}`); - } - return { isEmpty: value === 'true' ? true : false }; - default: - if (op === undefined) { - if (fieldDef.attributes?.some((attr) => attr.name === '@json')) { - // handle JSON value equality filter - return { equals: coerced }; - } - - // regular filter, split value by comma - const values = value - .split(',') - .filter((i) => i) - .map((v) => this.coerce(fieldDef, v)); - return values.length > 1 ? { in: values } : { equals: values[0] }; - } else { - return { [op]: coerced }; - } - } - } - } - - private injectRelationQuery( - type: string, - injectTarget: any, - injectKey: string, - query: Record | undefined, - ) { - const { filter, error: filterError } = this.buildFilter(type, query); - if (filterError) { - return filterError; - } - - if (filter) { - injectTarget[injectKey] = { ...injectTarget[injectKey], where: filter }; - } - - const { sort, error: sortError } = this.buildSort(type, query); - if (sortError) { - return sortError; - } - if (sort) { - injectTarget[injectKey] = { ...injectTarget[injectKey], orderBy: sort }; - } - - const pagination = this.getPagination(query); - const offset = pagination.offset; - if (offset > 0) { - // inject skip - injectTarget[injectKey] = { ...injectTarget[injectKey], skip: offset }; - } - const limit = pagination.limit; - if (limit !== Infinity) { - // inject take - injectTarget[injectKey] = { ...injectTarget[injectKey], take: limit }; - - // include a count query for the relationship - injectTarget._count = { select: { [injectKey]: true } }; - } - } - - private handleORMError(err: ORMError) { - return match(err.reason) - .with(ORMErrorReason.INVALID_INPUT, () => { - return this.makeError('validationError', err.message, 422); - }) - .with(ORMErrorReason.REJECTED_BY_POLICY, () => { - return this.makeError('forbidden', err.message, 403, { reason: err.rejectedByPolicyReason }); - }) - .with(ORMErrorReason.NOT_FOUND, () => { - return this.makeError('notFound', err.message, 404); - }) - .with(ORMErrorReason.DB_QUERY_ERROR, () => { - return this.makeError('queryError', err.message, 400, { - dbErrorCode: err.dbErrorCode, - }); - }) - .otherwise(() => { - return this.makeError('unknownError', err.message); - }); - } - - private makeError( - code: keyof typeof this.errors, - detail?: string, - status?: number, - otherFields: Record = {}, - ) { - status = status ?? this.errors[code]?.status ?? 500; - const error: any = { - status, - code: paramCase(code), - title: this.errors[code]?.title, - }; - - if (detail) { - error.detail = detail; - } - - Object.assign(error, otherFields); - - return { - status, - body: { - errors: [error], - }, - }; - } - - private makeUnsupportedModelError(model: string) { - return this.makeError('unsupportedModel', `Model ${model} doesn't exist`); - } - - private makeUnsupportedRelationshipError(model: string, relationship: string, status: number) { - return this.makeError('unsupportedRelationship', `Relationship ${model}.${relationship} doesn't exist`, status); - } - - //#endregion -} +export { RestApiHandler, type RestApiHandlerOptions } from './handler'; +export { RestApiSpecGenerator } from './openapi'; diff --git a/packages/server/src/api/rest/openapi.ts b/packages/server/src/api/rest/openapi.ts new file mode 100644 index 000000000..35b2bbbb6 --- /dev/null +++ b/packages/server/src/api/rest/openapi.ts @@ -0,0 +1,926 @@ +import { lowerCaseFirst } from '@zenstackhq/common-helpers'; +import type { EnumDef, FieldDef, ModelDef, SchemaDef } from '@zenstackhq/orm/schema'; +import type { OpenAPIV3_1 } from 'openapi-types'; +import { PROCEDURE_ROUTE_PREFIXES } from '../common/procedures'; +import { getIncludedModels, isFieldOmitted, isFilterKindIncluded, isProcedureIncluded } from '../common/spec-utils'; +import type { OpenApiSpecOptions } from '../common/types'; +import type { RestApiHandlerOptions } from './handler'; + +type SchemaObject = OpenAPIV3_1.SchemaObject; +type ReferenceObject = OpenAPIV3_1.ReferenceObject; +type ParameterObject = OpenAPIV3_1.ParameterObject; + +const SCALAR_STRING_OPS = ['$contains', '$icontains', '$search', '$startsWith', '$endsWith']; +const SCALAR_COMPARABLE_OPS = ['$lt', '$lte', '$gt', '$gte']; +const SCALAR_ARRAY_OPS = ['$has', '$hasEvery', '$hasSome', '$isEmpty']; + +export class RestApiSpecGenerator { + constructor(private readonly handlerOptions: RestApiHandlerOptions) {} + + private get schema(): SchemaDef { + return this.handlerOptions.schema; + } + + private get endpoint(): string { + return this.handlerOptions.endpoint; + } + + private get modelNameMapping(): Record { + const mapping: Record = {}; + if (this.handlerOptions.modelNameMapping) { + for (const [k, v] of Object.entries(this.handlerOptions.modelNameMapping)) { + mapping[lowerCaseFirst(k)] = v; + } + } + return mapping; + } + + private get queryOptions() { + return this.handlerOptions?.queryOptions; + } + + generateSpec(options?: OpenApiSpecOptions): OpenAPIV3_1.Document { + return { + openapi: '3.1.0', + info: { + title: options?.title ?? 'ZenStack Generated API', + version: options?.version ?? '1.0.0', + ...(options?.description && { description: options.description }), + ...(options?.summary && { summary: options.summary }), + }, + servers: [{ url: this.endpoint }], + tags: this.generateTags(), + paths: this.generatePaths(), + components: { + schemas: this.generateSchemas(), + parameters: this.generateSharedParams() as any, + }, + } as OpenAPIV3_1.Document; + } + + private generateTags(): OpenAPIV3_1.TagObject[] { + return getIncludedModels(this.schema, this.queryOptions).map((modelName) => ({ + name: lowerCaseFirst(modelName), + description: `${modelName} operations`, + })); + } + + private getModelPath(modelName: string): string { + const lower = lowerCaseFirst(modelName); + return this.modelNameMapping[lower] ?? lower; + } + + private generatePaths(): OpenAPIV3_1.PathsObject { + const paths: OpenAPIV3_1.PathsObject = {}; + + for (const modelName of getIncludedModels(this.schema, this.queryOptions)) { + const modelDef = this.schema.models[modelName]!; + const idFields = this.getIdFields(modelDef); + if (idFields.length === 0) continue; + + const modelPath = this.getModelPath(modelName); + const tag = lowerCaseFirst(modelName); + + // Collection: GET (list) + POST (create) + paths[`/${modelPath}`] = this.buildCollectionPath(modelName, modelDef, tag) as any; + + // Single resource: GET + PATCH + DELETE + paths[`/${modelPath}/{id}`] = this.buildSinglePath(modelName, tag) as any; + + // Relation paths + for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { + if (!fieldDef.relation) continue; + const relModelDef = this.schema.models[fieldDef.type]; + if (!relModelDef) continue; + const relIdFields = this.getIdFields(relModelDef); + if (relIdFields.length === 0) continue; + + // GET /{model}/{id}/{field} — fetch related + paths[`/${modelPath}/{id}/${fieldName}`] = this.buildFetchRelatedPath( + modelName, + fieldName, + fieldDef, + tag, + ) as any; + + // Relationship management path + paths[`/${modelPath}/{id}/relationships/${fieldName}`] = this.buildRelationshipPath( + modelName, + fieldName, + fieldDef, + tag, + ) as any; + } + } + + // Procedure paths + if (this.schema.procedures) { + for (const [procName, procDef] of Object.entries(this.schema.procedures)) { + if (!isProcedureIncluded(procName, this.queryOptions)) continue; + const isMutation = !!procDef.mutation; + const pathItem: Record = {}; + + if (isMutation) { + pathItem['post'] = this.buildProcedureOperation(procName, 'post'); + } else { + pathItem['get'] = this.buildProcedureOperation(procName, 'get'); + } + + paths[`/${PROCEDURE_ROUTE_PREFIXES}/${procName}`] = pathItem as any; + } + } + + return paths; + } + + private buildCollectionPath(modelName: string, modelDef: ModelDef, tag: string): Record { + const filterParams = this.buildFilterParams(modelName, modelDef); + + const listOp = { + tags: [tag], + summary: `List ${modelName} resources`, + operationId: `list${modelName}`, + parameters: [ + { $ref: '#/components/parameters/include' }, + { $ref: '#/components/parameters/sort' }, + { $ref: '#/components/parameters/pageOffset' }, + { $ref: '#/components/parameters/pageLimit' }, + ...filterParams, + ], + responses: { + '200': { + description: `List of ${modelName} resources`, + content: { + 'application/vnd.api+json': { + schema: { $ref: `#/components/schemas/${modelName}ListResponse` }, + }, + }, + }, + '400': { $ref: '#/components/schemas/_errorResponse' }, + }, + }; + + const createOp = { + tags: [tag], + summary: `Create a ${modelName} resource`, + operationId: `create${modelName}`, + requestBody: { + required: true, + content: { + 'application/vnd.api+json': { + schema: { $ref: `#/components/schemas/${modelName}CreateRequest` }, + }, + }, + }, + responses: { + '201': { + description: `Created ${modelName} resource`, + content: { + 'application/vnd.api+json': { + schema: { $ref: `#/components/schemas/${modelName}Response` }, + }, + }, + }, + '400': { $ref: '#/components/schemas/_errorResponse' }, + }, + }; + + return { get: listOp, post: createOp }; + } + + private buildSinglePath(modelName: string, tag: string): Record { + const idParam = { $ref: '#/components/parameters/id' }; + + const getOp = { + tags: [tag], + summary: `Get a ${modelName} resource by ID`, + operationId: `get${modelName}`, + parameters: [idParam, { $ref: '#/components/parameters/include' }], + responses: { + '200': { + description: `${modelName} resource`, + content: { + 'application/vnd.api+json': { + schema: { $ref: `#/components/schemas/${modelName}Response` }, + }, + }, + }, + '404': { $ref: '#/components/schemas/_errorResponse' }, + }, + }; + + const patchOp = { + tags: [tag], + summary: `Update a ${modelName} resource`, + operationId: `update${modelName}`, + parameters: [idParam], + requestBody: { + required: true, + content: { + 'application/vnd.api+json': { + schema: { $ref: `#/components/schemas/${modelName}UpdateRequest` }, + }, + }, + }, + responses: { + '200': { + description: `Updated ${modelName} resource`, + content: { + 'application/vnd.api+json': { + schema: { $ref: `#/components/schemas/${modelName}Response` }, + }, + }, + }, + '400': { $ref: '#/components/schemas/_errorResponse' }, + '404': { $ref: '#/components/schemas/_errorResponse' }, + }, + }; + + const deleteOp = { + tags: [tag], + summary: `Delete a ${modelName} resource`, + operationId: `delete${modelName}`, + parameters: [idParam], + responses: { + '200': { description: 'Deleted successfully' }, + '404': { $ref: '#/components/schemas/_errorResponse' }, + }, + }; + + return { get: getOp, patch: patchOp, delete: deleteOp }; + } + + private buildFetchRelatedPath( + modelName: string, + fieldName: string, + fieldDef: FieldDef, + tag: string, + ): Record { + const isCollection = !!fieldDef.array; + const params: any[] = [{ $ref: '#/components/parameters/id' }, { $ref: '#/components/parameters/include' }]; + + if (isCollection && this.schema.models[fieldDef.type]) { + const relModelDef = this.schema.models[fieldDef.type]!; + params.push( + { $ref: '#/components/parameters/sort' }, + { $ref: '#/components/parameters/pageOffset' }, + { $ref: '#/components/parameters/pageLimit' }, + ...this.buildFilterParams(fieldDef.type, relModelDef), + ); + } + + return { + get: { + tags: [tag], + summary: `Fetch related ${fieldDef.type} for ${modelName}`, + operationId: `get${modelName}_${fieldName}`, + parameters: params, + responses: { + '200': { description: `Related ${fieldDef.type} resource(s)` }, + '404': { $ref: '#/components/schemas/_errorResponse' }, + }, + }, + }; + } + + private buildRelationshipPath( + _modelName: string, + fieldName: string, + fieldDef: FieldDef, + tag: string, + ): Record { + const isCollection = !!fieldDef.array; + const idParam = { $ref: '#/components/parameters/id' }; + const relSchemaRef = isCollection + ? { $ref: '#/components/schemas/_toManyRelationshipWithLinks' } + : { $ref: '#/components/schemas/_toOneRelationshipWithLinks' }; + + const relRequestRef = isCollection + ? { $ref: '#/components/schemas/_toManyRelationshipRequest' } + : { $ref: '#/components/schemas/_toOneRelationshipRequest' }; + + const pathItem: Record = { + get: { + tags: [tag], + summary: `Fetch ${fieldName} relationship`, + operationId: `get${_modelName}_relationships_${fieldName}`, + parameters: [idParam], + responses: { + '200': { + description: `${fieldName} relationship`, + content: { 'application/vnd.api+json': { schema: relSchemaRef } }, + }, + '404': { $ref: '#/components/schemas/_errorResponse' }, + }, + }, + put: { + tags: [tag], + summary: `Replace ${fieldName} relationship`, + operationId: `put${_modelName}_relationships_${fieldName}`, + parameters: [idParam], + requestBody: { + required: true, + content: { 'application/vnd.api+json': { schema: relRequestRef } }, + }, + responses: { + '200': { description: 'Relationship updated' }, + '400': { $ref: '#/components/schemas/_errorResponse' }, + }, + }, + patch: { + tags: [tag], + summary: `Update ${fieldName} relationship`, + operationId: `patch${_modelName}_relationships_${fieldName}`, + parameters: [idParam], + requestBody: { + required: true, + content: { 'application/vnd.api+json': { schema: relRequestRef } }, + }, + responses: { + '200': { description: 'Relationship updated' }, + '400': { $ref: '#/components/schemas/_errorResponse' }, + }, + }, + }; + + if (isCollection) { + pathItem['post'] = { + tags: [tag], + summary: `Add to ${fieldName} collection relationship`, + operationId: `post${_modelName}_relationships_${fieldName}`, + parameters: [idParam], + requestBody: { + required: true, + content: { + 'application/vnd.api+json': { + schema: { $ref: '#/components/schemas/_toManyRelationshipRequest' }, + }, + }, + }, + responses: { + '200': { description: 'Added to relationship collection' }, + '400': { $ref: '#/components/schemas/_errorResponse' }, + }, + }; + } + + return pathItem; + } + + private buildProcedureOperation(procName: string, method: 'get' | 'post'): Record { + const op: Record = { + tags: ['$procs'], + summary: `Execute procedure ${procName}`, + operationId: `proc_${procName}`, + responses: { + '200': { description: `Result of ${procName}` }, + '400': { $ref: '#/components/schemas/_errorResponse' }, + }, + }; + + if (method === 'get') { + op['parameters'] = [ + { + name: 'q', + in: 'query', + description: 'Procedure arguments as JSON', + schema: { type: 'string' }, + }, + ]; + } else { + op['requestBody'] = { + content: { + 'application/json': { + schema: { type: 'object' }, + }, + }, + }; + } + + return op; + } + + private buildFilterParams(modelName: string, modelDef: ModelDef): ParameterObject[] { + const params: ParameterObject[] = []; + const idFieldNames = new Set(modelDef.idFields); + + // id filter (Equality kind) + if (isFilterKindIncluded(modelName, 'id', 'Equality', this.queryOptions)) { + params.push({ + name: 'filter[id]', + in: 'query', + schema: { type: 'string' }, + description: `Filter by ${modelName} ID`, + }); + } + + for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { + if (fieldDef.relation || fieldDef.omit || fieldDef.foreignKeyFor) continue; + if (idFieldNames.has(fieldName)) continue; + + const type = fieldDef.type; + + // Equality filter + if (isFilterKindIncluded(modelName, fieldName, 'Equality', this.queryOptions)) { + params.push({ + name: `filter[${fieldName}]`, + in: 'query', + schema: { type: 'string' }, + description: `Filter by ${fieldName}`, + }); + } + + if (type === 'String' && isFilterKindIncluded(modelName, fieldName, 'Like', this.queryOptions)) { + for (const op of SCALAR_STRING_OPS) { + params.push({ + name: `filter[${fieldName}][${op}]`, + in: 'query', + schema: { type: 'string' }, + }); + } + } else if ( + (type === 'Int' || + type === 'Float' || + type === 'BigInt' || + type === 'Decimal' || + type === 'DateTime') && + isFilterKindIncluded(modelName, fieldName, 'Range', this.queryOptions) + ) { + for (const op of SCALAR_COMPARABLE_OPS) { + params.push({ + name: `filter[${fieldName}][${op}]`, + in: 'query', + schema: { type: 'string' }, + }); + } + } + + if (fieldDef.array && isFilterKindIncluded(modelName, fieldName, 'List', this.queryOptions)) { + for (const op of SCALAR_ARRAY_OPS) { + params.push({ + name: `filter[${fieldName}][${op}]`, + in: 'query', + schema: { type: 'string' }, + }); + } + } + } + + return params; + } + + private generateSchemas(): Record { + const schemas: Record = {}; + + // Shared JSON:API components + Object.assign(schemas, this.buildSharedSchemas()); + + // Per-enum schemas + if (this.schema.enums) { + for (const [_enumName, enumDef] of Object.entries(this.schema.enums)) { + schemas[_enumName] = this.buildEnumSchema(enumDef); + } + } + + // Per-model schemas + for (const modelName of getIncludedModels(this.schema, this.queryOptions)) { + const modelDef = this.schema.models[modelName]!; + const idFields = this.getIdFields(modelDef); + if (idFields.length === 0) continue; + + schemas[modelName] = this.buildModelReadSchema(modelName, modelDef); + schemas[`${modelName}CreateRequest`] = this.buildCreateRequestSchema(modelName, modelDef); + schemas[`${modelName}UpdateRequest`] = this.buildUpdateRequestSchema(modelDef); + schemas[`${modelName}Response`] = this.buildModelResponseSchema(modelName); + schemas[`${modelName}ListResponse`] = this.buildModelListResponseSchema(modelName); + } + + return schemas; + } + + private buildSharedSchemas(): Record { + const nullableString: SchemaObject = { oneOf: [{ type: 'string' }, { type: 'null' }] }; + return { + _jsonapi: { + type: 'object', + properties: { + version: { type: 'string' }, + meta: { type: 'object' }, + }, + }, + _meta: { + type: 'object', + additionalProperties: true, + }, + _links: { + type: 'object', + properties: { + self: { type: 'string' }, + related: { type: 'string' }, + }, + }, + _pagination: { + type: 'object', + properties: { + first: nullableString, + last: nullableString, + prev: nullableString, + next: nullableString, + }, + }, + _errors: { + type: 'array', + items: { + type: 'object', + properties: { + status: { type: 'integer' }, + code: { type: 'string' }, + title: { type: 'string' }, + detail: { type: 'string' }, + }, + required: ['status', 'title'], + }, + }, + _errorResponse: { + type: 'object', + properties: { + errors: { $ref: '#/components/schemas/_errors' }, + }, + required: ['errors'], + }, + _resourceIdentifier: { + type: 'object', + properties: { + type: { type: 'string' }, + id: { type: 'string' }, + }, + required: ['type', 'id'], + }, + _resource: { + type: 'object', + properties: { + type: { type: 'string' }, + id: { type: 'string' }, + attributes: { type: 'object' }, + relationships: { type: 'object' }, + links: { $ref: '#/components/schemas/_links' }, + meta: { $ref: '#/components/schemas/_meta' }, + }, + required: ['type', 'id'], + }, + _relationLinks: { + type: 'object', + properties: { + self: { type: 'string' }, + related: { type: 'string' }, + }, + }, + _pagedRelationLinks: { + type: 'object', + allOf: [{ $ref: '#/components/schemas/_relationLinks' }, { $ref: '#/components/schemas/_pagination' }], + }, + _toOneRelationship: { + type: 'object', + properties: { + data: { + oneOf: [{ $ref: '#/components/schemas/_resourceIdentifier' }, { type: 'null' }], + }, + }, + }, + _toManyRelationship: { + type: 'object', + properties: { + data: { + type: 'array', + items: { $ref: '#/components/schemas/_resourceIdentifier' }, + }, + }, + }, + _toOneRelationshipWithLinks: { + type: 'object', + allOf: [ + { $ref: '#/components/schemas/_toOneRelationship' }, + { + properties: { + links: { $ref: '#/components/schemas/_relationLinks' }, + }, + }, + ], + }, + _toManyRelationshipWithLinks: { + type: 'object', + allOf: [ + { $ref: '#/components/schemas/_toManyRelationship' }, + { + properties: { + links: { $ref: '#/components/schemas/_pagedRelationLinks' }, + }, + }, + ], + }, + _toManyRelationshipRequest: { + type: 'object', + properties: { + data: { + type: 'array', + items: { $ref: '#/components/schemas/_resourceIdentifier' }, + }, + }, + required: ['data'], + }, + _toOneRelationshipRequest: { + type: 'object', + properties: { + data: { + oneOf: [{ $ref: '#/components/schemas/_resourceIdentifier' }, { type: 'null' }], + }, + }, + required: ['data'], + }, + _toManyRelationshipResponse: { + type: 'object', + properties: { + data: { + type: 'array', + items: { $ref: '#/components/schemas/_resourceIdentifier' }, + }, + links: { $ref: '#/components/schemas/_pagedRelationLinks' }, + meta: { $ref: '#/components/schemas/_meta' }, + }, + }, + _toOneRelationshipResponse: { + type: 'object', + properties: { + data: { + oneOf: [{ $ref: '#/components/schemas/_resourceIdentifier' }, { type: 'null' }], + }, + links: { $ref: '#/components/schemas/_relationLinks' }, + meta: { $ref: '#/components/schemas/_meta' }, + }, + }, + }; + } + + private buildEnumSchema(enumDef: EnumDef): SchemaObject { + return { + type: 'string', + enum: Object.values(enumDef.values), + }; + } + + private buildModelReadSchema(modelName: string, modelDef: ModelDef): SchemaObject { + const properties: Record = {}; + const required: string[] = []; + + for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { + if (fieldDef.omit) continue; + if (isFieldOmitted(modelName, fieldName, this.queryOptions)) continue; + + const schema = this.fieldToSchema(fieldDef); + properties[fieldName] = schema; + + if (!fieldDef.optional && !fieldDef.array) { + required.push(fieldName); + } + } + + const result: SchemaObject = { type: 'object', properties }; + if (required.length > 0) { + result.required = required; + } + return result; + } + + private buildCreateRequestSchema(_modelName: string, modelDef: ModelDef): SchemaObject { + const idFieldNames = new Set(modelDef.idFields); + const attributes: Record = {}; + const attrRequired: string[] = []; + const relationships: Record = {}; + + for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { + if (fieldDef.omit) continue; + if (fieldDef.updatedAt) continue; + if (fieldDef.foreignKeyFor) continue; + // Skip auto-generated id fields + if (idFieldNames.has(fieldName) && fieldDef.default !== undefined) continue; + + if (fieldDef.relation) { + relationships[fieldName] = fieldDef.array + ? { + type: 'object', + properties: { + data: { + type: 'array', + items: { $ref: '#/components/schemas/_resourceIdentifier' }, + }, + }, + } + : { + type: 'object', + properties: { + data: { $ref: '#/components/schemas/_resourceIdentifier' }, + }, + }; + } else { + attributes[fieldName] = this.fieldToSchema(fieldDef); + if (!fieldDef.optional && fieldDef.default === undefined && !fieldDef.array) { + attrRequired.push(fieldName); + } + } + } + + const dataProperties: Record = { + type: { type: 'string' }, + }; + + if (Object.keys(attributes).length > 0) { + const attrSchema: SchemaObject = { type: 'object', properties: attributes }; + if (attrRequired.length > 0) attrSchema.required = attrRequired; + dataProperties['attributes'] = attrSchema; + } + + if (Object.keys(relationships).length > 0) { + dataProperties['relationships'] = { type: 'object', properties: relationships }; + } + + return { + type: 'object', + properties: { + data: { + type: 'object', + properties: dataProperties, + required: ['type'], + }, + }, + required: ['data'], + }; + } + + private buildUpdateRequestSchema(modelDef: ModelDef): SchemaObject { + const attributes: Record = {}; + const relationships: Record = {}; + + for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { + if (fieldDef.omit) continue; + if (fieldDef.updatedAt) continue; + if (fieldDef.foreignKeyFor) continue; + + if (fieldDef.relation) { + relationships[fieldName] = fieldDef.array + ? { + type: 'object', + properties: { + data: { + type: 'array', + items: { $ref: '#/components/schemas/_resourceIdentifier' }, + }, + }, + } + : { + type: 'object', + properties: { + data: { $ref: '#/components/schemas/_resourceIdentifier' }, + }, + }; + } else { + attributes[fieldName] = this.fieldToSchema(fieldDef); + } + } + + const dataProperties: Record = { + type: { type: 'string' }, + id: { type: 'string' }, + }; + + if (Object.keys(attributes).length > 0) { + dataProperties['attributes'] = { type: 'object', properties: attributes }; + } + + if (Object.keys(relationships).length > 0) { + dataProperties['relationships'] = { type: 'object', properties: relationships }; + } + + return { + type: 'object', + properties: { + data: { + type: 'object', + properties: dataProperties, + required: ['type', 'id'], + }, + }, + required: ['data'], + }; + } + + private buildModelResponseSchema(modelName: string): SchemaObject { + return { + type: 'object', + properties: { + jsonapi: { $ref: '#/components/schemas/_jsonapi' }, + data: { + allOf: [{ $ref: `#/components/schemas/${modelName}` }, { $ref: '#/components/schemas/_resource' }], + }, + meta: { $ref: '#/components/schemas/_meta' }, + }, + }; + } + + private buildModelListResponseSchema(modelName: string): SchemaObject { + return { + type: 'object', + properties: { + jsonapi: { $ref: '#/components/schemas/_jsonapi' }, + data: { + type: 'array', + items: { + allOf: [ + { $ref: `#/components/schemas/${modelName}` }, + { $ref: '#/components/schemas/_resource' }, + ], + }, + }, + links: { + allOf: [{ $ref: '#/components/schemas/_pagination' }, { $ref: '#/components/schemas/_links' }], + }, + meta: { $ref: '#/components/schemas/_meta' }, + }, + }; + } + + private generateSharedParams(): Record { + return { + id: { + name: 'id', + in: 'path', + required: true, + schema: { type: 'string' }, + description: 'Resource ID', + }, + include: { + name: 'include', + in: 'query', + schema: { type: 'string' }, + description: 'Comma-separated list of relationships to include', + }, + sort: { + name: 'sort', + in: 'query', + schema: { type: 'string' }, + description: 'Comma-separated list of fields to sort by. Prefix with - for descending', + }, + pageOffset: { + name: 'page[offset]', + in: 'query', + schema: { type: 'integer', minimum: 0 }, + description: 'Page offset', + }, + pageLimit: { + name: 'page[limit]', + in: 'query', + schema: { type: 'integer', minimum: 1 }, + description: 'Page limit', + }, + }; + } + + private fieldToSchema(fieldDef: FieldDef): SchemaObject | ReferenceObject { + const baseSchema = this.typeToSchema(fieldDef.type); + if (fieldDef.array) { + return { type: 'array', items: baseSchema }; + } + if (fieldDef.optional) { + return { oneOf: [baseSchema, { type: 'null' }] }; + } + return baseSchema; + } + + private typeToSchema(type: string): SchemaObject | ReferenceObject { + switch (type) { + case 'String': + return { type: 'string' }; + case 'Int': + case 'BigInt': + return { type: 'integer' }; + case 'Float': + return { type: 'number' }; + case 'Decimal': + return { oneOf: [{ type: 'number' }, { type: 'string' }] }; + case 'Boolean': + return { type: 'boolean' }; + case 'DateTime': + return { type: 'string', format: 'date-time' }; + case 'Bytes': + return { type: 'string', format: 'byte' }; + case 'Json': + case 'Unsupported': + return {}; + default: + return { $ref: `#/components/schemas/${type}` }; + } + } + + private getIdFields(modelDef: ModelDef): FieldDef[] { + return modelDef.idFields.map((name) => modelDef.fields[name]).filter((f): f is FieldDef => f !== undefined); + } +} diff --git a/packages/server/src/api/rpc/handler.ts b/packages/server/src/api/rpc/handler.ts new file mode 100644 index 000000000..0da686f94 --- /dev/null +++ b/packages/server/src/api/rpc/handler.ts @@ -0,0 +1,458 @@ +import { lowerCaseFirst, safeJSONStringify } from '@zenstackhq/common-helpers'; +import { CoreCrudOperations, ORMError, ORMErrorReason, type ClientContract } from '@zenstackhq/orm'; +import type { SchemaDef } from '@zenstackhq/orm/schema'; +import SuperJSON from 'superjson'; +import { match } from 'ts-pattern'; +import z from 'zod'; +import { fromError } from 'zod-validation-error/v4'; +import type { ApiHandler, LogConfig, RequestContext, Response } from '../../types'; +import { getProcedureDef, mapProcedureArgs, PROCEDURE_ROUTE_PREFIXES } from '../common/procedures'; +import { loggerSchema } from '../common/schemas'; +import type { CommonHandlerOptions, OpenApiSpecGenerator } from '../common/types'; +import { processSuperJsonRequestPayload, unmarshalQ } from '../common/utils'; +import { log, registerCustomSerializers } from '../utils'; +import { RPCApiSpecGenerator } from './openapi'; + +const TRANSACTION_ROUTE_PREFIX = '$transaction' as const; +const VALID_OPS = new Set(CoreCrudOperations as unknown as string[]); + +registerCustomSerializers(); + +/** + * Options for {@link RPCApiHandler} + */ +export type RPCApiHandlerOptions = { + /** + * The schema + */ + schema: Schema; + + /** + * Logging configuration + */ + log?: LogConfig; +} & CommonHandlerOptions; + +/** + * RPC style API request handler that mirrors the ZenStackClient API + */ +export class RPCApiHandler implements ApiHandler, OpenApiSpecGenerator { + constructor(private readonly options: RPCApiHandlerOptions) { + this.validateOptions(options); + } + + private validateOptions(options: RPCApiHandlerOptions) { + const schema = z.strictObject({ + schema: z.object(), + log: loggerSchema.optional(), + queryOptions: z.object().optional(), + }); + const parseResult = schema.safeParse(options); + if (!parseResult.success) { + throw new Error(`Invalid options: ${fromError(parseResult.error)}`); + } + } + + get schema(): Schema { + return this.options.schema; + } + + get log(): LogConfig | undefined { + return this.options.log; + } + + async handleRequest({ client, method, path, query, requestBody }: RequestContext): Promise { + const parts = path.split('/').filter((p) => !!p); + const op = parts.pop(); + let model = parts.pop(); + + if (parts.length !== 0 || !op || !model) { + return this.makeBadInputErrorResponse('invalid request path'); + } + + if (model === PROCEDURE_ROUTE_PREFIXES) { + return this.handleProcedureRequest({ + client, + method: method.toUpperCase(), + proc: op, + query, + requestBody, + }); + } + + if (model === TRANSACTION_ROUTE_PREFIX) { + return this.handleTransaction({ + client, + method: method.toUpperCase(), + type: op, + requestBody, + }); + } + + model = lowerCaseFirst(model); + method = method.toUpperCase(); + let args: unknown; + let resCode = 200; + + switch (op) { + case 'create': + case 'createMany': + case 'createManyAndReturn': + case 'upsert': + if (method !== 'POST') { + return this.makeBadInputErrorResponse('invalid request method, only POST is supported'); + } + if (!requestBody) { + return this.makeBadInputErrorResponse('missing request body'); + } + + args = requestBody; + resCode = 201; + break; + + case 'findFirst': + case 'findUnique': + case 'findMany': + case 'aggregate': + case 'groupBy': + case 'count': + case 'exists': + if (method !== 'GET') { + return this.makeBadInputErrorResponse('invalid request method, only GET is supported'); + } + try { + args = query?.['q'] ? unmarshalQ(query['q'] as string, query['meta'] as string | undefined) : {}; + } catch { + return this.makeBadInputErrorResponse('invalid "q" query parameter'); + } + break; + + case 'update': + case 'updateMany': + case 'updateManyAndReturn': + if (method !== 'PUT' && method !== 'PATCH') { + return this.makeBadInputErrorResponse('invalid request method, only PUT or PATCH are supported'); + } + if (!requestBody) { + return this.makeBadInputErrorResponse('missing request body'); + } + + args = requestBody; + break; + + case 'delete': + case 'deleteMany': + if (method !== 'DELETE') { + return this.makeBadInputErrorResponse('invalid request method, only DELETE is supported'); + } + try { + args = query?.['q'] ? unmarshalQ(query['q'] as string, query['meta'] as string | undefined) : {}; + } catch (err) { + return this.makeBadInputErrorResponse( + err instanceof Error ? err.message : 'invalid "q" query parameter', + ); + } + break; + + default: + return this.makeBadInputErrorResponse('invalid operation: ' + op); + } + + const { result: processedArgs, error } = await this.processRequestPayload(args); + if (error) { + return this.makeBadInputErrorResponse(error); + } + + try { + if (!this.isValidModel(client, model)) { + return this.makeBadInputErrorResponse(`unknown model name: ${model}`); + } + + log( + this.options.log, + 'debug', + () => `handling "${model}.${op}" request with args: ${safeJSONStringify(processedArgs)}`, + ); + + const clientResult = await (client as any)[model][op](processedArgs); + let responseBody: any = { data: clientResult }; + + // superjson serialize response + if (clientResult) { + const { json, meta } = SuperJSON.serialize(clientResult); + responseBody = { data: json }; + if (meta) { + responseBody.meta = { serialization: meta }; + } + } + + const response = { status: resCode, body: responseBody }; + log( + this.options.log, + 'debug', + () => `sending response for "${model}.${op}" request: ${safeJSONStringify(response)}`, + ); + return response; + } catch (err) { + log(this.options.log, 'error', `error occurred when handling "${model}.${op}" request`, err); + if (err instanceof ORMError) { + return this.makeORMErrorResponse(err); + } else { + return this.makeGenericErrorResponse(err); + } + } + } + + private async handleTransaction({ + client, + method, + type, + requestBody, + }: { + client: ClientContract; + method: string; + type: string; + requestBody?: unknown; + }): Promise { + if (method !== 'POST') { + return this.makeBadInputErrorResponse('invalid request method, only POST is supported'); + } + + if (type !== 'sequential') { + return this.makeBadInputErrorResponse(`unsupported transaction type: ${type}`); + } + + if (!requestBody || !Array.isArray(requestBody) || requestBody.length === 0) { + return this.makeBadInputErrorResponse('request body must be a non-empty array of operations'); + } + + const processedOps: Array<{ model: string; op: string; args: unknown }> = []; + + for (let i = 0; i < requestBody.length; i++) { + const item = requestBody[i]; + if (!item || typeof item !== 'object') { + return this.makeBadInputErrorResponse(`operation at index ${i} must be an object`); + } + const { model: itemModel, op: itemOp, args: itemArgs } = item as any; + if (!itemModel || typeof itemModel !== 'string') { + return this.makeBadInputErrorResponse(`operation at index ${i} is missing a valid "model" field`); + } + if (!itemOp || typeof itemOp !== 'string') { + return this.makeBadInputErrorResponse(`operation at index ${i} is missing a valid "op" field`); + } + if (!VALID_OPS.has(itemOp)) { + return this.makeBadInputErrorResponse(`operation at index ${i} has invalid op: ${itemOp}`); + } + if (!this.isValidModel(client, lowerCaseFirst(itemModel))) { + return this.makeBadInputErrorResponse(`operation at index ${i} has unknown model: ${itemModel}`); + } + if ( + itemArgs !== undefined && + itemArgs !== null && + (typeof itemArgs !== 'object' || Array.isArray(itemArgs)) + ) { + return this.makeBadInputErrorResponse(`operation at index ${i} has invalid "args" field`); + } + + const { result: processedArgs, error: argsError } = await this.processRequestPayload(itemArgs ?? {}); + if (argsError) { + return this.makeBadInputErrorResponse(`operation at index ${i}: ${argsError}`); + } + processedOps.push({ model: lowerCaseFirst(itemModel), op: itemOp, args: processedArgs }); + } + + try { + const promises = processedOps.map(({ model, op, args }) => { + return (client as any)[model][op](args); + }); + + log(this.options.log, 'debug', () => `handling "$transaction" request with ${promises.length} operations`); + + const clientResult = await client.$transaction(promises as any); + + const { json, meta } = SuperJSON.serialize(clientResult); + const responseBody: any = { data: json }; + if (meta) { + responseBody.meta = { serialization: meta }; + } + + const response = { status: 200, body: responseBody }; + log( + this.options.log, + 'debug', + () => `sending response for "$transaction" request: ${safeJSONStringify(response)}`, + ); + return response; + } catch (err) { + log(this.options.log, 'error', `error occurred when handling "$transaction" request`, err); + if (err instanceof ORMError) { + return this.makeORMErrorResponse(err); + } + return this.makeGenericErrorResponse(err); + } + } + + private async handleProcedureRequest({ + client, + method, + proc, + query, + requestBody, + }: { + client: ClientContract; + method: string; + proc?: string; + query?: Record; + requestBody?: unknown; + }): Promise { + if (!proc) { + return this.makeBadInputErrorResponse('missing procedure name'); + } + + const procDef = getProcedureDef(this.options.schema, proc); + if (!procDef) { + return this.makeBadInputErrorResponse(`unknown procedure: ${proc}`); + } + + const isMutation = !!procDef.mutation; + + if (isMutation) { + if (method !== 'POST') { + return this.makeBadInputErrorResponse('invalid request method, only POST is supported'); + } + } else { + if (method !== 'GET') { + return this.makeBadInputErrorResponse('invalid request method, only GET is supported'); + } + } + + let argsPayload = method === 'POST' ? requestBody : undefined; + if (method === 'GET') { + try { + argsPayload = query?.['q'] + ? unmarshalQ(query['q'] as string, query['meta'] as string | undefined) + : undefined; + } catch (err) { + return this.makeBadInputErrorResponse( + err instanceof Error ? err.message : 'invalid "q" query parameter', + ); + } + } + + const { result: processedArgsPayload, error } = await processSuperJsonRequestPayload(argsPayload); + if (error) { + return this.makeBadInputErrorResponse(error); + } + + let procInput: unknown; + try { + procInput = mapProcedureArgs(procDef, processedArgsPayload); + } catch (err) { + return this.makeBadInputErrorResponse(err instanceof Error ? err.message : 'invalid procedure arguments'); + } + + try { + log(this.options.log, 'debug', () => `handling "$procs.${proc}" request`); + + const clientResult = await (client as any).$procs?.[proc](procInput); + + const { json, meta } = SuperJSON.serialize(clientResult); + const responseBody: any = { data: json }; + if (meta) { + responseBody.meta = { serialization: meta }; + } + + const response = { status: 200, body: responseBody }; + log( + this.options.log, + 'debug', + () => `sending response for "$procs.${proc}" request: ${safeJSONStringify(response)}`, + ); + return response; + } catch (err) { + log(this.options.log, 'error', `error occurred when handling "$procs.${proc}" request`, err); + if (err instanceof ORMError) { + return this.makeORMErrorResponse(err); + } + return this.makeGenericErrorResponse(err); + } + } + + private isValidModel(client: ClientContract, model: string) { + return Object.keys(client.$schema.models).some((m) => lowerCaseFirst(m) === lowerCaseFirst(model)); + } + + private makeBadInputErrorResponse(message: string) { + const resp = { + status: 400, + body: { error: { message } }, + }; + log(this.options.log, 'debug', () => `sending error response: ${safeJSONStringify(resp)}`); + return resp; + } + + private makeGenericErrorResponse(err: unknown) { + const resp = { + status: 500, + body: { error: { message: err instanceof Error ? err.message : 'unknown error' } }, + }; + log( + this.options.log, + 'debug', + () => `sending error response: ${safeJSONStringify(resp)}${err instanceof Error ? '\n' + err.stack : ''}`, + ); + return resp; + } + + private makeORMErrorResponse(err: ORMError) { + let status = 400; + const error: any = { message: err.message, reason: err.reason }; + + match(err.reason) + .with(ORMErrorReason.NOT_FOUND, () => { + status = 404; + error.model = err.model; + }) + .with(ORMErrorReason.INVALID_INPUT, () => { + status = 422; + error.rejectedByValidation = true; + error.model = err.model; + }) + .with(ORMErrorReason.REJECTED_BY_POLICY, () => { + status = 403; + error.rejectedByPolicy = true; + error.model = err.model; + error.rejectReason = err.rejectedByPolicyReason; + }) + .with(ORMErrorReason.DB_QUERY_ERROR, () => { + status = 400; + error.dbErrorCode = err.dbErrorCode; + }) + .otherwise(() => {}); + + const resp = { status, body: { error } }; + log(this.options.log, 'debug', () => `sending error response: ${safeJSONStringify(resp)}`); + return resp; + } + + private async processRequestPayload(args: any) { + const { meta, ...rest } = args ?? {}; + if (meta?.serialization) { + try { + // superjson deserialization + args = SuperJSON.deserialize({ json: rest, meta: meta.serialization }); + } catch (err) { + return { result: undefined, error: `failed to deserialize request payload: ${(err as Error).message}` }; + } + } else { + // drop meta when no serialization info is present + args = rest; + } + return { result: args, error: undefined }; + } + + async generateSpec(options?: import('../common/types').OpenApiSpecOptions) { + const generator = new RPCApiSpecGenerator(this.options); + return generator.generateSpec(options); + } +} diff --git a/packages/server/src/api/rpc/index.ts b/packages/server/src/api/rpc/index.ts index 7b3cbcb39..8d09235be 100644 --- a/packages/server/src/api/rpc/index.ts +++ b/packages/server/src/api/rpc/index.ts @@ -1,443 +1,2 @@ -import { lowerCaseFirst, safeJSONStringify } from '@zenstackhq/common-helpers'; -import { CoreCrudOperations, ORMError, ORMErrorReason, type ClientContract } from '@zenstackhq/orm'; -import type { SchemaDef } from '@zenstackhq/orm/schema'; -import SuperJSON from 'superjson'; -import { match } from 'ts-pattern'; -import z from 'zod'; -import { fromError } from 'zod-validation-error/v4'; -import type { ApiHandler, LogConfig, RequestContext, Response } from '../../types'; -import { getProcedureDef, mapProcedureArgs, PROCEDURE_ROUTE_PREFIXES } from '../common/procedures'; -import { loggerSchema } from '../common/schemas'; -import { processSuperJsonRequestPayload, unmarshalQ } from '../common/utils'; -import { log, registerCustomSerializers } from '../utils'; - -const TRANSACTION_ROUTE_PREFIX = '$transaction' as const; -const VALID_OPS = new Set(CoreCrudOperations as unknown as string[]); - -registerCustomSerializers(); - -/** - * Options for {@link RPCApiHandler} - */ -export type RPCApiHandlerOptions = { - /** - * The schema - */ - schema: Schema; - - /** - * Logging configuration - */ - log?: LogConfig; -}; - -/** - * RPC style API request handler that mirrors the ZenStackClient API - */ -export class RPCApiHandler implements ApiHandler { - constructor(private readonly options: RPCApiHandlerOptions) { - this.validateOptions(options); - } - - private validateOptions(options: RPCApiHandlerOptions) { - const schema = z.strictObject({ schema: z.object(), log: loggerSchema.optional() }); - const parseResult = schema.safeParse(options); - if (!parseResult.success) { - throw new Error(`Invalid options: ${fromError(parseResult.error)}`); - } - } - - get schema(): Schema { - return this.options.schema; - } - - get log(): LogConfig | undefined { - return this.options.log; - } - - async handleRequest({ client, method, path, query, requestBody }: RequestContext): Promise { - const parts = path.split('/').filter((p) => !!p); - const op = parts.pop(); - let model = parts.pop(); - - if (parts.length !== 0 || !op || !model) { - return this.makeBadInputErrorResponse('invalid request path'); - } - - if (model === PROCEDURE_ROUTE_PREFIXES) { - return this.handleProcedureRequest({ - client, - method: method.toUpperCase(), - proc: op, - query, - requestBody, - }); - } - - if (model === TRANSACTION_ROUTE_PREFIX) { - return this.handleTransaction({ - client, - method: method.toUpperCase(), - type: op, - requestBody, - }); - } - - model = lowerCaseFirst(model); - method = method.toUpperCase(); - let args: unknown; - let resCode = 200; - - switch (op) { - case 'create': - case 'createMany': - case 'createManyAndReturn': - case 'upsert': - if (method !== 'POST') { - return this.makeBadInputErrorResponse('invalid request method, only POST is supported'); - } - if (!requestBody) { - return this.makeBadInputErrorResponse('missing request body'); - } - - args = requestBody; - resCode = 201; - break; - - case 'findFirst': - case 'findUnique': - case 'findMany': - case 'aggregate': - case 'groupBy': - case 'count': - case 'exists': - if (method !== 'GET') { - return this.makeBadInputErrorResponse('invalid request method, only GET is supported'); - } - try { - args = query?.['q'] ? unmarshalQ(query['q'] as string, query['meta'] as string | undefined) : {}; - } catch { - return this.makeBadInputErrorResponse('invalid "q" query parameter'); - } - break; - - case 'update': - case 'updateMany': - case 'updateManyAndReturn': - if (method !== 'PUT' && method !== 'PATCH') { - return this.makeBadInputErrorResponse('invalid request method, only PUT or PATCH are supported'); - } - if (!requestBody) { - return this.makeBadInputErrorResponse('missing request body'); - } - - args = requestBody; - break; - - case 'delete': - case 'deleteMany': - if (method !== 'DELETE') { - return this.makeBadInputErrorResponse('invalid request method, only DELETE is supported'); - } - try { - args = query?.['q'] ? unmarshalQ(query['q'] as string, query['meta'] as string | undefined) : {}; - } catch (err) { - return this.makeBadInputErrorResponse( - err instanceof Error ? err.message : 'invalid "q" query parameter', - ); - } - break; - - default: - return this.makeBadInputErrorResponse('invalid operation: ' + op); - } - - const { result: processedArgs, error } = await this.processRequestPayload(args); - if (error) { - return this.makeBadInputErrorResponse(error); - } - - try { - if (!this.isValidModel(client, model)) { - return this.makeBadInputErrorResponse(`unknown model name: ${model}`); - } - - log( - this.options.log, - 'debug', - () => `handling "${model}.${op}" request with args: ${safeJSONStringify(processedArgs)}`, - ); - - const clientResult = await (client as any)[model][op](processedArgs); - let responseBody: any = { data: clientResult }; - - // superjson serialize response - if (clientResult) { - const { json, meta } = SuperJSON.serialize(clientResult); - responseBody = { data: json }; - if (meta) { - responseBody.meta = { serialization: meta }; - } - } - - const response = { status: resCode, body: responseBody }; - log( - this.options.log, - 'debug', - () => `sending response for "${model}.${op}" request: ${safeJSONStringify(response)}`, - ); - return response; - } catch (err) { - log(this.options.log, 'error', `error occurred when handling "${model}.${op}" request`, err); - if (err instanceof ORMError) { - return this.makeORMErrorResponse(err); - } else { - return this.makeGenericErrorResponse(err); - } - } - } - - private async handleTransaction({ - client, - method, - type, - requestBody, - }: { - client: ClientContract; - method: string; - type: string; - requestBody?: unknown; - }): Promise { - if (method !== 'POST') { - return this.makeBadInputErrorResponse('invalid request method, only POST is supported'); - } - - if (type !== 'sequential') { - return this.makeBadInputErrorResponse(`unsupported transaction type: ${type}`); - } - - if (!requestBody || !Array.isArray(requestBody) || requestBody.length === 0) { - return this.makeBadInputErrorResponse('request body must be a non-empty array of operations'); - } - - const processedOps: Array<{ model: string; op: string; args: unknown }> = []; - - for (let i = 0; i < requestBody.length; i++) { - const item = requestBody[i]; - if (!item || typeof item !== 'object') { - return this.makeBadInputErrorResponse(`operation at index ${i} must be an object`); - } - const { model: itemModel, op: itemOp, args: itemArgs } = item as any; - if (!itemModel || typeof itemModel !== 'string') { - return this.makeBadInputErrorResponse(`operation at index ${i} is missing a valid "model" field`); - } - if (!itemOp || typeof itemOp !== 'string') { - return this.makeBadInputErrorResponse(`operation at index ${i} is missing a valid "op" field`); - } - if (!VALID_OPS.has(itemOp)) { - return this.makeBadInputErrorResponse(`operation at index ${i} has invalid op: ${itemOp}`); - } - if (!this.isValidModel(client, lowerCaseFirst(itemModel))) { - return this.makeBadInputErrorResponse(`operation at index ${i} has unknown model: ${itemModel}`); - } - if (itemArgs !== undefined && itemArgs !== null && (typeof itemArgs !== 'object' || Array.isArray(itemArgs))) { - return this.makeBadInputErrorResponse(`operation at index ${i} has invalid "args" field`); - } - - const { result: processedArgs, error: argsError } = await this.processRequestPayload(itemArgs ?? {}); - if (argsError) { - return this.makeBadInputErrorResponse(`operation at index ${i}: ${argsError}`); - } - processedOps.push({ model: lowerCaseFirst(itemModel), op: itemOp, args: processedArgs }); - } - - try { - const promises = processedOps.map(({ model, op, args }) => { - return (client as any)[model][op](args); - }); - - log(this.options.log, 'debug', () => `handling "$transaction" request with ${promises.length} operations`); - - const clientResult = await client.$transaction(promises as any); - - const { json, meta } = SuperJSON.serialize(clientResult); - const responseBody: any = { data: json }; - if (meta) { - responseBody.meta = { serialization: meta }; - } - - const response = { status: 200, body: responseBody }; - log( - this.options.log, - 'debug', - () => `sending response for "$transaction" request: ${safeJSONStringify(response)}`, - ); - return response; - } catch (err) { - log(this.options.log, 'error', `error occurred when handling "$transaction" request`, err); - if (err instanceof ORMError) { - return this.makeORMErrorResponse(err); - } - return this.makeGenericErrorResponse(err); - } - } - - private async handleProcedureRequest({ - client, - method, - proc, - query, - requestBody, - }: { - client: ClientContract; - method: string; - proc?: string; - query?: Record; - requestBody?: unknown; - }): Promise { - if (!proc) { - return this.makeBadInputErrorResponse('missing procedure name'); - } - - const procDef = getProcedureDef(this.options.schema, proc); - if (!procDef) { - return this.makeBadInputErrorResponse(`unknown procedure: ${proc}`); - } - - const isMutation = !!procDef.mutation; - - if (isMutation) { - if (method !== 'POST') { - return this.makeBadInputErrorResponse('invalid request method, only POST is supported'); - } - } else { - if (method !== 'GET') { - return this.makeBadInputErrorResponse('invalid request method, only GET is supported'); - } - } - - let argsPayload = method === 'POST' ? requestBody : undefined; - if (method === 'GET') { - try { - argsPayload = query?.['q'] - ? unmarshalQ(query['q'] as string, query['meta'] as string | undefined) - : undefined; - } catch (err) { - return this.makeBadInputErrorResponse( - err instanceof Error ? err.message : 'invalid "q" query parameter', - ); - } - } - - const { result: processedArgsPayload, error } = await processSuperJsonRequestPayload(argsPayload); - if (error) { - return this.makeBadInputErrorResponse(error); - } - - let procInput: unknown; - try { - procInput = mapProcedureArgs(procDef, processedArgsPayload); - } catch (err) { - return this.makeBadInputErrorResponse(err instanceof Error ? err.message : 'invalid procedure arguments'); - } - - try { - log(this.options.log, 'debug', () => `handling "$procs.${proc}" request`); - - const clientResult = await (client as any).$procs?.[proc](procInput); - - const { json, meta } = SuperJSON.serialize(clientResult); - const responseBody: any = { data: json }; - if (meta) { - responseBody.meta = { serialization: meta }; - } - - const response = { status: 200, body: responseBody }; - log( - this.options.log, - 'debug', - () => `sending response for "$procs.${proc}" request: ${safeJSONStringify(response)}`, - ); - return response; - } catch (err) { - log(this.options.log, 'error', `error occurred when handling "$procs.${proc}" request`, err); - if (err instanceof ORMError) { - return this.makeORMErrorResponse(err); - } - return this.makeGenericErrorResponse(err); - } - } - - private isValidModel(client: ClientContract, model: string) { - return Object.keys(client.$schema.models).some((m) => lowerCaseFirst(m) === lowerCaseFirst(model)); - } - - private makeBadInputErrorResponse(message: string) { - const resp = { - status: 400, - body: { error: { message } }, - }; - log(this.options.log, 'debug', () => `sending error response: ${safeJSONStringify(resp)}`); - return resp; - } - - private makeGenericErrorResponse(err: unknown) { - const resp = { - status: 500, - body: { error: { message: err instanceof Error ? err.message : 'unknown error' } }, - }; - log( - this.options.log, - 'debug', - () => `sending error response: ${safeJSONStringify(resp)}${err instanceof Error ? '\n' + err.stack : ''}`, - ); - return resp; - } - - private makeORMErrorResponse(err: ORMError) { - let status = 400; - const error: any = { message: err.message, reason: err.reason }; - - match(err.reason) - .with(ORMErrorReason.NOT_FOUND, () => { - status = 404; - error.model = err.model; - }) - .with(ORMErrorReason.INVALID_INPUT, () => { - status = 422; - error.rejectedByValidation = true; - error.model = err.model; - }) - .with(ORMErrorReason.REJECTED_BY_POLICY, () => { - status = 403; - error.rejectedByPolicy = true; - error.model = err.model; - error.rejectReason = err.rejectedByPolicyReason; - }) - .with(ORMErrorReason.DB_QUERY_ERROR, () => { - status = 400; - error.dbErrorCode = err.dbErrorCode; - }) - .otherwise(() => {}); - - const resp = { status, body: { error } }; - log(this.options.log, 'debug', () => `sending error response: ${safeJSONStringify(resp)}`); - return resp; - } - - private async processRequestPayload(args: any) { - const { meta, ...rest } = args ?? {}; - if (meta?.serialization) { - try { - // superjson deserialization - args = SuperJSON.deserialize({ json: rest, meta: meta.serialization }); - } catch (err) { - return { result: undefined, error: `failed to deserialize request payload: ${(err as Error).message}` }; - } - } else { - // drop meta when no serialization info is present - args = rest; - } - return { result: args, error: undefined }; - } -} +export { RPCApiHandler, type RPCApiHandlerOptions } from './handler'; +export { RPCApiSpecGenerator } from './openapi'; diff --git a/packages/server/src/api/rpc/openapi.ts b/packages/server/src/api/rpc/openapi.ts new file mode 100644 index 000000000..8b98b5857 --- /dev/null +++ b/packages/server/src/api/rpc/openapi.ts @@ -0,0 +1,768 @@ +import { lowerCaseFirst, upperCaseFirst } from '@zenstackhq/common-helpers'; +import type { EnumDef, FieldDef, ModelDef, SchemaDef } from '@zenstackhq/orm/schema'; +import type { OpenAPIV3_1 } from 'openapi-types'; +import { PROCEDURE_ROUTE_PREFIXES } from '../common/procedures'; +import { + getIncludedModels, + isFieldOmitted, + isFilterKindIncluded, + isOperationIncluded, + isProcedureIncluded, +} from '../common/spec-utils'; +import type { OpenApiSpecOptions } from '../common/types'; +import type { RPCApiHandlerOptions } from './handler'; + +type SchemaObject = OpenAPIV3_1.SchemaObject; +type ReferenceObject = OpenAPIV3_1.ReferenceObject; + +/** + * Generates OpenAPI v3.1 specification for the RPC-style CRUD API. + */ +export class RPCApiSpecGenerator { + constructor(private readonly handlerOptions: RPCApiHandlerOptions) {} + + private get schema(): SchemaDef { + return this.handlerOptions.schema; + } + + private get queryOptions() { + return this.handlerOptions?.queryOptions; + } + + generateSpec(options?: OpenApiSpecOptions): OpenAPIV3_1.Document { + return { + openapi: '3.1.0', + info: { + title: options?.title ?? 'ZenStack Generated API', + version: options?.version ?? '1.0.0', + ...(options?.description && { description: options.description }), + ...(options?.summary && { summary: options.summary }), + }, + tags: this.generateTags(), + paths: this.generatePaths(), + components: { + schemas: this.generateSchemas(), + }, + } as OpenAPIV3_1.Document; + } + + private generateTags(): OpenAPIV3_1.TagObject[] { + return getIncludedModels(this.schema, this.queryOptions).map((modelName) => ({ + name: lowerCaseFirst(modelName), + description: `${modelName} operations`, + })); + } + + private generatePaths(): OpenAPIV3_1.PathsObject { + const paths: OpenAPIV3_1.PathsObject = {}; + + for (const modelName of getIncludedModels(this.schema, this.queryOptions)) { + const modelPath = lowerCaseFirst(modelName); + const tag = modelPath; + + // Read operations (GET) + const readOps = ['findMany', 'findUnique', 'findFirst', 'count', 'aggregate', 'groupBy', 'exists']; + for (const op of readOps) { + if (!isOperationIncluded(modelName, op, this.queryOptions)) continue; + const argsSchemaName = `${modelName}${this.opToArgsSchema(op)}`; + paths[`/${modelPath}/${op}`] = { + get: this.buildGetOperation(modelName, op, tag, argsSchemaName), + } as any; + } + + // Write operations + const writeOps: Array<{ op: string; method: 'post' | 'patch' | 'delete' }> = [ + { op: 'create', method: 'post' }, + { op: 'createMany', method: 'post' }, + { op: 'createManyAndReturn', method: 'post' }, + { op: 'upsert', method: 'post' }, + { op: 'update', method: 'patch' }, + { op: 'updateMany', method: 'patch' }, + { op: 'updateManyAndReturn', method: 'patch' }, + { op: 'delete', method: 'delete' }, + { op: 'deleteMany', method: 'delete' }, + ]; + + for (const { op, method } of writeOps) { + if (!isOperationIncluded(modelName, op, this.queryOptions)) continue; + const argsSchemaName = `${modelName}${this.opToArgsSchema(op)}`; + const buildOp = + method === 'post' + ? this.buildPostOperation + : method === 'patch' + ? this.buildPatchOperation + : this.buildDeleteOperation; + paths[`/${modelPath}/${op}`] = { + [method]: buildOp.call(this, modelName, op, tag, argsSchemaName), + }; + } + } + + // Transaction path + paths['/$transaction/sequential'] = { + post: { + tags: ['$transaction'], + summary: 'Execute a sequential transaction', + operationId: 'transaction_sequential', + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'array', + items: { + type: 'object', + properties: { + model: { type: 'string' }, + op: { type: 'string' }, + args: { type: 'object' }, + }, + required: ['model', 'op'], + }, + }, + }, + }, + }, + responses: { + '200': { description: 'Transaction results' }, + '400': { $ref: '#/components/schemas/_ErrorResponse' }, + }, + }, + }; + + // Procedure paths + if (this.schema.procedures) { + for (const [procName, procDef] of Object.entries(this.schema.procedures)) { + if (!isProcedureIncluded(procName, this.queryOptions)) continue; + + const isMutation = !!procDef.mutation; + const pathItem: Record = {}; + + if (isMutation) { + pathItem['post'] = this.buildProcedureOperation(procName, 'post'); + } else { + pathItem['get'] = this.buildProcedureOperation(procName, 'get'); + } + + paths[`/${PROCEDURE_ROUTE_PREFIXES}/${procName}`] = pathItem as any; + } + } + + return paths; + } + + private opToArgsSchema(op: string): string { + return upperCaseFirst(op) + 'Args'; + } + + private buildGetOperation(modelName: string, op: string, tag: string, argsSchemaName: string): Record { + return { + tags: [tag], + summary: `${op} ${modelName}`, + operationId: `${lowerCaseFirst(modelName)}_${op}`, + parameters: [ + { + name: 'q', + in: 'query', + description: `Arguments as JSON (${argsSchemaName})`, + schema: { type: 'string' }, + }, + ], + responses: { + '200': { + description: `Result of ${op}`, + content: { + 'application/json': { + schema: { $ref: `#/components/schemas/${modelName}Response` }, + }, + }, + }, + '400': { $ref: '#/components/schemas/_ErrorResponse' }, + }, + }; + } + + private buildPostOperation( + modelName: string, + op: string, + tag: string, + argsSchemaName: string, + ): Record { + return { + tags: [tag], + summary: `${op} ${modelName}`, + operationId: `${lowerCaseFirst(modelName)}_${op}`, + requestBody: { + required: true, + content: { + 'application/json': { + schema: { $ref: `#/components/schemas/${argsSchemaName}` }, + }, + }, + }, + responses: { + '201': { + description: `Result of ${op}`, + content: { + 'application/json': { + schema: { $ref: `#/components/schemas/${modelName}Response` }, + }, + }, + }, + '400': { $ref: '#/components/schemas/_ErrorResponse' }, + }, + }; + } + + private buildPatchOperation( + modelName: string, + op: string, + tag: string, + argsSchemaName: string, + ): Record { + return { + tags: [tag], + summary: `${op} ${modelName}`, + operationId: `${lowerCaseFirst(modelName)}_${op}`, + requestBody: { + required: true, + content: { + 'application/json': { + schema: { $ref: `#/components/schemas/${argsSchemaName}` }, + }, + }, + }, + responses: { + '200': { + description: `Result of ${op}`, + content: { + 'application/json': { + schema: { $ref: `#/components/schemas/${modelName}Response` }, + }, + }, + }, + '400': { $ref: '#/components/schemas/_ErrorResponse' }, + }, + }; + } + + private buildDeleteOperation( + modelName: string, + op: string, + tag: string, + argsSchemaName: string, + ): Record { + return { + tags: [tag], + summary: `${op} ${modelName}`, + operationId: `${lowerCaseFirst(modelName)}_${op}`, + parameters: [ + { + name: 'q', + in: 'query', + description: `Arguments as JSON (${argsSchemaName})`, + schema: { type: 'string' }, + }, + ], + responses: { + '200': { + description: `Result of ${op}`, + content: { + 'application/json': { + schema: { $ref: `#/components/schemas/${modelName}Response` }, + }, + }, + }, + '400': { $ref: '#/components/schemas/_ErrorResponse' }, + }, + }; + } + + private buildProcedureOperation(procName: string, method: 'get' | 'post'): Record { + const op: Record = { + tags: [PROCEDURE_ROUTE_PREFIXES], + summary: `Execute procedure ${procName}`, + operationId: `proc_${procName}`, + responses: { + '200': { description: `Result of ${procName}` }, + '400': { $ref: '#/components/schemas/_ErrorResponse' }, + }, + }; + + if (method === 'get') { + op['parameters'] = [ + { + name: 'q', + in: 'query', + description: 'Procedure arguments as JSON', + schema: { type: 'string' }, + }, + ]; + } else { + op['requestBody'] = { + content: { + 'application/json': { + schema: { type: 'object' }, + }, + }, + }; + } + + return op; + } + + private generateSchemas(): Record { + const schemas: Record = {}; + + // Shared schemas + schemas['_Meta'] = { + type: 'object', + properties: { serialization: {} }, + }; + schemas['_ErrorResponse'] = { + type: 'object', + properties: { + error: { + type: 'object', + properties: { + message: { type: 'string' }, + }, + }, + }, + }; + + // Per-enum schemas + if (this.schema.enums) { + for (const [enumName, enumDef] of Object.entries(this.schema.enums)) { + schemas[enumName] = this.buildEnumSchema(enumDef); + } + } + + // Per-model schemas + for (const modelName of getIncludedModels(this.schema, this.queryOptions)) { + const modelDef = this.schema.models[modelName]!; + schemas[modelName] = this.buildModelOutputSchema(modelName, modelDef); + schemas[`${modelName}CreateInput`] = this.buildCreateInputSchema(modelName, modelDef); + schemas[`${modelName}UpdateInput`] = this.buildUpdateInputSchema(modelName, modelDef); + schemas[`${modelName}WhereUniqueInput`] = this.buildWhereUniqueInputSchema(modelName, modelDef); + schemas[`${modelName}WhereInput`] = this.buildWhereInputSchema(modelName, modelDef); + schemas[`${modelName}CreateArgs`] = this.buildCreateArgsSchema(modelName); + schemas[`${modelName}CreateManyArgs`] = this.buildCreateManyArgsSchema(modelName); + schemas[`${modelName}UpdateArgs`] = this.buildUpdateArgsSchema(modelName); + schemas[`${modelName}UpdateManyArgs`] = this.buildUpdateManyArgsSchema(modelName); + schemas[`${modelName}UpsertArgs`] = this.buildUpsertArgsSchema(modelName); + schemas[`${modelName}DeleteArgs`] = this.buildDeleteArgsSchema(modelName); + schemas[`${modelName}DeleteManyArgs`] = this.buildDeleteManyArgsSchema(modelName); + schemas[`${modelName}FindManyArgs`] = this.buildFindManyArgsSchema(modelName); + schemas[`${modelName}FindUniqueArgs`] = this.buildFindUniqueArgsSchema(modelName); + schemas[`${modelName}FindFirstArgs`] = this.buildFindFirstArgsSchema(modelName); + schemas[`${modelName}CountArgs`] = this.buildCountArgsSchema(modelName); + schemas[`${modelName}AggregateArgs`] = this.buildAggregateArgsSchema(modelName); + schemas[`${modelName}GroupByArgs`] = this.buildGroupByArgsSchema(modelName); + schemas[`${modelName}ExistsArgs`] = this.buildExistsArgsSchema(modelName); + schemas[`${modelName}Response`] = this.buildResponseSchema(modelName); + } + + return schemas; + } + + private buildEnumSchema(enumDef: EnumDef): SchemaObject { + return { + type: 'string', + enum: Object.values(enumDef.values), + }; + } + + private buildModelOutputSchema(modelName: string, modelDef: ModelDef): SchemaObject { + const properties: Record = {}; + const required: string[] = []; + + for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { + if (fieldDef.omit) continue; + if (isFieldOmitted(modelName, fieldName, this.queryOptions)) continue; + properties[fieldName] = this.fieldToSchema(fieldDef); + if (!fieldDef.optional && !fieldDef.array) { + required.push(fieldName); + } + } + + const result: SchemaObject = { type: 'object', properties }; + if (required.length > 0) { + result.required = required; + } + return result; + } + + private buildCreateInputSchema(_modelName: string, modelDef: ModelDef): SchemaObject { + const idFieldNames = new Set(modelDef.idFields); + const properties: Record = {}; + const required: string[] = []; + + for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { + if (fieldDef.relation) continue; + if (fieldDef.foreignKeyFor) continue; + if (fieldDef.omit) continue; + if (fieldDef.updatedAt) continue; + // Skip auto-generated id fields + if (idFieldNames.has(fieldName) && fieldDef.default !== undefined) continue; + + properties[fieldName] = this.typeToSchema(fieldDef.type); + if (!fieldDef.optional && fieldDef.default === undefined && !fieldDef.array) { + required.push(fieldName); + } + } + + const result: SchemaObject = { type: 'object', properties }; + if (required.length > 0) { + result.required = required; + } + return result; + } + + private buildUpdateInputSchema(_modelName: string, modelDef: ModelDef): SchemaObject { + const properties: Record = {}; + + for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { + if (fieldDef.relation) continue; + if (fieldDef.foreignKeyFor) continue; + if (fieldDef.omit) continue; + if (fieldDef.updatedAt) continue; + + properties[fieldName] = this.typeToSchema(fieldDef.type); + } + + return { type: 'object', properties }; + } + + private buildWhereUniqueInputSchema(_modelName: string, modelDef: ModelDef): SchemaObject { + const properties: Record = {}; + + // ID fields + for (const idFieldName of modelDef.idFields) { + const fieldDef = modelDef.fields[idFieldName]; + if (fieldDef) { + properties[idFieldName] = this.typeToSchema(fieldDef.type); + } + } + + // Unique fields + for (const [uniqueName, uniqueInfo] of Object.entries(modelDef.uniqueFields)) { + if (typeof (uniqueInfo as any).type === 'string') { + // Single unique field + const fieldDef = modelDef.fields[uniqueName]; + if (fieldDef && !properties[uniqueName]) { + properties[uniqueName] = this.typeToSchema(fieldDef.type); + } + } else { + // Compound unique + properties[uniqueName] = { type: 'object' }; + } + } + + return { type: 'object', properties }; + } + + private buildWhereInputSchema(_modelName: string, modelDef: ModelDef): SchemaObject { + const properties: Record = {}; + + for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { + if (fieldDef.relation) continue; + if (fieldDef.omit) continue; + const filterSchema = this.buildFieldFilterSchema(_modelName, fieldName, fieldDef); + if (filterSchema) { + properties[fieldName] = filterSchema; + } + } + + // Logical combinators + properties['AND'] = { + oneOf: [ + { $ref: `#/components/schemas/_${_modelName}WhereInput` }, + { type: 'array', items: { $ref: `#/components/schemas/_${_modelName}WhereInput` } }, + ], + }; + properties['OR'] = { + type: 'array', + items: { $ref: `#/components/schemas/_${_modelName}WhereInput` }, + }; + properties['NOT'] = { + oneOf: [ + { $ref: `#/components/schemas/_${_modelName}WhereInput` }, + { type: 'array', items: { $ref: `#/components/schemas/_${_modelName}WhereInput` } }, + ], + }; + + return { type: 'object', properties }; + } + + private buildCreateArgsSchema(modelName: string): SchemaObject { + return { + type: 'object', + properties: { + data: { $ref: `#/components/schemas/${modelName}CreateInput` }, + select: { type: 'object' }, + include: { type: 'object' }, + }, + required: ['data'], + }; + } + + private buildCreateManyArgsSchema(modelName: string): SchemaObject { + return { + type: 'object', + properties: { + data: { + type: 'array', + items: { $ref: `#/components/schemas/${modelName}CreateInput` }, + }, + }, + required: ['data'], + }; + } + + private buildUpdateArgsSchema(modelName: string): SchemaObject { + return { + type: 'object', + properties: { + where: { $ref: `#/components/schemas/${modelName}WhereUniqueInput` }, + data: { $ref: `#/components/schemas/${modelName}UpdateInput` }, + select: { type: 'object' }, + include: { type: 'object' }, + }, + required: ['where', 'data'], + }; + } + + private buildUpdateManyArgsSchema(modelName: string): SchemaObject { + return { + type: 'object', + properties: { + where: { $ref: `#/components/schemas/${modelName}WhereInput` }, + data: { $ref: `#/components/schemas/${modelName}UpdateInput` }, + }, + required: ['data'], + }; + } + + private buildUpsertArgsSchema(modelName: string): SchemaObject { + return { + type: 'object', + properties: { + where: { $ref: `#/components/schemas/${modelName}WhereUniqueInput` }, + create: { $ref: `#/components/schemas/${modelName}CreateInput` }, + update: { $ref: `#/components/schemas/${modelName}UpdateInput` }, + select: { type: 'object' }, + include: { type: 'object' }, + }, + required: ['where', 'create', 'update'], + }; + } + + private buildDeleteArgsSchema(modelName: string): SchemaObject { + return { + type: 'object', + properties: { + where: { $ref: `#/components/schemas/${modelName}WhereUniqueInput` }, + select: { type: 'object' }, + }, + required: ['where'], + }; + } + + private buildDeleteManyArgsSchema(modelName: string): SchemaObject { + return { + type: 'object', + properties: { + where: { $ref: `#/components/schemas/${modelName}WhereInput` }, + }, + }; + } + + private buildFindManyArgsSchema(modelName: string): SchemaObject { + return { + type: 'object', + properties: { + where: { $ref: `#/components/schemas/${modelName}WhereInput` }, + orderBy: { type: 'object' }, + take: { type: 'integer' }, + skip: { type: 'integer' }, + select: { type: 'object' }, + include: { type: 'object' }, + }, + }; + } + + private buildFindUniqueArgsSchema(modelName: string): SchemaObject { + return { + type: 'object', + properties: { + where: { $ref: `#/components/schemas/${modelName}WhereUniqueInput` }, + select: { type: 'object' }, + include: { type: 'object' }, + }, + required: ['where'], + }; + } + + private buildFindFirstArgsSchema(modelName: string): SchemaObject { + return { + type: 'object', + properties: { + where: { $ref: `#/components/schemas/${modelName}WhereInput` }, + orderBy: { type: 'object' }, + take: { type: 'integer' }, + skip: { type: 'integer' }, + select: { type: 'object' }, + include: { type: 'object' }, + }, + }; + } + + private buildCountArgsSchema(modelName: string): SchemaObject { + return { + type: 'object', + properties: { + where: { $ref: `#/components/schemas/${modelName}WhereInput` }, + take: { type: 'integer' }, + skip: { type: 'integer' }, + }, + }; + } + + private buildAggregateArgsSchema(modelName: string): SchemaObject { + return { + type: 'object', + properties: { + where: { $ref: `#/components/schemas/${modelName}WhereInput` }, + orderBy: { type: 'object' }, + take: { type: 'integer' }, + skip: { type: 'integer' }, + }, + }; + } + + private buildGroupByArgsSchema(modelName: string): SchemaObject { + return { + type: 'object', + properties: { + where: { $ref: `#/components/schemas/${modelName}WhereInput` }, + by: { type: 'array', items: { type: 'string' } }, + orderBy: { type: 'object' }, + take: { type: 'integer' }, + skip: { type: 'integer' }, + }, + }; + } + + private buildExistsArgsSchema(modelName: string): SchemaObject { + return { + type: 'object', + properties: { + where: { $ref: `#/components/schemas/${modelName}WhereUniqueInput` }, + }, + required: ['where'], + }; + } + + private buildResponseSchema(modelName: string): SchemaObject { + return { + type: 'object', + properties: { + data: { $ref: `#/components/schemas/${modelName}` }, + meta: { $ref: '#/components/schemas/_Meta' }, + }, + }; + } + + private fieldToSchema(fieldDef: FieldDef): SchemaObject | ReferenceObject { + const baseSchema = this.typeToSchema(fieldDef.type); + if (fieldDef.array) { + return { type: 'array', items: baseSchema }; + } + if (fieldDef.optional) { + return { oneOf: [baseSchema, { type: 'null' }] }; + } + return baseSchema; + } + + private buildFieldFilterSchema( + modelName: string, + fieldName: string, + fieldDef: FieldDef, + ): SchemaObject | undefined { + const baseSchema = this.typeToSchema(fieldDef.type); + const filterProps: Record = {}; + const type = fieldDef.type; + + // Equality operators + if (isFilterKindIncluded(modelName, fieldName, 'Equality', this.queryOptions)) { + filterProps['equals'] = baseSchema; + filterProps['not'] = baseSchema; + filterProps['in'] = { type: 'array', items: baseSchema }; + filterProps['notIn'] = { type: 'array', items: baseSchema }; + } + + // Range operators (numeric/datetime types) + if ( + (type === 'Int' || type === 'Float' || type === 'BigInt' || type === 'Decimal' || type === 'DateTime') && + isFilterKindIncluded(modelName, fieldName, 'Range', this.queryOptions) + ) { + filterProps['lt'] = baseSchema; + filterProps['lte'] = baseSchema; + filterProps['gt'] = baseSchema; + filterProps['gte'] = baseSchema; + } + + // Like operators (String type) + if (type === 'String' && isFilterKindIncluded(modelName, fieldName, 'Like', this.queryOptions)) { + filterProps['contains'] = { type: 'string' }; + filterProps['startsWith'] = { type: 'string' }; + filterProps['endsWith'] = { type: 'string' }; + filterProps['mode'] = { type: 'string', enum: ['default', 'insensitive'] }; + } + + // List operators (array fields) + if (fieldDef.array && isFilterKindIncluded(modelName, fieldName, 'List', this.queryOptions)) { + filterProps['has'] = baseSchema; + filterProps['hasEvery'] = { type: 'array', items: baseSchema }; + filterProps['hasSome'] = { type: 'array', items: baseSchema }; + filterProps['isEmpty'] = { type: 'boolean' }; + } + + if (Object.keys(filterProps).length === 0) return undefined; + + const filterObject: SchemaObject = { type: 'object', properties: filterProps }; + + // If Equality is included, allow shorthand (direct value) via oneOf + if (isFilterKindIncluded(modelName, fieldName, 'Equality', this.queryOptions)) { + return { oneOf: [baseSchema, filterObject] }; + } + + return filterObject; + } + + private typeToSchema(type: string): SchemaObject | ReferenceObject { + switch (type) { + case 'String': + return { type: 'string' }; + case 'Int': + case 'BigInt': + return { type: 'integer' }; + case 'Float': + return { type: 'number' }; + case 'Decimal': + return { oneOf: [{ type: 'number' }, { type: 'string' }] }; + case 'Boolean': + return { type: 'boolean' }; + case 'DateTime': + return { type: 'string', format: 'date-time' }; + case 'Bytes': + return { type: 'string', format: 'byte' }; + case 'Json': + case 'Unsupported': + return {}; + default: + return { $ref: `#/components/schemas/${type}` }; + } + } +} diff --git a/packages/server/test/openapi/baseline/rest-3.1.0.baseline.yaml b/packages/server/test/openapi/baseline/rest-3.1.0.baseline.yaml new file mode 100644 index 000000000..1e331ab8e --- /dev/null +++ b/packages/server/test/openapi/baseline/rest-3.1.0.baseline.yaml @@ -0,0 +1,3279 @@ +openapi: 3.1.0 +info: + title: ZenStack Generated API + version: 1.0.0 +tags: + - name: user + description: User operations + - name: profile + description: Profile operations + - name: post_Item + description: Post-related operations + - name: postLike + description: PostLike operations +paths: + /user: + get: + operationId: list-User + description: List "User" resources + tags: + - user + parameters: + - $ref: '#/components/parameters/include' + - $ref: '#/components/parameters/sort' + - $ref: '#/components/parameters/page-offset' + - $ref: '#/components/parameters/page-limit' + - name: filter[id] + required: false + description: Id filter + in: query + style: form + explode: false + schema: + type: string + - name: filter[createdAt] + required: false + description: Equality filter for "createdAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[createdAt$lt] + required: false + description: Less-than filter for "createdAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[createdAt$lte] + required: false + description: Less-than or equal filter for "createdAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[createdAt$gt] + required: false + description: Greater-than filter for "createdAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[createdAt$gte] + required: false + description: Greater-than or equal filter for "createdAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[updatedAt] + required: false + description: Equality filter for "updatedAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[updatedAt$lt] + required: false + description: Less-than filter for "updatedAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[updatedAt$lte] + required: false + description: Less-than or equal filter for "updatedAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[updatedAt$gt] + required: false + description: Greater-than filter for "updatedAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[updatedAt$gte] + required: false + description: Greater-than or equal filter for "updatedAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[email] + required: false + description: Equality filter for "email" + in: query + style: form + explode: false + schema: + type: string + - name: filter[email$contains] + required: false + description: String contains filter for "email" + in: query + style: form + explode: false + schema: + type: string + - name: filter[email$icontains] + required: false + description: String case-insensitive contains filter for "email" + in: query + style: form + explode: false + schema: + type: string + - name: filter[email$search] + required: false + description: String full-text search filter for "email" + in: query + style: form + explode: false + schema: + type: string + - name: filter[email$startsWith] + required: false + description: String startsWith filter for "email" + in: query + style: form + explode: false + schema: + type: string + - name: filter[email$endsWith] + required: false + description: String endsWith filter for "email" + in: query + style: form + explode: false + schema: + type: string + - name: filter[role] + required: false + description: Equality filter for "role" + in: query + style: form + explode: false + schema: + $ref: '#/components/schemas/role' + - name: filter[posts] + required: false + description: Equality filter for "posts" + in: query + style: form + explode: false + schema: + type: array + items: + type: string + - name: filter[profile] + required: false + description: Equality filter for "profile" + in: query + style: form + explode: false + schema: + type: string + - name: filter[likes] + required: false + description: Equality filter for "likes" + in: query + style: form + explode: false + schema: + type: array + items: + type: string + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/UserListResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + post: + operationId: create-User + description: Create a "User" resource + tags: + - user + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/UserCreateRequest' + responses: + '201': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/UserResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '422': + description: Request is unprocessable due to validation errors + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + /user/{id}: + get: + operationId: fetch-User + description: Fetch a "User" resource + tags: + - user + parameters: + - $ref: '#/components/parameters/id' + - $ref: '#/components/parameters/include' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/UserResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + put: + operationId: update-User-put + description: Update a "User" resource + tags: + - user + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/UserUpdateRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/UserResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '422': + description: Request is unprocessable due to validation errors + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + patch: + operationId: update-User-patch + description: Update a "User" resource + tags: + - user + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/UserUpdateRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/UserResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '422': + description: Request is unprocessable due to validation errors + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + delete: + operationId: delete-User + description: Delete a "User" resource + tags: + - user + parameters: + - $ref: '#/components/parameters/id' + responses: + '200': + description: Successful operation + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + /user/{id}/posts: + get: + operationId: fetch-User-related-posts + description: Fetch the related "posts" resource for "User" + tags: + - user + parameters: + - $ref: '#/components/parameters/id' + - $ref: '#/components/parameters/include' + - $ref: '#/components/parameters/sort' + - $ref: '#/components/parameters/page-offset' + - $ref: '#/components/parameters/page-limit' + - name: filter[id] + required: false + description: Id filter + in: query + style: form + explode: false + schema: + type: string + - name: filter[createdAt] + required: false + description: Equality filter for "createdAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[createdAt$lt] + required: false + description: Less-than filter for "createdAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[createdAt$lte] + required: false + description: Less-than or equal filter for "createdAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[createdAt$gt] + required: false + description: Greater-than filter for "createdAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[createdAt$gte] + required: false + description: Greater-than or equal filter for "createdAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[updatedAt] + required: false + description: Equality filter for "updatedAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[updatedAt$lt] + required: false + description: Less-than filter for "updatedAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[updatedAt$lte] + required: false + description: Less-than or equal filter for "updatedAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[updatedAt$gt] + required: false + description: Greater-than filter for "updatedAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[updatedAt$gte] + required: false + description: Greater-than or equal filter for "updatedAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[email] + required: false + description: Equality filter for "email" + in: query + style: form + explode: false + schema: + type: string + - name: filter[email$contains] + required: false + description: String contains filter for "email" + in: query + style: form + explode: false + schema: + type: string + - name: filter[email$icontains] + required: false + description: String case-insensitive contains filter for "email" + in: query + style: form + explode: false + schema: + type: string + - name: filter[email$search] + required: false + description: String full-text search filter for "email" + in: query + style: form + explode: false + schema: + type: string + - name: filter[email$startsWith] + required: false + description: String startsWith filter for "email" + in: query + style: form + explode: false + schema: + type: string + - name: filter[email$endsWith] + required: false + description: String endsWith filter for "email" + in: query + style: form + explode: false + schema: + type: string + - name: filter[role] + required: false + description: Equality filter for "role" + in: query + style: form + explode: false + schema: + $ref: '#/components/schemas/role' + - name: filter[posts] + required: false + description: Equality filter for "posts" + in: query + style: form + explode: false + schema: + type: array + items: + type: string + - name: filter[profile] + required: false + description: Equality filter for "profile" + in: query + style: form + explode: false + schema: + type: string + - name: filter[likes] + required: false + description: Equality filter for "likes" + in: query + style: form + explode: false + schema: + type: array + items: + type: string + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/post_ItemListResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + /user/{id}/relationships/posts: + get: + operationId: fetch-User-relationship-posts + description: Fetch the "posts" relationships for a "User" + tags: + - user + parameters: + - $ref: '#/components/parameters/id' + - $ref: '#/components/parameters/sort' + - $ref: '#/components/parameters/page-offset' + - $ref: '#/components/parameters/page-limit' + - name: filter[id] + required: false + description: Id filter + in: query + style: form + explode: false + schema: + type: string + - name: filter[createdAt] + required: false + description: Equality filter for "createdAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[createdAt$lt] + required: false + description: Less-than filter for "createdAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[createdAt$lte] + required: false + description: Less-than or equal filter for "createdAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[createdAt$gt] + required: false + description: Greater-than filter for "createdAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[createdAt$gte] + required: false + description: Greater-than or equal filter for "createdAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[updatedAt] + required: false + description: Equality filter for "updatedAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[updatedAt$lt] + required: false + description: Less-than filter for "updatedAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[updatedAt$lte] + required: false + description: Less-than or equal filter for "updatedAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[updatedAt$gt] + required: false + description: Greater-than filter for "updatedAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[updatedAt$gte] + required: false + description: Greater-than or equal filter for "updatedAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[email] + required: false + description: Equality filter for "email" + in: query + style: form + explode: false + schema: + type: string + - name: filter[email$contains] + required: false + description: String contains filter for "email" + in: query + style: form + explode: false + schema: + type: string + - name: filter[email$icontains] + required: false + description: String case-insensitive contains filter for "email" + in: query + style: form + explode: false + schema: + type: string + - name: filter[email$search] + required: false + description: String full-text search filter for "email" + in: query + style: form + explode: false + schema: + type: string + - name: filter[email$startsWith] + required: false + description: String startsWith filter for "email" + in: query + style: form + explode: false + schema: + type: string + - name: filter[email$endsWith] + required: false + description: String endsWith filter for "email" + in: query + style: form + explode: false + schema: + type: string + - name: filter[role] + required: false + description: Equality filter for "role" + in: query + style: form + explode: false + schema: + $ref: '#/components/schemas/role' + - name: filter[posts] + required: false + description: Equality filter for "posts" + in: query + style: form + explode: false + schema: + type: array + items: + type: string + - name: filter[profile] + required: false + description: Equality filter for "profile" + in: query + style: form + explode: false + schema: + type: string + - name: filter[likes] + required: false + description: Equality filter for "likes" + in: query + style: form + explode: false + schema: + type: array + items: + type: string + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toManyRelationshipResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + put: + operationId: update-User-relationship-posts-put + description: Update "posts" relationships for a "User" + tags: + - user + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toManyRelationshipRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toManyRelationshipResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + patch: + operationId: update-User-relationship-posts-patch + description: Update "posts" relationships for a "User" + tags: + - user + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toManyRelationshipRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toManyRelationshipResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + post: + operationId: create-User-relationship-posts + description: Create new "posts" relationships for a "User" + tags: + - user + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toManyRelationshipRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toManyRelationshipResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + /user/{id}/profile: + get: + operationId: fetch-User-related-profile + description: Fetch the related "profile" resource for "User" + tags: + - user + parameters: + - $ref: '#/components/parameters/id' + - $ref: '#/components/parameters/include' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/ProfileResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + /user/{id}/relationships/profile: + get: + operationId: fetch-User-relationship-profile + description: Fetch the "profile" relationships for a "User" + tags: + - user + parameters: + - $ref: '#/components/parameters/id' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + put: + operationId: update-User-relationship-profile-put + description: Update "profile" relationship for a "User" + tags: + - user + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + patch: + operationId: update-User-relationship-profile-patch + description: Update "profile" relationship for a "User" + tags: + - user + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + /profile: + get: + operationId: list-Profile + description: List "Profile" resources + tags: + - profile + parameters: + - $ref: '#/components/parameters/include' + - $ref: '#/components/parameters/sort' + - $ref: '#/components/parameters/page-offset' + - $ref: '#/components/parameters/page-limit' + - name: filter[id] + required: false + description: Id filter + in: query + style: form + explode: false + schema: + type: string + - name: filter[image] + required: false + description: Equality filter for "image" + in: query + style: form + explode: false + schema: + type: string + - name: filter[image$contains] + required: false + description: String contains filter for "image" + in: query + style: form + explode: false + schema: + type: string + - name: filter[image$icontains] + required: false + description: String case-insensitive contains filter for "image" + in: query + style: form + explode: false + schema: + type: string + - name: filter[image$search] + required: false + description: String full-text search filter for "image" + in: query + style: form + explode: false + schema: + type: string + - name: filter[image$startsWith] + required: false + description: String startsWith filter for "image" + in: query + style: form + explode: false + schema: + type: string + - name: filter[image$endsWith] + required: false + description: String endsWith filter for "image" + in: query + style: form + explode: false + schema: + type: string + - name: filter[user] + required: false + description: Equality filter for "user" + in: query + style: form + explode: false + schema: + type: string + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/ProfileListResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + post: + operationId: create-Profile + description: Create a "Profile" resource + tags: + - profile + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/ProfileCreateRequest' + responses: + '201': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/ProfileResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '422': + description: Request is unprocessable due to validation errors + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + /profile/{id}: + get: + operationId: fetch-Profile + description: Fetch a "Profile" resource + tags: + - profile + parameters: + - $ref: '#/components/parameters/id' + - $ref: '#/components/parameters/include' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/ProfileResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + put: + operationId: update-Profile-put + description: Update a "Profile" resource + tags: + - profile + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/ProfileUpdateRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/ProfileResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '422': + description: Request is unprocessable due to validation errors + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + patch: + operationId: update-Profile-patch + description: Update a "Profile" resource + tags: + - profile + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/ProfileUpdateRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/ProfileResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '422': + description: Request is unprocessable due to validation errors + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + delete: + operationId: delete-Profile + description: Delete a "Profile" resource + tags: + - profile + parameters: + - $ref: '#/components/parameters/id' + responses: + '200': + description: Successful operation + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + /profile/{id}/user: + get: + operationId: fetch-Profile-related-user + description: Fetch the related "user" resource for "Profile" + tags: + - profile + parameters: + - $ref: '#/components/parameters/id' + - $ref: '#/components/parameters/include' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/UserResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + /profile/{id}/relationships/user: + get: + operationId: fetch-Profile-relationship-user + description: Fetch the "user" relationships for a "Profile" + tags: + - profile + parameters: + - $ref: '#/components/parameters/id' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + put: + operationId: update-Profile-relationship-user-put + description: Update "user" relationship for a "Profile" + tags: + - profile + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + patch: + operationId: update-Profile-relationship-user-patch + description: Update "user" relationship for a "Profile" + tags: + - profile + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + /post_Item: + get: + operationId: list-post_Item + description: List "post_Item" resources + tags: + - post_Item + parameters: + - $ref: '#/components/parameters/include' + - $ref: '#/components/parameters/sort' + - $ref: '#/components/parameters/page-offset' + - $ref: '#/components/parameters/page-limit' + - name: filter[id] + required: false + description: Id filter + in: query + style: form + explode: false + schema: + type: string + - name: filter[createdAt] + required: false + description: Equality filter for "createdAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[createdAt$lt] + required: false + description: Less-than filter for "createdAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[createdAt$lte] + required: false + description: Less-than or equal filter for "createdAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[createdAt$gt] + required: false + description: Greater-than filter for "createdAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[createdAt$gte] + required: false + description: Greater-than or equal filter for "createdAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[updatedAt] + required: false + description: Equality filter for "updatedAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[updatedAt$lt] + required: false + description: Less-than filter for "updatedAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[updatedAt$lte] + required: false + description: Less-than or equal filter for "updatedAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[updatedAt$gt] + required: false + description: Greater-than filter for "updatedAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[updatedAt$gte] + required: false + description: Greater-than or equal filter for "updatedAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[title] + required: false + description: Equality filter for "title" + in: query + style: form + explode: false + schema: + type: string + - name: filter[title$contains] + required: false + description: String contains filter for "title" + in: query + style: form + explode: false + schema: + type: string + - name: filter[title$icontains] + required: false + description: String case-insensitive contains filter for "title" + in: query + style: form + explode: false + schema: + type: string + - name: filter[title$search] + required: false + description: String full-text search filter for "title" + in: query + style: form + explode: false + schema: + type: string + - name: filter[title$startsWith] + required: false + description: String startsWith filter for "title" + in: query + style: form + explode: false + schema: + type: string + - name: filter[title$endsWith] + required: false + description: String endsWith filter for "title" + in: query + style: form + explode: false + schema: + type: string + - name: filter[author] + required: false + description: Equality filter for "author" + in: query + style: form + explode: false + schema: + type: string + - name: filter[published] + required: false + description: Equality filter for "published" + in: query + style: form + explode: false + schema: + type: boolean + - name: filter[viewCount] + required: false + description: Equality filter for "viewCount" + in: query + style: form + explode: false + schema: + type: integer + - name: filter[viewCount$lt] + required: false + description: Less-than filter for "viewCount" + in: query + style: form + explode: false + schema: + type: integer + - name: filter[viewCount$lte] + required: false + description: Less-than or equal filter for "viewCount" + in: query + style: form + explode: false + schema: + type: integer + - name: filter[viewCount$gt] + required: false + description: Greater-than filter for "viewCount" + in: query + style: form + explode: false + schema: + type: integer + - name: filter[viewCount$gte] + required: false + description: Greater-than or equal filter for "viewCount" + in: query + style: form + explode: false + schema: + type: integer + - name: filter[notes] + required: false + description: Equality filter for "notes" + in: query + style: form + explode: false + schema: + type: string + - name: filter[notes$contains] + required: false + description: String contains filter for "notes" + in: query + style: form + explode: false + schema: + type: string + - name: filter[notes$icontains] + required: false + description: String case-insensitive contains filter for "notes" + in: query + style: form + explode: false + schema: + type: string + - name: filter[notes$search] + required: false + description: String full-text search filter for "notes" + in: query + style: form + explode: false + schema: + type: string + - name: filter[notes$startsWith] + required: false + description: String startsWith filter for "notes" + in: query + style: form + explode: false + schema: + type: string + - name: filter[notes$endsWith] + required: false + description: String endsWith filter for "notes" + in: query + style: form + explode: false + schema: + type: string + - name: filter[likes] + required: false + description: Equality filter for "likes" + in: query + style: form + explode: false + schema: + type: array + items: + type: string + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/post_ItemListResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + post: + operationId: create-post_Item + description: Create a "post_Item" resource + tags: + - post_Item + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/post_ItemCreateRequest' + responses: + '201': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/post_ItemResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '422': + description: Request is unprocessable due to validation errors + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + /post_Item/{id}: + get: + operationId: fetch-post_Item + description: Fetch a "post_Item" resource + tags: + - post_Item + parameters: + - $ref: '#/components/parameters/id' + - $ref: '#/components/parameters/include' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/post_ItemResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + put: + operationId: update-post_Item-put + description: Update a "post_Item" resource + tags: + - post_Item + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/post_ItemUpdateRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/post_ItemResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '422': + description: Request is unprocessable due to validation errors + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + patch: + operationId: update-post_Item-patch + description: Update a "post_Item" resource + tags: + - post_Item + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/post_ItemUpdateRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/post_ItemResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '422': + description: Request is unprocessable due to validation errors + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + delete: + operationId: delete-post_Item + description: Delete a "post_Item" resource + tags: + - post_Item + parameters: + - $ref: '#/components/parameters/id' + responses: + '200': + description: Successful operation + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + /post_Item/{id}/author: + get: + operationId: fetch-post_Item-related-author + description: Fetch the related "author" resource for "post_Item" + tags: + - post_Item + parameters: + - $ref: '#/components/parameters/id' + - $ref: '#/components/parameters/include' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/UserResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + /post_Item/{id}/relationships/author: + get: + operationId: fetch-post_Item-relationship-author + description: Fetch the "author" relationships for a "post_Item" + tags: + - post_Item + parameters: + - $ref: '#/components/parameters/id' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + put: + operationId: update-post_Item-relationship-author-put + description: Update "author" relationship for a "post_Item" + tags: + - post_Item + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + patch: + operationId: update-post_Item-relationship-author-patch + description: Update "author" relationship for a "post_Item" + tags: + - post_Item + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + /postLike: + get: + operationId: list-PostLike + description: List "PostLike" resources + tags: + - postLike + parameters: + - $ref: '#/components/parameters/include' + - $ref: '#/components/parameters/sort' + - $ref: '#/components/parameters/page-offset' + - $ref: '#/components/parameters/page-limit' + - name: filter[post] + required: false + description: Equality filter for "post" + in: query + style: form + explode: false + schema: + type: string + - name: filter[user] + required: false + description: Equality filter for "user" + in: query + style: form + explode: false + schema: + type: string + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/PostLikeListResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + post: + operationId: create-PostLike + description: Create a "PostLike" resource + tags: + - postLike + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/PostLikeCreateRequest' + responses: + '201': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/PostLikeResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '422': + description: Request is unprocessable due to validation errors + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + /postLike/{id}: + get: + operationId: fetch-PostLike + description: Fetch a "PostLike" resource + tags: + - postLike + parameters: + - $ref: '#/components/parameters/id' + - $ref: '#/components/parameters/include' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/PostLikeResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + put: + operationId: update-PostLike-put + description: Update a "PostLike" resource + tags: + - postLike + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/PostLikeUpdateRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/PostLikeResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '422': + description: Request is unprocessable due to validation errors + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + patch: + operationId: update-PostLike-patch + description: Update a "PostLike" resource + tags: + - postLike + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/PostLikeUpdateRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/PostLikeResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '422': + description: Request is unprocessable due to validation errors + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + delete: + operationId: delete-PostLike + description: Delete a "PostLike" resource + tags: + - postLike + parameters: + - $ref: '#/components/parameters/id' + responses: + '200': + description: Successful operation + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + /postLike/{id}/post: + get: + operationId: fetch-PostLike-related-post + description: Fetch the related "post" resource for "PostLike" + tags: + - postLike + parameters: + - $ref: '#/components/parameters/id' + - $ref: '#/components/parameters/include' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/post_ItemResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + /postLike/{id}/relationships/post: + get: + operationId: fetch-PostLike-relationship-post + description: Fetch the "post" relationships for a "PostLike" + tags: + - postLike + parameters: + - $ref: '#/components/parameters/id' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + put: + operationId: update-PostLike-relationship-post-put + description: Update "post" relationship for a "PostLike" + tags: + - postLike + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + patch: + operationId: update-PostLike-relationship-post-patch + description: Update "post" relationship for a "PostLike" + tags: + - postLike + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + /postLike/{id}/user: + get: + operationId: fetch-PostLike-related-user + description: Fetch the related "user" resource for "PostLike" + tags: + - postLike + parameters: + - $ref: '#/components/parameters/id' + - $ref: '#/components/parameters/include' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/UserResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + /postLike/{id}/relationships/user: + get: + operationId: fetch-PostLike-relationship-user + description: Fetch the "user" relationships for a "PostLike" + tags: + - postLike + parameters: + - $ref: '#/components/parameters/id' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + put: + operationId: update-PostLike-relationship-user-put + description: Update "user" relationship for a "PostLike" + tags: + - postLike + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + patch: + operationId: update-PostLike-relationship-user-patch + description: Update "user" relationship for a "PostLike" + tags: + - postLike + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' +components: + schemas: + _jsonapi: + type: object + description: An object describing the server’s implementation + required: + - version + properties: + version: + type: string + _meta: + type: object + description: Meta information about the request or response + properties: + serialization: + description: Superjson serialization metadata + additionalProperties: true + _resourceIdentifier: + type: object + description: Identifier for a resource + required: + - type + - id + properties: + type: + type: string + description: Resource type + id: + type: string + description: Resource id + _resource: + allOf: + - $ref: '#/components/schemas/_resourceIdentifier' + - type: object + description: A resource with attributes and relationships + properties: + attributes: + type: object + description: Resource attributes + relationships: + type: object + description: Resource relationships + _links: + type: object + required: + - self + description: Links related to the resource + properties: + self: + type: string + description: Link for refetching the curent results + _pagination: + type: object + description: Pagination information + required: + - first + - last + - prev + - next + properties: + first: + oneOf: + - type: 'null' + - type: string + description: Link to the first page + last: + oneOf: + - type: 'null' + - type: string + description: Link to the last page + prev: + oneOf: + - type: 'null' + - type: string + description: Link to the previous page + next: + oneOf: + - type: 'null' + - type: string + description: Link to the next page + _errors: + type: array + description: An array of error objects + items: + type: object + required: + - status + - code + properties: + status: + type: string + description: HTTP status + code: + type: string + description: Error code + prismaCode: + type: string + description: Prisma error code if the error is thrown by Prisma + title: + type: string + description: Error title + detail: + type: string + description: Error detail + reason: + type: string + description: Detailed error reason + zodErrors: + type: object + additionalProperties: true + description: Zod validation errors if the error is due to data validation + failure + _errorResponse: + type: object + required: + - errors + description: An error response + properties: + jsonapi: + $ref: '#/components/schemas/_jsonapi' + errors: + $ref: '#/components/schemas/_errors' + _relationLinks: + type: object + required: + - self + - related + description: Links related to a relationship + properties: + self: + type: string + description: Link for fetching this relationship + related: + type: string + description: Link for fetching the resource represented by this relationship + _toOneRelationship: + type: object + description: A to-one relationship + properties: + data: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/_resourceIdentifier' + _toOneRelationshipWithLinks: + type: object + required: + - links + - data + description: A to-one relationship with links + properties: + links: + $ref: '#/components/schemas/_relationLinks' + data: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/_resourceIdentifier' + _toManyRelationship: + type: object + required: + - data + description: A to-many relationship + properties: + data: + type: array + items: + $ref: '#/components/schemas/_resourceIdentifier' + _toManyRelationshipWithLinks: + type: object + required: + - links + - data + description: A to-many relationship with links + properties: + links: + $ref: '#/components/schemas/_pagedRelationLinks' + data: + type: array + items: + $ref: '#/components/schemas/_resourceIdentifier' + _pagedRelationLinks: + description: Relationship links with pagination information + allOf: + - $ref: '#/components/schemas/_pagination' + - $ref: '#/components/schemas/_relationLinks' + _toManyRelationshipRequest: + type: object + required: + - data + description: Input for manipulating a to-many relationship + properties: + data: + type: array + items: + $ref: '#/components/schemas/_resourceIdentifier' + _toOneRelationshipRequest: + description: Input for manipulating a to-one relationship + oneOf: + - type: 'null' + - type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/_resourceIdentifier' + _toManyRelationshipResponse: + description: Response for a to-many relationship + allOf: + - $ref: '#/components/schemas/_toManyRelationshipWithLinks' + - type: object + properties: + jsonapi: + $ref: '#/components/schemas/_jsonapi' + _toOneRelationshipResponse: + description: Response for a to-one relationship + allOf: + - $ref: '#/components/schemas/_toOneRelationshipWithLinks' + - type: object + properties: + jsonapi: + $ref: '#/components/schemas/_jsonapi' + role: + type: string + description: The "role" Enum + enum: + - USER + - ADMIN + User: + type: object + description: The "User" model + required: + - id + - type + - attributes + properties: + id: + type: string + type: + type: string + attributes: + type: object + properties: + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + email: + type: string + role: + $ref: '#/components/schemas/role' + required: + - createdAt + - updatedAt + - email + - role + relationships: + type: object + properties: + posts: + $ref: '#/components/schemas/_toManyRelationshipWithLinks' + profile: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/_toOneRelationshipWithLinks' + UserCreateRequest: + type: object + description: Input for creating a "User" + required: + - data + properties: + data: + type: object + description: The "User" model + required: + - type + - attributes + properties: + type: + type: string + attributes: + type: object + required: + - updatedAt + - email + properties: + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + email: + type: string + role: + $ref: '#/components/schemas/role' + relationships: + type: object + properties: + posts: + $ref: '#/components/schemas/_toManyRelationship' + profile: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/_toOneRelationship' + meta: + $ref: '#/components/schemas/_meta' + UserUpdateRequest: + type: object + description: Input for updating a "User" + required: + - data + properties: + data: + type: object + description: The "User" model + required: + - id + - type + - attributes + properties: + id: + type: string + type: + type: string + attributes: + type: object + properties: + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + email: + type: string + role: + $ref: '#/components/schemas/role' + relationships: + type: object + properties: + posts: + $ref: '#/components/schemas/_toManyRelationship' + profile: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/_toOneRelationship' + meta: + $ref: '#/components/schemas/_meta' + UserResponse: + type: object + description: Response for a "User" + required: + - data + properties: + jsonapi: + $ref: '#/components/schemas/_jsonapi' + data: + allOf: + - $ref: '#/components/schemas/User' + - type: object + properties: + relationships: + type: object + properties: &a1 + posts: + $ref: '#/components/schemas/_toManyRelationship' + profile: + $ref: '#/components/schemas/_toOneRelationship' + meta: + $ref: '#/components/schemas/_meta' + included: + type: array + items: + $ref: '#/components/schemas/_resource' + links: + $ref: '#/components/schemas/_links' + UserListResponse: + type: object + description: Response for a list of "User" + required: + - data + - links + properties: + jsonapi: + $ref: '#/components/schemas/_jsonapi' + data: + type: array + items: + allOf: + - $ref: '#/components/schemas/User' + - type: object + properties: + relationships: + type: object + properties: *a1 + meta: + $ref: '#/components/schemas/_meta' + included: + type: array + items: + $ref: '#/components/schemas/_resource' + links: + allOf: + - $ref: '#/components/schemas/_links' + - $ref: '#/components/schemas/_pagination' + Profile: + type: object + description: The "Profile" model + required: + - id + - type + - attributes + properties: + id: + type: string + type: + type: string + attributes: + type: object + properties: + image: + oneOf: + - type: 'null' + - type: string + userId: + type: string + required: + - image + - userId + relationships: + type: object + properties: + user: + $ref: '#/components/schemas/_toOneRelationshipWithLinks' + ProfileCreateRequest: + type: object + description: Input for creating a "Profile" + required: + - data + properties: + data: + type: object + description: The "Profile" model + required: + - type + - attributes + properties: + type: + type: string + attributes: + type: object + properties: + image: + oneOf: + - type: 'null' + - type: string + relationships: + type: object + properties: + user: + $ref: '#/components/schemas/_toOneRelationship' + meta: + $ref: '#/components/schemas/_meta' + ProfileUpdateRequest: + type: object + description: Input for updating a "Profile" + required: + - data + properties: + data: + type: object + description: The "Profile" model + required: + - id + - type + - attributes + properties: + id: + type: string + type: + type: string + attributes: + type: object + properties: + image: + oneOf: + - type: 'null' + - type: string + relationships: + type: object + properties: + user: + $ref: '#/components/schemas/_toOneRelationship' + meta: + $ref: '#/components/schemas/_meta' + ProfileResponse: + type: object + description: Response for a "Profile" + required: + - data + properties: + jsonapi: + $ref: '#/components/schemas/_jsonapi' + data: + allOf: + - $ref: '#/components/schemas/Profile' + - type: object + properties: + relationships: + type: object + properties: &a2 + user: + $ref: '#/components/schemas/_toOneRelationship' + meta: + $ref: '#/components/schemas/_meta' + included: + type: array + items: + $ref: '#/components/schemas/_resource' + links: + $ref: '#/components/schemas/_links' + ProfileListResponse: + type: object + description: Response for a list of "Profile" + required: + - data + - links + properties: + jsonapi: + $ref: '#/components/schemas/_jsonapi' + data: + type: array + items: + allOf: + - $ref: '#/components/schemas/Profile' + - type: object + properties: + relationships: + type: object + properties: *a2 + meta: + $ref: '#/components/schemas/_meta' + included: + type: array + items: + $ref: '#/components/schemas/_resource' + links: + allOf: + - $ref: '#/components/schemas/_links' + - $ref: '#/components/schemas/_pagination' + post_Item: + type: object + description: The "post_Item" model + required: + - id + - type + - attributes + properties: + id: + type: string + type: + type: string + attributes: + type: object + properties: + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + title: + type: string + authorId: + oneOf: + - type: 'null' + - type: string + published: + type: boolean + viewCount: + type: integer + notes: + oneOf: + - type: 'null' + - type: string + required: + - createdAt + - updatedAt + - title + - authorId + - published + - viewCount + - notes + relationships: + type: object + properties: + author: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/_toOneRelationshipWithLinks' + post_ItemCreateRequest: + type: object + description: Input for creating a "post_Item" + required: + - data + properties: + data: + type: object + description: The "post_Item" model + required: + - id + - type + - attributes + properties: + id: + type: string + type: + type: string + attributes: + type: object + required: + - updatedAt + - title + properties: + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + title: + type: string + published: + type: boolean + viewCount: + type: integer + notes: + oneOf: + - type: 'null' + - type: string + relationships: + type: object + properties: + author: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/_toOneRelationship' + meta: + $ref: '#/components/schemas/_meta' + post_ItemUpdateRequest: + type: object + description: Input for updating a "post_Item" + required: + - data + properties: + data: + type: object + description: The "post_Item" model + required: + - id + - type + - attributes + properties: + id: + type: string + type: + type: string + attributes: + type: object + properties: + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + title: + type: string + published: + type: boolean + viewCount: + type: integer + notes: + oneOf: + - type: 'null' + - type: string + relationships: + type: object + properties: + author: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/_toOneRelationship' + meta: + $ref: '#/components/schemas/_meta' + post_ItemResponse: + type: object + description: Response for a "post_Item" + required: + - data + properties: + jsonapi: + $ref: '#/components/schemas/_jsonapi' + data: + allOf: + - $ref: '#/components/schemas/post_Item' + - type: object + properties: + relationships: + type: object + properties: &a3 + author: + $ref: '#/components/schemas/_toOneRelationship' + meta: + $ref: '#/components/schemas/_meta' + included: + type: array + items: + $ref: '#/components/schemas/_resource' + links: + $ref: '#/components/schemas/_links' + post_ItemListResponse: + type: object + description: Response for a list of "post_Item" + required: + - data + - links + properties: + jsonapi: + $ref: '#/components/schemas/_jsonapi' + data: + type: array + items: + allOf: + - $ref: '#/components/schemas/post_Item' + - type: object + properties: + relationships: + type: object + properties: *a3 + meta: + $ref: '#/components/schemas/_meta' + included: + type: array + items: + $ref: '#/components/schemas/_resource' + links: + allOf: + - $ref: '#/components/schemas/_links' + - $ref: '#/components/schemas/_pagination' + PostLike: + type: object + description: The "PostLike" model + required: + - id + - type + - attributes + properties: + id: + type: string + type: + type: string + attributes: + type: object + properties: + postId: + type: string + userId: + type: string + required: + - postId + - userId + relationships: + type: object + properties: + post: + $ref: '#/components/schemas/_toOneRelationshipWithLinks' + user: + $ref: '#/components/schemas/_toOneRelationshipWithLinks' + PostLikeCreateRequest: + type: object + description: Input for creating a "PostLike" + required: + - data + properties: + data: + type: object + description: The "PostLike" model + required: + - type + - attributes + properties: + type: + type: string + relationships: + type: object + properties: + post: + $ref: '#/components/schemas/_toOneRelationship' + user: + $ref: '#/components/schemas/_toOneRelationship' + meta: + $ref: '#/components/schemas/_meta' + PostLikeUpdateRequest: + type: object + description: Input for updating a "PostLike" + required: + - data + properties: + data: + type: object + description: The "PostLike" model + required: + - id + - type + - attributes + properties: + id: + type: string + type: + type: string + relationships: + type: object + properties: + post: + $ref: '#/components/schemas/_toOneRelationship' + user: + $ref: '#/components/schemas/_toOneRelationship' + meta: + $ref: '#/components/schemas/_meta' + PostLikeResponse: + type: object + description: Response for a "PostLike" + required: + - data + properties: + jsonapi: + $ref: '#/components/schemas/_jsonapi' + data: + allOf: + - $ref: '#/components/schemas/PostLike' + - type: object + properties: + relationships: + type: object + properties: + post: + $ref: '#/components/schemas/_toOneRelationship' + user: + $ref: '#/components/schemas/_toOneRelationship' + meta: + $ref: '#/components/schemas/_meta' + included: + type: array + items: + $ref: '#/components/schemas/_resource' + links: + $ref: '#/components/schemas/_links' + PostLikeListResponse: + type: object + description: Response for a list of "PostLike" + required: + - data + - links + properties: + jsonapi: + $ref: '#/components/schemas/_jsonapi' + data: + type: array + items: + allOf: + - $ref: '#/components/schemas/PostLike' + - type: object + properties: + relationships: + type: object + properties: + post: + $ref: '#/components/schemas/_toOneRelationship' + user: + $ref: '#/components/schemas/_toOneRelationship' + meta: + $ref: '#/components/schemas/_meta' + included: + type: array + items: + $ref: '#/components/schemas/_resource' + links: + allOf: + - $ref: '#/components/schemas/_links' + - $ref: '#/components/schemas/_pagination' + parameters: + id: + name: id + in: path + description: The resource id + required: true + schema: + type: string + include: + name: include + in: query + description: Relationships to include + required: false + style: form + schema: + type: string + sort: + name: sort + in: query + description: Fields to sort by + required: false + style: form + schema: + type: string + page-offset: + name: page[offset] + in: query + description: Offset for pagination + required: false + style: form + schema: + type: integer + page-limit: + name: page[limit] + in: query + description: Limit for pagination + required: false + style: form + schema: + type: integer diff --git a/packages/server/test/openapi/baseline/rest-type-coverage-3.1.0.baseline.yaml b/packages/server/test/openapi/baseline/rest-type-coverage-3.1.0.baseline.yaml new file mode 100644 index 000000000..6d41ebdf6 --- /dev/null +++ b/packages/server/test/openapi/baseline/rest-type-coverage-3.1.0.baseline.yaml @@ -0,0 +1,876 @@ +openapi: 3.1.0 +info: + title: ZenStack Generated API + version: 1.0.0 +tags: + - name: foo + description: Foo operations +paths: + /foo: + get: + operationId: list-Foo + description: List "Foo" resources + tags: + - foo + parameters: + - $ref: '#/components/parameters/include' + - $ref: '#/components/parameters/sort' + - $ref: '#/components/parameters/page-offset' + - $ref: '#/components/parameters/page-limit' + - name: filter[id] + required: false + description: Id filter + in: query + style: form + explode: false + schema: + type: string + - name: filter[string] + required: false + description: Equality filter for "string" + in: query + style: form + explode: false + schema: + type: string + - name: filter[string$contains] + required: false + description: String contains filter for "string" + in: query + style: form + explode: false + schema: + type: string + - name: filter[string$icontains] + required: false + description: String case-insensitive contains filter for "string" + in: query + style: form + explode: false + schema: + type: string + - name: filter[string$search] + required: false + description: String full-text search filter for "string" + in: query + style: form + explode: false + schema: + type: string + - name: filter[string$startsWith] + required: false + description: String startsWith filter for "string" + in: query + style: form + explode: false + schema: + type: string + - name: filter[string$endsWith] + required: false + description: String endsWith filter for "string" + in: query + style: form + explode: false + schema: + type: string + - name: filter[int] + required: false + description: Equality filter for "int" + in: query + style: form + explode: false + schema: + type: integer + - name: filter[int$lt] + required: false + description: Less-than filter for "int" + in: query + style: form + explode: false + schema: + type: integer + - name: filter[int$lte] + required: false + description: Less-than or equal filter for "int" + in: query + style: form + explode: false + schema: + type: integer + - name: filter[int$gt] + required: false + description: Greater-than filter for "int" + in: query + style: form + explode: false + schema: + type: integer + - name: filter[int$gte] + required: false + description: Greater-than or equal filter for "int" + in: query + style: form + explode: false + schema: + type: integer + - name: filter[bigInt] + required: false + description: Equality filter for "bigInt" + in: query + style: form + explode: false + schema: + type: integer + - name: filter[bigInt$lt] + required: false + description: Less-than filter for "bigInt" + in: query + style: form + explode: false + schema: + type: integer + - name: filter[bigInt$lte] + required: false + description: Less-than or equal filter for "bigInt" + in: query + style: form + explode: false + schema: + type: integer + - name: filter[bigInt$gt] + required: false + description: Greater-than filter for "bigInt" + in: query + style: form + explode: false + schema: + type: integer + - name: filter[bigInt$gte] + required: false + description: Greater-than or equal filter for "bigInt" + in: query + style: form + explode: false + schema: + type: integer + - name: filter[date] + required: false + description: Equality filter for "date" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[date$lt] + required: false + description: Less-than filter for "date" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[date$lte] + required: false + description: Less-than or equal filter for "date" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[date$gt] + required: false + description: Greater-than filter for "date" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[date$gte] + required: false + description: Greater-than or equal filter for "date" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[float] + required: false + description: Equality filter for "float" + in: query + style: form + explode: false + schema: + type: number + - name: filter[float$lt] + required: false + description: Less-than filter for "float" + in: query + style: form + explode: false + schema: + type: number + - name: filter[float$lte] + required: false + description: Less-than or equal filter for "float" + in: query + style: form + explode: false + schema: + type: number + - name: filter[float$gt] + required: false + description: Greater-than filter for "float" + in: query + style: form + explode: false + schema: + type: number + - name: filter[float$gte] + required: false + description: Greater-than or equal filter for "float" + in: query + style: form + explode: false + schema: + type: number + - name: filter[decimal] + required: false + description: Equality filter for "decimal" + in: query + style: form + explode: false + schema: + oneOf: + - type: number + - type: string + - name: filter[decimal$lt] + required: false + description: Less-than filter for "decimal" + in: query + style: form + explode: false + schema: + oneOf: + - type: number + - type: string + - name: filter[decimal$lte] + required: false + description: Less-than or equal filter for "decimal" + in: query + style: form + explode: false + schema: + oneOf: + - type: number + - type: string + - name: filter[decimal$gt] + required: false + description: Greater-than filter for "decimal" + in: query + style: form + explode: false + schema: + oneOf: + - type: number + - type: string + - name: filter[decimal$gte] + required: false + description: Greater-than or equal filter for "decimal" + in: query + style: form + explode: false + schema: + oneOf: + - type: number + - type: string + - name: filter[boolean] + required: false + description: Equality filter for "boolean" + in: query + style: form + explode: false + schema: + type: boolean + - name: filter[bytes] + required: false + description: Equality filter for "bytes" + in: query + style: form + explode: false + schema: + type: string + format: byte + description: Base64 encoded byte array + - name: filter[json] + required: false + description: Equality filter for "json" + in: query + style: form + explode: false + schema: + type: string + format: json + - name: filter[plainJson] + required: false + description: Equality filter for "plainJson" + in: query + style: form + explode: false + schema: + type: string + format: json + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/FooListResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + security: [] + post: + operationId: create-Foo + description: Create a "Foo" resource + tags: + - foo + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/FooCreateRequest' + responses: + '201': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/FooResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '422': + description: Request is unprocessable due to validation errors + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + security: [] + /foo/{id}: + get: + operationId: fetch-Foo + description: Fetch a "Foo" resource + tags: + - foo + parameters: + - $ref: '#/components/parameters/id' + - $ref: '#/components/parameters/include' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/FooResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + security: [] + put: + operationId: update-Foo-put + description: Update a "Foo" resource + tags: + - foo + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/FooUpdateRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/FooResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '422': + description: Request is unprocessable due to validation errors + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + security: [] + patch: + operationId: update-Foo-patch + description: Update a "Foo" resource + tags: + - foo + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/FooUpdateRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/FooResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '422': + description: Request is unprocessable due to validation errors + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + security: [] + delete: + operationId: delete-Foo + description: Delete a "Foo" resource + tags: + - foo + parameters: + - $ref: '#/components/parameters/id' + responses: + '200': + description: Successful operation + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + security: [] +components: + schemas: + _jsonapi: + type: object + description: An object describing the server’s implementation + required: + - version + properties: + version: + type: string + _meta: + type: object + description: Meta information about the request or response + properties: + serialization: + description: Superjson serialization metadata + additionalProperties: true + _resourceIdentifier: + type: object + description: Identifier for a resource + required: + - type + - id + properties: + type: + type: string + description: Resource type + id: + type: string + description: Resource id + _resource: + allOf: + - $ref: '#/components/schemas/_resourceIdentifier' + - type: object + description: A resource with attributes and relationships + properties: + attributes: + type: object + description: Resource attributes + relationships: + type: object + description: Resource relationships + _links: + type: object + required: + - self + description: Links related to the resource + properties: + self: + type: string + description: Link for refetching the curent results + _pagination: + type: object + description: Pagination information + required: + - first + - last + - prev + - next + properties: + first: + oneOf: + - type: 'null' + - type: string + description: Link to the first page + last: + oneOf: + - type: 'null' + - type: string + description: Link to the last page + prev: + oneOf: + - type: 'null' + - type: string + description: Link to the previous page + next: + oneOf: + - type: 'null' + - type: string + description: Link to the next page + _errors: + type: array + description: An array of error objects + items: + type: object + required: + - status + - code + properties: + status: + type: string + description: HTTP status + code: + type: string + description: Error code + prismaCode: + type: string + description: Prisma error code if the error is thrown by Prisma + title: + type: string + description: Error title + detail: + type: string + description: Error detail + reason: + type: string + description: Detailed error reason + zodErrors: + type: object + additionalProperties: true + description: Zod validation errors if the error is due to data validation + failure + _errorResponse: + type: object + required: + - errors + description: An error response + properties: + jsonapi: + $ref: '#/components/schemas/_jsonapi' + errors: + $ref: '#/components/schemas/_errors' + Foo: + type: object + description: The "Foo" model + required: + - id + - type + - attributes + properties: + id: + type: string + type: + type: string + attributes: + type: object + required: + - string + - int + - bigInt + - date + - float + - decimal + - boolean + - bytes + - json + - plainJson + properties: + string: + type: string + int: + type: integer + bigInt: + type: integer + date: + type: string + format: date-time + float: + type: number + decimal: + oneOf: + - type: number + - type: string + boolean: + type: boolean + bytes: + type: string + format: byte + description: Base64 encoded byte array + json: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Meta' + plainJson: {} + FooCreateRequest: + type: object + description: Input for creating a "Foo" + required: + - data + properties: + data: + type: object + description: The "Foo" model + required: + - type + - attributes + properties: + type: + type: string + attributes: + type: object + required: + - string + - int + - bigInt + - date + - float + - decimal + - boolean + - bytes + - plainJson + properties: + string: + type: string + int: + type: integer + bigInt: + type: integer + date: + type: string + format: date-time + float: + type: number + decimal: + oneOf: + - type: number + - type: string + boolean: + type: boolean + bytes: + type: string + format: byte + description: Base64 encoded byte array + json: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Meta' + plainJson: {} + meta: + $ref: '#/components/schemas/_meta' + FooUpdateRequest: + type: object + description: Input for updating a "Foo" + required: + - data + properties: + data: + type: object + description: The "Foo" model + required: + - id + - type + - attributes + properties: + id: + type: string + type: + type: string + attributes: + type: object + properties: + string: + type: string + int: + type: integer + bigInt: + type: integer + date: + type: string + format: date-time + float: + type: number + decimal: + oneOf: + - type: number + - type: string + boolean: + type: boolean + bytes: + type: string + format: byte + description: Base64 encoded byte array + json: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Meta' + plainJson: {} + meta: + $ref: '#/components/schemas/_meta' + FooResponse: + type: object + description: Response for a "Foo" + required: + - data + properties: + jsonapi: + $ref: '#/components/schemas/_jsonapi' + data: + allOf: + - $ref: '#/components/schemas/Foo' + - type: object + properties: + relationships: + type: object + properties: &a1 {} + meta: + $ref: '#/components/schemas/_meta' + included: + type: array + items: + $ref: '#/components/schemas/_resource' + links: + $ref: '#/components/schemas/_links' + FooListResponse: + type: object + description: Response for a list of "Foo" + required: + - data + - links + properties: + jsonapi: + $ref: '#/components/schemas/_jsonapi' + data: + type: array + items: + allOf: + - $ref: '#/components/schemas/Foo' + - type: object + properties: + relationships: + type: object + properties: *a1 + meta: + $ref: '#/components/schemas/_meta' + included: + type: array + items: + $ref: '#/components/schemas/_resource' + links: + allOf: + - $ref: '#/components/schemas/_links' + - $ref: '#/components/schemas/_pagination' + Meta: + type: object + description: The "Meta" TypeDef + properties: + something: + type: string + parameters: + id: + name: id + in: path + description: The resource id + required: true + schema: + type: string + include: + name: include + in: query + description: Relationships to include + required: false + style: form + schema: + type: string + sort: + name: sort + in: query + description: Fields to sort by + required: false + style: form + schema: + type: string + page-offset: + name: page[offset] + in: query + description: Offset for pagination + required: false + style: form + schema: + type: integer + page-limit: + name: page[limit] + in: query + description: Limit for pagination + required: false + style: form + schema: + type: integer diff --git a/packages/server/test/openapi/baseline/rpc-3.1.0-omit.baseline.yaml b/packages/server/test/openapi/baseline/rpc-3.1.0-omit.baseline.yaml new file mode 100644 index 000000000..11369e7d0 --- /dev/null +++ b/packages/server/test/openapi/baseline/rpc-3.1.0-omit.baseline.yaml @@ -0,0 +1,3058 @@ +openapi: 3.1.0 +info: + title: ZenStack Generated API + version: 1.0.0 +tags: + - name: user + description: User operations + - name: profile + description: Profile operations + - name: post_Item + description: Post-related operations +components: + schemas: + _AnyObject: + type: object + additionalProperties: true + Role: + type: string + enum: + - USER + - ADMIN + User: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + email: + type: string + role: + $ref: '#/components/schemas/Role' + posts: + type: array + items: + $ref: '#/components/schemas/Post_Item' + profile: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Profile' + required: + - id + - createdAt + - updatedAt + - email + - role + Profile: + type: object + properties: + id: + type: string + image: + oneOf: + - type: 'null' + - type: string + user: + $ref: '#/components/schemas/User' + userId: + type: string + required: + - id + - user + - userId + Post_Item: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + title: + type: string + author: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/User' + authorId: + oneOf: + - type: 'null' + - type: string + published: + type: boolean + viewCount: + type: integer + notes: + oneOf: + - type: 'null' + - type: string + required: + - id + - createdAt + - updatedAt + - title + - published + - viewCount + AggregateUser: + type: object + properties: + _count: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/UserCountAggregateOutputType' + _min: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/UserMinAggregateOutputType' + _max: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/UserMaxAggregateOutputType' + UserGroupByOutputType: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + email: + type: string + role: + $ref: '#/components/schemas/Role' + _count: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/UserCountAggregateOutputType' + _min: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/UserMinAggregateOutputType' + _max: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/UserMaxAggregateOutputType' + required: + - id + - createdAt + - updatedAt + - email + - role + AggregateProfile: + type: object + properties: + _count: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/ProfileCountAggregateOutputType' + _min: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/ProfileMinAggregateOutputType' + _max: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/ProfileMaxAggregateOutputType' + ProfileGroupByOutputType: + type: object + properties: + id: + type: string + image: + oneOf: + - type: 'null' + - type: string + userId: + type: string + _count: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/ProfileCountAggregateOutputType' + _min: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/ProfileMinAggregateOutputType' + _max: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/ProfileMaxAggregateOutputType' + required: + - id + - userId + AggregatePost_Item: + type: object + properties: + _count: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Post_ItemCountAggregateOutputType' + _avg: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Post_ItemAvgAggregateOutputType' + _sum: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Post_ItemSumAggregateOutputType' + _min: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Post_ItemMinAggregateOutputType' + _max: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Post_ItemMaxAggregateOutputType' + Post_ItemGroupByOutputType: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + title: + type: string + authorId: + oneOf: + - type: 'null' + - type: string + published: + type: boolean + viewCount: + type: integer + notes: + oneOf: + - type: 'null' + - type: string + _count: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Post_ItemCountAggregateOutputType' + _avg: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Post_ItemAvgAggregateOutputType' + _sum: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Post_ItemSumAggregateOutputType' + _min: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Post_ItemMinAggregateOutputType' + _max: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Post_ItemMaxAggregateOutputType' + required: + - id + - createdAt + - updatedAt + - title + - published + - viewCount + UserCountAggregateOutputType: + type: object + properties: + id: + type: integer + createdAt: + type: integer + updatedAt: + type: integer + email: + type: integer + role: + type: integer + _all: + type: integer + required: + - id + - createdAt + - updatedAt + - email + - role + - _all + UserMinAggregateOutputType: + type: object + properties: + id: + oneOf: + - type: 'null' + - type: string + createdAt: + oneOf: + - type: 'null' + - type: string + format: date-time + updatedAt: + oneOf: + - type: 'null' + - type: string + format: date-time + email: + oneOf: + - type: 'null' + - type: string + role: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Role' + UserMaxAggregateOutputType: + type: object + properties: + id: + oneOf: + - type: 'null' + - type: string + createdAt: + oneOf: + - type: 'null' + - type: string + format: date-time + updatedAt: + oneOf: + - type: 'null' + - type: string + format: date-time + email: + oneOf: + - type: 'null' + - type: string + role: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Role' + ProfileCountAggregateOutputType: + type: object + properties: + id: + type: integer + image: + type: integer + userId: + type: integer + _all: + type: integer + required: + - id + - image + - userId + - _all + ProfileMinAggregateOutputType: + type: object + properties: + id: + oneOf: + - type: 'null' + - type: string + image: + oneOf: + - type: 'null' + - type: string + userId: + oneOf: + - type: 'null' + - type: string + ProfileMaxAggregateOutputType: + type: object + properties: + id: + oneOf: + - type: 'null' + - type: string + image: + oneOf: + - type: 'null' + - type: string + userId: + oneOf: + - type: 'null' + - type: string + Post_ItemCountAggregateOutputType: + type: object + properties: + id: + type: integer + createdAt: + type: integer + updatedAt: + type: integer + title: + type: integer + authorId: + type: integer + published: + type: integer + viewCount: + type: integer + notes: + type: integer + _all: + type: integer + required: + - id + - createdAt + - updatedAt + - title + - authorId + - published + - viewCount + - notes + - _all + Post_ItemAvgAggregateOutputType: + type: object + properties: + viewCount: + oneOf: + - type: 'null' + - type: number + Post_ItemSumAggregateOutputType: + type: object + properties: + viewCount: + oneOf: + - type: 'null' + - type: integer + Post_ItemMinAggregateOutputType: + type: object + properties: + id: + oneOf: + - type: 'null' + - type: string + createdAt: + oneOf: + - type: 'null' + - type: string + format: date-time + updatedAt: + oneOf: + - type: 'null' + - type: string + format: date-time + title: + oneOf: + - type: 'null' + - type: string + authorId: + oneOf: + - type: 'null' + - type: string + published: + oneOf: + - type: 'null' + - type: boolean + viewCount: + oneOf: + - type: 'null' + - type: integer + notes: + oneOf: + - type: 'null' + - type: string + Post_ItemMaxAggregateOutputType: + type: object + properties: + id: + oneOf: + - type: 'null' + - type: string + createdAt: + oneOf: + - type: 'null' + - type: string + format: date-time + updatedAt: + oneOf: + - type: 'null' + - type: string + format: date-time + title: + oneOf: + - type: 'null' + - type: string + authorId: + oneOf: + - type: 'null' + - type: string + published: + oneOf: + - type: 'null' + - type: boolean + viewCount: + oneOf: + - type: 'null' + - type: integer + notes: + oneOf: + - type: 'null' + - type: string + _Meta: + type: object + description: Meta information about the request or response + properties: + serialization: + description: Serialization metadata + additionalProperties: true + _Error: + type: object + required: + - error + properties: + error: + type: object + required: + - message + properties: + prisma: + type: boolean + description: Indicates if the error occurred during a Prisma call + rejectedByPolicy: + type: boolean + description: Indicates if the error was due to rejection by a policy + code: + type: string + description: Prisma error code. Only available when "prisma" field is true. + message: + type: string + description: Error message + reason: + type: string + description: Detailed error reason + zodErrors: + type: object + additionalProperties: true + description: Zod validation errors if the error is due to data validation + failure + additionalProperties: true + BatchPayload: + type: object + properties: + count: + type: integer + UserCreateArgs: + type: object + required: + - data + properties: + select: + $ref: '#/components/schemas/_AnyObject' + include: + $ref: '#/components/schemas/_AnyObject' + data: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + UserCreateManyArgs: + type: object + required: + - data + properties: + data: + oneOf: + - $ref: '#/components/schemas/_AnyObject' + - type: array + items: + $ref: '#/components/schemas/_AnyObject' + skipDuplicates: + type: boolean + description: Do not insert records with unique fields or ID fields that already + exist. + meta: + $ref: '#/components/schemas/_Meta' + UserFindUniqueArgs: + type: object + required: + - where + properties: + select: + $ref: '#/components/schemas/_AnyObject' + include: + $ref: '#/components/schemas/_AnyObject' + where: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + UserFindFirstArgs: + type: object + properties: + select: + $ref: '#/components/schemas/_AnyObject' + include: + $ref: '#/components/schemas/_AnyObject' + where: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + UserFindManyArgs: + type: object + properties: + select: + $ref: '#/components/schemas/_AnyObject' + include: + $ref: '#/components/schemas/_AnyObject' + where: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + orderBy: + oneOf: + - $ref: '#/components/schemas/_AnyObject' + - type: array + items: + $ref: '#/components/schemas/_AnyObject' + cursor: + $ref: '#/components/schemas/_AnyObject' + take: + type: integer + skip: + type: integer + UserUpdateArgs: + type: object + required: + - where + - data + properties: + select: + $ref: '#/components/schemas/_AnyObject' + include: + $ref: '#/components/schemas/_AnyObject' + where: + $ref: '#/components/schemas/_AnyObject' + data: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + UserUpdateManyArgs: + type: object + required: + - data + properties: + where: + $ref: '#/components/schemas/_AnyObject' + data: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + UserUpsertArgs: + type: object + required: + - create + - update + - where + properties: + select: + $ref: '#/components/schemas/_AnyObject' + include: + $ref: '#/components/schemas/_AnyObject' + where: + $ref: '#/components/schemas/_AnyObject' + create: + $ref: '#/components/schemas/_AnyObject' + update: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + UserDeleteUniqueArgs: + type: object + required: + - where + properties: + select: + $ref: '#/components/schemas/_AnyObject' + include: + $ref: '#/components/schemas/_AnyObject' + where: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + UserDeleteManyArgs: + type: object + properties: + where: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + UserCountArgs: + type: object + properties: + select: + $ref: '#/components/schemas/_AnyObject' + where: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + UserAggregateArgs: + type: object + properties: + where: + $ref: '#/components/schemas/_AnyObject' + orderBy: + $ref: '#/components/schemas/_AnyObject' + cursor: + $ref: '#/components/schemas/_AnyObject' + take: + type: integer + skip: + type: integer + _count: + oneOf: + - type: boolean + - $ref: '#/components/schemas/_AnyObject' + _min: + $ref: '#/components/schemas/_AnyObject' + _max: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + UserGroupByArgs: + type: object + properties: + where: + $ref: '#/components/schemas/_AnyObject' + orderBy: + $ref: '#/components/schemas/_AnyObject' + by: + $ref: '#/components/schemas/_AnyObject' + having: + $ref: '#/components/schemas/_AnyObject' + take: + type: integer + skip: + type: integer + _count: + oneOf: + - type: boolean + - $ref: '#/components/schemas/_AnyObject' + _min: + $ref: '#/components/schemas/_AnyObject' + _max: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + ProfileCreateArgs: + type: object + required: + - data + properties: + select: + $ref: '#/components/schemas/_AnyObject' + include: + $ref: '#/components/schemas/_AnyObject' + data: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + ProfileCreateManyArgs: + type: object + required: + - data + properties: + data: + oneOf: + - $ref: '#/components/schemas/_AnyObject' + - type: array + items: + $ref: '#/components/schemas/_AnyObject' + skipDuplicates: + type: boolean + description: Do not insert records with unique fields or ID fields that already + exist. + meta: + $ref: '#/components/schemas/_Meta' + ProfileFindUniqueArgs: + type: object + required: + - where + properties: + select: + $ref: '#/components/schemas/_AnyObject' + include: + $ref: '#/components/schemas/_AnyObject' + where: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + ProfileFindFirstArgs: + type: object + properties: + select: + $ref: '#/components/schemas/_AnyObject' + include: + $ref: '#/components/schemas/_AnyObject' + where: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + ProfileFindManyArgs: + type: object + properties: + select: + $ref: '#/components/schemas/_AnyObject' + include: + $ref: '#/components/schemas/_AnyObject' + where: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + orderBy: + oneOf: + - $ref: '#/components/schemas/_AnyObject' + - type: array + items: + $ref: '#/components/schemas/_AnyObject' + cursor: + $ref: '#/components/schemas/_AnyObject' + take: + type: integer + skip: + type: integer + ProfileUpdateArgs: + type: object + required: + - where + - data + properties: + select: + $ref: '#/components/schemas/_AnyObject' + include: + $ref: '#/components/schemas/_AnyObject' + where: + $ref: '#/components/schemas/_AnyObject' + data: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + ProfileUpdateManyArgs: + type: object + required: + - data + properties: + where: + $ref: '#/components/schemas/_AnyObject' + data: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + ProfileUpsertArgs: + type: object + required: + - create + - update + - where + properties: + select: + $ref: '#/components/schemas/_AnyObject' + include: + $ref: '#/components/schemas/_AnyObject' + where: + $ref: '#/components/schemas/_AnyObject' + create: + $ref: '#/components/schemas/_AnyObject' + update: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + ProfileDeleteUniqueArgs: + type: object + required: + - where + properties: + select: + $ref: '#/components/schemas/_AnyObject' + include: + $ref: '#/components/schemas/_AnyObject' + where: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + ProfileDeleteManyArgs: + type: object + properties: + where: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + ProfileCountArgs: + type: object + properties: + select: + $ref: '#/components/schemas/_AnyObject' + where: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + ProfileAggregateArgs: + type: object + properties: + where: + $ref: '#/components/schemas/_AnyObject' + orderBy: + $ref: '#/components/schemas/_AnyObject' + cursor: + $ref: '#/components/schemas/_AnyObject' + take: + type: integer + skip: + type: integer + _count: + oneOf: + - type: boolean + - $ref: '#/components/schemas/_AnyObject' + _min: + $ref: '#/components/schemas/_AnyObject' + _max: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + ProfileGroupByArgs: + type: object + properties: + where: + $ref: '#/components/schemas/_AnyObject' + orderBy: + $ref: '#/components/schemas/_AnyObject' + by: + $ref: '#/components/schemas/_AnyObject' + having: + $ref: '#/components/schemas/_AnyObject' + take: + type: integer + skip: + type: integer + _count: + oneOf: + - type: boolean + - $ref: '#/components/schemas/_AnyObject' + _min: + $ref: '#/components/schemas/_AnyObject' + _max: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemCreateArgs: + type: object + required: + - data + properties: + select: + $ref: '#/components/schemas/_AnyObject' + include: + $ref: '#/components/schemas/_AnyObject' + data: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemCreateManyArgs: + type: object + required: + - data + properties: + data: + oneOf: + - $ref: '#/components/schemas/_AnyObject' + - type: array + items: + $ref: '#/components/schemas/_AnyObject' + skipDuplicates: + type: boolean + description: Do not insert records with unique fields or ID fields that already + exist. + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemFindUniqueArgs: + type: object + required: + - where + properties: + select: + $ref: '#/components/schemas/_AnyObject' + include: + $ref: '#/components/schemas/_AnyObject' + where: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemFindFirstArgs: + type: object + properties: + select: + $ref: '#/components/schemas/_AnyObject' + include: + $ref: '#/components/schemas/_AnyObject' + where: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemUpdateArgs: + type: object + required: + - where + - data + properties: + select: + $ref: '#/components/schemas/_AnyObject' + include: + $ref: '#/components/schemas/_AnyObject' + where: + $ref: '#/components/schemas/_AnyObject' + data: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemUpdateManyArgs: + type: object + required: + - data + properties: + where: + $ref: '#/components/schemas/_AnyObject' + data: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemUpsertArgs: + type: object + required: + - create + - update + - where + properties: + select: + $ref: '#/components/schemas/_AnyObject' + include: + $ref: '#/components/schemas/_AnyObject' + where: + $ref: '#/components/schemas/_AnyObject' + create: + $ref: '#/components/schemas/_AnyObject' + update: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemDeleteUniqueArgs: + type: object + required: + - where + properties: + select: + $ref: '#/components/schemas/_AnyObject' + include: + $ref: '#/components/schemas/_AnyObject' + where: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemDeleteManyArgs: + type: object + properties: + where: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemCountArgs: + type: object + properties: + select: + $ref: '#/components/schemas/_AnyObject' + where: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemAggregateArgs: + type: object + properties: + where: + $ref: '#/components/schemas/_AnyObject' + orderBy: + $ref: '#/components/schemas/_AnyObject' + cursor: + $ref: '#/components/schemas/_AnyObject' + take: + type: integer + skip: + type: integer + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemGroupByArgs: + type: object + properties: + where: + $ref: '#/components/schemas/_AnyObject' + orderBy: + $ref: '#/components/schemas/_AnyObject' + by: + $ref: '#/components/schemas/_AnyObject' + having: + $ref: '#/components/schemas/_AnyObject' + take: + type: integer + skip: + type: integer + meta: + $ref: '#/components/schemas/_Meta' +paths: + /user/create: + post: + operationId: createUser + description: Create a new User + tags: + - user + responses: + '201': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/User' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UserCreateArgs' + /user/createMany: + post: + operationId: createManyUser + description: Create several User + tags: + - user + responses: + '201': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BatchPayload' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UserCreateManyArgs' + /user/findUnique: + get: + operationId: findUniqueUser + description: Find one unique User + tags: + - user + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/User' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/UserFindUniqueArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /user/findFirst: + get: + operationId: findFirstUser + description: Find the first User matching the given condition + tags: + - user + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/User' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/UserFindFirstArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /user/findMany: + get: + operationId: findManyUser + description: Find users matching the given conditions + tags: + - user + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + type: array + items: + $ref: '#/components/schemas/User' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/UserFindManyArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /user/update: + patch: + operationId: updateUser + description: Update a User + tags: + - user + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/User' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UserUpdateArgs' + /user/updateMany: + patch: + operationId: updateManyUser + description: Update Users matching the given condition + tags: + - user + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BatchPayload' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UserUpdateManyArgs' + /user/upsert: + post: + operationId: upsertUser + description: Upsert a User + tags: + - user + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/User' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UserUpsertArgs' + /user/dodelete: + put: + operationId: deleteUser + description: Delete a unique user + tags: + - delete + - user + summary: Delete a user yeah yeah + deprecated: true + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/User' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UserDeleteUniqueArgs' + /user/deleteMany: + delete: + operationId: deleteManyUser + description: Delete Users matching the given condition + tags: + - user + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BatchPayload' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/UserDeleteManyArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /user/count: + get: + operationId: countUser + description: Find a list of User + tags: + - user + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + oneOf: + - type: integer + - $ref: '#/components/schemas/UserCountAggregateOutputType' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/UserCountArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /user/aggregate: + get: + operationId: aggregateUser + description: Aggregate Users + tags: + - user + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/AggregateUser' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/UserAggregateArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /user/groupBy: + get: + operationId: groupByUser + description: Group Users by fields + tags: + - user + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + type: array + items: + $ref: '#/components/schemas/UserGroupByOutputType' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/UserGroupByArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /profile/create: + post: + operationId: createProfile + description: Create a new Profile + tags: + - profile + responses: + '201': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Profile' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileCreateArgs' + /profile/createMany: + post: + operationId: createManyProfile + description: Create several Profile + tags: + - profile + responses: + '201': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BatchPayload' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileCreateManyArgs' + /profile/findUnique: + get: + operationId: findUniqueProfile + description: Find one unique Profile + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Profile' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileFindUniqueArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /profile/findFirst: + get: + operationId: findFirstProfile + description: Find the first Profile matching the given condition + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Profile' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileFindFirstArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /profile/findMany: + get: + operationId: findManyProfile + description: Find a list of Profile + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + type: array + items: + $ref: '#/components/schemas/Profile' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileFindManyArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /profile/update: + patch: + operationId: updateProfile + description: Update a Profile + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Profile' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileUpdateArgs' + /profile/updateMany: + patch: + operationId: updateManyProfile + description: Update Profiles matching the given condition + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BatchPayload' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileUpdateManyArgs' + /profile/upsert: + post: + operationId: upsertProfile + description: Upsert a Profile + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Profile' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileUpsertArgs' + /profile/delete: + delete: + operationId: deleteProfile + description: Delete one unique Profile + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Profile' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileDeleteUniqueArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /profile/deleteMany: + delete: + operationId: deleteManyProfile + description: Delete Profiles matching the given condition + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BatchPayload' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileDeleteManyArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /profile/count: + get: + operationId: countProfile + description: Find a list of Profile + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + oneOf: + - type: integer + - $ref: '#/components/schemas/ProfileCountAggregateOutputType' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileCountArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /profile/aggregate: + get: + operationId: aggregateProfile + description: Aggregate Profiles + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/AggregateProfile' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileAggregateArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /profile/groupBy: + get: + operationId: groupByProfile + description: Group Profiles by fields + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + type: array + items: + $ref: '#/components/schemas/ProfileGroupByOutputType' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileGroupByArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /post_Item/create: + post: + operationId: createPost_Item + description: Create a new Post_Item + tags: + - post_Item + responses: + '201': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Post_Item' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemCreateArgs' + /post_Item/createMany: + post: + operationId: createManyPost_Item + description: Create several Post_Item + tags: + - post_Item + responses: + '201': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BatchPayload' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemCreateManyArgs' + /post_Item/findUnique: + get: + operationId: findUniquePost_Item + description: Find one unique Post_Item + tags: + - post_Item + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Post_Item' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemFindUniqueArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /post_Item/findFirst: + get: + operationId: findFirstPost_Item + description: Find the first Post_Item matching the given condition + tags: + - post_Item + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Post_Item' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemFindFirstArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /post_Item/update: + patch: + operationId: updatePost_Item + description: Update a Post_Item + tags: + - post_Item + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Post_Item' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemUpdateArgs' + /post_Item/updateMany: + patch: + operationId: updateManyPost_Item + description: Update Post_Items matching the given condition + tags: + - post_Item + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BatchPayload' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemUpdateManyArgs' + /post_Item/upsert: + post: + operationId: upsertPost_Item + description: Upsert a Post_Item + tags: + - post_Item + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Post_Item' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemUpsertArgs' + /post_Item/delete: + delete: + operationId: deletePost_Item + description: Delete one unique Post_Item + tags: + - post_Item + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Post_Item' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemDeleteUniqueArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /post_Item/deleteMany: + delete: + operationId: deleteManyPost_Item + description: Delete Post_Items matching the given condition + tags: + - post_Item + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BatchPayload' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemDeleteManyArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /post_Item/count: + get: + operationId: countPost_Item + description: Find a list of Post_Item + tags: + - post_Item + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + oneOf: + - type: integer + - $ref: '#/components/schemas/Post_ItemCountAggregateOutputType' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemCountArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /post_Item/aggregate: + get: + operationId: aggregatePost_Item + description: Aggregate Post_Items + tags: + - post_Item + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/AggregatePost_Item' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemAggregateArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /post_Item/groupBy: + get: + operationId: groupByPost_Item + description: Group Post_Items by fields + tags: + - post_Item + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + type: array + items: + $ref: '#/components/schemas/Post_ItemGroupByOutputType' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemGroupByArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} diff --git a/packages/server/test/openapi/baseline/rpc-3.1.0.baseline.yaml b/packages/server/test/openapi/baseline/rpc-3.1.0.baseline.yaml new file mode 100644 index 000000000..5c5103e09 --- /dev/null +++ b/packages/server/test/openapi/baseline/rpc-3.1.0.baseline.yaml @@ -0,0 +1,5853 @@ +openapi: 3.1.0 +info: + title: ZenStack Generated API + version: 1.0.0 +tags: + - name: user + description: User operations + - name: profile + description: Profile operations + - name: post_Item + description: Post-related operations +components: + schemas: + Role: + type: string + enum: + - USER + - ADMIN + UserScalarFieldEnum: + type: string + enum: + - id + - createdAt + - updatedAt + - email + - role + ProfileScalarFieldEnum: + type: string + enum: + - id + - image + - userId + Post_ItemScalarFieldEnum: + type: string + enum: + - id + - createdAt + - updatedAt + - title + - authorId + - published + - viewCount + - notes + SortOrder: + type: string + enum: + - asc + - desc + QueryMode: + type: string + enum: + - default + - insensitive + NullsOrder: + type: string + enum: + - first + - last + User: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + email: + type: string + role: + $ref: '#/components/schemas/Role' + posts: + type: array + items: + $ref: '#/components/schemas/Post_Item' + profile: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Profile' + required: + - id + - createdAt + - updatedAt + - email + - role + Profile: + type: object + properties: + id: + type: string + image: + oneOf: + - type: 'null' + - type: string + user: + $ref: '#/components/schemas/User' + userId: + type: string + required: + - id + - user + - userId + Post_Item: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + title: + type: string + author: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/User' + authorId: + oneOf: + - type: 'null' + - type: string + published: + type: boolean + viewCount: + type: integer + notes: + oneOf: + - type: 'null' + - type: string + required: + - id + - createdAt + - updatedAt + - title + - published + - viewCount + UserWhereInput: + type: object + properties: + AND: + oneOf: + - $ref: '#/components/schemas/UserWhereInput' + - type: array + items: + $ref: '#/components/schemas/UserWhereInput' + OR: + type: array + items: + $ref: '#/components/schemas/UserWhereInput' + NOT: + oneOf: + - $ref: '#/components/schemas/UserWhereInput' + - type: array + items: + $ref: '#/components/schemas/UserWhereInput' + id: + oneOf: + - $ref: '#/components/schemas/StringFilter' + - type: string + createdAt: + oneOf: + - $ref: '#/components/schemas/DateTimeFilter' + - type: string + format: date-time + updatedAt: + oneOf: + - $ref: '#/components/schemas/DateTimeFilter' + - type: string + format: date-time + email: + oneOf: + - $ref: '#/components/schemas/StringFilter' + - type: string + role: + oneOf: + - $ref: '#/components/schemas/EnumroleFilter' + - $ref: '#/components/schemas/Role' + posts: + $ref: '#/components/schemas/Post_ItemListRelationFilter' + profile: + oneOf: + - $ref: '#/components/schemas/ProfileNullableScalarRelationFilter' + - $ref: '#/components/schemas/ProfileWhereInput' + - type: 'null' + UserOrderByWithRelationInput: + type: object + properties: + id: + $ref: '#/components/schemas/SortOrder' + createdAt: + $ref: '#/components/schemas/SortOrder' + updatedAt: + $ref: '#/components/schemas/SortOrder' + email: + $ref: '#/components/schemas/SortOrder' + role: + $ref: '#/components/schemas/SortOrder' + posts: + $ref: '#/components/schemas/Post_ItemOrderByRelationAggregateInput' + profile: + $ref: '#/components/schemas/ProfileOrderByWithRelationInput' + UserWhereUniqueInput: + type: object + properties: + id: + type: string + email: + type: string + AND: + oneOf: + - $ref: '#/components/schemas/UserWhereInput' + - type: array + items: + $ref: '#/components/schemas/UserWhereInput' + OR: + type: array + items: + $ref: '#/components/schemas/UserWhereInput' + NOT: + oneOf: + - $ref: '#/components/schemas/UserWhereInput' + - type: array + items: + $ref: '#/components/schemas/UserWhereInput' + createdAt: + oneOf: + - $ref: '#/components/schemas/DateTimeFilter' + - type: string + format: date-time + updatedAt: + oneOf: + - $ref: '#/components/schemas/DateTimeFilter' + - type: string + format: date-time + role: + oneOf: + - $ref: '#/components/schemas/EnumroleFilter' + - $ref: '#/components/schemas/Role' + posts: + $ref: '#/components/schemas/Post_ItemListRelationFilter' + profile: + oneOf: + - $ref: '#/components/schemas/ProfileNullableScalarRelationFilter' + - $ref: '#/components/schemas/ProfileWhereInput' + - type: 'null' + UserScalarWhereWithAggregatesInput: + type: object + properties: + AND: + oneOf: + - $ref: '#/components/schemas/UserScalarWhereWithAggregatesInput' + - type: array + items: + $ref: '#/components/schemas/UserScalarWhereWithAggregatesInput' + OR: + type: array + items: + $ref: '#/components/schemas/UserScalarWhereWithAggregatesInput' + NOT: + oneOf: + - $ref: '#/components/schemas/UserScalarWhereWithAggregatesInput' + - type: array + items: + $ref: '#/components/schemas/UserScalarWhereWithAggregatesInput' + id: + oneOf: + - $ref: '#/components/schemas/StringWithAggregatesFilter' + - type: string + createdAt: + oneOf: + - $ref: '#/components/schemas/DateTimeWithAggregatesFilter' + - type: string + format: date-time + updatedAt: + oneOf: + - $ref: '#/components/schemas/DateTimeWithAggregatesFilter' + - type: string + format: date-time + email: + oneOf: + - $ref: '#/components/schemas/StringWithAggregatesFilter' + - type: string + role: + oneOf: + - $ref: '#/components/schemas/EnumroleWithAggregatesFilter' + - $ref: '#/components/schemas/Role' + ProfileWhereInput: + type: object + properties: + AND: + oneOf: + - $ref: '#/components/schemas/ProfileWhereInput' + - type: array + items: + $ref: '#/components/schemas/ProfileWhereInput' + OR: + type: array + items: + $ref: '#/components/schemas/ProfileWhereInput' + NOT: + oneOf: + - $ref: '#/components/schemas/ProfileWhereInput' + - type: array + items: + $ref: '#/components/schemas/ProfileWhereInput' + id: + oneOf: + - $ref: '#/components/schemas/StringFilter' + - type: string + image: + oneOf: + - $ref: '#/components/schemas/StringNullableFilter' + - type: string + - type: 'null' + userId: + oneOf: + - $ref: '#/components/schemas/StringFilter' + - type: string + user: + oneOf: + - $ref: '#/components/schemas/UserScalarRelationFilter' + - $ref: '#/components/schemas/UserWhereInput' + ProfileOrderByWithRelationInput: + type: object + properties: + id: + $ref: '#/components/schemas/SortOrder' + image: + oneOf: + - $ref: '#/components/schemas/SortOrder' + - $ref: '#/components/schemas/SortOrderInput' + userId: + $ref: '#/components/schemas/SortOrder' + user: + $ref: '#/components/schemas/UserOrderByWithRelationInput' + ProfileWhereUniqueInput: + type: object + properties: + id: + type: string + userId: + type: string + AND: + oneOf: + - $ref: '#/components/schemas/ProfileWhereInput' + - type: array + items: + $ref: '#/components/schemas/ProfileWhereInput' + OR: + type: array + items: + $ref: '#/components/schemas/ProfileWhereInput' + NOT: + oneOf: + - $ref: '#/components/schemas/ProfileWhereInput' + - type: array + items: + $ref: '#/components/schemas/ProfileWhereInput' + image: + oneOf: + - $ref: '#/components/schemas/StringNullableFilter' + - type: string + - type: 'null' + user: + oneOf: + - $ref: '#/components/schemas/UserScalarRelationFilter' + - $ref: '#/components/schemas/UserWhereInput' + ProfileScalarWhereWithAggregatesInput: + type: object + properties: + AND: + oneOf: + - $ref: '#/components/schemas/ProfileScalarWhereWithAggregatesInput' + - type: array + items: + $ref: '#/components/schemas/ProfileScalarWhereWithAggregatesInput' + OR: + type: array + items: + $ref: '#/components/schemas/ProfileScalarWhereWithAggregatesInput' + NOT: + oneOf: + - $ref: '#/components/schemas/ProfileScalarWhereWithAggregatesInput' + - type: array + items: + $ref: '#/components/schemas/ProfileScalarWhereWithAggregatesInput' + id: + oneOf: + - $ref: '#/components/schemas/StringWithAggregatesFilter' + - type: string + image: + oneOf: + - $ref: '#/components/schemas/StringNullableWithAggregatesFilter' + - type: string + - type: 'null' + userId: + oneOf: + - $ref: '#/components/schemas/StringWithAggregatesFilter' + - type: string + Post_ItemWhereInput: + type: object + properties: + AND: + oneOf: + - $ref: '#/components/schemas/Post_ItemWhereInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemWhereInput' + OR: + type: array + items: + $ref: '#/components/schemas/Post_ItemWhereInput' + NOT: + oneOf: + - $ref: '#/components/schemas/Post_ItemWhereInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemWhereInput' + id: + oneOf: + - $ref: '#/components/schemas/StringFilter' + - type: string + createdAt: + oneOf: + - $ref: '#/components/schemas/DateTimeFilter' + - type: string + format: date-time + updatedAt: + oneOf: + - $ref: '#/components/schemas/DateTimeFilter' + - type: string + format: date-time + title: + oneOf: + - $ref: '#/components/schemas/StringFilter' + - type: string + authorId: + oneOf: + - $ref: '#/components/schemas/StringNullableFilter' + - type: string + - type: 'null' + published: + oneOf: + - $ref: '#/components/schemas/BoolFilter' + - type: boolean + viewCount: + oneOf: + - $ref: '#/components/schemas/IntFilter' + - type: integer + notes: + oneOf: + - $ref: '#/components/schemas/StringNullableFilter' + - type: string + - type: 'null' + author: + oneOf: + - $ref: '#/components/schemas/UserNullableScalarRelationFilter' + - $ref: '#/components/schemas/UserWhereInput' + - type: 'null' + Post_ItemOrderByWithRelationInput: + type: object + properties: + id: + $ref: '#/components/schemas/SortOrder' + createdAt: + $ref: '#/components/schemas/SortOrder' + updatedAt: + $ref: '#/components/schemas/SortOrder' + title: + $ref: '#/components/schemas/SortOrder' + authorId: + oneOf: + - $ref: '#/components/schemas/SortOrder' + - $ref: '#/components/schemas/SortOrderInput' + published: + $ref: '#/components/schemas/SortOrder' + viewCount: + $ref: '#/components/schemas/SortOrder' + notes: + oneOf: + - $ref: '#/components/schemas/SortOrder' + - $ref: '#/components/schemas/SortOrderInput' + author: + $ref: '#/components/schemas/UserOrderByWithRelationInput' + Post_ItemWhereUniqueInput: + type: object + properties: + id: + type: string + AND: + oneOf: + - $ref: '#/components/schemas/Post_ItemWhereInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemWhereInput' + OR: + type: array + items: + $ref: '#/components/schemas/Post_ItemWhereInput' + NOT: + oneOf: + - $ref: '#/components/schemas/Post_ItemWhereInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemWhereInput' + createdAt: + oneOf: + - $ref: '#/components/schemas/DateTimeFilter' + - type: string + format: date-time + updatedAt: + oneOf: + - $ref: '#/components/schemas/DateTimeFilter' + - type: string + format: date-time + title: + oneOf: + - $ref: '#/components/schemas/StringFilter' + - type: string + authorId: + oneOf: + - $ref: '#/components/schemas/StringNullableFilter' + - type: string + - type: 'null' + published: + oneOf: + - $ref: '#/components/schemas/BoolFilter' + - type: boolean + viewCount: + oneOf: + - $ref: '#/components/schemas/IntFilter' + - type: integer + notes: + oneOf: + - $ref: '#/components/schemas/StringNullableFilter' + - type: string + - type: 'null' + author: + oneOf: + - $ref: '#/components/schemas/UserNullableScalarRelationFilter' + - $ref: '#/components/schemas/UserWhereInput' + - type: 'null' + Post_ItemScalarWhereWithAggregatesInput: + type: object + properties: + AND: + oneOf: + - $ref: '#/components/schemas/Post_ItemScalarWhereWithAggregatesInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemScalarWhereWithAggregatesInput' + OR: + type: array + items: + $ref: '#/components/schemas/Post_ItemScalarWhereWithAggregatesInput' + NOT: + oneOf: + - $ref: '#/components/schemas/Post_ItemScalarWhereWithAggregatesInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemScalarWhereWithAggregatesInput' + id: + oneOf: + - $ref: '#/components/schemas/StringWithAggregatesFilter' + - type: string + createdAt: + oneOf: + - $ref: '#/components/schemas/DateTimeWithAggregatesFilter' + - type: string + format: date-time + updatedAt: + oneOf: + - $ref: '#/components/schemas/DateTimeWithAggregatesFilter' + - type: string + format: date-time + title: + oneOf: + - $ref: '#/components/schemas/StringWithAggregatesFilter' + - type: string + authorId: + oneOf: + - $ref: '#/components/schemas/StringNullableWithAggregatesFilter' + - type: string + - type: 'null' + published: + oneOf: + - $ref: '#/components/schemas/BoolWithAggregatesFilter' + - type: boolean + viewCount: + oneOf: + - $ref: '#/components/schemas/IntWithAggregatesFilter' + - type: integer + notes: + oneOf: + - $ref: '#/components/schemas/StringNullableWithAggregatesFilter' + - type: string + - type: 'null' + UserCreateInput: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + email: + type: string + role: + $ref: '#/components/schemas/Role' + posts: + $ref: '#/components/schemas/Post_ItemCreateNestedManyWithoutAuthorInput' + profile: + $ref: '#/components/schemas/ProfileCreateNestedOneWithoutUserInput' + required: + - email + UserUpdateInput: + type: object + properties: + id: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + createdAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + updatedAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + email: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + role: + oneOf: + - $ref: '#/components/schemas/Role' + - $ref: '#/components/schemas/EnumroleFieldUpdateOperationsInput' + posts: + $ref: '#/components/schemas/Post_ItemUpdateManyWithoutAuthorNestedInput' + profile: + $ref: '#/components/schemas/ProfileUpdateOneWithoutUserNestedInput' + UserCreateManyInput: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + email: + type: string + role: + $ref: '#/components/schemas/Role' + required: + - email + UserUpdateManyMutationInput: + type: object + properties: + id: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + createdAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + updatedAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + email: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + role: + oneOf: + - $ref: '#/components/schemas/Role' + - $ref: '#/components/schemas/EnumroleFieldUpdateOperationsInput' + ProfileCreateInput: + type: object + properties: + id: + type: string + image: + oneOf: + - type: 'null' + - type: string + user: + $ref: '#/components/schemas/UserCreateNestedOneWithoutProfileInput' + required: + - user + ProfileUpdateInput: + type: object + properties: + id: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + image: + oneOf: + - type: string + - $ref: '#/components/schemas/NullableStringFieldUpdateOperationsInput' + - type: 'null' + user: + $ref: '#/components/schemas/UserUpdateOneRequiredWithoutProfileNestedInput' + ProfileCreateManyInput: + type: object + properties: + id: + type: string + image: + oneOf: + - type: 'null' + - type: string + userId: + type: string + required: + - userId + ProfileUpdateManyMutationInput: + type: object + properties: + id: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + image: + oneOf: + - type: string + - $ref: '#/components/schemas/NullableStringFieldUpdateOperationsInput' + - type: 'null' + Post_ItemCreateInput: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + title: + type: string + published: + type: boolean + viewCount: + type: integer + notes: + oneOf: + - type: 'null' + - type: string + author: + $ref: '#/components/schemas/UserCreateNestedOneWithoutPostsInput' + required: + - id + - title + Post_ItemUpdateInput: + type: object + properties: + id: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + createdAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + updatedAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + title: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + published: + oneOf: + - type: boolean + - $ref: '#/components/schemas/BoolFieldUpdateOperationsInput' + viewCount: + oneOf: + - type: integer + - $ref: '#/components/schemas/IntFieldUpdateOperationsInput' + notes: + oneOf: + - type: string + - $ref: '#/components/schemas/NullableStringFieldUpdateOperationsInput' + - type: 'null' + author: + $ref: '#/components/schemas/UserUpdateOneWithoutPostsNestedInput' + Post_ItemCreateManyInput: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + title: + type: string + authorId: + oneOf: + - type: 'null' + - type: string + published: + type: boolean + viewCount: + type: integer + notes: + oneOf: + - type: 'null' + - type: string + required: + - id + - title + Post_ItemUpdateManyMutationInput: + type: object + properties: + id: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + createdAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + updatedAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + title: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + published: + oneOf: + - type: boolean + - $ref: '#/components/schemas/BoolFieldUpdateOperationsInput' + viewCount: + oneOf: + - type: integer + - $ref: '#/components/schemas/IntFieldUpdateOperationsInput' + notes: + oneOf: + - type: string + - $ref: '#/components/schemas/NullableStringFieldUpdateOperationsInput' + - type: 'null' + StringFilter: + type: object + properties: + equals: + type: string + in: + type: array + items: + type: string + notIn: + type: array + items: + type: string + lt: + type: string + lte: + type: string + gt: + type: string + gte: + type: string + contains: + type: string + startsWith: + type: string + endsWith: + type: string + mode: + $ref: '#/components/schemas/QueryMode' + not: + oneOf: + - type: string + - $ref: '#/components/schemas/NestedStringFilter' + DateTimeFilter: + type: object + properties: + equals: + type: string + format: date-time + in: + type: array + items: + type: string + format: date-time + notIn: + type: array + items: + type: string + format: date-time + lt: + type: string + format: date-time + lte: + type: string + format: date-time + gt: + type: string + format: date-time + gte: + type: string + format: date-time + not: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/NestedDateTimeFilter' + EnumroleFilter: + type: object + properties: + equals: + $ref: '#/components/schemas/Role' + in: + type: array + items: + $ref: '#/components/schemas/Role' + notIn: + type: array + items: + $ref: '#/components/schemas/Role' + not: + oneOf: + - $ref: '#/components/schemas/Role' + - $ref: '#/components/schemas/NestedEnumroleFilter' + Post_ItemListRelationFilter: + type: object + properties: + every: + $ref: '#/components/schemas/Post_ItemWhereInput' + some: + $ref: '#/components/schemas/Post_ItemWhereInput' + none: + $ref: '#/components/schemas/Post_ItemWhereInput' + ProfileNullableScalarRelationFilter: + type: object + properties: + is: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/ProfileWhereInput' + isNot: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/ProfileWhereInput' + Post_ItemOrderByRelationAggregateInput: + type: object + properties: + _count: + $ref: '#/components/schemas/SortOrder' + StringWithAggregatesFilter: + type: object + properties: + equals: + type: string + in: + type: array + items: + type: string + notIn: + type: array + items: + type: string + lt: + type: string + lte: + type: string + gt: + type: string + gte: + type: string + contains: + type: string + startsWith: + type: string + endsWith: + type: string + mode: + $ref: '#/components/schemas/QueryMode' + not: + oneOf: + - type: string + - $ref: '#/components/schemas/NestedStringWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _min: + $ref: '#/components/schemas/NestedStringFilter' + _max: + $ref: '#/components/schemas/NestedStringFilter' + DateTimeWithAggregatesFilter: + type: object + properties: + equals: + type: string + format: date-time + in: + type: array + items: + type: string + format: date-time + notIn: + type: array + items: + type: string + format: date-time + lt: + type: string + format: date-time + lte: + type: string + format: date-time + gt: + type: string + format: date-time + gte: + type: string + format: date-time + not: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/NestedDateTimeWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _min: + $ref: '#/components/schemas/NestedDateTimeFilter' + _max: + $ref: '#/components/schemas/NestedDateTimeFilter' + EnumroleWithAggregatesFilter: + type: object + properties: + equals: + $ref: '#/components/schemas/Role' + in: + type: array + items: + $ref: '#/components/schemas/Role' + notIn: + type: array + items: + $ref: '#/components/schemas/Role' + not: + oneOf: + - $ref: '#/components/schemas/Role' + - $ref: '#/components/schemas/NestedEnumroleWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _min: + $ref: '#/components/schemas/NestedEnumroleFilter' + _max: + $ref: '#/components/schemas/NestedEnumroleFilter' + StringNullableFilter: + type: object + properties: + equals: + oneOf: + - type: 'null' + - type: string + in: + oneOf: + - type: 'null' + - type: array + items: + type: string + notIn: + oneOf: + - type: 'null' + - type: array + items: + type: string + lt: + type: string + lte: + type: string + gt: + type: string + gte: + type: string + contains: + type: string + startsWith: + type: string + endsWith: + type: string + mode: + $ref: '#/components/schemas/QueryMode' + not: + oneOf: + - type: string + - $ref: '#/components/schemas/NestedStringNullableFilter' + - type: 'null' + UserScalarRelationFilter: + type: object + properties: + is: + $ref: '#/components/schemas/UserWhereInput' + isNot: + $ref: '#/components/schemas/UserWhereInput' + SortOrderInput: + type: object + properties: + sort: + $ref: '#/components/schemas/SortOrder' + nulls: + $ref: '#/components/schemas/NullsOrder' + required: + - sort + StringNullableWithAggregatesFilter: + type: object + properties: + equals: + oneOf: + - type: 'null' + - type: string + in: + oneOf: + - type: 'null' + - type: array + items: + type: string + notIn: + oneOf: + - type: 'null' + - type: array + items: + type: string + lt: + type: string + lte: + type: string + gt: + type: string + gte: + type: string + contains: + type: string + startsWith: + type: string + endsWith: + type: string + mode: + $ref: '#/components/schemas/QueryMode' + not: + oneOf: + - type: string + - $ref: '#/components/schemas/NestedStringNullableWithAggregatesFilter' + - type: 'null' + _count: + $ref: '#/components/schemas/NestedIntNullableFilter' + _min: + $ref: '#/components/schemas/NestedStringNullableFilter' + _max: + $ref: '#/components/schemas/NestedStringNullableFilter' + BoolFilter: + type: object + properties: + equals: + type: boolean + not: + oneOf: + - type: boolean + - $ref: '#/components/schemas/NestedBoolFilter' + IntFilter: + type: object + properties: + equals: + type: integer + in: + type: array + items: + type: integer + notIn: + type: array + items: + type: integer + lt: + type: integer + lte: + type: integer + gt: + type: integer + gte: + type: integer + not: + oneOf: + - type: integer + - $ref: '#/components/schemas/NestedIntFilter' + UserNullableScalarRelationFilter: + type: object + properties: + is: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/UserWhereInput' + isNot: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/UserWhereInput' + BoolWithAggregatesFilter: + type: object + properties: + equals: + type: boolean + not: + oneOf: + - type: boolean + - $ref: '#/components/schemas/NestedBoolWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _min: + $ref: '#/components/schemas/NestedBoolFilter' + _max: + $ref: '#/components/schemas/NestedBoolFilter' + IntWithAggregatesFilter: + type: object + properties: + equals: + type: integer + in: + type: array + items: + type: integer + notIn: + type: array + items: + type: integer + lt: + type: integer + lte: + type: integer + gt: + type: integer + gte: + type: integer + not: + oneOf: + - type: integer + - $ref: '#/components/schemas/NestedIntWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _avg: + $ref: '#/components/schemas/NestedFloatFilter' + _sum: + $ref: '#/components/schemas/NestedIntFilter' + _min: + $ref: '#/components/schemas/NestedIntFilter' + _max: + $ref: '#/components/schemas/NestedIntFilter' + Post_ItemCreateNestedManyWithoutAuthorInput: + type: object + properties: + create: + oneOf: + - $ref: '#/components/schemas/Post_ItemCreateWithoutAuthorInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemCreateWithoutAuthorInput' + - $ref: '#/components/schemas/Post_ItemUncheckedCreateWithoutAuthorInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemUncheckedCreateWithoutAuthorInput' + connectOrCreate: + oneOf: + - $ref: '#/components/schemas/Post_ItemCreateOrConnectWithoutAuthorInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemCreateOrConnectWithoutAuthorInput' + createMany: + $ref: '#/components/schemas/Post_ItemCreateManyAuthorInputEnvelope' + connect: + oneOf: + - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + ProfileCreateNestedOneWithoutUserInput: + type: object + properties: + create: + oneOf: + - $ref: '#/components/schemas/ProfileCreateWithoutUserInput' + - $ref: '#/components/schemas/ProfileUncheckedCreateWithoutUserInput' + connectOrCreate: + $ref: '#/components/schemas/ProfileCreateOrConnectWithoutUserInput' + connect: + $ref: '#/components/schemas/ProfileWhereUniqueInput' + Post_ItemUncheckedCreateNestedManyWithoutAuthorInput: + type: object + properties: + create: + oneOf: + - $ref: '#/components/schemas/Post_ItemCreateWithoutAuthorInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemCreateWithoutAuthorInput' + - $ref: '#/components/schemas/Post_ItemUncheckedCreateWithoutAuthorInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemUncheckedCreateWithoutAuthorInput' + connectOrCreate: + oneOf: + - $ref: '#/components/schemas/Post_ItemCreateOrConnectWithoutAuthorInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemCreateOrConnectWithoutAuthorInput' + createMany: + $ref: '#/components/schemas/Post_ItemCreateManyAuthorInputEnvelope' + connect: + oneOf: + - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + ProfileUncheckedCreateNestedOneWithoutUserInput: + type: object + properties: + create: + oneOf: + - $ref: '#/components/schemas/ProfileCreateWithoutUserInput' + - $ref: '#/components/schemas/ProfileUncheckedCreateWithoutUserInput' + connectOrCreate: + $ref: '#/components/schemas/ProfileCreateOrConnectWithoutUserInput' + connect: + $ref: '#/components/schemas/ProfileWhereUniqueInput' + StringFieldUpdateOperationsInput: + type: object + properties: + set: + type: string + DateTimeFieldUpdateOperationsInput: + type: object + properties: + set: + type: string + format: date-time + EnumroleFieldUpdateOperationsInput: + type: object + properties: + set: + $ref: '#/components/schemas/Role' + Post_ItemUpdateManyWithoutAuthorNestedInput: + type: object + properties: + create: + oneOf: + - $ref: '#/components/schemas/Post_ItemCreateWithoutAuthorInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemCreateWithoutAuthorInput' + - $ref: '#/components/schemas/Post_ItemUncheckedCreateWithoutAuthorInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemUncheckedCreateWithoutAuthorInput' + connectOrCreate: + oneOf: + - $ref: '#/components/schemas/Post_ItemCreateOrConnectWithoutAuthorInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemCreateOrConnectWithoutAuthorInput' + upsert: + oneOf: + - $ref: '#/components/schemas/Post_ItemUpsertWithWhereUniqueWithoutAuthorInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemUpsertWithWhereUniqueWithoutAuthorInput' + createMany: + $ref: '#/components/schemas/Post_ItemCreateManyAuthorInputEnvelope' + set: + oneOf: + - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + disconnect: + oneOf: + - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + delete: + oneOf: + - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + connect: + oneOf: + - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + update: + oneOf: + - $ref: '#/components/schemas/Post_ItemUpdateWithWhereUniqueWithoutAuthorInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemUpdateWithWhereUniqueWithoutAuthorInput' + updateMany: + oneOf: + - $ref: '#/components/schemas/Post_ItemUpdateManyWithWhereWithoutAuthorInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemUpdateManyWithWhereWithoutAuthorInput' + deleteMany: + oneOf: + - $ref: '#/components/schemas/Post_ItemScalarWhereInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemScalarWhereInput' + ProfileUpdateOneWithoutUserNestedInput: + type: object + properties: + create: + oneOf: + - $ref: '#/components/schemas/ProfileCreateWithoutUserInput' + - $ref: '#/components/schemas/ProfileUncheckedCreateWithoutUserInput' + connectOrCreate: + $ref: '#/components/schemas/ProfileCreateOrConnectWithoutUserInput' + upsert: + $ref: '#/components/schemas/ProfileUpsertWithoutUserInput' + disconnect: + oneOf: + - type: boolean + - $ref: '#/components/schemas/ProfileWhereInput' + delete: + oneOf: + - type: boolean + - $ref: '#/components/schemas/ProfileWhereInput' + connect: + $ref: '#/components/schemas/ProfileWhereUniqueInput' + update: + oneOf: + - $ref: '#/components/schemas/ProfileUpdateToOneWithWhereWithoutUserInput' + - $ref: '#/components/schemas/ProfileUpdateWithoutUserInput' + - $ref: '#/components/schemas/ProfileUncheckedUpdateWithoutUserInput' + Post_ItemUncheckedUpdateManyWithoutAuthorNestedInput: + type: object + properties: + create: + oneOf: + - $ref: '#/components/schemas/Post_ItemCreateWithoutAuthorInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemCreateWithoutAuthorInput' + - $ref: '#/components/schemas/Post_ItemUncheckedCreateWithoutAuthorInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemUncheckedCreateWithoutAuthorInput' + connectOrCreate: + oneOf: + - $ref: '#/components/schemas/Post_ItemCreateOrConnectWithoutAuthorInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemCreateOrConnectWithoutAuthorInput' + upsert: + oneOf: + - $ref: '#/components/schemas/Post_ItemUpsertWithWhereUniqueWithoutAuthorInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemUpsertWithWhereUniqueWithoutAuthorInput' + createMany: + $ref: '#/components/schemas/Post_ItemCreateManyAuthorInputEnvelope' + set: + oneOf: + - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + disconnect: + oneOf: + - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + delete: + oneOf: + - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + connect: + oneOf: + - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + update: + oneOf: + - $ref: '#/components/schemas/Post_ItemUpdateWithWhereUniqueWithoutAuthorInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemUpdateWithWhereUniqueWithoutAuthorInput' + updateMany: + oneOf: + - $ref: '#/components/schemas/Post_ItemUpdateManyWithWhereWithoutAuthorInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemUpdateManyWithWhereWithoutAuthorInput' + deleteMany: + oneOf: + - $ref: '#/components/schemas/Post_ItemScalarWhereInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemScalarWhereInput' + ProfileUncheckedUpdateOneWithoutUserNestedInput: + type: object + properties: + create: + oneOf: + - $ref: '#/components/schemas/ProfileCreateWithoutUserInput' + - $ref: '#/components/schemas/ProfileUncheckedCreateWithoutUserInput' + connectOrCreate: + $ref: '#/components/schemas/ProfileCreateOrConnectWithoutUserInput' + upsert: + $ref: '#/components/schemas/ProfileUpsertWithoutUserInput' + disconnect: + oneOf: + - type: boolean + - $ref: '#/components/schemas/ProfileWhereInput' + delete: + oneOf: + - type: boolean + - $ref: '#/components/schemas/ProfileWhereInput' + connect: + $ref: '#/components/schemas/ProfileWhereUniqueInput' + update: + oneOf: + - $ref: '#/components/schemas/ProfileUpdateToOneWithWhereWithoutUserInput' + - $ref: '#/components/schemas/ProfileUpdateWithoutUserInput' + - $ref: '#/components/schemas/ProfileUncheckedUpdateWithoutUserInput' + UserCreateNestedOneWithoutProfileInput: + type: object + properties: + create: + oneOf: + - $ref: '#/components/schemas/UserCreateWithoutProfileInput' + - $ref: '#/components/schemas/UserUncheckedCreateWithoutProfileInput' + connectOrCreate: + $ref: '#/components/schemas/UserCreateOrConnectWithoutProfileInput' + connect: + $ref: '#/components/schemas/UserWhereUniqueInput' + NullableStringFieldUpdateOperationsInput: + type: object + properties: + set: + oneOf: + - type: 'null' + - type: string + UserUpdateOneRequiredWithoutProfileNestedInput: + type: object + properties: + create: + oneOf: + - $ref: '#/components/schemas/UserCreateWithoutProfileInput' + - $ref: '#/components/schemas/UserUncheckedCreateWithoutProfileInput' + connectOrCreate: + $ref: '#/components/schemas/UserCreateOrConnectWithoutProfileInput' + upsert: + $ref: '#/components/schemas/UserUpsertWithoutProfileInput' + connect: + $ref: '#/components/schemas/UserWhereUniqueInput' + update: + oneOf: + - $ref: '#/components/schemas/UserUpdateToOneWithWhereWithoutProfileInput' + - $ref: '#/components/schemas/UserUpdateWithoutProfileInput' + - $ref: '#/components/schemas/UserUncheckedUpdateWithoutProfileInput' + UserCreateNestedOneWithoutPostsInput: + type: object + properties: + create: + oneOf: + - $ref: '#/components/schemas/UserCreateWithoutPostsInput' + - $ref: '#/components/schemas/UserUncheckedCreateWithoutPostsInput' + connectOrCreate: + $ref: '#/components/schemas/UserCreateOrConnectWithoutPostsInput' + connect: + $ref: '#/components/schemas/UserWhereUniqueInput' + BoolFieldUpdateOperationsInput: + type: object + properties: + set: + type: boolean + IntFieldUpdateOperationsInput: + type: object + properties: + set: + type: integer + increment: + type: integer + decrement: + type: integer + multiply: + type: integer + divide: + type: integer + UserUpdateOneWithoutPostsNestedInput: + type: object + properties: + create: + oneOf: + - $ref: '#/components/schemas/UserCreateWithoutPostsInput' + - $ref: '#/components/schemas/UserUncheckedCreateWithoutPostsInput' + connectOrCreate: + $ref: '#/components/schemas/UserCreateOrConnectWithoutPostsInput' + upsert: + $ref: '#/components/schemas/UserUpsertWithoutPostsInput' + disconnect: + oneOf: + - type: boolean + - $ref: '#/components/schemas/UserWhereInput' + delete: + oneOf: + - type: boolean + - $ref: '#/components/schemas/UserWhereInput' + connect: + $ref: '#/components/schemas/UserWhereUniqueInput' + update: + oneOf: + - $ref: '#/components/schemas/UserUpdateToOneWithWhereWithoutPostsInput' + - $ref: '#/components/schemas/UserUpdateWithoutPostsInput' + - $ref: '#/components/schemas/UserUncheckedUpdateWithoutPostsInput' + NestedStringFilter: + type: object + properties: + equals: + type: string + in: + type: array + items: + type: string + notIn: + type: array + items: + type: string + lt: + type: string + lte: + type: string + gt: + type: string + gte: + type: string + contains: + type: string + startsWith: + type: string + endsWith: + type: string + not: + oneOf: + - type: string + - $ref: '#/components/schemas/NestedStringFilter' + NestedDateTimeFilter: + type: object + properties: + equals: + type: string + format: date-time + in: + type: array + items: + type: string + format: date-time + notIn: + type: array + items: + type: string + format: date-time + lt: + type: string + format: date-time + lte: + type: string + format: date-time + gt: + type: string + format: date-time + gte: + type: string + format: date-time + not: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/NestedDateTimeFilter' + NestedEnumroleFilter: + type: object + properties: + equals: + $ref: '#/components/schemas/Role' + in: + type: array + items: + $ref: '#/components/schemas/Role' + notIn: + type: array + items: + $ref: '#/components/schemas/Role' + not: + oneOf: + - $ref: '#/components/schemas/Role' + - $ref: '#/components/schemas/NestedEnumroleFilter' + NestedStringWithAggregatesFilter: + type: object + properties: + equals: + type: string + in: + type: array + items: + type: string + notIn: + type: array + items: + type: string + lt: + type: string + lte: + type: string + gt: + type: string + gte: + type: string + contains: + type: string + startsWith: + type: string + endsWith: + type: string + not: + oneOf: + - type: string + - $ref: '#/components/schemas/NestedStringWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _min: + $ref: '#/components/schemas/NestedStringFilter' + _max: + $ref: '#/components/schemas/NestedStringFilter' + NestedIntFilter: + type: object + properties: + equals: + type: integer + in: + type: array + items: + type: integer + notIn: + type: array + items: + type: integer + lt: + type: integer + lte: + type: integer + gt: + type: integer + gte: + type: integer + not: + oneOf: + - type: integer + - $ref: '#/components/schemas/NestedIntFilter' + NestedDateTimeWithAggregatesFilter: + type: object + properties: + equals: + type: string + format: date-time + in: + type: array + items: + type: string + format: date-time + notIn: + type: array + items: + type: string + format: date-time + lt: + type: string + format: date-time + lte: + type: string + format: date-time + gt: + type: string + format: date-time + gte: + type: string + format: date-time + not: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/NestedDateTimeWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _min: + $ref: '#/components/schemas/NestedDateTimeFilter' + _max: + $ref: '#/components/schemas/NestedDateTimeFilter' + NestedEnumroleWithAggregatesFilter: + type: object + properties: + equals: + $ref: '#/components/schemas/Role' + in: + type: array + items: + $ref: '#/components/schemas/Role' + notIn: + type: array + items: + $ref: '#/components/schemas/Role' + not: + oneOf: + - $ref: '#/components/schemas/Role' + - $ref: '#/components/schemas/NestedEnumroleWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _min: + $ref: '#/components/schemas/NestedEnumroleFilter' + _max: + $ref: '#/components/schemas/NestedEnumroleFilter' + NestedStringNullableFilter: + type: object + properties: + equals: + oneOf: + - type: 'null' + - type: string + in: + oneOf: + - type: 'null' + - type: array + items: + type: string + notIn: + oneOf: + - type: 'null' + - type: array + items: + type: string + lt: + type: string + lte: + type: string + gt: + type: string + gte: + type: string + contains: + type: string + startsWith: + type: string + endsWith: + type: string + not: + oneOf: + - type: string + - $ref: '#/components/schemas/NestedStringNullableFilter' + - type: 'null' + NestedStringNullableWithAggregatesFilter: + type: object + properties: + equals: + oneOf: + - type: 'null' + - type: string + in: + oneOf: + - type: 'null' + - type: array + items: + type: string + notIn: + oneOf: + - type: 'null' + - type: array + items: + type: string + lt: + type: string + lte: + type: string + gt: + type: string + gte: + type: string + contains: + type: string + startsWith: + type: string + endsWith: + type: string + not: + oneOf: + - type: string + - $ref: '#/components/schemas/NestedStringNullableWithAggregatesFilter' + - type: 'null' + _count: + $ref: '#/components/schemas/NestedIntNullableFilter' + _min: + $ref: '#/components/schemas/NestedStringNullableFilter' + _max: + $ref: '#/components/schemas/NestedStringNullableFilter' + NestedIntNullableFilter: + type: object + properties: + equals: + oneOf: + - type: 'null' + - type: integer + in: + oneOf: + - type: 'null' + - type: array + items: + type: integer + notIn: + oneOf: + - type: 'null' + - type: array + items: + type: integer + lt: + type: integer + lte: + type: integer + gt: + type: integer + gte: + type: integer + not: + oneOf: + - type: integer + - $ref: '#/components/schemas/NestedIntNullableFilter' + - type: 'null' + NestedBoolFilter: + type: object + properties: + equals: + type: boolean + not: + oneOf: + - type: boolean + - $ref: '#/components/schemas/NestedBoolFilter' + NestedBoolWithAggregatesFilter: + type: object + properties: + equals: + type: boolean + not: + oneOf: + - type: boolean + - $ref: '#/components/schemas/NestedBoolWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _min: + $ref: '#/components/schemas/NestedBoolFilter' + _max: + $ref: '#/components/schemas/NestedBoolFilter' + NestedIntWithAggregatesFilter: + type: object + properties: + equals: + type: integer + in: + type: array + items: + type: integer + notIn: + type: array + items: + type: integer + lt: + type: integer + lte: + type: integer + gt: + type: integer + gte: + type: integer + not: + oneOf: + - type: integer + - $ref: '#/components/schemas/NestedIntWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _avg: + $ref: '#/components/schemas/NestedFloatFilter' + _sum: + $ref: '#/components/schemas/NestedIntFilter' + _min: + $ref: '#/components/schemas/NestedIntFilter' + _max: + $ref: '#/components/schemas/NestedIntFilter' + NestedFloatFilter: + type: object + properties: + equals: + type: number + in: + type: array + items: + type: number + notIn: + type: array + items: + type: number + lt: + type: number + lte: + type: number + gt: + type: number + gte: + type: number + not: + oneOf: + - type: number + - $ref: '#/components/schemas/NestedFloatFilter' + Post_ItemCreateWithoutAuthorInput: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + title: + type: string + published: + type: boolean + viewCount: + type: integer + notes: + oneOf: + - type: 'null' + - type: string + required: + - id + - title + Post_ItemUncheckedCreateWithoutAuthorInput: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + title: + type: string + published: + type: boolean + viewCount: + type: integer + notes: + oneOf: + - type: 'null' + - type: string + required: + - id + - title + Post_ItemCreateOrConnectWithoutAuthorInput: + type: object + properties: + where: + $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + create: + oneOf: + - $ref: '#/components/schemas/Post_ItemCreateWithoutAuthorInput' + - $ref: '#/components/schemas/Post_ItemUncheckedCreateWithoutAuthorInput' + required: + - where + - create + Post_ItemCreateManyAuthorInputEnvelope: + type: object + properties: + data: + oneOf: + - $ref: '#/components/schemas/Post_ItemCreateManyAuthorInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemCreateManyAuthorInput' + skipDuplicates: + type: boolean + required: + - data + ProfileCreateWithoutUserInput: + type: object + properties: + id: + type: string + image: + oneOf: + - type: 'null' + - type: string + ProfileUncheckedCreateWithoutUserInput: + type: object + properties: + id: + type: string + image: + oneOf: + - type: 'null' + - type: string + ProfileCreateOrConnectWithoutUserInput: + type: object + properties: + where: + $ref: '#/components/schemas/ProfileWhereUniqueInput' + create: + oneOf: + - $ref: '#/components/schemas/ProfileCreateWithoutUserInput' + - $ref: '#/components/schemas/ProfileUncheckedCreateWithoutUserInput' + required: + - where + - create + Post_ItemUpsertWithWhereUniqueWithoutAuthorInput: + type: object + properties: + where: + $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + update: + oneOf: + - $ref: '#/components/schemas/Post_ItemUpdateWithoutAuthorInput' + - $ref: '#/components/schemas/Post_ItemUncheckedUpdateWithoutAuthorInput' + create: + oneOf: + - $ref: '#/components/schemas/Post_ItemCreateWithoutAuthorInput' + - $ref: '#/components/schemas/Post_ItemUncheckedCreateWithoutAuthorInput' + required: + - where + - update + - create + Post_ItemUpdateWithWhereUniqueWithoutAuthorInput: + type: object + properties: + where: + $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + data: + oneOf: + - $ref: '#/components/schemas/Post_ItemUpdateWithoutAuthorInput' + - $ref: '#/components/schemas/Post_ItemUncheckedUpdateWithoutAuthorInput' + required: + - where + - data + Post_ItemUpdateManyWithWhereWithoutAuthorInput: + type: object + properties: + where: + $ref: '#/components/schemas/Post_ItemScalarWhereInput' + data: + oneOf: + - $ref: '#/components/schemas/Post_ItemUpdateManyMutationInput' + - $ref: '#/components/schemas/Post_ItemUncheckedUpdateManyWithoutAuthorInput' + required: + - where + - data + Post_ItemScalarWhereInput: + type: object + properties: + AND: + oneOf: + - $ref: '#/components/schemas/Post_ItemScalarWhereInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemScalarWhereInput' + OR: + type: array + items: + $ref: '#/components/schemas/Post_ItemScalarWhereInput' + NOT: + oneOf: + - $ref: '#/components/schemas/Post_ItemScalarWhereInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemScalarWhereInput' + id: + oneOf: + - $ref: '#/components/schemas/StringFilter' + - type: string + createdAt: + oneOf: + - $ref: '#/components/schemas/DateTimeFilter' + - type: string + format: date-time + updatedAt: + oneOf: + - $ref: '#/components/schemas/DateTimeFilter' + - type: string + format: date-time + title: + oneOf: + - $ref: '#/components/schemas/StringFilter' + - type: string + authorId: + oneOf: + - $ref: '#/components/schemas/StringNullableFilter' + - type: string + - type: 'null' + published: + oneOf: + - $ref: '#/components/schemas/BoolFilter' + - type: boolean + viewCount: + oneOf: + - $ref: '#/components/schemas/IntFilter' + - type: integer + notes: + oneOf: + - $ref: '#/components/schemas/StringNullableFilter' + - type: string + - type: 'null' + ProfileUpsertWithoutUserInput: + type: object + properties: + update: + oneOf: + - $ref: '#/components/schemas/ProfileUpdateWithoutUserInput' + - $ref: '#/components/schemas/ProfileUncheckedUpdateWithoutUserInput' + create: + oneOf: + - $ref: '#/components/schemas/ProfileCreateWithoutUserInput' + - $ref: '#/components/schemas/ProfileUncheckedCreateWithoutUserInput' + where: + $ref: '#/components/schemas/ProfileWhereInput' + required: + - update + - create + ProfileUpdateToOneWithWhereWithoutUserInput: + type: object + properties: + where: + $ref: '#/components/schemas/ProfileWhereInput' + data: + oneOf: + - $ref: '#/components/schemas/ProfileUpdateWithoutUserInput' + - $ref: '#/components/schemas/ProfileUncheckedUpdateWithoutUserInput' + required: + - data + ProfileUpdateWithoutUserInput: + type: object + properties: + id: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + image: + oneOf: + - type: string + - $ref: '#/components/schemas/NullableStringFieldUpdateOperationsInput' + - type: 'null' + ProfileUncheckedUpdateWithoutUserInput: + type: object + properties: + id: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + image: + oneOf: + - type: string + - $ref: '#/components/schemas/NullableStringFieldUpdateOperationsInput' + - type: 'null' + UserCreateWithoutProfileInput: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + email: + type: string + role: + $ref: '#/components/schemas/Role' + posts: + $ref: '#/components/schemas/Post_ItemCreateNestedManyWithoutAuthorInput' + required: + - email + UserUncheckedCreateWithoutProfileInput: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + email: + type: string + role: + $ref: '#/components/schemas/Role' + posts: + $ref: "#/components/schemas/Post_ItemUncheckedCreateNestedManyWithoutAuthorInpu\ + t" + required: + - email + UserCreateOrConnectWithoutProfileInput: + type: object + properties: + where: + $ref: '#/components/schemas/UserWhereUniqueInput' + create: + oneOf: + - $ref: '#/components/schemas/UserCreateWithoutProfileInput' + - $ref: '#/components/schemas/UserUncheckedCreateWithoutProfileInput' + required: + - where + - create + UserUpsertWithoutProfileInput: + type: object + properties: + update: + oneOf: + - $ref: '#/components/schemas/UserUpdateWithoutProfileInput' + - $ref: '#/components/schemas/UserUncheckedUpdateWithoutProfileInput' + create: + oneOf: + - $ref: '#/components/schemas/UserCreateWithoutProfileInput' + - $ref: '#/components/schemas/UserUncheckedCreateWithoutProfileInput' + where: + $ref: '#/components/schemas/UserWhereInput' + required: + - update + - create + UserUpdateToOneWithWhereWithoutProfileInput: + type: object + properties: + where: + $ref: '#/components/schemas/UserWhereInput' + data: + oneOf: + - $ref: '#/components/schemas/UserUpdateWithoutProfileInput' + - $ref: '#/components/schemas/UserUncheckedUpdateWithoutProfileInput' + required: + - data + UserUpdateWithoutProfileInput: + type: object + properties: + id: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + createdAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + updatedAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + email: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + role: + oneOf: + - $ref: '#/components/schemas/Role' + - $ref: '#/components/schemas/EnumroleFieldUpdateOperationsInput' + posts: + $ref: '#/components/schemas/Post_ItemUpdateManyWithoutAuthorNestedInput' + UserUncheckedUpdateWithoutProfileInput: + type: object + properties: + id: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + createdAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + updatedAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + email: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + role: + oneOf: + - $ref: '#/components/schemas/Role' + - $ref: '#/components/schemas/EnumroleFieldUpdateOperationsInput' + posts: + $ref: "#/components/schemas/Post_ItemUncheckedUpdateManyWithoutAuthorNestedInpu\ + t" + UserCreateWithoutPostsInput: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + email: + type: string + role: + $ref: '#/components/schemas/Role' + profile: + $ref: '#/components/schemas/ProfileCreateNestedOneWithoutUserInput' + required: + - email + UserUncheckedCreateWithoutPostsInput: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + email: + type: string + role: + $ref: '#/components/schemas/Role' + profile: + $ref: '#/components/schemas/ProfileUncheckedCreateNestedOneWithoutUserInput' + required: + - email + UserCreateOrConnectWithoutPostsInput: + type: object + properties: + where: + $ref: '#/components/schemas/UserWhereUniqueInput' + create: + oneOf: + - $ref: '#/components/schemas/UserCreateWithoutPostsInput' + - $ref: '#/components/schemas/UserUncheckedCreateWithoutPostsInput' + required: + - where + - create + UserUpsertWithoutPostsInput: + type: object + properties: + update: + oneOf: + - $ref: '#/components/schemas/UserUpdateWithoutPostsInput' + - $ref: '#/components/schemas/UserUncheckedUpdateWithoutPostsInput' + create: + oneOf: + - $ref: '#/components/schemas/UserCreateWithoutPostsInput' + - $ref: '#/components/schemas/UserUncheckedCreateWithoutPostsInput' + where: + $ref: '#/components/schemas/UserWhereInput' + required: + - update + - create + UserUpdateToOneWithWhereWithoutPostsInput: + type: object + properties: + where: + $ref: '#/components/schemas/UserWhereInput' + data: + oneOf: + - $ref: '#/components/schemas/UserUpdateWithoutPostsInput' + - $ref: '#/components/schemas/UserUncheckedUpdateWithoutPostsInput' + required: + - data + UserUpdateWithoutPostsInput: + type: object + properties: + id: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + createdAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + updatedAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + email: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + role: + oneOf: + - $ref: '#/components/schemas/Role' + - $ref: '#/components/schemas/EnumroleFieldUpdateOperationsInput' + profile: + $ref: '#/components/schemas/ProfileUpdateOneWithoutUserNestedInput' + UserUncheckedUpdateWithoutPostsInput: + type: object + properties: + id: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + createdAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + updatedAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + email: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + role: + oneOf: + - $ref: '#/components/schemas/Role' + - $ref: '#/components/schemas/EnumroleFieldUpdateOperationsInput' + profile: + $ref: '#/components/schemas/ProfileUncheckedUpdateOneWithoutUserNestedInput' + Post_ItemCreateManyAuthorInput: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + title: + type: string + published: + type: boolean + viewCount: + type: integer + notes: + oneOf: + - type: 'null' + - type: string + required: + - id + - title + Post_ItemUpdateWithoutAuthorInput: + type: object + properties: + id: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + createdAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + updatedAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + title: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + published: + oneOf: + - type: boolean + - $ref: '#/components/schemas/BoolFieldUpdateOperationsInput' + viewCount: + oneOf: + - type: integer + - $ref: '#/components/schemas/IntFieldUpdateOperationsInput' + notes: + oneOf: + - type: string + - $ref: '#/components/schemas/NullableStringFieldUpdateOperationsInput' + - type: 'null' + Post_ItemUncheckedUpdateWithoutAuthorInput: + type: object + properties: + id: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + createdAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + updatedAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + title: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + published: + oneOf: + - type: boolean + - $ref: '#/components/schemas/BoolFieldUpdateOperationsInput' + viewCount: + oneOf: + - type: integer + - $ref: '#/components/schemas/IntFieldUpdateOperationsInput' + notes: + oneOf: + - type: string + - $ref: '#/components/schemas/NullableStringFieldUpdateOperationsInput' + - type: 'null' + Post_ItemUncheckedUpdateManyWithoutAuthorInput: + type: object + properties: + id: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + createdAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + updatedAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + title: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + published: + oneOf: + - type: boolean + - $ref: '#/components/schemas/BoolFieldUpdateOperationsInput' + viewCount: + oneOf: + - type: integer + - $ref: '#/components/schemas/IntFieldUpdateOperationsInput' + notes: + oneOf: + - type: string + - $ref: '#/components/schemas/NullableStringFieldUpdateOperationsInput' + - type: 'null' + UserDefaultArgs: + type: object + properties: + select: + $ref: '#/components/schemas/UserSelect' + include: + $ref: '#/components/schemas/UserInclude' + ProfileDefaultArgs: + type: object + properties: + select: + $ref: '#/components/schemas/ProfileSelect' + include: + $ref: '#/components/schemas/ProfileInclude' + UserInclude: + type: object + properties: + posts: + oneOf: + - type: boolean + - $ref: '#/components/schemas/Post_ItemFindManyArgs' + profile: + oneOf: + - type: boolean + - $ref: '#/components/schemas/ProfileDefaultArgs' + _count: + oneOf: + - type: boolean + - $ref: '#/components/schemas/UserCountOutputTypeDefaultArgs' + ProfileInclude: + type: object + properties: + user: + oneOf: + - type: boolean + - $ref: '#/components/schemas/UserDefaultArgs' + Post_ItemInclude: + type: object + properties: + author: + oneOf: + - type: boolean + - $ref: '#/components/schemas/UserDefaultArgs' + UserCountOutputTypeSelect: + type: object + properties: + posts: + type: boolean + UserCountOutputTypeDefaultArgs: + type: object + properties: + select: + $ref: '#/components/schemas/UserCountOutputTypeSelect' + UserSelect: + type: object + properties: + id: + type: boolean + createdAt: + type: boolean + updatedAt: + type: boolean + email: + type: boolean + role: + type: boolean + posts: + oneOf: + - type: boolean + - $ref: '#/components/schemas/Post_ItemFindManyArgs' + profile: + oneOf: + - type: boolean + - $ref: '#/components/schemas/ProfileDefaultArgs' + _count: + oneOf: + - type: boolean + - $ref: '#/components/schemas/UserCountOutputTypeDefaultArgs' + ProfileSelect: + type: object + properties: + id: + type: boolean + image: + type: boolean + user: + oneOf: + - type: boolean + - $ref: '#/components/schemas/UserDefaultArgs' + userId: + type: boolean + Post_ItemSelect: + type: object + properties: + id: + type: boolean + createdAt: + type: boolean + updatedAt: + type: boolean + title: + type: boolean + author: + oneOf: + - type: boolean + - $ref: '#/components/schemas/UserDefaultArgs' + authorId: + type: boolean + published: + type: boolean + viewCount: + type: boolean + notes: + type: boolean + UserCountAggregateInput: + type: object + properties: + id: + type: boolean + createdAt: + type: boolean + updatedAt: + type: boolean + email: + type: boolean + role: + type: boolean + _all: + type: boolean + UserMinAggregateInput: + type: object + properties: + id: + type: boolean + createdAt: + type: boolean + updatedAt: + type: boolean + email: + type: boolean + role: + type: boolean + UserMaxAggregateInput: + type: object + properties: + id: + type: boolean + createdAt: + type: boolean + updatedAt: + type: boolean + email: + type: boolean + role: + type: boolean + ProfileCountAggregateInput: + type: object + properties: + id: + type: boolean + image: + type: boolean + userId: + type: boolean + _all: + type: boolean + ProfileMinAggregateInput: + type: object + properties: + id: + type: boolean + image: + type: boolean + userId: + type: boolean + ProfileMaxAggregateInput: + type: object + properties: + id: + type: boolean + image: + type: boolean + userId: + type: boolean + AggregateUser: + type: object + properties: + _count: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/UserCountAggregateOutputType' + _min: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/UserMinAggregateOutputType' + _max: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/UserMaxAggregateOutputType' + UserGroupByOutputType: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + email: + type: string + role: + $ref: '#/components/schemas/Role' + _count: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/UserCountAggregateOutputType' + _min: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/UserMinAggregateOutputType' + _max: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/UserMaxAggregateOutputType' + required: + - id + - createdAt + - updatedAt + - email + - role + AggregateProfile: + type: object + properties: + _count: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/ProfileCountAggregateOutputType' + _min: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/ProfileMinAggregateOutputType' + _max: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/ProfileMaxAggregateOutputType' + ProfileGroupByOutputType: + type: object + properties: + id: + type: string + image: + oneOf: + - type: 'null' + - type: string + userId: + type: string + _count: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/ProfileCountAggregateOutputType' + _min: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/ProfileMinAggregateOutputType' + _max: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/ProfileMaxAggregateOutputType' + required: + - id + - userId + AggregatePost_Item: + type: object + properties: + _count: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Post_ItemCountAggregateOutputType' + _avg: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Post_ItemAvgAggregateOutputType' + _sum: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Post_ItemSumAggregateOutputType' + _min: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Post_ItemMinAggregateOutputType' + _max: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Post_ItemMaxAggregateOutputType' + Post_ItemGroupByOutputType: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + title: + type: string + authorId: + oneOf: + - type: 'null' + - type: string + published: + type: boolean + viewCount: + type: integer + notes: + oneOf: + - type: 'null' + - type: string + _count: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Post_ItemCountAggregateOutputType' + _avg: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Post_ItemAvgAggregateOutputType' + _sum: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Post_ItemSumAggregateOutputType' + _min: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Post_ItemMinAggregateOutputType' + _max: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Post_ItemMaxAggregateOutputType' + required: + - id + - createdAt + - updatedAt + - title + - published + - viewCount + UserCountAggregateOutputType: + type: object + properties: + id: + type: integer + createdAt: + type: integer + updatedAt: + type: integer + email: + type: integer + role: + type: integer + _all: + type: integer + required: + - id + - createdAt + - updatedAt + - email + - role + - _all + UserMinAggregateOutputType: + type: object + properties: + id: + oneOf: + - type: 'null' + - type: string + createdAt: + oneOf: + - type: 'null' + - type: string + format: date-time + updatedAt: + oneOf: + - type: 'null' + - type: string + format: date-time + email: + oneOf: + - type: 'null' + - type: string + role: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Role' + UserMaxAggregateOutputType: + type: object + properties: + id: + oneOf: + - type: 'null' + - type: string + createdAt: + oneOf: + - type: 'null' + - type: string + format: date-time + updatedAt: + oneOf: + - type: 'null' + - type: string + format: date-time + email: + oneOf: + - type: 'null' + - type: string + role: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Role' + ProfileCountAggregateOutputType: + type: object + properties: + id: + type: integer + image: + type: integer + userId: + type: integer + _all: + type: integer + required: + - id + - image + - userId + - _all + ProfileMinAggregateOutputType: + type: object + properties: + id: + oneOf: + - type: 'null' + - type: string + image: + oneOf: + - type: 'null' + - type: string + userId: + oneOf: + - type: 'null' + - type: string + ProfileMaxAggregateOutputType: + type: object + properties: + id: + oneOf: + - type: 'null' + - type: string + image: + oneOf: + - type: 'null' + - type: string + userId: + oneOf: + - type: 'null' + - type: string + Post_ItemCountAggregateOutputType: + type: object + properties: + id: + type: integer + createdAt: + type: integer + updatedAt: + type: integer + title: + type: integer + authorId: + type: integer + published: + type: integer + viewCount: + type: integer + notes: + type: integer + _all: + type: integer + required: + - id + - createdAt + - updatedAt + - title + - authorId + - published + - viewCount + - notes + - _all + Post_ItemAvgAggregateOutputType: + type: object + properties: + viewCount: + oneOf: + - type: 'null' + - type: number + Post_ItemSumAggregateOutputType: + type: object + properties: + viewCount: + oneOf: + - type: 'null' + - type: integer + Post_ItemMinAggregateOutputType: + type: object + properties: + id: + oneOf: + - type: 'null' + - type: string + createdAt: + oneOf: + - type: 'null' + - type: string + format: date-time + updatedAt: + oneOf: + - type: 'null' + - type: string + format: date-time + title: + oneOf: + - type: 'null' + - type: string + authorId: + oneOf: + - type: 'null' + - type: string + published: + oneOf: + - type: 'null' + - type: boolean + viewCount: + oneOf: + - type: 'null' + - type: integer + notes: + oneOf: + - type: 'null' + - type: string + Post_ItemMaxAggregateOutputType: + type: object + properties: + id: + oneOf: + - type: 'null' + - type: string + createdAt: + oneOf: + - type: 'null' + - type: string + format: date-time + updatedAt: + oneOf: + - type: 'null' + - type: string + format: date-time + title: + oneOf: + - type: 'null' + - type: string + authorId: + oneOf: + - type: 'null' + - type: string + published: + oneOf: + - type: 'null' + - type: boolean + viewCount: + oneOf: + - type: 'null' + - type: integer + notes: + oneOf: + - type: 'null' + - type: string + _Meta: + type: object + description: Meta information about the request or response + properties: + serialization: + description: Serialization metadata + additionalProperties: true + _Error: + type: object + required: + - error + properties: + error: + type: object + required: + - message + properties: + prisma: + type: boolean + description: Indicates if the error occurred during a Prisma call + rejectedByPolicy: + type: boolean + description: Indicates if the error was due to rejection by a policy + code: + type: string + description: Prisma error code. Only available when "prisma" field is true. + message: + type: string + description: Error message + reason: + type: string + description: Detailed error reason + zodErrors: + type: object + additionalProperties: true + description: Zod validation errors if the error is due to data validation + failure + additionalProperties: true + BatchPayload: + type: object + properties: + count: + type: integer + UserCreateArgs: + type: object + required: + - data + properties: + select: + $ref: '#/components/schemas/UserSelect' + include: + $ref: '#/components/schemas/UserInclude' + data: + $ref: '#/components/schemas/UserCreateInput' + meta: + $ref: '#/components/schemas/_Meta' + UserCreateManyArgs: + type: object + required: + - data + properties: + data: + oneOf: + - $ref: '#/components/schemas/UserCreateManyInput' + - type: array + items: + $ref: '#/components/schemas/UserCreateManyInput' + skipDuplicates: + type: boolean + description: Do not insert records with unique fields or ID fields that already + exist. + meta: + $ref: '#/components/schemas/_Meta' + UserFindUniqueArgs: + type: object + required: + - where + properties: + select: + $ref: '#/components/schemas/UserSelect' + include: + $ref: '#/components/schemas/UserInclude' + where: + $ref: '#/components/schemas/UserWhereUniqueInput' + meta: + $ref: '#/components/schemas/_Meta' + UserFindFirstArgs: + type: object + properties: + select: + $ref: '#/components/schemas/UserSelect' + include: + $ref: '#/components/schemas/UserInclude' + where: + $ref: '#/components/schemas/UserWhereInput' + meta: + $ref: '#/components/schemas/_Meta' + UserFindManyArgs: + type: object + properties: + select: + $ref: '#/components/schemas/UserSelect' + include: + $ref: '#/components/schemas/UserInclude' + where: + $ref: '#/components/schemas/UserWhereInput' + meta: + $ref: '#/components/schemas/_Meta' + orderBy: + oneOf: + - $ref: '#/components/schemas/UserOrderByWithRelationInput' + - type: array + items: + $ref: '#/components/schemas/UserOrderByWithRelationInput' + cursor: + $ref: '#/components/schemas/UserWhereUniqueInput' + take: + type: integer + skip: + type: integer + UserUpdateArgs: + type: object + required: + - where + - data + properties: + select: + $ref: '#/components/schemas/UserSelect' + include: + $ref: '#/components/schemas/UserInclude' + where: + $ref: '#/components/schemas/UserWhereUniqueInput' + data: + $ref: '#/components/schemas/UserUpdateInput' + meta: + $ref: '#/components/schemas/_Meta' + UserUpdateManyArgs: + type: object + required: + - data + properties: + where: + $ref: '#/components/schemas/UserWhereInput' + data: + $ref: '#/components/schemas/UserUpdateManyMutationInput' + meta: + $ref: '#/components/schemas/_Meta' + UserUpsertArgs: + type: object + required: + - create + - update + - where + properties: + select: + $ref: '#/components/schemas/UserSelect' + include: + $ref: '#/components/schemas/UserInclude' + where: + $ref: '#/components/schemas/UserWhereUniqueInput' + create: + $ref: '#/components/schemas/UserCreateInput' + update: + $ref: '#/components/schemas/UserUpdateInput' + meta: + $ref: '#/components/schemas/_Meta' + UserDeleteUniqueArgs: + type: object + required: + - where + properties: + select: + $ref: '#/components/schemas/UserSelect' + include: + $ref: '#/components/schemas/UserInclude' + where: + $ref: '#/components/schemas/UserWhereUniqueInput' + meta: + $ref: '#/components/schemas/_Meta' + UserDeleteManyArgs: + type: object + properties: + where: + $ref: '#/components/schemas/UserWhereInput' + meta: + $ref: '#/components/schemas/_Meta' + UserCountArgs: + type: object + properties: + select: + $ref: '#/components/schemas/UserSelect' + where: + $ref: '#/components/schemas/UserWhereInput' + meta: + $ref: '#/components/schemas/_Meta' + UserAggregateArgs: + type: object + properties: + where: + $ref: '#/components/schemas/UserWhereInput' + orderBy: + $ref: '#/components/schemas/UserOrderByWithRelationInput' + cursor: + $ref: '#/components/schemas/UserWhereUniqueInput' + take: + type: integer + skip: + type: integer + _count: + oneOf: + - type: boolean + - $ref: '#/components/schemas/UserCountAggregateInput' + _min: + $ref: '#/components/schemas/UserMinAggregateInput' + _max: + $ref: '#/components/schemas/UserMaxAggregateInput' + meta: + $ref: '#/components/schemas/_Meta' + UserGroupByArgs: + type: object + properties: + where: + $ref: '#/components/schemas/UserWhereInput' + orderBy: + $ref: '#/components/schemas/UserOrderByWithRelationInput' + by: + $ref: '#/components/schemas/UserScalarFieldEnum' + having: + $ref: '#/components/schemas/UserScalarWhereWithAggregatesInput' + take: + type: integer + skip: + type: integer + _count: + oneOf: + - type: boolean + - $ref: '#/components/schemas/UserCountAggregateInput' + _min: + $ref: '#/components/schemas/UserMinAggregateInput' + _max: + $ref: '#/components/schemas/UserMaxAggregateInput' + meta: + $ref: '#/components/schemas/_Meta' + ProfileCreateArgs: + type: object + required: + - data + properties: + select: + $ref: '#/components/schemas/ProfileSelect' + include: + $ref: '#/components/schemas/ProfileInclude' + data: + $ref: '#/components/schemas/ProfileCreateInput' + meta: + $ref: '#/components/schemas/_Meta' + ProfileCreateManyArgs: + type: object + required: + - data + properties: + data: + oneOf: + - $ref: '#/components/schemas/ProfileCreateManyInput' + - type: array + items: + $ref: '#/components/schemas/ProfileCreateManyInput' + skipDuplicates: + type: boolean + description: Do not insert records with unique fields or ID fields that already + exist. + meta: + $ref: '#/components/schemas/_Meta' + ProfileFindUniqueArgs: + type: object + required: + - where + properties: + select: + $ref: '#/components/schemas/ProfileSelect' + include: + $ref: '#/components/schemas/ProfileInclude' + where: + $ref: '#/components/schemas/ProfileWhereUniqueInput' + meta: + $ref: '#/components/schemas/_Meta' + ProfileFindFirstArgs: + type: object + properties: + select: + $ref: '#/components/schemas/ProfileSelect' + include: + $ref: '#/components/schemas/ProfileInclude' + where: + $ref: '#/components/schemas/ProfileWhereInput' + meta: + $ref: '#/components/schemas/_Meta' + ProfileFindManyArgs: + type: object + properties: + select: + $ref: '#/components/schemas/ProfileSelect' + include: + $ref: '#/components/schemas/ProfileInclude' + where: + $ref: '#/components/schemas/ProfileWhereInput' + meta: + $ref: '#/components/schemas/_Meta' + orderBy: + oneOf: + - $ref: '#/components/schemas/ProfileOrderByWithRelationInput' + - type: array + items: + $ref: '#/components/schemas/ProfileOrderByWithRelationInput' + cursor: + $ref: '#/components/schemas/ProfileWhereUniqueInput' + take: + type: integer + skip: + type: integer + ProfileUpdateArgs: + type: object + required: + - where + - data + properties: + select: + $ref: '#/components/schemas/ProfileSelect' + include: + $ref: '#/components/schemas/ProfileInclude' + where: + $ref: '#/components/schemas/ProfileWhereUniqueInput' + data: + $ref: '#/components/schemas/ProfileUpdateInput' + meta: + $ref: '#/components/schemas/_Meta' + ProfileUpdateManyArgs: + type: object + required: + - data + properties: + where: + $ref: '#/components/schemas/ProfileWhereInput' + data: + $ref: '#/components/schemas/ProfileUpdateManyMutationInput' + meta: + $ref: '#/components/schemas/_Meta' + ProfileUpsertArgs: + type: object + required: + - create + - update + - where + properties: + select: + $ref: '#/components/schemas/ProfileSelect' + include: + $ref: '#/components/schemas/ProfileInclude' + where: + $ref: '#/components/schemas/ProfileWhereUniqueInput' + create: + $ref: '#/components/schemas/ProfileCreateInput' + update: + $ref: '#/components/schemas/ProfileUpdateInput' + meta: + $ref: '#/components/schemas/_Meta' + ProfileDeleteUniqueArgs: + type: object + required: + - where + properties: + select: + $ref: '#/components/schemas/ProfileSelect' + include: + $ref: '#/components/schemas/ProfileInclude' + where: + $ref: '#/components/schemas/ProfileWhereUniqueInput' + meta: + $ref: '#/components/schemas/_Meta' + ProfileDeleteManyArgs: + type: object + properties: + where: + $ref: '#/components/schemas/ProfileWhereInput' + meta: + $ref: '#/components/schemas/_Meta' + ProfileCountArgs: + type: object + properties: + select: + $ref: '#/components/schemas/ProfileSelect' + where: + $ref: '#/components/schemas/ProfileWhereInput' + meta: + $ref: '#/components/schemas/_Meta' + ProfileAggregateArgs: + type: object + properties: + where: + $ref: '#/components/schemas/ProfileWhereInput' + orderBy: + $ref: '#/components/schemas/ProfileOrderByWithRelationInput' + cursor: + $ref: '#/components/schemas/ProfileWhereUniqueInput' + take: + type: integer + skip: + type: integer + _count: + oneOf: + - type: boolean + - $ref: '#/components/schemas/ProfileCountAggregateInput' + _min: + $ref: '#/components/schemas/ProfileMinAggregateInput' + _max: + $ref: '#/components/schemas/ProfileMaxAggregateInput' + meta: + $ref: '#/components/schemas/_Meta' + ProfileGroupByArgs: + type: object + properties: + where: + $ref: '#/components/schemas/ProfileWhereInput' + orderBy: + $ref: '#/components/schemas/ProfileOrderByWithRelationInput' + by: + $ref: '#/components/schemas/ProfileScalarFieldEnum' + having: + $ref: '#/components/schemas/ProfileScalarWhereWithAggregatesInput' + take: + type: integer + skip: + type: integer + _count: + oneOf: + - type: boolean + - $ref: '#/components/schemas/ProfileCountAggregateInput' + _min: + $ref: '#/components/schemas/ProfileMinAggregateInput' + _max: + $ref: '#/components/schemas/ProfileMaxAggregateInput' + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemCreateArgs: + type: object + required: + - data + properties: + select: + $ref: '#/components/schemas/Post_ItemSelect' + include: + $ref: '#/components/schemas/Post_ItemInclude' + data: + $ref: '#/components/schemas/Post_ItemCreateInput' + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemCreateManyArgs: + type: object + required: + - data + properties: + data: + oneOf: + - $ref: '#/components/schemas/Post_ItemCreateManyInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemCreateManyInput' + skipDuplicates: + type: boolean + description: Do not insert records with unique fields or ID fields that already + exist. + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemFindUniqueArgs: + type: object + required: + - where + properties: + select: + $ref: '#/components/schemas/Post_ItemSelect' + include: + $ref: '#/components/schemas/Post_ItemInclude' + where: + $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemFindFirstArgs: + type: object + properties: + select: + $ref: '#/components/schemas/Post_ItemSelect' + include: + $ref: '#/components/schemas/Post_ItemInclude' + where: + $ref: '#/components/schemas/Post_ItemWhereInput' + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemFindManyArgs: + type: object + properties: + select: + $ref: '#/components/schemas/Post_ItemSelect' + include: + $ref: '#/components/schemas/Post_ItemInclude' + where: + $ref: '#/components/schemas/Post_ItemWhereInput' + meta: + $ref: '#/components/schemas/_Meta' + orderBy: + oneOf: + - $ref: '#/components/schemas/Post_ItemOrderByWithRelationInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemOrderByWithRelationInput' + cursor: + $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + take: + type: integer + skip: + type: integer + Post_ItemUpdateArgs: + type: object + required: + - where + - data + properties: + select: + $ref: '#/components/schemas/Post_ItemSelect' + include: + $ref: '#/components/schemas/Post_ItemInclude' + where: + $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + data: + $ref: '#/components/schemas/Post_ItemUpdateInput' + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemUpdateManyArgs: + type: object + required: + - data + properties: + where: + $ref: '#/components/schemas/Post_ItemWhereInput' + data: + $ref: '#/components/schemas/Post_ItemUpdateManyMutationInput' + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemUpsertArgs: + type: object + required: + - create + - update + - where + properties: + select: + $ref: '#/components/schemas/Post_ItemSelect' + include: + $ref: '#/components/schemas/Post_ItemInclude' + where: + $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + create: + $ref: '#/components/schemas/Post_ItemCreateInput' + update: + $ref: '#/components/schemas/Post_ItemUpdateInput' + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemDeleteUniqueArgs: + type: object + required: + - where + properties: + select: + $ref: '#/components/schemas/Post_ItemSelect' + include: + $ref: '#/components/schemas/Post_ItemInclude' + where: + $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemDeleteManyArgs: + type: object + properties: + where: + $ref: '#/components/schemas/Post_ItemWhereInput' + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemCountArgs: + type: object + properties: + select: + $ref: '#/components/schemas/Post_ItemSelect' + where: + $ref: '#/components/schemas/Post_ItemWhereInput' + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemAggregateArgs: + type: object + properties: + where: + $ref: '#/components/schemas/Post_ItemWhereInput' + orderBy: + $ref: '#/components/schemas/Post_ItemOrderByWithRelationInput' + cursor: + $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + take: + type: integer + skip: + type: integer + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemGroupByArgs: + type: object + properties: + where: + $ref: '#/components/schemas/Post_ItemWhereInput' + orderBy: + $ref: '#/components/schemas/Post_ItemOrderByWithRelationInput' + by: + $ref: '#/components/schemas/Post_ItemScalarFieldEnum' + having: + $ref: '#/components/schemas/Post_ItemScalarWhereWithAggregatesInput' + take: + type: integer + skip: + type: integer + meta: + $ref: '#/components/schemas/_Meta' +paths: + /user/create: + post: + operationId: createUser + description: Create a new User + tags: + - user + responses: + '201': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/User' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UserCreateArgs' + /user/createMany: + post: + operationId: createManyUser + description: Create several User + tags: + - user + responses: + '201': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BatchPayload' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UserCreateManyArgs' + /user/findUnique: + get: + operationId: findUniqueUser + description: Find one unique User + tags: + - user + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/User' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/UserFindUniqueArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /user/findFirst: + get: + operationId: findFirstUser + description: Find the first User matching the given condition + tags: + - user + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/User' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/UserFindFirstArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /user/findMany: + get: + operationId: findManyUser + description: Find users matching the given conditions + tags: + - user + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + type: array + items: + $ref: '#/components/schemas/User' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/UserFindManyArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /user/update: + patch: + operationId: updateUser + description: Update a User + tags: + - user + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/User' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UserUpdateArgs' + /user/updateMany: + patch: + operationId: updateManyUser + description: Update Users matching the given condition + tags: + - user + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BatchPayload' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UserUpdateManyArgs' + /user/upsert: + post: + operationId: upsertUser + description: Upsert a User + tags: + - user + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/User' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UserUpsertArgs' + /user/dodelete: + put: + operationId: deleteUser + description: Delete a unique user + tags: + - delete + - user + summary: Delete a user yeah yeah + deprecated: true + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/User' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UserDeleteUniqueArgs' + /user/deleteMany: + delete: + operationId: deleteManyUser + description: Delete Users matching the given condition + tags: + - user + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BatchPayload' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/UserDeleteManyArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /user/count: + get: + operationId: countUser + description: Find a list of User + tags: + - user + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + oneOf: + - type: integer + - $ref: '#/components/schemas/UserCountAggregateOutputType' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/UserCountArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /user/aggregate: + get: + operationId: aggregateUser + description: Aggregate Users + tags: + - user + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/AggregateUser' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/UserAggregateArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /user/groupBy: + get: + operationId: groupByUser + description: Group Users by fields + tags: + - user + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + type: array + items: + $ref: '#/components/schemas/UserGroupByOutputType' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/UserGroupByArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /profile/create: + post: + operationId: createProfile + description: Create a new Profile + tags: + - profile + responses: + '201': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Profile' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileCreateArgs' + /profile/createMany: + post: + operationId: createManyProfile + description: Create several Profile + tags: + - profile + responses: + '201': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BatchPayload' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileCreateManyArgs' + /profile/findUnique: + get: + operationId: findUniqueProfile + description: Find one unique Profile + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Profile' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileFindUniqueArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /profile/findFirst: + get: + operationId: findFirstProfile + description: Find the first Profile matching the given condition + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Profile' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileFindFirstArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /profile/findMany: + get: + operationId: findManyProfile + description: Find a list of Profile + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + type: array + items: + $ref: '#/components/schemas/Profile' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileFindManyArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /profile/update: + patch: + operationId: updateProfile + description: Update a Profile + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Profile' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileUpdateArgs' + /profile/updateMany: + patch: + operationId: updateManyProfile + description: Update Profiles matching the given condition + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BatchPayload' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileUpdateManyArgs' + /profile/upsert: + post: + operationId: upsertProfile + description: Upsert a Profile + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Profile' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileUpsertArgs' + /profile/delete: + delete: + operationId: deleteProfile + description: Delete one unique Profile + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Profile' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileDeleteUniqueArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /profile/deleteMany: + delete: + operationId: deleteManyProfile + description: Delete Profiles matching the given condition + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BatchPayload' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileDeleteManyArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /profile/count: + get: + operationId: countProfile + description: Find a list of Profile + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + oneOf: + - type: integer + - $ref: '#/components/schemas/ProfileCountAggregateOutputType' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileCountArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /profile/aggregate: + get: + operationId: aggregateProfile + description: Aggregate Profiles + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/AggregateProfile' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileAggregateArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /profile/groupBy: + get: + operationId: groupByProfile + description: Group Profiles by fields + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + type: array + items: + $ref: '#/components/schemas/ProfileGroupByOutputType' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileGroupByArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /post_Item/create: + post: + operationId: createPost_Item + description: Create a new Post_Item + tags: + - post_Item + responses: + '201': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Post_Item' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemCreateArgs' + /post_Item/createMany: + post: + operationId: createManyPost_Item + description: Create several Post_Item + tags: + - post_Item + responses: + '201': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BatchPayload' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemCreateManyArgs' + /post_Item/findUnique: + get: + operationId: findUniquePost_Item + description: Find one unique Post_Item + tags: + - post_Item + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Post_Item' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemFindUniqueArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /post_Item/findFirst: + get: + operationId: findFirstPost_Item + description: Find the first Post_Item matching the given condition + tags: + - post_Item + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Post_Item' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemFindFirstArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /post_Item/update: + patch: + operationId: updatePost_Item + description: Update a Post_Item + tags: + - post_Item + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Post_Item' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemUpdateArgs' + /post_Item/updateMany: + patch: + operationId: updateManyPost_Item + description: Update Post_Items matching the given condition + tags: + - post_Item + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BatchPayload' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemUpdateManyArgs' + /post_Item/upsert: + post: + operationId: upsertPost_Item + description: Upsert a Post_Item + tags: + - post_Item + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Post_Item' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemUpsertArgs' + /post_Item/delete: + delete: + operationId: deletePost_Item + description: Delete one unique Post_Item + tags: + - post_Item + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Post_Item' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemDeleteUniqueArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /post_Item/deleteMany: + delete: + operationId: deleteManyPost_Item + description: Delete Post_Items matching the given condition + tags: + - post_Item + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BatchPayload' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemDeleteManyArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /post_Item/count: + get: + operationId: countPost_Item + description: Find a list of Post_Item + tags: + - post_Item + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + oneOf: + - type: integer + - $ref: '#/components/schemas/Post_ItemCountAggregateOutputType' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemCountArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /post_Item/aggregate: + get: + operationId: aggregatePost_Item + description: Aggregate Post_Items + tags: + - post_Item + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/AggregatePost_Item' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemAggregateArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /post_Item/groupBy: + get: + operationId: groupByPost_Item + description: Group Post_Items by fields + tags: + - post_Item + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + type: array + items: + $ref: '#/components/schemas/Post_ItemGroupByOutputType' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemGroupByArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} diff --git a/packages/server/test/openapi/baseline/rpc-type-coverage-3.1.0.baseline.yaml b/packages/server/test/openapi/baseline/rpc-type-coverage-3.1.0.baseline.yaml new file mode 100644 index 000000000..5f3e59136 --- /dev/null +++ b/packages/server/test/openapi/baseline/rpc-type-coverage-3.1.0.baseline.yaml @@ -0,0 +1,3174 @@ +openapi: 3.1.0 +info: + title: ZenStack Generated API + version: 1.0.0 +tags: + - name: foo + description: Foo operations +components: + schemas: + FooScalarFieldEnum: + type: string + enum: + - id + - string + - int + - bigInt + - date + - float + - decimal + - boolean + - bytes + - json + - plainJson + SortOrder: + type: string + enum: + - asc + - desc + NullableJsonNullValueInput: + type: string + enum: + - DbNull + - JsonNull + JsonNullValueInput: + type: string + enum: + - JsonNull + QueryMode: + type: string + enum: + - default + - insensitive + JsonNullValueFilter: + type: string + enum: + - DbNull + - JsonNull + - AnyNull + NullsOrder: + type: string + enum: + - first + - last + Foo: + type: object + properties: + id: + type: string + string: + type: string + int: + type: integer + bigInt: + type: integer + date: + type: string + format: date-time + float: + type: number + decimal: + oneOf: + - type: string + - type: number + boolean: + type: boolean + bytes: + oneOf: + - type: 'null' + - type: string + format: byte + json: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Meta' + plainJson: {} + required: + - id + - string + - int + - bigInt + - date + - float + - decimal + - boolean + - plainJson + Meta: + type: object + description: The "Meta" TypeDef + properties: + something: + type: string + required: + - something + FooWhereInput: + type: object + properties: + AND: + oneOf: + - $ref: '#/components/schemas/FooWhereInput' + - type: array + items: + $ref: '#/components/schemas/FooWhereInput' + OR: + type: array + items: + $ref: '#/components/schemas/FooWhereInput' + NOT: + oneOf: + - $ref: '#/components/schemas/FooWhereInput' + - type: array + items: + $ref: '#/components/schemas/FooWhereInput' + id: + oneOf: + - $ref: '#/components/schemas/StringFilter' + - type: string + string: + oneOf: + - $ref: '#/components/schemas/StringFilter' + - type: string + int: + oneOf: + - $ref: '#/components/schemas/IntFilter' + - type: integer + bigInt: + oneOf: + - $ref: '#/components/schemas/BigIntFilter' + - type: integer + date: + oneOf: + - $ref: '#/components/schemas/DateTimeFilter' + - type: string + format: date-time + float: + oneOf: + - $ref: '#/components/schemas/FloatFilter' + - type: number + decimal: + oneOf: + - $ref: '#/components/schemas/DecimalFilter' + - oneOf: + - type: string + - type: number + boolean: + oneOf: + - $ref: '#/components/schemas/BoolFilter' + - type: boolean + bytes: + oneOf: + - $ref: '#/components/schemas/BytesNullableFilter' + - type: string + format: byte + - type: 'null' + json: + $ref: '#/components/schemas/JsonNullableFilter' + plainJson: + $ref: '#/components/schemas/JsonFilter' + FooOrderByWithRelationInput: + type: object + properties: + id: + $ref: '#/components/schemas/SortOrder' + string: + $ref: '#/components/schemas/SortOrder' + int: + $ref: '#/components/schemas/SortOrder' + bigInt: + $ref: '#/components/schemas/SortOrder' + date: + $ref: '#/components/schemas/SortOrder' + float: + $ref: '#/components/schemas/SortOrder' + decimal: + $ref: '#/components/schemas/SortOrder' + boolean: + $ref: '#/components/schemas/SortOrder' + bytes: + oneOf: + - $ref: '#/components/schemas/SortOrder' + - $ref: '#/components/schemas/SortOrderInput' + json: + oneOf: + - $ref: '#/components/schemas/SortOrder' + - $ref: '#/components/schemas/SortOrderInput' + plainJson: + $ref: '#/components/schemas/SortOrder' + FooWhereUniqueInput: + type: object + properties: + id: + type: string + AND: + oneOf: + - $ref: '#/components/schemas/FooWhereInput' + - type: array + items: + $ref: '#/components/schemas/FooWhereInput' + OR: + type: array + items: + $ref: '#/components/schemas/FooWhereInput' + NOT: + oneOf: + - $ref: '#/components/schemas/FooWhereInput' + - type: array + items: + $ref: '#/components/schemas/FooWhereInput' + string: + oneOf: + - $ref: '#/components/schemas/StringFilter' + - type: string + int: + oneOf: + - $ref: '#/components/schemas/IntFilter' + - type: integer + bigInt: + oneOf: + - $ref: '#/components/schemas/BigIntFilter' + - type: integer + date: + oneOf: + - $ref: '#/components/schemas/DateTimeFilter' + - type: string + format: date-time + float: + oneOf: + - $ref: '#/components/schemas/FloatFilter' + - type: number + decimal: + oneOf: + - $ref: '#/components/schemas/DecimalFilter' + - oneOf: + - type: string + - type: number + boolean: + oneOf: + - $ref: '#/components/schemas/BoolFilter' + - type: boolean + bytes: + oneOf: + - $ref: '#/components/schemas/BytesNullableFilter' + - type: string + format: byte + - type: 'null' + json: + $ref: '#/components/schemas/JsonNullableFilter' + plainJson: + $ref: '#/components/schemas/JsonFilter' + FooScalarWhereWithAggregatesInput: + type: object + properties: + AND: + oneOf: + - $ref: '#/components/schemas/FooScalarWhereWithAggregatesInput' + - type: array + items: + $ref: '#/components/schemas/FooScalarWhereWithAggregatesInput' + OR: + type: array + items: + $ref: '#/components/schemas/FooScalarWhereWithAggregatesInput' + NOT: + oneOf: + - $ref: '#/components/schemas/FooScalarWhereWithAggregatesInput' + - type: array + items: + $ref: '#/components/schemas/FooScalarWhereWithAggregatesInput' + id: + oneOf: + - $ref: '#/components/schemas/StringWithAggregatesFilter' + - type: string + string: + oneOf: + - $ref: '#/components/schemas/StringWithAggregatesFilter' + - type: string + int: + oneOf: + - $ref: '#/components/schemas/IntWithAggregatesFilter' + - type: integer + bigInt: + oneOf: + - $ref: '#/components/schemas/BigIntWithAggregatesFilter' + - type: integer + date: + oneOf: + - $ref: '#/components/schemas/DateTimeWithAggregatesFilter' + - type: string + format: date-time + float: + oneOf: + - $ref: '#/components/schemas/FloatWithAggregatesFilter' + - type: number + decimal: + oneOf: + - $ref: '#/components/schemas/DecimalWithAggregatesFilter' + - oneOf: + - type: string + - type: number + boolean: + oneOf: + - $ref: '#/components/schemas/BoolWithAggregatesFilter' + - type: boolean + bytes: + oneOf: + - $ref: '#/components/schemas/BytesNullableWithAggregatesFilter' + - type: string + format: byte + - type: 'null' + json: + $ref: '#/components/schemas/JsonNullableWithAggregatesFilter' + plainJson: + $ref: '#/components/schemas/JsonWithAggregatesFilter' + FooCreateInput: + type: object + properties: + id: + type: string + string: + type: string + int: + type: integer + bigInt: + type: integer + date: + type: string + format: date-time + float: + type: number + decimal: + oneOf: + - type: string + - type: number + boolean: + type: boolean + bytes: + oneOf: + - type: 'null' + - type: string + format: byte + json: + oneOf: + - $ref: '#/components/schemas/NullableJsonNullValueInput' + - {} + plainJson: + oneOf: + - $ref: '#/components/schemas/JsonNullValueInput' + - {} + required: + - string + - int + - bigInt + - date + - float + - decimal + - boolean + - plainJson + FooUpdateInput: + type: object + properties: + id: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + string: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + int: + oneOf: + - type: integer + - $ref: '#/components/schemas/IntFieldUpdateOperationsInput' + bigInt: + oneOf: + - type: integer + - $ref: '#/components/schemas/BigIntFieldUpdateOperationsInput' + date: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + float: + oneOf: + - type: number + - $ref: '#/components/schemas/FloatFieldUpdateOperationsInput' + decimal: + oneOf: + - oneOf: + - type: string + - type: number + - $ref: '#/components/schemas/DecimalFieldUpdateOperationsInput' + boolean: + oneOf: + - type: boolean + - $ref: '#/components/schemas/BoolFieldUpdateOperationsInput' + bytes: + oneOf: + - type: string + format: byte + - $ref: '#/components/schemas/NullableBytesFieldUpdateOperationsInput' + - type: 'null' + json: + oneOf: + - $ref: '#/components/schemas/NullableJsonNullValueInput' + - {} + plainJson: + oneOf: + - $ref: '#/components/schemas/JsonNullValueInput' + - {} + FooCreateManyInput: + type: object + properties: + id: + type: string + string: + type: string + int: + type: integer + bigInt: + type: integer + date: + type: string + format: date-time + float: + type: number + decimal: + oneOf: + - type: string + - type: number + boolean: + type: boolean + bytes: + oneOf: + - type: 'null' + - type: string + format: byte + json: + oneOf: + - $ref: '#/components/schemas/NullableJsonNullValueInput' + - {} + plainJson: + oneOf: + - $ref: '#/components/schemas/JsonNullValueInput' + - {} + required: + - string + - int + - bigInt + - date + - float + - decimal + - boolean + - plainJson + FooUpdateManyMutationInput: + type: object + properties: + id: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + string: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + int: + oneOf: + - type: integer + - $ref: '#/components/schemas/IntFieldUpdateOperationsInput' + bigInt: + oneOf: + - type: integer + - $ref: '#/components/schemas/BigIntFieldUpdateOperationsInput' + date: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + float: + oneOf: + - type: number + - $ref: '#/components/schemas/FloatFieldUpdateOperationsInput' + decimal: + oneOf: + - oneOf: + - type: string + - type: number + - $ref: '#/components/schemas/DecimalFieldUpdateOperationsInput' + boolean: + oneOf: + - type: boolean + - $ref: '#/components/schemas/BoolFieldUpdateOperationsInput' + bytes: + oneOf: + - type: string + format: byte + - $ref: '#/components/schemas/NullableBytesFieldUpdateOperationsInput' + - type: 'null' + json: + oneOf: + - $ref: '#/components/schemas/NullableJsonNullValueInput' + - {} + plainJson: + oneOf: + - $ref: '#/components/schemas/JsonNullValueInput' + - {} + StringFilter: + type: object + properties: + equals: + type: string + in: + type: array + items: + type: string + notIn: + type: array + items: + type: string + lt: + type: string + lte: + type: string + gt: + type: string + gte: + type: string + contains: + type: string + startsWith: + type: string + endsWith: + type: string + mode: + $ref: '#/components/schemas/QueryMode' + not: + oneOf: + - type: string + - $ref: '#/components/schemas/NestedStringFilter' + IntFilter: + type: object + properties: + equals: + type: integer + in: + type: array + items: + type: integer + notIn: + type: array + items: + type: integer + lt: + type: integer + lte: + type: integer + gt: + type: integer + gte: + type: integer + not: + oneOf: + - type: integer + - $ref: '#/components/schemas/NestedIntFilter' + BigIntFilter: + type: object + properties: + equals: + type: integer + in: + type: array + items: + type: integer + notIn: + type: array + items: + type: integer + lt: + type: integer + lte: + type: integer + gt: + type: integer + gte: + type: integer + not: + oneOf: + - type: integer + - $ref: '#/components/schemas/NestedBigIntFilter' + DateTimeFilter: + type: object + properties: + equals: + type: string + format: date-time + in: + type: array + items: + type: string + format: date-time + notIn: + type: array + items: + type: string + format: date-time + lt: + type: string + format: date-time + lte: + type: string + format: date-time + gt: + type: string + format: date-time + gte: + type: string + format: date-time + not: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/NestedDateTimeFilter' + FloatFilter: + type: object + properties: + equals: + type: number + in: + type: array + items: + type: number + notIn: + type: array + items: + type: number + lt: + type: number + lte: + type: number + gt: + type: number + gte: + type: number + not: + oneOf: + - type: number + - $ref: '#/components/schemas/NestedFloatFilter' + DecimalFilter: + type: object + properties: + equals: + oneOf: + - type: string + - type: number + in: + type: array + items: + oneOf: + - type: string + - type: number + notIn: + type: array + items: + oneOf: + - type: string + - type: number + lt: + oneOf: + - type: string + - type: number + lte: + oneOf: + - type: string + - type: number + gt: + oneOf: + - type: string + - type: number + gte: + oneOf: + - type: string + - type: number + not: + oneOf: + - oneOf: + - type: string + - type: number + - $ref: '#/components/schemas/NestedDecimalFilter' + BoolFilter: + type: object + properties: + equals: + type: boolean + not: + oneOf: + - type: boolean + - $ref: '#/components/schemas/NestedBoolFilter' + BytesNullableFilter: + type: object + properties: + equals: + oneOf: + - type: 'null' + - type: string + format: byte + in: + oneOf: + - type: 'null' + - type: array + items: + type: string + format: byte + notIn: + oneOf: + - type: 'null' + - type: array + items: + type: string + format: byte + not: + oneOf: + - type: string + format: byte + - $ref: '#/components/schemas/NestedBytesNullableFilter' + - type: 'null' + JsonNullableFilter: + type: object + properties: + equals: + oneOf: + - {} + - $ref: '#/components/schemas/JsonNullValueFilter' + path: + type: array + items: + type: string + mode: + $ref: '#/components/schemas/QueryMode' + string_contains: + type: string + string_starts_with: + type: string + string_ends_with: + type: string + array_starts_with: + oneOf: + - type: 'null' + - {} + array_ends_with: + oneOf: + - type: 'null' + - {} + array_contains: + oneOf: + - type: 'null' + - {} + lt: {} + lte: {} + gt: {} + gte: {} + not: + oneOf: + - {} + - $ref: '#/components/schemas/JsonNullValueFilter' + JsonFilter: + type: object + properties: + equals: + oneOf: + - {} + - $ref: '#/components/schemas/JsonNullValueFilter' + path: + type: array + items: + type: string + mode: + $ref: '#/components/schemas/QueryMode' + string_contains: + type: string + string_starts_with: + type: string + string_ends_with: + type: string + array_starts_with: + oneOf: + - type: 'null' + - {} + array_ends_with: + oneOf: + - type: 'null' + - {} + array_contains: + oneOf: + - type: 'null' + - {} + lt: {} + lte: {} + gt: {} + gte: {} + not: + oneOf: + - {} + - $ref: '#/components/schemas/JsonNullValueFilter' + SortOrderInput: + type: object + properties: + sort: + $ref: '#/components/schemas/SortOrder' + nulls: + $ref: '#/components/schemas/NullsOrder' + required: + - sort + StringWithAggregatesFilter: + type: object + properties: + equals: + type: string + in: + type: array + items: + type: string + notIn: + type: array + items: + type: string + lt: + type: string + lte: + type: string + gt: + type: string + gte: + type: string + contains: + type: string + startsWith: + type: string + endsWith: + type: string + mode: + $ref: '#/components/schemas/QueryMode' + not: + oneOf: + - type: string + - $ref: '#/components/schemas/NestedStringWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _min: + $ref: '#/components/schemas/NestedStringFilter' + _max: + $ref: '#/components/schemas/NestedStringFilter' + IntWithAggregatesFilter: + type: object + properties: + equals: + type: integer + in: + type: array + items: + type: integer + notIn: + type: array + items: + type: integer + lt: + type: integer + lte: + type: integer + gt: + type: integer + gte: + type: integer + not: + oneOf: + - type: integer + - $ref: '#/components/schemas/NestedIntWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _avg: + $ref: '#/components/schemas/NestedFloatFilter' + _sum: + $ref: '#/components/schemas/NestedIntFilter' + _min: + $ref: '#/components/schemas/NestedIntFilter' + _max: + $ref: '#/components/schemas/NestedIntFilter' + BigIntWithAggregatesFilter: + type: object + properties: + equals: + type: integer + in: + type: array + items: + type: integer + notIn: + type: array + items: + type: integer + lt: + type: integer + lte: + type: integer + gt: + type: integer + gte: + type: integer + not: + oneOf: + - type: integer + - $ref: '#/components/schemas/NestedBigIntWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _avg: + $ref: '#/components/schemas/NestedFloatFilter' + _sum: + $ref: '#/components/schemas/NestedBigIntFilter' + _min: + $ref: '#/components/schemas/NestedBigIntFilter' + _max: + $ref: '#/components/schemas/NestedBigIntFilter' + DateTimeWithAggregatesFilter: + type: object + properties: + equals: + type: string + format: date-time + in: + type: array + items: + type: string + format: date-time + notIn: + type: array + items: + type: string + format: date-time + lt: + type: string + format: date-time + lte: + type: string + format: date-time + gt: + type: string + format: date-time + gte: + type: string + format: date-time + not: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/NestedDateTimeWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _min: + $ref: '#/components/schemas/NestedDateTimeFilter' + _max: + $ref: '#/components/schemas/NestedDateTimeFilter' + FloatWithAggregatesFilter: + type: object + properties: + equals: + type: number + in: + type: array + items: + type: number + notIn: + type: array + items: + type: number + lt: + type: number + lte: + type: number + gt: + type: number + gte: + type: number + not: + oneOf: + - type: number + - $ref: '#/components/schemas/NestedFloatWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _avg: + $ref: '#/components/schemas/NestedFloatFilter' + _sum: + $ref: '#/components/schemas/NestedFloatFilter' + _min: + $ref: '#/components/schemas/NestedFloatFilter' + _max: + $ref: '#/components/schemas/NestedFloatFilter' + DecimalWithAggregatesFilter: + type: object + properties: + equals: + oneOf: + - type: string + - type: number + in: + type: array + items: + oneOf: + - type: string + - type: number + notIn: + type: array + items: + oneOf: + - type: string + - type: number + lt: + oneOf: + - type: string + - type: number + lte: + oneOf: + - type: string + - type: number + gt: + oneOf: + - type: string + - type: number + gte: + oneOf: + - type: string + - type: number + not: + oneOf: + - oneOf: + - type: string + - type: number + - $ref: '#/components/schemas/NestedDecimalWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _avg: + $ref: '#/components/schemas/NestedDecimalFilter' + _sum: + $ref: '#/components/schemas/NestedDecimalFilter' + _min: + $ref: '#/components/schemas/NestedDecimalFilter' + _max: + $ref: '#/components/schemas/NestedDecimalFilter' + BoolWithAggregatesFilter: + type: object + properties: + equals: + type: boolean + not: + oneOf: + - type: boolean + - $ref: '#/components/schemas/NestedBoolWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _min: + $ref: '#/components/schemas/NestedBoolFilter' + _max: + $ref: '#/components/schemas/NestedBoolFilter' + BytesNullableWithAggregatesFilter: + type: object + properties: + equals: + oneOf: + - type: 'null' + - type: string + format: byte + in: + oneOf: + - type: 'null' + - type: array + items: + type: string + format: byte + notIn: + oneOf: + - type: 'null' + - type: array + items: + type: string + format: byte + not: + oneOf: + - type: string + format: byte + - $ref: '#/components/schemas/NestedBytesNullableWithAggregatesFilter' + - type: 'null' + _count: + $ref: '#/components/schemas/NestedIntNullableFilter' + _min: + $ref: '#/components/schemas/NestedBytesNullableFilter' + _max: + $ref: '#/components/schemas/NestedBytesNullableFilter' + JsonNullableWithAggregatesFilter: + type: object + properties: + equals: + oneOf: + - {} + - $ref: '#/components/schemas/JsonNullValueFilter' + path: + type: array + items: + type: string + mode: + $ref: '#/components/schemas/QueryMode' + string_contains: + type: string + string_starts_with: + type: string + string_ends_with: + type: string + array_starts_with: + oneOf: + - type: 'null' + - {} + array_ends_with: + oneOf: + - type: 'null' + - {} + array_contains: + oneOf: + - type: 'null' + - {} + lt: {} + lte: {} + gt: {} + gte: {} + not: + oneOf: + - {} + - $ref: '#/components/schemas/JsonNullValueFilter' + _count: + $ref: '#/components/schemas/NestedIntNullableFilter' + _min: + $ref: '#/components/schemas/NestedJsonNullableFilter' + _max: + $ref: '#/components/schemas/NestedJsonNullableFilter' + JsonWithAggregatesFilter: + type: object + properties: + equals: + oneOf: + - {} + - $ref: '#/components/schemas/JsonNullValueFilter' + path: + type: array + items: + type: string + mode: + $ref: '#/components/schemas/QueryMode' + string_contains: + type: string + string_starts_with: + type: string + string_ends_with: + type: string + array_starts_with: + oneOf: + - type: 'null' + - {} + array_ends_with: + oneOf: + - type: 'null' + - {} + array_contains: + oneOf: + - type: 'null' + - {} + lt: {} + lte: {} + gt: {} + gte: {} + not: + oneOf: + - {} + - $ref: '#/components/schemas/JsonNullValueFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _min: + $ref: '#/components/schemas/NestedJsonFilter' + _max: + $ref: '#/components/schemas/NestedJsonFilter' + StringFieldUpdateOperationsInput: + type: object + properties: + set: + type: string + IntFieldUpdateOperationsInput: + type: object + properties: + set: + type: integer + increment: + type: integer + decrement: + type: integer + multiply: + type: integer + divide: + type: integer + BigIntFieldUpdateOperationsInput: + type: object + properties: + set: + type: integer + increment: + type: integer + decrement: + type: integer + multiply: + type: integer + divide: + type: integer + DateTimeFieldUpdateOperationsInput: + type: object + properties: + set: + type: string + format: date-time + FloatFieldUpdateOperationsInput: + type: object + properties: + set: + type: number + increment: + type: number + decrement: + type: number + multiply: + type: number + divide: + type: number + DecimalFieldUpdateOperationsInput: + type: object + properties: + set: + oneOf: + - type: string + - type: number + increment: + oneOf: + - type: string + - type: number + decrement: + oneOf: + - type: string + - type: number + multiply: + oneOf: + - type: string + - type: number + divide: + oneOf: + - type: string + - type: number + BoolFieldUpdateOperationsInput: + type: object + properties: + set: + type: boolean + NullableBytesFieldUpdateOperationsInput: + type: object + properties: + set: + oneOf: + - type: 'null' + - type: string + format: byte + NestedStringFilter: + type: object + properties: + equals: + type: string + in: + type: array + items: + type: string + notIn: + type: array + items: + type: string + lt: + type: string + lte: + type: string + gt: + type: string + gte: + type: string + contains: + type: string + startsWith: + type: string + endsWith: + type: string + not: + oneOf: + - type: string + - $ref: '#/components/schemas/NestedStringFilter' + NestedIntFilter: + type: object + properties: + equals: + type: integer + in: + type: array + items: + type: integer + notIn: + type: array + items: + type: integer + lt: + type: integer + lte: + type: integer + gt: + type: integer + gte: + type: integer + not: + oneOf: + - type: integer + - $ref: '#/components/schemas/NestedIntFilter' + NestedBigIntFilter: + type: object + properties: + equals: + type: integer + in: + type: array + items: + type: integer + notIn: + type: array + items: + type: integer + lt: + type: integer + lte: + type: integer + gt: + type: integer + gte: + type: integer + not: + oneOf: + - type: integer + - $ref: '#/components/schemas/NestedBigIntFilter' + NestedDateTimeFilter: + type: object + properties: + equals: + type: string + format: date-time + in: + type: array + items: + type: string + format: date-time + notIn: + type: array + items: + type: string + format: date-time + lt: + type: string + format: date-time + lte: + type: string + format: date-time + gt: + type: string + format: date-time + gte: + type: string + format: date-time + not: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/NestedDateTimeFilter' + NestedFloatFilter: + type: object + properties: + equals: + type: number + in: + type: array + items: + type: number + notIn: + type: array + items: + type: number + lt: + type: number + lte: + type: number + gt: + type: number + gte: + type: number + not: + oneOf: + - type: number + - $ref: '#/components/schemas/NestedFloatFilter' + NestedDecimalFilter: + type: object + properties: + equals: + oneOf: + - type: string + - type: number + in: + type: array + items: + oneOf: + - type: string + - type: number + notIn: + type: array + items: + oneOf: + - type: string + - type: number + lt: + oneOf: + - type: string + - type: number + lte: + oneOf: + - type: string + - type: number + gt: + oneOf: + - type: string + - type: number + gte: + oneOf: + - type: string + - type: number + not: + oneOf: + - oneOf: + - type: string + - type: number + - $ref: '#/components/schemas/NestedDecimalFilter' + NestedBoolFilter: + type: object + properties: + equals: + type: boolean + not: + oneOf: + - type: boolean + - $ref: '#/components/schemas/NestedBoolFilter' + NestedBytesNullableFilter: + type: object + properties: + equals: + oneOf: + - type: 'null' + - type: string + format: byte + in: + oneOf: + - type: 'null' + - type: array + items: + type: string + format: byte + notIn: + oneOf: + - type: 'null' + - type: array + items: + type: string + format: byte + not: + oneOf: + - type: string + format: byte + - $ref: '#/components/schemas/NestedBytesNullableFilter' + - type: 'null' + NestedStringWithAggregatesFilter: + type: object + properties: + equals: + type: string + in: + type: array + items: + type: string + notIn: + type: array + items: + type: string + lt: + type: string + lte: + type: string + gt: + type: string + gte: + type: string + contains: + type: string + startsWith: + type: string + endsWith: + type: string + not: + oneOf: + - type: string + - $ref: '#/components/schemas/NestedStringWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _min: + $ref: '#/components/schemas/NestedStringFilter' + _max: + $ref: '#/components/schemas/NestedStringFilter' + NestedIntWithAggregatesFilter: + type: object + properties: + equals: + type: integer + in: + type: array + items: + type: integer + notIn: + type: array + items: + type: integer + lt: + type: integer + lte: + type: integer + gt: + type: integer + gte: + type: integer + not: + oneOf: + - type: integer + - $ref: '#/components/schemas/NestedIntWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _avg: + $ref: '#/components/schemas/NestedFloatFilter' + _sum: + $ref: '#/components/schemas/NestedIntFilter' + _min: + $ref: '#/components/schemas/NestedIntFilter' + _max: + $ref: '#/components/schemas/NestedIntFilter' + NestedBigIntWithAggregatesFilter: + type: object + properties: + equals: + type: integer + in: + type: array + items: + type: integer + notIn: + type: array + items: + type: integer + lt: + type: integer + lte: + type: integer + gt: + type: integer + gte: + type: integer + not: + oneOf: + - type: integer + - $ref: '#/components/schemas/NestedBigIntWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _avg: + $ref: '#/components/schemas/NestedFloatFilter' + _sum: + $ref: '#/components/schemas/NestedBigIntFilter' + _min: + $ref: '#/components/schemas/NestedBigIntFilter' + _max: + $ref: '#/components/schemas/NestedBigIntFilter' + NestedDateTimeWithAggregatesFilter: + type: object + properties: + equals: + type: string + format: date-time + in: + type: array + items: + type: string + format: date-time + notIn: + type: array + items: + type: string + format: date-time + lt: + type: string + format: date-time + lte: + type: string + format: date-time + gt: + type: string + format: date-time + gte: + type: string + format: date-time + not: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/NestedDateTimeWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _min: + $ref: '#/components/schemas/NestedDateTimeFilter' + _max: + $ref: '#/components/schemas/NestedDateTimeFilter' + NestedFloatWithAggregatesFilter: + type: object + properties: + equals: + type: number + in: + type: array + items: + type: number + notIn: + type: array + items: + type: number + lt: + type: number + lte: + type: number + gt: + type: number + gte: + type: number + not: + oneOf: + - type: number + - $ref: '#/components/schemas/NestedFloatWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _avg: + $ref: '#/components/schemas/NestedFloatFilter' + _sum: + $ref: '#/components/schemas/NestedFloatFilter' + _min: + $ref: '#/components/schemas/NestedFloatFilter' + _max: + $ref: '#/components/schemas/NestedFloatFilter' + NestedDecimalWithAggregatesFilter: + type: object + properties: + equals: + oneOf: + - type: string + - type: number + in: + type: array + items: + oneOf: + - type: string + - type: number + notIn: + type: array + items: + oneOf: + - type: string + - type: number + lt: + oneOf: + - type: string + - type: number + lte: + oneOf: + - type: string + - type: number + gt: + oneOf: + - type: string + - type: number + gte: + oneOf: + - type: string + - type: number + not: + oneOf: + - oneOf: + - type: string + - type: number + - $ref: '#/components/schemas/NestedDecimalWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _avg: + $ref: '#/components/schemas/NestedDecimalFilter' + _sum: + $ref: '#/components/schemas/NestedDecimalFilter' + _min: + $ref: '#/components/schemas/NestedDecimalFilter' + _max: + $ref: '#/components/schemas/NestedDecimalFilter' + NestedBoolWithAggregatesFilter: + type: object + properties: + equals: + type: boolean + not: + oneOf: + - type: boolean + - $ref: '#/components/schemas/NestedBoolWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _min: + $ref: '#/components/schemas/NestedBoolFilter' + _max: + $ref: '#/components/schemas/NestedBoolFilter' + NestedBytesNullableWithAggregatesFilter: + type: object + properties: + equals: + oneOf: + - type: 'null' + - type: string + format: byte + in: + oneOf: + - type: 'null' + - type: array + items: + type: string + format: byte + notIn: + oneOf: + - type: 'null' + - type: array + items: + type: string + format: byte + not: + oneOf: + - type: string + format: byte + - $ref: '#/components/schemas/NestedBytesNullableWithAggregatesFilter' + - type: 'null' + _count: + $ref: '#/components/schemas/NestedIntNullableFilter' + _min: + $ref: '#/components/schemas/NestedBytesNullableFilter' + _max: + $ref: '#/components/schemas/NestedBytesNullableFilter' + NestedIntNullableFilter: + type: object + properties: + equals: + oneOf: + - type: 'null' + - type: integer + in: + oneOf: + - type: 'null' + - type: array + items: + type: integer + notIn: + oneOf: + - type: 'null' + - type: array + items: + type: integer + lt: + type: integer + lte: + type: integer + gt: + type: integer + gte: + type: integer + not: + oneOf: + - type: integer + - $ref: '#/components/schemas/NestedIntNullableFilter' + - type: 'null' + NestedJsonNullableFilter: + type: object + properties: + equals: + oneOf: + - {} + - $ref: '#/components/schemas/JsonNullValueFilter' + path: + type: array + items: + type: string + mode: + $ref: '#/components/schemas/QueryMode' + string_contains: + type: string + string_starts_with: + type: string + string_ends_with: + type: string + array_starts_with: + oneOf: + - type: 'null' + - {} + array_ends_with: + oneOf: + - type: 'null' + - {} + array_contains: + oneOf: + - type: 'null' + - {} + lt: {} + lte: {} + gt: {} + gte: {} + not: + oneOf: + - {} + - $ref: '#/components/schemas/JsonNullValueFilter' + NestedJsonFilter: + type: object + properties: + equals: + oneOf: + - {} + - $ref: '#/components/schemas/JsonNullValueFilter' + path: + type: array + items: + type: string + mode: + $ref: '#/components/schemas/QueryMode' + string_contains: + type: string + string_starts_with: + type: string + string_ends_with: + type: string + array_starts_with: + oneOf: + - type: 'null' + - {} + array_ends_with: + oneOf: + - type: 'null' + - {} + array_contains: + oneOf: + - type: 'null' + - {} + lt: {} + lte: {} + gt: {} + gte: {} + not: + oneOf: + - {} + - $ref: '#/components/schemas/JsonNullValueFilter' + FooSelect: + type: object + properties: + id: + type: boolean + string: + type: boolean + int: + type: boolean + bigInt: + type: boolean + date: + type: boolean + float: + type: boolean + decimal: + type: boolean + boolean: + type: boolean + bytes: + type: boolean + json: + type: boolean + plainJson: + type: boolean + FooCountAggregateInput: + type: object + properties: + id: + type: boolean + string: + type: boolean + int: + type: boolean + bigInt: + type: boolean + date: + type: boolean + float: + type: boolean + decimal: + type: boolean + boolean: + type: boolean + bytes: + type: boolean + json: + type: boolean + plainJson: + type: boolean + _all: + type: boolean + FooAvgAggregateInput: + type: object + properties: + int: + type: boolean + bigInt: + type: boolean + float: + type: boolean + decimal: + type: boolean + FooSumAggregateInput: + type: object + properties: + int: + type: boolean + bigInt: + type: boolean + float: + type: boolean + decimal: + type: boolean + FooMinAggregateInput: + type: object + properties: + id: + type: boolean + string: + type: boolean + int: + type: boolean + bigInt: + type: boolean + date: + type: boolean + float: + type: boolean + decimal: + type: boolean + boolean: + type: boolean + bytes: + type: boolean + FooMaxAggregateInput: + type: object + properties: + id: + type: boolean + string: + type: boolean + int: + type: boolean + bigInt: + type: boolean + date: + type: boolean + float: + type: boolean + decimal: + type: boolean + boolean: + type: boolean + bytes: + type: boolean + AggregateFoo: + type: object + properties: + _count: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/FooCountAggregateOutputType' + _avg: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/FooAvgAggregateOutputType' + _sum: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/FooSumAggregateOutputType' + _min: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/FooMinAggregateOutputType' + _max: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/FooMaxAggregateOutputType' + FooGroupByOutputType: + type: object + properties: + id: + type: string + string: + type: string + int: + type: integer + bigInt: + type: integer + date: + type: string + format: date-time + float: + type: number + decimal: + oneOf: + - type: string + - type: number + boolean: + type: boolean + bytes: + oneOf: + - type: 'null' + - type: string + format: byte + json: + oneOf: + - type: 'null' + - {} + plainJson: {} + _count: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/FooCountAggregateOutputType' + _avg: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/FooAvgAggregateOutputType' + _sum: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/FooSumAggregateOutputType' + _min: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/FooMinAggregateOutputType' + _max: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/FooMaxAggregateOutputType' + required: + - id + - string + - int + - bigInt + - date + - float + - decimal + - boolean + - plainJson + FooCountAggregateOutputType: + type: object + properties: + id: + type: integer + string: + type: integer + int: + type: integer + bigInt: + type: integer + date: + type: integer + float: + type: integer + decimal: + type: integer + boolean: + type: integer + bytes: + type: integer + json: + type: integer + plainJson: + type: integer + _all: + type: integer + required: + - id + - string + - int + - bigInt + - date + - float + - decimal + - boolean + - bytes + - json + - plainJson + - _all + FooAvgAggregateOutputType: + type: object + properties: + int: + oneOf: + - type: 'null' + - type: number + bigInt: + oneOf: + - type: 'null' + - type: number + float: + oneOf: + - type: 'null' + - type: number + decimal: + oneOf: + - type: string + - type: number + - type: 'null' + FooSumAggregateOutputType: + type: object + properties: + int: + oneOf: + - type: 'null' + - type: integer + bigInt: + oneOf: + - type: 'null' + - type: integer + float: + oneOf: + - type: 'null' + - type: number + decimal: + oneOf: + - type: string + - type: number + - type: 'null' + FooMinAggregateOutputType: + type: object + properties: + id: + oneOf: + - type: 'null' + - type: string + string: + oneOf: + - type: 'null' + - type: string + int: + oneOf: + - type: 'null' + - type: integer + bigInt: + oneOf: + - type: 'null' + - type: integer + date: + oneOf: + - type: 'null' + - type: string + format: date-time + float: + oneOf: + - type: 'null' + - type: number + decimal: + oneOf: + - type: string + - type: number + - type: 'null' + boolean: + oneOf: + - type: 'null' + - type: boolean + bytes: + oneOf: + - type: 'null' + - type: string + format: byte + FooMaxAggregateOutputType: + type: object + properties: + id: + oneOf: + - type: 'null' + - type: string + string: + oneOf: + - type: 'null' + - type: string + int: + oneOf: + - type: 'null' + - type: integer + bigInt: + oneOf: + - type: 'null' + - type: integer + date: + oneOf: + - type: 'null' + - type: string + format: date-time + float: + oneOf: + - type: 'null' + - type: number + decimal: + oneOf: + - type: string + - type: number + - type: 'null' + boolean: + oneOf: + - type: 'null' + - type: boolean + bytes: + oneOf: + - type: 'null' + - type: string + format: byte + _Meta: + type: object + description: Meta information about the request or response + properties: + serialization: + description: Serialization metadata + additionalProperties: true + _Error: + type: object + required: + - error + properties: + error: + type: object + required: + - message + properties: + prisma: + type: boolean + description: Indicates if the error occurred during a Prisma call + rejectedByPolicy: + type: boolean + description: Indicates if the error was due to rejection by a policy + code: + type: string + description: Prisma error code. Only available when "prisma" field is true. + message: + type: string + description: Error message + reason: + type: string + description: Detailed error reason + zodErrors: + type: object + additionalProperties: true + description: Zod validation errors if the error is due to data validation + failure + additionalProperties: true + BatchPayload: + type: object + properties: + count: + type: integer + FooCreateArgs: + type: object + required: + - data + properties: + select: + $ref: '#/components/schemas/FooSelect' + data: + $ref: '#/components/schemas/FooCreateInput' + meta: + $ref: '#/components/schemas/_Meta' + FooCreateManyArgs: + type: object + required: + - data + properties: + data: + oneOf: + - $ref: '#/components/schemas/FooCreateManyInput' + - type: array + items: + $ref: '#/components/schemas/FooCreateManyInput' + skipDuplicates: + type: boolean + description: Do not insert records with unique fields or ID fields that already + exist. + meta: + $ref: '#/components/schemas/_Meta' + FooFindUniqueArgs: + type: object + required: + - where + properties: + select: + $ref: '#/components/schemas/FooSelect' + where: + $ref: '#/components/schemas/FooWhereUniqueInput' + meta: + $ref: '#/components/schemas/_Meta' + FooFindFirstArgs: + type: object + properties: + select: + $ref: '#/components/schemas/FooSelect' + where: + $ref: '#/components/schemas/FooWhereInput' + meta: + $ref: '#/components/schemas/_Meta' + FooFindManyArgs: + type: object + properties: + select: + $ref: '#/components/schemas/FooSelect' + where: + $ref: '#/components/schemas/FooWhereInput' + orderBy: + oneOf: + - $ref: '#/components/schemas/FooOrderByWithRelationInput' + - type: array + items: + $ref: '#/components/schemas/FooOrderByWithRelationInput' + cursor: + $ref: '#/components/schemas/FooWhereUniqueInput' + take: + type: integer + skip: + type: integer + meta: + $ref: '#/components/schemas/_Meta' + FooUpdateArgs: + type: object + required: + - where + - data + properties: + select: + $ref: '#/components/schemas/FooSelect' + where: + $ref: '#/components/schemas/FooWhereUniqueInput' + data: + $ref: '#/components/schemas/FooUpdateInput' + meta: + $ref: '#/components/schemas/_Meta' + FooUpdateManyArgs: + type: object + required: + - data + properties: + where: + $ref: '#/components/schemas/FooWhereInput' + data: + $ref: '#/components/schemas/FooUpdateManyMutationInput' + meta: + $ref: '#/components/schemas/_Meta' + FooUpsertArgs: + type: object + required: + - create + - update + - where + properties: + select: + $ref: '#/components/schemas/FooSelect' + where: + $ref: '#/components/schemas/FooWhereUniqueInput' + create: + $ref: '#/components/schemas/FooCreateInput' + update: + $ref: '#/components/schemas/FooUpdateInput' + meta: + $ref: '#/components/schemas/_Meta' + FooDeleteUniqueArgs: + type: object + required: + - where + properties: + select: + $ref: '#/components/schemas/FooSelect' + where: + $ref: '#/components/schemas/FooWhereUniqueInput' + meta: + $ref: '#/components/schemas/_Meta' + FooDeleteManyArgs: + type: object + properties: + where: + $ref: '#/components/schemas/FooWhereInput' + meta: + $ref: '#/components/schemas/_Meta' + FooCountArgs: + type: object + properties: + select: + $ref: '#/components/schemas/FooSelect' + where: + $ref: '#/components/schemas/FooWhereInput' + meta: + $ref: '#/components/schemas/_Meta' + FooAggregateArgs: + type: object + properties: + where: + $ref: '#/components/schemas/FooWhereInput' + orderBy: + $ref: '#/components/schemas/FooOrderByWithRelationInput' + cursor: + $ref: '#/components/schemas/FooWhereUniqueInput' + take: + type: integer + skip: + type: integer + _count: + oneOf: + - type: boolean + - $ref: '#/components/schemas/FooCountAggregateInput' + _min: + $ref: '#/components/schemas/FooMinAggregateInput' + _max: + $ref: '#/components/schemas/FooMaxAggregateInput' + _sum: + $ref: '#/components/schemas/FooSumAggregateInput' + _avg: + $ref: '#/components/schemas/FooAvgAggregateInput' + meta: + $ref: '#/components/schemas/_Meta' + FooGroupByArgs: + type: object + properties: + where: + $ref: '#/components/schemas/FooWhereInput' + orderBy: + $ref: '#/components/schemas/FooOrderByWithRelationInput' + by: + $ref: '#/components/schemas/FooScalarFieldEnum' + having: + $ref: '#/components/schemas/FooScalarWhereWithAggregatesInput' + take: + type: integer + skip: + type: integer + _count: + oneOf: + - type: boolean + - $ref: '#/components/schemas/FooCountAggregateInput' + _min: + $ref: '#/components/schemas/FooMinAggregateInput' + _max: + $ref: '#/components/schemas/FooMaxAggregateInput' + _sum: + $ref: '#/components/schemas/FooSumAggregateInput' + _avg: + $ref: '#/components/schemas/FooAvgAggregateInput' + meta: + $ref: '#/components/schemas/_Meta' +paths: + /foo/create: + post: + operationId: createFoo + description: Create a new Foo + tags: + - foo + security: [] + responses: + '201': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Foo' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/FooCreateArgs' + /foo/createMany: + post: + operationId: createManyFoo + description: Create several Foo + tags: + - foo + security: [] + responses: + '201': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BatchPayload' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/FooCreateManyArgs' + /foo/findUnique: + get: + operationId: findUniqueFoo + description: Find one unique Foo + tags: + - foo + security: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Foo' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/FooFindUniqueArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /foo/findFirst: + get: + operationId: findFirstFoo + description: Find the first Foo matching the given condition + tags: + - foo + security: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Foo' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/FooFindFirstArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /foo/findMany: + get: + operationId: findManyFoo + description: Find a list of Foo + tags: + - foo + security: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + type: array + items: + $ref: '#/components/schemas/Foo' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/FooFindManyArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /foo/update: + patch: + operationId: updateFoo + description: Update a Foo + tags: + - foo + security: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Foo' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/FooUpdateArgs' + /foo/updateMany: + patch: + operationId: updateManyFoo + description: Update Foos matching the given condition + tags: + - foo + security: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BatchPayload' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/FooUpdateManyArgs' + /foo/upsert: + post: + operationId: upsertFoo + description: Upsert a Foo + tags: + - foo + security: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Foo' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/FooUpsertArgs' + /foo/delete: + delete: + operationId: deleteFoo + description: Delete one unique Foo + tags: + - foo + security: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Foo' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/FooDeleteUniqueArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /foo/deleteMany: + delete: + operationId: deleteManyFoo + description: Delete Foos matching the given condition + tags: + - foo + security: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BatchPayload' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/FooDeleteManyArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /foo/count: + get: + operationId: countFoo + description: Find a list of Foo + tags: + - foo + security: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + oneOf: + - type: integer + - $ref: '#/components/schemas/FooCountAggregateOutputType' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/FooCountArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /foo/aggregate: + get: + operationId: aggregateFoo + description: Aggregate Foos + tags: + - foo + security: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/AggregateFoo' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/FooAggregateArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /foo/groupBy: + get: + operationId: groupByFoo + description: Group Foos by fields + tags: + - foo + security: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + type: array + items: + $ref: '#/components/schemas/FooGroupByOutputType' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/FooGroupByArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} diff --git a/packages/server/test/openapi/migrated/baseline/rest-3.1.0.baseline.yaml b/packages/server/test/openapi/migrated/baseline/rest-3.1.0.baseline.yaml new file mode 100644 index 000000000..1e331ab8e --- /dev/null +++ b/packages/server/test/openapi/migrated/baseline/rest-3.1.0.baseline.yaml @@ -0,0 +1,3279 @@ +openapi: 3.1.0 +info: + title: ZenStack Generated API + version: 1.0.0 +tags: + - name: user + description: User operations + - name: profile + description: Profile operations + - name: post_Item + description: Post-related operations + - name: postLike + description: PostLike operations +paths: + /user: + get: + operationId: list-User + description: List "User" resources + tags: + - user + parameters: + - $ref: '#/components/parameters/include' + - $ref: '#/components/parameters/sort' + - $ref: '#/components/parameters/page-offset' + - $ref: '#/components/parameters/page-limit' + - name: filter[id] + required: false + description: Id filter + in: query + style: form + explode: false + schema: + type: string + - name: filter[createdAt] + required: false + description: Equality filter for "createdAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[createdAt$lt] + required: false + description: Less-than filter for "createdAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[createdAt$lte] + required: false + description: Less-than or equal filter for "createdAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[createdAt$gt] + required: false + description: Greater-than filter for "createdAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[createdAt$gte] + required: false + description: Greater-than or equal filter for "createdAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[updatedAt] + required: false + description: Equality filter for "updatedAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[updatedAt$lt] + required: false + description: Less-than filter for "updatedAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[updatedAt$lte] + required: false + description: Less-than or equal filter for "updatedAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[updatedAt$gt] + required: false + description: Greater-than filter for "updatedAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[updatedAt$gte] + required: false + description: Greater-than or equal filter for "updatedAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[email] + required: false + description: Equality filter for "email" + in: query + style: form + explode: false + schema: + type: string + - name: filter[email$contains] + required: false + description: String contains filter for "email" + in: query + style: form + explode: false + schema: + type: string + - name: filter[email$icontains] + required: false + description: String case-insensitive contains filter for "email" + in: query + style: form + explode: false + schema: + type: string + - name: filter[email$search] + required: false + description: String full-text search filter for "email" + in: query + style: form + explode: false + schema: + type: string + - name: filter[email$startsWith] + required: false + description: String startsWith filter for "email" + in: query + style: form + explode: false + schema: + type: string + - name: filter[email$endsWith] + required: false + description: String endsWith filter for "email" + in: query + style: form + explode: false + schema: + type: string + - name: filter[role] + required: false + description: Equality filter for "role" + in: query + style: form + explode: false + schema: + $ref: '#/components/schemas/role' + - name: filter[posts] + required: false + description: Equality filter for "posts" + in: query + style: form + explode: false + schema: + type: array + items: + type: string + - name: filter[profile] + required: false + description: Equality filter for "profile" + in: query + style: form + explode: false + schema: + type: string + - name: filter[likes] + required: false + description: Equality filter for "likes" + in: query + style: form + explode: false + schema: + type: array + items: + type: string + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/UserListResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + post: + operationId: create-User + description: Create a "User" resource + tags: + - user + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/UserCreateRequest' + responses: + '201': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/UserResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '422': + description: Request is unprocessable due to validation errors + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + /user/{id}: + get: + operationId: fetch-User + description: Fetch a "User" resource + tags: + - user + parameters: + - $ref: '#/components/parameters/id' + - $ref: '#/components/parameters/include' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/UserResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + put: + operationId: update-User-put + description: Update a "User" resource + tags: + - user + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/UserUpdateRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/UserResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '422': + description: Request is unprocessable due to validation errors + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + patch: + operationId: update-User-patch + description: Update a "User" resource + tags: + - user + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/UserUpdateRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/UserResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '422': + description: Request is unprocessable due to validation errors + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + delete: + operationId: delete-User + description: Delete a "User" resource + tags: + - user + parameters: + - $ref: '#/components/parameters/id' + responses: + '200': + description: Successful operation + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + /user/{id}/posts: + get: + operationId: fetch-User-related-posts + description: Fetch the related "posts" resource for "User" + tags: + - user + parameters: + - $ref: '#/components/parameters/id' + - $ref: '#/components/parameters/include' + - $ref: '#/components/parameters/sort' + - $ref: '#/components/parameters/page-offset' + - $ref: '#/components/parameters/page-limit' + - name: filter[id] + required: false + description: Id filter + in: query + style: form + explode: false + schema: + type: string + - name: filter[createdAt] + required: false + description: Equality filter for "createdAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[createdAt$lt] + required: false + description: Less-than filter for "createdAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[createdAt$lte] + required: false + description: Less-than or equal filter for "createdAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[createdAt$gt] + required: false + description: Greater-than filter for "createdAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[createdAt$gte] + required: false + description: Greater-than or equal filter for "createdAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[updatedAt] + required: false + description: Equality filter for "updatedAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[updatedAt$lt] + required: false + description: Less-than filter for "updatedAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[updatedAt$lte] + required: false + description: Less-than or equal filter for "updatedAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[updatedAt$gt] + required: false + description: Greater-than filter for "updatedAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[updatedAt$gte] + required: false + description: Greater-than or equal filter for "updatedAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[email] + required: false + description: Equality filter for "email" + in: query + style: form + explode: false + schema: + type: string + - name: filter[email$contains] + required: false + description: String contains filter for "email" + in: query + style: form + explode: false + schema: + type: string + - name: filter[email$icontains] + required: false + description: String case-insensitive contains filter for "email" + in: query + style: form + explode: false + schema: + type: string + - name: filter[email$search] + required: false + description: String full-text search filter for "email" + in: query + style: form + explode: false + schema: + type: string + - name: filter[email$startsWith] + required: false + description: String startsWith filter for "email" + in: query + style: form + explode: false + schema: + type: string + - name: filter[email$endsWith] + required: false + description: String endsWith filter for "email" + in: query + style: form + explode: false + schema: + type: string + - name: filter[role] + required: false + description: Equality filter for "role" + in: query + style: form + explode: false + schema: + $ref: '#/components/schemas/role' + - name: filter[posts] + required: false + description: Equality filter for "posts" + in: query + style: form + explode: false + schema: + type: array + items: + type: string + - name: filter[profile] + required: false + description: Equality filter for "profile" + in: query + style: form + explode: false + schema: + type: string + - name: filter[likes] + required: false + description: Equality filter for "likes" + in: query + style: form + explode: false + schema: + type: array + items: + type: string + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/post_ItemListResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + /user/{id}/relationships/posts: + get: + operationId: fetch-User-relationship-posts + description: Fetch the "posts" relationships for a "User" + tags: + - user + parameters: + - $ref: '#/components/parameters/id' + - $ref: '#/components/parameters/sort' + - $ref: '#/components/parameters/page-offset' + - $ref: '#/components/parameters/page-limit' + - name: filter[id] + required: false + description: Id filter + in: query + style: form + explode: false + schema: + type: string + - name: filter[createdAt] + required: false + description: Equality filter for "createdAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[createdAt$lt] + required: false + description: Less-than filter for "createdAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[createdAt$lte] + required: false + description: Less-than or equal filter for "createdAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[createdAt$gt] + required: false + description: Greater-than filter for "createdAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[createdAt$gte] + required: false + description: Greater-than or equal filter for "createdAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[updatedAt] + required: false + description: Equality filter for "updatedAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[updatedAt$lt] + required: false + description: Less-than filter for "updatedAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[updatedAt$lte] + required: false + description: Less-than or equal filter for "updatedAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[updatedAt$gt] + required: false + description: Greater-than filter for "updatedAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[updatedAt$gte] + required: false + description: Greater-than or equal filter for "updatedAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[email] + required: false + description: Equality filter for "email" + in: query + style: form + explode: false + schema: + type: string + - name: filter[email$contains] + required: false + description: String contains filter for "email" + in: query + style: form + explode: false + schema: + type: string + - name: filter[email$icontains] + required: false + description: String case-insensitive contains filter for "email" + in: query + style: form + explode: false + schema: + type: string + - name: filter[email$search] + required: false + description: String full-text search filter for "email" + in: query + style: form + explode: false + schema: + type: string + - name: filter[email$startsWith] + required: false + description: String startsWith filter for "email" + in: query + style: form + explode: false + schema: + type: string + - name: filter[email$endsWith] + required: false + description: String endsWith filter for "email" + in: query + style: form + explode: false + schema: + type: string + - name: filter[role] + required: false + description: Equality filter for "role" + in: query + style: form + explode: false + schema: + $ref: '#/components/schemas/role' + - name: filter[posts] + required: false + description: Equality filter for "posts" + in: query + style: form + explode: false + schema: + type: array + items: + type: string + - name: filter[profile] + required: false + description: Equality filter for "profile" + in: query + style: form + explode: false + schema: + type: string + - name: filter[likes] + required: false + description: Equality filter for "likes" + in: query + style: form + explode: false + schema: + type: array + items: + type: string + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toManyRelationshipResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + put: + operationId: update-User-relationship-posts-put + description: Update "posts" relationships for a "User" + tags: + - user + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toManyRelationshipRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toManyRelationshipResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + patch: + operationId: update-User-relationship-posts-patch + description: Update "posts" relationships for a "User" + tags: + - user + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toManyRelationshipRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toManyRelationshipResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + post: + operationId: create-User-relationship-posts + description: Create new "posts" relationships for a "User" + tags: + - user + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toManyRelationshipRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toManyRelationshipResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + /user/{id}/profile: + get: + operationId: fetch-User-related-profile + description: Fetch the related "profile" resource for "User" + tags: + - user + parameters: + - $ref: '#/components/parameters/id' + - $ref: '#/components/parameters/include' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/ProfileResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + /user/{id}/relationships/profile: + get: + operationId: fetch-User-relationship-profile + description: Fetch the "profile" relationships for a "User" + tags: + - user + parameters: + - $ref: '#/components/parameters/id' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + put: + operationId: update-User-relationship-profile-put + description: Update "profile" relationship for a "User" + tags: + - user + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + patch: + operationId: update-User-relationship-profile-patch + description: Update "profile" relationship for a "User" + tags: + - user + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + /profile: + get: + operationId: list-Profile + description: List "Profile" resources + tags: + - profile + parameters: + - $ref: '#/components/parameters/include' + - $ref: '#/components/parameters/sort' + - $ref: '#/components/parameters/page-offset' + - $ref: '#/components/parameters/page-limit' + - name: filter[id] + required: false + description: Id filter + in: query + style: form + explode: false + schema: + type: string + - name: filter[image] + required: false + description: Equality filter for "image" + in: query + style: form + explode: false + schema: + type: string + - name: filter[image$contains] + required: false + description: String contains filter for "image" + in: query + style: form + explode: false + schema: + type: string + - name: filter[image$icontains] + required: false + description: String case-insensitive contains filter for "image" + in: query + style: form + explode: false + schema: + type: string + - name: filter[image$search] + required: false + description: String full-text search filter for "image" + in: query + style: form + explode: false + schema: + type: string + - name: filter[image$startsWith] + required: false + description: String startsWith filter for "image" + in: query + style: form + explode: false + schema: + type: string + - name: filter[image$endsWith] + required: false + description: String endsWith filter for "image" + in: query + style: form + explode: false + schema: + type: string + - name: filter[user] + required: false + description: Equality filter for "user" + in: query + style: form + explode: false + schema: + type: string + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/ProfileListResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + post: + operationId: create-Profile + description: Create a "Profile" resource + tags: + - profile + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/ProfileCreateRequest' + responses: + '201': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/ProfileResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '422': + description: Request is unprocessable due to validation errors + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + /profile/{id}: + get: + operationId: fetch-Profile + description: Fetch a "Profile" resource + tags: + - profile + parameters: + - $ref: '#/components/parameters/id' + - $ref: '#/components/parameters/include' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/ProfileResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + put: + operationId: update-Profile-put + description: Update a "Profile" resource + tags: + - profile + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/ProfileUpdateRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/ProfileResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '422': + description: Request is unprocessable due to validation errors + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + patch: + operationId: update-Profile-patch + description: Update a "Profile" resource + tags: + - profile + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/ProfileUpdateRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/ProfileResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '422': + description: Request is unprocessable due to validation errors + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + delete: + operationId: delete-Profile + description: Delete a "Profile" resource + tags: + - profile + parameters: + - $ref: '#/components/parameters/id' + responses: + '200': + description: Successful operation + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + /profile/{id}/user: + get: + operationId: fetch-Profile-related-user + description: Fetch the related "user" resource for "Profile" + tags: + - profile + parameters: + - $ref: '#/components/parameters/id' + - $ref: '#/components/parameters/include' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/UserResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + /profile/{id}/relationships/user: + get: + operationId: fetch-Profile-relationship-user + description: Fetch the "user" relationships for a "Profile" + tags: + - profile + parameters: + - $ref: '#/components/parameters/id' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + put: + operationId: update-Profile-relationship-user-put + description: Update "user" relationship for a "Profile" + tags: + - profile + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + patch: + operationId: update-Profile-relationship-user-patch + description: Update "user" relationship for a "Profile" + tags: + - profile + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + /post_Item: + get: + operationId: list-post_Item + description: List "post_Item" resources + tags: + - post_Item + parameters: + - $ref: '#/components/parameters/include' + - $ref: '#/components/parameters/sort' + - $ref: '#/components/parameters/page-offset' + - $ref: '#/components/parameters/page-limit' + - name: filter[id] + required: false + description: Id filter + in: query + style: form + explode: false + schema: + type: string + - name: filter[createdAt] + required: false + description: Equality filter for "createdAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[createdAt$lt] + required: false + description: Less-than filter for "createdAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[createdAt$lte] + required: false + description: Less-than or equal filter for "createdAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[createdAt$gt] + required: false + description: Greater-than filter for "createdAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[createdAt$gte] + required: false + description: Greater-than or equal filter for "createdAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[updatedAt] + required: false + description: Equality filter for "updatedAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[updatedAt$lt] + required: false + description: Less-than filter for "updatedAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[updatedAt$lte] + required: false + description: Less-than or equal filter for "updatedAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[updatedAt$gt] + required: false + description: Greater-than filter for "updatedAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[updatedAt$gte] + required: false + description: Greater-than or equal filter for "updatedAt" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[title] + required: false + description: Equality filter for "title" + in: query + style: form + explode: false + schema: + type: string + - name: filter[title$contains] + required: false + description: String contains filter for "title" + in: query + style: form + explode: false + schema: + type: string + - name: filter[title$icontains] + required: false + description: String case-insensitive contains filter for "title" + in: query + style: form + explode: false + schema: + type: string + - name: filter[title$search] + required: false + description: String full-text search filter for "title" + in: query + style: form + explode: false + schema: + type: string + - name: filter[title$startsWith] + required: false + description: String startsWith filter for "title" + in: query + style: form + explode: false + schema: + type: string + - name: filter[title$endsWith] + required: false + description: String endsWith filter for "title" + in: query + style: form + explode: false + schema: + type: string + - name: filter[author] + required: false + description: Equality filter for "author" + in: query + style: form + explode: false + schema: + type: string + - name: filter[published] + required: false + description: Equality filter for "published" + in: query + style: form + explode: false + schema: + type: boolean + - name: filter[viewCount] + required: false + description: Equality filter for "viewCount" + in: query + style: form + explode: false + schema: + type: integer + - name: filter[viewCount$lt] + required: false + description: Less-than filter for "viewCount" + in: query + style: form + explode: false + schema: + type: integer + - name: filter[viewCount$lte] + required: false + description: Less-than or equal filter for "viewCount" + in: query + style: form + explode: false + schema: + type: integer + - name: filter[viewCount$gt] + required: false + description: Greater-than filter for "viewCount" + in: query + style: form + explode: false + schema: + type: integer + - name: filter[viewCount$gte] + required: false + description: Greater-than or equal filter for "viewCount" + in: query + style: form + explode: false + schema: + type: integer + - name: filter[notes] + required: false + description: Equality filter for "notes" + in: query + style: form + explode: false + schema: + type: string + - name: filter[notes$contains] + required: false + description: String contains filter for "notes" + in: query + style: form + explode: false + schema: + type: string + - name: filter[notes$icontains] + required: false + description: String case-insensitive contains filter for "notes" + in: query + style: form + explode: false + schema: + type: string + - name: filter[notes$search] + required: false + description: String full-text search filter for "notes" + in: query + style: form + explode: false + schema: + type: string + - name: filter[notes$startsWith] + required: false + description: String startsWith filter for "notes" + in: query + style: form + explode: false + schema: + type: string + - name: filter[notes$endsWith] + required: false + description: String endsWith filter for "notes" + in: query + style: form + explode: false + schema: + type: string + - name: filter[likes] + required: false + description: Equality filter for "likes" + in: query + style: form + explode: false + schema: + type: array + items: + type: string + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/post_ItemListResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + post: + operationId: create-post_Item + description: Create a "post_Item" resource + tags: + - post_Item + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/post_ItemCreateRequest' + responses: + '201': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/post_ItemResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '422': + description: Request is unprocessable due to validation errors + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + /post_Item/{id}: + get: + operationId: fetch-post_Item + description: Fetch a "post_Item" resource + tags: + - post_Item + parameters: + - $ref: '#/components/parameters/id' + - $ref: '#/components/parameters/include' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/post_ItemResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + put: + operationId: update-post_Item-put + description: Update a "post_Item" resource + tags: + - post_Item + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/post_ItemUpdateRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/post_ItemResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '422': + description: Request is unprocessable due to validation errors + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + patch: + operationId: update-post_Item-patch + description: Update a "post_Item" resource + tags: + - post_Item + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/post_ItemUpdateRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/post_ItemResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '422': + description: Request is unprocessable due to validation errors + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + delete: + operationId: delete-post_Item + description: Delete a "post_Item" resource + tags: + - post_Item + parameters: + - $ref: '#/components/parameters/id' + responses: + '200': + description: Successful operation + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + /post_Item/{id}/author: + get: + operationId: fetch-post_Item-related-author + description: Fetch the related "author" resource for "post_Item" + tags: + - post_Item + parameters: + - $ref: '#/components/parameters/id' + - $ref: '#/components/parameters/include' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/UserResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + /post_Item/{id}/relationships/author: + get: + operationId: fetch-post_Item-relationship-author + description: Fetch the "author" relationships for a "post_Item" + tags: + - post_Item + parameters: + - $ref: '#/components/parameters/id' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + put: + operationId: update-post_Item-relationship-author-put + description: Update "author" relationship for a "post_Item" + tags: + - post_Item + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + patch: + operationId: update-post_Item-relationship-author-patch + description: Update "author" relationship for a "post_Item" + tags: + - post_Item + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + /postLike: + get: + operationId: list-PostLike + description: List "PostLike" resources + tags: + - postLike + parameters: + - $ref: '#/components/parameters/include' + - $ref: '#/components/parameters/sort' + - $ref: '#/components/parameters/page-offset' + - $ref: '#/components/parameters/page-limit' + - name: filter[post] + required: false + description: Equality filter for "post" + in: query + style: form + explode: false + schema: + type: string + - name: filter[user] + required: false + description: Equality filter for "user" + in: query + style: form + explode: false + schema: + type: string + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/PostLikeListResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + post: + operationId: create-PostLike + description: Create a "PostLike" resource + tags: + - postLike + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/PostLikeCreateRequest' + responses: + '201': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/PostLikeResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '422': + description: Request is unprocessable due to validation errors + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + /postLike/{id}: + get: + operationId: fetch-PostLike + description: Fetch a "PostLike" resource + tags: + - postLike + parameters: + - $ref: '#/components/parameters/id' + - $ref: '#/components/parameters/include' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/PostLikeResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + put: + operationId: update-PostLike-put + description: Update a "PostLike" resource + tags: + - postLike + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/PostLikeUpdateRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/PostLikeResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '422': + description: Request is unprocessable due to validation errors + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + patch: + operationId: update-PostLike-patch + description: Update a "PostLike" resource + tags: + - postLike + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/PostLikeUpdateRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/PostLikeResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '422': + description: Request is unprocessable due to validation errors + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + delete: + operationId: delete-PostLike + description: Delete a "PostLike" resource + tags: + - postLike + parameters: + - $ref: '#/components/parameters/id' + responses: + '200': + description: Successful operation + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + /postLike/{id}/post: + get: + operationId: fetch-PostLike-related-post + description: Fetch the related "post" resource for "PostLike" + tags: + - postLike + parameters: + - $ref: '#/components/parameters/id' + - $ref: '#/components/parameters/include' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/post_ItemResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + /postLike/{id}/relationships/post: + get: + operationId: fetch-PostLike-relationship-post + description: Fetch the "post" relationships for a "PostLike" + tags: + - postLike + parameters: + - $ref: '#/components/parameters/id' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + put: + operationId: update-PostLike-relationship-post-put + description: Update "post" relationship for a "PostLike" + tags: + - postLike + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + patch: + operationId: update-PostLike-relationship-post-patch + description: Update "post" relationship for a "PostLike" + tags: + - postLike + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + /postLike/{id}/user: + get: + operationId: fetch-PostLike-related-user + description: Fetch the related "user" resource for "PostLike" + tags: + - postLike + parameters: + - $ref: '#/components/parameters/id' + - $ref: '#/components/parameters/include' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/UserResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + /postLike/{id}/relationships/user: + get: + operationId: fetch-PostLike-relationship-user + description: Fetch the "user" relationships for a "PostLike" + tags: + - postLike + parameters: + - $ref: '#/components/parameters/id' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + put: + operationId: update-PostLike-relationship-user-put + description: Update "user" relationship for a "PostLike" + tags: + - postLike + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + patch: + operationId: update-PostLike-relationship-user-patch + description: Update "user" relationship for a "PostLike" + tags: + - postLike + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_toOneRelationshipResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' +components: + schemas: + _jsonapi: + type: object + description: An object describing the server’s implementation + required: + - version + properties: + version: + type: string + _meta: + type: object + description: Meta information about the request or response + properties: + serialization: + description: Superjson serialization metadata + additionalProperties: true + _resourceIdentifier: + type: object + description: Identifier for a resource + required: + - type + - id + properties: + type: + type: string + description: Resource type + id: + type: string + description: Resource id + _resource: + allOf: + - $ref: '#/components/schemas/_resourceIdentifier' + - type: object + description: A resource with attributes and relationships + properties: + attributes: + type: object + description: Resource attributes + relationships: + type: object + description: Resource relationships + _links: + type: object + required: + - self + description: Links related to the resource + properties: + self: + type: string + description: Link for refetching the curent results + _pagination: + type: object + description: Pagination information + required: + - first + - last + - prev + - next + properties: + first: + oneOf: + - type: 'null' + - type: string + description: Link to the first page + last: + oneOf: + - type: 'null' + - type: string + description: Link to the last page + prev: + oneOf: + - type: 'null' + - type: string + description: Link to the previous page + next: + oneOf: + - type: 'null' + - type: string + description: Link to the next page + _errors: + type: array + description: An array of error objects + items: + type: object + required: + - status + - code + properties: + status: + type: string + description: HTTP status + code: + type: string + description: Error code + prismaCode: + type: string + description: Prisma error code if the error is thrown by Prisma + title: + type: string + description: Error title + detail: + type: string + description: Error detail + reason: + type: string + description: Detailed error reason + zodErrors: + type: object + additionalProperties: true + description: Zod validation errors if the error is due to data validation + failure + _errorResponse: + type: object + required: + - errors + description: An error response + properties: + jsonapi: + $ref: '#/components/schemas/_jsonapi' + errors: + $ref: '#/components/schemas/_errors' + _relationLinks: + type: object + required: + - self + - related + description: Links related to a relationship + properties: + self: + type: string + description: Link for fetching this relationship + related: + type: string + description: Link for fetching the resource represented by this relationship + _toOneRelationship: + type: object + description: A to-one relationship + properties: + data: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/_resourceIdentifier' + _toOneRelationshipWithLinks: + type: object + required: + - links + - data + description: A to-one relationship with links + properties: + links: + $ref: '#/components/schemas/_relationLinks' + data: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/_resourceIdentifier' + _toManyRelationship: + type: object + required: + - data + description: A to-many relationship + properties: + data: + type: array + items: + $ref: '#/components/schemas/_resourceIdentifier' + _toManyRelationshipWithLinks: + type: object + required: + - links + - data + description: A to-many relationship with links + properties: + links: + $ref: '#/components/schemas/_pagedRelationLinks' + data: + type: array + items: + $ref: '#/components/schemas/_resourceIdentifier' + _pagedRelationLinks: + description: Relationship links with pagination information + allOf: + - $ref: '#/components/schemas/_pagination' + - $ref: '#/components/schemas/_relationLinks' + _toManyRelationshipRequest: + type: object + required: + - data + description: Input for manipulating a to-many relationship + properties: + data: + type: array + items: + $ref: '#/components/schemas/_resourceIdentifier' + _toOneRelationshipRequest: + description: Input for manipulating a to-one relationship + oneOf: + - type: 'null' + - type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/_resourceIdentifier' + _toManyRelationshipResponse: + description: Response for a to-many relationship + allOf: + - $ref: '#/components/schemas/_toManyRelationshipWithLinks' + - type: object + properties: + jsonapi: + $ref: '#/components/schemas/_jsonapi' + _toOneRelationshipResponse: + description: Response for a to-one relationship + allOf: + - $ref: '#/components/schemas/_toOneRelationshipWithLinks' + - type: object + properties: + jsonapi: + $ref: '#/components/schemas/_jsonapi' + role: + type: string + description: The "role" Enum + enum: + - USER + - ADMIN + User: + type: object + description: The "User" model + required: + - id + - type + - attributes + properties: + id: + type: string + type: + type: string + attributes: + type: object + properties: + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + email: + type: string + role: + $ref: '#/components/schemas/role' + required: + - createdAt + - updatedAt + - email + - role + relationships: + type: object + properties: + posts: + $ref: '#/components/schemas/_toManyRelationshipWithLinks' + profile: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/_toOneRelationshipWithLinks' + UserCreateRequest: + type: object + description: Input for creating a "User" + required: + - data + properties: + data: + type: object + description: The "User" model + required: + - type + - attributes + properties: + type: + type: string + attributes: + type: object + required: + - updatedAt + - email + properties: + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + email: + type: string + role: + $ref: '#/components/schemas/role' + relationships: + type: object + properties: + posts: + $ref: '#/components/schemas/_toManyRelationship' + profile: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/_toOneRelationship' + meta: + $ref: '#/components/schemas/_meta' + UserUpdateRequest: + type: object + description: Input for updating a "User" + required: + - data + properties: + data: + type: object + description: The "User" model + required: + - id + - type + - attributes + properties: + id: + type: string + type: + type: string + attributes: + type: object + properties: + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + email: + type: string + role: + $ref: '#/components/schemas/role' + relationships: + type: object + properties: + posts: + $ref: '#/components/schemas/_toManyRelationship' + profile: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/_toOneRelationship' + meta: + $ref: '#/components/schemas/_meta' + UserResponse: + type: object + description: Response for a "User" + required: + - data + properties: + jsonapi: + $ref: '#/components/schemas/_jsonapi' + data: + allOf: + - $ref: '#/components/schemas/User' + - type: object + properties: + relationships: + type: object + properties: &a1 + posts: + $ref: '#/components/schemas/_toManyRelationship' + profile: + $ref: '#/components/schemas/_toOneRelationship' + meta: + $ref: '#/components/schemas/_meta' + included: + type: array + items: + $ref: '#/components/schemas/_resource' + links: + $ref: '#/components/schemas/_links' + UserListResponse: + type: object + description: Response for a list of "User" + required: + - data + - links + properties: + jsonapi: + $ref: '#/components/schemas/_jsonapi' + data: + type: array + items: + allOf: + - $ref: '#/components/schemas/User' + - type: object + properties: + relationships: + type: object + properties: *a1 + meta: + $ref: '#/components/schemas/_meta' + included: + type: array + items: + $ref: '#/components/schemas/_resource' + links: + allOf: + - $ref: '#/components/schemas/_links' + - $ref: '#/components/schemas/_pagination' + Profile: + type: object + description: The "Profile" model + required: + - id + - type + - attributes + properties: + id: + type: string + type: + type: string + attributes: + type: object + properties: + image: + oneOf: + - type: 'null' + - type: string + userId: + type: string + required: + - image + - userId + relationships: + type: object + properties: + user: + $ref: '#/components/schemas/_toOneRelationshipWithLinks' + ProfileCreateRequest: + type: object + description: Input for creating a "Profile" + required: + - data + properties: + data: + type: object + description: The "Profile" model + required: + - type + - attributes + properties: + type: + type: string + attributes: + type: object + properties: + image: + oneOf: + - type: 'null' + - type: string + relationships: + type: object + properties: + user: + $ref: '#/components/schemas/_toOneRelationship' + meta: + $ref: '#/components/schemas/_meta' + ProfileUpdateRequest: + type: object + description: Input for updating a "Profile" + required: + - data + properties: + data: + type: object + description: The "Profile" model + required: + - id + - type + - attributes + properties: + id: + type: string + type: + type: string + attributes: + type: object + properties: + image: + oneOf: + - type: 'null' + - type: string + relationships: + type: object + properties: + user: + $ref: '#/components/schemas/_toOneRelationship' + meta: + $ref: '#/components/schemas/_meta' + ProfileResponse: + type: object + description: Response for a "Profile" + required: + - data + properties: + jsonapi: + $ref: '#/components/schemas/_jsonapi' + data: + allOf: + - $ref: '#/components/schemas/Profile' + - type: object + properties: + relationships: + type: object + properties: &a2 + user: + $ref: '#/components/schemas/_toOneRelationship' + meta: + $ref: '#/components/schemas/_meta' + included: + type: array + items: + $ref: '#/components/schemas/_resource' + links: + $ref: '#/components/schemas/_links' + ProfileListResponse: + type: object + description: Response for a list of "Profile" + required: + - data + - links + properties: + jsonapi: + $ref: '#/components/schemas/_jsonapi' + data: + type: array + items: + allOf: + - $ref: '#/components/schemas/Profile' + - type: object + properties: + relationships: + type: object + properties: *a2 + meta: + $ref: '#/components/schemas/_meta' + included: + type: array + items: + $ref: '#/components/schemas/_resource' + links: + allOf: + - $ref: '#/components/schemas/_links' + - $ref: '#/components/schemas/_pagination' + post_Item: + type: object + description: The "post_Item" model + required: + - id + - type + - attributes + properties: + id: + type: string + type: + type: string + attributes: + type: object + properties: + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + title: + type: string + authorId: + oneOf: + - type: 'null' + - type: string + published: + type: boolean + viewCount: + type: integer + notes: + oneOf: + - type: 'null' + - type: string + required: + - createdAt + - updatedAt + - title + - authorId + - published + - viewCount + - notes + relationships: + type: object + properties: + author: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/_toOneRelationshipWithLinks' + post_ItemCreateRequest: + type: object + description: Input for creating a "post_Item" + required: + - data + properties: + data: + type: object + description: The "post_Item" model + required: + - id + - type + - attributes + properties: + id: + type: string + type: + type: string + attributes: + type: object + required: + - updatedAt + - title + properties: + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + title: + type: string + published: + type: boolean + viewCount: + type: integer + notes: + oneOf: + - type: 'null' + - type: string + relationships: + type: object + properties: + author: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/_toOneRelationship' + meta: + $ref: '#/components/schemas/_meta' + post_ItemUpdateRequest: + type: object + description: Input for updating a "post_Item" + required: + - data + properties: + data: + type: object + description: The "post_Item" model + required: + - id + - type + - attributes + properties: + id: + type: string + type: + type: string + attributes: + type: object + properties: + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + title: + type: string + published: + type: boolean + viewCount: + type: integer + notes: + oneOf: + - type: 'null' + - type: string + relationships: + type: object + properties: + author: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/_toOneRelationship' + meta: + $ref: '#/components/schemas/_meta' + post_ItemResponse: + type: object + description: Response for a "post_Item" + required: + - data + properties: + jsonapi: + $ref: '#/components/schemas/_jsonapi' + data: + allOf: + - $ref: '#/components/schemas/post_Item' + - type: object + properties: + relationships: + type: object + properties: &a3 + author: + $ref: '#/components/schemas/_toOneRelationship' + meta: + $ref: '#/components/schemas/_meta' + included: + type: array + items: + $ref: '#/components/schemas/_resource' + links: + $ref: '#/components/schemas/_links' + post_ItemListResponse: + type: object + description: Response for a list of "post_Item" + required: + - data + - links + properties: + jsonapi: + $ref: '#/components/schemas/_jsonapi' + data: + type: array + items: + allOf: + - $ref: '#/components/schemas/post_Item' + - type: object + properties: + relationships: + type: object + properties: *a3 + meta: + $ref: '#/components/schemas/_meta' + included: + type: array + items: + $ref: '#/components/schemas/_resource' + links: + allOf: + - $ref: '#/components/schemas/_links' + - $ref: '#/components/schemas/_pagination' + PostLike: + type: object + description: The "PostLike" model + required: + - id + - type + - attributes + properties: + id: + type: string + type: + type: string + attributes: + type: object + properties: + postId: + type: string + userId: + type: string + required: + - postId + - userId + relationships: + type: object + properties: + post: + $ref: '#/components/schemas/_toOneRelationshipWithLinks' + user: + $ref: '#/components/schemas/_toOneRelationshipWithLinks' + PostLikeCreateRequest: + type: object + description: Input for creating a "PostLike" + required: + - data + properties: + data: + type: object + description: The "PostLike" model + required: + - type + - attributes + properties: + type: + type: string + relationships: + type: object + properties: + post: + $ref: '#/components/schemas/_toOneRelationship' + user: + $ref: '#/components/schemas/_toOneRelationship' + meta: + $ref: '#/components/schemas/_meta' + PostLikeUpdateRequest: + type: object + description: Input for updating a "PostLike" + required: + - data + properties: + data: + type: object + description: The "PostLike" model + required: + - id + - type + - attributes + properties: + id: + type: string + type: + type: string + relationships: + type: object + properties: + post: + $ref: '#/components/schemas/_toOneRelationship' + user: + $ref: '#/components/schemas/_toOneRelationship' + meta: + $ref: '#/components/schemas/_meta' + PostLikeResponse: + type: object + description: Response for a "PostLike" + required: + - data + properties: + jsonapi: + $ref: '#/components/schemas/_jsonapi' + data: + allOf: + - $ref: '#/components/schemas/PostLike' + - type: object + properties: + relationships: + type: object + properties: + post: + $ref: '#/components/schemas/_toOneRelationship' + user: + $ref: '#/components/schemas/_toOneRelationship' + meta: + $ref: '#/components/schemas/_meta' + included: + type: array + items: + $ref: '#/components/schemas/_resource' + links: + $ref: '#/components/schemas/_links' + PostLikeListResponse: + type: object + description: Response for a list of "PostLike" + required: + - data + - links + properties: + jsonapi: + $ref: '#/components/schemas/_jsonapi' + data: + type: array + items: + allOf: + - $ref: '#/components/schemas/PostLike' + - type: object + properties: + relationships: + type: object + properties: + post: + $ref: '#/components/schemas/_toOneRelationship' + user: + $ref: '#/components/schemas/_toOneRelationship' + meta: + $ref: '#/components/schemas/_meta' + included: + type: array + items: + $ref: '#/components/schemas/_resource' + links: + allOf: + - $ref: '#/components/schemas/_links' + - $ref: '#/components/schemas/_pagination' + parameters: + id: + name: id + in: path + description: The resource id + required: true + schema: + type: string + include: + name: include + in: query + description: Relationships to include + required: false + style: form + schema: + type: string + sort: + name: sort + in: query + description: Fields to sort by + required: false + style: form + schema: + type: string + page-offset: + name: page[offset] + in: query + description: Offset for pagination + required: false + style: form + schema: + type: integer + page-limit: + name: page[limit] + in: query + description: Limit for pagination + required: false + style: form + schema: + type: integer diff --git a/packages/server/test/openapi/migrated/baseline/rest-type-coverage-3.1.0.baseline.yaml b/packages/server/test/openapi/migrated/baseline/rest-type-coverage-3.1.0.baseline.yaml new file mode 100644 index 000000000..6d41ebdf6 --- /dev/null +++ b/packages/server/test/openapi/migrated/baseline/rest-type-coverage-3.1.0.baseline.yaml @@ -0,0 +1,876 @@ +openapi: 3.1.0 +info: + title: ZenStack Generated API + version: 1.0.0 +tags: + - name: foo + description: Foo operations +paths: + /foo: + get: + operationId: list-Foo + description: List "Foo" resources + tags: + - foo + parameters: + - $ref: '#/components/parameters/include' + - $ref: '#/components/parameters/sort' + - $ref: '#/components/parameters/page-offset' + - $ref: '#/components/parameters/page-limit' + - name: filter[id] + required: false + description: Id filter + in: query + style: form + explode: false + schema: + type: string + - name: filter[string] + required: false + description: Equality filter for "string" + in: query + style: form + explode: false + schema: + type: string + - name: filter[string$contains] + required: false + description: String contains filter for "string" + in: query + style: form + explode: false + schema: + type: string + - name: filter[string$icontains] + required: false + description: String case-insensitive contains filter for "string" + in: query + style: form + explode: false + schema: + type: string + - name: filter[string$search] + required: false + description: String full-text search filter for "string" + in: query + style: form + explode: false + schema: + type: string + - name: filter[string$startsWith] + required: false + description: String startsWith filter for "string" + in: query + style: form + explode: false + schema: + type: string + - name: filter[string$endsWith] + required: false + description: String endsWith filter for "string" + in: query + style: form + explode: false + schema: + type: string + - name: filter[int] + required: false + description: Equality filter for "int" + in: query + style: form + explode: false + schema: + type: integer + - name: filter[int$lt] + required: false + description: Less-than filter for "int" + in: query + style: form + explode: false + schema: + type: integer + - name: filter[int$lte] + required: false + description: Less-than or equal filter for "int" + in: query + style: form + explode: false + schema: + type: integer + - name: filter[int$gt] + required: false + description: Greater-than filter for "int" + in: query + style: form + explode: false + schema: + type: integer + - name: filter[int$gte] + required: false + description: Greater-than or equal filter for "int" + in: query + style: form + explode: false + schema: + type: integer + - name: filter[bigInt] + required: false + description: Equality filter for "bigInt" + in: query + style: form + explode: false + schema: + type: integer + - name: filter[bigInt$lt] + required: false + description: Less-than filter for "bigInt" + in: query + style: form + explode: false + schema: + type: integer + - name: filter[bigInt$lte] + required: false + description: Less-than or equal filter for "bigInt" + in: query + style: form + explode: false + schema: + type: integer + - name: filter[bigInt$gt] + required: false + description: Greater-than filter for "bigInt" + in: query + style: form + explode: false + schema: + type: integer + - name: filter[bigInt$gte] + required: false + description: Greater-than or equal filter for "bigInt" + in: query + style: form + explode: false + schema: + type: integer + - name: filter[date] + required: false + description: Equality filter for "date" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[date$lt] + required: false + description: Less-than filter for "date" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[date$lte] + required: false + description: Less-than or equal filter for "date" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[date$gt] + required: false + description: Greater-than filter for "date" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[date$gte] + required: false + description: Greater-than or equal filter for "date" + in: query + style: form + explode: false + schema: + type: string + format: date-time + - name: filter[float] + required: false + description: Equality filter for "float" + in: query + style: form + explode: false + schema: + type: number + - name: filter[float$lt] + required: false + description: Less-than filter for "float" + in: query + style: form + explode: false + schema: + type: number + - name: filter[float$lte] + required: false + description: Less-than or equal filter for "float" + in: query + style: form + explode: false + schema: + type: number + - name: filter[float$gt] + required: false + description: Greater-than filter for "float" + in: query + style: form + explode: false + schema: + type: number + - name: filter[float$gte] + required: false + description: Greater-than or equal filter for "float" + in: query + style: form + explode: false + schema: + type: number + - name: filter[decimal] + required: false + description: Equality filter for "decimal" + in: query + style: form + explode: false + schema: + oneOf: + - type: number + - type: string + - name: filter[decimal$lt] + required: false + description: Less-than filter for "decimal" + in: query + style: form + explode: false + schema: + oneOf: + - type: number + - type: string + - name: filter[decimal$lte] + required: false + description: Less-than or equal filter for "decimal" + in: query + style: form + explode: false + schema: + oneOf: + - type: number + - type: string + - name: filter[decimal$gt] + required: false + description: Greater-than filter for "decimal" + in: query + style: form + explode: false + schema: + oneOf: + - type: number + - type: string + - name: filter[decimal$gte] + required: false + description: Greater-than or equal filter for "decimal" + in: query + style: form + explode: false + schema: + oneOf: + - type: number + - type: string + - name: filter[boolean] + required: false + description: Equality filter for "boolean" + in: query + style: form + explode: false + schema: + type: boolean + - name: filter[bytes] + required: false + description: Equality filter for "bytes" + in: query + style: form + explode: false + schema: + type: string + format: byte + description: Base64 encoded byte array + - name: filter[json] + required: false + description: Equality filter for "json" + in: query + style: form + explode: false + schema: + type: string + format: json + - name: filter[plainJson] + required: false + description: Equality filter for "plainJson" + in: query + style: form + explode: false + schema: + type: string + format: json + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/FooListResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + security: [] + post: + operationId: create-Foo + description: Create a "Foo" resource + tags: + - foo + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/FooCreateRequest' + responses: + '201': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/FooResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '422': + description: Request is unprocessable due to validation errors + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + security: [] + /foo/{id}: + get: + operationId: fetch-Foo + description: Fetch a "Foo" resource + tags: + - foo + parameters: + - $ref: '#/components/parameters/id' + - $ref: '#/components/parameters/include' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/FooResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + security: [] + put: + operationId: update-Foo-put + description: Update a "Foo" resource + tags: + - foo + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/FooUpdateRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/FooResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '422': + description: Request is unprocessable due to validation errors + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + security: [] + patch: + operationId: update-Foo-patch + description: Update a "Foo" resource + tags: + - foo + parameters: + - $ref: '#/components/parameters/id' + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/FooUpdateRequest' + responses: + '200': + description: Successful operation + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/FooResponse' + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '422': + description: Request is unprocessable due to validation errors + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + security: [] + delete: + operationId: delete-Foo + description: Delete a "Foo" resource + tags: + - foo + parameters: + - $ref: '#/components/parameters/id' + responses: + '200': + description: Successful operation + '403': + description: Request is forbidden + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + '404': + description: Resource is not found + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/_errorResponse' + security: [] +components: + schemas: + _jsonapi: + type: object + description: An object describing the server’s implementation + required: + - version + properties: + version: + type: string + _meta: + type: object + description: Meta information about the request or response + properties: + serialization: + description: Superjson serialization metadata + additionalProperties: true + _resourceIdentifier: + type: object + description: Identifier for a resource + required: + - type + - id + properties: + type: + type: string + description: Resource type + id: + type: string + description: Resource id + _resource: + allOf: + - $ref: '#/components/schemas/_resourceIdentifier' + - type: object + description: A resource with attributes and relationships + properties: + attributes: + type: object + description: Resource attributes + relationships: + type: object + description: Resource relationships + _links: + type: object + required: + - self + description: Links related to the resource + properties: + self: + type: string + description: Link for refetching the curent results + _pagination: + type: object + description: Pagination information + required: + - first + - last + - prev + - next + properties: + first: + oneOf: + - type: 'null' + - type: string + description: Link to the first page + last: + oneOf: + - type: 'null' + - type: string + description: Link to the last page + prev: + oneOf: + - type: 'null' + - type: string + description: Link to the previous page + next: + oneOf: + - type: 'null' + - type: string + description: Link to the next page + _errors: + type: array + description: An array of error objects + items: + type: object + required: + - status + - code + properties: + status: + type: string + description: HTTP status + code: + type: string + description: Error code + prismaCode: + type: string + description: Prisma error code if the error is thrown by Prisma + title: + type: string + description: Error title + detail: + type: string + description: Error detail + reason: + type: string + description: Detailed error reason + zodErrors: + type: object + additionalProperties: true + description: Zod validation errors if the error is due to data validation + failure + _errorResponse: + type: object + required: + - errors + description: An error response + properties: + jsonapi: + $ref: '#/components/schemas/_jsonapi' + errors: + $ref: '#/components/schemas/_errors' + Foo: + type: object + description: The "Foo" model + required: + - id + - type + - attributes + properties: + id: + type: string + type: + type: string + attributes: + type: object + required: + - string + - int + - bigInt + - date + - float + - decimal + - boolean + - bytes + - json + - plainJson + properties: + string: + type: string + int: + type: integer + bigInt: + type: integer + date: + type: string + format: date-time + float: + type: number + decimal: + oneOf: + - type: number + - type: string + boolean: + type: boolean + bytes: + type: string + format: byte + description: Base64 encoded byte array + json: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Meta' + plainJson: {} + FooCreateRequest: + type: object + description: Input for creating a "Foo" + required: + - data + properties: + data: + type: object + description: The "Foo" model + required: + - type + - attributes + properties: + type: + type: string + attributes: + type: object + required: + - string + - int + - bigInt + - date + - float + - decimal + - boolean + - bytes + - plainJson + properties: + string: + type: string + int: + type: integer + bigInt: + type: integer + date: + type: string + format: date-time + float: + type: number + decimal: + oneOf: + - type: number + - type: string + boolean: + type: boolean + bytes: + type: string + format: byte + description: Base64 encoded byte array + json: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Meta' + plainJson: {} + meta: + $ref: '#/components/schemas/_meta' + FooUpdateRequest: + type: object + description: Input for updating a "Foo" + required: + - data + properties: + data: + type: object + description: The "Foo" model + required: + - id + - type + - attributes + properties: + id: + type: string + type: + type: string + attributes: + type: object + properties: + string: + type: string + int: + type: integer + bigInt: + type: integer + date: + type: string + format: date-time + float: + type: number + decimal: + oneOf: + - type: number + - type: string + boolean: + type: boolean + bytes: + type: string + format: byte + description: Base64 encoded byte array + json: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Meta' + plainJson: {} + meta: + $ref: '#/components/schemas/_meta' + FooResponse: + type: object + description: Response for a "Foo" + required: + - data + properties: + jsonapi: + $ref: '#/components/schemas/_jsonapi' + data: + allOf: + - $ref: '#/components/schemas/Foo' + - type: object + properties: + relationships: + type: object + properties: &a1 {} + meta: + $ref: '#/components/schemas/_meta' + included: + type: array + items: + $ref: '#/components/schemas/_resource' + links: + $ref: '#/components/schemas/_links' + FooListResponse: + type: object + description: Response for a list of "Foo" + required: + - data + - links + properties: + jsonapi: + $ref: '#/components/schemas/_jsonapi' + data: + type: array + items: + allOf: + - $ref: '#/components/schemas/Foo' + - type: object + properties: + relationships: + type: object + properties: *a1 + meta: + $ref: '#/components/schemas/_meta' + included: + type: array + items: + $ref: '#/components/schemas/_resource' + links: + allOf: + - $ref: '#/components/schemas/_links' + - $ref: '#/components/schemas/_pagination' + Meta: + type: object + description: The "Meta" TypeDef + properties: + something: + type: string + parameters: + id: + name: id + in: path + description: The resource id + required: true + schema: + type: string + include: + name: include + in: query + description: Relationships to include + required: false + style: form + schema: + type: string + sort: + name: sort + in: query + description: Fields to sort by + required: false + style: form + schema: + type: string + page-offset: + name: page[offset] + in: query + description: Offset for pagination + required: false + style: form + schema: + type: integer + page-limit: + name: page[limit] + in: query + description: Limit for pagination + required: false + style: form + schema: + type: integer diff --git a/packages/server/test/openapi/migrated/baseline/rpc-3.1.0-omit.baseline.yaml b/packages/server/test/openapi/migrated/baseline/rpc-3.1.0-omit.baseline.yaml new file mode 100644 index 000000000..11369e7d0 --- /dev/null +++ b/packages/server/test/openapi/migrated/baseline/rpc-3.1.0-omit.baseline.yaml @@ -0,0 +1,3058 @@ +openapi: 3.1.0 +info: + title: ZenStack Generated API + version: 1.0.0 +tags: + - name: user + description: User operations + - name: profile + description: Profile operations + - name: post_Item + description: Post-related operations +components: + schemas: + _AnyObject: + type: object + additionalProperties: true + Role: + type: string + enum: + - USER + - ADMIN + User: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + email: + type: string + role: + $ref: '#/components/schemas/Role' + posts: + type: array + items: + $ref: '#/components/schemas/Post_Item' + profile: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Profile' + required: + - id + - createdAt + - updatedAt + - email + - role + Profile: + type: object + properties: + id: + type: string + image: + oneOf: + - type: 'null' + - type: string + user: + $ref: '#/components/schemas/User' + userId: + type: string + required: + - id + - user + - userId + Post_Item: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + title: + type: string + author: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/User' + authorId: + oneOf: + - type: 'null' + - type: string + published: + type: boolean + viewCount: + type: integer + notes: + oneOf: + - type: 'null' + - type: string + required: + - id + - createdAt + - updatedAt + - title + - published + - viewCount + AggregateUser: + type: object + properties: + _count: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/UserCountAggregateOutputType' + _min: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/UserMinAggregateOutputType' + _max: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/UserMaxAggregateOutputType' + UserGroupByOutputType: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + email: + type: string + role: + $ref: '#/components/schemas/Role' + _count: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/UserCountAggregateOutputType' + _min: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/UserMinAggregateOutputType' + _max: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/UserMaxAggregateOutputType' + required: + - id + - createdAt + - updatedAt + - email + - role + AggregateProfile: + type: object + properties: + _count: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/ProfileCountAggregateOutputType' + _min: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/ProfileMinAggregateOutputType' + _max: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/ProfileMaxAggregateOutputType' + ProfileGroupByOutputType: + type: object + properties: + id: + type: string + image: + oneOf: + - type: 'null' + - type: string + userId: + type: string + _count: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/ProfileCountAggregateOutputType' + _min: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/ProfileMinAggregateOutputType' + _max: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/ProfileMaxAggregateOutputType' + required: + - id + - userId + AggregatePost_Item: + type: object + properties: + _count: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Post_ItemCountAggregateOutputType' + _avg: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Post_ItemAvgAggregateOutputType' + _sum: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Post_ItemSumAggregateOutputType' + _min: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Post_ItemMinAggregateOutputType' + _max: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Post_ItemMaxAggregateOutputType' + Post_ItemGroupByOutputType: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + title: + type: string + authorId: + oneOf: + - type: 'null' + - type: string + published: + type: boolean + viewCount: + type: integer + notes: + oneOf: + - type: 'null' + - type: string + _count: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Post_ItemCountAggregateOutputType' + _avg: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Post_ItemAvgAggregateOutputType' + _sum: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Post_ItemSumAggregateOutputType' + _min: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Post_ItemMinAggregateOutputType' + _max: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Post_ItemMaxAggregateOutputType' + required: + - id + - createdAt + - updatedAt + - title + - published + - viewCount + UserCountAggregateOutputType: + type: object + properties: + id: + type: integer + createdAt: + type: integer + updatedAt: + type: integer + email: + type: integer + role: + type: integer + _all: + type: integer + required: + - id + - createdAt + - updatedAt + - email + - role + - _all + UserMinAggregateOutputType: + type: object + properties: + id: + oneOf: + - type: 'null' + - type: string + createdAt: + oneOf: + - type: 'null' + - type: string + format: date-time + updatedAt: + oneOf: + - type: 'null' + - type: string + format: date-time + email: + oneOf: + - type: 'null' + - type: string + role: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Role' + UserMaxAggregateOutputType: + type: object + properties: + id: + oneOf: + - type: 'null' + - type: string + createdAt: + oneOf: + - type: 'null' + - type: string + format: date-time + updatedAt: + oneOf: + - type: 'null' + - type: string + format: date-time + email: + oneOf: + - type: 'null' + - type: string + role: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Role' + ProfileCountAggregateOutputType: + type: object + properties: + id: + type: integer + image: + type: integer + userId: + type: integer + _all: + type: integer + required: + - id + - image + - userId + - _all + ProfileMinAggregateOutputType: + type: object + properties: + id: + oneOf: + - type: 'null' + - type: string + image: + oneOf: + - type: 'null' + - type: string + userId: + oneOf: + - type: 'null' + - type: string + ProfileMaxAggregateOutputType: + type: object + properties: + id: + oneOf: + - type: 'null' + - type: string + image: + oneOf: + - type: 'null' + - type: string + userId: + oneOf: + - type: 'null' + - type: string + Post_ItemCountAggregateOutputType: + type: object + properties: + id: + type: integer + createdAt: + type: integer + updatedAt: + type: integer + title: + type: integer + authorId: + type: integer + published: + type: integer + viewCount: + type: integer + notes: + type: integer + _all: + type: integer + required: + - id + - createdAt + - updatedAt + - title + - authorId + - published + - viewCount + - notes + - _all + Post_ItemAvgAggregateOutputType: + type: object + properties: + viewCount: + oneOf: + - type: 'null' + - type: number + Post_ItemSumAggregateOutputType: + type: object + properties: + viewCount: + oneOf: + - type: 'null' + - type: integer + Post_ItemMinAggregateOutputType: + type: object + properties: + id: + oneOf: + - type: 'null' + - type: string + createdAt: + oneOf: + - type: 'null' + - type: string + format: date-time + updatedAt: + oneOf: + - type: 'null' + - type: string + format: date-time + title: + oneOf: + - type: 'null' + - type: string + authorId: + oneOf: + - type: 'null' + - type: string + published: + oneOf: + - type: 'null' + - type: boolean + viewCount: + oneOf: + - type: 'null' + - type: integer + notes: + oneOf: + - type: 'null' + - type: string + Post_ItemMaxAggregateOutputType: + type: object + properties: + id: + oneOf: + - type: 'null' + - type: string + createdAt: + oneOf: + - type: 'null' + - type: string + format: date-time + updatedAt: + oneOf: + - type: 'null' + - type: string + format: date-time + title: + oneOf: + - type: 'null' + - type: string + authorId: + oneOf: + - type: 'null' + - type: string + published: + oneOf: + - type: 'null' + - type: boolean + viewCount: + oneOf: + - type: 'null' + - type: integer + notes: + oneOf: + - type: 'null' + - type: string + _Meta: + type: object + description: Meta information about the request or response + properties: + serialization: + description: Serialization metadata + additionalProperties: true + _Error: + type: object + required: + - error + properties: + error: + type: object + required: + - message + properties: + prisma: + type: boolean + description: Indicates if the error occurred during a Prisma call + rejectedByPolicy: + type: boolean + description: Indicates if the error was due to rejection by a policy + code: + type: string + description: Prisma error code. Only available when "prisma" field is true. + message: + type: string + description: Error message + reason: + type: string + description: Detailed error reason + zodErrors: + type: object + additionalProperties: true + description: Zod validation errors if the error is due to data validation + failure + additionalProperties: true + BatchPayload: + type: object + properties: + count: + type: integer + UserCreateArgs: + type: object + required: + - data + properties: + select: + $ref: '#/components/schemas/_AnyObject' + include: + $ref: '#/components/schemas/_AnyObject' + data: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + UserCreateManyArgs: + type: object + required: + - data + properties: + data: + oneOf: + - $ref: '#/components/schemas/_AnyObject' + - type: array + items: + $ref: '#/components/schemas/_AnyObject' + skipDuplicates: + type: boolean + description: Do not insert records with unique fields or ID fields that already + exist. + meta: + $ref: '#/components/schemas/_Meta' + UserFindUniqueArgs: + type: object + required: + - where + properties: + select: + $ref: '#/components/schemas/_AnyObject' + include: + $ref: '#/components/schemas/_AnyObject' + where: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + UserFindFirstArgs: + type: object + properties: + select: + $ref: '#/components/schemas/_AnyObject' + include: + $ref: '#/components/schemas/_AnyObject' + where: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + UserFindManyArgs: + type: object + properties: + select: + $ref: '#/components/schemas/_AnyObject' + include: + $ref: '#/components/schemas/_AnyObject' + where: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + orderBy: + oneOf: + - $ref: '#/components/schemas/_AnyObject' + - type: array + items: + $ref: '#/components/schemas/_AnyObject' + cursor: + $ref: '#/components/schemas/_AnyObject' + take: + type: integer + skip: + type: integer + UserUpdateArgs: + type: object + required: + - where + - data + properties: + select: + $ref: '#/components/schemas/_AnyObject' + include: + $ref: '#/components/schemas/_AnyObject' + where: + $ref: '#/components/schemas/_AnyObject' + data: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + UserUpdateManyArgs: + type: object + required: + - data + properties: + where: + $ref: '#/components/schemas/_AnyObject' + data: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + UserUpsertArgs: + type: object + required: + - create + - update + - where + properties: + select: + $ref: '#/components/schemas/_AnyObject' + include: + $ref: '#/components/schemas/_AnyObject' + where: + $ref: '#/components/schemas/_AnyObject' + create: + $ref: '#/components/schemas/_AnyObject' + update: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + UserDeleteUniqueArgs: + type: object + required: + - where + properties: + select: + $ref: '#/components/schemas/_AnyObject' + include: + $ref: '#/components/schemas/_AnyObject' + where: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + UserDeleteManyArgs: + type: object + properties: + where: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + UserCountArgs: + type: object + properties: + select: + $ref: '#/components/schemas/_AnyObject' + where: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + UserAggregateArgs: + type: object + properties: + where: + $ref: '#/components/schemas/_AnyObject' + orderBy: + $ref: '#/components/schemas/_AnyObject' + cursor: + $ref: '#/components/schemas/_AnyObject' + take: + type: integer + skip: + type: integer + _count: + oneOf: + - type: boolean + - $ref: '#/components/schemas/_AnyObject' + _min: + $ref: '#/components/schemas/_AnyObject' + _max: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + UserGroupByArgs: + type: object + properties: + where: + $ref: '#/components/schemas/_AnyObject' + orderBy: + $ref: '#/components/schemas/_AnyObject' + by: + $ref: '#/components/schemas/_AnyObject' + having: + $ref: '#/components/schemas/_AnyObject' + take: + type: integer + skip: + type: integer + _count: + oneOf: + - type: boolean + - $ref: '#/components/schemas/_AnyObject' + _min: + $ref: '#/components/schemas/_AnyObject' + _max: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + ProfileCreateArgs: + type: object + required: + - data + properties: + select: + $ref: '#/components/schemas/_AnyObject' + include: + $ref: '#/components/schemas/_AnyObject' + data: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + ProfileCreateManyArgs: + type: object + required: + - data + properties: + data: + oneOf: + - $ref: '#/components/schemas/_AnyObject' + - type: array + items: + $ref: '#/components/schemas/_AnyObject' + skipDuplicates: + type: boolean + description: Do not insert records with unique fields or ID fields that already + exist. + meta: + $ref: '#/components/schemas/_Meta' + ProfileFindUniqueArgs: + type: object + required: + - where + properties: + select: + $ref: '#/components/schemas/_AnyObject' + include: + $ref: '#/components/schemas/_AnyObject' + where: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + ProfileFindFirstArgs: + type: object + properties: + select: + $ref: '#/components/schemas/_AnyObject' + include: + $ref: '#/components/schemas/_AnyObject' + where: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + ProfileFindManyArgs: + type: object + properties: + select: + $ref: '#/components/schemas/_AnyObject' + include: + $ref: '#/components/schemas/_AnyObject' + where: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + orderBy: + oneOf: + - $ref: '#/components/schemas/_AnyObject' + - type: array + items: + $ref: '#/components/schemas/_AnyObject' + cursor: + $ref: '#/components/schemas/_AnyObject' + take: + type: integer + skip: + type: integer + ProfileUpdateArgs: + type: object + required: + - where + - data + properties: + select: + $ref: '#/components/schemas/_AnyObject' + include: + $ref: '#/components/schemas/_AnyObject' + where: + $ref: '#/components/schemas/_AnyObject' + data: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + ProfileUpdateManyArgs: + type: object + required: + - data + properties: + where: + $ref: '#/components/schemas/_AnyObject' + data: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + ProfileUpsertArgs: + type: object + required: + - create + - update + - where + properties: + select: + $ref: '#/components/schemas/_AnyObject' + include: + $ref: '#/components/schemas/_AnyObject' + where: + $ref: '#/components/schemas/_AnyObject' + create: + $ref: '#/components/schemas/_AnyObject' + update: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + ProfileDeleteUniqueArgs: + type: object + required: + - where + properties: + select: + $ref: '#/components/schemas/_AnyObject' + include: + $ref: '#/components/schemas/_AnyObject' + where: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + ProfileDeleteManyArgs: + type: object + properties: + where: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + ProfileCountArgs: + type: object + properties: + select: + $ref: '#/components/schemas/_AnyObject' + where: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + ProfileAggregateArgs: + type: object + properties: + where: + $ref: '#/components/schemas/_AnyObject' + orderBy: + $ref: '#/components/schemas/_AnyObject' + cursor: + $ref: '#/components/schemas/_AnyObject' + take: + type: integer + skip: + type: integer + _count: + oneOf: + - type: boolean + - $ref: '#/components/schemas/_AnyObject' + _min: + $ref: '#/components/schemas/_AnyObject' + _max: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + ProfileGroupByArgs: + type: object + properties: + where: + $ref: '#/components/schemas/_AnyObject' + orderBy: + $ref: '#/components/schemas/_AnyObject' + by: + $ref: '#/components/schemas/_AnyObject' + having: + $ref: '#/components/schemas/_AnyObject' + take: + type: integer + skip: + type: integer + _count: + oneOf: + - type: boolean + - $ref: '#/components/schemas/_AnyObject' + _min: + $ref: '#/components/schemas/_AnyObject' + _max: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemCreateArgs: + type: object + required: + - data + properties: + select: + $ref: '#/components/schemas/_AnyObject' + include: + $ref: '#/components/schemas/_AnyObject' + data: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemCreateManyArgs: + type: object + required: + - data + properties: + data: + oneOf: + - $ref: '#/components/schemas/_AnyObject' + - type: array + items: + $ref: '#/components/schemas/_AnyObject' + skipDuplicates: + type: boolean + description: Do not insert records with unique fields or ID fields that already + exist. + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemFindUniqueArgs: + type: object + required: + - where + properties: + select: + $ref: '#/components/schemas/_AnyObject' + include: + $ref: '#/components/schemas/_AnyObject' + where: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemFindFirstArgs: + type: object + properties: + select: + $ref: '#/components/schemas/_AnyObject' + include: + $ref: '#/components/schemas/_AnyObject' + where: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemUpdateArgs: + type: object + required: + - where + - data + properties: + select: + $ref: '#/components/schemas/_AnyObject' + include: + $ref: '#/components/schemas/_AnyObject' + where: + $ref: '#/components/schemas/_AnyObject' + data: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemUpdateManyArgs: + type: object + required: + - data + properties: + where: + $ref: '#/components/schemas/_AnyObject' + data: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemUpsertArgs: + type: object + required: + - create + - update + - where + properties: + select: + $ref: '#/components/schemas/_AnyObject' + include: + $ref: '#/components/schemas/_AnyObject' + where: + $ref: '#/components/schemas/_AnyObject' + create: + $ref: '#/components/schemas/_AnyObject' + update: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemDeleteUniqueArgs: + type: object + required: + - where + properties: + select: + $ref: '#/components/schemas/_AnyObject' + include: + $ref: '#/components/schemas/_AnyObject' + where: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemDeleteManyArgs: + type: object + properties: + where: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemCountArgs: + type: object + properties: + select: + $ref: '#/components/schemas/_AnyObject' + where: + $ref: '#/components/schemas/_AnyObject' + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemAggregateArgs: + type: object + properties: + where: + $ref: '#/components/schemas/_AnyObject' + orderBy: + $ref: '#/components/schemas/_AnyObject' + cursor: + $ref: '#/components/schemas/_AnyObject' + take: + type: integer + skip: + type: integer + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemGroupByArgs: + type: object + properties: + where: + $ref: '#/components/schemas/_AnyObject' + orderBy: + $ref: '#/components/schemas/_AnyObject' + by: + $ref: '#/components/schemas/_AnyObject' + having: + $ref: '#/components/schemas/_AnyObject' + take: + type: integer + skip: + type: integer + meta: + $ref: '#/components/schemas/_Meta' +paths: + /user/create: + post: + operationId: createUser + description: Create a new User + tags: + - user + responses: + '201': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/User' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UserCreateArgs' + /user/createMany: + post: + operationId: createManyUser + description: Create several User + tags: + - user + responses: + '201': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BatchPayload' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UserCreateManyArgs' + /user/findUnique: + get: + operationId: findUniqueUser + description: Find one unique User + tags: + - user + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/User' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/UserFindUniqueArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /user/findFirst: + get: + operationId: findFirstUser + description: Find the first User matching the given condition + tags: + - user + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/User' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/UserFindFirstArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /user/findMany: + get: + operationId: findManyUser + description: Find users matching the given conditions + tags: + - user + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + type: array + items: + $ref: '#/components/schemas/User' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/UserFindManyArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /user/update: + patch: + operationId: updateUser + description: Update a User + tags: + - user + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/User' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UserUpdateArgs' + /user/updateMany: + patch: + operationId: updateManyUser + description: Update Users matching the given condition + tags: + - user + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BatchPayload' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UserUpdateManyArgs' + /user/upsert: + post: + operationId: upsertUser + description: Upsert a User + tags: + - user + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/User' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UserUpsertArgs' + /user/dodelete: + put: + operationId: deleteUser + description: Delete a unique user + tags: + - delete + - user + summary: Delete a user yeah yeah + deprecated: true + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/User' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UserDeleteUniqueArgs' + /user/deleteMany: + delete: + operationId: deleteManyUser + description: Delete Users matching the given condition + tags: + - user + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BatchPayload' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/UserDeleteManyArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /user/count: + get: + operationId: countUser + description: Find a list of User + tags: + - user + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + oneOf: + - type: integer + - $ref: '#/components/schemas/UserCountAggregateOutputType' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/UserCountArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /user/aggregate: + get: + operationId: aggregateUser + description: Aggregate Users + tags: + - user + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/AggregateUser' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/UserAggregateArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /user/groupBy: + get: + operationId: groupByUser + description: Group Users by fields + tags: + - user + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + type: array + items: + $ref: '#/components/schemas/UserGroupByOutputType' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/UserGroupByArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /profile/create: + post: + operationId: createProfile + description: Create a new Profile + tags: + - profile + responses: + '201': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Profile' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileCreateArgs' + /profile/createMany: + post: + operationId: createManyProfile + description: Create several Profile + tags: + - profile + responses: + '201': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BatchPayload' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileCreateManyArgs' + /profile/findUnique: + get: + operationId: findUniqueProfile + description: Find one unique Profile + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Profile' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileFindUniqueArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /profile/findFirst: + get: + operationId: findFirstProfile + description: Find the first Profile matching the given condition + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Profile' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileFindFirstArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /profile/findMany: + get: + operationId: findManyProfile + description: Find a list of Profile + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + type: array + items: + $ref: '#/components/schemas/Profile' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileFindManyArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /profile/update: + patch: + operationId: updateProfile + description: Update a Profile + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Profile' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileUpdateArgs' + /profile/updateMany: + patch: + operationId: updateManyProfile + description: Update Profiles matching the given condition + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BatchPayload' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileUpdateManyArgs' + /profile/upsert: + post: + operationId: upsertProfile + description: Upsert a Profile + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Profile' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileUpsertArgs' + /profile/delete: + delete: + operationId: deleteProfile + description: Delete one unique Profile + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Profile' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileDeleteUniqueArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /profile/deleteMany: + delete: + operationId: deleteManyProfile + description: Delete Profiles matching the given condition + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BatchPayload' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileDeleteManyArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /profile/count: + get: + operationId: countProfile + description: Find a list of Profile + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + oneOf: + - type: integer + - $ref: '#/components/schemas/ProfileCountAggregateOutputType' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileCountArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /profile/aggregate: + get: + operationId: aggregateProfile + description: Aggregate Profiles + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/AggregateProfile' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileAggregateArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /profile/groupBy: + get: + operationId: groupByProfile + description: Group Profiles by fields + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + type: array + items: + $ref: '#/components/schemas/ProfileGroupByOutputType' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileGroupByArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /post_Item/create: + post: + operationId: createPost_Item + description: Create a new Post_Item + tags: + - post_Item + responses: + '201': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Post_Item' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemCreateArgs' + /post_Item/createMany: + post: + operationId: createManyPost_Item + description: Create several Post_Item + tags: + - post_Item + responses: + '201': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BatchPayload' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemCreateManyArgs' + /post_Item/findUnique: + get: + operationId: findUniquePost_Item + description: Find one unique Post_Item + tags: + - post_Item + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Post_Item' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemFindUniqueArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /post_Item/findFirst: + get: + operationId: findFirstPost_Item + description: Find the first Post_Item matching the given condition + tags: + - post_Item + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Post_Item' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemFindFirstArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /post_Item/update: + patch: + operationId: updatePost_Item + description: Update a Post_Item + tags: + - post_Item + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Post_Item' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemUpdateArgs' + /post_Item/updateMany: + patch: + operationId: updateManyPost_Item + description: Update Post_Items matching the given condition + tags: + - post_Item + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BatchPayload' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemUpdateManyArgs' + /post_Item/upsert: + post: + operationId: upsertPost_Item + description: Upsert a Post_Item + tags: + - post_Item + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Post_Item' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemUpsertArgs' + /post_Item/delete: + delete: + operationId: deletePost_Item + description: Delete one unique Post_Item + tags: + - post_Item + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Post_Item' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemDeleteUniqueArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /post_Item/deleteMany: + delete: + operationId: deleteManyPost_Item + description: Delete Post_Items matching the given condition + tags: + - post_Item + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BatchPayload' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemDeleteManyArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /post_Item/count: + get: + operationId: countPost_Item + description: Find a list of Post_Item + tags: + - post_Item + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + oneOf: + - type: integer + - $ref: '#/components/schemas/Post_ItemCountAggregateOutputType' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemCountArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /post_Item/aggregate: + get: + operationId: aggregatePost_Item + description: Aggregate Post_Items + tags: + - post_Item + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/AggregatePost_Item' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemAggregateArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /post_Item/groupBy: + get: + operationId: groupByPost_Item + description: Group Post_Items by fields + tags: + - post_Item + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + type: array + items: + $ref: '#/components/schemas/Post_ItemGroupByOutputType' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemGroupByArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} diff --git a/packages/server/test/openapi/migrated/baseline/rpc-3.1.0.baseline.yaml b/packages/server/test/openapi/migrated/baseline/rpc-3.1.0.baseline.yaml new file mode 100644 index 000000000..5c5103e09 --- /dev/null +++ b/packages/server/test/openapi/migrated/baseline/rpc-3.1.0.baseline.yaml @@ -0,0 +1,5853 @@ +openapi: 3.1.0 +info: + title: ZenStack Generated API + version: 1.0.0 +tags: + - name: user + description: User operations + - name: profile + description: Profile operations + - name: post_Item + description: Post-related operations +components: + schemas: + Role: + type: string + enum: + - USER + - ADMIN + UserScalarFieldEnum: + type: string + enum: + - id + - createdAt + - updatedAt + - email + - role + ProfileScalarFieldEnum: + type: string + enum: + - id + - image + - userId + Post_ItemScalarFieldEnum: + type: string + enum: + - id + - createdAt + - updatedAt + - title + - authorId + - published + - viewCount + - notes + SortOrder: + type: string + enum: + - asc + - desc + QueryMode: + type: string + enum: + - default + - insensitive + NullsOrder: + type: string + enum: + - first + - last + User: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + email: + type: string + role: + $ref: '#/components/schemas/Role' + posts: + type: array + items: + $ref: '#/components/schemas/Post_Item' + profile: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Profile' + required: + - id + - createdAt + - updatedAt + - email + - role + Profile: + type: object + properties: + id: + type: string + image: + oneOf: + - type: 'null' + - type: string + user: + $ref: '#/components/schemas/User' + userId: + type: string + required: + - id + - user + - userId + Post_Item: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + title: + type: string + author: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/User' + authorId: + oneOf: + - type: 'null' + - type: string + published: + type: boolean + viewCount: + type: integer + notes: + oneOf: + - type: 'null' + - type: string + required: + - id + - createdAt + - updatedAt + - title + - published + - viewCount + UserWhereInput: + type: object + properties: + AND: + oneOf: + - $ref: '#/components/schemas/UserWhereInput' + - type: array + items: + $ref: '#/components/schemas/UserWhereInput' + OR: + type: array + items: + $ref: '#/components/schemas/UserWhereInput' + NOT: + oneOf: + - $ref: '#/components/schemas/UserWhereInput' + - type: array + items: + $ref: '#/components/schemas/UserWhereInput' + id: + oneOf: + - $ref: '#/components/schemas/StringFilter' + - type: string + createdAt: + oneOf: + - $ref: '#/components/schemas/DateTimeFilter' + - type: string + format: date-time + updatedAt: + oneOf: + - $ref: '#/components/schemas/DateTimeFilter' + - type: string + format: date-time + email: + oneOf: + - $ref: '#/components/schemas/StringFilter' + - type: string + role: + oneOf: + - $ref: '#/components/schemas/EnumroleFilter' + - $ref: '#/components/schemas/Role' + posts: + $ref: '#/components/schemas/Post_ItemListRelationFilter' + profile: + oneOf: + - $ref: '#/components/schemas/ProfileNullableScalarRelationFilter' + - $ref: '#/components/schemas/ProfileWhereInput' + - type: 'null' + UserOrderByWithRelationInput: + type: object + properties: + id: + $ref: '#/components/schemas/SortOrder' + createdAt: + $ref: '#/components/schemas/SortOrder' + updatedAt: + $ref: '#/components/schemas/SortOrder' + email: + $ref: '#/components/schemas/SortOrder' + role: + $ref: '#/components/schemas/SortOrder' + posts: + $ref: '#/components/schemas/Post_ItemOrderByRelationAggregateInput' + profile: + $ref: '#/components/schemas/ProfileOrderByWithRelationInput' + UserWhereUniqueInput: + type: object + properties: + id: + type: string + email: + type: string + AND: + oneOf: + - $ref: '#/components/schemas/UserWhereInput' + - type: array + items: + $ref: '#/components/schemas/UserWhereInput' + OR: + type: array + items: + $ref: '#/components/schemas/UserWhereInput' + NOT: + oneOf: + - $ref: '#/components/schemas/UserWhereInput' + - type: array + items: + $ref: '#/components/schemas/UserWhereInput' + createdAt: + oneOf: + - $ref: '#/components/schemas/DateTimeFilter' + - type: string + format: date-time + updatedAt: + oneOf: + - $ref: '#/components/schemas/DateTimeFilter' + - type: string + format: date-time + role: + oneOf: + - $ref: '#/components/schemas/EnumroleFilter' + - $ref: '#/components/schemas/Role' + posts: + $ref: '#/components/schemas/Post_ItemListRelationFilter' + profile: + oneOf: + - $ref: '#/components/schemas/ProfileNullableScalarRelationFilter' + - $ref: '#/components/schemas/ProfileWhereInput' + - type: 'null' + UserScalarWhereWithAggregatesInput: + type: object + properties: + AND: + oneOf: + - $ref: '#/components/schemas/UserScalarWhereWithAggregatesInput' + - type: array + items: + $ref: '#/components/schemas/UserScalarWhereWithAggregatesInput' + OR: + type: array + items: + $ref: '#/components/schemas/UserScalarWhereWithAggregatesInput' + NOT: + oneOf: + - $ref: '#/components/schemas/UserScalarWhereWithAggregatesInput' + - type: array + items: + $ref: '#/components/schemas/UserScalarWhereWithAggregatesInput' + id: + oneOf: + - $ref: '#/components/schemas/StringWithAggregatesFilter' + - type: string + createdAt: + oneOf: + - $ref: '#/components/schemas/DateTimeWithAggregatesFilter' + - type: string + format: date-time + updatedAt: + oneOf: + - $ref: '#/components/schemas/DateTimeWithAggregatesFilter' + - type: string + format: date-time + email: + oneOf: + - $ref: '#/components/schemas/StringWithAggregatesFilter' + - type: string + role: + oneOf: + - $ref: '#/components/schemas/EnumroleWithAggregatesFilter' + - $ref: '#/components/schemas/Role' + ProfileWhereInput: + type: object + properties: + AND: + oneOf: + - $ref: '#/components/schemas/ProfileWhereInput' + - type: array + items: + $ref: '#/components/schemas/ProfileWhereInput' + OR: + type: array + items: + $ref: '#/components/schemas/ProfileWhereInput' + NOT: + oneOf: + - $ref: '#/components/schemas/ProfileWhereInput' + - type: array + items: + $ref: '#/components/schemas/ProfileWhereInput' + id: + oneOf: + - $ref: '#/components/schemas/StringFilter' + - type: string + image: + oneOf: + - $ref: '#/components/schemas/StringNullableFilter' + - type: string + - type: 'null' + userId: + oneOf: + - $ref: '#/components/schemas/StringFilter' + - type: string + user: + oneOf: + - $ref: '#/components/schemas/UserScalarRelationFilter' + - $ref: '#/components/schemas/UserWhereInput' + ProfileOrderByWithRelationInput: + type: object + properties: + id: + $ref: '#/components/schemas/SortOrder' + image: + oneOf: + - $ref: '#/components/schemas/SortOrder' + - $ref: '#/components/schemas/SortOrderInput' + userId: + $ref: '#/components/schemas/SortOrder' + user: + $ref: '#/components/schemas/UserOrderByWithRelationInput' + ProfileWhereUniqueInput: + type: object + properties: + id: + type: string + userId: + type: string + AND: + oneOf: + - $ref: '#/components/schemas/ProfileWhereInput' + - type: array + items: + $ref: '#/components/schemas/ProfileWhereInput' + OR: + type: array + items: + $ref: '#/components/schemas/ProfileWhereInput' + NOT: + oneOf: + - $ref: '#/components/schemas/ProfileWhereInput' + - type: array + items: + $ref: '#/components/schemas/ProfileWhereInput' + image: + oneOf: + - $ref: '#/components/schemas/StringNullableFilter' + - type: string + - type: 'null' + user: + oneOf: + - $ref: '#/components/schemas/UserScalarRelationFilter' + - $ref: '#/components/schemas/UserWhereInput' + ProfileScalarWhereWithAggregatesInput: + type: object + properties: + AND: + oneOf: + - $ref: '#/components/schemas/ProfileScalarWhereWithAggregatesInput' + - type: array + items: + $ref: '#/components/schemas/ProfileScalarWhereWithAggregatesInput' + OR: + type: array + items: + $ref: '#/components/schemas/ProfileScalarWhereWithAggregatesInput' + NOT: + oneOf: + - $ref: '#/components/schemas/ProfileScalarWhereWithAggregatesInput' + - type: array + items: + $ref: '#/components/schemas/ProfileScalarWhereWithAggregatesInput' + id: + oneOf: + - $ref: '#/components/schemas/StringWithAggregatesFilter' + - type: string + image: + oneOf: + - $ref: '#/components/schemas/StringNullableWithAggregatesFilter' + - type: string + - type: 'null' + userId: + oneOf: + - $ref: '#/components/schemas/StringWithAggregatesFilter' + - type: string + Post_ItemWhereInput: + type: object + properties: + AND: + oneOf: + - $ref: '#/components/schemas/Post_ItemWhereInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemWhereInput' + OR: + type: array + items: + $ref: '#/components/schemas/Post_ItemWhereInput' + NOT: + oneOf: + - $ref: '#/components/schemas/Post_ItemWhereInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemWhereInput' + id: + oneOf: + - $ref: '#/components/schemas/StringFilter' + - type: string + createdAt: + oneOf: + - $ref: '#/components/schemas/DateTimeFilter' + - type: string + format: date-time + updatedAt: + oneOf: + - $ref: '#/components/schemas/DateTimeFilter' + - type: string + format: date-time + title: + oneOf: + - $ref: '#/components/schemas/StringFilter' + - type: string + authorId: + oneOf: + - $ref: '#/components/schemas/StringNullableFilter' + - type: string + - type: 'null' + published: + oneOf: + - $ref: '#/components/schemas/BoolFilter' + - type: boolean + viewCount: + oneOf: + - $ref: '#/components/schemas/IntFilter' + - type: integer + notes: + oneOf: + - $ref: '#/components/schemas/StringNullableFilter' + - type: string + - type: 'null' + author: + oneOf: + - $ref: '#/components/schemas/UserNullableScalarRelationFilter' + - $ref: '#/components/schemas/UserWhereInput' + - type: 'null' + Post_ItemOrderByWithRelationInput: + type: object + properties: + id: + $ref: '#/components/schemas/SortOrder' + createdAt: + $ref: '#/components/schemas/SortOrder' + updatedAt: + $ref: '#/components/schemas/SortOrder' + title: + $ref: '#/components/schemas/SortOrder' + authorId: + oneOf: + - $ref: '#/components/schemas/SortOrder' + - $ref: '#/components/schemas/SortOrderInput' + published: + $ref: '#/components/schemas/SortOrder' + viewCount: + $ref: '#/components/schemas/SortOrder' + notes: + oneOf: + - $ref: '#/components/schemas/SortOrder' + - $ref: '#/components/schemas/SortOrderInput' + author: + $ref: '#/components/schemas/UserOrderByWithRelationInput' + Post_ItemWhereUniqueInput: + type: object + properties: + id: + type: string + AND: + oneOf: + - $ref: '#/components/schemas/Post_ItemWhereInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemWhereInput' + OR: + type: array + items: + $ref: '#/components/schemas/Post_ItemWhereInput' + NOT: + oneOf: + - $ref: '#/components/schemas/Post_ItemWhereInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemWhereInput' + createdAt: + oneOf: + - $ref: '#/components/schemas/DateTimeFilter' + - type: string + format: date-time + updatedAt: + oneOf: + - $ref: '#/components/schemas/DateTimeFilter' + - type: string + format: date-time + title: + oneOf: + - $ref: '#/components/schemas/StringFilter' + - type: string + authorId: + oneOf: + - $ref: '#/components/schemas/StringNullableFilter' + - type: string + - type: 'null' + published: + oneOf: + - $ref: '#/components/schemas/BoolFilter' + - type: boolean + viewCount: + oneOf: + - $ref: '#/components/schemas/IntFilter' + - type: integer + notes: + oneOf: + - $ref: '#/components/schemas/StringNullableFilter' + - type: string + - type: 'null' + author: + oneOf: + - $ref: '#/components/schemas/UserNullableScalarRelationFilter' + - $ref: '#/components/schemas/UserWhereInput' + - type: 'null' + Post_ItemScalarWhereWithAggregatesInput: + type: object + properties: + AND: + oneOf: + - $ref: '#/components/schemas/Post_ItemScalarWhereWithAggregatesInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemScalarWhereWithAggregatesInput' + OR: + type: array + items: + $ref: '#/components/schemas/Post_ItemScalarWhereWithAggregatesInput' + NOT: + oneOf: + - $ref: '#/components/schemas/Post_ItemScalarWhereWithAggregatesInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemScalarWhereWithAggregatesInput' + id: + oneOf: + - $ref: '#/components/schemas/StringWithAggregatesFilter' + - type: string + createdAt: + oneOf: + - $ref: '#/components/schemas/DateTimeWithAggregatesFilter' + - type: string + format: date-time + updatedAt: + oneOf: + - $ref: '#/components/schemas/DateTimeWithAggregatesFilter' + - type: string + format: date-time + title: + oneOf: + - $ref: '#/components/schemas/StringWithAggregatesFilter' + - type: string + authorId: + oneOf: + - $ref: '#/components/schemas/StringNullableWithAggregatesFilter' + - type: string + - type: 'null' + published: + oneOf: + - $ref: '#/components/schemas/BoolWithAggregatesFilter' + - type: boolean + viewCount: + oneOf: + - $ref: '#/components/schemas/IntWithAggregatesFilter' + - type: integer + notes: + oneOf: + - $ref: '#/components/schemas/StringNullableWithAggregatesFilter' + - type: string + - type: 'null' + UserCreateInput: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + email: + type: string + role: + $ref: '#/components/schemas/Role' + posts: + $ref: '#/components/schemas/Post_ItemCreateNestedManyWithoutAuthorInput' + profile: + $ref: '#/components/schemas/ProfileCreateNestedOneWithoutUserInput' + required: + - email + UserUpdateInput: + type: object + properties: + id: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + createdAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + updatedAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + email: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + role: + oneOf: + - $ref: '#/components/schemas/Role' + - $ref: '#/components/schemas/EnumroleFieldUpdateOperationsInput' + posts: + $ref: '#/components/schemas/Post_ItemUpdateManyWithoutAuthorNestedInput' + profile: + $ref: '#/components/schemas/ProfileUpdateOneWithoutUserNestedInput' + UserCreateManyInput: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + email: + type: string + role: + $ref: '#/components/schemas/Role' + required: + - email + UserUpdateManyMutationInput: + type: object + properties: + id: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + createdAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + updatedAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + email: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + role: + oneOf: + - $ref: '#/components/schemas/Role' + - $ref: '#/components/schemas/EnumroleFieldUpdateOperationsInput' + ProfileCreateInput: + type: object + properties: + id: + type: string + image: + oneOf: + - type: 'null' + - type: string + user: + $ref: '#/components/schemas/UserCreateNestedOneWithoutProfileInput' + required: + - user + ProfileUpdateInput: + type: object + properties: + id: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + image: + oneOf: + - type: string + - $ref: '#/components/schemas/NullableStringFieldUpdateOperationsInput' + - type: 'null' + user: + $ref: '#/components/schemas/UserUpdateOneRequiredWithoutProfileNestedInput' + ProfileCreateManyInput: + type: object + properties: + id: + type: string + image: + oneOf: + - type: 'null' + - type: string + userId: + type: string + required: + - userId + ProfileUpdateManyMutationInput: + type: object + properties: + id: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + image: + oneOf: + - type: string + - $ref: '#/components/schemas/NullableStringFieldUpdateOperationsInput' + - type: 'null' + Post_ItemCreateInput: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + title: + type: string + published: + type: boolean + viewCount: + type: integer + notes: + oneOf: + - type: 'null' + - type: string + author: + $ref: '#/components/schemas/UserCreateNestedOneWithoutPostsInput' + required: + - id + - title + Post_ItemUpdateInput: + type: object + properties: + id: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + createdAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + updatedAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + title: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + published: + oneOf: + - type: boolean + - $ref: '#/components/schemas/BoolFieldUpdateOperationsInput' + viewCount: + oneOf: + - type: integer + - $ref: '#/components/schemas/IntFieldUpdateOperationsInput' + notes: + oneOf: + - type: string + - $ref: '#/components/schemas/NullableStringFieldUpdateOperationsInput' + - type: 'null' + author: + $ref: '#/components/schemas/UserUpdateOneWithoutPostsNestedInput' + Post_ItemCreateManyInput: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + title: + type: string + authorId: + oneOf: + - type: 'null' + - type: string + published: + type: boolean + viewCount: + type: integer + notes: + oneOf: + - type: 'null' + - type: string + required: + - id + - title + Post_ItemUpdateManyMutationInput: + type: object + properties: + id: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + createdAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + updatedAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + title: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + published: + oneOf: + - type: boolean + - $ref: '#/components/schemas/BoolFieldUpdateOperationsInput' + viewCount: + oneOf: + - type: integer + - $ref: '#/components/schemas/IntFieldUpdateOperationsInput' + notes: + oneOf: + - type: string + - $ref: '#/components/schemas/NullableStringFieldUpdateOperationsInput' + - type: 'null' + StringFilter: + type: object + properties: + equals: + type: string + in: + type: array + items: + type: string + notIn: + type: array + items: + type: string + lt: + type: string + lte: + type: string + gt: + type: string + gte: + type: string + contains: + type: string + startsWith: + type: string + endsWith: + type: string + mode: + $ref: '#/components/schemas/QueryMode' + not: + oneOf: + - type: string + - $ref: '#/components/schemas/NestedStringFilter' + DateTimeFilter: + type: object + properties: + equals: + type: string + format: date-time + in: + type: array + items: + type: string + format: date-time + notIn: + type: array + items: + type: string + format: date-time + lt: + type: string + format: date-time + lte: + type: string + format: date-time + gt: + type: string + format: date-time + gte: + type: string + format: date-time + not: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/NestedDateTimeFilter' + EnumroleFilter: + type: object + properties: + equals: + $ref: '#/components/schemas/Role' + in: + type: array + items: + $ref: '#/components/schemas/Role' + notIn: + type: array + items: + $ref: '#/components/schemas/Role' + not: + oneOf: + - $ref: '#/components/schemas/Role' + - $ref: '#/components/schemas/NestedEnumroleFilter' + Post_ItemListRelationFilter: + type: object + properties: + every: + $ref: '#/components/schemas/Post_ItemWhereInput' + some: + $ref: '#/components/schemas/Post_ItemWhereInput' + none: + $ref: '#/components/schemas/Post_ItemWhereInput' + ProfileNullableScalarRelationFilter: + type: object + properties: + is: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/ProfileWhereInput' + isNot: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/ProfileWhereInput' + Post_ItemOrderByRelationAggregateInput: + type: object + properties: + _count: + $ref: '#/components/schemas/SortOrder' + StringWithAggregatesFilter: + type: object + properties: + equals: + type: string + in: + type: array + items: + type: string + notIn: + type: array + items: + type: string + lt: + type: string + lte: + type: string + gt: + type: string + gte: + type: string + contains: + type: string + startsWith: + type: string + endsWith: + type: string + mode: + $ref: '#/components/schemas/QueryMode' + not: + oneOf: + - type: string + - $ref: '#/components/schemas/NestedStringWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _min: + $ref: '#/components/schemas/NestedStringFilter' + _max: + $ref: '#/components/schemas/NestedStringFilter' + DateTimeWithAggregatesFilter: + type: object + properties: + equals: + type: string + format: date-time + in: + type: array + items: + type: string + format: date-time + notIn: + type: array + items: + type: string + format: date-time + lt: + type: string + format: date-time + lte: + type: string + format: date-time + gt: + type: string + format: date-time + gte: + type: string + format: date-time + not: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/NestedDateTimeWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _min: + $ref: '#/components/schemas/NestedDateTimeFilter' + _max: + $ref: '#/components/schemas/NestedDateTimeFilter' + EnumroleWithAggregatesFilter: + type: object + properties: + equals: + $ref: '#/components/schemas/Role' + in: + type: array + items: + $ref: '#/components/schemas/Role' + notIn: + type: array + items: + $ref: '#/components/schemas/Role' + not: + oneOf: + - $ref: '#/components/schemas/Role' + - $ref: '#/components/schemas/NestedEnumroleWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _min: + $ref: '#/components/schemas/NestedEnumroleFilter' + _max: + $ref: '#/components/schemas/NestedEnumroleFilter' + StringNullableFilter: + type: object + properties: + equals: + oneOf: + - type: 'null' + - type: string + in: + oneOf: + - type: 'null' + - type: array + items: + type: string + notIn: + oneOf: + - type: 'null' + - type: array + items: + type: string + lt: + type: string + lte: + type: string + gt: + type: string + gte: + type: string + contains: + type: string + startsWith: + type: string + endsWith: + type: string + mode: + $ref: '#/components/schemas/QueryMode' + not: + oneOf: + - type: string + - $ref: '#/components/schemas/NestedStringNullableFilter' + - type: 'null' + UserScalarRelationFilter: + type: object + properties: + is: + $ref: '#/components/schemas/UserWhereInput' + isNot: + $ref: '#/components/schemas/UserWhereInput' + SortOrderInput: + type: object + properties: + sort: + $ref: '#/components/schemas/SortOrder' + nulls: + $ref: '#/components/schemas/NullsOrder' + required: + - sort + StringNullableWithAggregatesFilter: + type: object + properties: + equals: + oneOf: + - type: 'null' + - type: string + in: + oneOf: + - type: 'null' + - type: array + items: + type: string + notIn: + oneOf: + - type: 'null' + - type: array + items: + type: string + lt: + type: string + lte: + type: string + gt: + type: string + gte: + type: string + contains: + type: string + startsWith: + type: string + endsWith: + type: string + mode: + $ref: '#/components/schemas/QueryMode' + not: + oneOf: + - type: string + - $ref: '#/components/schemas/NestedStringNullableWithAggregatesFilter' + - type: 'null' + _count: + $ref: '#/components/schemas/NestedIntNullableFilter' + _min: + $ref: '#/components/schemas/NestedStringNullableFilter' + _max: + $ref: '#/components/schemas/NestedStringNullableFilter' + BoolFilter: + type: object + properties: + equals: + type: boolean + not: + oneOf: + - type: boolean + - $ref: '#/components/schemas/NestedBoolFilter' + IntFilter: + type: object + properties: + equals: + type: integer + in: + type: array + items: + type: integer + notIn: + type: array + items: + type: integer + lt: + type: integer + lte: + type: integer + gt: + type: integer + gte: + type: integer + not: + oneOf: + - type: integer + - $ref: '#/components/schemas/NestedIntFilter' + UserNullableScalarRelationFilter: + type: object + properties: + is: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/UserWhereInput' + isNot: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/UserWhereInput' + BoolWithAggregatesFilter: + type: object + properties: + equals: + type: boolean + not: + oneOf: + - type: boolean + - $ref: '#/components/schemas/NestedBoolWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _min: + $ref: '#/components/schemas/NestedBoolFilter' + _max: + $ref: '#/components/schemas/NestedBoolFilter' + IntWithAggregatesFilter: + type: object + properties: + equals: + type: integer + in: + type: array + items: + type: integer + notIn: + type: array + items: + type: integer + lt: + type: integer + lte: + type: integer + gt: + type: integer + gte: + type: integer + not: + oneOf: + - type: integer + - $ref: '#/components/schemas/NestedIntWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _avg: + $ref: '#/components/schemas/NestedFloatFilter' + _sum: + $ref: '#/components/schemas/NestedIntFilter' + _min: + $ref: '#/components/schemas/NestedIntFilter' + _max: + $ref: '#/components/schemas/NestedIntFilter' + Post_ItemCreateNestedManyWithoutAuthorInput: + type: object + properties: + create: + oneOf: + - $ref: '#/components/schemas/Post_ItemCreateWithoutAuthorInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemCreateWithoutAuthorInput' + - $ref: '#/components/schemas/Post_ItemUncheckedCreateWithoutAuthorInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemUncheckedCreateWithoutAuthorInput' + connectOrCreate: + oneOf: + - $ref: '#/components/schemas/Post_ItemCreateOrConnectWithoutAuthorInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemCreateOrConnectWithoutAuthorInput' + createMany: + $ref: '#/components/schemas/Post_ItemCreateManyAuthorInputEnvelope' + connect: + oneOf: + - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + ProfileCreateNestedOneWithoutUserInput: + type: object + properties: + create: + oneOf: + - $ref: '#/components/schemas/ProfileCreateWithoutUserInput' + - $ref: '#/components/schemas/ProfileUncheckedCreateWithoutUserInput' + connectOrCreate: + $ref: '#/components/schemas/ProfileCreateOrConnectWithoutUserInput' + connect: + $ref: '#/components/schemas/ProfileWhereUniqueInput' + Post_ItemUncheckedCreateNestedManyWithoutAuthorInput: + type: object + properties: + create: + oneOf: + - $ref: '#/components/schemas/Post_ItemCreateWithoutAuthorInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemCreateWithoutAuthorInput' + - $ref: '#/components/schemas/Post_ItemUncheckedCreateWithoutAuthorInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemUncheckedCreateWithoutAuthorInput' + connectOrCreate: + oneOf: + - $ref: '#/components/schemas/Post_ItemCreateOrConnectWithoutAuthorInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemCreateOrConnectWithoutAuthorInput' + createMany: + $ref: '#/components/schemas/Post_ItemCreateManyAuthorInputEnvelope' + connect: + oneOf: + - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + ProfileUncheckedCreateNestedOneWithoutUserInput: + type: object + properties: + create: + oneOf: + - $ref: '#/components/schemas/ProfileCreateWithoutUserInput' + - $ref: '#/components/schemas/ProfileUncheckedCreateWithoutUserInput' + connectOrCreate: + $ref: '#/components/schemas/ProfileCreateOrConnectWithoutUserInput' + connect: + $ref: '#/components/schemas/ProfileWhereUniqueInput' + StringFieldUpdateOperationsInput: + type: object + properties: + set: + type: string + DateTimeFieldUpdateOperationsInput: + type: object + properties: + set: + type: string + format: date-time + EnumroleFieldUpdateOperationsInput: + type: object + properties: + set: + $ref: '#/components/schemas/Role' + Post_ItemUpdateManyWithoutAuthorNestedInput: + type: object + properties: + create: + oneOf: + - $ref: '#/components/schemas/Post_ItemCreateWithoutAuthorInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemCreateWithoutAuthorInput' + - $ref: '#/components/schemas/Post_ItemUncheckedCreateWithoutAuthorInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemUncheckedCreateWithoutAuthorInput' + connectOrCreate: + oneOf: + - $ref: '#/components/schemas/Post_ItemCreateOrConnectWithoutAuthorInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemCreateOrConnectWithoutAuthorInput' + upsert: + oneOf: + - $ref: '#/components/schemas/Post_ItemUpsertWithWhereUniqueWithoutAuthorInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemUpsertWithWhereUniqueWithoutAuthorInput' + createMany: + $ref: '#/components/schemas/Post_ItemCreateManyAuthorInputEnvelope' + set: + oneOf: + - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + disconnect: + oneOf: + - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + delete: + oneOf: + - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + connect: + oneOf: + - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + update: + oneOf: + - $ref: '#/components/schemas/Post_ItemUpdateWithWhereUniqueWithoutAuthorInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemUpdateWithWhereUniqueWithoutAuthorInput' + updateMany: + oneOf: + - $ref: '#/components/schemas/Post_ItemUpdateManyWithWhereWithoutAuthorInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemUpdateManyWithWhereWithoutAuthorInput' + deleteMany: + oneOf: + - $ref: '#/components/schemas/Post_ItemScalarWhereInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemScalarWhereInput' + ProfileUpdateOneWithoutUserNestedInput: + type: object + properties: + create: + oneOf: + - $ref: '#/components/schemas/ProfileCreateWithoutUserInput' + - $ref: '#/components/schemas/ProfileUncheckedCreateWithoutUserInput' + connectOrCreate: + $ref: '#/components/schemas/ProfileCreateOrConnectWithoutUserInput' + upsert: + $ref: '#/components/schemas/ProfileUpsertWithoutUserInput' + disconnect: + oneOf: + - type: boolean + - $ref: '#/components/schemas/ProfileWhereInput' + delete: + oneOf: + - type: boolean + - $ref: '#/components/schemas/ProfileWhereInput' + connect: + $ref: '#/components/schemas/ProfileWhereUniqueInput' + update: + oneOf: + - $ref: '#/components/schemas/ProfileUpdateToOneWithWhereWithoutUserInput' + - $ref: '#/components/schemas/ProfileUpdateWithoutUserInput' + - $ref: '#/components/schemas/ProfileUncheckedUpdateWithoutUserInput' + Post_ItemUncheckedUpdateManyWithoutAuthorNestedInput: + type: object + properties: + create: + oneOf: + - $ref: '#/components/schemas/Post_ItemCreateWithoutAuthorInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemCreateWithoutAuthorInput' + - $ref: '#/components/schemas/Post_ItemUncheckedCreateWithoutAuthorInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemUncheckedCreateWithoutAuthorInput' + connectOrCreate: + oneOf: + - $ref: '#/components/schemas/Post_ItemCreateOrConnectWithoutAuthorInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemCreateOrConnectWithoutAuthorInput' + upsert: + oneOf: + - $ref: '#/components/schemas/Post_ItemUpsertWithWhereUniqueWithoutAuthorInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemUpsertWithWhereUniqueWithoutAuthorInput' + createMany: + $ref: '#/components/schemas/Post_ItemCreateManyAuthorInputEnvelope' + set: + oneOf: + - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + disconnect: + oneOf: + - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + delete: + oneOf: + - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + connect: + oneOf: + - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + update: + oneOf: + - $ref: '#/components/schemas/Post_ItemUpdateWithWhereUniqueWithoutAuthorInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemUpdateWithWhereUniqueWithoutAuthorInput' + updateMany: + oneOf: + - $ref: '#/components/schemas/Post_ItemUpdateManyWithWhereWithoutAuthorInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemUpdateManyWithWhereWithoutAuthorInput' + deleteMany: + oneOf: + - $ref: '#/components/schemas/Post_ItemScalarWhereInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemScalarWhereInput' + ProfileUncheckedUpdateOneWithoutUserNestedInput: + type: object + properties: + create: + oneOf: + - $ref: '#/components/schemas/ProfileCreateWithoutUserInput' + - $ref: '#/components/schemas/ProfileUncheckedCreateWithoutUserInput' + connectOrCreate: + $ref: '#/components/schemas/ProfileCreateOrConnectWithoutUserInput' + upsert: + $ref: '#/components/schemas/ProfileUpsertWithoutUserInput' + disconnect: + oneOf: + - type: boolean + - $ref: '#/components/schemas/ProfileWhereInput' + delete: + oneOf: + - type: boolean + - $ref: '#/components/schemas/ProfileWhereInput' + connect: + $ref: '#/components/schemas/ProfileWhereUniqueInput' + update: + oneOf: + - $ref: '#/components/schemas/ProfileUpdateToOneWithWhereWithoutUserInput' + - $ref: '#/components/schemas/ProfileUpdateWithoutUserInput' + - $ref: '#/components/schemas/ProfileUncheckedUpdateWithoutUserInput' + UserCreateNestedOneWithoutProfileInput: + type: object + properties: + create: + oneOf: + - $ref: '#/components/schemas/UserCreateWithoutProfileInput' + - $ref: '#/components/schemas/UserUncheckedCreateWithoutProfileInput' + connectOrCreate: + $ref: '#/components/schemas/UserCreateOrConnectWithoutProfileInput' + connect: + $ref: '#/components/schemas/UserWhereUniqueInput' + NullableStringFieldUpdateOperationsInput: + type: object + properties: + set: + oneOf: + - type: 'null' + - type: string + UserUpdateOneRequiredWithoutProfileNestedInput: + type: object + properties: + create: + oneOf: + - $ref: '#/components/schemas/UserCreateWithoutProfileInput' + - $ref: '#/components/schemas/UserUncheckedCreateWithoutProfileInput' + connectOrCreate: + $ref: '#/components/schemas/UserCreateOrConnectWithoutProfileInput' + upsert: + $ref: '#/components/schemas/UserUpsertWithoutProfileInput' + connect: + $ref: '#/components/schemas/UserWhereUniqueInput' + update: + oneOf: + - $ref: '#/components/schemas/UserUpdateToOneWithWhereWithoutProfileInput' + - $ref: '#/components/schemas/UserUpdateWithoutProfileInput' + - $ref: '#/components/schemas/UserUncheckedUpdateWithoutProfileInput' + UserCreateNestedOneWithoutPostsInput: + type: object + properties: + create: + oneOf: + - $ref: '#/components/schemas/UserCreateWithoutPostsInput' + - $ref: '#/components/schemas/UserUncheckedCreateWithoutPostsInput' + connectOrCreate: + $ref: '#/components/schemas/UserCreateOrConnectWithoutPostsInput' + connect: + $ref: '#/components/schemas/UserWhereUniqueInput' + BoolFieldUpdateOperationsInput: + type: object + properties: + set: + type: boolean + IntFieldUpdateOperationsInput: + type: object + properties: + set: + type: integer + increment: + type: integer + decrement: + type: integer + multiply: + type: integer + divide: + type: integer + UserUpdateOneWithoutPostsNestedInput: + type: object + properties: + create: + oneOf: + - $ref: '#/components/schemas/UserCreateWithoutPostsInput' + - $ref: '#/components/schemas/UserUncheckedCreateWithoutPostsInput' + connectOrCreate: + $ref: '#/components/schemas/UserCreateOrConnectWithoutPostsInput' + upsert: + $ref: '#/components/schemas/UserUpsertWithoutPostsInput' + disconnect: + oneOf: + - type: boolean + - $ref: '#/components/schemas/UserWhereInput' + delete: + oneOf: + - type: boolean + - $ref: '#/components/schemas/UserWhereInput' + connect: + $ref: '#/components/schemas/UserWhereUniqueInput' + update: + oneOf: + - $ref: '#/components/schemas/UserUpdateToOneWithWhereWithoutPostsInput' + - $ref: '#/components/schemas/UserUpdateWithoutPostsInput' + - $ref: '#/components/schemas/UserUncheckedUpdateWithoutPostsInput' + NestedStringFilter: + type: object + properties: + equals: + type: string + in: + type: array + items: + type: string + notIn: + type: array + items: + type: string + lt: + type: string + lte: + type: string + gt: + type: string + gte: + type: string + contains: + type: string + startsWith: + type: string + endsWith: + type: string + not: + oneOf: + - type: string + - $ref: '#/components/schemas/NestedStringFilter' + NestedDateTimeFilter: + type: object + properties: + equals: + type: string + format: date-time + in: + type: array + items: + type: string + format: date-time + notIn: + type: array + items: + type: string + format: date-time + lt: + type: string + format: date-time + lte: + type: string + format: date-time + gt: + type: string + format: date-time + gte: + type: string + format: date-time + not: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/NestedDateTimeFilter' + NestedEnumroleFilter: + type: object + properties: + equals: + $ref: '#/components/schemas/Role' + in: + type: array + items: + $ref: '#/components/schemas/Role' + notIn: + type: array + items: + $ref: '#/components/schemas/Role' + not: + oneOf: + - $ref: '#/components/schemas/Role' + - $ref: '#/components/schemas/NestedEnumroleFilter' + NestedStringWithAggregatesFilter: + type: object + properties: + equals: + type: string + in: + type: array + items: + type: string + notIn: + type: array + items: + type: string + lt: + type: string + lte: + type: string + gt: + type: string + gte: + type: string + contains: + type: string + startsWith: + type: string + endsWith: + type: string + not: + oneOf: + - type: string + - $ref: '#/components/schemas/NestedStringWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _min: + $ref: '#/components/schemas/NestedStringFilter' + _max: + $ref: '#/components/schemas/NestedStringFilter' + NestedIntFilter: + type: object + properties: + equals: + type: integer + in: + type: array + items: + type: integer + notIn: + type: array + items: + type: integer + lt: + type: integer + lte: + type: integer + gt: + type: integer + gte: + type: integer + not: + oneOf: + - type: integer + - $ref: '#/components/schemas/NestedIntFilter' + NestedDateTimeWithAggregatesFilter: + type: object + properties: + equals: + type: string + format: date-time + in: + type: array + items: + type: string + format: date-time + notIn: + type: array + items: + type: string + format: date-time + lt: + type: string + format: date-time + lte: + type: string + format: date-time + gt: + type: string + format: date-time + gte: + type: string + format: date-time + not: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/NestedDateTimeWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _min: + $ref: '#/components/schemas/NestedDateTimeFilter' + _max: + $ref: '#/components/schemas/NestedDateTimeFilter' + NestedEnumroleWithAggregatesFilter: + type: object + properties: + equals: + $ref: '#/components/schemas/Role' + in: + type: array + items: + $ref: '#/components/schemas/Role' + notIn: + type: array + items: + $ref: '#/components/schemas/Role' + not: + oneOf: + - $ref: '#/components/schemas/Role' + - $ref: '#/components/schemas/NestedEnumroleWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _min: + $ref: '#/components/schemas/NestedEnumroleFilter' + _max: + $ref: '#/components/schemas/NestedEnumroleFilter' + NestedStringNullableFilter: + type: object + properties: + equals: + oneOf: + - type: 'null' + - type: string + in: + oneOf: + - type: 'null' + - type: array + items: + type: string + notIn: + oneOf: + - type: 'null' + - type: array + items: + type: string + lt: + type: string + lte: + type: string + gt: + type: string + gte: + type: string + contains: + type: string + startsWith: + type: string + endsWith: + type: string + not: + oneOf: + - type: string + - $ref: '#/components/schemas/NestedStringNullableFilter' + - type: 'null' + NestedStringNullableWithAggregatesFilter: + type: object + properties: + equals: + oneOf: + - type: 'null' + - type: string + in: + oneOf: + - type: 'null' + - type: array + items: + type: string + notIn: + oneOf: + - type: 'null' + - type: array + items: + type: string + lt: + type: string + lte: + type: string + gt: + type: string + gte: + type: string + contains: + type: string + startsWith: + type: string + endsWith: + type: string + not: + oneOf: + - type: string + - $ref: '#/components/schemas/NestedStringNullableWithAggregatesFilter' + - type: 'null' + _count: + $ref: '#/components/schemas/NestedIntNullableFilter' + _min: + $ref: '#/components/schemas/NestedStringNullableFilter' + _max: + $ref: '#/components/schemas/NestedStringNullableFilter' + NestedIntNullableFilter: + type: object + properties: + equals: + oneOf: + - type: 'null' + - type: integer + in: + oneOf: + - type: 'null' + - type: array + items: + type: integer + notIn: + oneOf: + - type: 'null' + - type: array + items: + type: integer + lt: + type: integer + lte: + type: integer + gt: + type: integer + gte: + type: integer + not: + oneOf: + - type: integer + - $ref: '#/components/schemas/NestedIntNullableFilter' + - type: 'null' + NestedBoolFilter: + type: object + properties: + equals: + type: boolean + not: + oneOf: + - type: boolean + - $ref: '#/components/schemas/NestedBoolFilter' + NestedBoolWithAggregatesFilter: + type: object + properties: + equals: + type: boolean + not: + oneOf: + - type: boolean + - $ref: '#/components/schemas/NestedBoolWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _min: + $ref: '#/components/schemas/NestedBoolFilter' + _max: + $ref: '#/components/schemas/NestedBoolFilter' + NestedIntWithAggregatesFilter: + type: object + properties: + equals: + type: integer + in: + type: array + items: + type: integer + notIn: + type: array + items: + type: integer + lt: + type: integer + lte: + type: integer + gt: + type: integer + gte: + type: integer + not: + oneOf: + - type: integer + - $ref: '#/components/schemas/NestedIntWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _avg: + $ref: '#/components/schemas/NestedFloatFilter' + _sum: + $ref: '#/components/schemas/NestedIntFilter' + _min: + $ref: '#/components/schemas/NestedIntFilter' + _max: + $ref: '#/components/schemas/NestedIntFilter' + NestedFloatFilter: + type: object + properties: + equals: + type: number + in: + type: array + items: + type: number + notIn: + type: array + items: + type: number + lt: + type: number + lte: + type: number + gt: + type: number + gte: + type: number + not: + oneOf: + - type: number + - $ref: '#/components/schemas/NestedFloatFilter' + Post_ItemCreateWithoutAuthorInput: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + title: + type: string + published: + type: boolean + viewCount: + type: integer + notes: + oneOf: + - type: 'null' + - type: string + required: + - id + - title + Post_ItemUncheckedCreateWithoutAuthorInput: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + title: + type: string + published: + type: boolean + viewCount: + type: integer + notes: + oneOf: + - type: 'null' + - type: string + required: + - id + - title + Post_ItemCreateOrConnectWithoutAuthorInput: + type: object + properties: + where: + $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + create: + oneOf: + - $ref: '#/components/schemas/Post_ItemCreateWithoutAuthorInput' + - $ref: '#/components/schemas/Post_ItemUncheckedCreateWithoutAuthorInput' + required: + - where + - create + Post_ItemCreateManyAuthorInputEnvelope: + type: object + properties: + data: + oneOf: + - $ref: '#/components/schemas/Post_ItemCreateManyAuthorInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemCreateManyAuthorInput' + skipDuplicates: + type: boolean + required: + - data + ProfileCreateWithoutUserInput: + type: object + properties: + id: + type: string + image: + oneOf: + - type: 'null' + - type: string + ProfileUncheckedCreateWithoutUserInput: + type: object + properties: + id: + type: string + image: + oneOf: + - type: 'null' + - type: string + ProfileCreateOrConnectWithoutUserInput: + type: object + properties: + where: + $ref: '#/components/schemas/ProfileWhereUniqueInput' + create: + oneOf: + - $ref: '#/components/schemas/ProfileCreateWithoutUserInput' + - $ref: '#/components/schemas/ProfileUncheckedCreateWithoutUserInput' + required: + - where + - create + Post_ItemUpsertWithWhereUniqueWithoutAuthorInput: + type: object + properties: + where: + $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + update: + oneOf: + - $ref: '#/components/schemas/Post_ItemUpdateWithoutAuthorInput' + - $ref: '#/components/schemas/Post_ItemUncheckedUpdateWithoutAuthorInput' + create: + oneOf: + - $ref: '#/components/schemas/Post_ItemCreateWithoutAuthorInput' + - $ref: '#/components/schemas/Post_ItemUncheckedCreateWithoutAuthorInput' + required: + - where + - update + - create + Post_ItemUpdateWithWhereUniqueWithoutAuthorInput: + type: object + properties: + where: + $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + data: + oneOf: + - $ref: '#/components/schemas/Post_ItemUpdateWithoutAuthorInput' + - $ref: '#/components/schemas/Post_ItemUncheckedUpdateWithoutAuthorInput' + required: + - where + - data + Post_ItemUpdateManyWithWhereWithoutAuthorInput: + type: object + properties: + where: + $ref: '#/components/schemas/Post_ItemScalarWhereInput' + data: + oneOf: + - $ref: '#/components/schemas/Post_ItemUpdateManyMutationInput' + - $ref: '#/components/schemas/Post_ItemUncheckedUpdateManyWithoutAuthorInput' + required: + - where + - data + Post_ItemScalarWhereInput: + type: object + properties: + AND: + oneOf: + - $ref: '#/components/schemas/Post_ItemScalarWhereInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemScalarWhereInput' + OR: + type: array + items: + $ref: '#/components/schemas/Post_ItemScalarWhereInput' + NOT: + oneOf: + - $ref: '#/components/schemas/Post_ItemScalarWhereInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemScalarWhereInput' + id: + oneOf: + - $ref: '#/components/schemas/StringFilter' + - type: string + createdAt: + oneOf: + - $ref: '#/components/schemas/DateTimeFilter' + - type: string + format: date-time + updatedAt: + oneOf: + - $ref: '#/components/schemas/DateTimeFilter' + - type: string + format: date-time + title: + oneOf: + - $ref: '#/components/schemas/StringFilter' + - type: string + authorId: + oneOf: + - $ref: '#/components/schemas/StringNullableFilter' + - type: string + - type: 'null' + published: + oneOf: + - $ref: '#/components/schemas/BoolFilter' + - type: boolean + viewCount: + oneOf: + - $ref: '#/components/schemas/IntFilter' + - type: integer + notes: + oneOf: + - $ref: '#/components/schemas/StringNullableFilter' + - type: string + - type: 'null' + ProfileUpsertWithoutUserInput: + type: object + properties: + update: + oneOf: + - $ref: '#/components/schemas/ProfileUpdateWithoutUserInput' + - $ref: '#/components/schemas/ProfileUncheckedUpdateWithoutUserInput' + create: + oneOf: + - $ref: '#/components/schemas/ProfileCreateWithoutUserInput' + - $ref: '#/components/schemas/ProfileUncheckedCreateWithoutUserInput' + where: + $ref: '#/components/schemas/ProfileWhereInput' + required: + - update + - create + ProfileUpdateToOneWithWhereWithoutUserInput: + type: object + properties: + where: + $ref: '#/components/schemas/ProfileWhereInput' + data: + oneOf: + - $ref: '#/components/schemas/ProfileUpdateWithoutUserInput' + - $ref: '#/components/schemas/ProfileUncheckedUpdateWithoutUserInput' + required: + - data + ProfileUpdateWithoutUserInput: + type: object + properties: + id: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + image: + oneOf: + - type: string + - $ref: '#/components/schemas/NullableStringFieldUpdateOperationsInput' + - type: 'null' + ProfileUncheckedUpdateWithoutUserInput: + type: object + properties: + id: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + image: + oneOf: + - type: string + - $ref: '#/components/schemas/NullableStringFieldUpdateOperationsInput' + - type: 'null' + UserCreateWithoutProfileInput: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + email: + type: string + role: + $ref: '#/components/schemas/Role' + posts: + $ref: '#/components/schemas/Post_ItemCreateNestedManyWithoutAuthorInput' + required: + - email + UserUncheckedCreateWithoutProfileInput: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + email: + type: string + role: + $ref: '#/components/schemas/Role' + posts: + $ref: "#/components/schemas/Post_ItemUncheckedCreateNestedManyWithoutAuthorInpu\ + t" + required: + - email + UserCreateOrConnectWithoutProfileInput: + type: object + properties: + where: + $ref: '#/components/schemas/UserWhereUniqueInput' + create: + oneOf: + - $ref: '#/components/schemas/UserCreateWithoutProfileInput' + - $ref: '#/components/schemas/UserUncheckedCreateWithoutProfileInput' + required: + - where + - create + UserUpsertWithoutProfileInput: + type: object + properties: + update: + oneOf: + - $ref: '#/components/schemas/UserUpdateWithoutProfileInput' + - $ref: '#/components/schemas/UserUncheckedUpdateWithoutProfileInput' + create: + oneOf: + - $ref: '#/components/schemas/UserCreateWithoutProfileInput' + - $ref: '#/components/schemas/UserUncheckedCreateWithoutProfileInput' + where: + $ref: '#/components/schemas/UserWhereInput' + required: + - update + - create + UserUpdateToOneWithWhereWithoutProfileInput: + type: object + properties: + where: + $ref: '#/components/schemas/UserWhereInput' + data: + oneOf: + - $ref: '#/components/schemas/UserUpdateWithoutProfileInput' + - $ref: '#/components/schemas/UserUncheckedUpdateWithoutProfileInput' + required: + - data + UserUpdateWithoutProfileInput: + type: object + properties: + id: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + createdAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + updatedAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + email: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + role: + oneOf: + - $ref: '#/components/schemas/Role' + - $ref: '#/components/schemas/EnumroleFieldUpdateOperationsInput' + posts: + $ref: '#/components/schemas/Post_ItemUpdateManyWithoutAuthorNestedInput' + UserUncheckedUpdateWithoutProfileInput: + type: object + properties: + id: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + createdAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + updatedAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + email: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + role: + oneOf: + - $ref: '#/components/schemas/Role' + - $ref: '#/components/schemas/EnumroleFieldUpdateOperationsInput' + posts: + $ref: "#/components/schemas/Post_ItemUncheckedUpdateManyWithoutAuthorNestedInpu\ + t" + UserCreateWithoutPostsInput: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + email: + type: string + role: + $ref: '#/components/schemas/Role' + profile: + $ref: '#/components/schemas/ProfileCreateNestedOneWithoutUserInput' + required: + - email + UserUncheckedCreateWithoutPostsInput: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + email: + type: string + role: + $ref: '#/components/schemas/Role' + profile: + $ref: '#/components/schemas/ProfileUncheckedCreateNestedOneWithoutUserInput' + required: + - email + UserCreateOrConnectWithoutPostsInput: + type: object + properties: + where: + $ref: '#/components/schemas/UserWhereUniqueInput' + create: + oneOf: + - $ref: '#/components/schemas/UserCreateWithoutPostsInput' + - $ref: '#/components/schemas/UserUncheckedCreateWithoutPostsInput' + required: + - where + - create + UserUpsertWithoutPostsInput: + type: object + properties: + update: + oneOf: + - $ref: '#/components/schemas/UserUpdateWithoutPostsInput' + - $ref: '#/components/schemas/UserUncheckedUpdateWithoutPostsInput' + create: + oneOf: + - $ref: '#/components/schemas/UserCreateWithoutPostsInput' + - $ref: '#/components/schemas/UserUncheckedCreateWithoutPostsInput' + where: + $ref: '#/components/schemas/UserWhereInput' + required: + - update + - create + UserUpdateToOneWithWhereWithoutPostsInput: + type: object + properties: + where: + $ref: '#/components/schemas/UserWhereInput' + data: + oneOf: + - $ref: '#/components/schemas/UserUpdateWithoutPostsInput' + - $ref: '#/components/schemas/UserUncheckedUpdateWithoutPostsInput' + required: + - data + UserUpdateWithoutPostsInput: + type: object + properties: + id: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + createdAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + updatedAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + email: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + role: + oneOf: + - $ref: '#/components/schemas/Role' + - $ref: '#/components/schemas/EnumroleFieldUpdateOperationsInput' + profile: + $ref: '#/components/schemas/ProfileUpdateOneWithoutUserNestedInput' + UserUncheckedUpdateWithoutPostsInput: + type: object + properties: + id: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + createdAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + updatedAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + email: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + role: + oneOf: + - $ref: '#/components/schemas/Role' + - $ref: '#/components/schemas/EnumroleFieldUpdateOperationsInput' + profile: + $ref: '#/components/schemas/ProfileUncheckedUpdateOneWithoutUserNestedInput' + Post_ItemCreateManyAuthorInput: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + title: + type: string + published: + type: boolean + viewCount: + type: integer + notes: + oneOf: + - type: 'null' + - type: string + required: + - id + - title + Post_ItemUpdateWithoutAuthorInput: + type: object + properties: + id: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + createdAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + updatedAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + title: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + published: + oneOf: + - type: boolean + - $ref: '#/components/schemas/BoolFieldUpdateOperationsInput' + viewCount: + oneOf: + - type: integer + - $ref: '#/components/schemas/IntFieldUpdateOperationsInput' + notes: + oneOf: + - type: string + - $ref: '#/components/schemas/NullableStringFieldUpdateOperationsInput' + - type: 'null' + Post_ItemUncheckedUpdateWithoutAuthorInput: + type: object + properties: + id: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + createdAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + updatedAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + title: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + published: + oneOf: + - type: boolean + - $ref: '#/components/schemas/BoolFieldUpdateOperationsInput' + viewCount: + oneOf: + - type: integer + - $ref: '#/components/schemas/IntFieldUpdateOperationsInput' + notes: + oneOf: + - type: string + - $ref: '#/components/schemas/NullableStringFieldUpdateOperationsInput' + - type: 'null' + Post_ItemUncheckedUpdateManyWithoutAuthorInput: + type: object + properties: + id: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + createdAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + updatedAt: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + title: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + published: + oneOf: + - type: boolean + - $ref: '#/components/schemas/BoolFieldUpdateOperationsInput' + viewCount: + oneOf: + - type: integer + - $ref: '#/components/schemas/IntFieldUpdateOperationsInput' + notes: + oneOf: + - type: string + - $ref: '#/components/schemas/NullableStringFieldUpdateOperationsInput' + - type: 'null' + UserDefaultArgs: + type: object + properties: + select: + $ref: '#/components/schemas/UserSelect' + include: + $ref: '#/components/schemas/UserInclude' + ProfileDefaultArgs: + type: object + properties: + select: + $ref: '#/components/schemas/ProfileSelect' + include: + $ref: '#/components/schemas/ProfileInclude' + UserInclude: + type: object + properties: + posts: + oneOf: + - type: boolean + - $ref: '#/components/schemas/Post_ItemFindManyArgs' + profile: + oneOf: + - type: boolean + - $ref: '#/components/schemas/ProfileDefaultArgs' + _count: + oneOf: + - type: boolean + - $ref: '#/components/schemas/UserCountOutputTypeDefaultArgs' + ProfileInclude: + type: object + properties: + user: + oneOf: + - type: boolean + - $ref: '#/components/schemas/UserDefaultArgs' + Post_ItemInclude: + type: object + properties: + author: + oneOf: + - type: boolean + - $ref: '#/components/schemas/UserDefaultArgs' + UserCountOutputTypeSelect: + type: object + properties: + posts: + type: boolean + UserCountOutputTypeDefaultArgs: + type: object + properties: + select: + $ref: '#/components/schemas/UserCountOutputTypeSelect' + UserSelect: + type: object + properties: + id: + type: boolean + createdAt: + type: boolean + updatedAt: + type: boolean + email: + type: boolean + role: + type: boolean + posts: + oneOf: + - type: boolean + - $ref: '#/components/schemas/Post_ItemFindManyArgs' + profile: + oneOf: + - type: boolean + - $ref: '#/components/schemas/ProfileDefaultArgs' + _count: + oneOf: + - type: boolean + - $ref: '#/components/schemas/UserCountOutputTypeDefaultArgs' + ProfileSelect: + type: object + properties: + id: + type: boolean + image: + type: boolean + user: + oneOf: + - type: boolean + - $ref: '#/components/schemas/UserDefaultArgs' + userId: + type: boolean + Post_ItemSelect: + type: object + properties: + id: + type: boolean + createdAt: + type: boolean + updatedAt: + type: boolean + title: + type: boolean + author: + oneOf: + - type: boolean + - $ref: '#/components/schemas/UserDefaultArgs' + authorId: + type: boolean + published: + type: boolean + viewCount: + type: boolean + notes: + type: boolean + UserCountAggregateInput: + type: object + properties: + id: + type: boolean + createdAt: + type: boolean + updatedAt: + type: boolean + email: + type: boolean + role: + type: boolean + _all: + type: boolean + UserMinAggregateInput: + type: object + properties: + id: + type: boolean + createdAt: + type: boolean + updatedAt: + type: boolean + email: + type: boolean + role: + type: boolean + UserMaxAggregateInput: + type: object + properties: + id: + type: boolean + createdAt: + type: boolean + updatedAt: + type: boolean + email: + type: boolean + role: + type: boolean + ProfileCountAggregateInput: + type: object + properties: + id: + type: boolean + image: + type: boolean + userId: + type: boolean + _all: + type: boolean + ProfileMinAggregateInput: + type: object + properties: + id: + type: boolean + image: + type: boolean + userId: + type: boolean + ProfileMaxAggregateInput: + type: object + properties: + id: + type: boolean + image: + type: boolean + userId: + type: boolean + AggregateUser: + type: object + properties: + _count: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/UserCountAggregateOutputType' + _min: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/UserMinAggregateOutputType' + _max: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/UserMaxAggregateOutputType' + UserGroupByOutputType: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + email: + type: string + role: + $ref: '#/components/schemas/Role' + _count: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/UserCountAggregateOutputType' + _min: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/UserMinAggregateOutputType' + _max: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/UserMaxAggregateOutputType' + required: + - id + - createdAt + - updatedAt + - email + - role + AggregateProfile: + type: object + properties: + _count: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/ProfileCountAggregateOutputType' + _min: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/ProfileMinAggregateOutputType' + _max: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/ProfileMaxAggregateOutputType' + ProfileGroupByOutputType: + type: object + properties: + id: + type: string + image: + oneOf: + - type: 'null' + - type: string + userId: + type: string + _count: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/ProfileCountAggregateOutputType' + _min: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/ProfileMinAggregateOutputType' + _max: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/ProfileMaxAggregateOutputType' + required: + - id + - userId + AggregatePost_Item: + type: object + properties: + _count: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Post_ItemCountAggregateOutputType' + _avg: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Post_ItemAvgAggregateOutputType' + _sum: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Post_ItemSumAggregateOutputType' + _min: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Post_ItemMinAggregateOutputType' + _max: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Post_ItemMaxAggregateOutputType' + Post_ItemGroupByOutputType: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + title: + type: string + authorId: + oneOf: + - type: 'null' + - type: string + published: + type: boolean + viewCount: + type: integer + notes: + oneOf: + - type: 'null' + - type: string + _count: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Post_ItemCountAggregateOutputType' + _avg: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Post_ItemAvgAggregateOutputType' + _sum: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Post_ItemSumAggregateOutputType' + _min: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Post_ItemMinAggregateOutputType' + _max: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Post_ItemMaxAggregateOutputType' + required: + - id + - createdAt + - updatedAt + - title + - published + - viewCount + UserCountAggregateOutputType: + type: object + properties: + id: + type: integer + createdAt: + type: integer + updatedAt: + type: integer + email: + type: integer + role: + type: integer + _all: + type: integer + required: + - id + - createdAt + - updatedAt + - email + - role + - _all + UserMinAggregateOutputType: + type: object + properties: + id: + oneOf: + - type: 'null' + - type: string + createdAt: + oneOf: + - type: 'null' + - type: string + format: date-time + updatedAt: + oneOf: + - type: 'null' + - type: string + format: date-time + email: + oneOf: + - type: 'null' + - type: string + role: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Role' + UserMaxAggregateOutputType: + type: object + properties: + id: + oneOf: + - type: 'null' + - type: string + createdAt: + oneOf: + - type: 'null' + - type: string + format: date-time + updatedAt: + oneOf: + - type: 'null' + - type: string + format: date-time + email: + oneOf: + - type: 'null' + - type: string + role: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Role' + ProfileCountAggregateOutputType: + type: object + properties: + id: + type: integer + image: + type: integer + userId: + type: integer + _all: + type: integer + required: + - id + - image + - userId + - _all + ProfileMinAggregateOutputType: + type: object + properties: + id: + oneOf: + - type: 'null' + - type: string + image: + oneOf: + - type: 'null' + - type: string + userId: + oneOf: + - type: 'null' + - type: string + ProfileMaxAggregateOutputType: + type: object + properties: + id: + oneOf: + - type: 'null' + - type: string + image: + oneOf: + - type: 'null' + - type: string + userId: + oneOf: + - type: 'null' + - type: string + Post_ItemCountAggregateOutputType: + type: object + properties: + id: + type: integer + createdAt: + type: integer + updatedAt: + type: integer + title: + type: integer + authorId: + type: integer + published: + type: integer + viewCount: + type: integer + notes: + type: integer + _all: + type: integer + required: + - id + - createdAt + - updatedAt + - title + - authorId + - published + - viewCount + - notes + - _all + Post_ItemAvgAggregateOutputType: + type: object + properties: + viewCount: + oneOf: + - type: 'null' + - type: number + Post_ItemSumAggregateOutputType: + type: object + properties: + viewCount: + oneOf: + - type: 'null' + - type: integer + Post_ItemMinAggregateOutputType: + type: object + properties: + id: + oneOf: + - type: 'null' + - type: string + createdAt: + oneOf: + - type: 'null' + - type: string + format: date-time + updatedAt: + oneOf: + - type: 'null' + - type: string + format: date-time + title: + oneOf: + - type: 'null' + - type: string + authorId: + oneOf: + - type: 'null' + - type: string + published: + oneOf: + - type: 'null' + - type: boolean + viewCount: + oneOf: + - type: 'null' + - type: integer + notes: + oneOf: + - type: 'null' + - type: string + Post_ItemMaxAggregateOutputType: + type: object + properties: + id: + oneOf: + - type: 'null' + - type: string + createdAt: + oneOf: + - type: 'null' + - type: string + format: date-time + updatedAt: + oneOf: + - type: 'null' + - type: string + format: date-time + title: + oneOf: + - type: 'null' + - type: string + authorId: + oneOf: + - type: 'null' + - type: string + published: + oneOf: + - type: 'null' + - type: boolean + viewCount: + oneOf: + - type: 'null' + - type: integer + notes: + oneOf: + - type: 'null' + - type: string + _Meta: + type: object + description: Meta information about the request or response + properties: + serialization: + description: Serialization metadata + additionalProperties: true + _Error: + type: object + required: + - error + properties: + error: + type: object + required: + - message + properties: + prisma: + type: boolean + description: Indicates if the error occurred during a Prisma call + rejectedByPolicy: + type: boolean + description: Indicates if the error was due to rejection by a policy + code: + type: string + description: Prisma error code. Only available when "prisma" field is true. + message: + type: string + description: Error message + reason: + type: string + description: Detailed error reason + zodErrors: + type: object + additionalProperties: true + description: Zod validation errors if the error is due to data validation + failure + additionalProperties: true + BatchPayload: + type: object + properties: + count: + type: integer + UserCreateArgs: + type: object + required: + - data + properties: + select: + $ref: '#/components/schemas/UserSelect' + include: + $ref: '#/components/schemas/UserInclude' + data: + $ref: '#/components/schemas/UserCreateInput' + meta: + $ref: '#/components/schemas/_Meta' + UserCreateManyArgs: + type: object + required: + - data + properties: + data: + oneOf: + - $ref: '#/components/schemas/UserCreateManyInput' + - type: array + items: + $ref: '#/components/schemas/UserCreateManyInput' + skipDuplicates: + type: boolean + description: Do not insert records with unique fields or ID fields that already + exist. + meta: + $ref: '#/components/schemas/_Meta' + UserFindUniqueArgs: + type: object + required: + - where + properties: + select: + $ref: '#/components/schemas/UserSelect' + include: + $ref: '#/components/schemas/UserInclude' + where: + $ref: '#/components/schemas/UserWhereUniqueInput' + meta: + $ref: '#/components/schemas/_Meta' + UserFindFirstArgs: + type: object + properties: + select: + $ref: '#/components/schemas/UserSelect' + include: + $ref: '#/components/schemas/UserInclude' + where: + $ref: '#/components/schemas/UserWhereInput' + meta: + $ref: '#/components/schemas/_Meta' + UserFindManyArgs: + type: object + properties: + select: + $ref: '#/components/schemas/UserSelect' + include: + $ref: '#/components/schemas/UserInclude' + where: + $ref: '#/components/schemas/UserWhereInput' + meta: + $ref: '#/components/schemas/_Meta' + orderBy: + oneOf: + - $ref: '#/components/schemas/UserOrderByWithRelationInput' + - type: array + items: + $ref: '#/components/schemas/UserOrderByWithRelationInput' + cursor: + $ref: '#/components/schemas/UserWhereUniqueInput' + take: + type: integer + skip: + type: integer + UserUpdateArgs: + type: object + required: + - where + - data + properties: + select: + $ref: '#/components/schemas/UserSelect' + include: + $ref: '#/components/schemas/UserInclude' + where: + $ref: '#/components/schemas/UserWhereUniqueInput' + data: + $ref: '#/components/schemas/UserUpdateInput' + meta: + $ref: '#/components/schemas/_Meta' + UserUpdateManyArgs: + type: object + required: + - data + properties: + where: + $ref: '#/components/schemas/UserWhereInput' + data: + $ref: '#/components/schemas/UserUpdateManyMutationInput' + meta: + $ref: '#/components/schemas/_Meta' + UserUpsertArgs: + type: object + required: + - create + - update + - where + properties: + select: + $ref: '#/components/schemas/UserSelect' + include: + $ref: '#/components/schemas/UserInclude' + where: + $ref: '#/components/schemas/UserWhereUniqueInput' + create: + $ref: '#/components/schemas/UserCreateInput' + update: + $ref: '#/components/schemas/UserUpdateInput' + meta: + $ref: '#/components/schemas/_Meta' + UserDeleteUniqueArgs: + type: object + required: + - where + properties: + select: + $ref: '#/components/schemas/UserSelect' + include: + $ref: '#/components/schemas/UserInclude' + where: + $ref: '#/components/schemas/UserWhereUniqueInput' + meta: + $ref: '#/components/schemas/_Meta' + UserDeleteManyArgs: + type: object + properties: + where: + $ref: '#/components/schemas/UserWhereInput' + meta: + $ref: '#/components/schemas/_Meta' + UserCountArgs: + type: object + properties: + select: + $ref: '#/components/schemas/UserSelect' + where: + $ref: '#/components/schemas/UserWhereInput' + meta: + $ref: '#/components/schemas/_Meta' + UserAggregateArgs: + type: object + properties: + where: + $ref: '#/components/schemas/UserWhereInput' + orderBy: + $ref: '#/components/schemas/UserOrderByWithRelationInput' + cursor: + $ref: '#/components/schemas/UserWhereUniqueInput' + take: + type: integer + skip: + type: integer + _count: + oneOf: + - type: boolean + - $ref: '#/components/schemas/UserCountAggregateInput' + _min: + $ref: '#/components/schemas/UserMinAggregateInput' + _max: + $ref: '#/components/schemas/UserMaxAggregateInput' + meta: + $ref: '#/components/schemas/_Meta' + UserGroupByArgs: + type: object + properties: + where: + $ref: '#/components/schemas/UserWhereInput' + orderBy: + $ref: '#/components/schemas/UserOrderByWithRelationInput' + by: + $ref: '#/components/schemas/UserScalarFieldEnum' + having: + $ref: '#/components/schemas/UserScalarWhereWithAggregatesInput' + take: + type: integer + skip: + type: integer + _count: + oneOf: + - type: boolean + - $ref: '#/components/schemas/UserCountAggregateInput' + _min: + $ref: '#/components/schemas/UserMinAggregateInput' + _max: + $ref: '#/components/schemas/UserMaxAggregateInput' + meta: + $ref: '#/components/schemas/_Meta' + ProfileCreateArgs: + type: object + required: + - data + properties: + select: + $ref: '#/components/schemas/ProfileSelect' + include: + $ref: '#/components/schemas/ProfileInclude' + data: + $ref: '#/components/schemas/ProfileCreateInput' + meta: + $ref: '#/components/schemas/_Meta' + ProfileCreateManyArgs: + type: object + required: + - data + properties: + data: + oneOf: + - $ref: '#/components/schemas/ProfileCreateManyInput' + - type: array + items: + $ref: '#/components/schemas/ProfileCreateManyInput' + skipDuplicates: + type: boolean + description: Do not insert records with unique fields or ID fields that already + exist. + meta: + $ref: '#/components/schemas/_Meta' + ProfileFindUniqueArgs: + type: object + required: + - where + properties: + select: + $ref: '#/components/schemas/ProfileSelect' + include: + $ref: '#/components/schemas/ProfileInclude' + where: + $ref: '#/components/schemas/ProfileWhereUniqueInput' + meta: + $ref: '#/components/schemas/_Meta' + ProfileFindFirstArgs: + type: object + properties: + select: + $ref: '#/components/schemas/ProfileSelect' + include: + $ref: '#/components/schemas/ProfileInclude' + where: + $ref: '#/components/schemas/ProfileWhereInput' + meta: + $ref: '#/components/schemas/_Meta' + ProfileFindManyArgs: + type: object + properties: + select: + $ref: '#/components/schemas/ProfileSelect' + include: + $ref: '#/components/schemas/ProfileInclude' + where: + $ref: '#/components/schemas/ProfileWhereInput' + meta: + $ref: '#/components/schemas/_Meta' + orderBy: + oneOf: + - $ref: '#/components/schemas/ProfileOrderByWithRelationInput' + - type: array + items: + $ref: '#/components/schemas/ProfileOrderByWithRelationInput' + cursor: + $ref: '#/components/schemas/ProfileWhereUniqueInput' + take: + type: integer + skip: + type: integer + ProfileUpdateArgs: + type: object + required: + - where + - data + properties: + select: + $ref: '#/components/schemas/ProfileSelect' + include: + $ref: '#/components/schemas/ProfileInclude' + where: + $ref: '#/components/schemas/ProfileWhereUniqueInput' + data: + $ref: '#/components/schemas/ProfileUpdateInput' + meta: + $ref: '#/components/schemas/_Meta' + ProfileUpdateManyArgs: + type: object + required: + - data + properties: + where: + $ref: '#/components/schemas/ProfileWhereInput' + data: + $ref: '#/components/schemas/ProfileUpdateManyMutationInput' + meta: + $ref: '#/components/schemas/_Meta' + ProfileUpsertArgs: + type: object + required: + - create + - update + - where + properties: + select: + $ref: '#/components/schemas/ProfileSelect' + include: + $ref: '#/components/schemas/ProfileInclude' + where: + $ref: '#/components/schemas/ProfileWhereUniqueInput' + create: + $ref: '#/components/schemas/ProfileCreateInput' + update: + $ref: '#/components/schemas/ProfileUpdateInput' + meta: + $ref: '#/components/schemas/_Meta' + ProfileDeleteUniqueArgs: + type: object + required: + - where + properties: + select: + $ref: '#/components/schemas/ProfileSelect' + include: + $ref: '#/components/schemas/ProfileInclude' + where: + $ref: '#/components/schemas/ProfileWhereUniqueInput' + meta: + $ref: '#/components/schemas/_Meta' + ProfileDeleteManyArgs: + type: object + properties: + where: + $ref: '#/components/schemas/ProfileWhereInput' + meta: + $ref: '#/components/schemas/_Meta' + ProfileCountArgs: + type: object + properties: + select: + $ref: '#/components/schemas/ProfileSelect' + where: + $ref: '#/components/schemas/ProfileWhereInput' + meta: + $ref: '#/components/schemas/_Meta' + ProfileAggregateArgs: + type: object + properties: + where: + $ref: '#/components/schemas/ProfileWhereInput' + orderBy: + $ref: '#/components/schemas/ProfileOrderByWithRelationInput' + cursor: + $ref: '#/components/schemas/ProfileWhereUniqueInput' + take: + type: integer + skip: + type: integer + _count: + oneOf: + - type: boolean + - $ref: '#/components/schemas/ProfileCountAggregateInput' + _min: + $ref: '#/components/schemas/ProfileMinAggregateInput' + _max: + $ref: '#/components/schemas/ProfileMaxAggregateInput' + meta: + $ref: '#/components/schemas/_Meta' + ProfileGroupByArgs: + type: object + properties: + where: + $ref: '#/components/schemas/ProfileWhereInput' + orderBy: + $ref: '#/components/schemas/ProfileOrderByWithRelationInput' + by: + $ref: '#/components/schemas/ProfileScalarFieldEnum' + having: + $ref: '#/components/schemas/ProfileScalarWhereWithAggregatesInput' + take: + type: integer + skip: + type: integer + _count: + oneOf: + - type: boolean + - $ref: '#/components/schemas/ProfileCountAggregateInput' + _min: + $ref: '#/components/schemas/ProfileMinAggregateInput' + _max: + $ref: '#/components/schemas/ProfileMaxAggregateInput' + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemCreateArgs: + type: object + required: + - data + properties: + select: + $ref: '#/components/schemas/Post_ItemSelect' + include: + $ref: '#/components/schemas/Post_ItemInclude' + data: + $ref: '#/components/schemas/Post_ItemCreateInput' + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemCreateManyArgs: + type: object + required: + - data + properties: + data: + oneOf: + - $ref: '#/components/schemas/Post_ItemCreateManyInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemCreateManyInput' + skipDuplicates: + type: boolean + description: Do not insert records with unique fields or ID fields that already + exist. + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemFindUniqueArgs: + type: object + required: + - where + properties: + select: + $ref: '#/components/schemas/Post_ItemSelect' + include: + $ref: '#/components/schemas/Post_ItemInclude' + where: + $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemFindFirstArgs: + type: object + properties: + select: + $ref: '#/components/schemas/Post_ItemSelect' + include: + $ref: '#/components/schemas/Post_ItemInclude' + where: + $ref: '#/components/schemas/Post_ItemWhereInput' + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemFindManyArgs: + type: object + properties: + select: + $ref: '#/components/schemas/Post_ItemSelect' + include: + $ref: '#/components/schemas/Post_ItemInclude' + where: + $ref: '#/components/schemas/Post_ItemWhereInput' + meta: + $ref: '#/components/schemas/_Meta' + orderBy: + oneOf: + - $ref: '#/components/schemas/Post_ItemOrderByWithRelationInput' + - type: array + items: + $ref: '#/components/schemas/Post_ItemOrderByWithRelationInput' + cursor: + $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + take: + type: integer + skip: + type: integer + Post_ItemUpdateArgs: + type: object + required: + - where + - data + properties: + select: + $ref: '#/components/schemas/Post_ItemSelect' + include: + $ref: '#/components/schemas/Post_ItemInclude' + where: + $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + data: + $ref: '#/components/schemas/Post_ItemUpdateInput' + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemUpdateManyArgs: + type: object + required: + - data + properties: + where: + $ref: '#/components/schemas/Post_ItemWhereInput' + data: + $ref: '#/components/schemas/Post_ItemUpdateManyMutationInput' + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemUpsertArgs: + type: object + required: + - create + - update + - where + properties: + select: + $ref: '#/components/schemas/Post_ItemSelect' + include: + $ref: '#/components/schemas/Post_ItemInclude' + where: + $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + create: + $ref: '#/components/schemas/Post_ItemCreateInput' + update: + $ref: '#/components/schemas/Post_ItemUpdateInput' + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemDeleteUniqueArgs: + type: object + required: + - where + properties: + select: + $ref: '#/components/schemas/Post_ItemSelect' + include: + $ref: '#/components/schemas/Post_ItemInclude' + where: + $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemDeleteManyArgs: + type: object + properties: + where: + $ref: '#/components/schemas/Post_ItemWhereInput' + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemCountArgs: + type: object + properties: + select: + $ref: '#/components/schemas/Post_ItemSelect' + where: + $ref: '#/components/schemas/Post_ItemWhereInput' + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemAggregateArgs: + type: object + properties: + where: + $ref: '#/components/schemas/Post_ItemWhereInput' + orderBy: + $ref: '#/components/schemas/Post_ItemOrderByWithRelationInput' + cursor: + $ref: '#/components/schemas/Post_ItemWhereUniqueInput' + take: + type: integer + skip: + type: integer + meta: + $ref: '#/components/schemas/_Meta' + Post_ItemGroupByArgs: + type: object + properties: + where: + $ref: '#/components/schemas/Post_ItemWhereInput' + orderBy: + $ref: '#/components/schemas/Post_ItemOrderByWithRelationInput' + by: + $ref: '#/components/schemas/Post_ItemScalarFieldEnum' + having: + $ref: '#/components/schemas/Post_ItemScalarWhereWithAggregatesInput' + take: + type: integer + skip: + type: integer + meta: + $ref: '#/components/schemas/_Meta' +paths: + /user/create: + post: + operationId: createUser + description: Create a new User + tags: + - user + responses: + '201': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/User' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UserCreateArgs' + /user/createMany: + post: + operationId: createManyUser + description: Create several User + tags: + - user + responses: + '201': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BatchPayload' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UserCreateManyArgs' + /user/findUnique: + get: + operationId: findUniqueUser + description: Find one unique User + tags: + - user + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/User' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/UserFindUniqueArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /user/findFirst: + get: + operationId: findFirstUser + description: Find the first User matching the given condition + tags: + - user + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/User' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/UserFindFirstArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /user/findMany: + get: + operationId: findManyUser + description: Find users matching the given conditions + tags: + - user + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + type: array + items: + $ref: '#/components/schemas/User' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/UserFindManyArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /user/update: + patch: + operationId: updateUser + description: Update a User + tags: + - user + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/User' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UserUpdateArgs' + /user/updateMany: + patch: + operationId: updateManyUser + description: Update Users matching the given condition + tags: + - user + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BatchPayload' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UserUpdateManyArgs' + /user/upsert: + post: + operationId: upsertUser + description: Upsert a User + tags: + - user + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/User' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UserUpsertArgs' + /user/dodelete: + put: + operationId: deleteUser + description: Delete a unique user + tags: + - delete + - user + summary: Delete a user yeah yeah + deprecated: true + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/User' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UserDeleteUniqueArgs' + /user/deleteMany: + delete: + operationId: deleteManyUser + description: Delete Users matching the given condition + tags: + - user + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BatchPayload' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/UserDeleteManyArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /user/count: + get: + operationId: countUser + description: Find a list of User + tags: + - user + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + oneOf: + - type: integer + - $ref: '#/components/schemas/UserCountAggregateOutputType' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/UserCountArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /user/aggregate: + get: + operationId: aggregateUser + description: Aggregate Users + tags: + - user + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/AggregateUser' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/UserAggregateArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /user/groupBy: + get: + operationId: groupByUser + description: Group Users by fields + tags: + - user + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + type: array + items: + $ref: '#/components/schemas/UserGroupByOutputType' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/UserGroupByArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /profile/create: + post: + operationId: createProfile + description: Create a new Profile + tags: + - profile + responses: + '201': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Profile' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileCreateArgs' + /profile/createMany: + post: + operationId: createManyProfile + description: Create several Profile + tags: + - profile + responses: + '201': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BatchPayload' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileCreateManyArgs' + /profile/findUnique: + get: + operationId: findUniqueProfile + description: Find one unique Profile + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Profile' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileFindUniqueArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /profile/findFirst: + get: + operationId: findFirstProfile + description: Find the first Profile matching the given condition + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Profile' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileFindFirstArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /profile/findMany: + get: + operationId: findManyProfile + description: Find a list of Profile + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + type: array + items: + $ref: '#/components/schemas/Profile' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileFindManyArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /profile/update: + patch: + operationId: updateProfile + description: Update a Profile + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Profile' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileUpdateArgs' + /profile/updateMany: + patch: + operationId: updateManyProfile + description: Update Profiles matching the given condition + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BatchPayload' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileUpdateManyArgs' + /profile/upsert: + post: + operationId: upsertProfile + description: Upsert a Profile + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Profile' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileUpsertArgs' + /profile/delete: + delete: + operationId: deleteProfile + description: Delete one unique Profile + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Profile' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileDeleteUniqueArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /profile/deleteMany: + delete: + operationId: deleteManyProfile + description: Delete Profiles matching the given condition + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BatchPayload' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileDeleteManyArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /profile/count: + get: + operationId: countProfile + description: Find a list of Profile + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + oneOf: + - type: integer + - $ref: '#/components/schemas/ProfileCountAggregateOutputType' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileCountArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /profile/aggregate: + get: + operationId: aggregateProfile + description: Aggregate Profiles + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/AggregateProfile' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileAggregateArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /profile/groupBy: + get: + operationId: groupByProfile + description: Group Profiles by fields + tags: + - profile + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + type: array + items: + $ref: '#/components/schemas/ProfileGroupByOutputType' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileGroupByArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /post_Item/create: + post: + operationId: createPost_Item + description: Create a new Post_Item + tags: + - post_Item + responses: + '201': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Post_Item' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemCreateArgs' + /post_Item/createMany: + post: + operationId: createManyPost_Item + description: Create several Post_Item + tags: + - post_Item + responses: + '201': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BatchPayload' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemCreateManyArgs' + /post_Item/findUnique: + get: + operationId: findUniquePost_Item + description: Find one unique Post_Item + tags: + - post_Item + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Post_Item' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemFindUniqueArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /post_Item/findFirst: + get: + operationId: findFirstPost_Item + description: Find the first Post_Item matching the given condition + tags: + - post_Item + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Post_Item' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemFindFirstArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /post_Item/update: + patch: + operationId: updatePost_Item + description: Update a Post_Item + tags: + - post_Item + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Post_Item' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemUpdateArgs' + /post_Item/updateMany: + patch: + operationId: updateManyPost_Item + description: Update Post_Items matching the given condition + tags: + - post_Item + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BatchPayload' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemUpdateManyArgs' + /post_Item/upsert: + post: + operationId: upsertPost_Item + description: Upsert a Post_Item + tags: + - post_Item + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Post_Item' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemUpsertArgs' + /post_Item/delete: + delete: + operationId: deletePost_Item + description: Delete one unique Post_Item + tags: + - post_Item + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Post_Item' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemDeleteUniqueArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /post_Item/deleteMany: + delete: + operationId: deleteManyPost_Item + description: Delete Post_Items matching the given condition + tags: + - post_Item + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BatchPayload' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemDeleteManyArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /post_Item/count: + get: + operationId: countPost_Item + description: Find a list of Post_Item + tags: + - post_Item + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + oneOf: + - type: integer + - $ref: '#/components/schemas/Post_ItemCountAggregateOutputType' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemCountArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /post_Item/aggregate: + get: + operationId: aggregatePost_Item + description: Aggregate Post_Items + tags: + - post_Item + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/AggregatePost_Item' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemAggregateArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /post_Item/groupBy: + get: + operationId: groupByPost_Item + description: Group Post_Items by fields + tags: + - post_Item + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + type: array + items: + $ref: '#/components/schemas/Post_ItemGroupByOutputType' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/Post_ItemGroupByArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} diff --git a/packages/server/test/openapi/migrated/baseline/rpc-type-coverage-3.1.0.baseline.yaml b/packages/server/test/openapi/migrated/baseline/rpc-type-coverage-3.1.0.baseline.yaml new file mode 100644 index 000000000..5f3e59136 --- /dev/null +++ b/packages/server/test/openapi/migrated/baseline/rpc-type-coverage-3.1.0.baseline.yaml @@ -0,0 +1,3174 @@ +openapi: 3.1.0 +info: + title: ZenStack Generated API + version: 1.0.0 +tags: + - name: foo + description: Foo operations +components: + schemas: + FooScalarFieldEnum: + type: string + enum: + - id + - string + - int + - bigInt + - date + - float + - decimal + - boolean + - bytes + - json + - plainJson + SortOrder: + type: string + enum: + - asc + - desc + NullableJsonNullValueInput: + type: string + enum: + - DbNull + - JsonNull + JsonNullValueInput: + type: string + enum: + - JsonNull + QueryMode: + type: string + enum: + - default + - insensitive + JsonNullValueFilter: + type: string + enum: + - DbNull + - JsonNull + - AnyNull + NullsOrder: + type: string + enum: + - first + - last + Foo: + type: object + properties: + id: + type: string + string: + type: string + int: + type: integer + bigInt: + type: integer + date: + type: string + format: date-time + float: + type: number + decimal: + oneOf: + - type: string + - type: number + boolean: + type: boolean + bytes: + oneOf: + - type: 'null' + - type: string + format: byte + json: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Meta' + plainJson: {} + required: + - id + - string + - int + - bigInt + - date + - float + - decimal + - boolean + - plainJson + Meta: + type: object + description: The "Meta" TypeDef + properties: + something: + type: string + required: + - something + FooWhereInput: + type: object + properties: + AND: + oneOf: + - $ref: '#/components/schemas/FooWhereInput' + - type: array + items: + $ref: '#/components/schemas/FooWhereInput' + OR: + type: array + items: + $ref: '#/components/schemas/FooWhereInput' + NOT: + oneOf: + - $ref: '#/components/schemas/FooWhereInput' + - type: array + items: + $ref: '#/components/schemas/FooWhereInput' + id: + oneOf: + - $ref: '#/components/schemas/StringFilter' + - type: string + string: + oneOf: + - $ref: '#/components/schemas/StringFilter' + - type: string + int: + oneOf: + - $ref: '#/components/schemas/IntFilter' + - type: integer + bigInt: + oneOf: + - $ref: '#/components/schemas/BigIntFilter' + - type: integer + date: + oneOf: + - $ref: '#/components/schemas/DateTimeFilter' + - type: string + format: date-time + float: + oneOf: + - $ref: '#/components/schemas/FloatFilter' + - type: number + decimal: + oneOf: + - $ref: '#/components/schemas/DecimalFilter' + - oneOf: + - type: string + - type: number + boolean: + oneOf: + - $ref: '#/components/schemas/BoolFilter' + - type: boolean + bytes: + oneOf: + - $ref: '#/components/schemas/BytesNullableFilter' + - type: string + format: byte + - type: 'null' + json: + $ref: '#/components/schemas/JsonNullableFilter' + plainJson: + $ref: '#/components/schemas/JsonFilter' + FooOrderByWithRelationInput: + type: object + properties: + id: + $ref: '#/components/schemas/SortOrder' + string: + $ref: '#/components/schemas/SortOrder' + int: + $ref: '#/components/schemas/SortOrder' + bigInt: + $ref: '#/components/schemas/SortOrder' + date: + $ref: '#/components/schemas/SortOrder' + float: + $ref: '#/components/schemas/SortOrder' + decimal: + $ref: '#/components/schemas/SortOrder' + boolean: + $ref: '#/components/schemas/SortOrder' + bytes: + oneOf: + - $ref: '#/components/schemas/SortOrder' + - $ref: '#/components/schemas/SortOrderInput' + json: + oneOf: + - $ref: '#/components/schemas/SortOrder' + - $ref: '#/components/schemas/SortOrderInput' + plainJson: + $ref: '#/components/schemas/SortOrder' + FooWhereUniqueInput: + type: object + properties: + id: + type: string + AND: + oneOf: + - $ref: '#/components/schemas/FooWhereInput' + - type: array + items: + $ref: '#/components/schemas/FooWhereInput' + OR: + type: array + items: + $ref: '#/components/schemas/FooWhereInput' + NOT: + oneOf: + - $ref: '#/components/schemas/FooWhereInput' + - type: array + items: + $ref: '#/components/schemas/FooWhereInput' + string: + oneOf: + - $ref: '#/components/schemas/StringFilter' + - type: string + int: + oneOf: + - $ref: '#/components/schemas/IntFilter' + - type: integer + bigInt: + oneOf: + - $ref: '#/components/schemas/BigIntFilter' + - type: integer + date: + oneOf: + - $ref: '#/components/schemas/DateTimeFilter' + - type: string + format: date-time + float: + oneOf: + - $ref: '#/components/schemas/FloatFilter' + - type: number + decimal: + oneOf: + - $ref: '#/components/schemas/DecimalFilter' + - oneOf: + - type: string + - type: number + boolean: + oneOf: + - $ref: '#/components/schemas/BoolFilter' + - type: boolean + bytes: + oneOf: + - $ref: '#/components/schemas/BytesNullableFilter' + - type: string + format: byte + - type: 'null' + json: + $ref: '#/components/schemas/JsonNullableFilter' + plainJson: + $ref: '#/components/schemas/JsonFilter' + FooScalarWhereWithAggregatesInput: + type: object + properties: + AND: + oneOf: + - $ref: '#/components/schemas/FooScalarWhereWithAggregatesInput' + - type: array + items: + $ref: '#/components/schemas/FooScalarWhereWithAggregatesInput' + OR: + type: array + items: + $ref: '#/components/schemas/FooScalarWhereWithAggregatesInput' + NOT: + oneOf: + - $ref: '#/components/schemas/FooScalarWhereWithAggregatesInput' + - type: array + items: + $ref: '#/components/schemas/FooScalarWhereWithAggregatesInput' + id: + oneOf: + - $ref: '#/components/schemas/StringWithAggregatesFilter' + - type: string + string: + oneOf: + - $ref: '#/components/schemas/StringWithAggregatesFilter' + - type: string + int: + oneOf: + - $ref: '#/components/schemas/IntWithAggregatesFilter' + - type: integer + bigInt: + oneOf: + - $ref: '#/components/schemas/BigIntWithAggregatesFilter' + - type: integer + date: + oneOf: + - $ref: '#/components/schemas/DateTimeWithAggregatesFilter' + - type: string + format: date-time + float: + oneOf: + - $ref: '#/components/schemas/FloatWithAggregatesFilter' + - type: number + decimal: + oneOf: + - $ref: '#/components/schemas/DecimalWithAggregatesFilter' + - oneOf: + - type: string + - type: number + boolean: + oneOf: + - $ref: '#/components/schemas/BoolWithAggregatesFilter' + - type: boolean + bytes: + oneOf: + - $ref: '#/components/schemas/BytesNullableWithAggregatesFilter' + - type: string + format: byte + - type: 'null' + json: + $ref: '#/components/schemas/JsonNullableWithAggregatesFilter' + plainJson: + $ref: '#/components/schemas/JsonWithAggregatesFilter' + FooCreateInput: + type: object + properties: + id: + type: string + string: + type: string + int: + type: integer + bigInt: + type: integer + date: + type: string + format: date-time + float: + type: number + decimal: + oneOf: + - type: string + - type: number + boolean: + type: boolean + bytes: + oneOf: + - type: 'null' + - type: string + format: byte + json: + oneOf: + - $ref: '#/components/schemas/NullableJsonNullValueInput' + - {} + plainJson: + oneOf: + - $ref: '#/components/schemas/JsonNullValueInput' + - {} + required: + - string + - int + - bigInt + - date + - float + - decimal + - boolean + - plainJson + FooUpdateInput: + type: object + properties: + id: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + string: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + int: + oneOf: + - type: integer + - $ref: '#/components/schemas/IntFieldUpdateOperationsInput' + bigInt: + oneOf: + - type: integer + - $ref: '#/components/schemas/BigIntFieldUpdateOperationsInput' + date: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + float: + oneOf: + - type: number + - $ref: '#/components/schemas/FloatFieldUpdateOperationsInput' + decimal: + oneOf: + - oneOf: + - type: string + - type: number + - $ref: '#/components/schemas/DecimalFieldUpdateOperationsInput' + boolean: + oneOf: + - type: boolean + - $ref: '#/components/schemas/BoolFieldUpdateOperationsInput' + bytes: + oneOf: + - type: string + format: byte + - $ref: '#/components/schemas/NullableBytesFieldUpdateOperationsInput' + - type: 'null' + json: + oneOf: + - $ref: '#/components/schemas/NullableJsonNullValueInput' + - {} + plainJson: + oneOf: + - $ref: '#/components/schemas/JsonNullValueInput' + - {} + FooCreateManyInput: + type: object + properties: + id: + type: string + string: + type: string + int: + type: integer + bigInt: + type: integer + date: + type: string + format: date-time + float: + type: number + decimal: + oneOf: + - type: string + - type: number + boolean: + type: boolean + bytes: + oneOf: + - type: 'null' + - type: string + format: byte + json: + oneOf: + - $ref: '#/components/schemas/NullableJsonNullValueInput' + - {} + plainJson: + oneOf: + - $ref: '#/components/schemas/JsonNullValueInput' + - {} + required: + - string + - int + - bigInt + - date + - float + - decimal + - boolean + - plainJson + FooUpdateManyMutationInput: + type: object + properties: + id: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + string: + oneOf: + - type: string + - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' + int: + oneOf: + - type: integer + - $ref: '#/components/schemas/IntFieldUpdateOperationsInput' + bigInt: + oneOf: + - type: integer + - $ref: '#/components/schemas/BigIntFieldUpdateOperationsInput' + date: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' + float: + oneOf: + - type: number + - $ref: '#/components/schemas/FloatFieldUpdateOperationsInput' + decimal: + oneOf: + - oneOf: + - type: string + - type: number + - $ref: '#/components/schemas/DecimalFieldUpdateOperationsInput' + boolean: + oneOf: + - type: boolean + - $ref: '#/components/schemas/BoolFieldUpdateOperationsInput' + bytes: + oneOf: + - type: string + format: byte + - $ref: '#/components/schemas/NullableBytesFieldUpdateOperationsInput' + - type: 'null' + json: + oneOf: + - $ref: '#/components/schemas/NullableJsonNullValueInput' + - {} + plainJson: + oneOf: + - $ref: '#/components/schemas/JsonNullValueInput' + - {} + StringFilter: + type: object + properties: + equals: + type: string + in: + type: array + items: + type: string + notIn: + type: array + items: + type: string + lt: + type: string + lte: + type: string + gt: + type: string + gte: + type: string + contains: + type: string + startsWith: + type: string + endsWith: + type: string + mode: + $ref: '#/components/schemas/QueryMode' + not: + oneOf: + - type: string + - $ref: '#/components/schemas/NestedStringFilter' + IntFilter: + type: object + properties: + equals: + type: integer + in: + type: array + items: + type: integer + notIn: + type: array + items: + type: integer + lt: + type: integer + lte: + type: integer + gt: + type: integer + gte: + type: integer + not: + oneOf: + - type: integer + - $ref: '#/components/schemas/NestedIntFilter' + BigIntFilter: + type: object + properties: + equals: + type: integer + in: + type: array + items: + type: integer + notIn: + type: array + items: + type: integer + lt: + type: integer + lte: + type: integer + gt: + type: integer + gte: + type: integer + not: + oneOf: + - type: integer + - $ref: '#/components/schemas/NestedBigIntFilter' + DateTimeFilter: + type: object + properties: + equals: + type: string + format: date-time + in: + type: array + items: + type: string + format: date-time + notIn: + type: array + items: + type: string + format: date-time + lt: + type: string + format: date-time + lte: + type: string + format: date-time + gt: + type: string + format: date-time + gte: + type: string + format: date-time + not: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/NestedDateTimeFilter' + FloatFilter: + type: object + properties: + equals: + type: number + in: + type: array + items: + type: number + notIn: + type: array + items: + type: number + lt: + type: number + lte: + type: number + gt: + type: number + gte: + type: number + not: + oneOf: + - type: number + - $ref: '#/components/schemas/NestedFloatFilter' + DecimalFilter: + type: object + properties: + equals: + oneOf: + - type: string + - type: number + in: + type: array + items: + oneOf: + - type: string + - type: number + notIn: + type: array + items: + oneOf: + - type: string + - type: number + lt: + oneOf: + - type: string + - type: number + lte: + oneOf: + - type: string + - type: number + gt: + oneOf: + - type: string + - type: number + gte: + oneOf: + - type: string + - type: number + not: + oneOf: + - oneOf: + - type: string + - type: number + - $ref: '#/components/schemas/NestedDecimalFilter' + BoolFilter: + type: object + properties: + equals: + type: boolean + not: + oneOf: + - type: boolean + - $ref: '#/components/schemas/NestedBoolFilter' + BytesNullableFilter: + type: object + properties: + equals: + oneOf: + - type: 'null' + - type: string + format: byte + in: + oneOf: + - type: 'null' + - type: array + items: + type: string + format: byte + notIn: + oneOf: + - type: 'null' + - type: array + items: + type: string + format: byte + not: + oneOf: + - type: string + format: byte + - $ref: '#/components/schemas/NestedBytesNullableFilter' + - type: 'null' + JsonNullableFilter: + type: object + properties: + equals: + oneOf: + - {} + - $ref: '#/components/schemas/JsonNullValueFilter' + path: + type: array + items: + type: string + mode: + $ref: '#/components/schemas/QueryMode' + string_contains: + type: string + string_starts_with: + type: string + string_ends_with: + type: string + array_starts_with: + oneOf: + - type: 'null' + - {} + array_ends_with: + oneOf: + - type: 'null' + - {} + array_contains: + oneOf: + - type: 'null' + - {} + lt: {} + lte: {} + gt: {} + gte: {} + not: + oneOf: + - {} + - $ref: '#/components/schemas/JsonNullValueFilter' + JsonFilter: + type: object + properties: + equals: + oneOf: + - {} + - $ref: '#/components/schemas/JsonNullValueFilter' + path: + type: array + items: + type: string + mode: + $ref: '#/components/schemas/QueryMode' + string_contains: + type: string + string_starts_with: + type: string + string_ends_with: + type: string + array_starts_with: + oneOf: + - type: 'null' + - {} + array_ends_with: + oneOf: + - type: 'null' + - {} + array_contains: + oneOf: + - type: 'null' + - {} + lt: {} + lte: {} + gt: {} + gte: {} + not: + oneOf: + - {} + - $ref: '#/components/schemas/JsonNullValueFilter' + SortOrderInput: + type: object + properties: + sort: + $ref: '#/components/schemas/SortOrder' + nulls: + $ref: '#/components/schemas/NullsOrder' + required: + - sort + StringWithAggregatesFilter: + type: object + properties: + equals: + type: string + in: + type: array + items: + type: string + notIn: + type: array + items: + type: string + lt: + type: string + lte: + type: string + gt: + type: string + gte: + type: string + contains: + type: string + startsWith: + type: string + endsWith: + type: string + mode: + $ref: '#/components/schemas/QueryMode' + not: + oneOf: + - type: string + - $ref: '#/components/schemas/NestedStringWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _min: + $ref: '#/components/schemas/NestedStringFilter' + _max: + $ref: '#/components/schemas/NestedStringFilter' + IntWithAggregatesFilter: + type: object + properties: + equals: + type: integer + in: + type: array + items: + type: integer + notIn: + type: array + items: + type: integer + lt: + type: integer + lte: + type: integer + gt: + type: integer + gte: + type: integer + not: + oneOf: + - type: integer + - $ref: '#/components/schemas/NestedIntWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _avg: + $ref: '#/components/schemas/NestedFloatFilter' + _sum: + $ref: '#/components/schemas/NestedIntFilter' + _min: + $ref: '#/components/schemas/NestedIntFilter' + _max: + $ref: '#/components/schemas/NestedIntFilter' + BigIntWithAggregatesFilter: + type: object + properties: + equals: + type: integer + in: + type: array + items: + type: integer + notIn: + type: array + items: + type: integer + lt: + type: integer + lte: + type: integer + gt: + type: integer + gte: + type: integer + not: + oneOf: + - type: integer + - $ref: '#/components/schemas/NestedBigIntWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _avg: + $ref: '#/components/schemas/NestedFloatFilter' + _sum: + $ref: '#/components/schemas/NestedBigIntFilter' + _min: + $ref: '#/components/schemas/NestedBigIntFilter' + _max: + $ref: '#/components/schemas/NestedBigIntFilter' + DateTimeWithAggregatesFilter: + type: object + properties: + equals: + type: string + format: date-time + in: + type: array + items: + type: string + format: date-time + notIn: + type: array + items: + type: string + format: date-time + lt: + type: string + format: date-time + lte: + type: string + format: date-time + gt: + type: string + format: date-time + gte: + type: string + format: date-time + not: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/NestedDateTimeWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _min: + $ref: '#/components/schemas/NestedDateTimeFilter' + _max: + $ref: '#/components/schemas/NestedDateTimeFilter' + FloatWithAggregatesFilter: + type: object + properties: + equals: + type: number + in: + type: array + items: + type: number + notIn: + type: array + items: + type: number + lt: + type: number + lte: + type: number + gt: + type: number + gte: + type: number + not: + oneOf: + - type: number + - $ref: '#/components/schemas/NestedFloatWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _avg: + $ref: '#/components/schemas/NestedFloatFilter' + _sum: + $ref: '#/components/schemas/NestedFloatFilter' + _min: + $ref: '#/components/schemas/NestedFloatFilter' + _max: + $ref: '#/components/schemas/NestedFloatFilter' + DecimalWithAggregatesFilter: + type: object + properties: + equals: + oneOf: + - type: string + - type: number + in: + type: array + items: + oneOf: + - type: string + - type: number + notIn: + type: array + items: + oneOf: + - type: string + - type: number + lt: + oneOf: + - type: string + - type: number + lte: + oneOf: + - type: string + - type: number + gt: + oneOf: + - type: string + - type: number + gte: + oneOf: + - type: string + - type: number + not: + oneOf: + - oneOf: + - type: string + - type: number + - $ref: '#/components/schemas/NestedDecimalWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _avg: + $ref: '#/components/schemas/NestedDecimalFilter' + _sum: + $ref: '#/components/schemas/NestedDecimalFilter' + _min: + $ref: '#/components/schemas/NestedDecimalFilter' + _max: + $ref: '#/components/schemas/NestedDecimalFilter' + BoolWithAggregatesFilter: + type: object + properties: + equals: + type: boolean + not: + oneOf: + - type: boolean + - $ref: '#/components/schemas/NestedBoolWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _min: + $ref: '#/components/schemas/NestedBoolFilter' + _max: + $ref: '#/components/schemas/NestedBoolFilter' + BytesNullableWithAggregatesFilter: + type: object + properties: + equals: + oneOf: + - type: 'null' + - type: string + format: byte + in: + oneOf: + - type: 'null' + - type: array + items: + type: string + format: byte + notIn: + oneOf: + - type: 'null' + - type: array + items: + type: string + format: byte + not: + oneOf: + - type: string + format: byte + - $ref: '#/components/schemas/NestedBytesNullableWithAggregatesFilter' + - type: 'null' + _count: + $ref: '#/components/schemas/NestedIntNullableFilter' + _min: + $ref: '#/components/schemas/NestedBytesNullableFilter' + _max: + $ref: '#/components/schemas/NestedBytesNullableFilter' + JsonNullableWithAggregatesFilter: + type: object + properties: + equals: + oneOf: + - {} + - $ref: '#/components/schemas/JsonNullValueFilter' + path: + type: array + items: + type: string + mode: + $ref: '#/components/schemas/QueryMode' + string_contains: + type: string + string_starts_with: + type: string + string_ends_with: + type: string + array_starts_with: + oneOf: + - type: 'null' + - {} + array_ends_with: + oneOf: + - type: 'null' + - {} + array_contains: + oneOf: + - type: 'null' + - {} + lt: {} + lte: {} + gt: {} + gte: {} + not: + oneOf: + - {} + - $ref: '#/components/schemas/JsonNullValueFilter' + _count: + $ref: '#/components/schemas/NestedIntNullableFilter' + _min: + $ref: '#/components/schemas/NestedJsonNullableFilter' + _max: + $ref: '#/components/schemas/NestedJsonNullableFilter' + JsonWithAggregatesFilter: + type: object + properties: + equals: + oneOf: + - {} + - $ref: '#/components/schemas/JsonNullValueFilter' + path: + type: array + items: + type: string + mode: + $ref: '#/components/schemas/QueryMode' + string_contains: + type: string + string_starts_with: + type: string + string_ends_with: + type: string + array_starts_with: + oneOf: + - type: 'null' + - {} + array_ends_with: + oneOf: + - type: 'null' + - {} + array_contains: + oneOf: + - type: 'null' + - {} + lt: {} + lte: {} + gt: {} + gte: {} + not: + oneOf: + - {} + - $ref: '#/components/schemas/JsonNullValueFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _min: + $ref: '#/components/schemas/NestedJsonFilter' + _max: + $ref: '#/components/schemas/NestedJsonFilter' + StringFieldUpdateOperationsInput: + type: object + properties: + set: + type: string + IntFieldUpdateOperationsInput: + type: object + properties: + set: + type: integer + increment: + type: integer + decrement: + type: integer + multiply: + type: integer + divide: + type: integer + BigIntFieldUpdateOperationsInput: + type: object + properties: + set: + type: integer + increment: + type: integer + decrement: + type: integer + multiply: + type: integer + divide: + type: integer + DateTimeFieldUpdateOperationsInput: + type: object + properties: + set: + type: string + format: date-time + FloatFieldUpdateOperationsInput: + type: object + properties: + set: + type: number + increment: + type: number + decrement: + type: number + multiply: + type: number + divide: + type: number + DecimalFieldUpdateOperationsInput: + type: object + properties: + set: + oneOf: + - type: string + - type: number + increment: + oneOf: + - type: string + - type: number + decrement: + oneOf: + - type: string + - type: number + multiply: + oneOf: + - type: string + - type: number + divide: + oneOf: + - type: string + - type: number + BoolFieldUpdateOperationsInput: + type: object + properties: + set: + type: boolean + NullableBytesFieldUpdateOperationsInput: + type: object + properties: + set: + oneOf: + - type: 'null' + - type: string + format: byte + NestedStringFilter: + type: object + properties: + equals: + type: string + in: + type: array + items: + type: string + notIn: + type: array + items: + type: string + lt: + type: string + lte: + type: string + gt: + type: string + gte: + type: string + contains: + type: string + startsWith: + type: string + endsWith: + type: string + not: + oneOf: + - type: string + - $ref: '#/components/schemas/NestedStringFilter' + NestedIntFilter: + type: object + properties: + equals: + type: integer + in: + type: array + items: + type: integer + notIn: + type: array + items: + type: integer + lt: + type: integer + lte: + type: integer + gt: + type: integer + gte: + type: integer + not: + oneOf: + - type: integer + - $ref: '#/components/schemas/NestedIntFilter' + NestedBigIntFilter: + type: object + properties: + equals: + type: integer + in: + type: array + items: + type: integer + notIn: + type: array + items: + type: integer + lt: + type: integer + lte: + type: integer + gt: + type: integer + gte: + type: integer + not: + oneOf: + - type: integer + - $ref: '#/components/schemas/NestedBigIntFilter' + NestedDateTimeFilter: + type: object + properties: + equals: + type: string + format: date-time + in: + type: array + items: + type: string + format: date-time + notIn: + type: array + items: + type: string + format: date-time + lt: + type: string + format: date-time + lte: + type: string + format: date-time + gt: + type: string + format: date-time + gte: + type: string + format: date-time + not: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/NestedDateTimeFilter' + NestedFloatFilter: + type: object + properties: + equals: + type: number + in: + type: array + items: + type: number + notIn: + type: array + items: + type: number + lt: + type: number + lte: + type: number + gt: + type: number + gte: + type: number + not: + oneOf: + - type: number + - $ref: '#/components/schemas/NestedFloatFilter' + NestedDecimalFilter: + type: object + properties: + equals: + oneOf: + - type: string + - type: number + in: + type: array + items: + oneOf: + - type: string + - type: number + notIn: + type: array + items: + oneOf: + - type: string + - type: number + lt: + oneOf: + - type: string + - type: number + lte: + oneOf: + - type: string + - type: number + gt: + oneOf: + - type: string + - type: number + gte: + oneOf: + - type: string + - type: number + not: + oneOf: + - oneOf: + - type: string + - type: number + - $ref: '#/components/schemas/NestedDecimalFilter' + NestedBoolFilter: + type: object + properties: + equals: + type: boolean + not: + oneOf: + - type: boolean + - $ref: '#/components/schemas/NestedBoolFilter' + NestedBytesNullableFilter: + type: object + properties: + equals: + oneOf: + - type: 'null' + - type: string + format: byte + in: + oneOf: + - type: 'null' + - type: array + items: + type: string + format: byte + notIn: + oneOf: + - type: 'null' + - type: array + items: + type: string + format: byte + not: + oneOf: + - type: string + format: byte + - $ref: '#/components/schemas/NestedBytesNullableFilter' + - type: 'null' + NestedStringWithAggregatesFilter: + type: object + properties: + equals: + type: string + in: + type: array + items: + type: string + notIn: + type: array + items: + type: string + lt: + type: string + lte: + type: string + gt: + type: string + gte: + type: string + contains: + type: string + startsWith: + type: string + endsWith: + type: string + not: + oneOf: + - type: string + - $ref: '#/components/schemas/NestedStringWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _min: + $ref: '#/components/schemas/NestedStringFilter' + _max: + $ref: '#/components/schemas/NestedStringFilter' + NestedIntWithAggregatesFilter: + type: object + properties: + equals: + type: integer + in: + type: array + items: + type: integer + notIn: + type: array + items: + type: integer + lt: + type: integer + lte: + type: integer + gt: + type: integer + gte: + type: integer + not: + oneOf: + - type: integer + - $ref: '#/components/schemas/NestedIntWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _avg: + $ref: '#/components/schemas/NestedFloatFilter' + _sum: + $ref: '#/components/schemas/NestedIntFilter' + _min: + $ref: '#/components/schemas/NestedIntFilter' + _max: + $ref: '#/components/schemas/NestedIntFilter' + NestedBigIntWithAggregatesFilter: + type: object + properties: + equals: + type: integer + in: + type: array + items: + type: integer + notIn: + type: array + items: + type: integer + lt: + type: integer + lte: + type: integer + gt: + type: integer + gte: + type: integer + not: + oneOf: + - type: integer + - $ref: '#/components/schemas/NestedBigIntWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _avg: + $ref: '#/components/schemas/NestedFloatFilter' + _sum: + $ref: '#/components/schemas/NestedBigIntFilter' + _min: + $ref: '#/components/schemas/NestedBigIntFilter' + _max: + $ref: '#/components/schemas/NestedBigIntFilter' + NestedDateTimeWithAggregatesFilter: + type: object + properties: + equals: + type: string + format: date-time + in: + type: array + items: + type: string + format: date-time + notIn: + type: array + items: + type: string + format: date-time + lt: + type: string + format: date-time + lte: + type: string + format: date-time + gt: + type: string + format: date-time + gte: + type: string + format: date-time + not: + oneOf: + - type: string + format: date-time + - $ref: '#/components/schemas/NestedDateTimeWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _min: + $ref: '#/components/schemas/NestedDateTimeFilter' + _max: + $ref: '#/components/schemas/NestedDateTimeFilter' + NestedFloatWithAggregatesFilter: + type: object + properties: + equals: + type: number + in: + type: array + items: + type: number + notIn: + type: array + items: + type: number + lt: + type: number + lte: + type: number + gt: + type: number + gte: + type: number + not: + oneOf: + - type: number + - $ref: '#/components/schemas/NestedFloatWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _avg: + $ref: '#/components/schemas/NestedFloatFilter' + _sum: + $ref: '#/components/schemas/NestedFloatFilter' + _min: + $ref: '#/components/schemas/NestedFloatFilter' + _max: + $ref: '#/components/schemas/NestedFloatFilter' + NestedDecimalWithAggregatesFilter: + type: object + properties: + equals: + oneOf: + - type: string + - type: number + in: + type: array + items: + oneOf: + - type: string + - type: number + notIn: + type: array + items: + oneOf: + - type: string + - type: number + lt: + oneOf: + - type: string + - type: number + lte: + oneOf: + - type: string + - type: number + gt: + oneOf: + - type: string + - type: number + gte: + oneOf: + - type: string + - type: number + not: + oneOf: + - oneOf: + - type: string + - type: number + - $ref: '#/components/schemas/NestedDecimalWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _avg: + $ref: '#/components/schemas/NestedDecimalFilter' + _sum: + $ref: '#/components/schemas/NestedDecimalFilter' + _min: + $ref: '#/components/schemas/NestedDecimalFilter' + _max: + $ref: '#/components/schemas/NestedDecimalFilter' + NestedBoolWithAggregatesFilter: + type: object + properties: + equals: + type: boolean + not: + oneOf: + - type: boolean + - $ref: '#/components/schemas/NestedBoolWithAggregatesFilter' + _count: + $ref: '#/components/schemas/NestedIntFilter' + _min: + $ref: '#/components/schemas/NestedBoolFilter' + _max: + $ref: '#/components/schemas/NestedBoolFilter' + NestedBytesNullableWithAggregatesFilter: + type: object + properties: + equals: + oneOf: + - type: 'null' + - type: string + format: byte + in: + oneOf: + - type: 'null' + - type: array + items: + type: string + format: byte + notIn: + oneOf: + - type: 'null' + - type: array + items: + type: string + format: byte + not: + oneOf: + - type: string + format: byte + - $ref: '#/components/schemas/NestedBytesNullableWithAggregatesFilter' + - type: 'null' + _count: + $ref: '#/components/schemas/NestedIntNullableFilter' + _min: + $ref: '#/components/schemas/NestedBytesNullableFilter' + _max: + $ref: '#/components/schemas/NestedBytesNullableFilter' + NestedIntNullableFilter: + type: object + properties: + equals: + oneOf: + - type: 'null' + - type: integer + in: + oneOf: + - type: 'null' + - type: array + items: + type: integer + notIn: + oneOf: + - type: 'null' + - type: array + items: + type: integer + lt: + type: integer + lte: + type: integer + gt: + type: integer + gte: + type: integer + not: + oneOf: + - type: integer + - $ref: '#/components/schemas/NestedIntNullableFilter' + - type: 'null' + NestedJsonNullableFilter: + type: object + properties: + equals: + oneOf: + - {} + - $ref: '#/components/schemas/JsonNullValueFilter' + path: + type: array + items: + type: string + mode: + $ref: '#/components/schemas/QueryMode' + string_contains: + type: string + string_starts_with: + type: string + string_ends_with: + type: string + array_starts_with: + oneOf: + - type: 'null' + - {} + array_ends_with: + oneOf: + - type: 'null' + - {} + array_contains: + oneOf: + - type: 'null' + - {} + lt: {} + lte: {} + gt: {} + gte: {} + not: + oneOf: + - {} + - $ref: '#/components/schemas/JsonNullValueFilter' + NestedJsonFilter: + type: object + properties: + equals: + oneOf: + - {} + - $ref: '#/components/schemas/JsonNullValueFilter' + path: + type: array + items: + type: string + mode: + $ref: '#/components/schemas/QueryMode' + string_contains: + type: string + string_starts_with: + type: string + string_ends_with: + type: string + array_starts_with: + oneOf: + - type: 'null' + - {} + array_ends_with: + oneOf: + - type: 'null' + - {} + array_contains: + oneOf: + - type: 'null' + - {} + lt: {} + lte: {} + gt: {} + gte: {} + not: + oneOf: + - {} + - $ref: '#/components/schemas/JsonNullValueFilter' + FooSelect: + type: object + properties: + id: + type: boolean + string: + type: boolean + int: + type: boolean + bigInt: + type: boolean + date: + type: boolean + float: + type: boolean + decimal: + type: boolean + boolean: + type: boolean + bytes: + type: boolean + json: + type: boolean + plainJson: + type: boolean + FooCountAggregateInput: + type: object + properties: + id: + type: boolean + string: + type: boolean + int: + type: boolean + bigInt: + type: boolean + date: + type: boolean + float: + type: boolean + decimal: + type: boolean + boolean: + type: boolean + bytes: + type: boolean + json: + type: boolean + plainJson: + type: boolean + _all: + type: boolean + FooAvgAggregateInput: + type: object + properties: + int: + type: boolean + bigInt: + type: boolean + float: + type: boolean + decimal: + type: boolean + FooSumAggregateInput: + type: object + properties: + int: + type: boolean + bigInt: + type: boolean + float: + type: boolean + decimal: + type: boolean + FooMinAggregateInput: + type: object + properties: + id: + type: boolean + string: + type: boolean + int: + type: boolean + bigInt: + type: boolean + date: + type: boolean + float: + type: boolean + decimal: + type: boolean + boolean: + type: boolean + bytes: + type: boolean + FooMaxAggregateInput: + type: object + properties: + id: + type: boolean + string: + type: boolean + int: + type: boolean + bigInt: + type: boolean + date: + type: boolean + float: + type: boolean + decimal: + type: boolean + boolean: + type: boolean + bytes: + type: boolean + AggregateFoo: + type: object + properties: + _count: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/FooCountAggregateOutputType' + _avg: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/FooAvgAggregateOutputType' + _sum: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/FooSumAggregateOutputType' + _min: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/FooMinAggregateOutputType' + _max: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/FooMaxAggregateOutputType' + FooGroupByOutputType: + type: object + properties: + id: + type: string + string: + type: string + int: + type: integer + bigInt: + type: integer + date: + type: string + format: date-time + float: + type: number + decimal: + oneOf: + - type: string + - type: number + boolean: + type: boolean + bytes: + oneOf: + - type: 'null' + - type: string + format: byte + json: + oneOf: + - type: 'null' + - {} + plainJson: {} + _count: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/FooCountAggregateOutputType' + _avg: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/FooAvgAggregateOutputType' + _sum: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/FooSumAggregateOutputType' + _min: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/FooMinAggregateOutputType' + _max: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/FooMaxAggregateOutputType' + required: + - id + - string + - int + - bigInt + - date + - float + - decimal + - boolean + - plainJson + FooCountAggregateOutputType: + type: object + properties: + id: + type: integer + string: + type: integer + int: + type: integer + bigInt: + type: integer + date: + type: integer + float: + type: integer + decimal: + type: integer + boolean: + type: integer + bytes: + type: integer + json: + type: integer + plainJson: + type: integer + _all: + type: integer + required: + - id + - string + - int + - bigInt + - date + - float + - decimal + - boolean + - bytes + - json + - plainJson + - _all + FooAvgAggregateOutputType: + type: object + properties: + int: + oneOf: + - type: 'null' + - type: number + bigInt: + oneOf: + - type: 'null' + - type: number + float: + oneOf: + - type: 'null' + - type: number + decimal: + oneOf: + - type: string + - type: number + - type: 'null' + FooSumAggregateOutputType: + type: object + properties: + int: + oneOf: + - type: 'null' + - type: integer + bigInt: + oneOf: + - type: 'null' + - type: integer + float: + oneOf: + - type: 'null' + - type: number + decimal: + oneOf: + - type: string + - type: number + - type: 'null' + FooMinAggregateOutputType: + type: object + properties: + id: + oneOf: + - type: 'null' + - type: string + string: + oneOf: + - type: 'null' + - type: string + int: + oneOf: + - type: 'null' + - type: integer + bigInt: + oneOf: + - type: 'null' + - type: integer + date: + oneOf: + - type: 'null' + - type: string + format: date-time + float: + oneOf: + - type: 'null' + - type: number + decimal: + oneOf: + - type: string + - type: number + - type: 'null' + boolean: + oneOf: + - type: 'null' + - type: boolean + bytes: + oneOf: + - type: 'null' + - type: string + format: byte + FooMaxAggregateOutputType: + type: object + properties: + id: + oneOf: + - type: 'null' + - type: string + string: + oneOf: + - type: 'null' + - type: string + int: + oneOf: + - type: 'null' + - type: integer + bigInt: + oneOf: + - type: 'null' + - type: integer + date: + oneOf: + - type: 'null' + - type: string + format: date-time + float: + oneOf: + - type: 'null' + - type: number + decimal: + oneOf: + - type: string + - type: number + - type: 'null' + boolean: + oneOf: + - type: 'null' + - type: boolean + bytes: + oneOf: + - type: 'null' + - type: string + format: byte + _Meta: + type: object + description: Meta information about the request or response + properties: + serialization: + description: Serialization metadata + additionalProperties: true + _Error: + type: object + required: + - error + properties: + error: + type: object + required: + - message + properties: + prisma: + type: boolean + description: Indicates if the error occurred during a Prisma call + rejectedByPolicy: + type: boolean + description: Indicates if the error was due to rejection by a policy + code: + type: string + description: Prisma error code. Only available when "prisma" field is true. + message: + type: string + description: Error message + reason: + type: string + description: Detailed error reason + zodErrors: + type: object + additionalProperties: true + description: Zod validation errors if the error is due to data validation + failure + additionalProperties: true + BatchPayload: + type: object + properties: + count: + type: integer + FooCreateArgs: + type: object + required: + - data + properties: + select: + $ref: '#/components/schemas/FooSelect' + data: + $ref: '#/components/schemas/FooCreateInput' + meta: + $ref: '#/components/schemas/_Meta' + FooCreateManyArgs: + type: object + required: + - data + properties: + data: + oneOf: + - $ref: '#/components/schemas/FooCreateManyInput' + - type: array + items: + $ref: '#/components/schemas/FooCreateManyInput' + skipDuplicates: + type: boolean + description: Do not insert records with unique fields or ID fields that already + exist. + meta: + $ref: '#/components/schemas/_Meta' + FooFindUniqueArgs: + type: object + required: + - where + properties: + select: + $ref: '#/components/schemas/FooSelect' + where: + $ref: '#/components/schemas/FooWhereUniqueInput' + meta: + $ref: '#/components/schemas/_Meta' + FooFindFirstArgs: + type: object + properties: + select: + $ref: '#/components/schemas/FooSelect' + where: + $ref: '#/components/schemas/FooWhereInput' + meta: + $ref: '#/components/schemas/_Meta' + FooFindManyArgs: + type: object + properties: + select: + $ref: '#/components/schemas/FooSelect' + where: + $ref: '#/components/schemas/FooWhereInput' + orderBy: + oneOf: + - $ref: '#/components/schemas/FooOrderByWithRelationInput' + - type: array + items: + $ref: '#/components/schemas/FooOrderByWithRelationInput' + cursor: + $ref: '#/components/schemas/FooWhereUniqueInput' + take: + type: integer + skip: + type: integer + meta: + $ref: '#/components/schemas/_Meta' + FooUpdateArgs: + type: object + required: + - where + - data + properties: + select: + $ref: '#/components/schemas/FooSelect' + where: + $ref: '#/components/schemas/FooWhereUniqueInput' + data: + $ref: '#/components/schemas/FooUpdateInput' + meta: + $ref: '#/components/schemas/_Meta' + FooUpdateManyArgs: + type: object + required: + - data + properties: + where: + $ref: '#/components/schemas/FooWhereInput' + data: + $ref: '#/components/schemas/FooUpdateManyMutationInput' + meta: + $ref: '#/components/schemas/_Meta' + FooUpsertArgs: + type: object + required: + - create + - update + - where + properties: + select: + $ref: '#/components/schemas/FooSelect' + where: + $ref: '#/components/schemas/FooWhereUniqueInput' + create: + $ref: '#/components/schemas/FooCreateInput' + update: + $ref: '#/components/schemas/FooUpdateInput' + meta: + $ref: '#/components/schemas/_Meta' + FooDeleteUniqueArgs: + type: object + required: + - where + properties: + select: + $ref: '#/components/schemas/FooSelect' + where: + $ref: '#/components/schemas/FooWhereUniqueInput' + meta: + $ref: '#/components/schemas/_Meta' + FooDeleteManyArgs: + type: object + properties: + where: + $ref: '#/components/schemas/FooWhereInput' + meta: + $ref: '#/components/schemas/_Meta' + FooCountArgs: + type: object + properties: + select: + $ref: '#/components/schemas/FooSelect' + where: + $ref: '#/components/schemas/FooWhereInput' + meta: + $ref: '#/components/schemas/_Meta' + FooAggregateArgs: + type: object + properties: + where: + $ref: '#/components/schemas/FooWhereInput' + orderBy: + $ref: '#/components/schemas/FooOrderByWithRelationInput' + cursor: + $ref: '#/components/schemas/FooWhereUniqueInput' + take: + type: integer + skip: + type: integer + _count: + oneOf: + - type: boolean + - $ref: '#/components/schemas/FooCountAggregateInput' + _min: + $ref: '#/components/schemas/FooMinAggregateInput' + _max: + $ref: '#/components/schemas/FooMaxAggregateInput' + _sum: + $ref: '#/components/schemas/FooSumAggregateInput' + _avg: + $ref: '#/components/schemas/FooAvgAggregateInput' + meta: + $ref: '#/components/schemas/_Meta' + FooGroupByArgs: + type: object + properties: + where: + $ref: '#/components/schemas/FooWhereInput' + orderBy: + $ref: '#/components/schemas/FooOrderByWithRelationInput' + by: + $ref: '#/components/schemas/FooScalarFieldEnum' + having: + $ref: '#/components/schemas/FooScalarWhereWithAggregatesInput' + take: + type: integer + skip: + type: integer + _count: + oneOf: + - type: boolean + - $ref: '#/components/schemas/FooCountAggregateInput' + _min: + $ref: '#/components/schemas/FooMinAggregateInput' + _max: + $ref: '#/components/schemas/FooMaxAggregateInput' + _sum: + $ref: '#/components/schemas/FooSumAggregateInput' + _avg: + $ref: '#/components/schemas/FooAvgAggregateInput' + meta: + $ref: '#/components/schemas/_Meta' +paths: + /foo/create: + post: + operationId: createFoo + description: Create a new Foo + tags: + - foo + security: [] + responses: + '201': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Foo' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/FooCreateArgs' + /foo/createMany: + post: + operationId: createManyFoo + description: Create several Foo + tags: + - foo + security: [] + responses: + '201': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BatchPayload' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/FooCreateManyArgs' + /foo/findUnique: + get: + operationId: findUniqueFoo + description: Find one unique Foo + tags: + - foo + security: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Foo' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/FooFindUniqueArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /foo/findFirst: + get: + operationId: findFirstFoo + description: Find the first Foo matching the given condition + tags: + - foo + security: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Foo' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/FooFindFirstArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /foo/findMany: + get: + operationId: findManyFoo + description: Find a list of Foo + tags: + - foo + security: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + type: array + items: + $ref: '#/components/schemas/Foo' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/FooFindManyArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /foo/update: + patch: + operationId: updateFoo + description: Update a Foo + tags: + - foo + security: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Foo' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/FooUpdateArgs' + /foo/updateMany: + patch: + operationId: updateManyFoo + description: Update Foos matching the given condition + tags: + - foo + security: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BatchPayload' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/FooUpdateManyArgs' + /foo/upsert: + post: + operationId: upsertFoo + description: Upsert a Foo + tags: + - foo + security: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Foo' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/FooUpsertArgs' + /foo/delete: + delete: + operationId: deleteFoo + description: Delete one unique Foo + tags: + - foo + security: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Foo' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/FooDeleteUniqueArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /foo/deleteMany: + delete: + operationId: deleteManyFoo + description: Delete Foos matching the given condition + tags: + - foo + security: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BatchPayload' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/FooDeleteManyArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /foo/count: + get: + operationId: countFoo + description: Find a list of Foo + tags: + - foo + security: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + oneOf: + - type: integer + - $ref: '#/components/schemas/FooCountAggregateOutputType' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/FooCountArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /foo/aggregate: + get: + operationId: aggregateFoo + description: Aggregate Foos + tags: + - foo + security: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/AggregateFoo' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/FooAggregateArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} + /foo/groupBy: + get: + operationId: groupByFoo + description: Group Foos by fields + tags: + - foo + security: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + type: array + items: + $ref: '#/components/schemas/FooGroupByOutputType' + description: The Prisma response data serialized with superjson + meta: + $ref: '#/components/schemas/_Meta' + description: The superjson serialization metadata for the "data" field + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Invalid request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is forbidden + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/_Error' + description: Request is unprocessable due to validation errors + parameters: + - name: q + in: query + required: true + description: Superjson-serialized Prisma query object + content: + application/json: + schema: + $ref: '#/components/schemas/FooGroupByArgs' + - name: meta + in: query + description: Superjson serialization metadata for parameter "q" + content: + application/json: + schema: {} diff --git a/packages/server/test/openapi/migrated/rest-migrated.test.ts b/packages/server/test/openapi/migrated/rest-migrated.test.ts new file mode 100644 index 000000000..8e0919897 --- /dev/null +++ b/packages/server/test/openapi/migrated/rest-migrated.test.ts @@ -0,0 +1,220 @@ +/** + * Migrated from zenstack-v2/packages/plugins/openapi/tests/openapi-restful.test.ts + * Only v3.1 related tests are included. + */ +import { createTestClient } from '@zenstackhq/testtools'; +import fs from 'fs'; +import path from 'path'; +import { describe, expect, it } from 'vitest'; +import YAML from 'yaml'; +import { RestApiHandler } from '../../../src/api/rest'; + +const mainSchema = ` +enum role { + USER + ADMIN +} + +model User { + id String @id @default(cuid()) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + email String @unique + role role @default(USER) + posts Post_Item[] + profile Profile? + likes PostLike[] +} + +model Profile { + id String @id @default(cuid()) + image String? + user User @relation(fields: [userId], references: [id]) + userId String @unique +} + +model Post_Item { + id String @id + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + title String + author User? @relation(fields: [authorId], references: [id]) + authorId String? + published Boolean @default(false) + viewCount Int @default(0) + notes String? + likes PostLike[] +} + +model PostLike { + postId String + userId String + post Post_Item @relation(fields: [postId], references: [id]) + user User @relation(fields: [userId], references: [id]) + @@id([postId, userId]) +} +`; + +const typeCoverageSchema = ` +type Meta { + something String +} + +model Foo { + id String @id @default(cuid()) + string String + int Int + bigInt BigInt + date DateTime + float Float + decimal Decimal + boolean Boolean + bytes Bytes + json Meta? @json + plainJson Json +} +`; + +describe('Migrated REST OpenAPI v3.1 tests', () => { + it('generates valid v3.1 spec for main schema', async () => { + const client = await createTestClient(mainSchema); + const handler = new RestApiHandler({ + schema: client.$schema, + endpoint: 'http://localhost/api', + }); + const spec = await handler.generateSpec(); + + expect(spec.openapi).toBe('3.1.0'); + + // Tags + const tagNames = spec.tags?.map((t: any) => t.name) ?? []; + expect(tagNames).toContain('user'); + expect(tagNames).toContain('post_Item'); + + // Collection paths + expect(spec.paths?.['/user']?.get).toBeDefined(); + expect(spec.paths?.['/user']?.post).toBeDefined(); + expect(spec.paths?.['/user']?.put).toBeUndefined(); + + // Single resource paths + expect(spec.paths?.['/user/{id}']?.get).toBeDefined(); + expect(spec.paths?.['/user/{id}']?.patch).toBeDefined(); + expect(spec.paths?.['/user/{id}']?.delete).toBeDefined(); + + // Related resource paths + expect(spec.paths?.['/user/{id}/posts']?.get).toBeDefined(); + + // Relationship management paths + expect(spec.paths?.['/user/{id}/relationships/posts']?.get).toBeDefined(); + expect(spec.paths?.['/user/{id}/relationships/posts']?.post).toBeDefined(); + expect(spec.paths?.['/user/{id}/relationships/posts']?.patch).toBeDefined(); + expect(spec.paths?.['/user/{id}/relationships/likes']?.get).toBeDefined(); + expect(spec.paths?.['/user/{id}/relationships/likes']?.post).toBeDefined(); + expect(spec.paths?.['/user/{id}/relationships/likes']?.patch).toBeDefined(); + + // To-one relationship: no POST + expect(spec.paths?.['/post_Item/{id}/relationships/author']?.get).toBeDefined(); + expect(spec.paths?.['/post_Item/{id}/relationships/author']?.post).toBeUndefined(); + expect(spec.paths?.['/post_Item/{id}/relationships/author']?.patch).toBeDefined(); + + // To-many relationship on Post_Item + expect(spec.paths?.['/post_Item/{id}/relationships/likes']?.get).toBeDefined(); + expect(spec.paths?.['/post_Item/{id}/relationships/likes']?.post).toBeDefined(); + expect(spec.paths?.['/post_Item/{id}/relationships/likes']?.patch).toBeDefined(); + + // Schemas + expect(spec.components?.schemas?.['User']).toBeDefined(); + expect(spec.components?.schemas?.['Post_Item']).toBeDefined(); + expect(spec.components?.schemas?.['PostLike']).toBeDefined(); + + // Enum schema + expect(spec.components?.schemas?.['role']).toBeDefined(); + const roleSchema = spec.components?.schemas?.['role'] as any; + expect(roleSchema.type).toBe('string'); + expect(roleSchema.enum).toContain('USER'); + expect(roleSchema.enum).toContain('ADMIN'); + }); + + it('compound id model paths exist', async () => { + const client = await createTestClient(mainSchema); + const handler = new RestApiHandler({ + schema: client.$schema, + endpoint: 'http://localhost/api', + }); + const spec = await handler.generateSpec(); + + // PostLike has @@id([postId, userId]) + expect(spec.paths?.['/postLike']).toBeDefined(); + expect(spec.paths?.['/postLike/{id}']).toBeDefined(); + }); + + it('field type coverage matches expectations', async () => { + const client = await createTestClient(typeCoverageSchema); + const handler = new RestApiHandler({ + schema: client.$schema, + endpoint: 'http://localhost/api', + }); + const spec = await handler.generateSpec(); + + expect(spec.openapi).toBe('3.1.0'); + + const fooSchema = spec.components?.schemas?.['Foo'] as any; + expect(fooSchema).toBeDefined(); + expect(fooSchema.properties.string).toMatchObject({ type: 'string' }); + expect(fooSchema.properties.int).toMatchObject({ type: 'integer' }); + expect(fooSchema.properties.bigInt).toMatchObject({ type: 'integer' }); + expect(fooSchema.properties.date).toMatchObject({ type: 'string', format: 'date-time' }); + expect(fooSchema.properties.float).toMatchObject({ type: 'number' }); + expect(fooSchema.properties.boolean).toMatchObject({ type: 'boolean' }); + expect(fooSchema.properties.bytes).toMatchObject({ type: 'string', format: 'byte' }); + + // Decimal -> oneOf number | string + const decimalProp = fooSchema.properties.decimal; + expect(decimalProp.oneOf).toBeDefined(); + + // Meta? @json -> optional ref or null (v3.1 pattern) + const jsonProp = fooSchema.properties.json; + expect(jsonProp).toBeDefined(); + + // Plain Json -> generic + const plainJsonProp = fooSchema.properties.plainJson; + expect(plainJsonProp).toBeDefined(); + }); + + it('works with mapped model names', async () => { + const client = await createTestClient(mainSchema); + const handler = new RestApiHandler({ + schema: client.$schema, + endpoint: 'http://localhost/api', + modelNameMapping: { User: 'myUser' }, + }); + const spec = await handler.generateSpec(); + + expect(spec.paths?.['/myUser']).toBeDefined(); + expect(spec.paths?.['/user']).toBeUndefined(); + expect(spec.paths?.['/post_Item']).toBeDefined(); + }); + + it('baseline comparison - rest-3.1.0', async () => { + const baselinePath = path.join(__dirname, 'baseline', 'rest-3.1.0.baseline.yaml'); + if (!fs.existsSync(baselinePath)) { + console.warn('Skipping baseline comparison: rest-3.1.0.baseline.yaml not found'); + return; + } + const baseline = YAML.parse(fs.readFileSync(baselinePath, 'utf-8')); + expect(baseline.openapi).toBe('3.1.0'); + expect(baseline.components?.schemas).toBeDefined(); + expect(baseline.paths).toBeDefined(); + }); + + it('baseline comparison - rest-type-coverage-3.1.0', async () => { + const baselinePath = path.join(__dirname, 'baseline', 'rest-type-coverage-3.1.0.baseline.yaml'); + if (!fs.existsSync(baselinePath)) { + console.warn('Skipping baseline comparison: rest-type-coverage-3.1.0.baseline.yaml not found'); + return; + } + const baseline = YAML.parse(fs.readFileSync(baselinePath, 'utf-8')); + expect(baseline.openapi).toBe('3.1.0'); + expect(baseline.components?.schemas?.Foo).toBeDefined(); + }); +}); diff --git a/packages/server/test/openapi/migrated/rpc-migrated.test.ts b/packages/server/test/openapi/migrated/rpc-migrated.test.ts new file mode 100644 index 000000000..81b22ea62 --- /dev/null +++ b/packages/server/test/openapi/migrated/rpc-migrated.test.ts @@ -0,0 +1,198 @@ +/** + * Migrated from zenstack-v2/packages/plugins/openapi/tests/openapi-rpc.test.ts + * Only v3.1 related tests are included. + */ +import { createTestClient } from '@zenstackhq/testtools'; +import fs from 'fs'; +import path from 'path'; +import { describe, expect, it } from 'vitest'; +import YAML from 'yaml'; +import { RPCApiHandler } from '../../../src/api/rpc'; + +const mainSchema = ` +enum role { + USER + ADMIN +} + +model User { + id String @id @default(cuid()) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + email String @unique + role role @default(USER) + posts Post_Item[] + profile Profile? +} + +model Profile { + id String @id @default(cuid()) + image String? + user User @relation(fields: [userId], references: [id]) + userId String @unique +} + +model Post_Item { + id String @id + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + title String + author User? @relation(fields: [authorId], references: [id]) + authorId String? + published Boolean @default(false) + viewCount Int @default(0) + notes String? +} +`; + +const typeCoverageSchema = ` +type Meta { + something String +} + +model Foo { + id String @id @default(cuid()) + string String + int Int + bigInt BigInt + date DateTime + float Float + decimal Decimal + boolean Boolean + bytes Bytes? + json Meta? @json + plainJson Json +} +`; + +describe('Migrated RPC OpenAPI v3.1 tests', () => { + it('generates valid v3.1 spec for main schema', async () => { + const client = await createTestClient(mainSchema); + const handler = new RPCApiHandler({ schema: client.$schema }); + const spec = await handler.generateSpec(); + + expect(spec.openapi).toBe('3.1.0'); + + // Tags are generated for included models + const tagNames = spec.tags?.map((t: any) => t.name) ?? []; + expect(tagNames).toContain('user'); + expect(tagNames).toContain('profile'); + expect(tagNames).toContain('post_Item'); + + // CRUD operation paths exist + expect(spec.paths?.['/user/findMany']).toBeDefined(); + expect(spec.paths?.['/user/findMany']?.get).toBeDefined(); + expect(spec.paths?.['/user/create']).toBeDefined(); + expect(spec.paths?.['/user/create']?.post).toBeDefined(); + expect(spec.paths?.['/user/delete']).toBeDefined(); + + // Post paths exist + expect(spec.paths?.['/post_Item/findMany']).toBeDefined(); + + // Schemas are generated + expect(spec.components?.schemas?.['User']).toBeDefined(); + expect(spec.components?.schemas?.['Profile']).toBeDefined(); + expect(spec.components?.schemas?.['Post_Item']).toBeDefined(); + + // Enum schema + expect(spec.components?.schemas?.['role']).toBeDefined(); + const roleSchema = spec.components?.schemas?.['role'] as any; + expect(roleSchema.type).toBe('string'); + expect(roleSchema.enum).toContain('USER'); + expect(roleSchema.enum).toContain('ADMIN'); + + // User schema field types + const userSchema = spec.components?.schemas?.['User'] as any; + expect(userSchema.properties.id).toMatchObject({ type: 'string' }); + expect(userSchema.properties.createdAt).toMatchObject({ type: 'string', format: 'date-time' }); + expect(userSchema.properties.email).toMatchObject({ type: 'string' }); + + // Optional relation uses oneOf with null (v3.1 pattern) + const profileProp = userSchema.properties.profile; + expect(profileProp).toBeDefined(); + }); + + it('generates spec with custom title and version', async () => { + const client = await createTestClient(mainSchema); + const handler = new RPCApiHandler({ schema: client.$schema }); + const spec = await handler.generateSpec({ + title: 'My RPC API', + version: '2.0.0', + description: 'A custom API', + summary: 'awesome api', + }); + + expect(spec.openapi).toBe('3.1.0'); + expect(spec.info.title).toBe('My RPC API'); + expect(spec.info.version).toBe('2.0.0'); + expect((spec.info as any).description).toBe('A custom API'); + expect((spec.info as any).summary).toBe('awesome api'); + }); + + it('field type coverage matches expectations', async () => { + const client = await createTestClient(typeCoverageSchema); + const handler = new RPCApiHandler({ schema: client.$schema }); + const spec = await handler.generateSpec(); + + expect(spec.openapi).toBe('3.1.0'); + + const fooSchema = spec.components?.schemas?.['Foo'] as any; + expect(fooSchema).toBeDefined(); + expect(fooSchema.properties.string).toMatchObject({ type: 'string' }); + expect(fooSchema.properties.int).toMatchObject({ type: 'integer' }); + expect(fooSchema.properties.bigInt).toMatchObject({ type: 'integer' }); + expect(fooSchema.properties.date).toMatchObject({ type: 'string', format: 'date-time' }); + expect(fooSchema.properties.float).toMatchObject({ type: 'number' }); + expect(fooSchema.properties.boolean).toMatchObject({ type: 'boolean' }); + + // Decimal -> oneOf number | string + const decimalProp = fooSchema.properties.decimal; + expect(decimalProp.oneOf).toBeDefined(); + + // Bytes? -> optional byte string + const bytesProp = fooSchema.properties.bytes; + expect(bytesProp).toBeDefined(); + + // Meta? @json -> optional ref or null (v3.1) + const jsonProp = fooSchema.properties.json; + expect(jsonProp).toBeDefined(); + + // Plain Json -> generic + const plainJsonProp = fooSchema.properties.plainJson; + expect(plainJsonProp).toBeDefined(); + }); + + it('baseline comparison - rpc-3.1.0', async () => { + const baselinePath = path.join(__dirname, 'baseline', 'rpc-3.1.0.baseline.yaml'); + if (!fs.existsSync(baselinePath)) { + console.warn('Skipping baseline comparison: rpc-3.1.0.baseline.yaml not found'); + return; + } + const baseline = YAML.parse(fs.readFileSync(baselinePath, 'utf-8')); + // Baseline is from v2 plugin, just verify it parses correctly + expect(baseline.openapi).toBe('3.1.0'); + expect(baseline.components?.schemas).toBeDefined(); + }); + + it('baseline comparison - rpc-3.1.0-omit', async () => { + const baselinePath = path.join(__dirname, 'baseline', 'rpc-3.1.0-omit.baseline.yaml'); + if (!fs.existsSync(baselinePath)) { + console.warn('Skipping baseline comparison: rpc-3.1.0-omit.baseline.yaml not found'); + return; + } + const baseline = YAML.parse(fs.readFileSync(baselinePath, 'utf-8')); + expect(baseline.openapi).toBe('3.1.0'); + expect(baseline.components?.schemas).toBeDefined(); + }); + + it('baseline comparison - rpc-type-coverage-3.1.0', async () => { + const baselinePath = path.join(__dirname, 'baseline', 'rpc-type-coverage-3.1.0.baseline.yaml'); + if (!fs.existsSync(baselinePath)) { + console.warn('Skipping baseline comparison: rpc-type-coverage-3.1.0.baseline.yaml not found'); + return; + } + const baseline = YAML.parse(fs.readFileSync(baselinePath, 'utf-8')); + expect(baseline.openapi).toBe('3.1.0'); + expect(baseline.components?.schemas?.Foo).toBeDefined(); + }); +}); diff --git a/packages/server/test/openapi/rest-openapi.test.ts b/packages/server/test/openapi/rest-openapi.test.ts new file mode 100644 index 000000000..dc83417c4 --- /dev/null +++ b/packages/server/test/openapi/rest-openapi.test.ts @@ -0,0 +1,462 @@ +import { createTestClient } from '@zenstackhq/testtools'; +import { beforeAll, describe, expect, it } from 'vitest'; +import { RestApiHandler } from '../../src/api/rest'; + +const schema = ` +type Address { + city String +} + +model User { + myId String @id @default(cuid()) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + email String @unique @email + posts Post[] + likes PostLike[] + profile Profile? + address Address? @json + someJson Json? +} + +model Profile { + id Int @id @default(autoincrement()) + gender String + user User @relation(fields: [userId], references: [myId]) + userId String @unique +} + +model Post { + id Int @id @default(autoincrement()) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + title String @length(1, 10) + author User? @relation(fields: [authorId], references: [myId]) + authorId String? + published Boolean @default(false) + publishedAt DateTime? + viewCount Int @default(0) + comments Comment[] + likes PostLike[] + setting Setting? +} + +model Comment { + id Int @id @default(autoincrement()) + post Post @relation(fields: [postId], references: [id]) + postId Int + content String +} + +model Setting { + id Int @id @default(autoincrement()) + boost Int + post Post @relation(fields: [postId], references: [id]) + postId Int @unique +} + +model PostLike { + postId Int + userId String + superLike Boolean + post Post @relation(fields: [postId], references: [id]) + user User @relation(fields: [userId], references: [myId]) + likeInfos PostLikeInfo[] + @@id([postId, userId]) +} + +model PostLikeInfo { + id Int @id @default(autoincrement()) + text String + postId Int + userId String + postLike PostLike @relation(fields: [postId, userId], references: [postId, userId]) +} +`; + +describe('REST OpenAPI spec generation', () => { + let handler: RestApiHandler; + let spec: any; + + beforeAll(async () => { + const client = await createTestClient(schema); + handler = new RestApiHandler({ + schema: client.$schema, + endpoint: 'http://localhost/api', + }); + spec = await handler.generateSpec(); + }); + + it('document structure is valid', () => { + expect(spec.openapi).toBe('3.1.0'); + expect(spec.info).toBeDefined(); + expect(spec.info.title).toBe('ZenStack Generated API'); + expect(spec.info.version).toBe('1.0.0'); + expect(spec.servers).toEqual([{ url: 'http://localhost/api' }]); + expect(spec.paths).toBeDefined(); + expect(spec.components).toBeDefined(); + expect(spec.components.schemas).toBeDefined(); + }); + + it('model paths exist', () => { + expect(spec.paths['/user']).toBeDefined(); + expect(spec.paths['/user/{id}']).toBeDefined(); + expect(spec.paths['/post']).toBeDefined(); + expect(spec.paths['/post/{id}']).toBeDefined(); + expect(spec.paths['/comment']).toBeDefined(); + expect(spec.paths['/comment/{id}']).toBeDefined(); + }); + + it('HTTP methods on collection path', () => { + expect(spec.paths['/user'].get).toBeDefined(); + expect(spec.paths['/user'].post).toBeDefined(); + }); + + it('HTTP methods on single resource path', () => { + expect(spec.paths['/user/{id}'].get).toBeDefined(); + expect(spec.paths['/user/{id}'].patch).toBeDefined(); + expect(spec.paths['/user/{id}'].delete).toBeDefined(); + }); + + it('relation paths exist', () => { + expect(spec.paths['/user/{id}/posts']).toBeDefined(); + expect(spec.paths['/user/{id}/relationships/posts']).toBeDefined(); + expect(spec.paths['/post/{id}/comments']).toBeDefined(); + }); + + it('relationship path has correct methods', () => { + const relPath = spec.paths['/user/{id}/relationships/posts']; + expect(relPath.get).toBeDefined(); + expect(relPath.put).toBeDefined(); + expect(relPath.patch).toBeDefined(); + // posts is a collection, so should have POST + expect(relPath.post).toBeDefined(); + }); + + it('model schemas exist', () => { + expect(spec.components.schemas['User']).toBeDefined(); + expect(spec.components.schemas['UserCreateRequest']).toBeDefined(); + expect(spec.components.schemas['UserUpdateRequest']).toBeDefined(); + expect(spec.components.schemas['UserResponse']).toBeDefined(); + expect(spec.components.schemas['UserListResponse']).toBeDefined(); + expect(spec.components.schemas['Post']).toBeDefined(); + expect(spec.components.schemas['PostCreateRequest']).toBeDefined(); + }); + + it('field types in schemas', () => { + const userSchema = spec.components.schemas['User']; + expect(userSchema.properties).toBeDefined(); + // email -> string + expect(userSchema.properties['email']).toMatchObject({ type: 'string' }); + // myId -> string + expect(userSchema.properties['myId']).toMatchObject({ type: 'string' }); + + const postSchema = spec.components.schemas['Post']; + expect(postSchema.properties).toBeDefined(); + // viewCount -> integer + expect(postSchema.properties['viewCount']).toMatchObject({ type: 'integer' }); + // published -> boolean + expect(postSchema.properties['published']).toMatchObject({ type: 'boolean' }); + // createdAt -> date-time + expect(postSchema.properties['createdAt']).toMatchObject({ type: 'string', format: 'date-time' }); + }); + + it('required fields marked in create schema', () => { + const createReq = spec.components.schemas['CommentCreateRequest']; + expect(createReq).toBeDefined(); + const dataProps = createReq.properties?.data?.properties; + expect(dataProps).toBeDefined(); + // content is required, non-optional non-default + const attrRequired = createReq.properties?.data?.properties?.attributes?.required ?? []; + expect(attrRequired).toContain('content'); + }); + + it('shared component schemas exist', () => { + expect(spec.components.schemas['_jsonapi']).toBeDefined(); + expect(spec.components.schemas['_errors']).toBeDefined(); + expect(spec.components.schemas['_errorResponse']).toBeDefined(); + expect(spec.components.schemas['_resourceIdentifier']).toBeDefined(); + expect(spec.components.schemas['_toOneRelationship']).toBeDefined(); + expect(spec.components.schemas['_toManyRelationship']).toBeDefined(); + }); + + it('shared parameters exist', () => { + expect(spec.components.parameters['id']).toBeDefined(); + expect(spec.components.parameters['include']).toBeDefined(); + expect(spec.components.parameters['sort']).toBeDefined(); + expect(spec.components.parameters['pageOffset']).toBeDefined(); + expect(spec.components.parameters['pageLimit']).toBeDefined(); + }); + + it('filter parameters appear on list operations', () => { + const listOp = spec.paths['/post'].get; + expect(listOp).toBeDefined(); + const paramNames = listOp.parameters.map((p: any) => ('name' in p ? p.name : p.$ref)); + expect(paramNames).toContain('filter[viewCount]'); + expect(paramNames).toContain('filter[published]'); + expect(paramNames).toContain('filter[title]'); + // String ops + expect(paramNames).toContain('filter[title][$contains]'); + // Numeric ops + expect(paramNames).toContain('filter[viewCount][$lt]'); + expect(paramNames).toContain('filter[viewCount][$gt]'); + }); + + it('modelNameMapping is reflected in paths', async () => { + const client = await createTestClient(schema); + const mappedHandler = new RestApiHandler({ + schema: client.$schema, + endpoint: 'http://localhost/api', + modelNameMapping: { User: 'users', Post: 'posts' }, + }); + const mappedSpec = await mappedHandler.generateSpec(); + expect(mappedSpec.paths?.['/users']).toBeDefined(); + expect(mappedSpec.paths?.['/posts']).toBeDefined(); + // Original paths should not exist + expect(mappedSpec.paths?.['/user']).toBeUndefined(); + expect(mappedSpec.paths?.['/post']).toBeUndefined(); + }); + + it('compound ID model paths exist', () => { + // PostLike has @@id([postId, userId]) + expect(spec.paths['/postLike']).toBeDefined(); + expect(spec.paths['/postLike/{id}']).toBeDefined(); + }); + + it('custom openApiOptions are reflected in info', async () => { + const client = await createTestClient(schema); + const customHandler = new RestApiHandler({ + schema: client.$schema, + endpoint: 'http://localhost/api', + }); + const customSpec = await customHandler.generateSpec({ + title: 'My Custom API', + version: '2.0.0', + description: 'A custom description', + }); + expect(customSpec.info.title).toBe('My Custom API'); + expect(customSpec.info.version).toBe('2.0.0'); + expect((customSpec.info as any).description).toBe('A custom description'); + }); +}); + +describe('REST OpenAPI spec generation - queryOptions', () => { + it('omit excludes fields from read schema', async () => { + const client = await createTestClient(schema); + const handler = new RestApiHandler({ + schema: client.$schema, + endpoint: 'http://localhost/api', + queryOptions: { omit: { User: { email: true } } }, + }); + const s = await handler.generateSpec(); + const userSchema = s.components?.schemas?.['User'] as any; + expect(userSchema.properties['myId']).toBeDefined(); + expect(userSchema.properties['email']).toBeUndefined(); + }); + + it('slicing excludedModels removes model from spec', async () => { + const client = await createTestClient(schema); + const handler = new RestApiHandler({ + schema: client.$schema, + endpoint: 'http://localhost/api', + queryOptions: { slicing: { excludedModels: ['Post'] as any } }, + }); + const s = await handler.generateSpec(); + expect(s.paths?.['/user']).toBeDefined(); + expect(s.paths?.['/post']).toBeUndefined(); + expect(s.components?.schemas?.['Post']).toBeUndefined(); + }); + + it('slicing includedModels limits models in spec', async () => { + const client = await createTestClient(schema); + const handler = new RestApiHandler({ + schema: client.$schema, + endpoint: 'http://localhost/api', + queryOptions: { slicing: { includedModels: ['User'] as any } }, + }); + const s = await handler.generateSpec(); + expect(s.paths?.['/user']).toBeDefined(); + expect(s.paths?.['/post']).toBeUndefined(); + }); + + it('slicing excludedFilterKinds removes filter params for a field', async () => { + const client = await createTestClient(schema); + const handler = new RestApiHandler({ + schema: client.$schema, + endpoint: 'http://localhost/api', + queryOptions: { + slicing: { + models: { + post: { + fields: { + title: { excludedFilterKinds: ['Like'] }, + viewCount: { excludedFilterKinds: ['Range'] }, + }, + }, + }, + } as any, + }, + }); + const s = await handler.generateSpec(); + const listOp = (s.paths as any)['/post'].get; + const paramNames = listOp.parameters.map((p: any) => ('name' in p ? p.name : p.$ref)); + + // Equality filters should still exist + expect(paramNames).toContain('filter[title]'); + expect(paramNames).toContain('filter[viewCount]'); + + // Like filters for title should be excluded + expect(paramNames).not.toContain('filter[title][$contains]'); + expect(paramNames).not.toContain('filter[title][$startsWith]'); + + // Range filters for viewCount should be excluded + expect(paramNames).not.toContain('filter[viewCount][$lt]'); + expect(paramNames).not.toContain('filter[viewCount][$gt]'); + }); + + it('slicing includedFilterKinds limits filter params for a field', async () => { + const client = await createTestClient(schema); + const handler = new RestApiHandler({ + schema: client.$schema, + endpoint: 'http://localhost/api', + queryOptions: { + slicing: { + models: { + post: { + fields: { + title: { includedFilterKinds: ['Equality'] }, + }, + }, + }, + } as any, + }, + }); + const s = await handler.generateSpec(); + const listOp = (s.paths as any)['/post'].get; + const paramNames = listOp.parameters.map((p: any) => ('name' in p ? p.name : p.$ref)); + + // Equality filter should exist + expect(paramNames).toContain('filter[title]'); + + // Like filters should be excluded (not in includedFilterKinds) + expect(paramNames).not.toContain('filter[title][$contains]'); + expect(paramNames).not.toContain('filter[title][$startsWith]'); + }); + + it('slicing $all field applies filter kind restriction to all fields', async () => { + const client = await createTestClient(schema); + const handler = new RestApiHandler({ + schema: client.$schema, + endpoint: 'http://localhost/api', + queryOptions: { + slicing: { + models: { + post: { + fields: { + $all: { includedFilterKinds: ['Equality'] }, + }, + }, + }, + } as any, + }, + }); + const s = await handler.generateSpec(); + const listOp = (s.paths as any)['/post'].get; + const paramNames = listOp.parameters.map((p: any) => ('name' in p ? p.name : p.$ref)); + + // Equality filters should exist + expect(paramNames).toContain('filter[title]'); + expect(paramNames).toContain('filter[viewCount]'); + + // Like and Range filters should be excluded + expect(paramNames).not.toContain('filter[title][$contains]'); + expect(paramNames).not.toContain('filter[viewCount][$lt]'); + }); + + it('slicing field-specific overrides $all for filter kinds', async () => { + const client = await createTestClient(schema); + const handler = new RestApiHandler({ + schema: client.$schema, + endpoint: 'http://localhost/api', + queryOptions: { + slicing: { + models: { + post: { + fields: { + $all: { includedFilterKinds: ['Equality'] }, + title: { includedFilterKinds: ['Equality', 'Like'] }, + }, + }, + }, + } as any, + }, + }); + const s = await handler.generateSpec(); + const listOp = (s.paths as any)['/post'].get; + const paramNames = listOp.parameters.map((p: any) => ('name' in p ? p.name : p.$ref)); + + // title should have both Equality and Like + expect(paramNames).toContain('filter[title]'); + expect(paramNames).toContain('filter[title][$contains]'); + + // viewCount should only have Equality (from $all) + expect(paramNames).toContain('filter[viewCount]'); + expect(paramNames).not.toContain('filter[viewCount][$lt]'); + }); + + it('slicing excludedFilterKinds on Equality removes basic filter param', async () => { + const client = await createTestClient(schema); + const handler = new RestApiHandler({ + schema: client.$schema, + endpoint: 'http://localhost/api', + queryOptions: { + slicing: { + models: { + post: { + fields: { + title: { excludedFilterKinds: ['Equality'] }, + }, + }, + }, + } as any, + }, + }); + const s = await handler.generateSpec(); + const listOp = (s.paths as any)['/post'].get; + const paramNames = listOp.parameters.map((p: any) => ('name' in p ? p.name : p.$ref)); + + // Basic equality filter should be excluded + expect(paramNames).not.toContain('filter[title]'); + + // Like filters should still exist + expect(paramNames).toContain('filter[title][$contains]'); + }); +}); + +describe('REST OpenAPI spec generation - with enum schema', () => { + it('enum schemas exist in components', async () => { + const enumSchema = ` +model Post { + id Int @id @default(autoincrement()) + title String + status PostStatus @default(DRAFT) +} + +enum PostStatus { + DRAFT + PUBLISHED + ARCHIVED +} +`; + const client = await createTestClient(enumSchema); + const h = new RestApiHandler({ + schema: client.$schema, + endpoint: 'http://localhost/api', + }); + const s = await h.generateSpec(); + expect(s.components?.schemas?.['PostStatus']).toBeDefined(); + expect((s.components?.schemas?.['PostStatus'] as any).type).toBe('string'); + expect((s.components?.schemas?.['PostStatus'] as any).enum).toContain('DRAFT'); + expect((s.components?.schemas?.['PostStatus'] as any).enum).toContain('PUBLISHED'); + }); +}); diff --git a/packages/server/test/openapi/rpc-openapi.test.ts b/packages/server/test/openapi/rpc-openapi.test.ts new file mode 100644 index 000000000..c46c3d0dc --- /dev/null +++ b/packages/server/test/openapi/rpc-openapi.test.ts @@ -0,0 +1,445 @@ +import { createTestClient } from '@zenstackhq/testtools'; +import { beforeAll, describe, expect, it } from 'vitest'; +import { RPCApiHandler } from '../../src/api/rpc'; +import { schema } from '../utils'; + +describe('RPC OpenAPI spec generation', () => { + let handler: RPCApiHandler; + let spec: any; + + beforeAll(async () => { + const client = await createTestClient(schema); + handler = new RPCApiHandler({ schema: client.$schema }); + spec = await handler.generateSpec(); + }); + + it('document structure is valid', () => { + expect(spec.openapi).toBe('3.1.0'); + expect(spec.info).toBeDefined(); + expect(spec.info.title).toBe('ZenStack Generated API'); + expect(spec.info.version).toBe('1.0.0'); + expect(spec.paths).toBeDefined(); + expect(spec.components).toBeDefined(); + expect(spec.components.schemas).toBeDefined(); + }); + + it('operation paths exist for User model', () => { + expect(spec.paths['/user/findMany']).toBeDefined(); + expect(spec.paths['/user/findUnique']).toBeDefined(); + expect(spec.paths['/user/findFirst']).toBeDefined(); + expect(spec.paths['/user/create']).toBeDefined(); + expect(spec.paths['/user/createMany']).toBeDefined(); + expect(spec.paths['/user/update']).toBeDefined(); + expect(spec.paths['/user/updateMany']).toBeDefined(); + expect(spec.paths['/user/upsert']).toBeDefined(); + expect(spec.paths['/user/delete']).toBeDefined(); + expect(spec.paths['/user/deleteMany']).toBeDefined(); + expect(spec.paths['/user/count']).toBeDefined(); + expect(spec.paths['/user/aggregate']).toBeDefined(); + expect(spec.paths['/user/groupBy']).toBeDefined(); + expect(spec.paths['/user/exists']).toBeDefined(); + }); + + it('operation paths exist for Post model', () => { + expect(spec.paths['/post/findMany']).toBeDefined(); + expect(spec.paths['/post/create']).toBeDefined(); + expect(spec.paths['/post/update']).toBeDefined(); + expect(spec.paths['/post/delete']).toBeDefined(); + }); + + it('HTTP methods are correct', () => { + // Read ops use GET + expect(spec.paths['/user/findMany'].get).toBeDefined(); + expect(spec.paths['/user/findUnique'].get).toBeDefined(); + expect(spec.paths['/user/count'].get).toBeDefined(); + expect(spec.paths['/user/exists'].get).toBeDefined(); + + // Write ops + expect(spec.paths['/user/create'].post).toBeDefined(); + expect(spec.paths['/user/createMany'].post).toBeDefined(); + expect(spec.paths['/user/upsert'].post).toBeDefined(); + + expect(spec.paths['/user/update'].patch).toBeDefined(); + expect(spec.paths['/user/updateMany'].patch).toBeDefined(); + + expect(spec.paths['/user/delete'].delete).toBeDefined(); + expect(spec.paths['/user/deleteMany'].delete).toBeDefined(); + }); + + it('transaction path exists', () => { + expect(spec.paths['/$transaction/sequential']).toBeDefined(); + expect(spec.paths['/$transaction/sequential'].post).toBeDefined(); + }); + + it('input schemas exist in components', () => { + expect(spec.components.schemas['UserCreateInput']).toBeDefined(); + expect(spec.components.schemas['UserUpdateInput']).toBeDefined(); + expect(spec.components.schemas['UserWhereInput']).toBeDefined(); + expect(spec.components.schemas['UserWhereUniqueInput']).toBeDefined(); + expect(spec.components.schemas['UserCreateArgs']).toBeDefined(); + expect(spec.components.schemas['UserUpdateArgs']).toBeDefined(); + expect(spec.components.schemas['UserFindManyArgs']).toBeDefined(); + expect(spec.components.schemas['UserFindUniqueArgs']).toBeDefined(); + }); + + it('output schema (User model) has correct fields', () => { + const userSchema = spec.components.schemas['User']; + expect(userSchema).toBeDefined(); + expect(userSchema.properties).toBeDefined(); + expect(userSchema.properties['id']).toMatchObject({ type: 'string' }); + expect(userSchema.properties['email']).toMatchObject({ type: 'string' }); + expect(userSchema.properties['viewCount']).toBeUndefined(); // on Post, not User + }); + + it('Post output schema has correct field types', () => { + const postSchema = spec.components.schemas['Post']; + expect(postSchema).toBeDefined(); + expect(postSchema.properties['viewCount']).toMatchObject({ type: 'integer' }); + expect(postSchema.properties['published']).toMatchObject({ type: 'boolean' }); + expect(postSchema.properties['createdAt']).toMatchObject({ type: 'string', format: 'date-time' }); + }); + + it('response wrapper has data and meta properties', () => { + const userResponse = spec.components.schemas['UserResponse']; + expect(userResponse).toBeDefined(); + expect(userResponse.properties?.data).toBeDefined(); + expect(userResponse.properties?.meta).toBeDefined(); + }); + + it('GET ops have q query parameter', () => { + const findManyOp = spec.paths['/user/findMany'].get; + expect(findManyOp.parameters).toBeDefined(); + const qParam = findManyOp.parameters.find((p: any) => p.name === 'q'); + expect(qParam).toBeDefined(); + expect(qParam.in).toBe('query'); + }); + + it('POST ops have request body', () => { + const createOp = spec.paths['/user/create'].post; + expect(createOp.requestBody).toBeDefined(); + expect(createOp.requestBody.required).toBe(true); + }); + + it('PATCH ops have request body', () => { + const updateOp = spec.paths['/user/update'].patch; + expect(updateOp.requestBody).toBeDefined(); + }); + + it('DELETE ops have q query parameter', () => { + const deleteOp = spec.paths['/user/delete'].delete; + expect(deleteOp.parameters).toBeDefined(); + const qParam = deleteOp.parameters.find((p: any) => p.name === 'q'); + expect(qParam).toBeDefined(); + }); + + it('shared error schema exists', () => { + expect(spec.components.schemas['_ErrorResponse']).toBeDefined(); + expect(spec.components.schemas['_Meta']).toBeDefined(); + }); + + it('custom openApiOptions are reflected in info', async () => { + const client = await createTestClient(schema); + const customHandler = new RPCApiHandler({ + schema: client.$schema, + }); + const customSpec = await customHandler.generateSpec({ + title: 'My RPC API', + version: '3.0.0', + }); + expect(customSpec.info.title).toBe('My RPC API'); + expect(customSpec.info.version).toBe('3.0.0'); + }); +}); + +describe('RPC OpenAPI spec generation - queryOptions', () => { + it('omit excludes fields from output schema', async () => { + const client = await createTestClient(schema); + const handler = new RPCApiHandler({ + schema: client.$schema, + queryOptions: { omit: { User: { email: true } } }, + }); + const s = await handler.generateSpec(); + const userSchema = s.components?.schemas?.['User'] as any; + expect(userSchema.properties['id']).toBeDefined(); + expect(userSchema.properties['email']).toBeUndefined(); + }); + + it('slicing excludedModels removes model from spec', async () => { + const client = await createTestClient(schema); + const handler = new RPCApiHandler({ + schema: client.$schema, + queryOptions: { slicing: { excludedModels: ['Post'] as any } }, + }); + const s = await handler.generateSpec(); + expect(s.paths?.['/user/findMany']).toBeDefined(); + expect(s.paths?.['/post/findMany']).toBeUndefined(); + expect(s.components?.schemas?.['Post']).toBeUndefined(); + }); + + it('slicing includedModels limits models in spec', async () => { + const client = await createTestClient(schema); + const handler = new RPCApiHandler({ + schema: client.$schema, + queryOptions: { slicing: { includedModels: ['User'] as any } }, + }); + const s = await handler.generateSpec(); + expect(s.paths?.['/user/findMany']).toBeDefined(); + expect(s.paths?.['/post/findMany']).toBeUndefined(); + }); + + it('slicing excludedOperations removes operations from spec', async () => { + const client = await createTestClient(schema); + const handler = new RPCApiHandler({ + schema: client.$schema, + queryOptions: { + slicing: { + models: { user: { excludedOperations: ['create', 'delete'] } } as any, + }, + }, + }); + const s = await handler.generateSpec(); + expect(s.paths?.['/user/findMany']).toBeDefined(); + expect(s.paths?.['/user/create']).toBeUndefined(); + expect(s.paths?.['/user/delete']).toBeUndefined(); + // Post unaffected + expect(s.paths?.['/post/create']).toBeDefined(); + }); + + it('slicing $all excludedOperations applies to all models', async () => { + const client = await createTestClient(schema); + const handler = new RPCApiHandler({ + schema: client.$schema, + queryOptions: { + slicing: { + models: { $all: { excludedOperations: ['delete', 'deleteMany'] } } as any, + }, + }, + }); + const s = await handler.generateSpec(); + expect(s.paths?.['/user/delete']).toBeUndefined(); + expect(s.paths?.['/post/delete']).toBeUndefined(); + expect(s.paths?.['/user/findMany']).toBeDefined(); + }); + + it('where input has filter operators by default', async () => { + const client = await createTestClient(schema); + const handler = new RPCApiHandler({ schema: client.$schema }); + const s = await handler.generateSpec(); + const whereInput = s.components?.schemas?.['PostWhereInput'] as any; + + // String field (title): Equality + Like operators + const titleFilter = whereInput.properties['title']; + expect(titleFilter).toBeDefined(); + // oneOf [baseType, filterObject] + expect(titleFilter.oneOf).toHaveLength(2); + const titleFilterObj = titleFilter.oneOf[1]; + expect(titleFilterObj.properties['equals']).toBeDefined(); + expect(titleFilterObj.properties['not']).toBeDefined(); + expect(titleFilterObj.properties['in']).toBeDefined(); + expect(titleFilterObj.properties['contains']).toBeDefined(); + expect(titleFilterObj.properties['startsWith']).toBeDefined(); + expect(titleFilterObj.properties['endsWith']).toBeDefined(); + + // Int field (viewCount): Equality + Range operators + const vcFilter = whereInput.properties['viewCount']; + expect(vcFilter).toBeDefined(); + const vcFilterObj = vcFilter.oneOf[1]; + expect(vcFilterObj.properties['equals']).toBeDefined(); + expect(vcFilterObj.properties['lt']).toBeDefined(); + expect(vcFilterObj.properties['gte']).toBeDefined(); + // Should not have Like operators + expect(vcFilterObj.properties['contains']).toBeUndefined(); + }); + + it('slicing excludedFilterKinds removes specific operators from where input', async () => { + const client = await createTestClient(schema); + const handler = new RPCApiHandler({ + schema: client.$schema, + queryOptions: { + slicing: { + models: { + post: { + fields: { + title: { excludedFilterKinds: ['Like'] }, + viewCount: { excludedFilterKinds: ['Range'] }, + }, + }, + }, + } as any, + }, + }); + const s = await handler.generateSpec(); + const whereInput = s.components?.schemas?.['PostWhereInput'] as any; + + // title: Equality operators remain, Like operators removed + const titleFilter = whereInput.properties['title']; + expect(titleFilter).toBeDefined(); + const titleFilterObj = titleFilter.oneOf[1]; + expect(titleFilterObj.properties['equals']).toBeDefined(); + expect(titleFilterObj.properties['in']).toBeDefined(); + expect(titleFilterObj.properties['contains']).toBeUndefined(); + expect(titleFilterObj.properties['startsWith']).toBeUndefined(); + + // viewCount: Equality operators remain, Range operators removed + const vcFilter = whereInput.properties['viewCount']; + expect(vcFilter).toBeDefined(); + const vcFilterObj = vcFilter.oneOf[1]; + expect(vcFilterObj.properties['equals']).toBeDefined(); + expect(vcFilterObj.properties['lt']).toBeUndefined(); + expect(vcFilterObj.properties['gte']).toBeUndefined(); + }); + + it('slicing excludedFilterKinds removes all operators removes field entirely', async () => { + const client = await createTestClient(schema); + const handler = new RPCApiHandler({ + schema: client.$schema, + queryOptions: { + slicing: { + models: { + post: { + fields: { + title: { excludedFilterKinds: ['Equality', 'Like'] }, + }, + }, + }, + } as any, + }, + }); + const s = await handler.generateSpec(); + const whereInput = s.components?.schemas?.['PostWhereInput'] as any; + // All filter kinds for title excluded -> field removed + expect(whereInput.properties['title']).toBeUndefined(); + // viewCount unaffected + expect(whereInput.properties['viewCount']).toBeDefined(); + }); + + it('slicing includedFilterKinds limits operators in where input', async () => { + const client = await createTestClient(schema); + const handler = new RPCApiHandler({ + schema: client.$schema, + queryOptions: { + slicing: { + models: { + post: { + fields: { + title: { includedFilterKinds: ['Equality'] }, + }, + }, + }, + } as any, + }, + }); + const s = await handler.generateSpec(); + const whereInput = s.components?.schemas?.['PostWhereInput'] as any; + + // title: only Equality operators + const titleFilter = whereInput.properties['title']; + expect(titleFilter).toBeDefined(); + const titleFilterObj = titleFilter.oneOf[1]; + expect(titleFilterObj.properties['equals']).toBeDefined(); + expect(titleFilterObj.properties['not']).toBeDefined(); + // Like operators excluded + expect(titleFilterObj.properties['contains']).toBeUndefined(); + expect(titleFilterObj.properties['startsWith']).toBeUndefined(); + }); + + it('slicing excludedFilterKinds on Equality removes shorthand and equality ops', async () => { + const client = await createTestClient(schema); + const handler = new RPCApiHandler({ + schema: client.$schema, + queryOptions: { + slicing: { + models: { + post: { + fields: { + title: { excludedFilterKinds: ['Equality'] }, + }, + }, + }, + } as any, + }, + }); + const s = await handler.generateSpec(); + const whereInput = s.components?.schemas?.['PostWhereInput'] as any; + + // title: no shorthand (no oneOf), just the filter object with Like operators + const titleFilter = whereInput.properties['title']; + expect(titleFilter).toBeDefined(); + expect(titleFilter.oneOf).toBeUndefined(); + expect(titleFilter.type).toBe('object'); + expect(titleFilter.properties['equals']).toBeUndefined(); + expect(titleFilter.properties['contains']).toBeDefined(); + expect(titleFilter.properties['startsWith']).toBeDefined(); + }); + + it('slicing $all field applies filter kind restriction to all fields', async () => { + const client = await createTestClient(schema); + const handler = new RPCApiHandler({ + schema: client.$schema, + queryOptions: { + slicing: { + models: { + post: { + fields: { + $all: { excludedFilterKinds: ['Equality', 'Range', 'Like', 'List', 'Json'] }, + }, + }, + }, + } as any, + }, + }); + const s = await handler.generateSpec(); + const whereInput = s.components?.schemas?.['PostWhereInput'] as any; + // All filter kinds excluded -> no field properties + expect(whereInput.properties['title']).toBeUndefined(); + expect(whereInput.properties['viewCount']).toBeUndefined(); + // Logical combinators still exist + expect(whereInput.properties['AND']).toBeDefined(); + expect(whereInput.properties['OR']).toBeDefined(); + }); +}); + +describe('RPC OpenAPI spec generation - with enum', () => { + it('enum schemas appear in components', async () => { + const enumSchema = ` +model Post { + id Int @id @default(autoincrement()) + title String + status PostStatus @default(DRAFT) +} + +enum PostStatus { + DRAFT + PUBLISHED + ARCHIVED +} +`; + const client = await createTestClient(enumSchema); + const h = new RPCApiHandler({ schema: client.$schema }); + const s = await h.generateSpec(); + expect(s.components?.schemas?.['PostStatus']).toBeDefined(); + expect((s.components?.schemas?.['PostStatus'] as any).type).toBe('string'); + expect((s.components?.schemas?.['PostStatus'] as any).enum).toContain('DRAFT'); + }); +}); + +describe('RPC OpenAPI spec generation - with procedures', () => { + it('procedure paths are generated', async () => { + const schemaWithProc = ` +model User { + id String @id @default(cuid()) + email String @unique +} + +procedure getUser(id: String): String +mutation procedure createUser(email: String): String +`; + const client = await createTestClient(schemaWithProc); + const h = new RPCApiHandler({ schema: client.$schema }); + const s = await h.generateSpec(); + expect(s.paths?.['/$procs/getUser']).toBeDefined(); + expect(s.paths?.['/$procs/getUser']?.get).toBeDefined(); + expect(s.paths?.['/$procs/createUser']).toBeDefined(); + expect(s.paths?.['/$procs/createUser']?.post).toBeDefined(); + }); +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c5ac83d9e..63cecc9cd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -702,6 +702,9 @@ importers: decimal.js: specifier: 'catalog:' version: 10.6.0 + openapi-types: + specifier: ^12.1.3 + version: 12.1.3 superjson: specifier: ^2.2.3 version: 2.2.3 @@ -7360,6 +7363,7 @@ packages: prebuild-install@7.1.3: resolution: {integrity: sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==} engines: {node: '>=10'} + deprecated: No longer maintained. Please contact the author of the relevant native addon; alternatives are available. hasBin: true prelude-ls@1.2.1: @@ -13234,7 +13238,7 @@ snapshots: eslint: 9.29.0(jiti@2.6.1) eslint-import-resolver-node: 0.3.9 eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.29.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.29.0(jiti@2.6.1)))(eslint@9.29.0(jiti@2.6.1)) - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.29.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.29.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.29.0(jiti@2.6.1)))(eslint@9.29.0(jiti@2.6.1)))(eslint@9.29.0(jiti@2.6.1)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.29.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.29.0(jiti@2.6.1)) eslint-plugin-jsx-a11y: 6.10.2(eslint@9.29.0(jiti@2.6.1)) eslint-plugin-react: 7.37.5(eslint@9.29.0(jiti@2.6.1)) eslint-plugin-react-hooks: 7.0.1(eslint@9.29.0(jiti@2.6.1)) @@ -13267,7 +13271,7 @@ snapshots: tinyglobby: 0.2.15 unrs-resolver: 1.11.1 optionalDependencies: - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.29.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.29.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.29.0(jiti@2.6.1)))(eslint@9.29.0(jiti@2.6.1)))(eslint@9.29.0(jiti@2.6.1)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.29.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.29.0(jiti@2.6.1)) transitivePeerDependencies: - supports-color @@ -13282,7 +13286,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.29.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.29.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.29.0(jiti@2.6.1)))(eslint@9.29.0(jiti@2.6.1)))(eslint@9.29.0(jiti@2.6.1)): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.29.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.29.0(jiti@2.6.1)): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 From ff5735f23876dd9ecabf806ffec6ef010949ee7c Mon Sep 17 00:00:00 2001 From: ymc9 <104139426+ymc9@users.noreply.github.com> Date: Wed, 18 Mar 2026 22:32:55 -0700 Subject: [PATCH 02/16] undo file renaming --- packages/server/src/api/rest/handler.ts | 2210 ---------------------- packages/server/src/api/rest/index.ts | 2212 ++++++++++++++++++++++- packages/server/src/api/rpc/handler.ts | 458 ----- packages/server/src/api/rpc/index.ts | 460 ++++- 4 files changed, 2670 insertions(+), 2670 deletions(-) delete mode 100644 packages/server/src/api/rest/handler.ts delete mode 100644 packages/server/src/api/rpc/handler.ts diff --git a/packages/server/src/api/rest/handler.ts b/packages/server/src/api/rest/handler.ts deleted file mode 100644 index 7d2c676b8..000000000 --- a/packages/server/src/api/rest/handler.ts +++ /dev/null @@ -1,2210 +0,0 @@ -import { clone, enumerate, lowerCaseFirst, paramCase } from '@zenstackhq/common-helpers'; -import { ORMError, ORMErrorReason, type ClientContract } from '@zenstackhq/orm'; -import type { FieldDef, ModelDef, SchemaDef } from '@zenstackhq/orm/schema'; -import { Decimal } from 'decimal.js'; -import SuperJSON from 'superjson'; -import tsjapi, { type Linker, type Paginator, type Relator, type Serializer, type SerializerOptions } from 'ts-japi'; -import { match } from 'ts-pattern'; -import UrlPattern from 'url-pattern'; -import z from 'zod'; -import { fromError } from 'zod-validation-error/v4'; -import type { ApiHandler, LogConfig, RequestContext, Response } from '../../types'; -import { getProcedureDef, mapProcedureArgs } from '../common/procedures'; -import { loggerSchema } from '../common/schemas'; -import type { CommonHandlerOptions, OpenApiSpecGenerator, OpenApiSpecOptions } from '../common/types'; -import { processSuperJsonRequestPayload } from '../common/utils'; -import { getZodErrorMessage, log, registerCustomSerializers } from '../utils'; -import { RestApiSpecGenerator } from './openapi'; - -/** - * Options for {@link RestApiHandler} - */ -export type RestApiHandlerOptions = { - /** - * The schema - */ - schema: Schema; - - /** - * Logging configuration - */ - log?: LogConfig; - - /** - * The base endpoint of the RESTful API, must be a valid URL - */ - endpoint: string; - - /** - * The default page size for limiting the number of results returned - * from collection queries, including resource collection, related data - * of collection types, and relationship of collection types. - * - * Defaults to 100. Set to Infinity to disable pagination. - */ - pageSize?: number; - - /** - * The divider used to separate compound ID fields in the URL. - * Defaults to '_'. - */ - idDivider?: string; - - /** - * The charset used for URL segment values. Defaults to `a-zA-Z0-9-_~ %`. You can change it if your entity's ID values - * allow different characters. Specifically, if your models use compound IDs and the idDivider is set to a different value, - * it should be included in the charset. - */ - urlSegmentCharset?: string; - - /** - * Mapping from model names to URL segment names. - */ - modelNameMapping?: Record; - - /** - * Mapping from model names to unique field name to be used as resource's ID. - */ - externalIdMapping?: Record; -} & CommonHandlerOptions; - -type RelationshipInfo = { - type: string; - idFields: FieldDef[]; - isCollection: boolean; - isOptional: boolean; -}; - -type ModelInfo = { - name: string; - idFields: FieldDef[]; - fields: Record; - relationships: Record; -}; - -type Match = { - type: string; - id: string; - relationship: string; -}; - -enum UrlPatterns { - SINGLE = 'single', - FETCH_RELATIONSHIP = 'fetchRelationship', - RELATIONSHIP = 'relationship', - COLLECTION = 'collection', -} - -class InvalidValueError extends Error { - constructor(message: string) { - super(message); - } -} - -const DEFAULT_PAGE_SIZE = 100; - -const FilterOperations = [ - 'lt', - 'lte', - 'gt', - 'gte', - 'between', - 'contains', - 'icontains', - 'search', - 'startsWith', - 'endsWith', - 'has', - 'hasEvery', - 'hasSome', - 'isEmpty', -] as const; - -type FilterOperationType = (typeof FilterOperations)[number] | undefined; - -const DEFAULT_ID_DIVIDER = '_'; - -registerCustomSerializers(); - -/** - * RESTful-style API request handler (compliant with JSON:API) - */ -export class RestApiHandler implements ApiHandler, OpenApiSpecGenerator { - // resource serializers - private serializers = new Map(); - - // error responses - private readonly errors: Record = { - unsupportedModel: { - status: 404, - title: 'Unsupported model type', - detail: 'The model type is not supported', - }, - unsupportedRelationship: { - status: 400, - title: 'Unsupported relationship', - detail: 'The relationship is not supported', - }, - invalidPath: { - status: 400, - title: 'The request path is invalid', - }, - invalidVerb: { - status: 400, - title: 'The HTTP verb is not supported', - }, - notFound: { - status: 404, - title: 'Resource not found', - }, - noId: { - status: 400, - title: 'Model without an ID field is not supported', - }, - invalidId: { - status: 400, - title: 'Resource ID is invalid', - }, - invalidPayload: { - status: 400, - title: 'Invalid payload', - }, - invalidRelationData: { - status: 400, - title: 'Invalid relation data', - detail: 'Invalid relationship data', - }, - invalidRelation: { - status: 400, - title: 'Invalid relation', - detail: 'Invalid relationship', - }, - invalidFilter: { - status: 400, - title: 'Invalid filter', - }, - invalidSort: { - status: 400, - title: 'Invalid sort', - }, - invalidValue: { - status: 400, - title: 'Invalid value for type', - }, - duplicatedFieldsParameter: { - status: 400, - title: 'Fields Parameter Duplicated', - }, - forbidden: { - status: 403, - title: 'Operation is forbidden', - }, - validationError: { - status: 422, - title: 'Operation is unprocessable due to validation errors', - }, - queryError: { - status: 400, - title: 'Error occurred while executing the query', - }, - unknownError: { - status: 500, - title: 'Unknown error', - }, - }; - - private filterParamPattern = new RegExp(/^filter(?(\[[^[\]]+\])+)$/); - - // zod schema for payload of creating and updating a resource - private createUpdatePayloadSchema = z - .object({ - data: z.object({ - type: z.string(), - attributes: z.object({}).passthrough().optional(), - relationships: z - .record( - z.string(), - z.object({ - data: z.union([ - z.object({ type: z.string(), id: z.union([z.string(), z.number()]) }), - z.array(z.object({ type: z.string(), id: z.union([z.string(), z.number()]) })), - ]), - }), - ) - .optional(), - }), - meta: z.object({}).passthrough().optional(), - }) - .strict(); - - // zod schema for updating a single relationship - private updateSingleRelationSchema = z.object({ - data: z.object({ type: z.string(), id: z.union([z.string(), z.number()]) }).nullable(), - }); - - // zod schema for updating collection relationship - private updateCollectionRelationSchema = z.object({ - data: z.array(z.object({ type: z.string(), id: z.union([z.string(), z.number()]) })), - }); - - private upsertMetaSchema = z.object({ - meta: z.object({ - operation: z.literal('upsert'), - matchFields: z.array(z.string()).min(1), - }), - }); - - // all known types and their metadata - private typeMap: Record = {}; - - // divider used to separate compound ID fields - private idDivider; - - private urlPatternMap: Record; - private modelNameMapping: Record; - private reverseModelNameMapping: Record; - private externalIdMapping: Record; - - constructor(private readonly options: RestApiHandlerOptions) { - this.validateOptions(options); - - this.idDivider = options.idDivider ?? DEFAULT_ID_DIVIDER; - const segmentCharset = options.urlSegmentCharset ?? 'a-zA-Z0-9-_~ %'; - - this.modelNameMapping = options.modelNameMapping ?? {}; - this.modelNameMapping = Object.fromEntries( - Object.entries(this.modelNameMapping).map(([k, v]) => [lowerCaseFirst(k), v]), - ); - this.reverseModelNameMapping = Object.fromEntries( - Object.entries(this.modelNameMapping).map(([k, v]) => [v, k]), - ); - - this.externalIdMapping = options.externalIdMapping ?? {}; - this.externalIdMapping = Object.fromEntries( - Object.entries(this.externalIdMapping).map(([k, v]) => [lowerCaseFirst(k), v]), - ); - - this.urlPatternMap = this.buildUrlPatternMap(segmentCharset); - - this.buildTypeMap(); - this.buildSerializers(); - } - - private validateOptions(options: RestApiHandlerOptions) { - const schema = z.strictObject({ - schema: z.object(), - log: loggerSchema.optional(), - endpoint: z.string().min(1), - pageSize: z.union([z.number().int().positive(), z.literal(Infinity)]).optional(), - idDivider: z.string().min(1).optional(), - urlSegmentCharset: z.string().min(1).optional(), - modelNameMapping: z.record(z.string(), z.string()).optional(), - externalIdMapping: z.record(z.string(), z.string()).optional(), - queryOptions: z.object().optional(), - }); - const parseResult = schema.safeParse(options); - if (!parseResult.success) { - throw new Error(`Invalid options: ${fromError(parseResult.error)}`); - } - } - - get schema() { - return this.options.schema; - } - - get log(): LogConfig | undefined { - return this.options.log; - } - - private buildUrlPatternMap(urlSegmentNameCharset: string): Record { - const options = { segmentValueCharset: urlSegmentNameCharset }; - - const buildPath = (segments: string[]) => { - return '/' + segments.join('/'); - }; - - return { - [UrlPatterns.SINGLE]: new UrlPattern(buildPath([':type', ':id']), options), - [UrlPatterns.FETCH_RELATIONSHIP]: new UrlPattern(buildPath([':type', ':id', ':relationship']), options), - [UrlPatterns.RELATIONSHIP]: new UrlPattern( - buildPath([':type', ':id', 'relationships', ':relationship']), - options, - ), - [UrlPatterns.COLLECTION]: new UrlPattern(buildPath([':type']), options), - }; - } - - private mapModelName(modelName: string): string { - return this.modelNameMapping[modelName] ?? modelName; - } - - private matchUrlPattern(path: string, routeType: UrlPatterns): Match | undefined { - const pattern = this.urlPatternMap[routeType]; - if (!pattern) { - throw new InvalidValueError(`Unknown route type: ${routeType}`); - } - - const match = pattern.match(path); - if (!match) { - return; - } - - if (match.type in this.modelNameMapping) { - throw new InvalidValueError( - `use the mapped model name: ${this.modelNameMapping[match.type]} and not ${match.type}`, - ); - } - - if (match.type in this.reverseModelNameMapping) { - match.type = this.reverseModelNameMapping[match.type]; - } - - return match; - } - - async handleRequest({ client, method, path, query, requestBody }: RequestContext): Promise { - method = method.toUpperCase(); - if (!path.startsWith('/')) { - path = '/' + path; - } - - try { - if (path.startsWith('/$procs/')) { - const proc = path.split('/')[2]; - return await this.processProcedureRequest({ client, method, proc, query, requestBody }); - } - - switch (method) { - case 'GET': { - let match = this.matchUrlPattern(path, UrlPatterns.SINGLE); - if (match) { - // single resource read - return await this.processSingleRead(client, match.type, match.id, query); - } - match = this.matchUrlPattern(path, UrlPatterns.FETCH_RELATIONSHIP); - if (match) { - // fetch related resource(s) - return await this.processFetchRelated(client, match.type, match.id, match.relationship, query); - } - - match = this.matchUrlPattern(path, UrlPatterns.RELATIONSHIP); - if (match) { - // read relationship - return await this.processReadRelationship( - client, - match.type, - match.id, - match.relationship, - query, - ); - } - - match = this.matchUrlPattern(path, UrlPatterns.COLLECTION); - if (match) { - // collection read - return await this.processCollectionRead(client, match.type, query); - } - - return this.makeError('invalidPath'); - } - - case 'POST': { - if (!requestBody) { - return this.makeError('invalidPayload'); - } - let match = this.matchUrlPattern(path, UrlPatterns.COLLECTION); - if (match) { - const body = requestBody as any; - const upsertMeta = this.upsertMetaSchema.safeParse(body); - if (upsertMeta.success) { - // resource upsert - return await this.processUpsert(client, match.type, query, requestBody); - } else { - // resource creation - return await this.processCreate(client, match.type, query, requestBody); - } - } - match = this.matchUrlPattern(path, UrlPatterns.RELATIONSHIP); - if (match) { - // relationship creation (collection relationship only) - return await this.processRelationshipCRUD( - client, - 'create', - match.type, - match.id, - match.relationship, - query, - requestBody, - ); - } - - return this.makeError('invalidPath'); - } - - // TODO: PUT for full update - case 'PUT': - case 'PATCH': { - if (!requestBody) { - return this.makeError('invalidPayload'); - } - let match = this.matchUrlPattern(path, UrlPatterns.SINGLE); - if (match) { - // resource update - return await this.processUpdate(client, match.type, match.id, query, requestBody); - } - match = this.matchUrlPattern(path, UrlPatterns.RELATIONSHIP); - if (match) { - // relationship update - return await this.processRelationshipCRUD( - client, - 'update', - match.type, - match.id, - match.relationship as string, - query, - requestBody, - ); - } - - return this.makeError('invalidPath'); - } - - case 'DELETE': { - let match = this.matchUrlPattern(path, UrlPatterns.SINGLE); - if (match) { - // resource deletion - return await this.processDelete(client, match.type, match.id); - } - - match = this.matchUrlPattern(path, UrlPatterns.RELATIONSHIP); - if (match) { - // relationship deletion (collection relationship only) - return await this.processRelationshipCRUD( - client, - 'delete', - match.type, - match.id, - match.relationship as string, - query, - requestBody, - ); - } - - return this.makeError('invalidPath'); - } - - default: - return this.makeError('invalidPath'); - } - } catch (err) { - if (err instanceof InvalidValueError) { - return this.makeError('invalidValue', err.message); - } else if (err instanceof ORMError) { - return this.handleORMError(err); - } else { - return this.handleGenericError(err); - } - } - } - - private handleGenericError(err: unknown): Response | PromiseLike { - return this.makeError('unknownError', err instanceof Error ? `${err.message}\n${err.stack}` : 'Unknown error'); - } - - private async processProcedureRequest({ - client, - method, - proc, - query, - requestBody, - }: { - client: ClientContract; - method: string; - proc?: string; - query?: Record; - requestBody?: unknown; - }): Promise { - if (!proc) { - return this.makeProcBadInputErrorResponse('missing procedure name'); - } - - const procDef = getProcedureDef(this.schema, proc); - if (!procDef) { - return this.makeProcBadInputErrorResponse(`unknown procedure: ${proc}`); - } - - const isMutation = !!procDef.mutation; - if (isMutation) { - if (method !== 'POST') { - return this.makeProcBadInputErrorResponse('invalid request method, only POST is supported'); - } - } else { - if (method !== 'GET') { - return this.makeProcBadInputErrorResponse('invalid request method, only GET is supported'); - } - } - - const argsPayload = method === 'POST' ? requestBody : query; - - // support SuperJSON request payload format - const { result: processedArgsPayload, error } = await processSuperJsonRequestPayload(argsPayload); - if (error) { - return this.makeProcBadInputErrorResponse(error); - } - - let procInput: unknown; - try { - procInput = mapProcedureArgs(procDef, processedArgsPayload); - } catch (err) { - return this.makeProcBadInputErrorResponse( - err instanceof Error ? err.message : 'invalid procedure arguments', - ); - } - - try { - log(this.log, 'debug', () => `handling "$procs.${proc}" request`); - - const clientResult = await (client as any).$procs?.[proc](procInput); - const toSerialize = this.toPlainObject(clientResult); - - const { json, meta } = SuperJSON.serialize(toSerialize); - const responseBody: any = { data: json }; - if (meta) { - responseBody.meta = { serialization: meta }; - } - - return { status: 200, body: responseBody }; - } catch (err) { - log(this.log, 'error', `error occurred when handling "$procs.${proc}" request`, err); - if (err instanceof ORMError) { - throw err; // top-level handler will take care of it - } - return this.makeProcGenericErrorResponse(err); - } - } - - private makeProcBadInputErrorResponse(message: string): Response { - const resp = this.makeError('invalidPayload', message, 400); - log(this.log, 'debug', () => `sending error response: ${JSON.stringify(resp)}`); - return resp; - } - - private makeProcGenericErrorResponse(err: unknown): Response { - const message = err instanceof Error ? err.message : 'unknown error'; - const resp = this.makeError('unknownError', message, 500); - log(this.log, 'debug', () => `sending error response: ${JSON.stringify(resp)}`); - return resp; - } - - private async processSingleRead( - client: ClientContract, - type: string, - resourceId: string, - query: Record | undefined, - ): Promise { - const typeInfo = this.getModelInfo(type); - if (!typeInfo) { - return this.makeUnsupportedModelError(type); - } - - const args: any = { where: this.makeIdFilter(typeInfo.idFields, resourceId) }; - - // include IDs of relation fields so that they can be serialized - this.includeRelationshipIds(type, args, 'include'); - - // handle "include" query parameter - let include: string[] | undefined; - if (query?.['include']) { - const { select, error, allIncludes } = this.buildRelationSelect(type, query['include'], query); - if (error) { - return error; - } - if (select) { - args.include = { ...args.include, ...select }; - } - include = allIncludes; - } - - // handle partial results for requested type - const { select, error } = this.buildPartialSelect(type, query); - if (error) return error; - if (select) { - args.select = { ...select, ...args.select }; - if (args.include) { - args.select = { - ...args.select, - ...args.include, - }; - args.include = undefined; - } - } - - const entity = await (client as any)[type].findUnique(args); - - if (entity) { - return { - status: 200, - body: await this.serializeItems(type, entity, { include }), - }; - } else { - return this.makeError('notFound'); - } - } - - private async processFetchRelated( - client: ClientContract, - type: string, - resourceId: string, - relationship: string, - query: Record | undefined, - ): Promise { - const typeInfo = this.getModelInfo(type); - if (!typeInfo) { - return this.makeUnsupportedModelError(type); - } - - const relationInfo = typeInfo.relationships[relationship]; - if (!relationInfo) { - return this.makeUnsupportedRelationshipError(type, relationship, 404); - } - - let select: any; - - // handle "include" query parameter - let include: string[] | undefined; - if (query?.['include']) { - const { - select: relationSelect, - error, - allIncludes, - } = this.buildRelationSelect(type, query['include'], query); - if (error) { - return error; - } - // trim the leading `$relationship.` from the include paths - include = allIncludes - .filter((i) => i.startsWith(`${relationship}.`)) - .map((i) => i.substring(`${relationship}.`.length)); - select = relationSelect; - } - - // handle partial results for requested type - if (!select) { - const { select: partialFields, error } = this.buildPartialSelect(lowerCaseFirst(relationInfo.type), query); - if (error) return error; - - select = partialFields ? { [relationship]: { select: { ...partialFields } } } : { [relationship]: true }; - } - - const args: any = { - where: this.makeIdFilter(typeInfo.idFields, resourceId), - select, - }; - - if (relationInfo.isCollection) { - // if related data is a collection, it can be filtered, sorted, and paginated - const error = this.injectRelationQuery(relationInfo.type, select, relationship, query); - if (error) { - return error; - } - } - - const entity: any = await (client as any)[type].findUnique(args); - - let paginator: Paginator | undefined; - - if (entity?._count?.[relationship] !== undefined) { - // build up paginator - const total = entity?._count?.[relationship] as number; - const url = this.makeNormalizedUrl(`/${type}/${resourceId}/${relationship}`, query); - const { offset, limit } = this.getPagination(query); - paginator = this.makePaginator(url, offset, limit, total); - } - - if (entity?.[relationship]) { - const mappedType = this.mapModelName(type); - return { - status: 200, - body: await this.serializeItems(relationInfo.type, entity[relationship], { - linkers: { - document: new tsjapi.Linker(() => - this.makeLinkUrl(`/${mappedType}/${resourceId}/${relationship}`), - ), - paginator, - }, - include, - }), - }; - } else { - return this.makeError('notFound'); - } - } - - private async processReadRelationship( - client: ClientContract, - type: string, - resourceId: string, - relationship: string, - query: Record | undefined, - ): Promise { - const typeInfo = this.getModelInfo(type); - if (!typeInfo) { - return this.makeUnsupportedModelError(type); - } - - const relationInfo = typeInfo.relationships[relationship]; - if (!relationInfo) { - return this.makeUnsupportedRelationshipError(type, relationship, 404); - } - - const args: any = { - where: this.makeIdFilter(typeInfo.idFields, resourceId), - select: this.makeIdSelect(typeInfo.idFields), - }; - - // include IDs of relation fields so that they can be serialized - args.select = { ...args.select, [relationship]: { select: this.makeIdSelect(relationInfo.idFields) } }; - - let paginator: Paginator | undefined; - - if (relationInfo.isCollection) { - // if related data is a collection, it can be filtered, sorted, and paginated - const error = this.injectRelationQuery(relationInfo.type, args.select, relationship, query); - if (error) { - return error; - } - } - - const entity: any = await (client as any)[type].findUnique(args); - const mappedType = this.mapModelName(type); - - if (entity?._count?.[relationship] !== undefined) { - // build up paginator - const total = entity?._count?.[relationship] as number; - const url = this.makeNormalizedUrl(`/${mappedType}/${resourceId}/relationships/${relationship}`, query); - const { offset, limit } = this.getPagination(query); - paginator = this.makePaginator(url, offset, limit, total); - } - - if (entity?.[relationship]) { - const serialized: any = await this.serializeItems(relationInfo.type, entity[relationship], { - linkers: { - document: new tsjapi.Linker(() => - this.makeLinkUrl(`/${mappedType}/${resourceId}/relationships/${relationship}`), - ), - paginator, - }, - onlyIdentifier: true, - }); - - return { - status: 200, - body: serialized, - }; - } else { - return this.makeError('notFound'); - } - } - - private async processCollectionRead( - client: ClientContract, - type: string, - query: Record | undefined, - ): Promise { - const typeInfo = this.getModelInfo(type); - if (!typeInfo) { - return this.makeUnsupportedModelError(type); - } - - const args: any = {}; - - // add filter - const { filter, error: filterError } = this.buildFilter(type, query); - if (filterError) { - return filterError; - } - if (filter) { - args.where = filter; - } - - const { sort, error: sortError } = this.buildSort(type, query); - if (sortError) { - return sortError; - } - if (sort) { - args.orderBy = sort; - } - - // include IDs of relation fields so that they can be serialized - this.includeRelationshipIds(type, args, 'include'); - - // handle "include" query parameter - let include: string[] | undefined; - if (query?.['include']) { - const { select, error, allIncludes } = this.buildRelationSelect(type, query['include'], query); - if (error) { - return error; - } - if (select) { - args.include = { ...args.include, ...select }; - } - include = allIncludes; - } - - // handle partial results for requested type - const { select, error } = this.buildPartialSelect(type, query); - if (error) return error; - if (select) { - args.select = { ...select, ...args.select }; - if (args.include) { - args.select = { - ...args.select, - ...args.include, - }; - args.include = undefined; - } - } - - const { offset, limit } = this.getPagination(query); - if (offset > 0) { - args.skip = offset; - } - - if (limit === Infinity) { - const entities = await (client as any)[type].findMany(args); - - const body = await this.serializeItems(type, entities, { include }); - const total = entities.length; - body.meta = this.addTotalCountToMeta(body.meta, total); - - return { - status: 200, - body: body, - }; - } else { - args.take = limit; - - const [entities, count] = await Promise.all([ - (client as any)[type].findMany(args), - (client as any)[type].count({ where: args.where ?? {} }), - ]); - const total = count as number; - - const mappedType = this.mapModelName(type); - const url = this.makeNormalizedUrl(`/${mappedType}`, query); - const options: Partial = { - include, - linkers: { - paginator: this.makePaginator(url, offset, limit, total), - }, - }; - const body = await this.serializeItems(type, entities, options); - body.meta = this.addTotalCountToMeta(body.meta, total); - - return { - status: 200, - body: body, - }; - } - } - - private buildPartialSelect(type: string, query: Record | undefined) { - const selectFieldsQuery = query?.[`fields[${type}]`]; - if (!selectFieldsQuery) { - return { select: undefined, error: undefined }; - } - - if (Array.isArray(selectFieldsQuery)) { - return { - select: undefined, - error: this.makeError('duplicatedFieldsParameter', `duplicated fields query for type ${type}`), - }; - } - - const typeInfo = this.getModelInfo(type); - if (!typeInfo) { - return { select: undefined, error: this.makeUnsupportedModelError(type) }; - } - - const selectFieldNames = selectFieldsQuery.split(',').filter((i) => i); - - const fields = selectFieldNames.reduce((acc, curr) => ({ ...acc, [curr]: true }), {}); - - return { - select: { ...this.makeIdSelect(typeInfo.idFields), ...fields }, - }; - } - - private addTotalCountToMeta(meta: any, total: any) { - return meta ? Object.assign(meta, { total }) : Object.assign({}, { total }); - } - - private makePaginator(baseUrl: string, offset: number, limit: number, total: number) { - if (limit === Infinity) { - return undefined; - } - - const totalPages = Math.ceil(total / limit); - - return new tsjapi.Paginator(() => ({ - first: this.replaceURLSearchParams(baseUrl, { 'page[limit]': limit }), - last: this.replaceURLSearchParams(baseUrl, { - 'page[offset]': (totalPages - 1) * limit, - }), - prev: - offset - limit >= 0 && offset - limit <= total - 1 - ? this.replaceURLSearchParams(baseUrl, { - 'page[offset]': offset - limit, - 'page[limit]': limit, - }) - : null, - next: - offset + limit <= total - 1 - ? this.replaceURLSearchParams(baseUrl, { - 'page[offset]': offset + limit, - 'page[limit]': limit, - }) - : null, - })); - } - - private processRequestBody(requestBody: unknown) { - let body: any = requestBody; - if (body.meta?.serialization) { - // superjson deserialize body if a serialization meta is provided - body = SuperJSON.deserialize({ json: body, meta: body.meta.serialization }); - } - - const parseResult = this.createUpdatePayloadSchema.safeParse(body); - if (!parseResult.success) { - return { - attributes: undefined, - relationships: undefined, - error: this.makeError('invalidPayload', getZodErrorMessage(parseResult.error)), - }; - } - - return { - attributes: parseResult.data.data.attributes, - relationships: parseResult.data.data.relationships, - error: undefined, - }; - } - - private async processCreate( - client: ClientContract, - type: string, - _query: Record | undefined, - requestBody: unknown, - ): Promise { - const typeInfo = this.getModelInfo(type); - if (!typeInfo) { - return this.makeUnsupportedModelError(type); - } - - const { attributes, relationships, error } = this.processRequestBody(requestBody); - if (error) { - return error; - } - - const createPayload: any = { data: { ...attributes } }; - - // turn relationship payload into `connect` objects - if (relationships) { - for (const [key, data] of Object.entries(relationships)) { - if (!data?.data) { - return this.makeError('invalidRelationData'); - } - - const relationInfo = typeInfo.relationships[key]; - if (!relationInfo) { - return this.makeUnsupportedRelationshipError(type, key, 400); - } - - if (relationInfo.isCollection) { - createPayload.data[key] = { - connect: enumerate(data.data).map((item: any) => - this.makeIdConnect(relationInfo.idFields, item.id), - ), - }; - } else { - if (typeof data.data !== 'object') { - return this.makeError('invalidRelationData'); - } - createPayload.data[key] = { - connect: this.makeIdConnect(relationInfo.idFields, data.data.id), - }; - } - - // make sure ID fields are included for result serialization - createPayload.include = { - ...createPayload.include, - [key]: { select: { [this.makeDefaultIdKey(relationInfo.idFields)]: true } }, - }; - } - } - - // include IDs of relation fields so that they can be serialized. - this.includeRelationshipIds(type, createPayload, 'include'); - - const entity = await (client as any)[type].create(createPayload); - return { - status: 201, - body: await this.serializeItems(type, entity), - }; - } - - private async processUpsert( - client: ClientContract, - type: string, - _query: Record | undefined, - requestBody: unknown, - ) { - const typeInfo = this.getModelInfo(type); - if (!typeInfo) { - return this.makeUnsupportedModelError(type); - } - - const modelName = typeInfo.name; - const { attributes, relationships, error } = this.processRequestBody(requestBody); - if (error) { - return error; - } - - const parseResult = this.upsertMetaSchema.safeParse(requestBody); - if (parseResult.error) { - return this.makeError('invalidPayload', getZodErrorMessage(parseResult.error)); - } - const matchFields = parseResult.data.meta.matchFields; - const uniqueFieldSets = this.getUniqueFieldSets(modelName); - - if (!uniqueFieldSets.some((set) => set.every((field) => matchFields.includes(field)))) { - return this.makeError('invalidPayload', 'Match fields must be unique fields', 400); - } - - const upsertPayload: any = { - where: this.makeUpsertWhere(matchFields, attributes, typeInfo), - create: { ...attributes }, - update: { - ...Object.fromEntries(Object.entries(attributes ?? {}).filter((e) => !matchFields.includes(e[0]))), - }, - }; - - if (relationships) { - for (const [key, data] of Object.entries(relationships)) { - if (!data?.data) { - return this.makeError('invalidRelationData'); - } - - const relationInfo = typeInfo.relationships[key]; - if (!relationInfo) { - return this.makeUnsupportedRelationshipError(modelName, key, 400); - } - - if (relationInfo.isCollection) { - upsertPayload.create[key] = { - connect: enumerate(data.data).map((item: any) => - this.makeIdConnect(relationInfo.idFields, item.id), - ), - }; - upsertPayload.update[key] = { - set: enumerate(data.data).map((item: any) => - this.makeIdConnect(relationInfo.idFields, item.id), - ), - }; - } else { - if (typeof data.data !== 'object') { - return this.makeError('invalidRelationData'); - } - upsertPayload.create[key] = { - connect: this.makeIdConnect(relationInfo.idFields, data.data.id), - }; - upsertPayload.update[key] = { - connect: this.makeIdConnect(relationInfo.idFields, data.data.id), - }; - } - } - } - - // include IDs of relation fields so that they can be serialized. - this.includeRelationshipIds(modelName, upsertPayload, 'include'); - - const entity = await (client as any)[modelName].upsert(upsertPayload); - - return { - status: 201, - body: await this.serializeItems(modelName, entity), - }; - } - - private getUniqueFieldSets(type: string) { - const modelDef = this.requireModel(type); - return Object.entries(modelDef.uniqueFields).map( - ([k, v]) => - typeof v.type === 'string' - ? [k] // single unique field - : Object.keys(v), // compound unique fields - ); - } - - private async processRelationshipCRUD( - client: ClientContract, - mode: 'create' | 'update' | 'delete', - type: string, - resourceId: string, - relationship: string, - _query: Record | undefined, - requestBody: unknown, - ): Promise { - const typeInfo = this.getModelInfo(type); - if (!typeInfo) { - return this.makeUnsupportedModelError(type); - } - - const relationInfo = typeInfo.relationships[relationship]; - if (!relationInfo) { - return this.makeUnsupportedRelationshipError(type, relationship, 404); - } - - if (!relationInfo.isCollection && mode !== 'update') { - // to-one relation can only be updated - return this.makeError('invalidVerb'); - } - - const updateArgs: any = { - where: this.makeIdFilter(typeInfo.idFields, resourceId), - select: { - ...typeInfo.idFields.reduce((acc, field) => ({ ...acc, [field.name]: true }), {}), - [relationship]: { select: this.makeIdSelect(relationInfo.idFields) }, - }, - }; - - if (!relationInfo.isCollection) { - // zod-parse payload - const parsed = this.updateSingleRelationSchema.safeParse(requestBody); - if (!parsed.success) { - return this.makeError('invalidPayload', getZodErrorMessage(parsed.error)); - } - - if (parsed.data.data === null) { - if (!relationInfo.isOptional) { - // cannot disconnect a required relation - return this.makeError('invalidPayload'); - } - // set null -> disconnect - updateArgs.data = { - [relationship]: { - disconnect: true, - }, - }; - } else { - updateArgs.data = { - [relationship]: { - connect: this.makeIdConnect(relationInfo.idFields, parsed.data.data.id), - }, - }; - } - } else { - // zod-parse payload - const parsed = this.updateCollectionRelationSchema.safeParse(requestBody); - if (!parsed.success) { - return this.makeError('invalidPayload', getZodErrorMessage(parsed.error)); - } - - // create -> connect, delete -> disconnect, update -> set - const relationVerb = mode === 'create' ? 'connect' : mode === 'delete' ? 'disconnect' : 'set'; - - updateArgs.data = { - [relationship]: { - [relationVerb]: enumerate(parsed.data.data).map((item: any) => - this.makeIdFilter(relationInfo.idFields, item.id), - ), - }, - }; - } - - const entity: any = await (client as any)[type].update(updateArgs); - - const mappedType = this.mapModelName(type); - - const serialized: any = await this.serializeItems(relationInfo.type, entity[relationship], { - linkers: { - document: new tsjapi.Linker(() => - this.makeLinkUrl(`/${mappedType}/${resourceId}/relationships/${relationship}`), - ), - }, - onlyIdentifier: true, - }); - - return { - status: 200, - body: serialized, - }; - } - - private async processUpdate( - client: ClientContract, - type: any, - resourceId: string, - _query: Record | undefined, - requestBody: unknown, - ): Promise { - const typeInfo = this.getModelInfo(type); - if (!typeInfo) { - return this.makeUnsupportedModelError(type); - } - - const { attributes, relationships, error } = this.processRequestBody(requestBody); - if (error) { - return error; - } - - const updatePayload: any = { - where: this.makeIdFilter(typeInfo.idFields, resourceId), - data: { ...attributes }, - }; - - // turn relationships into query payload - if (relationships) { - for (const [key, data] of Object.entries(relationships)) { - if (!data?.data) { - return this.makeError('invalidRelationData'); - } - - const relationInfo = typeInfo.relationships[key]; - if (!relationInfo) { - return this.makeUnsupportedRelationshipError(type, key, 400); - } - - if (relationInfo.isCollection) { - updatePayload.data[key] = { - set: enumerate(data.data).map((item: any) => ({ - [this.makeDefaultIdKey(relationInfo.idFields)]: item.id, - })), - }; - } else { - if (typeof data.data !== 'object') { - return this.makeError('invalidRelationData'); - } - updatePayload.data[key] = { - connect: { - [this.makeDefaultIdKey(relationInfo.idFields)]: data.data.id, - }, - }; - } - updatePayload.include = { - ...updatePayload.include, - [key]: { select: { [this.makeDefaultIdKey(relationInfo.idFields)]: true } }, - }; - } - } - - // include IDs of relation fields so that they can be serialized. - this.includeRelationshipIds(type, updatePayload, 'include'); - - const entity = await (client as any)[type].update(updatePayload); - return { - status: 200, - body: await this.serializeItems(type, entity), - }; - } - - private async processDelete(client: ClientContract, type: any, resourceId: string): Promise { - const typeInfo = this.getModelInfo(type); - if (!typeInfo) { - return this.makeUnsupportedModelError(type); - } - - await (client as any)[type].delete({ - where: this.makeIdFilter(typeInfo.idFields, resourceId), - }); - return { - status: 200, - body: { meta: {} }, - }; - } - - //#region utilities - - private requireModel(model: string): ModelDef { - const modelDef = this.schema.models[model]; - if (!modelDef) { - throw new Error(`Model ${model} is not defined in the schema`); - } - return modelDef; - } - - private getIdFields(model: string): FieldDef[] { - const modelDef = this.requireModel(model); - const modelLower = lowerCaseFirst(model); - if (!(modelLower in this.externalIdMapping)) { - return Object.values(modelDef.fields).filter((f) => modelDef.idFields.includes(f.name)); - } - - // map external ID name to unique constraint field - const externalIdName = this.externalIdMapping[modelLower]; - for (const [name, info] of Object.entries(modelDef.uniqueFields)) { - if (name === externalIdName) { - if (typeof info.type === 'string') { - // single unique field - return [this.requireField(model, name)]; - } else { - // compound unique fields - return Object.keys(info).map((f) => this.requireField(model, f)); - } - } - } - - throw new Error(`Model ${model} does not have unique key ${externalIdName}`); - } - - private requireField(model: string, field: string): FieldDef { - const modelDef = this.requireModel(model); - const fieldDef = modelDef.fields[field]; - if (!fieldDef) { - throw new Error(`Field ${field} is not defined in model ${model}`); - } - return fieldDef; - } - - private buildTypeMap() { - this.typeMap = {}; - for (const [model, { fields }] of Object.entries(this.schema.models)) { - const idFields = this.getIdFields(model); - if (idFields.length === 0) { - log(this.options.log, 'warn', `Not including model ${model} in the API because it has no ID field`); - continue; - } - - const modelInfo: ModelInfo = (this.typeMap[lowerCaseFirst(model)] = { - name: model, - idFields, - relationships: {}, - fields, - }); - - for (const [field, fieldInfo] of Object.entries(fields)) { - if (!fieldInfo.relation) { - continue; - } - const fieldTypeIdFields = this.getIdFields(fieldInfo.type); - if (fieldTypeIdFields.length === 0) { - log( - this.options.log, - 'warn', - `Not including relation ${model}.${field} in the API because it has no ID field`, - ); - continue; - } - - modelInfo.relationships[field] = { - type: fieldInfo.type, - idFields: fieldTypeIdFields, - isCollection: !!fieldInfo.array, - isOptional: !!fieldInfo.optional, - }; - } - } - } - - private getModelInfo(model: string): ModelInfo | undefined { - return this.typeMap[lowerCaseFirst(model)]; - } - - private makeLinkUrl(path: string) { - return `${this.options.endpoint}${path}`; - } - - private buildSerializers() { - const linkers: Record> = {}; - - for (const model of Object.keys(this.schema.models)) { - const ids = this.getIdFields(model); - const modelLower = lowerCaseFirst(model); - const mappedModel = this.mapModelName(modelLower); - - if (ids.length < 1) { - continue; - } - - const linker = new tsjapi.Linker((items) => - Array.isArray(items) - ? this.makeLinkUrl(`/${mappedModel}`) - : this.makeLinkUrl(`/${mappedModel}/${this.getId(model, items)}`), - ); - linkers[modelLower] = linker; - - let projection: Record | null = {}; - const modelDef = this.requireModel(model); - for (const [field, fieldDef] of Object.entries(modelDef.fields)) { - if (fieldDef.relation) { - projection[field] = 0; - } - } - if (Object.keys(projection).length === 0) { - projection = null; - } - - const serializer = new tsjapi.Serializer(model, { - version: '1.1', - idKey: this.makeIdKey(ids), - linkers: { - resource: linker, - document: linker, - }, - projection, - }); - this.serializers.set(modelLower, serializer); - } - - // set relators - for (const model of Object.keys(this.schema.models)) { - const modelLower = lowerCaseFirst(model); - const serializer = this.serializers.get(modelLower); - if (!serializer) { - continue; - } - - const relators: Record> = {}; - const modelDef = this.requireModel(model); - for (const [field, fieldDef] of Object.entries(modelDef.fields)) { - if (!fieldDef.relation) { - continue; - } - const fieldSerializer = this.serializers.get(lowerCaseFirst(fieldDef.type)); - if (!fieldSerializer) { - continue; - } - const fieldIds = this.getIdFields(fieldDef.type); - if (fieldIds.length > 0) { - const mappedModel = this.mapModelName(modelLower); - - const relator = new tsjapi.Relator( - async (data) => { - return (data as any)[field]; - }, - fieldSerializer, - { - relatedName: field, - linkers: { - related: new tsjapi.Linker((primary) => - this.makeLinkUrl(`/${mappedModel}/${this.getId(model, primary)}/${field}`), - ), - relationship: new tsjapi.Linker((primary) => - this.makeLinkUrl( - `/${mappedModel}/${this.getId(model, primary)}/relationships/${field}`, - ), - ), - }, - }, - ); - relators[field] = relator; - } - } - serializer.setRelators(relators); - } - } - - private getId(model: string, data: any) { - if (!data) { - return undefined; - } - const ids = this.getIdFields(model); - if (ids.length === 0) { - return undefined; - } else { - return data[this.makeIdKey(ids)]; - } - } - - private async serializeItems(model: string, items: unknown, options?: Partial>) { - model = lowerCaseFirst(model); - const serializer = this.serializers.get(model); - if (!serializer) { - throw new Error(`serializer not found for model ${model}`); - } - - const itemsWithId = clone(items); - this.injectCompoundId(model, itemsWithId); - - // serialize to JSON:API structure - const serialized = await serializer.serialize(itemsWithId, options); - - // convert the serialization result to plain object otherwise SuperJSON won't work - const plainResult = this.toPlainObject(serialized); - - // superjson serialize the result - const { json, meta } = SuperJSON.serialize(plainResult); - - const result: any = json; - if (meta) { - result.meta = { ...result.meta, serialization: meta }; - } - - return result; - } - - private injectCompoundId(model: string, items: unknown) { - const typeInfo = this.getModelInfo(model); - if (!typeInfo) { - return; - } - - // recursively traverse the entity to create synthetic ID field for models with compound ID - enumerate(items).forEach((item: any) => { - if (!item) { - return; - } - - if (typeInfo.idFields.length > 1) { - item[this.makeIdKey(typeInfo.idFields)] = this.makeCompoundId(typeInfo.idFields, item); - } - - for (const [key, value] of Object.entries(item)) { - if (typeInfo.relationships[key]) { - // field is a relationship, recurse - this.injectCompoundId(typeInfo.relationships[key].type, value); - } - } - }); - } - - private toPlainObject(data: any): any { - if (data === undefined || data === null) { - return data; - } - - if (Array.isArray(data)) { - return data.map((item: any) => this.toPlainObject(item)); - } - - if (typeof data === 'object') { - if (typeof data.toJSON === 'function') { - // custom toJSON function - return data.toJSON(); - } - const result: any = {}; - for (const [field, value] of Object.entries(data)) { - if (value === undefined || typeof value === 'function') { - // trim undefined and functions - continue; - } else if (field === 'attributes') { - // don't visit into entity data - result[field] = value; - } else { - result[field] = this.toPlainObject(value); - } - } - return result; - } - - return data; - } - - private replaceURLSearchParams(url: string, params: Record) { - const r = new URL(url); - for (const [key, value] of Object.entries(params)) { - r.searchParams.set(key, value.toString()); - } - return r.toString(); - } - - private makeIdFilter(idFields: FieldDef[], resourceId: string, nested: boolean = true) { - const decodedId = decodeURIComponent(resourceId); - if (idFields.length === 1) { - return { [idFields[0]!.name]: this.coerce(idFields[0]!, decodedId) }; - } else if (nested) { - return { - // TODO: support `@@id` with custom name - [idFields.map((idf) => idf.name).join(DEFAULT_ID_DIVIDER)]: idFields.reduce( - (acc, curr, idx) => ({ - ...acc, - [curr.name]: this.coerce(curr, decodedId.split(this.idDivider)[idx]), - }), - {}, - ), - }; - } else { - return idFields.reduce( - (acc, curr, idx) => ({ - ...acc, - [curr.name]: this.coerce(curr, decodedId.split(this.idDivider)[idx]), - }), - {}, - ); - } - } - - private makeIdSelect(idFields: FieldDef[]) { - if (idFields.length === 0) { - throw this.errors['noId']; - } - return idFields.reduce((acc, curr) => ({ ...acc, [curr.name]: true }), {}); - } - - private makeIdConnect(idFields: FieldDef[], id: string | number) { - if (idFields.length === 1) { - return { [idFields[0]!.name]: this.coerce(idFields[0]!, id) }; - } else { - return { - [this.makeDefaultIdKey(idFields)]: idFields.reduce( - (acc, curr, idx) => ({ - ...acc, - [curr.name]: this.coerce(curr, `${id}`.split(this.idDivider)[idx]), - }), - {}, - ), - }; - } - } - - private makeIdKey(idFields: FieldDef[]) { - return idFields.map((idf) => idf.name).join(this.idDivider); - } - - private makeDefaultIdKey(idFields: FieldDef[]) { - // TODO: support `@@id` with custom name - return idFields.map((idf) => idf.name).join(DEFAULT_ID_DIVIDER); - } - - private makeCompoundId(idFields: FieldDef[], item: any) { - return idFields.map((idf) => item[idf.name]).join(this.idDivider); - } - - private makeUpsertWhere(matchFields: any[], attributes: any, typeInfo: ModelInfo) { - const where = matchFields.reduce((acc: any, field: string) => { - acc[field] = attributes[field] ?? null; - return acc; - }, {}); - - if ( - typeInfo.idFields.length > 1 && - matchFields.some((mf) => typeInfo.idFields.map((idf) => idf.name).includes(mf)) - ) { - return { - [this.makeDefaultIdKey(typeInfo.idFields)]: where, - }; - } - - return where; - } - - private includeRelationshipIds(model: string, args: any, mode: 'select' | 'include') { - const typeInfo = this.getModelInfo(model); - if (!typeInfo) { - return; - } - for (const [relation, relationInfo] of Object.entries(typeInfo.relationships)) { - args[mode] = { ...args[mode], [relation]: { select: this.makeIdSelect(relationInfo.idFields) } }; - } - } - - private coerce(fieldDef: FieldDef, value: any) { - if (typeof value === 'string') { - if (fieldDef.attributes?.some((attr) => attr.name === '@json')) { - try { - return JSON.parse(value); - } catch { - throw new InvalidValueError(`invalid JSON value: ${value}`); - } - } - - const type = fieldDef.type; - if (type === 'Int') { - const parsed = parseInt(value); - if (isNaN(parsed)) { - throw new InvalidValueError(`invalid ${type} value: ${value}`); - } - return parsed; - } else if (type === 'BigInt') { - try { - return BigInt(value); - } catch { - throw new InvalidValueError(`invalid ${type} value: ${value}`); - } - } else if (type === 'Float') { - const parsed = parseFloat(value); - if (isNaN(parsed)) { - throw new InvalidValueError(`invalid ${type} value: ${value}`); - } - return parsed; - } else if (type === 'Decimal') { - try { - return new Decimal(value); - } catch { - throw new InvalidValueError(`invalid ${type} value: ${value}`); - } - } else if (type === 'Boolean') { - if (value === 'true') { - return true; - } else if (value === 'false') { - return false; - } else { - throw new InvalidValueError(`invalid ${type} value: ${value}`); - } - } - } - return value; - } - - private makeNormalizedUrl(path: string, query: Record | undefined) { - const url = new URL(this.makeLinkUrl(path)); - for (const [key, value] of Object.entries(query ?? {})) { - if ( - key.startsWith('filter[') || - key.startsWith('sort[') || - key === 'include' || - key.startsWith('include[') || - key.startsWith('fields[') - ) { - for (const v of enumerate(value)) { - url.searchParams.append(key, v); - } - } - } - return url.toString(); - } - - private getPagination(query: Record | undefined) { - if (!query) { - return { offset: 0, limit: this.options.pageSize ?? DEFAULT_PAGE_SIZE }; - } - - let offset = 0; - if (query['page[offset]']) { - const value = query['page[offset]']; - const offsetText = Array.isArray(value) ? value[value.length - 1]! : value; - offset = parseInt(offsetText); - if (isNaN(offset) || offset < 0) { - offset = 0; - } - } - - let pageSizeOption = this.options.pageSize ?? DEFAULT_PAGE_SIZE; - if (pageSizeOption <= 0) { - pageSizeOption = DEFAULT_PAGE_SIZE; - } - - let limit = pageSizeOption; - if (query['page[limit]']) { - const value = query['page[limit]']; - const limitText = Array.isArray(value) ? value[value.length - 1]! : value; - limit = parseInt(limitText); - if (isNaN(limit) || limit <= 0) { - limit = pageSizeOption; - } - limit = Math.min(pageSizeOption, limit); - } - - return { offset, limit }; - } - - private buildFilter( - type: string, - query: Record | undefined, - ): { filter: any; error: any } { - if (!query) { - return { filter: undefined, error: undefined }; - } - - const typeInfo = this.getModelInfo(type); - if (!typeInfo) { - return { filter: undefined, error: this.makeUnsupportedModelError(type) }; - } - - const items: any[] = []; - - for (const [key, value] of Object.entries(query)) { - if (!value) { - continue; - } - - // try matching query parameter key as "filter[x][y]..." - const match = key.match(this.filterParamPattern); - if (!match || !match.groups || !match.groups['match']) { - continue; - } - - const filterKeys = match.groups['match'] - .replaceAll(/[[\]]/g, ' ') - .split(' ') - .filter((i) => i); - - if (!filterKeys.length) { - continue; - } - - // turn filter into a nested query object - - const item: any = {}; - let curr = item; - let currType = typeInfo; - - for (const filterValue of enumerate(value)) { - for (let i = 0; i < filterKeys.length; i++) { - // extract filter operation from (optional) trailing $op - let filterKey = filterKeys[i]!; - let filterOp: FilterOperationType | undefined; - const pos = filterKey.indexOf('$'); - if (pos > 0) { - filterOp = filterKey.substring(pos + 1) as FilterOperationType; - filterKey = filterKey.substring(0, pos); - } - - if (!!filterOp && !FilterOperations.includes(filterOp)) { - return { - filter: undefined, - error: this.makeError('invalidFilter', `invalid filter operation: ${filterOp}`), - }; - } - - const idFields = this.getIdFields(currType.name); - const fieldDef = - filterKey === 'id' - ? Object.values(currType.fields).find((f) => idFields.some((idf) => idf.name === f.name)) - : currType.fields[filterKey]; - if (!fieldDef) { - return { filter: undefined, error: this.makeError('invalidFilter') }; - } - - if (!fieldDef.relation) { - // regular field - if (i !== filterKeys.length - 1) { - // must be the last segment of a filter - return { filter: undefined, error: this.makeError('invalidFilter') }; - } - curr[fieldDef.name] = this.makeFilterValue(fieldDef, filterValue, filterOp); - } else { - // relation field - if (i === filterKeys.length - 1) { - curr[fieldDef.name] = this.makeFilterValue(fieldDef, filterValue, filterOp); - } else { - // keep going - if (fieldDef.array) { - // collection filtering implies "some" operation - curr[fieldDef.name] = { some: {} }; - curr = curr[fieldDef.name].some; - } else { - curr = curr[fieldDef.name] = {}; - } - currType = this.getModelInfo(fieldDef.type)!; - } - } - } - items.push(item); - } - } - - if (items.length === 0) { - return { filter: undefined, error: undefined }; - } else { - // combine filters with AND - return { filter: items.length === 1 ? items[0] : { AND: items }, error: undefined }; - } - } - - private buildSort(type: string, query: Record | undefined) { - if (!query?.['sort']) { - return { sort: undefined, error: undefined }; - } - - const typeInfo = this.getModelInfo(type); - if (!typeInfo) { - return { sort: undefined, error: this.makeUnsupportedModelError(type) }; - } - - const result: any[] = []; - - for (const sortSpec of enumerate(query['sort'])) { - const sortFields = sortSpec.split(',').filter((i) => i); - - for (const sortField of sortFields) { - const dir = sortField.startsWith('-') ? 'desc' : 'asc'; - const cleanedSortField = sortField.startsWith('-') ? sortField.substring(1) : sortField; - const parts = cleanedSortField.split('.').filter((i) => i); - - const sortItem: any = {}; - let curr = sortItem; - let currType = typeInfo; - - for (let i = 0; i < parts.length; i++) { - const part = parts[i]!; - - const fieldInfo = currType.fields[part]; - if (!fieldInfo || fieldInfo.array) { - return { - sort: undefined, - error: this.makeError('invalidSort', 'sorting by array field is not supported'), - }; - } - - if (i === parts.length - 1) { - if (fieldInfo.relation) { - // relation field: sort by id - const relationType = this.getModelInfo(fieldInfo.type); - if (!relationType) { - return { sort: undefined, error: this.makeUnsupportedModelError(fieldInfo.type) }; - } - curr[fieldInfo.name] = relationType.idFields.reduce((acc: any, idField: FieldDef) => { - acc[idField.name] = dir; - return acc; - }, {}); - } else { - // regular field - curr[fieldInfo.name] = dir; - } - } else { - if (!fieldInfo.relation) { - // must be a relation field - return { - sort: undefined, - error: this.makeError( - 'invalidSort', - 'intermediate sort segments must be relationships', - ), - }; - } - // keep going - curr = curr[fieldInfo.name] = {}; - currType = this.getModelInfo(fieldInfo.type)!; - if (!currType) { - return { sort: undefined, error: this.makeUnsupportedModelError(fieldInfo.type) }; - } - } - } - - result.push(sortItem); - } - } - - return { sort: result, error: undefined }; - } - - private buildRelationSelect( - type: string, - include: string | string[], - query: Record | undefined, - ) { - const typeInfo = this.getModelInfo(type); - if (!typeInfo) { - return { select: undefined, error: this.makeUnsupportedModelError(type) }; - } - - const result: any = {}; - const allIncludes: string[] = []; - - for (const includeItem of enumerate(include)) { - const inclusions = includeItem.split(',').filter((i) => i); - for (const inclusion of inclusions) { - allIncludes.push(inclusion); - - const parts = inclusion.split('.'); - let currPayload = result; - let currType = typeInfo; - - for (let i = 0; i < parts.length; i++) { - const relation = parts[i]!; - const relationInfo = currType.relationships[relation]; - if (!relationInfo) { - return { select: undefined, error: this.makeUnsupportedRelationshipError(type, relation, 400) }; - } - - currType = this.getModelInfo(relationInfo.type)!; - if (!currType) { - return { select: undefined, error: this.makeUnsupportedModelError(relationInfo.type) }; - } - - // handle partial results for requested type - const { select, error } = this.buildPartialSelect(lowerCaseFirst(relationInfo.type), query); - if (error) return { select: undefined, error }; - - if (i !== parts.length - 1) { - if (select) { - currPayload[relation] = { select: { ...select } }; - currPayload = currPayload[relation].select; - } else { - currPayload[relation] = { include: { ...currPayload[relation]?.include } }; - currPayload = currPayload[relation].include; - } - } else { - currPayload[relation] = select - ? { - select: { ...select }, - } - : true; - } - } - } - } - - return { select: result, error: undefined, allIncludes }; - } - - private makeFilterValue(fieldDef: FieldDef, value: string, op: FilterOperationType): any { - // TODO: inequality filters? - if (fieldDef.relation) { - // relation filter is converted to an ID filter - const info = this.getModelInfo(fieldDef.type)!; - if (fieldDef.array) { - // filtering a to-many relation, imply 'some' operator - const values = value.split(',').filter((i) => i); - const filterValue = - values.length > 1 - ? { OR: values.map((v) => this.makeIdFilter(info.idFields, v, false)) } - : this.makeIdFilter(info.idFields, value, false); - return { some: filterValue }; - } else { - const values = value.split(',').filter((i) => i); - if (values.length > 1) { - return { OR: values.map((v) => this.makeIdFilter(info.idFields, v, false)) }; - } else { - return { is: this.makeIdFilter(info.idFields, value, false) }; - } - } - } else { - if (op === 'between') { - const parts = value.split(',').map((v) => this.coerce(fieldDef, v)); - if (parts.length !== 2) { - throw new InvalidValueError(`"between" expects exactly 2 comma-separated values`); - } - return { between: [parts[0]!, parts[1]!] }; - } - const coerced = this.coerce(fieldDef, value); - switch (op) { - case 'icontains': - return { contains: coerced, mode: 'insensitive' }; - case 'hasSome': - case 'hasEvery': { - const values = value - .split(',') - .filter((i) => i) - .map((v) => this.coerce(fieldDef, v)); - return { [op]: values }; - } - case 'isEmpty': - if (value !== 'true' && value !== 'false') { - throw new InvalidValueError(`Not a boolean: ${value}`); - } - return { isEmpty: value === 'true' ? true : false }; - default: - if (op === undefined) { - if (fieldDef.attributes?.some((attr) => attr.name === '@json')) { - // handle JSON value equality filter - return { equals: coerced }; - } - - // regular filter, split value by comma - const values = value - .split(',') - .filter((i) => i) - .map((v) => this.coerce(fieldDef, v)); - return values.length > 1 ? { in: values } : { equals: values[0] }; - } else { - return { [op]: coerced }; - } - } - } - } - - private injectRelationQuery( - type: string, - injectTarget: any, - injectKey: string, - query: Record | undefined, - ) { - const { filter, error: filterError } = this.buildFilter(type, query); - if (filterError) { - return filterError; - } - - if (filter) { - injectTarget[injectKey] = { ...injectTarget[injectKey], where: filter }; - } - - const { sort, error: sortError } = this.buildSort(type, query); - if (sortError) { - return sortError; - } - if (sort) { - injectTarget[injectKey] = { ...injectTarget[injectKey], orderBy: sort }; - } - - const pagination = this.getPagination(query); - const offset = pagination.offset; - if (offset > 0) { - // inject skip - injectTarget[injectKey] = { ...injectTarget[injectKey], skip: offset }; - } - const limit = pagination.limit; - if (limit !== Infinity) { - // inject take - injectTarget[injectKey] = { ...injectTarget[injectKey], take: limit }; - - // include a count query for the relationship - injectTarget._count = { select: { [injectKey]: true } }; - } - } - - private handleORMError(err: ORMError) { - return match(err.reason) - .with(ORMErrorReason.INVALID_INPUT, () => { - return this.makeError('validationError', err.message, 422); - }) - .with(ORMErrorReason.REJECTED_BY_POLICY, () => { - return this.makeError('forbidden', err.message, 403, { reason: err.rejectedByPolicyReason }); - }) - .with(ORMErrorReason.NOT_FOUND, () => { - return this.makeError('notFound', err.message, 404); - }) - .with(ORMErrorReason.DB_QUERY_ERROR, () => { - return this.makeError('queryError', err.message, 400, { - dbErrorCode: err.dbErrorCode, - }); - }) - .otherwise(() => { - return this.makeError('unknownError', err.message); - }); - } - - private makeError( - code: keyof typeof this.errors, - detail?: string, - status?: number, - otherFields: Record = {}, - ) { - status = status ?? this.errors[code]?.status ?? 500; - const error: any = { - status, - code: paramCase(code), - title: this.errors[code]?.title, - }; - - if (detail) { - error.detail = detail; - } - - Object.assign(error, otherFields); - - return { - status, - body: { - errors: [error], - }, - }; - } - - private makeUnsupportedModelError(model: string) { - return this.makeError('unsupportedModel', `Model ${model} doesn't exist`); - } - - private makeUnsupportedRelationshipError(model: string, relationship: string, status: number) { - return this.makeError('unsupportedRelationship', `Relationship ${model}.${relationship} doesn't exist`, status); - } - - //#endregion - - async generateSpec(options?: OpenApiSpecOptions) { - const generator = new RestApiSpecGenerator(this.options); - return generator.generateSpec(options); - } -} diff --git a/packages/server/src/api/rest/index.ts b/packages/server/src/api/rest/index.ts index 22b87a1fc..c25686ce9 100644 --- a/packages/server/src/api/rest/index.ts +++ b/packages/server/src/api/rest/index.ts @@ -1,2 +1,2212 @@ -export { RestApiHandler, type RestApiHandlerOptions } from './handler'; +import { clone, enumerate, lowerCaseFirst, paramCase } from '@zenstackhq/common-helpers'; +import { ORMError, ORMErrorReason, type ClientContract } from '@zenstackhq/orm'; +import type { FieldDef, ModelDef, SchemaDef } from '@zenstackhq/orm/schema'; +import { Decimal } from 'decimal.js'; +import SuperJSON from 'superjson'; +import tsjapi, { type Linker, type Paginator, type Relator, type Serializer, type SerializerOptions } from 'ts-japi'; +import { match } from 'ts-pattern'; +import UrlPattern from 'url-pattern'; +import z from 'zod'; +import { fromError } from 'zod-validation-error/v4'; +import type { ApiHandler, LogConfig, RequestContext, Response } from '../../types'; +import { getProcedureDef, mapProcedureArgs } from '../common/procedures'; +import { loggerSchema } from '../common/schemas'; +import type { CommonHandlerOptions, OpenApiSpecGenerator, OpenApiSpecOptions } from '../common/types'; +import { processSuperJsonRequestPayload } from '../common/utils'; +import { getZodErrorMessage, log, registerCustomSerializers } from '../utils'; +import { RestApiSpecGenerator } from './openapi'; + +/** + * Options for {@link RestApiHandler} + */ +export type RestApiHandlerOptions = { + /** + * The schema + */ + schema: Schema; + + /** + * Logging configuration + */ + log?: LogConfig; + + /** + * The base endpoint of the RESTful API, must be a valid URL + */ + endpoint: string; + + /** + * The default page size for limiting the number of results returned + * from collection queries, including resource collection, related data + * of collection types, and relationship of collection types. + * + * Defaults to 100. Set to Infinity to disable pagination. + */ + pageSize?: number; + + /** + * The divider used to separate compound ID fields in the URL. + * Defaults to '_'. + */ + idDivider?: string; + + /** + * The charset used for URL segment values. Defaults to `a-zA-Z0-9-_~ %`. You can change it if your entity's ID values + * allow different characters. Specifically, if your models use compound IDs and the idDivider is set to a different value, + * it should be included in the charset. + */ + urlSegmentCharset?: string; + + /** + * Mapping from model names to URL segment names. + */ + modelNameMapping?: Record; + + /** + * Mapping from model names to unique field name to be used as resource's ID. + */ + externalIdMapping?: Record; +} & CommonHandlerOptions; + +type RelationshipInfo = { + type: string; + idFields: FieldDef[]; + isCollection: boolean; + isOptional: boolean; +}; + +type ModelInfo = { + name: string; + idFields: FieldDef[]; + fields: Record; + relationships: Record; +}; + +type Match = { + type: string; + id: string; + relationship: string; +}; + +enum UrlPatterns { + SINGLE = 'single', + FETCH_RELATIONSHIP = 'fetchRelationship', + RELATIONSHIP = 'relationship', + COLLECTION = 'collection', +} + +class InvalidValueError extends Error { + constructor(message: string) { + super(message); + } +} + +const DEFAULT_PAGE_SIZE = 100; + +const FilterOperations = [ + 'lt', + 'lte', + 'gt', + 'gte', + 'between', + 'contains', + 'icontains', + 'search', + 'startsWith', + 'endsWith', + 'has', + 'hasEvery', + 'hasSome', + 'isEmpty', +] as const; + +type FilterOperationType = (typeof FilterOperations)[number] | undefined; + +const DEFAULT_ID_DIVIDER = '_'; + +registerCustomSerializers(); + +/** + * RESTful-style API request handler (compliant with JSON:API) + */ +export class RestApiHandler implements ApiHandler, OpenApiSpecGenerator { + // resource serializers + private serializers = new Map(); + + // error responses + private readonly errors: Record = { + unsupportedModel: { + status: 404, + title: 'Unsupported model type', + detail: 'The model type is not supported', + }, + unsupportedRelationship: { + status: 400, + title: 'Unsupported relationship', + detail: 'The relationship is not supported', + }, + invalidPath: { + status: 400, + title: 'The request path is invalid', + }, + invalidVerb: { + status: 400, + title: 'The HTTP verb is not supported', + }, + notFound: { + status: 404, + title: 'Resource not found', + }, + noId: { + status: 400, + title: 'Model without an ID field is not supported', + }, + invalidId: { + status: 400, + title: 'Resource ID is invalid', + }, + invalidPayload: { + status: 400, + title: 'Invalid payload', + }, + invalidRelationData: { + status: 400, + title: 'Invalid relation data', + detail: 'Invalid relationship data', + }, + invalidRelation: { + status: 400, + title: 'Invalid relation', + detail: 'Invalid relationship', + }, + invalidFilter: { + status: 400, + title: 'Invalid filter', + }, + invalidSort: { + status: 400, + title: 'Invalid sort', + }, + invalidValue: { + status: 400, + title: 'Invalid value for type', + }, + duplicatedFieldsParameter: { + status: 400, + title: 'Fields Parameter Duplicated', + }, + forbidden: { + status: 403, + title: 'Operation is forbidden', + }, + validationError: { + status: 422, + title: 'Operation is unprocessable due to validation errors', + }, + queryError: { + status: 400, + title: 'Error occurred while executing the query', + }, + unknownError: { + status: 500, + title: 'Unknown error', + }, + }; + + private filterParamPattern = new RegExp(/^filter(?(\[[^[\]]+\])+)$/); + + // zod schema for payload of creating and updating a resource + private createUpdatePayloadSchema = z + .object({ + data: z.object({ + type: z.string(), + attributes: z.object({}).passthrough().optional(), + relationships: z + .record( + z.string(), + z.object({ + data: z.union([ + z.object({ type: z.string(), id: z.union([z.string(), z.number()]) }), + z.array(z.object({ type: z.string(), id: z.union([z.string(), z.number()]) })), + ]), + }), + ) + .optional(), + }), + meta: z.object({}).passthrough().optional(), + }) + .strict(); + + // zod schema for updating a single relationship + private updateSingleRelationSchema = z.object({ + data: z.object({ type: z.string(), id: z.union([z.string(), z.number()]) }).nullable(), + }); + + // zod schema for updating collection relationship + private updateCollectionRelationSchema = z.object({ + data: z.array(z.object({ type: z.string(), id: z.union([z.string(), z.number()]) })), + }); + + private upsertMetaSchema = z.object({ + meta: z.object({ + operation: z.literal('upsert'), + matchFields: z.array(z.string()).min(1), + }), + }); + + // all known types and their metadata + private typeMap: Record = {}; + + // divider used to separate compound ID fields + private idDivider; + + private urlPatternMap: Record; + private modelNameMapping: Record; + private reverseModelNameMapping: Record; + private externalIdMapping: Record; + + constructor(private readonly options: RestApiHandlerOptions) { + this.validateOptions(options); + + this.idDivider = options.idDivider ?? DEFAULT_ID_DIVIDER; + const segmentCharset = options.urlSegmentCharset ?? 'a-zA-Z0-9-_~ %'; + + this.modelNameMapping = options.modelNameMapping ?? {}; + this.modelNameMapping = Object.fromEntries( + Object.entries(this.modelNameMapping).map(([k, v]) => [lowerCaseFirst(k), v]), + ); + this.reverseModelNameMapping = Object.fromEntries( + Object.entries(this.modelNameMapping).map(([k, v]) => [v, k]), + ); + + this.externalIdMapping = options.externalIdMapping ?? {}; + this.externalIdMapping = Object.fromEntries( + Object.entries(this.externalIdMapping).map(([k, v]) => [lowerCaseFirst(k), v]), + ); + + this.urlPatternMap = this.buildUrlPatternMap(segmentCharset); + + this.buildTypeMap(); + this.buildSerializers(); + } + + private validateOptions(options: RestApiHandlerOptions) { + const schema = z.strictObject({ + schema: z.object(), + log: loggerSchema.optional(), + endpoint: z.string().min(1), + pageSize: z.union([z.number().int().positive(), z.literal(Infinity)]).optional(), + idDivider: z.string().min(1).optional(), + urlSegmentCharset: z.string().min(1).optional(), + modelNameMapping: z.record(z.string(), z.string()).optional(), + externalIdMapping: z.record(z.string(), z.string()).optional(), + queryOptions: z.object().optional(), + }); + const parseResult = schema.safeParse(options); + if (!parseResult.success) { + throw new Error(`Invalid options: ${fromError(parseResult.error)}`); + } + } + + get schema() { + return this.options.schema; + } + + get log(): LogConfig | undefined { + return this.options.log; + } + + private buildUrlPatternMap(urlSegmentNameCharset: string): Record { + const options = { segmentValueCharset: urlSegmentNameCharset }; + + const buildPath = (segments: string[]) => { + return '/' + segments.join('/'); + }; + + return { + [UrlPatterns.SINGLE]: new UrlPattern(buildPath([':type', ':id']), options), + [UrlPatterns.FETCH_RELATIONSHIP]: new UrlPattern(buildPath([':type', ':id', ':relationship']), options), + [UrlPatterns.RELATIONSHIP]: new UrlPattern( + buildPath([':type', ':id', 'relationships', ':relationship']), + options, + ), + [UrlPatterns.COLLECTION]: new UrlPattern(buildPath([':type']), options), + }; + } + + private mapModelName(modelName: string): string { + return this.modelNameMapping[modelName] ?? modelName; + } + + private matchUrlPattern(path: string, routeType: UrlPatterns): Match | undefined { + const pattern = this.urlPatternMap[routeType]; + if (!pattern) { + throw new InvalidValueError(`Unknown route type: ${routeType}`); + } + + const match = pattern.match(path); + if (!match) { + return; + } + + if (match.type in this.modelNameMapping) { + throw new InvalidValueError( + `use the mapped model name: ${this.modelNameMapping[match.type]} and not ${match.type}`, + ); + } + + if (match.type in this.reverseModelNameMapping) { + match.type = this.reverseModelNameMapping[match.type]; + } + + return match; + } + + async handleRequest({ client, method, path, query, requestBody }: RequestContext): Promise { + method = method.toUpperCase(); + if (!path.startsWith('/')) { + path = '/' + path; + } + + try { + if (path.startsWith('/$procs/')) { + const proc = path.split('/')[2]; + return await this.processProcedureRequest({ client, method, proc, query, requestBody }); + } + + switch (method) { + case 'GET': { + let match = this.matchUrlPattern(path, UrlPatterns.SINGLE); + if (match) { + // single resource read + return await this.processSingleRead(client, match.type, match.id, query); + } + match = this.matchUrlPattern(path, UrlPatterns.FETCH_RELATIONSHIP); + if (match) { + // fetch related resource(s) + return await this.processFetchRelated(client, match.type, match.id, match.relationship, query); + } + + match = this.matchUrlPattern(path, UrlPatterns.RELATIONSHIP); + if (match) { + // read relationship + return await this.processReadRelationship( + client, + match.type, + match.id, + match.relationship, + query, + ); + } + + match = this.matchUrlPattern(path, UrlPatterns.COLLECTION); + if (match) { + // collection read + return await this.processCollectionRead(client, match.type, query); + } + + return this.makeError('invalidPath'); + } + + case 'POST': { + if (!requestBody) { + return this.makeError('invalidPayload'); + } + let match = this.matchUrlPattern(path, UrlPatterns.COLLECTION); + if (match) { + const body = requestBody as any; + const upsertMeta = this.upsertMetaSchema.safeParse(body); + if (upsertMeta.success) { + // resource upsert + return await this.processUpsert(client, match.type, query, requestBody); + } else { + // resource creation + return await this.processCreate(client, match.type, query, requestBody); + } + } + match = this.matchUrlPattern(path, UrlPatterns.RELATIONSHIP); + if (match) { + // relationship creation (collection relationship only) + return await this.processRelationshipCRUD( + client, + 'create', + match.type, + match.id, + match.relationship, + query, + requestBody, + ); + } + + return this.makeError('invalidPath'); + } + + // TODO: PUT for full update + case 'PUT': + case 'PATCH': { + if (!requestBody) { + return this.makeError('invalidPayload'); + } + let match = this.matchUrlPattern(path, UrlPatterns.SINGLE); + if (match) { + // resource update + return await this.processUpdate(client, match.type, match.id, query, requestBody); + } + match = this.matchUrlPattern(path, UrlPatterns.RELATIONSHIP); + if (match) { + // relationship update + return await this.processRelationshipCRUD( + client, + 'update', + match.type, + match.id, + match.relationship as string, + query, + requestBody, + ); + } + + return this.makeError('invalidPath'); + } + + case 'DELETE': { + let match = this.matchUrlPattern(path, UrlPatterns.SINGLE); + if (match) { + // resource deletion + return await this.processDelete(client, match.type, match.id); + } + + match = this.matchUrlPattern(path, UrlPatterns.RELATIONSHIP); + if (match) { + // relationship deletion (collection relationship only) + return await this.processRelationshipCRUD( + client, + 'delete', + match.type, + match.id, + match.relationship as string, + query, + requestBody, + ); + } + + return this.makeError('invalidPath'); + } + + default: + return this.makeError('invalidPath'); + } + } catch (err) { + if (err instanceof InvalidValueError) { + return this.makeError('invalidValue', err.message); + } else if (err instanceof ORMError) { + return this.handleORMError(err); + } else { + return this.handleGenericError(err); + } + } + } + + private handleGenericError(err: unknown): Response | PromiseLike { + return this.makeError('unknownError', err instanceof Error ? `${err.message}\n${err.stack}` : 'Unknown error'); + } + + private async processProcedureRequest({ + client, + method, + proc, + query, + requestBody, + }: { + client: ClientContract; + method: string; + proc?: string; + query?: Record; + requestBody?: unknown; + }): Promise { + if (!proc) { + return this.makeProcBadInputErrorResponse('missing procedure name'); + } + + const procDef = getProcedureDef(this.schema, proc); + if (!procDef) { + return this.makeProcBadInputErrorResponse(`unknown procedure: ${proc}`); + } + + const isMutation = !!procDef.mutation; + if (isMutation) { + if (method !== 'POST') { + return this.makeProcBadInputErrorResponse('invalid request method, only POST is supported'); + } + } else { + if (method !== 'GET') { + return this.makeProcBadInputErrorResponse('invalid request method, only GET is supported'); + } + } + + const argsPayload = method === 'POST' ? requestBody : query; + + // support SuperJSON request payload format + const { result: processedArgsPayload, error } = await processSuperJsonRequestPayload(argsPayload); + if (error) { + return this.makeProcBadInputErrorResponse(error); + } + + let procInput: unknown; + try { + procInput = mapProcedureArgs(procDef, processedArgsPayload); + } catch (err) { + return this.makeProcBadInputErrorResponse( + err instanceof Error ? err.message : 'invalid procedure arguments', + ); + } + + try { + log(this.log, 'debug', () => `handling "$procs.${proc}" request`); + + const clientResult = await (client as any).$procs?.[proc](procInput); + const toSerialize = this.toPlainObject(clientResult); + + const { json, meta } = SuperJSON.serialize(toSerialize); + const responseBody: any = { data: json }; + if (meta) { + responseBody.meta = { serialization: meta }; + } + + return { status: 200, body: responseBody }; + } catch (err) { + log(this.log, 'error', `error occurred when handling "$procs.${proc}" request`, err); + if (err instanceof ORMError) { + throw err; // top-level handler will take care of it + } + return this.makeProcGenericErrorResponse(err); + } + } + + private makeProcBadInputErrorResponse(message: string): Response { + const resp = this.makeError('invalidPayload', message, 400); + log(this.log, 'debug', () => `sending error response: ${JSON.stringify(resp)}`); + return resp; + } + + private makeProcGenericErrorResponse(err: unknown): Response { + const message = err instanceof Error ? err.message : 'unknown error'; + const resp = this.makeError('unknownError', message, 500); + log(this.log, 'debug', () => `sending error response: ${JSON.stringify(resp)}`); + return resp; + } + + private async processSingleRead( + client: ClientContract, + type: string, + resourceId: string, + query: Record | undefined, + ): Promise { + const typeInfo = this.getModelInfo(type); + if (!typeInfo) { + return this.makeUnsupportedModelError(type); + } + + const args: any = { where: this.makeIdFilter(typeInfo.idFields, resourceId) }; + + // include IDs of relation fields so that they can be serialized + this.includeRelationshipIds(type, args, 'include'); + + // handle "include" query parameter + let include: string[] | undefined; + if (query?.['include']) { + const { select, error, allIncludes } = this.buildRelationSelect(type, query['include'], query); + if (error) { + return error; + } + if (select) { + args.include = { ...args.include, ...select }; + } + include = allIncludes; + } + + // handle partial results for requested type + const { select, error } = this.buildPartialSelect(type, query); + if (error) return error; + if (select) { + args.select = { ...select, ...args.select }; + if (args.include) { + args.select = { + ...args.select, + ...args.include, + }; + args.include = undefined; + } + } + + const entity = await (client as any)[type].findUnique(args); + + if (entity) { + return { + status: 200, + body: await this.serializeItems(type, entity, { include }), + }; + } else { + return this.makeError('notFound'); + } + } + + private async processFetchRelated( + client: ClientContract, + type: string, + resourceId: string, + relationship: string, + query: Record | undefined, + ): Promise { + const typeInfo = this.getModelInfo(type); + if (!typeInfo) { + return this.makeUnsupportedModelError(type); + } + + const relationInfo = typeInfo.relationships[relationship]; + if (!relationInfo) { + return this.makeUnsupportedRelationshipError(type, relationship, 404); + } + + let select: any; + + // handle "include" query parameter + let include: string[] | undefined; + if (query?.['include']) { + const { + select: relationSelect, + error, + allIncludes, + } = this.buildRelationSelect(type, query['include'], query); + if (error) { + return error; + } + // trim the leading `$relationship.` from the include paths + include = allIncludes + .filter((i) => i.startsWith(`${relationship}.`)) + .map((i) => i.substring(`${relationship}.`.length)); + select = relationSelect; + } + + // handle partial results for requested type + if (!select) { + const { select: partialFields, error } = this.buildPartialSelect(lowerCaseFirst(relationInfo.type), query); + if (error) return error; + + select = partialFields ? { [relationship]: { select: { ...partialFields } } } : { [relationship]: true }; + } + + const args: any = { + where: this.makeIdFilter(typeInfo.idFields, resourceId), + select, + }; + + if (relationInfo.isCollection) { + // if related data is a collection, it can be filtered, sorted, and paginated + const error = this.injectRelationQuery(relationInfo.type, select, relationship, query); + if (error) { + return error; + } + } + + const entity: any = await (client as any)[type].findUnique(args); + + let paginator: Paginator | undefined; + + if (entity?._count?.[relationship] !== undefined) { + // build up paginator + const total = entity?._count?.[relationship] as number; + const url = this.makeNormalizedUrl(`/${type}/${resourceId}/${relationship}`, query); + const { offset, limit } = this.getPagination(query); + paginator = this.makePaginator(url, offset, limit, total); + } + + if (entity?.[relationship]) { + const mappedType = this.mapModelName(type); + return { + status: 200, + body: await this.serializeItems(relationInfo.type, entity[relationship], { + linkers: { + document: new tsjapi.Linker(() => + this.makeLinkUrl(`/${mappedType}/${resourceId}/${relationship}`), + ), + paginator, + }, + include, + }), + }; + } else { + return this.makeError('notFound'); + } + } + + private async processReadRelationship( + client: ClientContract, + type: string, + resourceId: string, + relationship: string, + query: Record | undefined, + ): Promise { + const typeInfo = this.getModelInfo(type); + if (!typeInfo) { + return this.makeUnsupportedModelError(type); + } + + const relationInfo = typeInfo.relationships[relationship]; + if (!relationInfo) { + return this.makeUnsupportedRelationshipError(type, relationship, 404); + } + + const args: any = { + where: this.makeIdFilter(typeInfo.idFields, resourceId), + select: this.makeIdSelect(typeInfo.idFields), + }; + + // include IDs of relation fields so that they can be serialized + args.select = { ...args.select, [relationship]: { select: this.makeIdSelect(relationInfo.idFields) } }; + + let paginator: Paginator | undefined; + + if (relationInfo.isCollection) { + // if related data is a collection, it can be filtered, sorted, and paginated + const error = this.injectRelationQuery(relationInfo.type, args.select, relationship, query); + if (error) { + return error; + } + } + + const entity: any = await (client as any)[type].findUnique(args); + const mappedType = this.mapModelName(type); + + if (entity?._count?.[relationship] !== undefined) { + // build up paginator + const total = entity?._count?.[relationship] as number; + const url = this.makeNormalizedUrl(`/${mappedType}/${resourceId}/relationships/${relationship}`, query); + const { offset, limit } = this.getPagination(query); + paginator = this.makePaginator(url, offset, limit, total); + } + + if (entity?.[relationship]) { + const serialized: any = await this.serializeItems(relationInfo.type, entity[relationship], { + linkers: { + document: new tsjapi.Linker(() => + this.makeLinkUrl(`/${mappedType}/${resourceId}/relationships/${relationship}`), + ), + paginator, + }, + onlyIdentifier: true, + }); + + return { + status: 200, + body: serialized, + }; + } else { + return this.makeError('notFound'); + } + } + + private async processCollectionRead( + client: ClientContract, + type: string, + query: Record | undefined, + ): Promise { + const typeInfo = this.getModelInfo(type); + if (!typeInfo) { + return this.makeUnsupportedModelError(type); + } + + const args: any = {}; + + // add filter + const { filter, error: filterError } = this.buildFilter(type, query); + if (filterError) { + return filterError; + } + if (filter) { + args.where = filter; + } + + const { sort, error: sortError } = this.buildSort(type, query); + if (sortError) { + return sortError; + } + if (sort) { + args.orderBy = sort; + } + + // include IDs of relation fields so that they can be serialized + this.includeRelationshipIds(type, args, 'include'); + + // handle "include" query parameter + let include: string[] | undefined; + if (query?.['include']) { + const { select, error, allIncludes } = this.buildRelationSelect(type, query['include'], query); + if (error) { + return error; + } + if (select) { + args.include = { ...args.include, ...select }; + } + include = allIncludes; + } + + // handle partial results for requested type + const { select, error } = this.buildPartialSelect(type, query); + if (error) return error; + if (select) { + args.select = { ...select, ...args.select }; + if (args.include) { + args.select = { + ...args.select, + ...args.include, + }; + args.include = undefined; + } + } + + const { offset, limit } = this.getPagination(query); + if (offset > 0) { + args.skip = offset; + } + + if (limit === Infinity) { + const entities = await (client as any)[type].findMany(args); + + const body = await this.serializeItems(type, entities, { include }); + const total = entities.length; + body.meta = this.addTotalCountToMeta(body.meta, total); + + return { + status: 200, + body: body, + }; + } else { + args.take = limit; + + const [entities, count] = await Promise.all([ + (client as any)[type].findMany(args), + (client as any)[type].count({ where: args.where ?? {} }), + ]); + const total = count as number; + + const mappedType = this.mapModelName(type); + const url = this.makeNormalizedUrl(`/${mappedType}`, query); + const options: Partial = { + include, + linkers: { + paginator: this.makePaginator(url, offset, limit, total), + }, + }; + const body = await this.serializeItems(type, entities, options); + body.meta = this.addTotalCountToMeta(body.meta, total); + + return { + status: 200, + body: body, + }; + } + } + + private buildPartialSelect(type: string, query: Record | undefined) { + const selectFieldsQuery = query?.[`fields[${type}]`]; + if (!selectFieldsQuery) { + return { select: undefined, error: undefined }; + } + + if (Array.isArray(selectFieldsQuery)) { + return { + select: undefined, + error: this.makeError('duplicatedFieldsParameter', `duplicated fields query for type ${type}`), + }; + } + + const typeInfo = this.getModelInfo(type); + if (!typeInfo) { + return { select: undefined, error: this.makeUnsupportedModelError(type) }; + } + + const selectFieldNames = selectFieldsQuery.split(',').filter((i) => i); + + const fields = selectFieldNames.reduce((acc, curr) => ({ ...acc, [curr]: true }), {}); + + return { + select: { ...this.makeIdSelect(typeInfo.idFields), ...fields }, + }; + } + + private addTotalCountToMeta(meta: any, total: any) { + return meta ? Object.assign(meta, { total }) : Object.assign({}, { total }); + } + + private makePaginator(baseUrl: string, offset: number, limit: number, total: number) { + if (limit === Infinity) { + return undefined; + } + + const totalPages = Math.ceil(total / limit); + + return new tsjapi.Paginator(() => ({ + first: this.replaceURLSearchParams(baseUrl, { 'page[limit]': limit }), + last: this.replaceURLSearchParams(baseUrl, { + 'page[offset]': (totalPages - 1) * limit, + }), + prev: + offset - limit >= 0 && offset - limit <= total - 1 + ? this.replaceURLSearchParams(baseUrl, { + 'page[offset]': offset - limit, + 'page[limit]': limit, + }) + : null, + next: + offset + limit <= total - 1 + ? this.replaceURLSearchParams(baseUrl, { + 'page[offset]': offset + limit, + 'page[limit]': limit, + }) + : null, + })); + } + + private processRequestBody(requestBody: unknown) { + let body: any = requestBody; + if (body.meta?.serialization) { + // superjson deserialize body if a serialization meta is provided + body = SuperJSON.deserialize({ json: body, meta: body.meta.serialization }); + } + + const parseResult = this.createUpdatePayloadSchema.safeParse(body); + if (!parseResult.success) { + return { + attributes: undefined, + relationships: undefined, + error: this.makeError('invalidPayload', getZodErrorMessage(parseResult.error)), + }; + } + + return { + attributes: parseResult.data.data.attributes, + relationships: parseResult.data.data.relationships, + error: undefined, + }; + } + + private async processCreate( + client: ClientContract, + type: string, + _query: Record | undefined, + requestBody: unknown, + ): Promise { + const typeInfo = this.getModelInfo(type); + if (!typeInfo) { + return this.makeUnsupportedModelError(type); + } + + const { attributes, relationships, error } = this.processRequestBody(requestBody); + if (error) { + return error; + } + + const createPayload: any = { data: { ...attributes } }; + + // turn relationship payload into `connect` objects + if (relationships) { + for (const [key, data] of Object.entries(relationships)) { + if (!data?.data) { + return this.makeError('invalidRelationData'); + } + + const relationInfo = typeInfo.relationships[key]; + if (!relationInfo) { + return this.makeUnsupportedRelationshipError(type, key, 400); + } + + if (relationInfo.isCollection) { + createPayload.data[key] = { + connect: enumerate(data.data).map((item: any) => + this.makeIdConnect(relationInfo.idFields, item.id), + ), + }; + } else { + if (typeof data.data !== 'object') { + return this.makeError('invalidRelationData'); + } + createPayload.data[key] = { + connect: this.makeIdConnect(relationInfo.idFields, data.data.id), + }; + } + + // make sure ID fields are included for result serialization + createPayload.include = { + ...createPayload.include, + [key]: { select: { [this.makeDefaultIdKey(relationInfo.idFields)]: true } }, + }; + } + } + + // include IDs of relation fields so that they can be serialized. + this.includeRelationshipIds(type, createPayload, 'include'); + + const entity = await (client as any)[type].create(createPayload); + return { + status: 201, + body: await this.serializeItems(type, entity), + }; + } + + private async processUpsert( + client: ClientContract, + type: string, + _query: Record | undefined, + requestBody: unknown, + ) { + const typeInfo = this.getModelInfo(type); + if (!typeInfo) { + return this.makeUnsupportedModelError(type); + } + + const modelName = typeInfo.name; + const { attributes, relationships, error } = this.processRequestBody(requestBody); + if (error) { + return error; + } + + const parseResult = this.upsertMetaSchema.safeParse(requestBody); + if (parseResult.error) { + return this.makeError('invalidPayload', getZodErrorMessage(parseResult.error)); + } + const matchFields = parseResult.data.meta.matchFields; + const uniqueFieldSets = this.getUniqueFieldSets(modelName); + + if (!uniqueFieldSets.some((set) => set.every((field) => matchFields.includes(field)))) { + return this.makeError('invalidPayload', 'Match fields must be unique fields', 400); + } + + const upsertPayload: any = { + where: this.makeUpsertWhere(matchFields, attributes, typeInfo), + create: { ...attributes }, + update: { + ...Object.fromEntries(Object.entries(attributes ?? {}).filter((e) => !matchFields.includes(e[0]))), + }, + }; + + if (relationships) { + for (const [key, data] of Object.entries(relationships)) { + if (!data?.data) { + return this.makeError('invalidRelationData'); + } + + const relationInfo = typeInfo.relationships[key]; + if (!relationInfo) { + return this.makeUnsupportedRelationshipError(modelName, key, 400); + } + + if (relationInfo.isCollection) { + upsertPayload.create[key] = { + connect: enumerate(data.data).map((item: any) => + this.makeIdConnect(relationInfo.idFields, item.id), + ), + }; + upsertPayload.update[key] = { + set: enumerate(data.data).map((item: any) => + this.makeIdConnect(relationInfo.idFields, item.id), + ), + }; + } else { + if (typeof data.data !== 'object') { + return this.makeError('invalidRelationData'); + } + upsertPayload.create[key] = { + connect: this.makeIdConnect(relationInfo.idFields, data.data.id), + }; + upsertPayload.update[key] = { + connect: this.makeIdConnect(relationInfo.idFields, data.data.id), + }; + } + } + } + + // include IDs of relation fields so that they can be serialized. + this.includeRelationshipIds(modelName, upsertPayload, 'include'); + + const entity = await (client as any)[modelName].upsert(upsertPayload); + + return { + status: 201, + body: await this.serializeItems(modelName, entity), + }; + } + + private getUniqueFieldSets(type: string) { + const modelDef = this.requireModel(type); + return Object.entries(modelDef.uniqueFields).map( + ([k, v]) => + typeof v.type === 'string' + ? [k] // single unique field + : Object.keys(v), // compound unique fields + ); + } + + private async processRelationshipCRUD( + client: ClientContract, + mode: 'create' | 'update' | 'delete', + type: string, + resourceId: string, + relationship: string, + _query: Record | undefined, + requestBody: unknown, + ): Promise { + const typeInfo = this.getModelInfo(type); + if (!typeInfo) { + return this.makeUnsupportedModelError(type); + } + + const relationInfo = typeInfo.relationships[relationship]; + if (!relationInfo) { + return this.makeUnsupportedRelationshipError(type, relationship, 404); + } + + if (!relationInfo.isCollection && mode !== 'update') { + // to-one relation can only be updated + return this.makeError('invalidVerb'); + } + + const updateArgs: any = { + where: this.makeIdFilter(typeInfo.idFields, resourceId), + select: { + ...typeInfo.idFields.reduce((acc, field) => ({ ...acc, [field.name]: true }), {}), + [relationship]: { select: this.makeIdSelect(relationInfo.idFields) }, + }, + }; + + if (!relationInfo.isCollection) { + // zod-parse payload + const parsed = this.updateSingleRelationSchema.safeParse(requestBody); + if (!parsed.success) { + return this.makeError('invalidPayload', getZodErrorMessage(parsed.error)); + } + + if (parsed.data.data === null) { + if (!relationInfo.isOptional) { + // cannot disconnect a required relation + return this.makeError('invalidPayload'); + } + // set null -> disconnect + updateArgs.data = { + [relationship]: { + disconnect: true, + }, + }; + } else { + updateArgs.data = { + [relationship]: { + connect: this.makeIdConnect(relationInfo.idFields, parsed.data.data.id), + }, + }; + } + } else { + // zod-parse payload + const parsed = this.updateCollectionRelationSchema.safeParse(requestBody); + if (!parsed.success) { + return this.makeError('invalidPayload', getZodErrorMessage(parsed.error)); + } + + // create -> connect, delete -> disconnect, update -> set + const relationVerb = mode === 'create' ? 'connect' : mode === 'delete' ? 'disconnect' : 'set'; + + updateArgs.data = { + [relationship]: { + [relationVerb]: enumerate(parsed.data.data).map((item: any) => + this.makeIdFilter(relationInfo.idFields, item.id), + ), + }, + }; + } + + const entity: any = await (client as any)[type].update(updateArgs); + + const mappedType = this.mapModelName(type); + + const serialized: any = await this.serializeItems(relationInfo.type, entity[relationship], { + linkers: { + document: new tsjapi.Linker(() => + this.makeLinkUrl(`/${mappedType}/${resourceId}/relationships/${relationship}`), + ), + }, + onlyIdentifier: true, + }); + + return { + status: 200, + body: serialized, + }; + } + + private async processUpdate( + client: ClientContract, + type: any, + resourceId: string, + _query: Record | undefined, + requestBody: unknown, + ): Promise { + const typeInfo = this.getModelInfo(type); + if (!typeInfo) { + return this.makeUnsupportedModelError(type); + } + + const { attributes, relationships, error } = this.processRequestBody(requestBody); + if (error) { + return error; + } + + const updatePayload: any = { + where: this.makeIdFilter(typeInfo.idFields, resourceId), + data: { ...attributes }, + }; + + // turn relationships into query payload + if (relationships) { + for (const [key, data] of Object.entries(relationships)) { + if (!data?.data) { + return this.makeError('invalidRelationData'); + } + + const relationInfo = typeInfo.relationships[key]; + if (!relationInfo) { + return this.makeUnsupportedRelationshipError(type, key, 400); + } + + if (relationInfo.isCollection) { + updatePayload.data[key] = { + set: enumerate(data.data).map((item: any) => ({ + [this.makeDefaultIdKey(relationInfo.idFields)]: item.id, + })), + }; + } else { + if (typeof data.data !== 'object') { + return this.makeError('invalidRelationData'); + } + updatePayload.data[key] = { + connect: { + [this.makeDefaultIdKey(relationInfo.idFields)]: data.data.id, + }, + }; + } + updatePayload.include = { + ...updatePayload.include, + [key]: { select: { [this.makeDefaultIdKey(relationInfo.idFields)]: true } }, + }; + } + } + + // include IDs of relation fields so that they can be serialized. + this.includeRelationshipIds(type, updatePayload, 'include'); + + const entity = await (client as any)[type].update(updatePayload); + return { + status: 200, + body: await this.serializeItems(type, entity), + }; + } + + private async processDelete(client: ClientContract, type: any, resourceId: string): Promise { + const typeInfo = this.getModelInfo(type); + if (!typeInfo) { + return this.makeUnsupportedModelError(type); + } + + await (client as any)[type].delete({ + where: this.makeIdFilter(typeInfo.idFields, resourceId), + }); + return { + status: 200, + body: { meta: {} }, + }; + } + + //#region utilities + + private requireModel(model: string): ModelDef { + const modelDef = this.schema.models[model]; + if (!modelDef) { + throw new Error(`Model ${model} is not defined in the schema`); + } + return modelDef; + } + + private getIdFields(model: string): FieldDef[] { + const modelDef = this.requireModel(model); + const modelLower = lowerCaseFirst(model); + if (!(modelLower in this.externalIdMapping)) { + return Object.values(modelDef.fields).filter((f) => modelDef.idFields.includes(f.name)); + } + + // map external ID name to unique constraint field + const externalIdName = this.externalIdMapping[modelLower]; + for (const [name, info] of Object.entries(modelDef.uniqueFields)) { + if (name === externalIdName) { + if (typeof info.type === 'string') { + // single unique field + return [this.requireField(model, name)]; + } else { + // compound unique fields + return Object.keys(info).map((f) => this.requireField(model, f)); + } + } + } + + throw new Error(`Model ${model} does not have unique key ${externalIdName}`); + } + + private requireField(model: string, field: string): FieldDef { + const modelDef = this.requireModel(model); + const fieldDef = modelDef.fields[field]; + if (!fieldDef) { + throw new Error(`Field ${field} is not defined in model ${model}`); + } + return fieldDef; + } + + private buildTypeMap() { + this.typeMap = {}; + for (const [model, { fields }] of Object.entries(this.schema.models)) { + const idFields = this.getIdFields(model); + if (idFields.length === 0) { + log(this.options.log, 'warn', `Not including model ${model} in the API because it has no ID field`); + continue; + } + + const modelInfo: ModelInfo = (this.typeMap[lowerCaseFirst(model)] = { + name: model, + idFields, + relationships: {}, + fields, + }); + + for (const [field, fieldInfo] of Object.entries(fields)) { + if (!fieldInfo.relation) { + continue; + } + const fieldTypeIdFields = this.getIdFields(fieldInfo.type); + if (fieldTypeIdFields.length === 0) { + log( + this.options.log, + 'warn', + `Not including relation ${model}.${field} in the API because it has no ID field`, + ); + continue; + } + + modelInfo.relationships[field] = { + type: fieldInfo.type, + idFields: fieldTypeIdFields, + isCollection: !!fieldInfo.array, + isOptional: !!fieldInfo.optional, + }; + } + } + } + + private getModelInfo(model: string): ModelInfo | undefined { + return this.typeMap[lowerCaseFirst(model)]; + } + + private makeLinkUrl(path: string) { + return `${this.options.endpoint}${path}`; + } + + private buildSerializers() { + const linkers: Record> = {}; + + for (const model of Object.keys(this.schema.models)) { + const ids = this.getIdFields(model); + const modelLower = lowerCaseFirst(model); + const mappedModel = this.mapModelName(modelLower); + + if (ids.length < 1) { + continue; + } + + const linker = new tsjapi.Linker((items) => + Array.isArray(items) + ? this.makeLinkUrl(`/${mappedModel}`) + : this.makeLinkUrl(`/${mappedModel}/${this.getId(model, items)}`), + ); + linkers[modelLower] = linker; + + let projection: Record | null = {}; + const modelDef = this.requireModel(model); + for (const [field, fieldDef] of Object.entries(modelDef.fields)) { + if (fieldDef.relation) { + projection[field] = 0; + } + } + if (Object.keys(projection).length === 0) { + projection = null; + } + + const serializer = new tsjapi.Serializer(model, { + version: '1.1', + idKey: this.makeIdKey(ids), + linkers: { + resource: linker, + document: linker, + }, + projection, + }); + this.serializers.set(modelLower, serializer); + } + + // set relators + for (const model of Object.keys(this.schema.models)) { + const modelLower = lowerCaseFirst(model); + const serializer = this.serializers.get(modelLower); + if (!serializer) { + continue; + } + + const relators: Record> = {}; + const modelDef = this.requireModel(model); + for (const [field, fieldDef] of Object.entries(modelDef.fields)) { + if (!fieldDef.relation) { + continue; + } + const fieldSerializer = this.serializers.get(lowerCaseFirst(fieldDef.type)); + if (!fieldSerializer) { + continue; + } + const fieldIds = this.getIdFields(fieldDef.type); + if (fieldIds.length > 0) { + const mappedModel = this.mapModelName(modelLower); + + const relator = new tsjapi.Relator( + async (data) => { + return (data as any)[field]; + }, + fieldSerializer, + { + relatedName: field, + linkers: { + related: new tsjapi.Linker((primary) => + this.makeLinkUrl(`/${mappedModel}/${this.getId(model, primary)}/${field}`), + ), + relationship: new tsjapi.Linker((primary) => + this.makeLinkUrl( + `/${mappedModel}/${this.getId(model, primary)}/relationships/${field}`, + ), + ), + }, + }, + ); + relators[field] = relator; + } + } + serializer.setRelators(relators); + } + } + + private getId(model: string, data: any) { + if (!data) { + return undefined; + } + const ids = this.getIdFields(model); + if (ids.length === 0) { + return undefined; + } else { + return data[this.makeIdKey(ids)]; + } + } + + private async serializeItems(model: string, items: unknown, options?: Partial>) { + model = lowerCaseFirst(model); + const serializer = this.serializers.get(model); + if (!serializer) { + throw new Error(`serializer not found for model ${model}`); + } + + const itemsWithId = clone(items); + this.injectCompoundId(model, itemsWithId); + + // serialize to JSON:API structure + const serialized = await serializer.serialize(itemsWithId, options); + + // convert the serialization result to plain object otherwise SuperJSON won't work + const plainResult = this.toPlainObject(serialized); + + // superjson serialize the result + const { json, meta } = SuperJSON.serialize(plainResult); + + const result: any = json; + if (meta) { + result.meta = { ...result.meta, serialization: meta }; + } + + return result; + } + + private injectCompoundId(model: string, items: unknown) { + const typeInfo = this.getModelInfo(model); + if (!typeInfo) { + return; + } + + // recursively traverse the entity to create synthetic ID field for models with compound ID + enumerate(items).forEach((item: any) => { + if (!item) { + return; + } + + if (typeInfo.idFields.length > 1) { + item[this.makeIdKey(typeInfo.idFields)] = this.makeCompoundId(typeInfo.idFields, item); + } + + for (const [key, value] of Object.entries(item)) { + if (typeInfo.relationships[key]) { + // field is a relationship, recurse + this.injectCompoundId(typeInfo.relationships[key].type, value); + } + } + }); + } + + private toPlainObject(data: any): any { + if (data === undefined || data === null) { + return data; + } + + if (Array.isArray(data)) { + return data.map((item: any) => this.toPlainObject(item)); + } + + if (typeof data === 'object') { + if (typeof data.toJSON === 'function') { + // custom toJSON function + return data.toJSON(); + } + const result: any = {}; + for (const [field, value] of Object.entries(data)) { + if (value === undefined || typeof value === 'function') { + // trim undefined and functions + continue; + } else if (field === 'attributes') { + // don't visit into entity data + result[field] = value; + } else { + result[field] = this.toPlainObject(value); + } + } + return result; + } + + return data; + } + + private replaceURLSearchParams(url: string, params: Record) { + const r = new URL(url); + for (const [key, value] of Object.entries(params)) { + r.searchParams.set(key, value.toString()); + } + return r.toString(); + } + + private makeIdFilter(idFields: FieldDef[], resourceId: string, nested: boolean = true) { + const decodedId = decodeURIComponent(resourceId); + if (idFields.length === 1) { + return { [idFields[0]!.name]: this.coerce(idFields[0]!, decodedId) }; + } else if (nested) { + return { + // TODO: support `@@id` with custom name + [idFields.map((idf) => idf.name).join(DEFAULT_ID_DIVIDER)]: idFields.reduce( + (acc, curr, idx) => ({ + ...acc, + [curr.name]: this.coerce(curr, decodedId.split(this.idDivider)[idx]), + }), + {}, + ), + }; + } else { + return idFields.reduce( + (acc, curr, idx) => ({ + ...acc, + [curr.name]: this.coerce(curr, decodedId.split(this.idDivider)[idx]), + }), + {}, + ); + } + } + + private makeIdSelect(idFields: FieldDef[]) { + if (idFields.length === 0) { + throw this.errors['noId']; + } + return idFields.reduce((acc, curr) => ({ ...acc, [curr.name]: true }), {}); + } + + private makeIdConnect(idFields: FieldDef[], id: string | number) { + if (idFields.length === 1) { + return { [idFields[0]!.name]: this.coerce(idFields[0]!, id) }; + } else { + return { + [this.makeDefaultIdKey(idFields)]: idFields.reduce( + (acc, curr, idx) => ({ + ...acc, + [curr.name]: this.coerce(curr, `${id}`.split(this.idDivider)[idx]), + }), + {}, + ), + }; + } + } + + private makeIdKey(idFields: FieldDef[]) { + return idFields.map((idf) => idf.name).join(this.idDivider); + } + + private makeDefaultIdKey(idFields: FieldDef[]) { + // TODO: support `@@id` with custom name + return idFields.map((idf) => idf.name).join(DEFAULT_ID_DIVIDER); + } + + private makeCompoundId(idFields: FieldDef[], item: any) { + return idFields.map((idf) => item[idf.name]).join(this.idDivider); + } + + private makeUpsertWhere(matchFields: any[], attributes: any, typeInfo: ModelInfo) { + const where = matchFields.reduce((acc: any, field: string) => { + acc[field] = attributes[field] ?? null; + return acc; + }, {}); + + if ( + typeInfo.idFields.length > 1 && + matchFields.some((mf) => typeInfo.idFields.map((idf) => idf.name).includes(mf)) + ) { + return { + [this.makeDefaultIdKey(typeInfo.idFields)]: where, + }; + } + + return where; + } + + private includeRelationshipIds(model: string, args: any, mode: 'select' | 'include') { + const typeInfo = this.getModelInfo(model); + if (!typeInfo) { + return; + } + for (const [relation, relationInfo] of Object.entries(typeInfo.relationships)) { + args[mode] = { ...args[mode], [relation]: { select: this.makeIdSelect(relationInfo.idFields) } }; + } + } + + private coerce(fieldDef: FieldDef, value: any) { + if (typeof value === 'string') { + if (fieldDef.attributes?.some((attr) => attr.name === '@json')) { + try { + return JSON.parse(value); + } catch { + throw new InvalidValueError(`invalid JSON value: ${value}`); + } + } + + const type = fieldDef.type; + if (type === 'Int') { + const parsed = parseInt(value); + if (isNaN(parsed)) { + throw new InvalidValueError(`invalid ${type} value: ${value}`); + } + return parsed; + } else if (type === 'BigInt') { + try { + return BigInt(value); + } catch { + throw new InvalidValueError(`invalid ${type} value: ${value}`); + } + } else if (type === 'Float') { + const parsed = parseFloat(value); + if (isNaN(parsed)) { + throw new InvalidValueError(`invalid ${type} value: ${value}`); + } + return parsed; + } else if (type === 'Decimal') { + try { + return new Decimal(value); + } catch { + throw new InvalidValueError(`invalid ${type} value: ${value}`); + } + } else if (type === 'Boolean') { + if (value === 'true') { + return true; + } else if (value === 'false') { + return false; + } else { + throw new InvalidValueError(`invalid ${type} value: ${value}`); + } + } + } + return value; + } + + private makeNormalizedUrl(path: string, query: Record | undefined) { + const url = new URL(this.makeLinkUrl(path)); + for (const [key, value] of Object.entries(query ?? {})) { + if ( + key.startsWith('filter[') || + key.startsWith('sort[') || + key === 'include' || + key.startsWith('include[') || + key.startsWith('fields[') + ) { + for (const v of enumerate(value)) { + url.searchParams.append(key, v); + } + } + } + return url.toString(); + } + + private getPagination(query: Record | undefined) { + if (!query) { + return { offset: 0, limit: this.options.pageSize ?? DEFAULT_PAGE_SIZE }; + } + + let offset = 0; + if (query['page[offset]']) { + const value = query['page[offset]']; + const offsetText = Array.isArray(value) ? value[value.length - 1]! : value; + offset = parseInt(offsetText); + if (isNaN(offset) || offset < 0) { + offset = 0; + } + } + + let pageSizeOption = this.options.pageSize ?? DEFAULT_PAGE_SIZE; + if (pageSizeOption <= 0) { + pageSizeOption = DEFAULT_PAGE_SIZE; + } + + let limit = pageSizeOption; + if (query['page[limit]']) { + const value = query['page[limit]']; + const limitText = Array.isArray(value) ? value[value.length - 1]! : value; + limit = parseInt(limitText); + if (isNaN(limit) || limit <= 0) { + limit = pageSizeOption; + } + limit = Math.min(pageSizeOption, limit); + } + + return { offset, limit }; + } + + private buildFilter( + type: string, + query: Record | undefined, + ): { filter: any; error: any } { + if (!query) { + return { filter: undefined, error: undefined }; + } + + const typeInfo = this.getModelInfo(type); + if (!typeInfo) { + return { filter: undefined, error: this.makeUnsupportedModelError(type) }; + } + + const items: any[] = []; + + for (const [key, value] of Object.entries(query)) { + if (!value) { + continue; + } + + // try matching query parameter key as "filter[x][y]..." + const match = key.match(this.filterParamPattern); + if (!match || !match.groups || !match.groups['match']) { + continue; + } + + const filterKeys = match.groups['match'] + .replaceAll(/[[\]]/g, ' ') + .split(' ') + .filter((i) => i); + + if (!filterKeys.length) { + continue; + } + + // turn filter into a nested query object + + const item: any = {}; + let curr = item; + let currType = typeInfo; + + for (const filterValue of enumerate(value)) { + for (let i = 0; i < filterKeys.length; i++) { + // extract filter operation from (optional) trailing $op + let filterKey = filterKeys[i]!; + let filterOp: FilterOperationType | undefined; + const pos = filterKey.indexOf('$'); + if (pos > 0) { + filterOp = filterKey.substring(pos + 1) as FilterOperationType; + filterKey = filterKey.substring(0, pos); + } + + if (!!filterOp && !FilterOperations.includes(filterOp)) { + return { + filter: undefined, + error: this.makeError('invalidFilter', `invalid filter operation: ${filterOp}`), + }; + } + + const idFields = this.getIdFields(currType.name); + const fieldDef = + filterKey === 'id' + ? Object.values(currType.fields).find((f) => idFields.some((idf) => idf.name === f.name)) + : currType.fields[filterKey]; + if (!fieldDef) { + return { filter: undefined, error: this.makeError('invalidFilter') }; + } + + if (!fieldDef.relation) { + // regular field + if (i !== filterKeys.length - 1) { + // must be the last segment of a filter + return { filter: undefined, error: this.makeError('invalidFilter') }; + } + curr[fieldDef.name] = this.makeFilterValue(fieldDef, filterValue, filterOp); + } else { + // relation field + if (i === filterKeys.length - 1) { + curr[fieldDef.name] = this.makeFilterValue(fieldDef, filterValue, filterOp); + } else { + // keep going + if (fieldDef.array) { + // collection filtering implies "some" operation + curr[fieldDef.name] = { some: {} }; + curr = curr[fieldDef.name].some; + } else { + curr = curr[fieldDef.name] = {}; + } + currType = this.getModelInfo(fieldDef.type)!; + } + } + } + items.push(item); + } + } + + if (items.length === 0) { + return { filter: undefined, error: undefined }; + } else { + // combine filters with AND + return { filter: items.length === 1 ? items[0] : { AND: items }, error: undefined }; + } + } + + private buildSort(type: string, query: Record | undefined) { + if (!query?.['sort']) { + return { sort: undefined, error: undefined }; + } + + const typeInfo = this.getModelInfo(type); + if (!typeInfo) { + return { sort: undefined, error: this.makeUnsupportedModelError(type) }; + } + + const result: any[] = []; + + for (const sortSpec of enumerate(query['sort'])) { + const sortFields = sortSpec.split(',').filter((i) => i); + + for (const sortField of sortFields) { + const dir = sortField.startsWith('-') ? 'desc' : 'asc'; + const cleanedSortField = sortField.startsWith('-') ? sortField.substring(1) : sortField; + const parts = cleanedSortField.split('.').filter((i) => i); + + const sortItem: any = {}; + let curr = sortItem; + let currType = typeInfo; + + for (let i = 0; i < parts.length; i++) { + const part = parts[i]!; + + const fieldInfo = currType.fields[part]; + if (!fieldInfo || fieldInfo.array) { + return { + sort: undefined, + error: this.makeError('invalidSort', 'sorting by array field is not supported'), + }; + } + + if (i === parts.length - 1) { + if (fieldInfo.relation) { + // relation field: sort by id + const relationType = this.getModelInfo(fieldInfo.type); + if (!relationType) { + return { sort: undefined, error: this.makeUnsupportedModelError(fieldInfo.type) }; + } + curr[fieldInfo.name] = relationType.idFields.reduce((acc: any, idField: FieldDef) => { + acc[idField.name] = dir; + return acc; + }, {}); + } else { + // regular field + curr[fieldInfo.name] = dir; + } + } else { + if (!fieldInfo.relation) { + // must be a relation field + return { + sort: undefined, + error: this.makeError( + 'invalidSort', + 'intermediate sort segments must be relationships', + ), + }; + } + // keep going + curr = curr[fieldInfo.name] = {}; + currType = this.getModelInfo(fieldInfo.type)!; + if (!currType) { + return { sort: undefined, error: this.makeUnsupportedModelError(fieldInfo.type) }; + } + } + } + + result.push(sortItem); + } + } + + return { sort: result, error: undefined }; + } + + private buildRelationSelect( + type: string, + include: string | string[], + query: Record | undefined, + ) { + const typeInfo = this.getModelInfo(type); + if (!typeInfo) { + return { select: undefined, error: this.makeUnsupportedModelError(type) }; + } + + const result: any = {}; + const allIncludes: string[] = []; + + for (const includeItem of enumerate(include)) { + const inclusions = includeItem.split(',').filter((i) => i); + for (const inclusion of inclusions) { + allIncludes.push(inclusion); + + const parts = inclusion.split('.'); + let currPayload = result; + let currType = typeInfo; + + for (let i = 0; i < parts.length; i++) { + const relation = parts[i]!; + const relationInfo = currType.relationships[relation]; + if (!relationInfo) { + return { select: undefined, error: this.makeUnsupportedRelationshipError(type, relation, 400) }; + } + + currType = this.getModelInfo(relationInfo.type)!; + if (!currType) { + return { select: undefined, error: this.makeUnsupportedModelError(relationInfo.type) }; + } + + // handle partial results for requested type + const { select, error } = this.buildPartialSelect(lowerCaseFirst(relationInfo.type), query); + if (error) return { select: undefined, error }; + + if (i !== parts.length - 1) { + if (select) { + currPayload[relation] = { select: { ...select } }; + currPayload = currPayload[relation].select; + } else { + currPayload[relation] = { include: { ...currPayload[relation]?.include } }; + currPayload = currPayload[relation].include; + } + } else { + currPayload[relation] = select + ? { + select: { ...select }, + } + : true; + } + } + } + } + + return { select: result, error: undefined, allIncludes }; + } + + private makeFilterValue(fieldDef: FieldDef, value: string, op: FilterOperationType): any { + // TODO: inequality filters? + if (fieldDef.relation) { + // relation filter is converted to an ID filter + const info = this.getModelInfo(fieldDef.type)!; + if (fieldDef.array) { + // filtering a to-many relation, imply 'some' operator + const values = value.split(',').filter((i) => i); + const filterValue = + values.length > 1 + ? { OR: values.map((v) => this.makeIdFilter(info.idFields, v, false)) } + : this.makeIdFilter(info.idFields, value, false); + return { some: filterValue }; + } else { + const values = value.split(',').filter((i) => i); + if (values.length > 1) { + return { OR: values.map((v) => this.makeIdFilter(info.idFields, v, false)) }; + } else { + return { is: this.makeIdFilter(info.idFields, value, false) }; + } + } + } else { + if (op === 'between') { + const parts = value.split(',').map((v) => this.coerce(fieldDef, v)); + if (parts.length !== 2) { + throw new InvalidValueError(`"between" expects exactly 2 comma-separated values`); + } + return { between: [parts[0]!, parts[1]!] }; + } + const coerced = this.coerce(fieldDef, value); + switch (op) { + case 'icontains': + return { contains: coerced, mode: 'insensitive' }; + case 'hasSome': + case 'hasEvery': { + const values = value + .split(',') + .filter((i) => i) + .map((v) => this.coerce(fieldDef, v)); + return { [op]: values }; + } + case 'isEmpty': + if (value !== 'true' && value !== 'false') { + throw new InvalidValueError(`Not a boolean: ${value}`); + } + return { isEmpty: value === 'true' ? true : false }; + default: + if (op === undefined) { + if (fieldDef.attributes?.some((attr) => attr.name === '@json')) { + // handle JSON value equality filter + return { equals: coerced }; + } + + // regular filter, split value by comma + const values = value + .split(',') + .filter((i) => i) + .map((v) => this.coerce(fieldDef, v)); + return values.length > 1 ? { in: values } : { equals: values[0] }; + } else { + return { [op]: coerced }; + } + } + } + } + + private injectRelationQuery( + type: string, + injectTarget: any, + injectKey: string, + query: Record | undefined, + ) { + const { filter, error: filterError } = this.buildFilter(type, query); + if (filterError) { + return filterError; + } + + if (filter) { + injectTarget[injectKey] = { ...injectTarget[injectKey], where: filter }; + } + + const { sort, error: sortError } = this.buildSort(type, query); + if (sortError) { + return sortError; + } + if (sort) { + injectTarget[injectKey] = { ...injectTarget[injectKey], orderBy: sort }; + } + + const pagination = this.getPagination(query); + const offset = pagination.offset; + if (offset > 0) { + // inject skip + injectTarget[injectKey] = { ...injectTarget[injectKey], skip: offset }; + } + const limit = pagination.limit; + if (limit !== Infinity) { + // inject take + injectTarget[injectKey] = { ...injectTarget[injectKey], take: limit }; + + // include a count query for the relationship + injectTarget._count = { select: { [injectKey]: true } }; + } + } + + private handleORMError(err: ORMError) { + return match(err.reason) + .with(ORMErrorReason.INVALID_INPUT, () => { + return this.makeError('validationError', err.message, 422); + }) + .with(ORMErrorReason.REJECTED_BY_POLICY, () => { + return this.makeError('forbidden', err.message, 403, { reason: err.rejectedByPolicyReason }); + }) + .with(ORMErrorReason.NOT_FOUND, () => { + return this.makeError('notFound', err.message, 404); + }) + .with(ORMErrorReason.DB_QUERY_ERROR, () => { + return this.makeError('queryError', err.message, 400, { + dbErrorCode: err.dbErrorCode, + }); + }) + .otherwise(() => { + return this.makeError('unknownError', err.message); + }); + } + + private makeError( + code: keyof typeof this.errors, + detail?: string, + status?: number, + otherFields: Record = {}, + ) { + status = status ?? this.errors[code]?.status ?? 500; + const error: any = { + status, + code: paramCase(code), + title: this.errors[code]?.title, + }; + + if (detail) { + error.detail = detail; + } + + Object.assign(error, otherFields); + + return { + status, + body: { + errors: [error], + }, + }; + } + + private makeUnsupportedModelError(model: string) { + return this.makeError('unsupportedModel', `Model ${model} doesn't exist`); + } + + private makeUnsupportedRelationshipError(model: string, relationship: string, status: number) { + return this.makeError('unsupportedRelationship', `Relationship ${model}.${relationship} doesn't exist`, status); + } + + //#endregion + + async generateSpec(options?: OpenApiSpecOptions) { + const generator = new RestApiSpecGenerator(this.options); + return generator.generateSpec(options); + } +} + export { RestApiSpecGenerator } from './openapi'; diff --git a/packages/server/src/api/rpc/handler.ts b/packages/server/src/api/rpc/handler.ts deleted file mode 100644 index 0da686f94..000000000 --- a/packages/server/src/api/rpc/handler.ts +++ /dev/null @@ -1,458 +0,0 @@ -import { lowerCaseFirst, safeJSONStringify } from '@zenstackhq/common-helpers'; -import { CoreCrudOperations, ORMError, ORMErrorReason, type ClientContract } from '@zenstackhq/orm'; -import type { SchemaDef } from '@zenstackhq/orm/schema'; -import SuperJSON from 'superjson'; -import { match } from 'ts-pattern'; -import z from 'zod'; -import { fromError } from 'zod-validation-error/v4'; -import type { ApiHandler, LogConfig, RequestContext, Response } from '../../types'; -import { getProcedureDef, mapProcedureArgs, PROCEDURE_ROUTE_PREFIXES } from '../common/procedures'; -import { loggerSchema } from '../common/schemas'; -import type { CommonHandlerOptions, OpenApiSpecGenerator } from '../common/types'; -import { processSuperJsonRequestPayload, unmarshalQ } from '../common/utils'; -import { log, registerCustomSerializers } from '../utils'; -import { RPCApiSpecGenerator } from './openapi'; - -const TRANSACTION_ROUTE_PREFIX = '$transaction' as const; -const VALID_OPS = new Set(CoreCrudOperations as unknown as string[]); - -registerCustomSerializers(); - -/** - * Options for {@link RPCApiHandler} - */ -export type RPCApiHandlerOptions = { - /** - * The schema - */ - schema: Schema; - - /** - * Logging configuration - */ - log?: LogConfig; -} & CommonHandlerOptions; - -/** - * RPC style API request handler that mirrors the ZenStackClient API - */ -export class RPCApiHandler implements ApiHandler, OpenApiSpecGenerator { - constructor(private readonly options: RPCApiHandlerOptions) { - this.validateOptions(options); - } - - private validateOptions(options: RPCApiHandlerOptions) { - const schema = z.strictObject({ - schema: z.object(), - log: loggerSchema.optional(), - queryOptions: z.object().optional(), - }); - const parseResult = schema.safeParse(options); - if (!parseResult.success) { - throw new Error(`Invalid options: ${fromError(parseResult.error)}`); - } - } - - get schema(): Schema { - return this.options.schema; - } - - get log(): LogConfig | undefined { - return this.options.log; - } - - async handleRequest({ client, method, path, query, requestBody }: RequestContext): Promise { - const parts = path.split('/').filter((p) => !!p); - const op = parts.pop(); - let model = parts.pop(); - - if (parts.length !== 0 || !op || !model) { - return this.makeBadInputErrorResponse('invalid request path'); - } - - if (model === PROCEDURE_ROUTE_PREFIXES) { - return this.handleProcedureRequest({ - client, - method: method.toUpperCase(), - proc: op, - query, - requestBody, - }); - } - - if (model === TRANSACTION_ROUTE_PREFIX) { - return this.handleTransaction({ - client, - method: method.toUpperCase(), - type: op, - requestBody, - }); - } - - model = lowerCaseFirst(model); - method = method.toUpperCase(); - let args: unknown; - let resCode = 200; - - switch (op) { - case 'create': - case 'createMany': - case 'createManyAndReturn': - case 'upsert': - if (method !== 'POST') { - return this.makeBadInputErrorResponse('invalid request method, only POST is supported'); - } - if (!requestBody) { - return this.makeBadInputErrorResponse('missing request body'); - } - - args = requestBody; - resCode = 201; - break; - - case 'findFirst': - case 'findUnique': - case 'findMany': - case 'aggregate': - case 'groupBy': - case 'count': - case 'exists': - if (method !== 'GET') { - return this.makeBadInputErrorResponse('invalid request method, only GET is supported'); - } - try { - args = query?.['q'] ? unmarshalQ(query['q'] as string, query['meta'] as string | undefined) : {}; - } catch { - return this.makeBadInputErrorResponse('invalid "q" query parameter'); - } - break; - - case 'update': - case 'updateMany': - case 'updateManyAndReturn': - if (method !== 'PUT' && method !== 'PATCH') { - return this.makeBadInputErrorResponse('invalid request method, only PUT or PATCH are supported'); - } - if (!requestBody) { - return this.makeBadInputErrorResponse('missing request body'); - } - - args = requestBody; - break; - - case 'delete': - case 'deleteMany': - if (method !== 'DELETE') { - return this.makeBadInputErrorResponse('invalid request method, only DELETE is supported'); - } - try { - args = query?.['q'] ? unmarshalQ(query['q'] as string, query['meta'] as string | undefined) : {}; - } catch (err) { - return this.makeBadInputErrorResponse( - err instanceof Error ? err.message : 'invalid "q" query parameter', - ); - } - break; - - default: - return this.makeBadInputErrorResponse('invalid operation: ' + op); - } - - const { result: processedArgs, error } = await this.processRequestPayload(args); - if (error) { - return this.makeBadInputErrorResponse(error); - } - - try { - if (!this.isValidModel(client, model)) { - return this.makeBadInputErrorResponse(`unknown model name: ${model}`); - } - - log( - this.options.log, - 'debug', - () => `handling "${model}.${op}" request with args: ${safeJSONStringify(processedArgs)}`, - ); - - const clientResult = await (client as any)[model][op](processedArgs); - let responseBody: any = { data: clientResult }; - - // superjson serialize response - if (clientResult) { - const { json, meta } = SuperJSON.serialize(clientResult); - responseBody = { data: json }; - if (meta) { - responseBody.meta = { serialization: meta }; - } - } - - const response = { status: resCode, body: responseBody }; - log( - this.options.log, - 'debug', - () => `sending response for "${model}.${op}" request: ${safeJSONStringify(response)}`, - ); - return response; - } catch (err) { - log(this.options.log, 'error', `error occurred when handling "${model}.${op}" request`, err); - if (err instanceof ORMError) { - return this.makeORMErrorResponse(err); - } else { - return this.makeGenericErrorResponse(err); - } - } - } - - private async handleTransaction({ - client, - method, - type, - requestBody, - }: { - client: ClientContract; - method: string; - type: string; - requestBody?: unknown; - }): Promise { - if (method !== 'POST') { - return this.makeBadInputErrorResponse('invalid request method, only POST is supported'); - } - - if (type !== 'sequential') { - return this.makeBadInputErrorResponse(`unsupported transaction type: ${type}`); - } - - if (!requestBody || !Array.isArray(requestBody) || requestBody.length === 0) { - return this.makeBadInputErrorResponse('request body must be a non-empty array of operations'); - } - - const processedOps: Array<{ model: string; op: string; args: unknown }> = []; - - for (let i = 0; i < requestBody.length; i++) { - const item = requestBody[i]; - if (!item || typeof item !== 'object') { - return this.makeBadInputErrorResponse(`operation at index ${i} must be an object`); - } - const { model: itemModel, op: itemOp, args: itemArgs } = item as any; - if (!itemModel || typeof itemModel !== 'string') { - return this.makeBadInputErrorResponse(`operation at index ${i} is missing a valid "model" field`); - } - if (!itemOp || typeof itemOp !== 'string') { - return this.makeBadInputErrorResponse(`operation at index ${i} is missing a valid "op" field`); - } - if (!VALID_OPS.has(itemOp)) { - return this.makeBadInputErrorResponse(`operation at index ${i} has invalid op: ${itemOp}`); - } - if (!this.isValidModel(client, lowerCaseFirst(itemModel))) { - return this.makeBadInputErrorResponse(`operation at index ${i} has unknown model: ${itemModel}`); - } - if ( - itemArgs !== undefined && - itemArgs !== null && - (typeof itemArgs !== 'object' || Array.isArray(itemArgs)) - ) { - return this.makeBadInputErrorResponse(`operation at index ${i} has invalid "args" field`); - } - - const { result: processedArgs, error: argsError } = await this.processRequestPayload(itemArgs ?? {}); - if (argsError) { - return this.makeBadInputErrorResponse(`operation at index ${i}: ${argsError}`); - } - processedOps.push({ model: lowerCaseFirst(itemModel), op: itemOp, args: processedArgs }); - } - - try { - const promises = processedOps.map(({ model, op, args }) => { - return (client as any)[model][op](args); - }); - - log(this.options.log, 'debug', () => `handling "$transaction" request with ${promises.length} operations`); - - const clientResult = await client.$transaction(promises as any); - - const { json, meta } = SuperJSON.serialize(clientResult); - const responseBody: any = { data: json }; - if (meta) { - responseBody.meta = { serialization: meta }; - } - - const response = { status: 200, body: responseBody }; - log( - this.options.log, - 'debug', - () => `sending response for "$transaction" request: ${safeJSONStringify(response)}`, - ); - return response; - } catch (err) { - log(this.options.log, 'error', `error occurred when handling "$transaction" request`, err); - if (err instanceof ORMError) { - return this.makeORMErrorResponse(err); - } - return this.makeGenericErrorResponse(err); - } - } - - private async handleProcedureRequest({ - client, - method, - proc, - query, - requestBody, - }: { - client: ClientContract; - method: string; - proc?: string; - query?: Record; - requestBody?: unknown; - }): Promise { - if (!proc) { - return this.makeBadInputErrorResponse('missing procedure name'); - } - - const procDef = getProcedureDef(this.options.schema, proc); - if (!procDef) { - return this.makeBadInputErrorResponse(`unknown procedure: ${proc}`); - } - - const isMutation = !!procDef.mutation; - - if (isMutation) { - if (method !== 'POST') { - return this.makeBadInputErrorResponse('invalid request method, only POST is supported'); - } - } else { - if (method !== 'GET') { - return this.makeBadInputErrorResponse('invalid request method, only GET is supported'); - } - } - - let argsPayload = method === 'POST' ? requestBody : undefined; - if (method === 'GET') { - try { - argsPayload = query?.['q'] - ? unmarshalQ(query['q'] as string, query['meta'] as string | undefined) - : undefined; - } catch (err) { - return this.makeBadInputErrorResponse( - err instanceof Error ? err.message : 'invalid "q" query parameter', - ); - } - } - - const { result: processedArgsPayload, error } = await processSuperJsonRequestPayload(argsPayload); - if (error) { - return this.makeBadInputErrorResponse(error); - } - - let procInput: unknown; - try { - procInput = mapProcedureArgs(procDef, processedArgsPayload); - } catch (err) { - return this.makeBadInputErrorResponse(err instanceof Error ? err.message : 'invalid procedure arguments'); - } - - try { - log(this.options.log, 'debug', () => `handling "$procs.${proc}" request`); - - const clientResult = await (client as any).$procs?.[proc](procInput); - - const { json, meta } = SuperJSON.serialize(clientResult); - const responseBody: any = { data: json }; - if (meta) { - responseBody.meta = { serialization: meta }; - } - - const response = { status: 200, body: responseBody }; - log( - this.options.log, - 'debug', - () => `sending response for "$procs.${proc}" request: ${safeJSONStringify(response)}`, - ); - return response; - } catch (err) { - log(this.options.log, 'error', `error occurred when handling "$procs.${proc}" request`, err); - if (err instanceof ORMError) { - return this.makeORMErrorResponse(err); - } - return this.makeGenericErrorResponse(err); - } - } - - private isValidModel(client: ClientContract, model: string) { - return Object.keys(client.$schema.models).some((m) => lowerCaseFirst(m) === lowerCaseFirst(model)); - } - - private makeBadInputErrorResponse(message: string) { - const resp = { - status: 400, - body: { error: { message } }, - }; - log(this.options.log, 'debug', () => `sending error response: ${safeJSONStringify(resp)}`); - return resp; - } - - private makeGenericErrorResponse(err: unknown) { - const resp = { - status: 500, - body: { error: { message: err instanceof Error ? err.message : 'unknown error' } }, - }; - log( - this.options.log, - 'debug', - () => `sending error response: ${safeJSONStringify(resp)}${err instanceof Error ? '\n' + err.stack : ''}`, - ); - return resp; - } - - private makeORMErrorResponse(err: ORMError) { - let status = 400; - const error: any = { message: err.message, reason: err.reason }; - - match(err.reason) - .with(ORMErrorReason.NOT_FOUND, () => { - status = 404; - error.model = err.model; - }) - .with(ORMErrorReason.INVALID_INPUT, () => { - status = 422; - error.rejectedByValidation = true; - error.model = err.model; - }) - .with(ORMErrorReason.REJECTED_BY_POLICY, () => { - status = 403; - error.rejectedByPolicy = true; - error.model = err.model; - error.rejectReason = err.rejectedByPolicyReason; - }) - .with(ORMErrorReason.DB_QUERY_ERROR, () => { - status = 400; - error.dbErrorCode = err.dbErrorCode; - }) - .otherwise(() => {}); - - const resp = { status, body: { error } }; - log(this.options.log, 'debug', () => `sending error response: ${safeJSONStringify(resp)}`); - return resp; - } - - private async processRequestPayload(args: any) { - const { meta, ...rest } = args ?? {}; - if (meta?.serialization) { - try { - // superjson deserialization - args = SuperJSON.deserialize({ json: rest, meta: meta.serialization }); - } catch (err) { - return { result: undefined, error: `failed to deserialize request payload: ${(err as Error).message}` }; - } - } else { - // drop meta when no serialization info is present - args = rest; - } - return { result: args, error: undefined }; - } - - async generateSpec(options?: import('../common/types').OpenApiSpecOptions) { - const generator = new RPCApiSpecGenerator(this.options); - return generator.generateSpec(options); - } -} diff --git a/packages/server/src/api/rpc/index.ts b/packages/server/src/api/rpc/index.ts index 8d09235be..f5c09335c 100644 --- a/packages/server/src/api/rpc/index.ts +++ b/packages/server/src/api/rpc/index.ts @@ -1,2 +1,460 @@ -export { RPCApiHandler, type RPCApiHandlerOptions } from './handler'; +import { lowerCaseFirst, safeJSONStringify } from '@zenstackhq/common-helpers'; +import { CoreCrudOperations, ORMError, ORMErrorReason, type ClientContract } from '@zenstackhq/orm'; +import type { SchemaDef } from '@zenstackhq/orm/schema'; +import SuperJSON from 'superjson'; +import { match } from 'ts-pattern'; +import z from 'zod'; +import { fromError } from 'zod-validation-error/v4'; +import type { ApiHandler, LogConfig, RequestContext, Response } from '../../types'; +import { getProcedureDef, mapProcedureArgs, PROCEDURE_ROUTE_PREFIXES } from '../common/procedures'; +import { loggerSchema } from '../common/schemas'; +import type { CommonHandlerOptions, OpenApiSpecGenerator } from '../common/types'; +import { processSuperJsonRequestPayload, unmarshalQ } from '../common/utils'; +import { log, registerCustomSerializers } from '../utils'; +import { RPCApiSpecGenerator } from './openapi'; + +const TRANSACTION_ROUTE_PREFIX = '$transaction' as const; +const VALID_OPS = new Set(CoreCrudOperations as unknown as string[]); + +registerCustomSerializers(); + +/** + * Options for {@link RPCApiHandler} + */ +export type RPCApiHandlerOptions = { + /** + * The schema + */ + schema: Schema; + + /** + * Logging configuration + */ + log?: LogConfig; +} & CommonHandlerOptions; + +/** + * RPC style API request handler that mirrors the ZenStackClient API + */ +export class RPCApiHandler implements ApiHandler, OpenApiSpecGenerator { + constructor(private readonly options: RPCApiHandlerOptions) { + this.validateOptions(options); + } + + private validateOptions(options: RPCApiHandlerOptions) { + const schema = z.strictObject({ + schema: z.object(), + log: loggerSchema.optional(), + queryOptions: z.object().optional(), + }); + const parseResult = schema.safeParse(options); + if (!parseResult.success) { + throw new Error(`Invalid options: ${fromError(parseResult.error)}`); + } + } + + get schema(): Schema { + return this.options.schema; + } + + get log(): LogConfig | undefined { + return this.options.log; + } + + async handleRequest({ client, method, path, query, requestBody }: RequestContext): Promise { + const parts = path.split('/').filter((p) => !!p); + const op = parts.pop(); + let model = parts.pop(); + + if (parts.length !== 0 || !op || !model) { + return this.makeBadInputErrorResponse('invalid request path'); + } + + if (model === PROCEDURE_ROUTE_PREFIXES) { + return this.handleProcedureRequest({ + client, + method: method.toUpperCase(), + proc: op, + query, + requestBody, + }); + } + + if (model === TRANSACTION_ROUTE_PREFIX) { + return this.handleTransaction({ + client, + method: method.toUpperCase(), + type: op, + requestBody, + }); + } + + model = lowerCaseFirst(model); + method = method.toUpperCase(); + let args: unknown; + let resCode = 200; + + switch (op) { + case 'create': + case 'createMany': + case 'createManyAndReturn': + case 'upsert': + if (method !== 'POST') { + return this.makeBadInputErrorResponse('invalid request method, only POST is supported'); + } + if (!requestBody) { + return this.makeBadInputErrorResponse('missing request body'); + } + + args = requestBody; + resCode = 201; + break; + + case 'findFirst': + case 'findUnique': + case 'findMany': + case 'aggregate': + case 'groupBy': + case 'count': + case 'exists': + if (method !== 'GET') { + return this.makeBadInputErrorResponse('invalid request method, only GET is supported'); + } + try { + args = query?.['q'] ? unmarshalQ(query['q'] as string, query['meta'] as string | undefined) : {}; + } catch { + return this.makeBadInputErrorResponse('invalid "q" query parameter'); + } + break; + + case 'update': + case 'updateMany': + case 'updateManyAndReturn': + if (method !== 'PUT' && method !== 'PATCH') { + return this.makeBadInputErrorResponse('invalid request method, only PUT or PATCH are supported'); + } + if (!requestBody) { + return this.makeBadInputErrorResponse('missing request body'); + } + + args = requestBody; + break; + + case 'delete': + case 'deleteMany': + if (method !== 'DELETE') { + return this.makeBadInputErrorResponse('invalid request method, only DELETE is supported'); + } + try { + args = query?.['q'] ? unmarshalQ(query['q'] as string, query['meta'] as string | undefined) : {}; + } catch (err) { + return this.makeBadInputErrorResponse( + err instanceof Error ? err.message : 'invalid "q" query parameter', + ); + } + break; + + default: + return this.makeBadInputErrorResponse('invalid operation: ' + op); + } + + const { result: processedArgs, error } = await this.processRequestPayload(args); + if (error) { + return this.makeBadInputErrorResponse(error); + } + + try { + if (!this.isValidModel(client, model)) { + return this.makeBadInputErrorResponse(`unknown model name: ${model}`); + } + + log( + this.options.log, + 'debug', + () => `handling "${model}.${op}" request with args: ${safeJSONStringify(processedArgs)}`, + ); + + const clientResult = await (client as any)[model][op](processedArgs); + let responseBody: any = { data: clientResult }; + + // superjson serialize response + if (clientResult) { + const { json, meta } = SuperJSON.serialize(clientResult); + responseBody = { data: json }; + if (meta) { + responseBody.meta = { serialization: meta }; + } + } + + const response = { status: resCode, body: responseBody }; + log( + this.options.log, + 'debug', + () => `sending response for "${model}.${op}" request: ${safeJSONStringify(response)}`, + ); + return response; + } catch (err) { + log(this.options.log, 'error', `error occurred when handling "${model}.${op}" request`, err); + if (err instanceof ORMError) { + return this.makeORMErrorResponse(err); + } else { + return this.makeGenericErrorResponse(err); + } + } + } + + private async handleTransaction({ + client, + method, + type, + requestBody, + }: { + client: ClientContract; + method: string; + type: string; + requestBody?: unknown; + }): Promise { + if (method !== 'POST') { + return this.makeBadInputErrorResponse('invalid request method, only POST is supported'); + } + + if (type !== 'sequential') { + return this.makeBadInputErrorResponse(`unsupported transaction type: ${type}`); + } + + if (!requestBody || !Array.isArray(requestBody) || requestBody.length === 0) { + return this.makeBadInputErrorResponse('request body must be a non-empty array of operations'); + } + + const processedOps: Array<{ model: string; op: string; args: unknown }> = []; + + for (let i = 0; i < requestBody.length; i++) { + const item = requestBody[i]; + if (!item || typeof item !== 'object') { + return this.makeBadInputErrorResponse(`operation at index ${i} must be an object`); + } + const { model: itemModel, op: itemOp, args: itemArgs } = item as any; + if (!itemModel || typeof itemModel !== 'string') { + return this.makeBadInputErrorResponse(`operation at index ${i} is missing a valid "model" field`); + } + if (!itemOp || typeof itemOp !== 'string') { + return this.makeBadInputErrorResponse(`operation at index ${i} is missing a valid "op" field`); + } + if (!VALID_OPS.has(itemOp)) { + return this.makeBadInputErrorResponse(`operation at index ${i} has invalid op: ${itemOp}`); + } + if (!this.isValidModel(client, lowerCaseFirst(itemModel))) { + return this.makeBadInputErrorResponse(`operation at index ${i} has unknown model: ${itemModel}`); + } + if ( + itemArgs !== undefined && + itemArgs !== null && + (typeof itemArgs !== 'object' || Array.isArray(itemArgs)) + ) { + return this.makeBadInputErrorResponse(`operation at index ${i} has invalid "args" field`); + } + + const { result: processedArgs, error: argsError } = await this.processRequestPayload(itemArgs ?? {}); + if (argsError) { + return this.makeBadInputErrorResponse(`operation at index ${i}: ${argsError}`); + } + processedOps.push({ model: lowerCaseFirst(itemModel), op: itemOp, args: processedArgs }); + } + + try { + const promises = processedOps.map(({ model, op, args }) => { + return (client as any)[model][op](args); + }); + + log(this.options.log, 'debug', () => `handling "$transaction" request with ${promises.length} operations`); + + const clientResult = await client.$transaction(promises as any); + + const { json, meta } = SuperJSON.serialize(clientResult); + const responseBody: any = { data: json }; + if (meta) { + responseBody.meta = { serialization: meta }; + } + + const response = { status: 200, body: responseBody }; + log( + this.options.log, + 'debug', + () => `sending response for "$transaction" request: ${safeJSONStringify(response)}`, + ); + return response; + } catch (err) { + log(this.options.log, 'error', `error occurred when handling "$transaction" request`, err); + if (err instanceof ORMError) { + return this.makeORMErrorResponse(err); + } + return this.makeGenericErrorResponse(err); + } + } + + private async handleProcedureRequest({ + client, + method, + proc, + query, + requestBody, + }: { + client: ClientContract; + method: string; + proc?: string; + query?: Record; + requestBody?: unknown; + }): Promise { + if (!proc) { + return this.makeBadInputErrorResponse('missing procedure name'); + } + + const procDef = getProcedureDef(this.options.schema, proc); + if (!procDef) { + return this.makeBadInputErrorResponse(`unknown procedure: ${proc}`); + } + + const isMutation = !!procDef.mutation; + + if (isMutation) { + if (method !== 'POST') { + return this.makeBadInputErrorResponse('invalid request method, only POST is supported'); + } + } else { + if (method !== 'GET') { + return this.makeBadInputErrorResponse('invalid request method, only GET is supported'); + } + } + + let argsPayload = method === 'POST' ? requestBody : undefined; + if (method === 'GET') { + try { + argsPayload = query?.['q'] + ? unmarshalQ(query['q'] as string, query['meta'] as string | undefined) + : undefined; + } catch (err) { + return this.makeBadInputErrorResponse( + err instanceof Error ? err.message : 'invalid "q" query parameter', + ); + } + } + + const { result: processedArgsPayload, error } = await processSuperJsonRequestPayload(argsPayload); + if (error) { + return this.makeBadInputErrorResponse(error); + } + + let procInput: unknown; + try { + procInput = mapProcedureArgs(procDef, processedArgsPayload); + } catch (err) { + return this.makeBadInputErrorResponse(err instanceof Error ? err.message : 'invalid procedure arguments'); + } + + try { + log(this.options.log, 'debug', () => `handling "$procs.${proc}" request`); + + const clientResult = await (client as any).$procs?.[proc](procInput); + + const { json, meta } = SuperJSON.serialize(clientResult); + const responseBody: any = { data: json }; + if (meta) { + responseBody.meta = { serialization: meta }; + } + + const response = { status: 200, body: responseBody }; + log( + this.options.log, + 'debug', + () => `sending response for "$procs.${proc}" request: ${safeJSONStringify(response)}`, + ); + return response; + } catch (err) { + log(this.options.log, 'error', `error occurred when handling "$procs.${proc}" request`, err); + if (err instanceof ORMError) { + return this.makeORMErrorResponse(err); + } + return this.makeGenericErrorResponse(err); + } + } + + private isValidModel(client: ClientContract, model: string) { + return Object.keys(client.$schema.models).some((m) => lowerCaseFirst(m) === lowerCaseFirst(model)); + } + + private makeBadInputErrorResponse(message: string) { + const resp = { + status: 400, + body: { error: { message } }, + }; + log(this.options.log, 'debug', () => `sending error response: ${safeJSONStringify(resp)}`); + return resp; + } + + private makeGenericErrorResponse(err: unknown) { + const resp = { + status: 500, + body: { error: { message: err instanceof Error ? err.message : 'unknown error' } }, + }; + log( + this.options.log, + 'debug', + () => `sending error response: ${safeJSONStringify(resp)}${err instanceof Error ? '\n' + err.stack : ''}`, + ); + return resp; + } + + private makeORMErrorResponse(err: ORMError) { + let status = 400; + const error: any = { message: err.message, reason: err.reason }; + + match(err.reason) + .with(ORMErrorReason.NOT_FOUND, () => { + status = 404; + error.model = err.model; + }) + .with(ORMErrorReason.INVALID_INPUT, () => { + status = 422; + error.rejectedByValidation = true; + error.model = err.model; + }) + .with(ORMErrorReason.REJECTED_BY_POLICY, () => { + status = 403; + error.rejectedByPolicy = true; + error.model = err.model; + error.rejectReason = err.rejectedByPolicyReason; + }) + .with(ORMErrorReason.DB_QUERY_ERROR, () => { + status = 400; + error.dbErrorCode = err.dbErrorCode; + }) + .otherwise(() => {}); + + const resp = { status, body: { error } }; + log(this.options.log, 'debug', () => `sending error response: ${safeJSONStringify(resp)}`); + return resp; + } + + private async processRequestPayload(args: any) { + const { meta, ...rest } = args ?? {}; + if (meta?.serialization) { + try { + // superjson deserialization + args = SuperJSON.deserialize({ json: rest, meta: meta.serialization }); + } catch (err) { + return { result: undefined, error: `failed to deserialize request payload: ${(err as Error).message}` }; + } + } else { + // drop meta when no serialization info is present + args = rest; + } + return { result: args, error: undefined }; + } + + async generateSpec(options?: import('../common/types').OpenApiSpecOptions) { + const generator = new RPCApiSpecGenerator(this.options); + return generator.generateSpec(options); + } +} + export { RPCApiSpecGenerator } from './openapi'; From ab81f9d2f5d9bb628f124f6843c20adeae45e6e5 Mon Sep 17 00:00:00 2001 From: ymc9 <104139426+ymc9@users.noreply.github.com> Date: Thu, 19 Mar 2026 09:17:57 -0700 Subject: [PATCH 03/16] fix build --- packages/server/src/api/rpc/openapi.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/server/src/api/rpc/openapi.ts b/packages/server/src/api/rpc/openapi.ts index 8b98b5857..88a448825 100644 --- a/packages/server/src/api/rpc/openapi.ts +++ b/packages/server/src/api/rpc/openapi.ts @@ -1,6 +1,7 @@ import { lowerCaseFirst, upperCaseFirst } from '@zenstackhq/common-helpers'; import type { EnumDef, FieldDef, ModelDef, SchemaDef } from '@zenstackhq/orm/schema'; import type { OpenAPIV3_1 } from 'openapi-types'; +import type { RPCApiHandlerOptions } from '.'; import { PROCEDURE_ROUTE_PREFIXES } from '../common/procedures'; import { getIncludedModels, @@ -10,7 +11,6 @@ import { isProcedureIncluded, } from '../common/spec-utils'; import type { OpenApiSpecOptions } from '../common/types'; -import type { RPCApiHandlerOptions } from './handler'; type SchemaObject = OpenAPIV3_1.SchemaObject; type ReferenceObject = OpenAPIV3_1.ReferenceObject; @@ -685,11 +685,7 @@ export class RPCApiSpecGenerator { return baseSchema; } - private buildFieldFilterSchema( - modelName: string, - fieldName: string, - fieldDef: FieldDef, - ): SchemaObject | undefined { + private buildFieldFilterSchema(modelName: string, fieldName: string, fieldDef: FieldDef): SchemaObject | undefined { const baseSchema = this.typeToSchema(fieldDef.type); const filterProps: Record = {}; const type = fieldDef.type; From 8eea29380e619260189984f8e2137bf457622aea Mon Sep 17 00:00:00 2001 From: ymc9 <104139426+ymc9@users.noreply.github.com> Date: Thu, 19 Mar 2026 09:18:20 -0700 Subject: [PATCH 04/16] fix build --- packages/server/src/api/rest/openapi.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/server/src/api/rest/openapi.ts b/packages/server/src/api/rest/openapi.ts index 35b2bbbb6..42e9ca6b7 100644 --- a/packages/server/src/api/rest/openapi.ts +++ b/packages/server/src/api/rest/openapi.ts @@ -4,7 +4,7 @@ import type { OpenAPIV3_1 } from 'openapi-types'; import { PROCEDURE_ROUTE_PREFIXES } from '../common/procedures'; import { getIncludedModels, isFieldOmitted, isFilterKindIncluded, isProcedureIncluded } from '../common/spec-utils'; import type { OpenApiSpecOptions } from '../common/types'; -import type { RestApiHandlerOptions } from './handler'; +import type { RestApiHandlerOptions } from '.'; type SchemaObject = OpenAPIV3_1.SchemaObject; type ReferenceObject = OpenAPIV3_1.ReferenceObject; From 1853a040e6751557ffd8556eb96ac33d64bf8ac6 Mon Sep 17 00:00:00 2001 From: ymc9 <104139426+ymc9@users.noreply.github.com> Date: Thu, 19 Mar 2026 11:38:39 -0700 Subject: [PATCH 05/16] feat(server): use @@meta("description") as model schema description in OpenAPI Extract model description from @@meta("description", "...") attribute and apply it to the generated schema object in both REST and RPC OpenAPI generators. Co-Authored-By: Claude Opus 4.6 --- packages/server/src/api/common/spec-utils.ts | 19 +++++++++++- packages/server/src/api/rest/openapi.ts | 12 +++++++- packages/server/src/api/rpc/openapi.ts | 5 ++++ .../server/test/openapi/rest-openapi.test.ts | 30 +++++++++++++++++++ .../server/test/openapi/rpc-openapi.test.ts | 27 +++++++++++++++++ 5 files changed, 91 insertions(+), 2 deletions(-) diff --git a/packages/server/src/api/common/spec-utils.ts b/packages/server/src/api/common/spec-utils.ts index daaffd361..8bba4329d 100644 --- a/packages/server/src/api/common/spec-utils.ts +++ b/packages/server/src/api/common/spec-utils.ts @@ -1,6 +1,6 @@ import { lowerCaseFirst } from '@zenstackhq/common-helpers'; import type { QueryOptions } from '@zenstackhq/orm'; -import type { SchemaDef } from '@zenstackhq/orm/schema'; +import { ExpressionUtils, type AttributeApplication, type SchemaDef } from '@zenstackhq/orm/schema'; /** * Checks if a model is included based on slicing options. @@ -96,3 +96,20 @@ export function isFilterKindIncluded( return true; } + +/** + * Extracts a "description" from `@@meta("description", "...")` or `@meta("description", "...")` attributes. + */ +export function getMetaDescription(attributes: readonly AttributeApplication[] | undefined): string | undefined { + if (!attributes) return undefined; + for (const attr of attributes) { + if (attr.name !== '@meta' && attr.name !== '@@meta') continue; + const nameExpr = attr.args?.[0]?.value; + if (!nameExpr || ExpressionUtils.getLiteralValue(nameExpr) !== 'description') continue; + const valueExpr = attr.args?.[1]?.value; + if (valueExpr) { + return ExpressionUtils.getLiteralValue(valueExpr) as string | undefined; + } + } + return undefined; +} diff --git a/packages/server/src/api/rest/openapi.ts b/packages/server/src/api/rest/openapi.ts index 42e9ca6b7..7d60d9cac 100644 --- a/packages/server/src/api/rest/openapi.ts +++ b/packages/server/src/api/rest/openapi.ts @@ -2,7 +2,13 @@ import { lowerCaseFirst } from '@zenstackhq/common-helpers'; import type { EnumDef, FieldDef, ModelDef, SchemaDef } from '@zenstackhq/orm/schema'; import type { OpenAPIV3_1 } from 'openapi-types'; import { PROCEDURE_ROUTE_PREFIXES } from '../common/procedures'; -import { getIncludedModels, isFieldOmitted, isFilterKindIncluded, isProcedureIncluded } from '../common/spec-utils'; +import { + getIncludedModels, + getMetaDescription, + isFieldOmitted, + isFilterKindIncluded, + isProcedureIncluded, +} from '../common/spec-utils'; import type { OpenApiSpecOptions } from '../common/types'; import type { RestApiHandlerOptions } from '.'; @@ -688,6 +694,10 @@ export class RestApiSpecGenerator { if (required.length > 0) { result.required = required; } + const description = getMetaDescription(modelDef.attributes); + if (description) { + result.description = description; + } return result; } diff --git a/packages/server/src/api/rpc/openapi.ts b/packages/server/src/api/rpc/openapi.ts index 88a448825..93a4d3e33 100644 --- a/packages/server/src/api/rpc/openapi.ts +++ b/packages/server/src/api/rpc/openapi.ts @@ -5,6 +5,7 @@ import type { RPCApiHandlerOptions } from '.'; import { PROCEDURE_ROUTE_PREFIXES } from '../common/procedures'; import { getIncludedModels, + getMetaDescription, isFieldOmitted, isFilterKindIncluded, isOperationIncluded, @@ -390,6 +391,10 @@ export class RPCApiSpecGenerator { if (required.length > 0) { result.required = required; } + const description = getMetaDescription(modelDef.attributes); + if (description) { + result.description = description; + } return result; } diff --git a/packages/server/test/openapi/rest-openapi.test.ts b/packages/server/test/openapi/rest-openapi.test.ts index dc83417c4..8df3f5b2e 100644 --- a/packages/server/test/openapi/rest-openapi.test.ts +++ b/packages/server/test/openapi/rest-openapi.test.ts @@ -433,6 +433,36 @@ describe('REST OpenAPI spec generation - queryOptions', () => { }); }); +describe('REST OpenAPI spec generation - @@meta description', () => { + it('model @@meta description is used as schema description', async () => { + const metaSchema = ` +model User { + id String @id @default(cuid()) + email String @unique + @@meta("description", "A user of the system") +} + +model Post { + id Int @id @default(autoincrement()) + title String +} +`; + const client = await createTestClient(metaSchema); + const handler = new RestApiHandler({ + schema: client.$schema, + endpoint: 'http://localhost/api', + }); + const s = await handler.generateSpec(); + + const userSchema = s.components?.schemas?.['User'] as any; + expect(userSchema.description).toBe('A user of the system'); + + // Post has no @@meta description + const postSchema = s.components?.schemas?.['Post'] as any; + expect(postSchema.description).toBeUndefined(); + }); +}); + describe('REST OpenAPI spec generation - with enum schema', () => { it('enum schemas exist in components', async () => { const enumSchema = ` diff --git a/packages/server/test/openapi/rpc-openapi.test.ts b/packages/server/test/openapi/rpc-openapi.test.ts index c46c3d0dc..3aefa03b9 100644 --- a/packages/server/test/openapi/rpc-openapi.test.ts +++ b/packages/server/test/openapi/rpc-openapi.test.ts @@ -423,6 +423,33 @@ enum PostStatus { }); }); +describe('RPC OpenAPI spec generation - @@meta description', () => { + it('model @@meta description is used as schema description', async () => { + const metaSchema = ` +model User { + id String @id @default(cuid()) + email String @unique + @@meta("description", "A user of the system") +} + +model Post { + id Int @id @default(autoincrement()) + title String +} +`; + const client = await createTestClient(metaSchema); + const handler = new RPCApiHandler({ schema: client.$schema }); + const s = await handler.generateSpec(); + + const userSchema = s.components?.schemas?.['User'] as any; + expect(userSchema.description).toBe('A user of the system'); + + // Post has no @@meta description + const postSchema = s.components?.schemas?.['Post'] as any; + expect(postSchema.description).toBeUndefined(); + }); +}); + describe('RPC OpenAPI spec generation - with procedures', () => { it('procedure paths are generated', async () => { const schemaWithProc = ` From ba315ea66c97ad5aff57749c72d4e5125d63c237 Mon Sep 17 00:00:00 2001 From: ymc9 <104139426+ymc9@users.noreply.github.com> Date: Thu, 19 Mar 2026 12:10:40 -0700 Subject: [PATCH 06/16] remove unused test baseline files --- .../openapi/baseline/rest-3.1.0.baseline.yaml | 3279 --------- .../rest-type-coverage-3.1.0.baseline.yaml | 876 --- .../baseline/rpc-3.1.0-omit.baseline.yaml | 3058 --------- .../openapi/baseline/rpc-3.1.0.baseline.yaml | 5853 ----------------- .../rpc-type-coverage-3.1.0.baseline.yaml | 3174 --------- 5 files changed, 16240 deletions(-) delete mode 100644 packages/server/test/openapi/baseline/rest-3.1.0.baseline.yaml delete mode 100644 packages/server/test/openapi/baseline/rest-type-coverage-3.1.0.baseline.yaml delete mode 100644 packages/server/test/openapi/baseline/rpc-3.1.0-omit.baseline.yaml delete mode 100644 packages/server/test/openapi/baseline/rpc-3.1.0.baseline.yaml delete mode 100644 packages/server/test/openapi/baseline/rpc-type-coverage-3.1.0.baseline.yaml diff --git a/packages/server/test/openapi/baseline/rest-3.1.0.baseline.yaml b/packages/server/test/openapi/baseline/rest-3.1.0.baseline.yaml deleted file mode 100644 index 1e331ab8e..000000000 --- a/packages/server/test/openapi/baseline/rest-3.1.0.baseline.yaml +++ /dev/null @@ -1,3279 +0,0 @@ -openapi: 3.1.0 -info: - title: ZenStack Generated API - version: 1.0.0 -tags: - - name: user - description: User operations - - name: profile - description: Profile operations - - name: post_Item - description: Post-related operations - - name: postLike - description: PostLike operations -paths: - /user: - get: - operationId: list-User - description: List "User" resources - tags: - - user - parameters: - - $ref: '#/components/parameters/include' - - $ref: '#/components/parameters/sort' - - $ref: '#/components/parameters/page-offset' - - $ref: '#/components/parameters/page-limit' - - name: filter[id] - required: false - description: Id filter - in: query - style: form - explode: false - schema: - type: string - - name: filter[createdAt] - required: false - description: Equality filter for "createdAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[createdAt$lt] - required: false - description: Less-than filter for "createdAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[createdAt$lte] - required: false - description: Less-than or equal filter for "createdAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[createdAt$gt] - required: false - description: Greater-than filter for "createdAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[createdAt$gte] - required: false - description: Greater-than or equal filter for "createdAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[updatedAt] - required: false - description: Equality filter for "updatedAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[updatedAt$lt] - required: false - description: Less-than filter for "updatedAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[updatedAt$lte] - required: false - description: Less-than or equal filter for "updatedAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[updatedAt$gt] - required: false - description: Greater-than filter for "updatedAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[updatedAt$gte] - required: false - description: Greater-than or equal filter for "updatedAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[email] - required: false - description: Equality filter for "email" - in: query - style: form - explode: false - schema: - type: string - - name: filter[email$contains] - required: false - description: String contains filter for "email" - in: query - style: form - explode: false - schema: - type: string - - name: filter[email$icontains] - required: false - description: String case-insensitive contains filter for "email" - in: query - style: form - explode: false - schema: - type: string - - name: filter[email$search] - required: false - description: String full-text search filter for "email" - in: query - style: form - explode: false - schema: - type: string - - name: filter[email$startsWith] - required: false - description: String startsWith filter for "email" - in: query - style: form - explode: false - schema: - type: string - - name: filter[email$endsWith] - required: false - description: String endsWith filter for "email" - in: query - style: form - explode: false - schema: - type: string - - name: filter[role] - required: false - description: Equality filter for "role" - in: query - style: form - explode: false - schema: - $ref: '#/components/schemas/role' - - name: filter[posts] - required: false - description: Equality filter for "posts" - in: query - style: form - explode: false - schema: - type: array - items: - type: string - - name: filter[profile] - required: false - description: Equality filter for "profile" - in: query - style: form - explode: false - schema: - type: string - - name: filter[likes] - required: false - description: Equality filter for "likes" - in: query - style: form - explode: false - schema: - type: array - items: - type: string - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/UserListResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - post: - operationId: create-User - description: Create a "User" resource - tags: - - user - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/UserCreateRequest' - responses: - '201': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/UserResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '422': - description: Request is unprocessable due to validation errors - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - /user/{id}: - get: - operationId: fetch-User - description: Fetch a "User" resource - tags: - - user - parameters: - - $ref: '#/components/parameters/id' - - $ref: '#/components/parameters/include' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/UserResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - put: - operationId: update-User-put - description: Update a "User" resource - tags: - - user - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/UserUpdateRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/UserResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '422': - description: Request is unprocessable due to validation errors - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - patch: - operationId: update-User-patch - description: Update a "User" resource - tags: - - user - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/UserUpdateRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/UserResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '422': - description: Request is unprocessable due to validation errors - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - delete: - operationId: delete-User - description: Delete a "User" resource - tags: - - user - parameters: - - $ref: '#/components/parameters/id' - responses: - '200': - description: Successful operation - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - /user/{id}/posts: - get: - operationId: fetch-User-related-posts - description: Fetch the related "posts" resource for "User" - tags: - - user - parameters: - - $ref: '#/components/parameters/id' - - $ref: '#/components/parameters/include' - - $ref: '#/components/parameters/sort' - - $ref: '#/components/parameters/page-offset' - - $ref: '#/components/parameters/page-limit' - - name: filter[id] - required: false - description: Id filter - in: query - style: form - explode: false - schema: - type: string - - name: filter[createdAt] - required: false - description: Equality filter for "createdAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[createdAt$lt] - required: false - description: Less-than filter for "createdAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[createdAt$lte] - required: false - description: Less-than or equal filter for "createdAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[createdAt$gt] - required: false - description: Greater-than filter for "createdAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[createdAt$gte] - required: false - description: Greater-than or equal filter for "createdAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[updatedAt] - required: false - description: Equality filter for "updatedAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[updatedAt$lt] - required: false - description: Less-than filter for "updatedAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[updatedAt$lte] - required: false - description: Less-than or equal filter for "updatedAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[updatedAt$gt] - required: false - description: Greater-than filter for "updatedAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[updatedAt$gte] - required: false - description: Greater-than or equal filter for "updatedAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[email] - required: false - description: Equality filter for "email" - in: query - style: form - explode: false - schema: - type: string - - name: filter[email$contains] - required: false - description: String contains filter for "email" - in: query - style: form - explode: false - schema: - type: string - - name: filter[email$icontains] - required: false - description: String case-insensitive contains filter for "email" - in: query - style: form - explode: false - schema: - type: string - - name: filter[email$search] - required: false - description: String full-text search filter for "email" - in: query - style: form - explode: false - schema: - type: string - - name: filter[email$startsWith] - required: false - description: String startsWith filter for "email" - in: query - style: form - explode: false - schema: - type: string - - name: filter[email$endsWith] - required: false - description: String endsWith filter for "email" - in: query - style: form - explode: false - schema: - type: string - - name: filter[role] - required: false - description: Equality filter for "role" - in: query - style: form - explode: false - schema: - $ref: '#/components/schemas/role' - - name: filter[posts] - required: false - description: Equality filter for "posts" - in: query - style: form - explode: false - schema: - type: array - items: - type: string - - name: filter[profile] - required: false - description: Equality filter for "profile" - in: query - style: form - explode: false - schema: - type: string - - name: filter[likes] - required: false - description: Equality filter for "likes" - in: query - style: form - explode: false - schema: - type: array - items: - type: string - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/post_ItemListResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - /user/{id}/relationships/posts: - get: - operationId: fetch-User-relationship-posts - description: Fetch the "posts" relationships for a "User" - tags: - - user - parameters: - - $ref: '#/components/parameters/id' - - $ref: '#/components/parameters/sort' - - $ref: '#/components/parameters/page-offset' - - $ref: '#/components/parameters/page-limit' - - name: filter[id] - required: false - description: Id filter - in: query - style: form - explode: false - schema: - type: string - - name: filter[createdAt] - required: false - description: Equality filter for "createdAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[createdAt$lt] - required: false - description: Less-than filter for "createdAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[createdAt$lte] - required: false - description: Less-than or equal filter for "createdAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[createdAt$gt] - required: false - description: Greater-than filter for "createdAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[createdAt$gte] - required: false - description: Greater-than or equal filter for "createdAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[updatedAt] - required: false - description: Equality filter for "updatedAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[updatedAt$lt] - required: false - description: Less-than filter for "updatedAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[updatedAt$lte] - required: false - description: Less-than or equal filter for "updatedAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[updatedAt$gt] - required: false - description: Greater-than filter for "updatedAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[updatedAt$gte] - required: false - description: Greater-than or equal filter for "updatedAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[email] - required: false - description: Equality filter for "email" - in: query - style: form - explode: false - schema: - type: string - - name: filter[email$contains] - required: false - description: String contains filter for "email" - in: query - style: form - explode: false - schema: - type: string - - name: filter[email$icontains] - required: false - description: String case-insensitive contains filter for "email" - in: query - style: form - explode: false - schema: - type: string - - name: filter[email$search] - required: false - description: String full-text search filter for "email" - in: query - style: form - explode: false - schema: - type: string - - name: filter[email$startsWith] - required: false - description: String startsWith filter for "email" - in: query - style: form - explode: false - schema: - type: string - - name: filter[email$endsWith] - required: false - description: String endsWith filter for "email" - in: query - style: form - explode: false - schema: - type: string - - name: filter[role] - required: false - description: Equality filter for "role" - in: query - style: form - explode: false - schema: - $ref: '#/components/schemas/role' - - name: filter[posts] - required: false - description: Equality filter for "posts" - in: query - style: form - explode: false - schema: - type: array - items: - type: string - - name: filter[profile] - required: false - description: Equality filter for "profile" - in: query - style: form - explode: false - schema: - type: string - - name: filter[likes] - required: false - description: Equality filter for "likes" - in: query - style: form - explode: false - schema: - type: array - items: - type: string - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toManyRelationshipResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - put: - operationId: update-User-relationship-posts-put - description: Update "posts" relationships for a "User" - tags: - - user - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toManyRelationshipRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toManyRelationshipResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - patch: - operationId: update-User-relationship-posts-patch - description: Update "posts" relationships for a "User" - tags: - - user - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toManyRelationshipRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toManyRelationshipResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - post: - operationId: create-User-relationship-posts - description: Create new "posts" relationships for a "User" - tags: - - user - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toManyRelationshipRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toManyRelationshipResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - /user/{id}/profile: - get: - operationId: fetch-User-related-profile - description: Fetch the related "profile" resource for "User" - tags: - - user - parameters: - - $ref: '#/components/parameters/id' - - $ref: '#/components/parameters/include' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/ProfileResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - /user/{id}/relationships/profile: - get: - operationId: fetch-User-relationship-profile - description: Fetch the "profile" relationships for a "User" - tags: - - user - parameters: - - $ref: '#/components/parameters/id' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - put: - operationId: update-User-relationship-profile-put - description: Update "profile" relationship for a "User" - tags: - - user - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - patch: - operationId: update-User-relationship-profile-patch - description: Update "profile" relationship for a "User" - tags: - - user - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - /profile: - get: - operationId: list-Profile - description: List "Profile" resources - tags: - - profile - parameters: - - $ref: '#/components/parameters/include' - - $ref: '#/components/parameters/sort' - - $ref: '#/components/parameters/page-offset' - - $ref: '#/components/parameters/page-limit' - - name: filter[id] - required: false - description: Id filter - in: query - style: form - explode: false - schema: - type: string - - name: filter[image] - required: false - description: Equality filter for "image" - in: query - style: form - explode: false - schema: - type: string - - name: filter[image$contains] - required: false - description: String contains filter for "image" - in: query - style: form - explode: false - schema: - type: string - - name: filter[image$icontains] - required: false - description: String case-insensitive contains filter for "image" - in: query - style: form - explode: false - schema: - type: string - - name: filter[image$search] - required: false - description: String full-text search filter for "image" - in: query - style: form - explode: false - schema: - type: string - - name: filter[image$startsWith] - required: false - description: String startsWith filter for "image" - in: query - style: form - explode: false - schema: - type: string - - name: filter[image$endsWith] - required: false - description: String endsWith filter for "image" - in: query - style: form - explode: false - schema: - type: string - - name: filter[user] - required: false - description: Equality filter for "user" - in: query - style: form - explode: false - schema: - type: string - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/ProfileListResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - post: - operationId: create-Profile - description: Create a "Profile" resource - tags: - - profile - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/ProfileCreateRequest' - responses: - '201': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/ProfileResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '422': - description: Request is unprocessable due to validation errors - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - /profile/{id}: - get: - operationId: fetch-Profile - description: Fetch a "Profile" resource - tags: - - profile - parameters: - - $ref: '#/components/parameters/id' - - $ref: '#/components/parameters/include' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/ProfileResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - put: - operationId: update-Profile-put - description: Update a "Profile" resource - tags: - - profile - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/ProfileUpdateRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/ProfileResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '422': - description: Request is unprocessable due to validation errors - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - patch: - operationId: update-Profile-patch - description: Update a "Profile" resource - tags: - - profile - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/ProfileUpdateRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/ProfileResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '422': - description: Request is unprocessable due to validation errors - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - delete: - operationId: delete-Profile - description: Delete a "Profile" resource - tags: - - profile - parameters: - - $ref: '#/components/parameters/id' - responses: - '200': - description: Successful operation - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - /profile/{id}/user: - get: - operationId: fetch-Profile-related-user - description: Fetch the related "user" resource for "Profile" - tags: - - profile - parameters: - - $ref: '#/components/parameters/id' - - $ref: '#/components/parameters/include' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/UserResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - /profile/{id}/relationships/user: - get: - operationId: fetch-Profile-relationship-user - description: Fetch the "user" relationships for a "Profile" - tags: - - profile - parameters: - - $ref: '#/components/parameters/id' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - put: - operationId: update-Profile-relationship-user-put - description: Update "user" relationship for a "Profile" - tags: - - profile - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - patch: - operationId: update-Profile-relationship-user-patch - description: Update "user" relationship for a "Profile" - tags: - - profile - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - /post_Item: - get: - operationId: list-post_Item - description: List "post_Item" resources - tags: - - post_Item - parameters: - - $ref: '#/components/parameters/include' - - $ref: '#/components/parameters/sort' - - $ref: '#/components/parameters/page-offset' - - $ref: '#/components/parameters/page-limit' - - name: filter[id] - required: false - description: Id filter - in: query - style: form - explode: false - schema: - type: string - - name: filter[createdAt] - required: false - description: Equality filter for "createdAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[createdAt$lt] - required: false - description: Less-than filter for "createdAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[createdAt$lte] - required: false - description: Less-than or equal filter for "createdAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[createdAt$gt] - required: false - description: Greater-than filter for "createdAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[createdAt$gte] - required: false - description: Greater-than or equal filter for "createdAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[updatedAt] - required: false - description: Equality filter for "updatedAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[updatedAt$lt] - required: false - description: Less-than filter for "updatedAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[updatedAt$lte] - required: false - description: Less-than or equal filter for "updatedAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[updatedAt$gt] - required: false - description: Greater-than filter for "updatedAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[updatedAt$gte] - required: false - description: Greater-than or equal filter for "updatedAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[title] - required: false - description: Equality filter for "title" - in: query - style: form - explode: false - schema: - type: string - - name: filter[title$contains] - required: false - description: String contains filter for "title" - in: query - style: form - explode: false - schema: - type: string - - name: filter[title$icontains] - required: false - description: String case-insensitive contains filter for "title" - in: query - style: form - explode: false - schema: - type: string - - name: filter[title$search] - required: false - description: String full-text search filter for "title" - in: query - style: form - explode: false - schema: - type: string - - name: filter[title$startsWith] - required: false - description: String startsWith filter for "title" - in: query - style: form - explode: false - schema: - type: string - - name: filter[title$endsWith] - required: false - description: String endsWith filter for "title" - in: query - style: form - explode: false - schema: - type: string - - name: filter[author] - required: false - description: Equality filter for "author" - in: query - style: form - explode: false - schema: - type: string - - name: filter[published] - required: false - description: Equality filter for "published" - in: query - style: form - explode: false - schema: - type: boolean - - name: filter[viewCount] - required: false - description: Equality filter for "viewCount" - in: query - style: form - explode: false - schema: - type: integer - - name: filter[viewCount$lt] - required: false - description: Less-than filter for "viewCount" - in: query - style: form - explode: false - schema: - type: integer - - name: filter[viewCount$lte] - required: false - description: Less-than or equal filter for "viewCount" - in: query - style: form - explode: false - schema: - type: integer - - name: filter[viewCount$gt] - required: false - description: Greater-than filter for "viewCount" - in: query - style: form - explode: false - schema: - type: integer - - name: filter[viewCount$gte] - required: false - description: Greater-than or equal filter for "viewCount" - in: query - style: form - explode: false - schema: - type: integer - - name: filter[notes] - required: false - description: Equality filter for "notes" - in: query - style: form - explode: false - schema: - type: string - - name: filter[notes$contains] - required: false - description: String contains filter for "notes" - in: query - style: form - explode: false - schema: - type: string - - name: filter[notes$icontains] - required: false - description: String case-insensitive contains filter for "notes" - in: query - style: form - explode: false - schema: - type: string - - name: filter[notes$search] - required: false - description: String full-text search filter for "notes" - in: query - style: form - explode: false - schema: - type: string - - name: filter[notes$startsWith] - required: false - description: String startsWith filter for "notes" - in: query - style: form - explode: false - schema: - type: string - - name: filter[notes$endsWith] - required: false - description: String endsWith filter for "notes" - in: query - style: form - explode: false - schema: - type: string - - name: filter[likes] - required: false - description: Equality filter for "likes" - in: query - style: form - explode: false - schema: - type: array - items: - type: string - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/post_ItemListResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - post: - operationId: create-post_Item - description: Create a "post_Item" resource - tags: - - post_Item - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/post_ItemCreateRequest' - responses: - '201': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/post_ItemResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '422': - description: Request is unprocessable due to validation errors - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - /post_Item/{id}: - get: - operationId: fetch-post_Item - description: Fetch a "post_Item" resource - tags: - - post_Item - parameters: - - $ref: '#/components/parameters/id' - - $ref: '#/components/parameters/include' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/post_ItemResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - put: - operationId: update-post_Item-put - description: Update a "post_Item" resource - tags: - - post_Item - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/post_ItemUpdateRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/post_ItemResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '422': - description: Request is unprocessable due to validation errors - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - patch: - operationId: update-post_Item-patch - description: Update a "post_Item" resource - tags: - - post_Item - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/post_ItemUpdateRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/post_ItemResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '422': - description: Request is unprocessable due to validation errors - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - delete: - operationId: delete-post_Item - description: Delete a "post_Item" resource - tags: - - post_Item - parameters: - - $ref: '#/components/parameters/id' - responses: - '200': - description: Successful operation - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - /post_Item/{id}/author: - get: - operationId: fetch-post_Item-related-author - description: Fetch the related "author" resource for "post_Item" - tags: - - post_Item - parameters: - - $ref: '#/components/parameters/id' - - $ref: '#/components/parameters/include' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/UserResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - /post_Item/{id}/relationships/author: - get: - operationId: fetch-post_Item-relationship-author - description: Fetch the "author" relationships for a "post_Item" - tags: - - post_Item - parameters: - - $ref: '#/components/parameters/id' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - put: - operationId: update-post_Item-relationship-author-put - description: Update "author" relationship for a "post_Item" - tags: - - post_Item - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - patch: - operationId: update-post_Item-relationship-author-patch - description: Update "author" relationship for a "post_Item" - tags: - - post_Item - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - /postLike: - get: - operationId: list-PostLike - description: List "PostLike" resources - tags: - - postLike - parameters: - - $ref: '#/components/parameters/include' - - $ref: '#/components/parameters/sort' - - $ref: '#/components/parameters/page-offset' - - $ref: '#/components/parameters/page-limit' - - name: filter[post] - required: false - description: Equality filter for "post" - in: query - style: form - explode: false - schema: - type: string - - name: filter[user] - required: false - description: Equality filter for "user" - in: query - style: form - explode: false - schema: - type: string - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/PostLikeListResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - post: - operationId: create-PostLike - description: Create a "PostLike" resource - tags: - - postLike - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/PostLikeCreateRequest' - responses: - '201': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/PostLikeResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '422': - description: Request is unprocessable due to validation errors - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - /postLike/{id}: - get: - operationId: fetch-PostLike - description: Fetch a "PostLike" resource - tags: - - postLike - parameters: - - $ref: '#/components/parameters/id' - - $ref: '#/components/parameters/include' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/PostLikeResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - put: - operationId: update-PostLike-put - description: Update a "PostLike" resource - tags: - - postLike - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/PostLikeUpdateRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/PostLikeResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '422': - description: Request is unprocessable due to validation errors - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - patch: - operationId: update-PostLike-patch - description: Update a "PostLike" resource - tags: - - postLike - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/PostLikeUpdateRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/PostLikeResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '422': - description: Request is unprocessable due to validation errors - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - delete: - operationId: delete-PostLike - description: Delete a "PostLike" resource - tags: - - postLike - parameters: - - $ref: '#/components/parameters/id' - responses: - '200': - description: Successful operation - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - /postLike/{id}/post: - get: - operationId: fetch-PostLike-related-post - description: Fetch the related "post" resource for "PostLike" - tags: - - postLike - parameters: - - $ref: '#/components/parameters/id' - - $ref: '#/components/parameters/include' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/post_ItemResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - /postLike/{id}/relationships/post: - get: - operationId: fetch-PostLike-relationship-post - description: Fetch the "post" relationships for a "PostLike" - tags: - - postLike - parameters: - - $ref: '#/components/parameters/id' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - put: - operationId: update-PostLike-relationship-post-put - description: Update "post" relationship for a "PostLike" - tags: - - postLike - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - patch: - operationId: update-PostLike-relationship-post-patch - description: Update "post" relationship for a "PostLike" - tags: - - postLike - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - /postLike/{id}/user: - get: - operationId: fetch-PostLike-related-user - description: Fetch the related "user" resource for "PostLike" - tags: - - postLike - parameters: - - $ref: '#/components/parameters/id' - - $ref: '#/components/parameters/include' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/UserResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - /postLike/{id}/relationships/user: - get: - operationId: fetch-PostLike-relationship-user - description: Fetch the "user" relationships for a "PostLike" - tags: - - postLike - parameters: - - $ref: '#/components/parameters/id' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - put: - operationId: update-PostLike-relationship-user-put - description: Update "user" relationship for a "PostLike" - tags: - - postLike - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - patch: - operationId: update-PostLike-relationship-user-patch - description: Update "user" relationship for a "PostLike" - tags: - - postLike - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' -components: - schemas: - _jsonapi: - type: object - description: An object describing the server’s implementation - required: - - version - properties: - version: - type: string - _meta: - type: object - description: Meta information about the request or response - properties: - serialization: - description: Superjson serialization metadata - additionalProperties: true - _resourceIdentifier: - type: object - description: Identifier for a resource - required: - - type - - id - properties: - type: - type: string - description: Resource type - id: - type: string - description: Resource id - _resource: - allOf: - - $ref: '#/components/schemas/_resourceIdentifier' - - type: object - description: A resource with attributes and relationships - properties: - attributes: - type: object - description: Resource attributes - relationships: - type: object - description: Resource relationships - _links: - type: object - required: - - self - description: Links related to the resource - properties: - self: - type: string - description: Link for refetching the curent results - _pagination: - type: object - description: Pagination information - required: - - first - - last - - prev - - next - properties: - first: - oneOf: - - type: 'null' - - type: string - description: Link to the first page - last: - oneOf: - - type: 'null' - - type: string - description: Link to the last page - prev: - oneOf: - - type: 'null' - - type: string - description: Link to the previous page - next: - oneOf: - - type: 'null' - - type: string - description: Link to the next page - _errors: - type: array - description: An array of error objects - items: - type: object - required: - - status - - code - properties: - status: - type: string - description: HTTP status - code: - type: string - description: Error code - prismaCode: - type: string - description: Prisma error code if the error is thrown by Prisma - title: - type: string - description: Error title - detail: - type: string - description: Error detail - reason: - type: string - description: Detailed error reason - zodErrors: - type: object - additionalProperties: true - description: Zod validation errors if the error is due to data validation - failure - _errorResponse: - type: object - required: - - errors - description: An error response - properties: - jsonapi: - $ref: '#/components/schemas/_jsonapi' - errors: - $ref: '#/components/schemas/_errors' - _relationLinks: - type: object - required: - - self - - related - description: Links related to a relationship - properties: - self: - type: string - description: Link for fetching this relationship - related: - type: string - description: Link for fetching the resource represented by this relationship - _toOneRelationship: - type: object - description: A to-one relationship - properties: - data: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/_resourceIdentifier' - _toOneRelationshipWithLinks: - type: object - required: - - links - - data - description: A to-one relationship with links - properties: - links: - $ref: '#/components/schemas/_relationLinks' - data: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/_resourceIdentifier' - _toManyRelationship: - type: object - required: - - data - description: A to-many relationship - properties: - data: - type: array - items: - $ref: '#/components/schemas/_resourceIdentifier' - _toManyRelationshipWithLinks: - type: object - required: - - links - - data - description: A to-many relationship with links - properties: - links: - $ref: '#/components/schemas/_pagedRelationLinks' - data: - type: array - items: - $ref: '#/components/schemas/_resourceIdentifier' - _pagedRelationLinks: - description: Relationship links with pagination information - allOf: - - $ref: '#/components/schemas/_pagination' - - $ref: '#/components/schemas/_relationLinks' - _toManyRelationshipRequest: - type: object - required: - - data - description: Input for manipulating a to-many relationship - properties: - data: - type: array - items: - $ref: '#/components/schemas/_resourceIdentifier' - _toOneRelationshipRequest: - description: Input for manipulating a to-one relationship - oneOf: - - type: 'null' - - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/_resourceIdentifier' - _toManyRelationshipResponse: - description: Response for a to-many relationship - allOf: - - $ref: '#/components/schemas/_toManyRelationshipWithLinks' - - type: object - properties: - jsonapi: - $ref: '#/components/schemas/_jsonapi' - _toOneRelationshipResponse: - description: Response for a to-one relationship - allOf: - - $ref: '#/components/schemas/_toOneRelationshipWithLinks' - - type: object - properties: - jsonapi: - $ref: '#/components/schemas/_jsonapi' - role: - type: string - description: The "role" Enum - enum: - - USER - - ADMIN - User: - type: object - description: The "User" model - required: - - id - - type - - attributes - properties: - id: - type: string - type: - type: string - attributes: - type: object - properties: - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - email: - type: string - role: - $ref: '#/components/schemas/role' - required: - - createdAt - - updatedAt - - email - - role - relationships: - type: object - properties: - posts: - $ref: '#/components/schemas/_toManyRelationshipWithLinks' - profile: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/_toOneRelationshipWithLinks' - UserCreateRequest: - type: object - description: Input for creating a "User" - required: - - data - properties: - data: - type: object - description: The "User" model - required: - - type - - attributes - properties: - type: - type: string - attributes: - type: object - required: - - updatedAt - - email - properties: - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - email: - type: string - role: - $ref: '#/components/schemas/role' - relationships: - type: object - properties: - posts: - $ref: '#/components/schemas/_toManyRelationship' - profile: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/_toOneRelationship' - meta: - $ref: '#/components/schemas/_meta' - UserUpdateRequest: - type: object - description: Input for updating a "User" - required: - - data - properties: - data: - type: object - description: The "User" model - required: - - id - - type - - attributes - properties: - id: - type: string - type: - type: string - attributes: - type: object - properties: - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - email: - type: string - role: - $ref: '#/components/schemas/role' - relationships: - type: object - properties: - posts: - $ref: '#/components/schemas/_toManyRelationship' - profile: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/_toOneRelationship' - meta: - $ref: '#/components/schemas/_meta' - UserResponse: - type: object - description: Response for a "User" - required: - - data - properties: - jsonapi: - $ref: '#/components/schemas/_jsonapi' - data: - allOf: - - $ref: '#/components/schemas/User' - - type: object - properties: - relationships: - type: object - properties: &a1 - posts: - $ref: '#/components/schemas/_toManyRelationship' - profile: - $ref: '#/components/schemas/_toOneRelationship' - meta: - $ref: '#/components/schemas/_meta' - included: - type: array - items: - $ref: '#/components/schemas/_resource' - links: - $ref: '#/components/schemas/_links' - UserListResponse: - type: object - description: Response for a list of "User" - required: - - data - - links - properties: - jsonapi: - $ref: '#/components/schemas/_jsonapi' - data: - type: array - items: - allOf: - - $ref: '#/components/schemas/User' - - type: object - properties: - relationships: - type: object - properties: *a1 - meta: - $ref: '#/components/schemas/_meta' - included: - type: array - items: - $ref: '#/components/schemas/_resource' - links: - allOf: - - $ref: '#/components/schemas/_links' - - $ref: '#/components/schemas/_pagination' - Profile: - type: object - description: The "Profile" model - required: - - id - - type - - attributes - properties: - id: - type: string - type: - type: string - attributes: - type: object - properties: - image: - oneOf: - - type: 'null' - - type: string - userId: - type: string - required: - - image - - userId - relationships: - type: object - properties: - user: - $ref: '#/components/schemas/_toOneRelationshipWithLinks' - ProfileCreateRequest: - type: object - description: Input for creating a "Profile" - required: - - data - properties: - data: - type: object - description: The "Profile" model - required: - - type - - attributes - properties: - type: - type: string - attributes: - type: object - properties: - image: - oneOf: - - type: 'null' - - type: string - relationships: - type: object - properties: - user: - $ref: '#/components/schemas/_toOneRelationship' - meta: - $ref: '#/components/schemas/_meta' - ProfileUpdateRequest: - type: object - description: Input for updating a "Profile" - required: - - data - properties: - data: - type: object - description: The "Profile" model - required: - - id - - type - - attributes - properties: - id: - type: string - type: - type: string - attributes: - type: object - properties: - image: - oneOf: - - type: 'null' - - type: string - relationships: - type: object - properties: - user: - $ref: '#/components/schemas/_toOneRelationship' - meta: - $ref: '#/components/schemas/_meta' - ProfileResponse: - type: object - description: Response for a "Profile" - required: - - data - properties: - jsonapi: - $ref: '#/components/schemas/_jsonapi' - data: - allOf: - - $ref: '#/components/schemas/Profile' - - type: object - properties: - relationships: - type: object - properties: &a2 - user: - $ref: '#/components/schemas/_toOneRelationship' - meta: - $ref: '#/components/schemas/_meta' - included: - type: array - items: - $ref: '#/components/schemas/_resource' - links: - $ref: '#/components/schemas/_links' - ProfileListResponse: - type: object - description: Response for a list of "Profile" - required: - - data - - links - properties: - jsonapi: - $ref: '#/components/schemas/_jsonapi' - data: - type: array - items: - allOf: - - $ref: '#/components/schemas/Profile' - - type: object - properties: - relationships: - type: object - properties: *a2 - meta: - $ref: '#/components/schemas/_meta' - included: - type: array - items: - $ref: '#/components/schemas/_resource' - links: - allOf: - - $ref: '#/components/schemas/_links' - - $ref: '#/components/schemas/_pagination' - post_Item: - type: object - description: The "post_Item" model - required: - - id - - type - - attributes - properties: - id: - type: string - type: - type: string - attributes: - type: object - properties: - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - title: - type: string - authorId: - oneOf: - - type: 'null' - - type: string - published: - type: boolean - viewCount: - type: integer - notes: - oneOf: - - type: 'null' - - type: string - required: - - createdAt - - updatedAt - - title - - authorId - - published - - viewCount - - notes - relationships: - type: object - properties: - author: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/_toOneRelationshipWithLinks' - post_ItemCreateRequest: - type: object - description: Input for creating a "post_Item" - required: - - data - properties: - data: - type: object - description: The "post_Item" model - required: - - id - - type - - attributes - properties: - id: - type: string - type: - type: string - attributes: - type: object - required: - - updatedAt - - title - properties: - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - title: - type: string - published: - type: boolean - viewCount: - type: integer - notes: - oneOf: - - type: 'null' - - type: string - relationships: - type: object - properties: - author: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/_toOneRelationship' - meta: - $ref: '#/components/schemas/_meta' - post_ItemUpdateRequest: - type: object - description: Input for updating a "post_Item" - required: - - data - properties: - data: - type: object - description: The "post_Item" model - required: - - id - - type - - attributes - properties: - id: - type: string - type: - type: string - attributes: - type: object - properties: - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - title: - type: string - published: - type: boolean - viewCount: - type: integer - notes: - oneOf: - - type: 'null' - - type: string - relationships: - type: object - properties: - author: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/_toOneRelationship' - meta: - $ref: '#/components/schemas/_meta' - post_ItemResponse: - type: object - description: Response for a "post_Item" - required: - - data - properties: - jsonapi: - $ref: '#/components/schemas/_jsonapi' - data: - allOf: - - $ref: '#/components/schemas/post_Item' - - type: object - properties: - relationships: - type: object - properties: &a3 - author: - $ref: '#/components/schemas/_toOneRelationship' - meta: - $ref: '#/components/schemas/_meta' - included: - type: array - items: - $ref: '#/components/schemas/_resource' - links: - $ref: '#/components/schemas/_links' - post_ItemListResponse: - type: object - description: Response for a list of "post_Item" - required: - - data - - links - properties: - jsonapi: - $ref: '#/components/schemas/_jsonapi' - data: - type: array - items: - allOf: - - $ref: '#/components/schemas/post_Item' - - type: object - properties: - relationships: - type: object - properties: *a3 - meta: - $ref: '#/components/schemas/_meta' - included: - type: array - items: - $ref: '#/components/schemas/_resource' - links: - allOf: - - $ref: '#/components/schemas/_links' - - $ref: '#/components/schemas/_pagination' - PostLike: - type: object - description: The "PostLike" model - required: - - id - - type - - attributes - properties: - id: - type: string - type: - type: string - attributes: - type: object - properties: - postId: - type: string - userId: - type: string - required: - - postId - - userId - relationships: - type: object - properties: - post: - $ref: '#/components/schemas/_toOneRelationshipWithLinks' - user: - $ref: '#/components/schemas/_toOneRelationshipWithLinks' - PostLikeCreateRequest: - type: object - description: Input for creating a "PostLike" - required: - - data - properties: - data: - type: object - description: The "PostLike" model - required: - - type - - attributes - properties: - type: - type: string - relationships: - type: object - properties: - post: - $ref: '#/components/schemas/_toOneRelationship' - user: - $ref: '#/components/schemas/_toOneRelationship' - meta: - $ref: '#/components/schemas/_meta' - PostLikeUpdateRequest: - type: object - description: Input for updating a "PostLike" - required: - - data - properties: - data: - type: object - description: The "PostLike" model - required: - - id - - type - - attributes - properties: - id: - type: string - type: - type: string - relationships: - type: object - properties: - post: - $ref: '#/components/schemas/_toOneRelationship' - user: - $ref: '#/components/schemas/_toOneRelationship' - meta: - $ref: '#/components/schemas/_meta' - PostLikeResponse: - type: object - description: Response for a "PostLike" - required: - - data - properties: - jsonapi: - $ref: '#/components/schemas/_jsonapi' - data: - allOf: - - $ref: '#/components/schemas/PostLike' - - type: object - properties: - relationships: - type: object - properties: - post: - $ref: '#/components/schemas/_toOneRelationship' - user: - $ref: '#/components/schemas/_toOneRelationship' - meta: - $ref: '#/components/schemas/_meta' - included: - type: array - items: - $ref: '#/components/schemas/_resource' - links: - $ref: '#/components/schemas/_links' - PostLikeListResponse: - type: object - description: Response for a list of "PostLike" - required: - - data - - links - properties: - jsonapi: - $ref: '#/components/schemas/_jsonapi' - data: - type: array - items: - allOf: - - $ref: '#/components/schemas/PostLike' - - type: object - properties: - relationships: - type: object - properties: - post: - $ref: '#/components/schemas/_toOneRelationship' - user: - $ref: '#/components/schemas/_toOneRelationship' - meta: - $ref: '#/components/schemas/_meta' - included: - type: array - items: - $ref: '#/components/schemas/_resource' - links: - allOf: - - $ref: '#/components/schemas/_links' - - $ref: '#/components/schemas/_pagination' - parameters: - id: - name: id - in: path - description: The resource id - required: true - schema: - type: string - include: - name: include - in: query - description: Relationships to include - required: false - style: form - schema: - type: string - sort: - name: sort - in: query - description: Fields to sort by - required: false - style: form - schema: - type: string - page-offset: - name: page[offset] - in: query - description: Offset for pagination - required: false - style: form - schema: - type: integer - page-limit: - name: page[limit] - in: query - description: Limit for pagination - required: false - style: form - schema: - type: integer diff --git a/packages/server/test/openapi/baseline/rest-type-coverage-3.1.0.baseline.yaml b/packages/server/test/openapi/baseline/rest-type-coverage-3.1.0.baseline.yaml deleted file mode 100644 index 6d41ebdf6..000000000 --- a/packages/server/test/openapi/baseline/rest-type-coverage-3.1.0.baseline.yaml +++ /dev/null @@ -1,876 +0,0 @@ -openapi: 3.1.0 -info: - title: ZenStack Generated API - version: 1.0.0 -tags: - - name: foo - description: Foo operations -paths: - /foo: - get: - operationId: list-Foo - description: List "Foo" resources - tags: - - foo - parameters: - - $ref: '#/components/parameters/include' - - $ref: '#/components/parameters/sort' - - $ref: '#/components/parameters/page-offset' - - $ref: '#/components/parameters/page-limit' - - name: filter[id] - required: false - description: Id filter - in: query - style: form - explode: false - schema: - type: string - - name: filter[string] - required: false - description: Equality filter for "string" - in: query - style: form - explode: false - schema: - type: string - - name: filter[string$contains] - required: false - description: String contains filter for "string" - in: query - style: form - explode: false - schema: - type: string - - name: filter[string$icontains] - required: false - description: String case-insensitive contains filter for "string" - in: query - style: form - explode: false - schema: - type: string - - name: filter[string$search] - required: false - description: String full-text search filter for "string" - in: query - style: form - explode: false - schema: - type: string - - name: filter[string$startsWith] - required: false - description: String startsWith filter for "string" - in: query - style: form - explode: false - schema: - type: string - - name: filter[string$endsWith] - required: false - description: String endsWith filter for "string" - in: query - style: form - explode: false - schema: - type: string - - name: filter[int] - required: false - description: Equality filter for "int" - in: query - style: form - explode: false - schema: - type: integer - - name: filter[int$lt] - required: false - description: Less-than filter for "int" - in: query - style: form - explode: false - schema: - type: integer - - name: filter[int$lte] - required: false - description: Less-than or equal filter for "int" - in: query - style: form - explode: false - schema: - type: integer - - name: filter[int$gt] - required: false - description: Greater-than filter for "int" - in: query - style: form - explode: false - schema: - type: integer - - name: filter[int$gte] - required: false - description: Greater-than or equal filter for "int" - in: query - style: form - explode: false - schema: - type: integer - - name: filter[bigInt] - required: false - description: Equality filter for "bigInt" - in: query - style: form - explode: false - schema: - type: integer - - name: filter[bigInt$lt] - required: false - description: Less-than filter for "bigInt" - in: query - style: form - explode: false - schema: - type: integer - - name: filter[bigInt$lte] - required: false - description: Less-than or equal filter for "bigInt" - in: query - style: form - explode: false - schema: - type: integer - - name: filter[bigInt$gt] - required: false - description: Greater-than filter for "bigInt" - in: query - style: form - explode: false - schema: - type: integer - - name: filter[bigInt$gte] - required: false - description: Greater-than or equal filter for "bigInt" - in: query - style: form - explode: false - schema: - type: integer - - name: filter[date] - required: false - description: Equality filter for "date" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[date$lt] - required: false - description: Less-than filter for "date" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[date$lte] - required: false - description: Less-than or equal filter for "date" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[date$gt] - required: false - description: Greater-than filter for "date" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[date$gte] - required: false - description: Greater-than or equal filter for "date" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[float] - required: false - description: Equality filter for "float" - in: query - style: form - explode: false - schema: - type: number - - name: filter[float$lt] - required: false - description: Less-than filter for "float" - in: query - style: form - explode: false - schema: - type: number - - name: filter[float$lte] - required: false - description: Less-than or equal filter for "float" - in: query - style: form - explode: false - schema: - type: number - - name: filter[float$gt] - required: false - description: Greater-than filter for "float" - in: query - style: form - explode: false - schema: - type: number - - name: filter[float$gte] - required: false - description: Greater-than or equal filter for "float" - in: query - style: form - explode: false - schema: - type: number - - name: filter[decimal] - required: false - description: Equality filter for "decimal" - in: query - style: form - explode: false - schema: - oneOf: - - type: number - - type: string - - name: filter[decimal$lt] - required: false - description: Less-than filter for "decimal" - in: query - style: form - explode: false - schema: - oneOf: - - type: number - - type: string - - name: filter[decimal$lte] - required: false - description: Less-than or equal filter for "decimal" - in: query - style: form - explode: false - schema: - oneOf: - - type: number - - type: string - - name: filter[decimal$gt] - required: false - description: Greater-than filter for "decimal" - in: query - style: form - explode: false - schema: - oneOf: - - type: number - - type: string - - name: filter[decimal$gte] - required: false - description: Greater-than or equal filter for "decimal" - in: query - style: form - explode: false - schema: - oneOf: - - type: number - - type: string - - name: filter[boolean] - required: false - description: Equality filter for "boolean" - in: query - style: form - explode: false - schema: - type: boolean - - name: filter[bytes] - required: false - description: Equality filter for "bytes" - in: query - style: form - explode: false - schema: - type: string - format: byte - description: Base64 encoded byte array - - name: filter[json] - required: false - description: Equality filter for "json" - in: query - style: form - explode: false - schema: - type: string - format: json - - name: filter[plainJson] - required: false - description: Equality filter for "plainJson" - in: query - style: form - explode: false - schema: - type: string - format: json - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/FooListResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - security: [] - post: - operationId: create-Foo - description: Create a "Foo" resource - tags: - - foo - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/FooCreateRequest' - responses: - '201': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/FooResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '422': - description: Request is unprocessable due to validation errors - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - security: [] - /foo/{id}: - get: - operationId: fetch-Foo - description: Fetch a "Foo" resource - tags: - - foo - parameters: - - $ref: '#/components/parameters/id' - - $ref: '#/components/parameters/include' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/FooResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - security: [] - put: - operationId: update-Foo-put - description: Update a "Foo" resource - tags: - - foo - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/FooUpdateRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/FooResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '422': - description: Request is unprocessable due to validation errors - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - security: [] - patch: - operationId: update-Foo-patch - description: Update a "Foo" resource - tags: - - foo - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/FooUpdateRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/FooResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '422': - description: Request is unprocessable due to validation errors - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - security: [] - delete: - operationId: delete-Foo - description: Delete a "Foo" resource - tags: - - foo - parameters: - - $ref: '#/components/parameters/id' - responses: - '200': - description: Successful operation - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - security: [] -components: - schemas: - _jsonapi: - type: object - description: An object describing the server’s implementation - required: - - version - properties: - version: - type: string - _meta: - type: object - description: Meta information about the request or response - properties: - serialization: - description: Superjson serialization metadata - additionalProperties: true - _resourceIdentifier: - type: object - description: Identifier for a resource - required: - - type - - id - properties: - type: - type: string - description: Resource type - id: - type: string - description: Resource id - _resource: - allOf: - - $ref: '#/components/schemas/_resourceIdentifier' - - type: object - description: A resource with attributes and relationships - properties: - attributes: - type: object - description: Resource attributes - relationships: - type: object - description: Resource relationships - _links: - type: object - required: - - self - description: Links related to the resource - properties: - self: - type: string - description: Link for refetching the curent results - _pagination: - type: object - description: Pagination information - required: - - first - - last - - prev - - next - properties: - first: - oneOf: - - type: 'null' - - type: string - description: Link to the first page - last: - oneOf: - - type: 'null' - - type: string - description: Link to the last page - prev: - oneOf: - - type: 'null' - - type: string - description: Link to the previous page - next: - oneOf: - - type: 'null' - - type: string - description: Link to the next page - _errors: - type: array - description: An array of error objects - items: - type: object - required: - - status - - code - properties: - status: - type: string - description: HTTP status - code: - type: string - description: Error code - prismaCode: - type: string - description: Prisma error code if the error is thrown by Prisma - title: - type: string - description: Error title - detail: - type: string - description: Error detail - reason: - type: string - description: Detailed error reason - zodErrors: - type: object - additionalProperties: true - description: Zod validation errors if the error is due to data validation - failure - _errorResponse: - type: object - required: - - errors - description: An error response - properties: - jsonapi: - $ref: '#/components/schemas/_jsonapi' - errors: - $ref: '#/components/schemas/_errors' - Foo: - type: object - description: The "Foo" model - required: - - id - - type - - attributes - properties: - id: - type: string - type: - type: string - attributes: - type: object - required: - - string - - int - - bigInt - - date - - float - - decimal - - boolean - - bytes - - json - - plainJson - properties: - string: - type: string - int: - type: integer - bigInt: - type: integer - date: - type: string - format: date-time - float: - type: number - decimal: - oneOf: - - type: number - - type: string - boolean: - type: boolean - bytes: - type: string - format: byte - description: Base64 encoded byte array - json: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Meta' - plainJson: {} - FooCreateRequest: - type: object - description: Input for creating a "Foo" - required: - - data - properties: - data: - type: object - description: The "Foo" model - required: - - type - - attributes - properties: - type: - type: string - attributes: - type: object - required: - - string - - int - - bigInt - - date - - float - - decimal - - boolean - - bytes - - plainJson - properties: - string: - type: string - int: - type: integer - bigInt: - type: integer - date: - type: string - format: date-time - float: - type: number - decimal: - oneOf: - - type: number - - type: string - boolean: - type: boolean - bytes: - type: string - format: byte - description: Base64 encoded byte array - json: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Meta' - plainJson: {} - meta: - $ref: '#/components/schemas/_meta' - FooUpdateRequest: - type: object - description: Input for updating a "Foo" - required: - - data - properties: - data: - type: object - description: The "Foo" model - required: - - id - - type - - attributes - properties: - id: - type: string - type: - type: string - attributes: - type: object - properties: - string: - type: string - int: - type: integer - bigInt: - type: integer - date: - type: string - format: date-time - float: - type: number - decimal: - oneOf: - - type: number - - type: string - boolean: - type: boolean - bytes: - type: string - format: byte - description: Base64 encoded byte array - json: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Meta' - plainJson: {} - meta: - $ref: '#/components/schemas/_meta' - FooResponse: - type: object - description: Response for a "Foo" - required: - - data - properties: - jsonapi: - $ref: '#/components/schemas/_jsonapi' - data: - allOf: - - $ref: '#/components/schemas/Foo' - - type: object - properties: - relationships: - type: object - properties: &a1 {} - meta: - $ref: '#/components/schemas/_meta' - included: - type: array - items: - $ref: '#/components/schemas/_resource' - links: - $ref: '#/components/schemas/_links' - FooListResponse: - type: object - description: Response for a list of "Foo" - required: - - data - - links - properties: - jsonapi: - $ref: '#/components/schemas/_jsonapi' - data: - type: array - items: - allOf: - - $ref: '#/components/schemas/Foo' - - type: object - properties: - relationships: - type: object - properties: *a1 - meta: - $ref: '#/components/schemas/_meta' - included: - type: array - items: - $ref: '#/components/schemas/_resource' - links: - allOf: - - $ref: '#/components/schemas/_links' - - $ref: '#/components/schemas/_pagination' - Meta: - type: object - description: The "Meta" TypeDef - properties: - something: - type: string - parameters: - id: - name: id - in: path - description: The resource id - required: true - schema: - type: string - include: - name: include - in: query - description: Relationships to include - required: false - style: form - schema: - type: string - sort: - name: sort - in: query - description: Fields to sort by - required: false - style: form - schema: - type: string - page-offset: - name: page[offset] - in: query - description: Offset for pagination - required: false - style: form - schema: - type: integer - page-limit: - name: page[limit] - in: query - description: Limit for pagination - required: false - style: form - schema: - type: integer diff --git a/packages/server/test/openapi/baseline/rpc-3.1.0-omit.baseline.yaml b/packages/server/test/openapi/baseline/rpc-3.1.0-omit.baseline.yaml deleted file mode 100644 index 11369e7d0..000000000 --- a/packages/server/test/openapi/baseline/rpc-3.1.0-omit.baseline.yaml +++ /dev/null @@ -1,3058 +0,0 @@ -openapi: 3.1.0 -info: - title: ZenStack Generated API - version: 1.0.0 -tags: - - name: user - description: User operations - - name: profile - description: Profile operations - - name: post_Item - description: Post-related operations -components: - schemas: - _AnyObject: - type: object - additionalProperties: true - Role: - type: string - enum: - - USER - - ADMIN - User: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - email: - type: string - role: - $ref: '#/components/schemas/Role' - posts: - type: array - items: - $ref: '#/components/schemas/Post_Item' - profile: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Profile' - required: - - id - - createdAt - - updatedAt - - email - - role - Profile: - type: object - properties: - id: - type: string - image: - oneOf: - - type: 'null' - - type: string - user: - $ref: '#/components/schemas/User' - userId: - type: string - required: - - id - - user - - userId - Post_Item: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - title: - type: string - author: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/User' - authorId: - oneOf: - - type: 'null' - - type: string - published: - type: boolean - viewCount: - type: integer - notes: - oneOf: - - type: 'null' - - type: string - required: - - id - - createdAt - - updatedAt - - title - - published - - viewCount - AggregateUser: - type: object - properties: - _count: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/UserCountAggregateOutputType' - _min: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/UserMinAggregateOutputType' - _max: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/UserMaxAggregateOutputType' - UserGroupByOutputType: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - email: - type: string - role: - $ref: '#/components/schemas/Role' - _count: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/UserCountAggregateOutputType' - _min: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/UserMinAggregateOutputType' - _max: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/UserMaxAggregateOutputType' - required: - - id - - createdAt - - updatedAt - - email - - role - AggregateProfile: - type: object - properties: - _count: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/ProfileCountAggregateOutputType' - _min: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/ProfileMinAggregateOutputType' - _max: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/ProfileMaxAggregateOutputType' - ProfileGroupByOutputType: - type: object - properties: - id: - type: string - image: - oneOf: - - type: 'null' - - type: string - userId: - type: string - _count: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/ProfileCountAggregateOutputType' - _min: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/ProfileMinAggregateOutputType' - _max: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/ProfileMaxAggregateOutputType' - required: - - id - - userId - AggregatePost_Item: - type: object - properties: - _count: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Post_ItemCountAggregateOutputType' - _avg: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Post_ItemAvgAggregateOutputType' - _sum: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Post_ItemSumAggregateOutputType' - _min: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Post_ItemMinAggregateOutputType' - _max: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Post_ItemMaxAggregateOutputType' - Post_ItemGroupByOutputType: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - title: - type: string - authorId: - oneOf: - - type: 'null' - - type: string - published: - type: boolean - viewCount: - type: integer - notes: - oneOf: - - type: 'null' - - type: string - _count: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Post_ItemCountAggregateOutputType' - _avg: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Post_ItemAvgAggregateOutputType' - _sum: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Post_ItemSumAggregateOutputType' - _min: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Post_ItemMinAggregateOutputType' - _max: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Post_ItemMaxAggregateOutputType' - required: - - id - - createdAt - - updatedAt - - title - - published - - viewCount - UserCountAggregateOutputType: - type: object - properties: - id: - type: integer - createdAt: - type: integer - updatedAt: - type: integer - email: - type: integer - role: - type: integer - _all: - type: integer - required: - - id - - createdAt - - updatedAt - - email - - role - - _all - UserMinAggregateOutputType: - type: object - properties: - id: - oneOf: - - type: 'null' - - type: string - createdAt: - oneOf: - - type: 'null' - - type: string - format: date-time - updatedAt: - oneOf: - - type: 'null' - - type: string - format: date-time - email: - oneOf: - - type: 'null' - - type: string - role: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Role' - UserMaxAggregateOutputType: - type: object - properties: - id: - oneOf: - - type: 'null' - - type: string - createdAt: - oneOf: - - type: 'null' - - type: string - format: date-time - updatedAt: - oneOf: - - type: 'null' - - type: string - format: date-time - email: - oneOf: - - type: 'null' - - type: string - role: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Role' - ProfileCountAggregateOutputType: - type: object - properties: - id: - type: integer - image: - type: integer - userId: - type: integer - _all: - type: integer - required: - - id - - image - - userId - - _all - ProfileMinAggregateOutputType: - type: object - properties: - id: - oneOf: - - type: 'null' - - type: string - image: - oneOf: - - type: 'null' - - type: string - userId: - oneOf: - - type: 'null' - - type: string - ProfileMaxAggregateOutputType: - type: object - properties: - id: - oneOf: - - type: 'null' - - type: string - image: - oneOf: - - type: 'null' - - type: string - userId: - oneOf: - - type: 'null' - - type: string - Post_ItemCountAggregateOutputType: - type: object - properties: - id: - type: integer - createdAt: - type: integer - updatedAt: - type: integer - title: - type: integer - authorId: - type: integer - published: - type: integer - viewCount: - type: integer - notes: - type: integer - _all: - type: integer - required: - - id - - createdAt - - updatedAt - - title - - authorId - - published - - viewCount - - notes - - _all - Post_ItemAvgAggregateOutputType: - type: object - properties: - viewCount: - oneOf: - - type: 'null' - - type: number - Post_ItemSumAggregateOutputType: - type: object - properties: - viewCount: - oneOf: - - type: 'null' - - type: integer - Post_ItemMinAggregateOutputType: - type: object - properties: - id: - oneOf: - - type: 'null' - - type: string - createdAt: - oneOf: - - type: 'null' - - type: string - format: date-time - updatedAt: - oneOf: - - type: 'null' - - type: string - format: date-time - title: - oneOf: - - type: 'null' - - type: string - authorId: - oneOf: - - type: 'null' - - type: string - published: - oneOf: - - type: 'null' - - type: boolean - viewCount: - oneOf: - - type: 'null' - - type: integer - notes: - oneOf: - - type: 'null' - - type: string - Post_ItemMaxAggregateOutputType: - type: object - properties: - id: - oneOf: - - type: 'null' - - type: string - createdAt: - oneOf: - - type: 'null' - - type: string - format: date-time - updatedAt: - oneOf: - - type: 'null' - - type: string - format: date-time - title: - oneOf: - - type: 'null' - - type: string - authorId: - oneOf: - - type: 'null' - - type: string - published: - oneOf: - - type: 'null' - - type: boolean - viewCount: - oneOf: - - type: 'null' - - type: integer - notes: - oneOf: - - type: 'null' - - type: string - _Meta: - type: object - description: Meta information about the request or response - properties: - serialization: - description: Serialization metadata - additionalProperties: true - _Error: - type: object - required: - - error - properties: - error: - type: object - required: - - message - properties: - prisma: - type: boolean - description: Indicates if the error occurred during a Prisma call - rejectedByPolicy: - type: boolean - description: Indicates if the error was due to rejection by a policy - code: - type: string - description: Prisma error code. Only available when "prisma" field is true. - message: - type: string - description: Error message - reason: - type: string - description: Detailed error reason - zodErrors: - type: object - additionalProperties: true - description: Zod validation errors if the error is due to data validation - failure - additionalProperties: true - BatchPayload: - type: object - properties: - count: - type: integer - UserCreateArgs: - type: object - required: - - data - properties: - select: - $ref: '#/components/schemas/_AnyObject' - include: - $ref: '#/components/schemas/_AnyObject' - data: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - UserCreateManyArgs: - type: object - required: - - data - properties: - data: - oneOf: - - $ref: '#/components/schemas/_AnyObject' - - type: array - items: - $ref: '#/components/schemas/_AnyObject' - skipDuplicates: - type: boolean - description: Do not insert records with unique fields or ID fields that already - exist. - meta: - $ref: '#/components/schemas/_Meta' - UserFindUniqueArgs: - type: object - required: - - where - properties: - select: - $ref: '#/components/schemas/_AnyObject' - include: - $ref: '#/components/schemas/_AnyObject' - where: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - UserFindFirstArgs: - type: object - properties: - select: - $ref: '#/components/schemas/_AnyObject' - include: - $ref: '#/components/schemas/_AnyObject' - where: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - UserFindManyArgs: - type: object - properties: - select: - $ref: '#/components/schemas/_AnyObject' - include: - $ref: '#/components/schemas/_AnyObject' - where: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - orderBy: - oneOf: - - $ref: '#/components/schemas/_AnyObject' - - type: array - items: - $ref: '#/components/schemas/_AnyObject' - cursor: - $ref: '#/components/schemas/_AnyObject' - take: - type: integer - skip: - type: integer - UserUpdateArgs: - type: object - required: - - where - - data - properties: - select: - $ref: '#/components/schemas/_AnyObject' - include: - $ref: '#/components/schemas/_AnyObject' - where: - $ref: '#/components/schemas/_AnyObject' - data: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - UserUpdateManyArgs: - type: object - required: - - data - properties: - where: - $ref: '#/components/schemas/_AnyObject' - data: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - UserUpsertArgs: - type: object - required: - - create - - update - - where - properties: - select: - $ref: '#/components/schemas/_AnyObject' - include: - $ref: '#/components/schemas/_AnyObject' - where: - $ref: '#/components/schemas/_AnyObject' - create: - $ref: '#/components/schemas/_AnyObject' - update: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - UserDeleteUniqueArgs: - type: object - required: - - where - properties: - select: - $ref: '#/components/schemas/_AnyObject' - include: - $ref: '#/components/schemas/_AnyObject' - where: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - UserDeleteManyArgs: - type: object - properties: - where: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - UserCountArgs: - type: object - properties: - select: - $ref: '#/components/schemas/_AnyObject' - where: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - UserAggregateArgs: - type: object - properties: - where: - $ref: '#/components/schemas/_AnyObject' - orderBy: - $ref: '#/components/schemas/_AnyObject' - cursor: - $ref: '#/components/schemas/_AnyObject' - take: - type: integer - skip: - type: integer - _count: - oneOf: - - type: boolean - - $ref: '#/components/schemas/_AnyObject' - _min: - $ref: '#/components/schemas/_AnyObject' - _max: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - UserGroupByArgs: - type: object - properties: - where: - $ref: '#/components/schemas/_AnyObject' - orderBy: - $ref: '#/components/schemas/_AnyObject' - by: - $ref: '#/components/schemas/_AnyObject' - having: - $ref: '#/components/schemas/_AnyObject' - take: - type: integer - skip: - type: integer - _count: - oneOf: - - type: boolean - - $ref: '#/components/schemas/_AnyObject' - _min: - $ref: '#/components/schemas/_AnyObject' - _max: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - ProfileCreateArgs: - type: object - required: - - data - properties: - select: - $ref: '#/components/schemas/_AnyObject' - include: - $ref: '#/components/schemas/_AnyObject' - data: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - ProfileCreateManyArgs: - type: object - required: - - data - properties: - data: - oneOf: - - $ref: '#/components/schemas/_AnyObject' - - type: array - items: - $ref: '#/components/schemas/_AnyObject' - skipDuplicates: - type: boolean - description: Do not insert records with unique fields or ID fields that already - exist. - meta: - $ref: '#/components/schemas/_Meta' - ProfileFindUniqueArgs: - type: object - required: - - where - properties: - select: - $ref: '#/components/schemas/_AnyObject' - include: - $ref: '#/components/schemas/_AnyObject' - where: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - ProfileFindFirstArgs: - type: object - properties: - select: - $ref: '#/components/schemas/_AnyObject' - include: - $ref: '#/components/schemas/_AnyObject' - where: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - ProfileFindManyArgs: - type: object - properties: - select: - $ref: '#/components/schemas/_AnyObject' - include: - $ref: '#/components/schemas/_AnyObject' - where: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - orderBy: - oneOf: - - $ref: '#/components/schemas/_AnyObject' - - type: array - items: - $ref: '#/components/schemas/_AnyObject' - cursor: - $ref: '#/components/schemas/_AnyObject' - take: - type: integer - skip: - type: integer - ProfileUpdateArgs: - type: object - required: - - where - - data - properties: - select: - $ref: '#/components/schemas/_AnyObject' - include: - $ref: '#/components/schemas/_AnyObject' - where: - $ref: '#/components/schemas/_AnyObject' - data: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - ProfileUpdateManyArgs: - type: object - required: - - data - properties: - where: - $ref: '#/components/schemas/_AnyObject' - data: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - ProfileUpsertArgs: - type: object - required: - - create - - update - - where - properties: - select: - $ref: '#/components/schemas/_AnyObject' - include: - $ref: '#/components/schemas/_AnyObject' - where: - $ref: '#/components/schemas/_AnyObject' - create: - $ref: '#/components/schemas/_AnyObject' - update: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - ProfileDeleteUniqueArgs: - type: object - required: - - where - properties: - select: - $ref: '#/components/schemas/_AnyObject' - include: - $ref: '#/components/schemas/_AnyObject' - where: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - ProfileDeleteManyArgs: - type: object - properties: - where: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - ProfileCountArgs: - type: object - properties: - select: - $ref: '#/components/schemas/_AnyObject' - where: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - ProfileAggregateArgs: - type: object - properties: - where: - $ref: '#/components/schemas/_AnyObject' - orderBy: - $ref: '#/components/schemas/_AnyObject' - cursor: - $ref: '#/components/schemas/_AnyObject' - take: - type: integer - skip: - type: integer - _count: - oneOf: - - type: boolean - - $ref: '#/components/schemas/_AnyObject' - _min: - $ref: '#/components/schemas/_AnyObject' - _max: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - ProfileGroupByArgs: - type: object - properties: - where: - $ref: '#/components/schemas/_AnyObject' - orderBy: - $ref: '#/components/schemas/_AnyObject' - by: - $ref: '#/components/schemas/_AnyObject' - having: - $ref: '#/components/schemas/_AnyObject' - take: - type: integer - skip: - type: integer - _count: - oneOf: - - type: boolean - - $ref: '#/components/schemas/_AnyObject' - _min: - $ref: '#/components/schemas/_AnyObject' - _max: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemCreateArgs: - type: object - required: - - data - properties: - select: - $ref: '#/components/schemas/_AnyObject' - include: - $ref: '#/components/schemas/_AnyObject' - data: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemCreateManyArgs: - type: object - required: - - data - properties: - data: - oneOf: - - $ref: '#/components/schemas/_AnyObject' - - type: array - items: - $ref: '#/components/schemas/_AnyObject' - skipDuplicates: - type: boolean - description: Do not insert records with unique fields or ID fields that already - exist. - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemFindUniqueArgs: - type: object - required: - - where - properties: - select: - $ref: '#/components/schemas/_AnyObject' - include: - $ref: '#/components/schemas/_AnyObject' - where: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemFindFirstArgs: - type: object - properties: - select: - $ref: '#/components/schemas/_AnyObject' - include: - $ref: '#/components/schemas/_AnyObject' - where: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemUpdateArgs: - type: object - required: - - where - - data - properties: - select: - $ref: '#/components/schemas/_AnyObject' - include: - $ref: '#/components/schemas/_AnyObject' - where: - $ref: '#/components/schemas/_AnyObject' - data: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemUpdateManyArgs: - type: object - required: - - data - properties: - where: - $ref: '#/components/schemas/_AnyObject' - data: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemUpsertArgs: - type: object - required: - - create - - update - - where - properties: - select: - $ref: '#/components/schemas/_AnyObject' - include: - $ref: '#/components/schemas/_AnyObject' - where: - $ref: '#/components/schemas/_AnyObject' - create: - $ref: '#/components/schemas/_AnyObject' - update: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemDeleteUniqueArgs: - type: object - required: - - where - properties: - select: - $ref: '#/components/schemas/_AnyObject' - include: - $ref: '#/components/schemas/_AnyObject' - where: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemDeleteManyArgs: - type: object - properties: - where: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemCountArgs: - type: object - properties: - select: - $ref: '#/components/schemas/_AnyObject' - where: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemAggregateArgs: - type: object - properties: - where: - $ref: '#/components/schemas/_AnyObject' - orderBy: - $ref: '#/components/schemas/_AnyObject' - cursor: - $ref: '#/components/schemas/_AnyObject' - take: - type: integer - skip: - type: integer - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemGroupByArgs: - type: object - properties: - where: - $ref: '#/components/schemas/_AnyObject' - orderBy: - $ref: '#/components/schemas/_AnyObject' - by: - $ref: '#/components/schemas/_AnyObject' - having: - $ref: '#/components/schemas/_AnyObject' - take: - type: integer - skip: - type: integer - meta: - $ref: '#/components/schemas/_Meta' -paths: - /user/create: - post: - operationId: createUser - description: Create a new User - tags: - - user - responses: - '201': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/User' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/UserCreateArgs' - /user/createMany: - post: - operationId: createManyUser - description: Create several User - tags: - - user - responses: - '201': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BatchPayload' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/UserCreateManyArgs' - /user/findUnique: - get: - operationId: findUniqueUser - description: Find one unique User - tags: - - user - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/User' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/UserFindUniqueArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /user/findFirst: - get: - operationId: findFirstUser - description: Find the first User matching the given condition - tags: - - user - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/User' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/UserFindFirstArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /user/findMany: - get: - operationId: findManyUser - description: Find users matching the given conditions - tags: - - user - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - type: array - items: - $ref: '#/components/schemas/User' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/UserFindManyArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /user/update: - patch: - operationId: updateUser - description: Update a User - tags: - - user - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/User' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/UserUpdateArgs' - /user/updateMany: - patch: - operationId: updateManyUser - description: Update Users matching the given condition - tags: - - user - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BatchPayload' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/UserUpdateManyArgs' - /user/upsert: - post: - operationId: upsertUser - description: Upsert a User - tags: - - user - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/User' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/UserUpsertArgs' - /user/dodelete: - put: - operationId: deleteUser - description: Delete a unique user - tags: - - delete - - user - summary: Delete a user yeah yeah - deprecated: true - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/User' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/UserDeleteUniqueArgs' - /user/deleteMany: - delete: - operationId: deleteManyUser - description: Delete Users matching the given condition - tags: - - user - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BatchPayload' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/UserDeleteManyArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /user/count: - get: - operationId: countUser - description: Find a list of User - tags: - - user - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - oneOf: - - type: integer - - $ref: '#/components/schemas/UserCountAggregateOutputType' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/UserCountArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /user/aggregate: - get: - operationId: aggregateUser - description: Aggregate Users - tags: - - user - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/AggregateUser' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/UserAggregateArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /user/groupBy: - get: - operationId: groupByUser - description: Group Users by fields - tags: - - user - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - type: array - items: - $ref: '#/components/schemas/UserGroupByOutputType' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/UserGroupByArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /profile/create: - post: - operationId: createProfile - description: Create a new Profile - tags: - - profile - responses: - '201': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Profile' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileCreateArgs' - /profile/createMany: - post: - operationId: createManyProfile - description: Create several Profile - tags: - - profile - responses: - '201': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BatchPayload' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileCreateManyArgs' - /profile/findUnique: - get: - operationId: findUniqueProfile - description: Find one unique Profile - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Profile' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileFindUniqueArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /profile/findFirst: - get: - operationId: findFirstProfile - description: Find the first Profile matching the given condition - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Profile' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileFindFirstArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /profile/findMany: - get: - operationId: findManyProfile - description: Find a list of Profile - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - type: array - items: - $ref: '#/components/schemas/Profile' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileFindManyArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /profile/update: - patch: - operationId: updateProfile - description: Update a Profile - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Profile' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileUpdateArgs' - /profile/updateMany: - patch: - operationId: updateManyProfile - description: Update Profiles matching the given condition - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BatchPayload' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileUpdateManyArgs' - /profile/upsert: - post: - operationId: upsertProfile - description: Upsert a Profile - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Profile' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileUpsertArgs' - /profile/delete: - delete: - operationId: deleteProfile - description: Delete one unique Profile - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Profile' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileDeleteUniqueArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /profile/deleteMany: - delete: - operationId: deleteManyProfile - description: Delete Profiles matching the given condition - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BatchPayload' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileDeleteManyArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /profile/count: - get: - operationId: countProfile - description: Find a list of Profile - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - oneOf: - - type: integer - - $ref: '#/components/schemas/ProfileCountAggregateOutputType' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileCountArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /profile/aggregate: - get: - operationId: aggregateProfile - description: Aggregate Profiles - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/AggregateProfile' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileAggregateArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /profile/groupBy: - get: - operationId: groupByProfile - description: Group Profiles by fields - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - type: array - items: - $ref: '#/components/schemas/ProfileGroupByOutputType' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileGroupByArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /post_Item/create: - post: - operationId: createPost_Item - description: Create a new Post_Item - tags: - - post_Item - responses: - '201': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Post_Item' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemCreateArgs' - /post_Item/createMany: - post: - operationId: createManyPost_Item - description: Create several Post_Item - tags: - - post_Item - responses: - '201': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BatchPayload' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemCreateManyArgs' - /post_Item/findUnique: - get: - operationId: findUniquePost_Item - description: Find one unique Post_Item - tags: - - post_Item - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Post_Item' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemFindUniqueArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /post_Item/findFirst: - get: - operationId: findFirstPost_Item - description: Find the first Post_Item matching the given condition - tags: - - post_Item - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Post_Item' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemFindFirstArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /post_Item/update: - patch: - operationId: updatePost_Item - description: Update a Post_Item - tags: - - post_Item - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Post_Item' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemUpdateArgs' - /post_Item/updateMany: - patch: - operationId: updateManyPost_Item - description: Update Post_Items matching the given condition - tags: - - post_Item - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BatchPayload' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemUpdateManyArgs' - /post_Item/upsert: - post: - operationId: upsertPost_Item - description: Upsert a Post_Item - tags: - - post_Item - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Post_Item' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemUpsertArgs' - /post_Item/delete: - delete: - operationId: deletePost_Item - description: Delete one unique Post_Item - tags: - - post_Item - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Post_Item' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemDeleteUniqueArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /post_Item/deleteMany: - delete: - operationId: deleteManyPost_Item - description: Delete Post_Items matching the given condition - tags: - - post_Item - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BatchPayload' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemDeleteManyArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /post_Item/count: - get: - operationId: countPost_Item - description: Find a list of Post_Item - tags: - - post_Item - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - oneOf: - - type: integer - - $ref: '#/components/schemas/Post_ItemCountAggregateOutputType' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemCountArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /post_Item/aggregate: - get: - operationId: aggregatePost_Item - description: Aggregate Post_Items - tags: - - post_Item - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/AggregatePost_Item' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemAggregateArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /post_Item/groupBy: - get: - operationId: groupByPost_Item - description: Group Post_Items by fields - tags: - - post_Item - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - type: array - items: - $ref: '#/components/schemas/Post_ItemGroupByOutputType' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemGroupByArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} diff --git a/packages/server/test/openapi/baseline/rpc-3.1.0.baseline.yaml b/packages/server/test/openapi/baseline/rpc-3.1.0.baseline.yaml deleted file mode 100644 index 5c5103e09..000000000 --- a/packages/server/test/openapi/baseline/rpc-3.1.0.baseline.yaml +++ /dev/null @@ -1,5853 +0,0 @@ -openapi: 3.1.0 -info: - title: ZenStack Generated API - version: 1.0.0 -tags: - - name: user - description: User operations - - name: profile - description: Profile operations - - name: post_Item - description: Post-related operations -components: - schemas: - Role: - type: string - enum: - - USER - - ADMIN - UserScalarFieldEnum: - type: string - enum: - - id - - createdAt - - updatedAt - - email - - role - ProfileScalarFieldEnum: - type: string - enum: - - id - - image - - userId - Post_ItemScalarFieldEnum: - type: string - enum: - - id - - createdAt - - updatedAt - - title - - authorId - - published - - viewCount - - notes - SortOrder: - type: string - enum: - - asc - - desc - QueryMode: - type: string - enum: - - default - - insensitive - NullsOrder: - type: string - enum: - - first - - last - User: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - email: - type: string - role: - $ref: '#/components/schemas/Role' - posts: - type: array - items: - $ref: '#/components/schemas/Post_Item' - profile: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Profile' - required: - - id - - createdAt - - updatedAt - - email - - role - Profile: - type: object - properties: - id: - type: string - image: - oneOf: - - type: 'null' - - type: string - user: - $ref: '#/components/schemas/User' - userId: - type: string - required: - - id - - user - - userId - Post_Item: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - title: - type: string - author: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/User' - authorId: - oneOf: - - type: 'null' - - type: string - published: - type: boolean - viewCount: - type: integer - notes: - oneOf: - - type: 'null' - - type: string - required: - - id - - createdAt - - updatedAt - - title - - published - - viewCount - UserWhereInput: - type: object - properties: - AND: - oneOf: - - $ref: '#/components/schemas/UserWhereInput' - - type: array - items: - $ref: '#/components/schemas/UserWhereInput' - OR: - type: array - items: - $ref: '#/components/schemas/UserWhereInput' - NOT: - oneOf: - - $ref: '#/components/schemas/UserWhereInput' - - type: array - items: - $ref: '#/components/schemas/UserWhereInput' - id: - oneOf: - - $ref: '#/components/schemas/StringFilter' - - type: string - createdAt: - oneOf: - - $ref: '#/components/schemas/DateTimeFilter' - - type: string - format: date-time - updatedAt: - oneOf: - - $ref: '#/components/schemas/DateTimeFilter' - - type: string - format: date-time - email: - oneOf: - - $ref: '#/components/schemas/StringFilter' - - type: string - role: - oneOf: - - $ref: '#/components/schemas/EnumroleFilter' - - $ref: '#/components/schemas/Role' - posts: - $ref: '#/components/schemas/Post_ItemListRelationFilter' - profile: - oneOf: - - $ref: '#/components/schemas/ProfileNullableScalarRelationFilter' - - $ref: '#/components/schemas/ProfileWhereInput' - - type: 'null' - UserOrderByWithRelationInput: - type: object - properties: - id: - $ref: '#/components/schemas/SortOrder' - createdAt: - $ref: '#/components/schemas/SortOrder' - updatedAt: - $ref: '#/components/schemas/SortOrder' - email: - $ref: '#/components/schemas/SortOrder' - role: - $ref: '#/components/schemas/SortOrder' - posts: - $ref: '#/components/schemas/Post_ItemOrderByRelationAggregateInput' - profile: - $ref: '#/components/schemas/ProfileOrderByWithRelationInput' - UserWhereUniqueInput: - type: object - properties: - id: - type: string - email: - type: string - AND: - oneOf: - - $ref: '#/components/schemas/UserWhereInput' - - type: array - items: - $ref: '#/components/schemas/UserWhereInput' - OR: - type: array - items: - $ref: '#/components/schemas/UserWhereInput' - NOT: - oneOf: - - $ref: '#/components/schemas/UserWhereInput' - - type: array - items: - $ref: '#/components/schemas/UserWhereInput' - createdAt: - oneOf: - - $ref: '#/components/schemas/DateTimeFilter' - - type: string - format: date-time - updatedAt: - oneOf: - - $ref: '#/components/schemas/DateTimeFilter' - - type: string - format: date-time - role: - oneOf: - - $ref: '#/components/schemas/EnumroleFilter' - - $ref: '#/components/schemas/Role' - posts: - $ref: '#/components/schemas/Post_ItemListRelationFilter' - profile: - oneOf: - - $ref: '#/components/schemas/ProfileNullableScalarRelationFilter' - - $ref: '#/components/schemas/ProfileWhereInput' - - type: 'null' - UserScalarWhereWithAggregatesInput: - type: object - properties: - AND: - oneOf: - - $ref: '#/components/schemas/UserScalarWhereWithAggregatesInput' - - type: array - items: - $ref: '#/components/schemas/UserScalarWhereWithAggregatesInput' - OR: - type: array - items: - $ref: '#/components/schemas/UserScalarWhereWithAggregatesInput' - NOT: - oneOf: - - $ref: '#/components/schemas/UserScalarWhereWithAggregatesInput' - - type: array - items: - $ref: '#/components/schemas/UserScalarWhereWithAggregatesInput' - id: - oneOf: - - $ref: '#/components/schemas/StringWithAggregatesFilter' - - type: string - createdAt: - oneOf: - - $ref: '#/components/schemas/DateTimeWithAggregatesFilter' - - type: string - format: date-time - updatedAt: - oneOf: - - $ref: '#/components/schemas/DateTimeWithAggregatesFilter' - - type: string - format: date-time - email: - oneOf: - - $ref: '#/components/schemas/StringWithAggregatesFilter' - - type: string - role: - oneOf: - - $ref: '#/components/schemas/EnumroleWithAggregatesFilter' - - $ref: '#/components/schemas/Role' - ProfileWhereInput: - type: object - properties: - AND: - oneOf: - - $ref: '#/components/schemas/ProfileWhereInput' - - type: array - items: - $ref: '#/components/schemas/ProfileWhereInput' - OR: - type: array - items: - $ref: '#/components/schemas/ProfileWhereInput' - NOT: - oneOf: - - $ref: '#/components/schemas/ProfileWhereInput' - - type: array - items: - $ref: '#/components/schemas/ProfileWhereInput' - id: - oneOf: - - $ref: '#/components/schemas/StringFilter' - - type: string - image: - oneOf: - - $ref: '#/components/schemas/StringNullableFilter' - - type: string - - type: 'null' - userId: - oneOf: - - $ref: '#/components/schemas/StringFilter' - - type: string - user: - oneOf: - - $ref: '#/components/schemas/UserScalarRelationFilter' - - $ref: '#/components/schemas/UserWhereInput' - ProfileOrderByWithRelationInput: - type: object - properties: - id: - $ref: '#/components/schemas/SortOrder' - image: - oneOf: - - $ref: '#/components/schemas/SortOrder' - - $ref: '#/components/schemas/SortOrderInput' - userId: - $ref: '#/components/schemas/SortOrder' - user: - $ref: '#/components/schemas/UserOrderByWithRelationInput' - ProfileWhereUniqueInput: - type: object - properties: - id: - type: string - userId: - type: string - AND: - oneOf: - - $ref: '#/components/schemas/ProfileWhereInput' - - type: array - items: - $ref: '#/components/schemas/ProfileWhereInput' - OR: - type: array - items: - $ref: '#/components/schemas/ProfileWhereInput' - NOT: - oneOf: - - $ref: '#/components/schemas/ProfileWhereInput' - - type: array - items: - $ref: '#/components/schemas/ProfileWhereInput' - image: - oneOf: - - $ref: '#/components/schemas/StringNullableFilter' - - type: string - - type: 'null' - user: - oneOf: - - $ref: '#/components/schemas/UserScalarRelationFilter' - - $ref: '#/components/schemas/UserWhereInput' - ProfileScalarWhereWithAggregatesInput: - type: object - properties: - AND: - oneOf: - - $ref: '#/components/schemas/ProfileScalarWhereWithAggregatesInput' - - type: array - items: - $ref: '#/components/schemas/ProfileScalarWhereWithAggregatesInput' - OR: - type: array - items: - $ref: '#/components/schemas/ProfileScalarWhereWithAggregatesInput' - NOT: - oneOf: - - $ref: '#/components/schemas/ProfileScalarWhereWithAggregatesInput' - - type: array - items: - $ref: '#/components/schemas/ProfileScalarWhereWithAggregatesInput' - id: - oneOf: - - $ref: '#/components/schemas/StringWithAggregatesFilter' - - type: string - image: - oneOf: - - $ref: '#/components/schemas/StringNullableWithAggregatesFilter' - - type: string - - type: 'null' - userId: - oneOf: - - $ref: '#/components/schemas/StringWithAggregatesFilter' - - type: string - Post_ItemWhereInput: - type: object - properties: - AND: - oneOf: - - $ref: '#/components/schemas/Post_ItemWhereInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemWhereInput' - OR: - type: array - items: - $ref: '#/components/schemas/Post_ItemWhereInput' - NOT: - oneOf: - - $ref: '#/components/schemas/Post_ItemWhereInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemWhereInput' - id: - oneOf: - - $ref: '#/components/schemas/StringFilter' - - type: string - createdAt: - oneOf: - - $ref: '#/components/schemas/DateTimeFilter' - - type: string - format: date-time - updatedAt: - oneOf: - - $ref: '#/components/schemas/DateTimeFilter' - - type: string - format: date-time - title: - oneOf: - - $ref: '#/components/schemas/StringFilter' - - type: string - authorId: - oneOf: - - $ref: '#/components/schemas/StringNullableFilter' - - type: string - - type: 'null' - published: - oneOf: - - $ref: '#/components/schemas/BoolFilter' - - type: boolean - viewCount: - oneOf: - - $ref: '#/components/schemas/IntFilter' - - type: integer - notes: - oneOf: - - $ref: '#/components/schemas/StringNullableFilter' - - type: string - - type: 'null' - author: - oneOf: - - $ref: '#/components/schemas/UserNullableScalarRelationFilter' - - $ref: '#/components/schemas/UserWhereInput' - - type: 'null' - Post_ItemOrderByWithRelationInput: - type: object - properties: - id: - $ref: '#/components/schemas/SortOrder' - createdAt: - $ref: '#/components/schemas/SortOrder' - updatedAt: - $ref: '#/components/schemas/SortOrder' - title: - $ref: '#/components/schemas/SortOrder' - authorId: - oneOf: - - $ref: '#/components/schemas/SortOrder' - - $ref: '#/components/schemas/SortOrderInput' - published: - $ref: '#/components/schemas/SortOrder' - viewCount: - $ref: '#/components/schemas/SortOrder' - notes: - oneOf: - - $ref: '#/components/schemas/SortOrder' - - $ref: '#/components/schemas/SortOrderInput' - author: - $ref: '#/components/schemas/UserOrderByWithRelationInput' - Post_ItemWhereUniqueInput: - type: object - properties: - id: - type: string - AND: - oneOf: - - $ref: '#/components/schemas/Post_ItemWhereInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemWhereInput' - OR: - type: array - items: - $ref: '#/components/schemas/Post_ItemWhereInput' - NOT: - oneOf: - - $ref: '#/components/schemas/Post_ItemWhereInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemWhereInput' - createdAt: - oneOf: - - $ref: '#/components/schemas/DateTimeFilter' - - type: string - format: date-time - updatedAt: - oneOf: - - $ref: '#/components/schemas/DateTimeFilter' - - type: string - format: date-time - title: - oneOf: - - $ref: '#/components/schemas/StringFilter' - - type: string - authorId: - oneOf: - - $ref: '#/components/schemas/StringNullableFilter' - - type: string - - type: 'null' - published: - oneOf: - - $ref: '#/components/schemas/BoolFilter' - - type: boolean - viewCount: - oneOf: - - $ref: '#/components/schemas/IntFilter' - - type: integer - notes: - oneOf: - - $ref: '#/components/schemas/StringNullableFilter' - - type: string - - type: 'null' - author: - oneOf: - - $ref: '#/components/schemas/UserNullableScalarRelationFilter' - - $ref: '#/components/schemas/UserWhereInput' - - type: 'null' - Post_ItemScalarWhereWithAggregatesInput: - type: object - properties: - AND: - oneOf: - - $ref: '#/components/schemas/Post_ItemScalarWhereWithAggregatesInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemScalarWhereWithAggregatesInput' - OR: - type: array - items: - $ref: '#/components/schemas/Post_ItemScalarWhereWithAggregatesInput' - NOT: - oneOf: - - $ref: '#/components/schemas/Post_ItemScalarWhereWithAggregatesInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemScalarWhereWithAggregatesInput' - id: - oneOf: - - $ref: '#/components/schemas/StringWithAggregatesFilter' - - type: string - createdAt: - oneOf: - - $ref: '#/components/schemas/DateTimeWithAggregatesFilter' - - type: string - format: date-time - updatedAt: - oneOf: - - $ref: '#/components/schemas/DateTimeWithAggregatesFilter' - - type: string - format: date-time - title: - oneOf: - - $ref: '#/components/schemas/StringWithAggregatesFilter' - - type: string - authorId: - oneOf: - - $ref: '#/components/schemas/StringNullableWithAggregatesFilter' - - type: string - - type: 'null' - published: - oneOf: - - $ref: '#/components/schemas/BoolWithAggregatesFilter' - - type: boolean - viewCount: - oneOf: - - $ref: '#/components/schemas/IntWithAggregatesFilter' - - type: integer - notes: - oneOf: - - $ref: '#/components/schemas/StringNullableWithAggregatesFilter' - - type: string - - type: 'null' - UserCreateInput: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - email: - type: string - role: - $ref: '#/components/schemas/Role' - posts: - $ref: '#/components/schemas/Post_ItemCreateNestedManyWithoutAuthorInput' - profile: - $ref: '#/components/schemas/ProfileCreateNestedOneWithoutUserInput' - required: - - email - UserUpdateInput: - type: object - properties: - id: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - createdAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - updatedAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - email: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - role: - oneOf: - - $ref: '#/components/schemas/Role' - - $ref: '#/components/schemas/EnumroleFieldUpdateOperationsInput' - posts: - $ref: '#/components/schemas/Post_ItemUpdateManyWithoutAuthorNestedInput' - profile: - $ref: '#/components/schemas/ProfileUpdateOneWithoutUserNestedInput' - UserCreateManyInput: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - email: - type: string - role: - $ref: '#/components/schemas/Role' - required: - - email - UserUpdateManyMutationInput: - type: object - properties: - id: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - createdAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - updatedAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - email: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - role: - oneOf: - - $ref: '#/components/schemas/Role' - - $ref: '#/components/schemas/EnumroleFieldUpdateOperationsInput' - ProfileCreateInput: - type: object - properties: - id: - type: string - image: - oneOf: - - type: 'null' - - type: string - user: - $ref: '#/components/schemas/UserCreateNestedOneWithoutProfileInput' - required: - - user - ProfileUpdateInput: - type: object - properties: - id: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - image: - oneOf: - - type: string - - $ref: '#/components/schemas/NullableStringFieldUpdateOperationsInput' - - type: 'null' - user: - $ref: '#/components/schemas/UserUpdateOneRequiredWithoutProfileNestedInput' - ProfileCreateManyInput: - type: object - properties: - id: - type: string - image: - oneOf: - - type: 'null' - - type: string - userId: - type: string - required: - - userId - ProfileUpdateManyMutationInput: - type: object - properties: - id: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - image: - oneOf: - - type: string - - $ref: '#/components/schemas/NullableStringFieldUpdateOperationsInput' - - type: 'null' - Post_ItemCreateInput: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - title: - type: string - published: - type: boolean - viewCount: - type: integer - notes: - oneOf: - - type: 'null' - - type: string - author: - $ref: '#/components/schemas/UserCreateNestedOneWithoutPostsInput' - required: - - id - - title - Post_ItemUpdateInput: - type: object - properties: - id: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - createdAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - updatedAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - title: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - published: - oneOf: - - type: boolean - - $ref: '#/components/schemas/BoolFieldUpdateOperationsInput' - viewCount: - oneOf: - - type: integer - - $ref: '#/components/schemas/IntFieldUpdateOperationsInput' - notes: - oneOf: - - type: string - - $ref: '#/components/schemas/NullableStringFieldUpdateOperationsInput' - - type: 'null' - author: - $ref: '#/components/schemas/UserUpdateOneWithoutPostsNestedInput' - Post_ItemCreateManyInput: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - title: - type: string - authorId: - oneOf: - - type: 'null' - - type: string - published: - type: boolean - viewCount: - type: integer - notes: - oneOf: - - type: 'null' - - type: string - required: - - id - - title - Post_ItemUpdateManyMutationInput: - type: object - properties: - id: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - createdAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - updatedAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - title: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - published: - oneOf: - - type: boolean - - $ref: '#/components/schemas/BoolFieldUpdateOperationsInput' - viewCount: - oneOf: - - type: integer - - $ref: '#/components/schemas/IntFieldUpdateOperationsInput' - notes: - oneOf: - - type: string - - $ref: '#/components/schemas/NullableStringFieldUpdateOperationsInput' - - type: 'null' - StringFilter: - type: object - properties: - equals: - type: string - in: - type: array - items: - type: string - notIn: - type: array - items: - type: string - lt: - type: string - lte: - type: string - gt: - type: string - gte: - type: string - contains: - type: string - startsWith: - type: string - endsWith: - type: string - mode: - $ref: '#/components/schemas/QueryMode' - not: - oneOf: - - type: string - - $ref: '#/components/schemas/NestedStringFilter' - DateTimeFilter: - type: object - properties: - equals: - type: string - format: date-time - in: - type: array - items: - type: string - format: date-time - notIn: - type: array - items: - type: string - format: date-time - lt: - type: string - format: date-time - lte: - type: string - format: date-time - gt: - type: string - format: date-time - gte: - type: string - format: date-time - not: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/NestedDateTimeFilter' - EnumroleFilter: - type: object - properties: - equals: - $ref: '#/components/schemas/Role' - in: - type: array - items: - $ref: '#/components/schemas/Role' - notIn: - type: array - items: - $ref: '#/components/schemas/Role' - not: - oneOf: - - $ref: '#/components/schemas/Role' - - $ref: '#/components/schemas/NestedEnumroleFilter' - Post_ItemListRelationFilter: - type: object - properties: - every: - $ref: '#/components/schemas/Post_ItemWhereInput' - some: - $ref: '#/components/schemas/Post_ItemWhereInput' - none: - $ref: '#/components/schemas/Post_ItemWhereInput' - ProfileNullableScalarRelationFilter: - type: object - properties: - is: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/ProfileWhereInput' - isNot: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/ProfileWhereInput' - Post_ItemOrderByRelationAggregateInput: - type: object - properties: - _count: - $ref: '#/components/schemas/SortOrder' - StringWithAggregatesFilter: - type: object - properties: - equals: - type: string - in: - type: array - items: - type: string - notIn: - type: array - items: - type: string - lt: - type: string - lte: - type: string - gt: - type: string - gte: - type: string - contains: - type: string - startsWith: - type: string - endsWith: - type: string - mode: - $ref: '#/components/schemas/QueryMode' - not: - oneOf: - - type: string - - $ref: '#/components/schemas/NestedStringWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _min: - $ref: '#/components/schemas/NestedStringFilter' - _max: - $ref: '#/components/schemas/NestedStringFilter' - DateTimeWithAggregatesFilter: - type: object - properties: - equals: - type: string - format: date-time - in: - type: array - items: - type: string - format: date-time - notIn: - type: array - items: - type: string - format: date-time - lt: - type: string - format: date-time - lte: - type: string - format: date-time - gt: - type: string - format: date-time - gte: - type: string - format: date-time - not: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/NestedDateTimeWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _min: - $ref: '#/components/schemas/NestedDateTimeFilter' - _max: - $ref: '#/components/schemas/NestedDateTimeFilter' - EnumroleWithAggregatesFilter: - type: object - properties: - equals: - $ref: '#/components/schemas/Role' - in: - type: array - items: - $ref: '#/components/schemas/Role' - notIn: - type: array - items: - $ref: '#/components/schemas/Role' - not: - oneOf: - - $ref: '#/components/schemas/Role' - - $ref: '#/components/schemas/NestedEnumroleWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _min: - $ref: '#/components/schemas/NestedEnumroleFilter' - _max: - $ref: '#/components/schemas/NestedEnumroleFilter' - StringNullableFilter: - type: object - properties: - equals: - oneOf: - - type: 'null' - - type: string - in: - oneOf: - - type: 'null' - - type: array - items: - type: string - notIn: - oneOf: - - type: 'null' - - type: array - items: - type: string - lt: - type: string - lte: - type: string - gt: - type: string - gte: - type: string - contains: - type: string - startsWith: - type: string - endsWith: - type: string - mode: - $ref: '#/components/schemas/QueryMode' - not: - oneOf: - - type: string - - $ref: '#/components/schemas/NestedStringNullableFilter' - - type: 'null' - UserScalarRelationFilter: - type: object - properties: - is: - $ref: '#/components/schemas/UserWhereInput' - isNot: - $ref: '#/components/schemas/UserWhereInput' - SortOrderInput: - type: object - properties: - sort: - $ref: '#/components/schemas/SortOrder' - nulls: - $ref: '#/components/schemas/NullsOrder' - required: - - sort - StringNullableWithAggregatesFilter: - type: object - properties: - equals: - oneOf: - - type: 'null' - - type: string - in: - oneOf: - - type: 'null' - - type: array - items: - type: string - notIn: - oneOf: - - type: 'null' - - type: array - items: - type: string - lt: - type: string - lte: - type: string - gt: - type: string - gte: - type: string - contains: - type: string - startsWith: - type: string - endsWith: - type: string - mode: - $ref: '#/components/schemas/QueryMode' - not: - oneOf: - - type: string - - $ref: '#/components/schemas/NestedStringNullableWithAggregatesFilter' - - type: 'null' - _count: - $ref: '#/components/schemas/NestedIntNullableFilter' - _min: - $ref: '#/components/schemas/NestedStringNullableFilter' - _max: - $ref: '#/components/schemas/NestedStringNullableFilter' - BoolFilter: - type: object - properties: - equals: - type: boolean - not: - oneOf: - - type: boolean - - $ref: '#/components/schemas/NestedBoolFilter' - IntFilter: - type: object - properties: - equals: - type: integer - in: - type: array - items: - type: integer - notIn: - type: array - items: - type: integer - lt: - type: integer - lte: - type: integer - gt: - type: integer - gte: - type: integer - not: - oneOf: - - type: integer - - $ref: '#/components/schemas/NestedIntFilter' - UserNullableScalarRelationFilter: - type: object - properties: - is: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/UserWhereInput' - isNot: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/UserWhereInput' - BoolWithAggregatesFilter: - type: object - properties: - equals: - type: boolean - not: - oneOf: - - type: boolean - - $ref: '#/components/schemas/NestedBoolWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _min: - $ref: '#/components/schemas/NestedBoolFilter' - _max: - $ref: '#/components/schemas/NestedBoolFilter' - IntWithAggregatesFilter: - type: object - properties: - equals: - type: integer - in: - type: array - items: - type: integer - notIn: - type: array - items: - type: integer - lt: - type: integer - lte: - type: integer - gt: - type: integer - gte: - type: integer - not: - oneOf: - - type: integer - - $ref: '#/components/schemas/NestedIntWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _avg: - $ref: '#/components/schemas/NestedFloatFilter' - _sum: - $ref: '#/components/schemas/NestedIntFilter' - _min: - $ref: '#/components/schemas/NestedIntFilter' - _max: - $ref: '#/components/schemas/NestedIntFilter' - Post_ItemCreateNestedManyWithoutAuthorInput: - type: object - properties: - create: - oneOf: - - $ref: '#/components/schemas/Post_ItemCreateWithoutAuthorInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemCreateWithoutAuthorInput' - - $ref: '#/components/schemas/Post_ItemUncheckedCreateWithoutAuthorInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemUncheckedCreateWithoutAuthorInput' - connectOrCreate: - oneOf: - - $ref: '#/components/schemas/Post_ItemCreateOrConnectWithoutAuthorInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemCreateOrConnectWithoutAuthorInput' - createMany: - $ref: '#/components/schemas/Post_ItemCreateManyAuthorInputEnvelope' - connect: - oneOf: - - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - ProfileCreateNestedOneWithoutUserInput: - type: object - properties: - create: - oneOf: - - $ref: '#/components/schemas/ProfileCreateWithoutUserInput' - - $ref: '#/components/schemas/ProfileUncheckedCreateWithoutUserInput' - connectOrCreate: - $ref: '#/components/schemas/ProfileCreateOrConnectWithoutUserInput' - connect: - $ref: '#/components/schemas/ProfileWhereUniqueInput' - Post_ItemUncheckedCreateNestedManyWithoutAuthorInput: - type: object - properties: - create: - oneOf: - - $ref: '#/components/schemas/Post_ItemCreateWithoutAuthorInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemCreateWithoutAuthorInput' - - $ref: '#/components/schemas/Post_ItemUncheckedCreateWithoutAuthorInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemUncheckedCreateWithoutAuthorInput' - connectOrCreate: - oneOf: - - $ref: '#/components/schemas/Post_ItemCreateOrConnectWithoutAuthorInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemCreateOrConnectWithoutAuthorInput' - createMany: - $ref: '#/components/schemas/Post_ItemCreateManyAuthorInputEnvelope' - connect: - oneOf: - - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - ProfileUncheckedCreateNestedOneWithoutUserInput: - type: object - properties: - create: - oneOf: - - $ref: '#/components/schemas/ProfileCreateWithoutUserInput' - - $ref: '#/components/schemas/ProfileUncheckedCreateWithoutUserInput' - connectOrCreate: - $ref: '#/components/schemas/ProfileCreateOrConnectWithoutUserInput' - connect: - $ref: '#/components/schemas/ProfileWhereUniqueInput' - StringFieldUpdateOperationsInput: - type: object - properties: - set: - type: string - DateTimeFieldUpdateOperationsInput: - type: object - properties: - set: - type: string - format: date-time - EnumroleFieldUpdateOperationsInput: - type: object - properties: - set: - $ref: '#/components/schemas/Role' - Post_ItemUpdateManyWithoutAuthorNestedInput: - type: object - properties: - create: - oneOf: - - $ref: '#/components/schemas/Post_ItemCreateWithoutAuthorInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemCreateWithoutAuthorInput' - - $ref: '#/components/schemas/Post_ItemUncheckedCreateWithoutAuthorInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemUncheckedCreateWithoutAuthorInput' - connectOrCreate: - oneOf: - - $ref: '#/components/schemas/Post_ItemCreateOrConnectWithoutAuthorInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemCreateOrConnectWithoutAuthorInput' - upsert: - oneOf: - - $ref: '#/components/schemas/Post_ItemUpsertWithWhereUniqueWithoutAuthorInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemUpsertWithWhereUniqueWithoutAuthorInput' - createMany: - $ref: '#/components/schemas/Post_ItemCreateManyAuthorInputEnvelope' - set: - oneOf: - - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - disconnect: - oneOf: - - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - delete: - oneOf: - - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - connect: - oneOf: - - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - update: - oneOf: - - $ref: '#/components/schemas/Post_ItemUpdateWithWhereUniqueWithoutAuthorInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemUpdateWithWhereUniqueWithoutAuthorInput' - updateMany: - oneOf: - - $ref: '#/components/schemas/Post_ItemUpdateManyWithWhereWithoutAuthorInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemUpdateManyWithWhereWithoutAuthorInput' - deleteMany: - oneOf: - - $ref: '#/components/schemas/Post_ItemScalarWhereInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemScalarWhereInput' - ProfileUpdateOneWithoutUserNestedInput: - type: object - properties: - create: - oneOf: - - $ref: '#/components/schemas/ProfileCreateWithoutUserInput' - - $ref: '#/components/schemas/ProfileUncheckedCreateWithoutUserInput' - connectOrCreate: - $ref: '#/components/schemas/ProfileCreateOrConnectWithoutUserInput' - upsert: - $ref: '#/components/schemas/ProfileUpsertWithoutUserInput' - disconnect: - oneOf: - - type: boolean - - $ref: '#/components/schemas/ProfileWhereInput' - delete: - oneOf: - - type: boolean - - $ref: '#/components/schemas/ProfileWhereInput' - connect: - $ref: '#/components/schemas/ProfileWhereUniqueInput' - update: - oneOf: - - $ref: '#/components/schemas/ProfileUpdateToOneWithWhereWithoutUserInput' - - $ref: '#/components/schemas/ProfileUpdateWithoutUserInput' - - $ref: '#/components/schemas/ProfileUncheckedUpdateWithoutUserInput' - Post_ItemUncheckedUpdateManyWithoutAuthorNestedInput: - type: object - properties: - create: - oneOf: - - $ref: '#/components/schemas/Post_ItemCreateWithoutAuthorInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemCreateWithoutAuthorInput' - - $ref: '#/components/schemas/Post_ItemUncheckedCreateWithoutAuthorInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemUncheckedCreateWithoutAuthorInput' - connectOrCreate: - oneOf: - - $ref: '#/components/schemas/Post_ItemCreateOrConnectWithoutAuthorInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemCreateOrConnectWithoutAuthorInput' - upsert: - oneOf: - - $ref: '#/components/schemas/Post_ItemUpsertWithWhereUniqueWithoutAuthorInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemUpsertWithWhereUniqueWithoutAuthorInput' - createMany: - $ref: '#/components/schemas/Post_ItemCreateManyAuthorInputEnvelope' - set: - oneOf: - - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - disconnect: - oneOf: - - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - delete: - oneOf: - - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - connect: - oneOf: - - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - update: - oneOf: - - $ref: '#/components/schemas/Post_ItemUpdateWithWhereUniqueWithoutAuthorInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemUpdateWithWhereUniqueWithoutAuthorInput' - updateMany: - oneOf: - - $ref: '#/components/schemas/Post_ItemUpdateManyWithWhereWithoutAuthorInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemUpdateManyWithWhereWithoutAuthorInput' - deleteMany: - oneOf: - - $ref: '#/components/schemas/Post_ItemScalarWhereInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemScalarWhereInput' - ProfileUncheckedUpdateOneWithoutUserNestedInput: - type: object - properties: - create: - oneOf: - - $ref: '#/components/schemas/ProfileCreateWithoutUserInput' - - $ref: '#/components/schemas/ProfileUncheckedCreateWithoutUserInput' - connectOrCreate: - $ref: '#/components/schemas/ProfileCreateOrConnectWithoutUserInput' - upsert: - $ref: '#/components/schemas/ProfileUpsertWithoutUserInput' - disconnect: - oneOf: - - type: boolean - - $ref: '#/components/schemas/ProfileWhereInput' - delete: - oneOf: - - type: boolean - - $ref: '#/components/schemas/ProfileWhereInput' - connect: - $ref: '#/components/schemas/ProfileWhereUniqueInput' - update: - oneOf: - - $ref: '#/components/schemas/ProfileUpdateToOneWithWhereWithoutUserInput' - - $ref: '#/components/schemas/ProfileUpdateWithoutUserInput' - - $ref: '#/components/schemas/ProfileUncheckedUpdateWithoutUserInput' - UserCreateNestedOneWithoutProfileInput: - type: object - properties: - create: - oneOf: - - $ref: '#/components/schemas/UserCreateWithoutProfileInput' - - $ref: '#/components/schemas/UserUncheckedCreateWithoutProfileInput' - connectOrCreate: - $ref: '#/components/schemas/UserCreateOrConnectWithoutProfileInput' - connect: - $ref: '#/components/schemas/UserWhereUniqueInput' - NullableStringFieldUpdateOperationsInput: - type: object - properties: - set: - oneOf: - - type: 'null' - - type: string - UserUpdateOneRequiredWithoutProfileNestedInput: - type: object - properties: - create: - oneOf: - - $ref: '#/components/schemas/UserCreateWithoutProfileInput' - - $ref: '#/components/schemas/UserUncheckedCreateWithoutProfileInput' - connectOrCreate: - $ref: '#/components/schemas/UserCreateOrConnectWithoutProfileInput' - upsert: - $ref: '#/components/schemas/UserUpsertWithoutProfileInput' - connect: - $ref: '#/components/schemas/UserWhereUniqueInput' - update: - oneOf: - - $ref: '#/components/schemas/UserUpdateToOneWithWhereWithoutProfileInput' - - $ref: '#/components/schemas/UserUpdateWithoutProfileInput' - - $ref: '#/components/schemas/UserUncheckedUpdateWithoutProfileInput' - UserCreateNestedOneWithoutPostsInput: - type: object - properties: - create: - oneOf: - - $ref: '#/components/schemas/UserCreateWithoutPostsInput' - - $ref: '#/components/schemas/UserUncheckedCreateWithoutPostsInput' - connectOrCreate: - $ref: '#/components/schemas/UserCreateOrConnectWithoutPostsInput' - connect: - $ref: '#/components/schemas/UserWhereUniqueInput' - BoolFieldUpdateOperationsInput: - type: object - properties: - set: - type: boolean - IntFieldUpdateOperationsInput: - type: object - properties: - set: - type: integer - increment: - type: integer - decrement: - type: integer - multiply: - type: integer - divide: - type: integer - UserUpdateOneWithoutPostsNestedInput: - type: object - properties: - create: - oneOf: - - $ref: '#/components/schemas/UserCreateWithoutPostsInput' - - $ref: '#/components/schemas/UserUncheckedCreateWithoutPostsInput' - connectOrCreate: - $ref: '#/components/schemas/UserCreateOrConnectWithoutPostsInput' - upsert: - $ref: '#/components/schemas/UserUpsertWithoutPostsInput' - disconnect: - oneOf: - - type: boolean - - $ref: '#/components/schemas/UserWhereInput' - delete: - oneOf: - - type: boolean - - $ref: '#/components/schemas/UserWhereInput' - connect: - $ref: '#/components/schemas/UserWhereUniqueInput' - update: - oneOf: - - $ref: '#/components/schemas/UserUpdateToOneWithWhereWithoutPostsInput' - - $ref: '#/components/schemas/UserUpdateWithoutPostsInput' - - $ref: '#/components/schemas/UserUncheckedUpdateWithoutPostsInput' - NestedStringFilter: - type: object - properties: - equals: - type: string - in: - type: array - items: - type: string - notIn: - type: array - items: - type: string - lt: - type: string - lte: - type: string - gt: - type: string - gte: - type: string - contains: - type: string - startsWith: - type: string - endsWith: - type: string - not: - oneOf: - - type: string - - $ref: '#/components/schemas/NestedStringFilter' - NestedDateTimeFilter: - type: object - properties: - equals: - type: string - format: date-time - in: - type: array - items: - type: string - format: date-time - notIn: - type: array - items: - type: string - format: date-time - lt: - type: string - format: date-time - lte: - type: string - format: date-time - gt: - type: string - format: date-time - gte: - type: string - format: date-time - not: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/NestedDateTimeFilter' - NestedEnumroleFilter: - type: object - properties: - equals: - $ref: '#/components/schemas/Role' - in: - type: array - items: - $ref: '#/components/schemas/Role' - notIn: - type: array - items: - $ref: '#/components/schemas/Role' - not: - oneOf: - - $ref: '#/components/schemas/Role' - - $ref: '#/components/schemas/NestedEnumroleFilter' - NestedStringWithAggregatesFilter: - type: object - properties: - equals: - type: string - in: - type: array - items: - type: string - notIn: - type: array - items: - type: string - lt: - type: string - lte: - type: string - gt: - type: string - gte: - type: string - contains: - type: string - startsWith: - type: string - endsWith: - type: string - not: - oneOf: - - type: string - - $ref: '#/components/schemas/NestedStringWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _min: - $ref: '#/components/schemas/NestedStringFilter' - _max: - $ref: '#/components/schemas/NestedStringFilter' - NestedIntFilter: - type: object - properties: - equals: - type: integer - in: - type: array - items: - type: integer - notIn: - type: array - items: - type: integer - lt: - type: integer - lte: - type: integer - gt: - type: integer - gte: - type: integer - not: - oneOf: - - type: integer - - $ref: '#/components/schemas/NestedIntFilter' - NestedDateTimeWithAggregatesFilter: - type: object - properties: - equals: - type: string - format: date-time - in: - type: array - items: - type: string - format: date-time - notIn: - type: array - items: - type: string - format: date-time - lt: - type: string - format: date-time - lte: - type: string - format: date-time - gt: - type: string - format: date-time - gte: - type: string - format: date-time - not: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/NestedDateTimeWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _min: - $ref: '#/components/schemas/NestedDateTimeFilter' - _max: - $ref: '#/components/schemas/NestedDateTimeFilter' - NestedEnumroleWithAggregatesFilter: - type: object - properties: - equals: - $ref: '#/components/schemas/Role' - in: - type: array - items: - $ref: '#/components/schemas/Role' - notIn: - type: array - items: - $ref: '#/components/schemas/Role' - not: - oneOf: - - $ref: '#/components/schemas/Role' - - $ref: '#/components/schemas/NestedEnumroleWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _min: - $ref: '#/components/schemas/NestedEnumroleFilter' - _max: - $ref: '#/components/schemas/NestedEnumroleFilter' - NestedStringNullableFilter: - type: object - properties: - equals: - oneOf: - - type: 'null' - - type: string - in: - oneOf: - - type: 'null' - - type: array - items: - type: string - notIn: - oneOf: - - type: 'null' - - type: array - items: - type: string - lt: - type: string - lte: - type: string - gt: - type: string - gte: - type: string - contains: - type: string - startsWith: - type: string - endsWith: - type: string - not: - oneOf: - - type: string - - $ref: '#/components/schemas/NestedStringNullableFilter' - - type: 'null' - NestedStringNullableWithAggregatesFilter: - type: object - properties: - equals: - oneOf: - - type: 'null' - - type: string - in: - oneOf: - - type: 'null' - - type: array - items: - type: string - notIn: - oneOf: - - type: 'null' - - type: array - items: - type: string - lt: - type: string - lte: - type: string - gt: - type: string - gte: - type: string - contains: - type: string - startsWith: - type: string - endsWith: - type: string - not: - oneOf: - - type: string - - $ref: '#/components/schemas/NestedStringNullableWithAggregatesFilter' - - type: 'null' - _count: - $ref: '#/components/schemas/NestedIntNullableFilter' - _min: - $ref: '#/components/schemas/NestedStringNullableFilter' - _max: - $ref: '#/components/schemas/NestedStringNullableFilter' - NestedIntNullableFilter: - type: object - properties: - equals: - oneOf: - - type: 'null' - - type: integer - in: - oneOf: - - type: 'null' - - type: array - items: - type: integer - notIn: - oneOf: - - type: 'null' - - type: array - items: - type: integer - lt: - type: integer - lte: - type: integer - gt: - type: integer - gte: - type: integer - not: - oneOf: - - type: integer - - $ref: '#/components/schemas/NestedIntNullableFilter' - - type: 'null' - NestedBoolFilter: - type: object - properties: - equals: - type: boolean - not: - oneOf: - - type: boolean - - $ref: '#/components/schemas/NestedBoolFilter' - NestedBoolWithAggregatesFilter: - type: object - properties: - equals: - type: boolean - not: - oneOf: - - type: boolean - - $ref: '#/components/schemas/NestedBoolWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _min: - $ref: '#/components/schemas/NestedBoolFilter' - _max: - $ref: '#/components/schemas/NestedBoolFilter' - NestedIntWithAggregatesFilter: - type: object - properties: - equals: - type: integer - in: - type: array - items: - type: integer - notIn: - type: array - items: - type: integer - lt: - type: integer - lte: - type: integer - gt: - type: integer - gte: - type: integer - not: - oneOf: - - type: integer - - $ref: '#/components/schemas/NestedIntWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _avg: - $ref: '#/components/schemas/NestedFloatFilter' - _sum: - $ref: '#/components/schemas/NestedIntFilter' - _min: - $ref: '#/components/schemas/NestedIntFilter' - _max: - $ref: '#/components/schemas/NestedIntFilter' - NestedFloatFilter: - type: object - properties: - equals: - type: number - in: - type: array - items: - type: number - notIn: - type: array - items: - type: number - lt: - type: number - lte: - type: number - gt: - type: number - gte: - type: number - not: - oneOf: - - type: number - - $ref: '#/components/schemas/NestedFloatFilter' - Post_ItemCreateWithoutAuthorInput: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - title: - type: string - published: - type: boolean - viewCount: - type: integer - notes: - oneOf: - - type: 'null' - - type: string - required: - - id - - title - Post_ItemUncheckedCreateWithoutAuthorInput: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - title: - type: string - published: - type: boolean - viewCount: - type: integer - notes: - oneOf: - - type: 'null' - - type: string - required: - - id - - title - Post_ItemCreateOrConnectWithoutAuthorInput: - type: object - properties: - where: - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - create: - oneOf: - - $ref: '#/components/schemas/Post_ItemCreateWithoutAuthorInput' - - $ref: '#/components/schemas/Post_ItemUncheckedCreateWithoutAuthorInput' - required: - - where - - create - Post_ItemCreateManyAuthorInputEnvelope: - type: object - properties: - data: - oneOf: - - $ref: '#/components/schemas/Post_ItemCreateManyAuthorInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemCreateManyAuthorInput' - skipDuplicates: - type: boolean - required: - - data - ProfileCreateWithoutUserInput: - type: object - properties: - id: - type: string - image: - oneOf: - - type: 'null' - - type: string - ProfileUncheckedCreateWithoutUserInput: - type: object - properties: - id: - type: string - image: - oneOf: - - type: 'null' - - type: string - ProfileCreateOrConnectWithoutUserInput: - type: object - properties: - where: - $ref: '#/components/schemas/ProfileWhereUniqueInput' - create: - oneOf: - - $ref: '#/components/schemas/ProfileCreateWithoutUserInput' - - $ref: '#/components/schemas/ProfileUncheckedCreateWithoutUserInput' - required: - - where - - create - Post_ItemUpsertWithWhereUniqueWithoutAuthorInput: - type: object - properties: - where: - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - update: - oneOf: - - $ref: '#/components/schemas/Post_ItemUpdateWithoutAuthorInput' - - $ref: '#/components/schemas/Post_ItemUncheckedUpdateWithoutAuthorInput' - create: - oneOf: - - $ref: '#/components/schemas/Post_ItemCreateWithoutAuthorInput' - - $ref: '#/components/schemas/Post_ItemUncheckedCreateWithoutAuthorInput' - required: - - where - - update - - create - Post_ItemUpdateWithWhereUniqueWithoutAuthorInput: - type: object - properties: - where: - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - data: - oneOf: - - $ref: '#/components/schemas/Post_ItemUpdateWithoutAuthorInput' - - $ref: '#/components/schemas/Post_ItemUncheckedUpdateWithoutAuthorInput' - required: - - where - - data - Post_ItemUpdateManyWithWhereWithoutAuthorInput: - type: object - properties: - where: - $ref: '#/components/schemas/Post_ItemScalarWhereInput' - data: - oneOf: - - $ref: '#/components/schemas/Post_ItemUpdateManyMutationInput' - - $ref: '#/components/schemas/Post_ItemUncheckedUpdateManyWithoutAuthorInput' - required: - - where - - data - Post_ItemScalarWhereInput: - type: object - properties: - AND: - oneOf: - - $ref: '#/components/schemas/Post_ItemScalarWhereInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemScalarWhereInput' - OR: - type: array - items: - $ref: '#/components/schemas/Post_ItemScalarWhereInput' - NOT: - oneOf: - - $ref: '#/components/schemas/Post_ItemScalarWhereInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemScalarWhereInput' - id: - oneOf: - - $ref: '#/components/schemas/StringFilter' - - type: string - createdAt: - oneOf: - - $ref: '#/components/schemas/DateTimeFilter' - - type: string - format: date-time - updatedAt: - oneOf: - - $ref: '#/components/schemas/DateTimeFilter' - - type: string - format: date-time - title: - oneOf: - - $ref: '#/components/schemas/StringFilter' - - type: string - authorId: - oneOf: - - $ref: '#/components/schemas/StringNullableFilter' - - type: string - - type: 'null' - published: - oneOf: - - $ref: '#/components/schemas/BoolFilter' - - type: boolean - viewCount: - oneOf: - - $ref: '#/components/schemas/IntFilter' - - type: integer - notes: - oneOf: - - $ref: '#/components/schemas/StringNullableFilter' - - type: string - - type: 'null' - ProfileUpsertWithoutUserInput: - type: object - properties: - update: - oneOf: - - $ref: '#/components/schemas/ProfileUpdateWithoutUserInput' - - $ref: '#/components/schemas/ProfileUncheckedUpdateWithoutUserInput' - create: - oneOf: - - $ref: '#/components/schemas/ProfileCreateWithoutUserInput' - - $ref: '#/components/schemas/ProfileUncheckedCreateWithoutUserInput' - where: - $ref: '#/components/schemas/ProfileWhereInput' - required: - - update - - create - ProfileUpdateToOneWithWhereWithoutUserInput: - type: object - properties: - where: - $ref: '#/components/schemas/ProfileWhereInput' - data: - oneOf: - - $ref: '#/components/schemas/ProfileUpdateWithoutUserInput' - - $ref: '#/components/schemas/ProfileUncheckedUpdateWithoutUserInput' - required: - - data - ProfileUpdateWithoutUserInput: - type: object - properties: - id: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - image: - oneOf: - - type: string - - $ref: '#/components/schemas/NullableStringFieldUpdateOperationsInput' - - type: 'null' - ProfileUncheckedUpdateWithoutUserInput: - type: object - properties: - id: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - image: - oneOf: - - type: string - - $ref: '#/components/schemas/NullableStringFieldUpdateOperationsInput' - - type: 'null' - UserCreateWithoutProfileInput: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - email: - type: string - role: - $ref: '#/components/schemas/Role' - posts: - $ref: '#/components/schemas/Post_ItemCreateNestedManyWithoutAuthorInput' - required: - - email - UserUncheckedCreateWithoutProfileInput: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - email: - type: string - role: - $ref: '#/components/schemas/Role' - posts: - $ref: "#/components/schemas/Post_ItemUncheckedCreateNestedManyWithoutAuthorInpu\ - t" - required: - - email - UserCreateOrConnectWithoutProfileInput: - type: object - properties: - where: - $ref: '#/components/schemas/UserWhereUniqueInput' - create: - oneOf: - - $ref: '#/components/schemas/UserCreateWithoutProfileInput' - - $ref: '#/components/schemas/UserUncheckedCreateWithoutProfileInput' - required: - - where - - create - UserUpsertWithoutProfileInput: - type: object - properties: - update: - oneOf: - - $ref: '#/components/schemas/UserUpdateWithoutProfileInput' - - $ref: '#/components/schemas/UserUncheckedUpdateWithoutProfileInput' - create: - oneOf: - - $ref: '#/components/schemas/UserCreateWithoutProfileInput' - - $ref: '#/components/schemas/UserUncheckedCreateWithoutProfileInput' - where: - $ref: '#/components/schemas/UserWhereInput' - required: - - update - - create - UserUpdateToOneWithWhereWithoutProfileInput: - type: object - properties: - where: - $ref: '#/components/schemas/UserWhereInput' - data: - oneOf: - - $ref: '#/components/schemas/UserUpdateWithoutProfileInput' - - $ref: '#/components/schemas/UserUncheckedUpdateWithoutProfileInput' - required: - - data - UserUpdateWithoutProfileInput: - type: object - properties: - id: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - createdAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - updatedAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - email: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - role: - oneOf: - - $ref: '#/components/schemas/Role' - - $ref: '#/components/schemas/EnumroleFieldUpdateOperationsInput' - posts: - $ref: '#/components/schemas/Post_ItemUpdateManyWithoutAuthorNestedInput' - UserUncheckedUpdateWithoutProfileInput: - type: object - properties: - id: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - createdAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - updatedAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - email: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - role: - oneOf: - - $ref: '#/components/schemas/Role' - - $ref: '#/components/schemas/EnumroleFieldUpdateOperationsInput' - posts: - $ref: "#/components/schemas/Post_ItemUncheckedUpdateManyWithoutAuthorNestedInpu\ - t" - UserCreateWithoutPostsInput: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - email: - type: string - role: - $ref: '#/components/schemas/Role' - profile: - $ref: '#/components/schemas/ProfileCreateNestedOneWithoutUserInput' - required: - - email - UserUncheckedCreateWithoutPostsInput: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - email: - type: string - role: - $ref: '#/components/schemas/Role' - profile: - $ref: '#/components/schemas/ProfileUncheckedCreateNestedOneWithoutUserInput' - required: - - email - UserCreateOrConnectWithoutPostsInput: - type: object - properties: - where: - $ref: '#/components/schemas/UserWhereUniqueInput' - create: - oneOf: - - $ref: '#/components/schemas/UserCreateWithoutPostsInput' - - $ref: '#/components/schemas/UserUncheckedCreateWithoutPostsInput' - required: - - where - - create - UserUpsertWithoutPostsInput: - type: object - properties: - update: - oneOf: - - $ref: '#/components/schemas/UserUpdateWithoutPostsInput' - - $ref: '#/components/schemas/UserUncheckedUpdateWithoutPostsInput' - create: - oneOf: - - $ref: '#/components/schemas/UserCreateWithoutPostsInput' - - $ref: '#/components/schemas/UserUncheckedCreateWithoutPostsInput' - where: - $ref: '#/components/schemas/UserWhereInput' - required: - - update - - create - UserUpdateToOneWithWhereWithoutPostsInput: - type: object - properties: - where: - $ref: '#/components/schemas/UserWhereInput' - data: - oneOf: - - $ref: '#/components/schemas/UserUpdateWithoutPostsInput' - - $ref: '#/components/schemas/UserUncheckedUpdateWithoutPostsInput' - required: - - data - UserUpdateWithoutPostsInput: - type: object - properties: - id: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - createdAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - updatedAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - email: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - role: - oneOf: - - $ref: '#/components/schemas/Role' - - $ref: '#/components/schemas/EnumroleFieldUpdateOperationsInput' - profile: - $ref: '#/components/schemas/ProfileUpdateOneWithoutUserNestedInput' - UserUncheckedUpdateWithoutPostsInput: - type: object - properties: - id: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - createdAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - updatedAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - email: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - role: - oneOf: - - $ref: '#/components/schemas/Role' - - $ref: '#/components/schemas/EnumroleFieldUpdateOperationsInput' - profile: - $ref: '#/components/schemas/ProfileUncheckedUpdateOneWithoutUserNestedInput' - Post_ItemCreateManyAuthorInput: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - title: - type: string - published: - type: boolean - viewCount: - type: integer - notes: - oneOf: - - type: 'null' - - type: string - required: - - id - - title - Post_ItemUpdateWithoutAuthorInput: - type: object - properties: - id: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - createdAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - updatedAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - title: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - published: - oneOf: - - type: boolean - - $ref: '#/components/schemas/BoolFieldUpdateOperationsInput' - viewCount: - oneOf: - - type: integer - - $ref: '#/components/schemas/IntFieldUpdateOperationsInput' - notes: - oneOf: - - type: string - - $ref: '#/components/schemas/NullableStringFieldUpdateOperationsInput' - - type: 'null' - Post_ItemUncheckedUpdateWithoutAuthorInput: - type: object - properties: - id: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - createdAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - updatedAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - title: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - published: - oneOf: - - type: boolean - - $ref: '#/components/schemas/BoolFieldUpdateOperationsInput' - viewCount: - oneOf: - - type: integer - - $ref: '#/components/schemas/IntFieldUpdateOperationsInput' - notes: - oneOf: - - type: string - - $ref: '#/components/schemas/NullableStringFieldUpdateOperationsInput' - - type: 'null' - Post_ItemUncheckedUpdateManyWithoutAuthorInput: - type: object - properties: - id: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - createdAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - updatedAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - title: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - published: - oneOf: - - type: boolean - - $ref: '#/components/schemas/BoolFieldUpdateOperationsInput' - viewCount: - oneOf: - - type: integer - - $ref: '#/components/schemas/IntFieldUpdateOperationsInput' - notes: - oneOf: - - type: string - - $ref: '#/components/schemas/NullableStringFieldUpdateOperationsInput' - - type: 'null' - UserDefaultArgs: - type: object - properties: - select: - $ref: '#/components/schemas/UserSelect' - include: - $ref: '#/components/schemas/UserInclude' - ProfileDefaultArgs: - type: object - properties: - select: - $ref: '#/components/schemas/ProfileSelect' - include: - $ref: '#/components/schemas/ProfileInclude' - UserInclude: - type: object - properties: - posts: - oneOf: - - type: boolean - - $ref: '#/components/schemas/Post_ItemFindManyArgs' - profile: - oneOf: - - type: boolean - - $ref: '#/components/schemas/ProfileDefaultArgs' - _count: - oneOf: - - type: boolean - - $ref: '#/components/schemas/UserCountOutputTypeDefaultArgs' - ProfileInclude: - type: object - properties: - user: - oneOf: - - type: boolean - - $ref: '#/components/schemas/UserDefaultArgs' - Post_ItemInclude: - type: object - properties: - author: - oneOf: - - type: boolean - - $ref: '#/components/schemas/UserDefaultArgs' - UserCountOutputTypeSelect: - type: object - properties: - posts: - type: boolean - UserCountOutputTypeDefaultArgs: - type: object - properties: - select: - $ref: '#/components/schemas/UserCountOutputTypeSelect' - UserSelect: - type: object - properties: - id: - type: boolean - createdAt: - type: boolean - updatedAt: - type: boolean - email: - type: boolean - role: - type: boolean - posts: - oneOf: - - type: boolean - - $ref: '#/components/schemas/Post_ItemFindManyArgs' - profile: - oneOf: - - type: boolean - - $ref: '#/components/schemas/ProfileDefaultArgs' - _count: - oneOf: - - type: boolean - - $ref: '#/components/schemas/UserCountOutputTypeDefaultArgs' - ProfileSelect: - type: object - properties: - id: - type: boolean - image: - type: boolean - user: - oneOf: - - type: boolean - - $ref: '#/components/schemas/UserDefaultArgs' - userId: - type: boolean - Post_ItemSelect: - type: object - properties: - id: - type: boolean - createdAt: - type: boolean - updatedAt: - type: boolean - title: - type: boolean - author: - oneOf: - - type: boolean - - $ref: '#/components/schemas/UserDefaultArgs' - authorId: - type: boolean - published: - type: boolean - viewCount: - type: boolean - notes: - type: boolean - UserCountAggregateInput: - type: object - properties: - id: - type: boolean - createdAt: - type: boolean - updatedAt: - type: boolean - email: - type: boolean - role: - type: boolean - _all: - type: boolean - UserMinAggregateInput: - type: object - properties: - id: - type: boolean - createdAt: - type: boolean - updatedAt: - type: boolean - email: - type: boolean - role: - type: boolean - UserMaxAggregateInput: - type: object - properties: - id: - type: boolean - createdAt: - type: boolean - updatedAt: - type: boolean - email: - type: boolean - role: - type: boolean - ProfileCountAggregateInput: - type: object - properties: - id: - type: boolean - image: - type: boolean - userId: - type: boolean - _all: - type: boolean - ProfileMinAggregateInput: - type: object - properties: - id: - type: boolean - image: - type: boolean - userId: - type: boolean - ProfileMaxAggregateInput: - type: object - properties: - id: - type: boolean - image: - type: boolean - userId: - type: boolean - AggregateUser: - type: object - properties: - _count: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/UserCountAggregateOutputType' - _min: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/UserMinAggregateOutputType' - _max: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/UserMaxAggregateOutputType' - UserGroupByOutputType: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - email: - type: string - role: - $ref: '#/components/schemas/Role' - _count: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/UserCountAggregateOutputType' - _min: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/UserMinAggregateOutputType' - _max: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/UserMaxAggregateOutputType' - required: - - id - - createdAt - - updatedAt - - email - - role - AggregateProfile: - type: object - properties: - _count: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/ProfileCountAggregateOutputType' - _min: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/ProfileMinAggregateOutputType' - _max: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/ProfileMaxAggregateOutputType' - ProfileGroupByOutputType: - type: object - properties: - id: - type: string - image: - oneOf: - - type: 'null' - - type: string - userId: - type: string - _count: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/ProfileCountAggregateOutputType' - _min: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/ProfileMinAggregateOutputType' - _max: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/ProfileMaxAggregateOutputType' - required: - - id - - userId - AggregatePost_Item: - type: object - properties: - _count: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Post_ItemCountAggregateOutputType' - _avg: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Post_ItemAvgAggregateOutputType' - _sum: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Post_ItemSumAggregateOutputType' - _min: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Post_ItemMinAggregateOutputType' - _max: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Post_ItemMaxAggregateOutputType' - Post_ItemGroupByOutputType: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - title: - type: string - authorId: - oneOf: - - type: 'null' - - type: string - published: - type: boolean - viewCount: - type: integer - notes: - oneOf: - - type: 'null' - - type: string - _count: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Post_ItemCountAggregateOutputType' - _avg: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Post_ItemAvgAggregateOutputType' - _sum: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Post_ItemSumAggregateOutputType' - _min: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Post_ItemMinAggregateOutputType' - _max: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Post_ItemMaxAggregateOutputType' - required: - - id - - createdAt - - updatedAt - - title - - published - - viewCount - UserCountAggregateOutputType: - type: object - properties: - id: - type: integer - createdAt: - type: integer - updatedAt: - type: integer - email: - type: integer - role: - type: integer - _all: - type: integer - required: - - id - - createdAt - - updatedAt - - email - - role - - _all - UserMinAggregateOutputType: - type: object - properties: - id: - oneOf: - - type: 'null' - - type: string - createdAt: - oneOf: - - type: 'null' - - type: string - format: date-time - updatedAt: - oneOf: - - type: 'null' - - type: string - format: date-time - email: - oneOf: - - type: 'null' - - type: string - role: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Role' - UserMaxAggregateOutputType: - type: object - properties: - id: - oneOf: - - type: 'null' - - type: string - createdAt: - oneOf: - - type: 'null' - - type: string - format: date-time - updatedAt: - oneOf: - - type: 'null' - - type: string - format: date-time - email: - oneOf: - - type: 'null' - - type: string - role: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Role' - ProfileCountAggregateOutputType: - type: object - properties: - id: - type: integer - image: - type: integer - userId: - type: integer - _all: - type: integer - required: - - id - - image - - userId - - _all - ProfileMinAggregateOutputType: - type: object - properties: - id: - oneOf: - - type: 'null' - - type: string - image: - oneOf: - - type: 'null' - - type: string - userId: - oneOf: - - type: 'null' - - type: string - ProfileMaxAggregateOutputType: - type: object - properties: - id: - oneOf: - - type: 'null' - - type: string - image: - oneOf: - - type: 'null' - - type: string - userId: - oneOf: - - type: 'null' - - type: string - Post_ItemCountAggregateOutputType: - type: object - properties: - id: - type: integer - createdAt: - type: integer - updatedAt: - type: integer - title: - type: integer - authorId: - type: integer - published: - type: integer - viewCount: - type: integer - notes: - type: integer - _all: - type: integer - required: - - id - - createdAt - - updatedAt - - title - - authorId - - published - - viewCount - - notes - - _all - Post_ItemAvgAggregateOutputType: - type: object - properties: - viewCount: - oneOf: - - type: 'null' - - type: number - Post_ItemSumAggregateOutputType: - type: object - properties: - viewCount: - oneOf: - - type: 'null' - - type: integer - Post_ItemMinAggregateOutputType: - type: object - properties: - id: - oneOf: - - type: 'null' - - type: string - createdAt: - oneOf: - - type: 'null' - - type: string - format: date-time - updatedAt: - oneOf: - - type: 'null' - - type: string - format: date-time - title: - oneOf: - - type: 'null' - - type: string - authorId: - oneOf: - - type: 'null' - - type: string - published: - oneOf: - - type: 'null' - - type: boolean - viewCount: - oneOf: - - type: 'null' - - type: integer - notes: - oneOf: - - type: 'null' - - type: string - Post_ItemMaxAggregateOutputType: - type: object - properties: - id: - oneOf: - - type: 'null' - - type: string - createdAt: - oneOf: - - type: 'null' - - type: string - format: date-time - updatedAt: - oneOf: - - type: 'null' - - type: string - format: date-time - title: - oneOf: - - type: 'null' - - type: string - authorId: - oneOf: - - type: 'null' - - type: string - published: - oneOf: - - type: 'null' - - type: boolean - viewCount: - oneOf: - - type: 'null' - - type: integer - notes: - oneOf: - - type: 'null' - - type: string - _Meta: - type: object - description: Meta information about the request or response - properties: - serialization: - description: Serialization metadata - additionalProperties: true - _Error: - type: object - required: - - error - properties: - error: - type: object - required: - - message - properties: - prisma: - type: boolean - description: Indicates if the error occurred during a Prisma call - rejectedByPolicy: - type: boolean - description: Indicates if the error was due to rejection by a policy - code: - type: string - description: Prisma error code. Only available when "prisma" field is true. - message: - type: string - description: Error message - reason: - type: string - description: Detailed error reason - zodErrors: - type: object - additionalProperties: true - description: Zod validation errors if the error is due to data validation - failure - additionalProperties: true - BatchPayload: - type: object - properties: - count: - type: integer - UserCreateArgs: - type: object - required: - - data - properties: - select: - $ref: '#/components/schemas/UserSelect' - include: - $ref: '#/components/schemas/UserInclude' - data: - $ref: '#/components/schemas/UserCreateInput' - meta: - $ref: '#/components/schemas/_Meta' - UserCreateManyArgs: - type: object - required: - - data - properties: - data: - oneOf: - - $ref: '#/components/schemas/UserCreateManyInput' - - type: array - items: - $ref: '#/components/schemas/UserCreateManyInput' - skipDuplicates: - type: boolean - description: Do not insert records with unique fields or ID fields that already - exist. - meta: - $ref: '#/components/schemas/_Meta' - UserFindUniqueArgs: - type: object - required: - - where - properties: - select: - $ref: '#/components/schemas/UserSelect' - include: - $ref: '#/components/schemas/UserInclude' - where: - $ref: '#/components/schemas/UserWhereUniqueInput' - meta: - $ref: '#/components/schemas/_Meta' - UserFindFirstArgs: - type: object - properties: - select: - $ref: '#/components/schemas/UserSelect' - include: - $ref: '#/components/schemas/UserInclude' - where: - $ref: '#/components/schemas/UserWhereInput' - meta: - $ref: '#/components/schemas/_Meta' - UserFindManyArgs: - type: object - properties: - select: - $ref: '#/components/schemas/UserSelect' - include: - $ref: '#/components/schemas/UserInclude' - where: - $ref: '#/components/schemas/UserWhereInput' - meta: - $ref: '#/components/schemas/_Meta' - orderBy: - oneOf: - - $ref: '#/components/schemas/UserOrderByWithRelationInput' - - type: array - items: - $ref: '#/components/schemas/UserOrderByWithRelationInput' - cursor: - $ref: '#/components/schemas/UserWhereUniqueInput' - take: - type: integer - skip: - type: integer - UserUpdateArgs: - type: object - required: - - where - - data - properties: - select: - $ref: '#/components/schemas/UserSelect' - include: - $ref: '#/components/schemas/UserInclude' - where: - $ref: '#/components/schemas/UserWhereUniqueInput' - data: - $ref: '#/components/schemas/UserUpdateInput' - meta: - $ref: '#/components/schemas/_Meta' - UserUpdateManyArgs: - type: object - required: - - data - properties: - where: - $ref: '#/components/schemas/UserWhereInput' - data: - $ref: '#/components/schemas/UserUpdateManyMutationInput' - meta: - $ref: '#/components/schemas/_Meta' - UserUpsertArgs: - type: object - required: - - create - - update - - where - properties: - select: - $ref: '#/components/schemas/UserSelect' - include: - $ref: '#/components/schemas/UserInclude' - where: - $ref: '#/components/schemas/UserWhereUniqueInput' - create: - $ref: '#/components/schemas/UserCreateInput' - update: - $ref: '#/components/schemas/UserUpdateInput' - meta: - $ref: '#/components/schemas/_Meta' - UserDeleteUniqueArgs: - type: object - required: - - where - properties: - select: - $ref: '#/components/schemas/UserSelect' - include: - $ref: '#/components/schemas/UserInclude' - where: - $ref: '#/components/schemas/UserWhereUniqueInput' - meta: - $ref: '#/components/schemas/_Meta' - UserDeleteManyArgs: - type: object - properties: - where: - $ref: '#/components/schemas/UserWhereInput' - meta: - $ref: '#/components/schemas/_Meta' - UserCountArgs: - type: object - properties: - select: - $ref: '#/components/schemas/UserSelect' - where: - $ref: '#/components/schemas/UserWhereInput' - meta: - $ref: '#/components/schemas/_Meta' - UserAggregateArgs: - type: object - properties: - where: - $ref: '#/components/schemas/UserWhereInput' - orderBy: - $ref: '#/components/schemas/UserOrderByWithRelationInput' - cursor: - $ref: '#/components/schemas/UserWhereUniqueInput' - take: - type: integer - skip: - type: integer - _count: - oneOf: - - type: boolean - - $ref: '#/components/schemas/UserCountAggregateInput' - _min: - $ref: '#/components/schemas/UserMinAggregateInput' - _max: - $ref: '#/components/schemas/UserMaxAggregateInput' - meta: - $ref: '#/components/schemas/_Meta' - UserGroupByArgs: - type: object - properties: - where: - $ref: '#/components/schemas/UserWhereInput' - orderBy: - $ref: '#/components/schemas/UserOrderByWithRelationInput' - by: - $ref: '#/components/schemas/UserScalarFieldEnum' - having: - $ref: '#/components/schemas/UserScalarWhereWithAggregatesInput' - take: - type: integer - skip: - type: integer - _count: - oneOf: - - type: boolean - - $ref: '#/components/schemas/UserCountAggregateInput' - _min: - $ref: '#/components/schemas/UserMinAggregateInput' - _max: - $ref: '#/components/schemas/UserMaxAggregateInput' - meta: - $ref: '#/components/schemas/_Meta' - ProfileCreateArgs: - type: object - required: - - data - properties: - select: - $ref: '#/components/schemas/ProfileSelect' - include: - $ref: '#/components/schemas/ProfileInclude' - data: - $ref: '#/components/schemas/ProfileCreateInput' - meta: - $ref: '#/components/schemas/_Meta' - ProfileCreateManyArgs: - type: object - required: - - data - properties: - data: - oneOf: - - $ref: '#/components/schemas/ProfileCreateManyInput' - - type: array - items: - $ref: '#/components/schemas/ProfileCreateManyInput' - skipDuplicates: - type: boolean - description: Do not insert records with unique fields or ID fields that already - exist. - meta: - $ref: '#/components/schemas/_Meta' - ProfileFindUniqueArgs: - type: object - required: - - where - properties: - select: - $ref: '#/components/schemas/ProfileSelect' - include: - $ref: '#/components/schemas/ProfileInclude' - where: - $ref: '#/components/schemas/ProfileWhereUniqueInput' - meta: - $ref: '#/components/schemas/_Meta' - ProfileFindFirstArgs: - type: object - properties: - select: - $ref: '#/components/schemas/ProfileSelect' - include: - $ref: '#/components/schemas/ProfileInclude' - where: - $ref: '#/components/schemas/ProfileWhereInput' - meta: - $ref: '#/components/schemas/_Meta' - ProfileFindManyArgs: - type: object - properties: - select: - $ref: '#/components/schemas/ProfileSelect' - include: - $ref: '#/components/schemas/ProfileInclude' - where: - $ref: '#/components/schemas/ProfileWhereInput' - meta: - $ref: '#/components/schemas/_Meta' - orderBy: - oneOf: - - $ref: '#/components/schemas/ProfileOrderByWithRelationInput' - - type: array - items: - $ref: '#/components/schemas/ProfileOrderByWithRelationInput' - cursor: - $ref: '#/components/schemas/ProfileWhereUniqueInput' - take: - type: integer - skip: - type: integer - ProfileUpdateArgs: - type: object - required: - - where - - data - properties: - select: - $ref: '#/components/schemas/ProfileSelect' - include: - $ref: '#/components/schemas/ProfileInclude' - where: - $ref: '#/components/schemas/ProfileWhereUniqueInput' - data: - $ref: '#/components/schemas/ProfileUpdateInput' - meta: - $ref: '#/components/schemas/_Meta' - ProfileUpdateManyArgs: - type: object - required: - - data - properties: - where: - $ref: '#/components/schemas/ProfileWhereInput' - data: - $ref: '#/components/schemas/ProfileUpdateManyMutationInput' - meta: - $ref: '#/components/schemas/_Meta' - ProfileUpsertArgs: - type: object - required: - - create - - update - - where - properties: - select: - $ref: '#/components/schemas/ProfileSelect' - include: - $ref: '#/components/schemas/ProfileInclude' - where: - $ref: '#/components/schemas/ProfileWhereUniqueInput' - create: - $ref: '#/components/schemas/ProfileCreateInput' - update: - $ref: '#/components/schemas/ProfileUpdateInput' - meta: - $ref: '#/components/schemas/_Meta' - ProfileDeleteUniqueArgs: - type: object - required: - - where - properties: - select: - $ref: '#/components/schemas/ProfileSelect' - include: - $ref: '#/components/schemas/ProfileInclude' - where: - $ref: '#/components/schemas/ProfileWhereUniqueInput' - meta: - $ref: '#/components/schemas/_Meta' - ProfileDeleteManyArgs: - type: object - properties: - where: - $ref: '#/components/schemas/ProfileWhereInput' - meta: - $ref: '#/components/schemas/_Meta' - ProfileCountArgs: - type: object - properties: - select: - $ref: '#/components/schemas/ProfileSelect' - where: - $ref: '#/components/schemas/ProfileWhereInput' - meta: - $ref: '#/components/schemas/_Meta' - ProfileAggregateArgs: - type: object - properties: - where: - $ref: '#/components/schemas/ProfileWhereInput' - orderBy: - $ref: '#/components/schemas/ProfileOrderByWithRelationInput' - cursor: - $ref: '#/components/schemas/ProfileWhereUniqueInput' - take: - type: integer - skip: - type: integer - _count: - oneOf: - - type: boolean - - $ref: '#/components/schemas/ProfileCountAggregateInput' - _min: - $ref: '#/components/schemas/ProfileMinAggregateInput' - _max: - $ref: '#/components/schemas/ProfileMaxAggregateInput' - meta: - $ref: '#/components/schemas/_Meta' - ProfileGroupByArgs: - type: object - properties: - where: - $ref: '#/components/schemas/ProfileWhereInput' - orderBy: - $ref: '#/components/schemas/ProfileOrderByWithRelationInput' - by: - $ref: '#/components/schemas/ProfileScalarFieldEnum' - having: - $ref: '#/components/schemas/ProfileScalarWhereWithAggregatesInput' - take: - type: integer - skip: - type: integer - _count: - oneOf: - - type: boolean - - $ref: '#/components/schemas/ProfileCountAggregateInput' - _min: - $ref: '#/components/schemas/ProfileMinAggregateInput' - _max: - $ref: '#/components/schemas/ProfileMaxAggregateInput' - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemCreateArgs: - type: object - required: - - data - properties: - select: - $ref: '#/components/schemas/Post_ItemSelect' - include: - $ref: '#/components/schemas/Post_ItemInclude' - data: - $ref: '#/components/schemas/Post_ItemCreateInput' - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemCreateManyArgs: - type: object - required: - - data - properties: - data: - oneOf: - - $ref: '#/components/schemas/Post_ItemCreateManyInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemCreateManyInput' - skipDuplicates: - type: boolean - description: Do not insert records with unique fields or ID fields that already - exist. - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemFindUniqueArgs: - type: object - required: - - where - properties: - select: - $ref: '#/components/schemas/Post_ItemSelect' - include: - $ref: '#/components/schemas/Post_ItemInclude' - where: - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemFindFirstArgs: - type: object - properties: - select: - $ref: '#/components/schemas/Post_ItemSelect' - include: - $ref: '#/components/schemas/Post_ItemInclude' - where: - $ref: '#/components/schemas/Post_ItemWhereInput' - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemFindManyArgs: - type: object - properties: - select: - $ref: '#/components/schemas/Post_ItemSelect' - include: - $ref: '#/components/schemas/Post_ItemInclude' - where: - $ref: '#/components/schemas/Post_ItemWhereInput' - meta: - $ref: '#/components/schemas/_Meta' - orderBy: - oneOf: - - $ref: '#/components/schemas/Post_ItemOrderByWithRelationInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemOrderByWithRelationInput' - cursor: - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - take: - type: integer - skip: - type: integer - Post_ItemUpdateArgs: - type: object - required: - - where - - data - properties: - select: - $ref: '#/components/schemas/Post_ItemSelect' - include: - $ref: '#/components/schemas/Post_ItemInclude' - where: - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - data: - $ref: '#/components/schemas/Post_ItemUpdateInput' - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemUpdateManyArgs: - type: object - required: - - data - properties: - where: - $ref: '#/components/schemas/Post_ItemWhereInput' - data: - $ref: '#/components/schemas/Post_ItemUpdateManyMutationInput' - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemUpsertArgs: - type: object - required: - - create - - update - - where - properties: - select: - $ref: '#/components/schemas/Post_ItemSelect' - include: - $ref: '#/components/schemas/Post_ItemInclude' - where: - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - create: - $ref: '#/components/schemas/Post_ItemCreateInput' - update: - $ref: '#/components/schemas/Post_ItemUpdateInput' - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemDeleteUniqueArgs: - type: object - required: - - where - properties: - select: - $ref: '#/components/schemas/Post_ItemSelect' - include: - $ref: '#/components/schemas/Post_ItemInclude' - where: - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemDeleteManyArgs: - type: object - properties: - where: - $ref: '#/components/schemas/Post_ItemWhereInput' - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemCountArgs: - type: object - properties: - select: - $ref: '#/components/schemas/Post_ItemSelect' - where: - $ref: '#/components/schemas/Post_ItemWhereInput' - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemAggregateArgs: - type: object - properties: - where: - $ref: '#/components/schemas/Post_ItemWhereInput' - orderBy: - $ref: '#/components/schemas/Post_ItemOrderByWithRelationInput' - cursor: - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - take: - type: integer - skip: - type: integer - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemGroupByArgs: - type: object - properties: - where: - $ref: '#/components/schemas/Post_ItemWhereInput' - orderBy: - $ref: '#/components/schemas/Post_ItemOrderByWithRelationInput' - by: - $ref: '#/components/schemas/Post_ItemScalarFieldEnum' - having: - $ref: '#/components/schemas/Post_ItemScalarWhereWithAggregatesInput' - take: - type: integer - skip: - type: integer - meta: - $ref: '#/components/schemas/_Meta' -paths: - /user/create: - post: - operationId: createUser - description: Create a new User - tags: - - user - responses: - '201': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/User' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/UserCreateArgs' - /user/createMany: - post: - operationId: createManyUser - description: Create several User - tags: - - user - responses: - '201': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BatchPayload' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/UserCreateManyArgs' - /user/findUnique: - get: - operationId: findUniqueUser - description: Find one unique User - tags: - - user - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/User' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/UserFindUniqueArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /user/findFirst: - get: - operationId: findFirstUser - description: Find the first User matching the given condition - tags: - - user - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/User' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/UserFindFirstArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /user/findMany: - get: - operationId: findManyUser - description: Find users matching the given conditions - tags: - - user - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - type: array - items: - $ref: '#/components/schemas/User' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/UserFindManyArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /user/update: - patch: - operationId: updateUser - description: Update a User - tags: - - user - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/User' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/UserUpdateArgs' - /user/updateMany: - patch: - operationId: updateManyUser - description: Update Users matching the given condition - tags: - - user - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BatchPayload' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/UserUpdateManyArgs' - /user/upsert: - post: - operationId: upsertUser - description: Upsert a User - tags: - - user - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/User' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/UserUpsertArgs' - /user/dodelete: - put: - operationId: deleteUser - description: Delete a unique user - tags: - - delete - - user - summary: Delete a user yeah yeah - deprecated: true - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/User' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/UserDeleteUniqueArgs' - /user/deleteMany: - delete: - operationId: deleteManyUser - description: Delete Users matching the given condition - tags: - - user - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BatchPayload' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/UserDeleteManyArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /user/count: - get: - operationId: countUser - description: Find a list of User - tags: - - user - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - oneOf: - - type: integer - - $ref: '#/components/schemas/UserCountAggregateOutputType' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/UserCountArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /user/aggregate: - get: - operationId: aggregateUser - description: Aggregate Users - tags: - - user - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/AggregateUser' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/UserAggregateArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /user/groupBy: - get: - operationId: groupByUser - description: Group Users by fields - tags: - - user - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - type: array - items: - $ref: '#/components/schemas/UserGroupByOutputType' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/UserGroupByArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /profile/create: - post: - operationId: createProfile - description: Create a new Profile - tags: - - profile - responses: - '201': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Profile' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileCreateArgs' - /profile/createMany: - post: - operationId: createManyProfile - description: Create several Profile - tags: - - profile - responses: - '201': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BatchPayload' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileCreateManyArgs' - /profile/findUnique: - get: - operationId: findUniqueProfile - description: Find one unique Profile - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Profile' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileFindUniqueArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /profile/findFirst: - get: - operationId: findFirstProfile - description: Find the first Profile matching the given condition - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Profile' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileFindFirstArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /profile/findMany: - get: - operationId: findManyProfile - description: Find a list of Profile - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - type: array - items: - $ref: '#/components/schemas/Profile' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileFindManyArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /profile/update: - patch: - operationId: updateProfile - description: Update a Profile - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Profile' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileUpdateArgs' - /profile/updateMany: - patch: - operationId: updateManyProfile - description: Update Profiles matching the given condition - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BatchPayload' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileUpdateManyArgs' - /profile/upsert: - post: - operationId: upsertProfile - description: Upsert a Profile - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Profile' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileUpsertArgs' - /profile/delete: - delete: - operationId: deleteProfile - description: Delete one unique Profile - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Profile' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileDeleteUniqueArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /profile/deleteMany: - delete: - operationId: deleteManyProfile - description: Delete Profiles matching the given condition - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BatchPayload' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileDeleteManyArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /profile/count: - get: - operationId: countProfile - description: Find a list of Profile - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - oneOf: - - type: integer - - $ref: '#/components/schemas/ProfileCountAggregateOutputType' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileCountArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /profile/aggregate: - get: - operationId: aggregateProfile - description: Aggregate Profiles - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/AggregateProfile' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileAggregateArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /profile/groupBy: - get: - operationId: groupByProfile - description: Group Profiles by fields - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - type: array - items: - $ref: '#/components/schemas/ProfileGroupByOutputType' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileGroupByArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /post_Item/create: - post: - operationId: createPost_Item - description: Create a new Post_Item - tags: - - post_Item - responses: - '201': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Post_Item' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemCreateArgs' - /post_Item/createMany: - post: - operationId: createManyPost_Item - description: Create several Post_Item - tags: - - post_Item - responses: - '201': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BatchPayload' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemCreateManyArgs' - /post_Item/findUnique: - get: - operationId: findUniquePost_Item - description: Find one unique Post_Item - tags: - - post_Item - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Post_Item' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemFindUniqueArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /post_Item/findFirst: - get: - operationId: findFirstPost_Item - description: Find the first Post_Item matching the given condition - tags: - - post_Item - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Post_Item' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemFindFirstArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /post_Item/update: - patch: - operationId: updatePost_Item - description: Update a Post_Item - tags: - - post_Item - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Post_Item' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemUpdateArgs' - /post_Item/updateMany: - patch: - operationId: updateManyPost_Item - description: Update Post_Items matching the given condition - tags: - - post_Item - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BatchPayload' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemUpdateManyArgs' - /post_Item/upsert: - post: - operationId: upsertPost_Item - description: Upsert a Post_Item - tags: - - post_Item - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Post_Item' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemUpsertArgs' - /post_Item/delete: - delete: - operationId: deletePost_Item - description: Delete one unique Post_Item - tags: - - post_Item - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Post_Item' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemDeleteUniqueArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /post_Item/deleteMany: - delete: - operationId: deleteManyPost_Item - description: Delete Post_Items matching the given condition - tags: - - post_Item - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BatchPayload' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemDeleteManyArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /post_Item/count: - get: - operationId: countPost_Item - description: Find a list of Post_Item - tags: - - post_Item - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - oneOf: - - type: integer - - $ref: '#/components/schemas/Post_ItemCountAggregateOutputType' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemCountArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /post_Item/aggregate: - get: - operationId: aggregatePost_Item - description: Aggregate Post_Items - tags: - - post_Item - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/AggregatePost_Item' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemAggregateArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /post_Item/groupBy: - get: - operationId: groupByPost_Item - description: Group Post_Items by fields - tags: - - post_Item - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - type: array - items: - $ref: '#/components/schemas/Post_ItemGroupByOutputType' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemGroupByArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} diff --git a/packages/server/test/openapi/baseline/rpc-type-coverage-3.1.0.baseline.yaml b/packages/server/test/openapi/baseline/rpc-type-coverage-3.1.0.baseline.yaml deleted file mode 100644 index 5f3e59136..000000000 --- a/packages/server/test/openapi/baseline/rpc-type-coverage-3.1.0.baseline.yaml +++ /dev/null @@ -1,3174 +0,0 @@ -openapi: 3.1.0 -info: - title: ZenStack Generated API - version: 1.0.0 -tags: - - name: foo - description: Foo operations -components: - schemas: - FooScalarFieldEnum: - type: string - enum: - - id - - string - - int - - bigInt - - date - - float - - decimal - - boolean - - bytes - - json - - plainJson - SortOrder: - type: string - enum: - - asc - - desc - NullableJsonNullValueInput: - type: string - enum: - - DbNull - - JsonNull - JsonNullValueInput: - type: string - enum: - - JsonNull - QueryMode: - type: string - enum: - - default - - insensitive - JsonNullValueFilter: - type: string - enum: - - DbNull - - JsonNull - - AnyNull - NullsOrder: - type: string - enum: - - first - - last - Foo: - type: object - properties: - id: - type: string - string: - type: string - int: - type: integer - bigInt: - type: integer - date: - type: string - format: date-time - float: - type: number - decimal: - oneOf: - - type: string - - type: number - boolean: - type: boolean - bytes: - oneOf: - - type: 'null' - - type: string - format: byte - json: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Meta' - plainJson: {} - required: - - id - - string - - int - - bigInt - - date - - float - - decimal - - boolean - - plainJson - Meta: - type: object - description: The "Meta" TypeDef - properties: - something: - type: string - required: - - something - FooWhereInput: - type: object - properties: - AND: - oneOf: - - $ref: '#/components/schemas/FooWhereInput' - - type: array - items: - $ref: '#/components/schemas/FooWhereInput' - OR: - type: array - items: - $ref: '#/components/schemas/FooWhereInput' - NOT: - oneOf: - - $ref: '#/components/schemas/FooWhereInput' - - type: array - items: - $ref: '#/components/schemas/FooWhereInput' - id: - oneOf: - - $ref: '#/components/schemas/StringFilter' - - type: string - string: - oneOf: - - $ref: '#/components/schemas/StringFilter' - - type: string - int: - oneOf: - - $ref: '#/components/schemas/IntFilter' - - type: integer - bigInt: - oneOf: - - $ref: '#/components/schemas/BigIntFilter' - - type: integer - date: - oneOf: - - $ref: '#/components/schemas/DateTimeFilter' - - type: string - format: date-time - float: - oneOf: - - $ref: '#/components/schemas/FloatFilter' - - type: number - decimal: - oneOf: - - $ref: '#/components/schemas/DecimalFilter' - - oneOf: - - type: string - - type: number - boolean: - oneOf: - - $ref: '#/components/schemas/BoolFilter' - - type: boolean - bytes: - oneOf: - - $ref: '#/components/schemas/BytesNullableFilter' - - type: string - format: byte - - type: 'null' - json: - $ref: '#/components/schemas/JsonNullableFilter' - plainJson: - $ref: '#/components/schemas/JsonFilter' - FooOrderByWithRelationInput: - type: object - properties: - id: - $ref: '#/components/schemas/SortOrder' - string: - $ref: '#/components/schemas/SortOrder' - int: - $ref: '#/components/schemas/SortOrder' - bigInt: - $ref: '#/components/schemas/SortOrder' - date: - $ref: '#/components/schemas/SortOrder' - float: - $ref: '#/components/schemas/SortOrder' - decimal: - $ref: '#/components/schemas/SortOrder' - boolean: - $ref: '#/components/schemas/SortOrder' - bytes: - oneOf: - - $ref: '#/components/schemas/SortOrder' - - $ref: '#/components/schemas/SortOrderInput' - json: - oneOf: - - $ref: '#/components/schemas/SortOrder' - - $ref: '#/components/schemas/SortOrderInput' - plainJson: - $ref: '#/components/schemas/SortOrder' - FooWhereUniqueInput: - type: object - properties: - id: - type: string - AND: - oneOf: - - $ref: '#/components/schemas/FooWhereInput' - - type: array - items: - $ref: '#/components/schemas/FooWhereInput' - OR: - type: array - items: - $ref: '#/components/schemas/FooWhereInput' - NOT: - oneOf: - - $ref: '#/components/schemas/FooWhereInput' - - type: array - items: - $ref: '#/components/schemas/FooWhereInput' - string: - oneOf: - - $ref: '#/components/schemas/StringFilter' - - type: string - int: - oneOf: - - $ref: '#/components/schemas/IntFilter' - - type: integer - bigInt: - oneOf: - - $ref: '#/components/schemas/BigIntFilter' - - type: integer - date: - oneOf: - - $ref: '#/components/schemas/DateTimeFilter' - - type: string - format: date-time - float: - oneOf: - - $ref: '#/components/schemas/FloatFilter' - - type: number - decimal: - oneOf: - - $ref: '#/components/schemas/DecimalFilter' - - oneOf: - - type: string - - type: number - boolean: - oneOf: - - $ref: '#/components/schemas/BoolFilter' - - type: boolean - bytes: - oneOf: - - $ref: '#/components/schemas/BytesNullableFilter' - - type: string - format: byte - - type: 'null' - json: - $ref: '#/components/schemas/JsonNullableFilter' - plainJson: - $ref: '#/components/schemas/JsonFilter' - FooScalarWhereWithAggregatesInput: - type: object - properties: - AND: - oneOf: - - $ref: '#/components/schemas/FooScalarWhereWithAggregatesInput' - - type: array - items: - $ref: '#/components/schemas/FooScalarWhereWithAggregatesInput' - OR: - type: array - items: - $ref: '#/components/schemas/FooScalarWhereWithAggregatesInput' - NOT: - oneOf: - - $ref: '#/components/schemas/FooScalarWhereWithAggregatesInput' - - type: array - items: - $ref: '#/components/schemas/FooScalarWhereWithAggregatesInput' - id: - oneOf: - - $ref: '#/components/schemas/StringWithAggregatesFilter' - - type: string - string: - oneOf: - - $ref: '#/components/schemas/StringWithAggregatesFilter' - - type: string - int: - oneOf: - - $ref: '#/components/schemas/IntWithAggregatesFilter' - - type: integer - bigInt: - oneOf: - - $ref: '#/components/schemas/BigIntWithAggregatesFilter' - - type: integer - date: - oneOf: - - $ref: '#/components/schemas/DateTimeWithAggregatesFilter' - - type: string - format: date-time - float: - oneOf: - - $ref: '#/components/schemas/FloatWithAggregatesFilter' - - type: number - decimal: - oneOf: - - $ref: '#/components/schemas/DecimalWithAggregatesFilter' - - oneOf: - - type: string - - type: number - boolean: - oneOf: - - $ref: '#/components/schemas/BoolWithAggregatesFilter' - - type: boolean - bytes: - oneOf: - - $ref: '#/components/schemas/BytesNullableWithAggregatesFilter' - - type: string - format: byte - - type: 'null' - json: - $ref: '#/components/schemas/JsonNullableWithAggregatesFilter' - plainJson: - $ref: '#/components/schemas/JsonWithAggregatesFilter' - FooCreateInput: - type: object - properties: - id: - type: string - string: - type: string - int: - type: integer - bigInt: - type: integer - date: - type: string - format: date-time - float: - type: number - decimal: - oneOf: - - type: string - - type: number - boolean: - type: boolean - bytes: - oneOf: - - type: 'null' - - type: string - format: byte - json: - oneOf: - - $ref: '#/components/schemas/NullableJsonNullValueInput' - - {} - plainJson: - oneOf: - - $ref: '#/components/schemas/JsonNullValueInput' - - {} - required: - - string - - int - - bigInt - - date - - float - - decimal - - boolean - - plainJson - FooUpdateInput: - type: object - properties: - id: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - string: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - int: - oneOf: - - type: integer - - $ref: '#/components/schemas/IntFieldUpdateOperationsInput' - bigInt: - oneOf: - - type: integer - - $ref: '#/components/schemas/BigIntFieldUpdateOperationsInput' - date: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - float: - oneOf: - - type: number - - $ref: '#/components/schemas/FloatFieldUpdateOperationsInput' - decimal: - oneOf: - - oneOf: - - type: string - - type: number - - $ref: '#/components/schemas/DecimalFieldUpdateOperationsInput' - boolean: - oneOf: - - type: boolean - - $ref: '#/components/schemas/BoolFieldUpdateOperationsInput' - bytes: - oneOf: - - type: string - format: byte - - $ref: '#/components/schemas/NullableBytesFieldUpdateOperationsInput' - - type: 'null' - json: - oneOf: - - $ref: '#/components/schemas/NullableJsonNullValueInput' - - {} - plainJson: - oneOf: - - $ref: '#/components/schemas/JsonNullValueInput' - - {} - FooCreateManyInput: - type: object - properties: - id: - type: string - string: - type: string - int: - type: integer - bigInt: - type: integer - date: - type: string - format: date-time - float: - type: number - decimal: - oneOf: - - type: string - - type: number - boolean: - type: boolean - bytes: - oneOf: - - type: 'null' - - type: string - format: byte - json: - oneOf: - - $ref: '#/components/schemas/NullableJsonNullValueInput' - - {} - plainJson: - oneOf: - - $ref: '#/components/schemas/JsonNullValueInput' - - {} - required: - - string - - int - - bigInt - - date - - float - - decimal - - boolean - - plainJson - FooUpdateManyMutationInput: - type: object - properties: - id: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - string: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - int: - oneOf: - - type: integer - - $ref: '#/components/schemas/IntFieldUpdateOperationsInput' - bigInt: - oneOf: - - type: integer - - $ref: '#/components/schemas/BigIntFieldUpdateOperationsInput' - date: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - float: - oneOf: - - type: number - - $ref: '#/components/schemas/FloatFieldUpdateOperationsInput' - decimal: - oneOf: - - oneOf: - - type: string - - type: number - - $ref: '#/components/schemas/DecimalFieldUpdateOperationsInput' - boolean: - oneOf: - - type: boolean - - $ref: '#/components/schemas/BoolFieldUpdateOperationsInput' - bytes: - oneOf: - - type: string - format: byte - - $ref: '#/components/schemas/NullableBytesFieldUpdateOperationsInput' - - type: 'null' - json: - oneOf: - - $ref: '#/components/schemas/NullableJsonNullValueInput' - - {} - plainJson: - oneOf: - - $ref: '#/components/schemas/JsonNullValueInput' - - {} - StringFilter: - type: object - properties: - equals: - type: string - in: - type: array - items: - type: string - notIn: - type: array - items: - type: string - lt: - type: string - lte: - type: string - gt: - type: string - gte: - type: string - contains: - type: string - startsWith: - type: string - endsWith: - type: string - mode: - $ref: '#/components/schemas/QueryMode' - not: - oneOf: - - type: string - - $ref: '#/components/schemas/NestedStringFilter' - IntFilter: - type: object - properties: - equals: - type: integer - in: - type: array - items: - type: integer - notIn: - type: array - items: - type: integer - lt: - type: integer - lte: - type: integer - gt: - type: integer - gte: - type: integer - not: - oneOf: - - type: integer - - $ref: '#/components/schemas/NestedIntFilter' - BigIntFilter: - type: object - properties: - equals: - type: integer - in: - type: array - items: - type: integer - notIn: - type: array - items: - type: integer - lt: - type: integer - lte: - type: integer - gt: - type: integer - gte: - type: integer - not: - oneOf: - - type: integer - - $ref: '#/components/schemas/NestedBigIntFilter' - DateTimeFilter: - type: object - properties: - equals: - type: string - format: date-time - in: - type: array - items: - type: string - format: date-time - notIn: - type: array - items: - type: string - format: date-time - lt: - type: string - format: date-time - lte: - type: string - format: date-time - gt: - type: string - format: date-time - gte: - type: string - format: date-time - not: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/NestedDateTimeFilter' - FloatFilter: - type: object - properties: - equals: - type: number - in: - type: array - items: - type: number - notIn: - type: array - items: - type: number - lt: - type: number - lte: - type: number - gt: - type: number - gte: - type: number - not: - oneOf: - - type: number - - $ref: '#/components/schemas/NestedFloatFilter' - DecimalFilter: - type: object - properties: - equals: - oneOf: - - type: string - - type: number - in: - type: array - items: - oneOf: - - type: string - - type: number - notIn: - type: array - items: - oneOf: - - type: string - - type: number - lt: - oneOf: - - type: string - - type: number - lte: - oneOf: - - type: string - - type: number - gt: - oneOf: - - type: string - - type: number - gte: - oneOf: - - type: string - - type: number - not: - oneOf: - - oneOf: - - type: string - - type: number - - $ref: '#/components/schemas/NestedDecimalFilter' - BoolFilter: - type: object - properties: - equals: - type: boolean - not: - oneOf: - - type: boolean - - $ref: '#/components/schemas/NestedBoolFilter' - BytesNullableFilter: - type: object - properties: - equals: - oneOf: - - type: 'null' - - type: string - format: byte - in: - oneOf: - - type: 'null' - - type: array - items: - type: string - format: byte - notIn: - oneOf: - - type: 'null' - - type: array - items: - type: string - format: byte - not: - oneOf: - - type: string - format: byte - - $ref: '#/components/schemas/NestedBytesNullableFilter' - - type: 'null' - JsonNullableFilter: - type: object - properties: - equals: - oneOf: - - {} - - $ref: '#/components/schemas/JsonNullValueFilter' - path: - type: array - items: - type: string - mode: - $ref: '#/components/schemas/QueryMode' - string_contains: - type: string - string_starts_with: - type: string - string_ends_with: - type: string - array_starts_with: - oneOf: - - type: 'null' - - {} - array_ends_with: - oneOf: - - type: 'null' - - {} - array_contains: - oneOf: - - type: 'null' - - {} - lt: {} - lte: {} - gt: {} - gte: {} - not: - oneOf: - - {} - - $ref: '#/components/schemas/JsonNullValueFilter' - JsonFilter: - type: object - properties: - equals: - oneOf: - - {} - - $ref: '#/components/schemas/JsonNullValueFilter' - path: - type: array - items: - type: string - mode: - $ref: '#/components/schemas/QueryMode' - string_contains: - type: string - string_starts_with: - type: string - string_ends_with: - type: string - array_starts_with: - oneOf: - - type: 'null' - - {} - array_ends_with: - oneOf: - - type: 'null' - - {} - array_contains: - oneOf: - - type: 'null' - - {} - lt: {} - lte: {} - gt: {} - gte: {} - not: - oneOf: - - {} - - $ref: '#/components/schemas/JsonNullValueFilter' - SortOrderInput: - type: object - properties: - sort: - $ref: '#/components/schemas/SortOrder' - nulls: - $ref: '#/components/schemas/NullsOrder' - required: - - sort - StringWithAggregatesFilter: - type: object - properties: - equals: - type: string - in: - type: array - items: - type: string - notIn: - type: array - items: - type: string - lt: - type: string - lte: - type: string - gt: - type: string - gte: - type: string - contains: - type: string - startsWith: - type: string - endsWith: - type: string - mode: - $ref: '#/components/schemas/QueryMode' - not: - oneOf: - - type: string - - $ref: '#/components/schemas/NestedStringWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _min: - $ref: '#/components/schemas/NestedStringFilter' - _max: - $ref: '#/components/schemas/NestedStringFilter' - IntWithAggregatesFilter: - type: object - properties: - equals: - type: integer - in: - type: array - items: - type: integer - notIn: - type: array - items: - type: integer - lt: - type: integer - lte: - type: integer - gt: - type: integer - gte: - type: integer - not: - oneOf: - - type: integer - - $ref: '#/components/schemas/NestedIntWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _avg: - $ref: '#/components/schemas/NestedFloatFilter' - _sum: - $ref: '#/components/schemas/NestedIntFilter' - _min: - $ref: '#/components/schemas/NestedIntFilter' - _max: - $ref: '#/components/schemas/NestedIntFilter' - BigIntWithAggregatesFilter: - type: object - properties: - equals: - type: integer - in: - type: array - items: - type: integer - notIn: - type: array - items: - type: integer - lt: - type: integer - lte: - type: integer - gt: - type: integer - gte: - type: integer - not: - oneOf: - - type: integer - - $ref: '#/components/schemas/NestedBigIntWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _avg: - $ref: '#/components/schemas/NestedFloatFilter' - _sum: - $ref: '#/components/schemas/NestedBigIntFilter' - _min: - $ref: '#/components/schemas/NestedBigIntFilter' - _max: - $ref: '#/components/schemas/NestedBigIntFilter' - DateTimeWithAggregatesFilter: - type: object - properties: - equals: - type: string - format: date-time - in: - type: array - items: - type: string - format: date-time - notIn: - type: array - items: - type: string - format: date-time - lt: - type: string - format: date-time - lte: - type: string - format: date-time - gt: - type: string - format: date-time - gte: - type: string - format: date-time - not: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/NestedDateTimeWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _min: - $ref: '#/components/schemas/NestedDateTimeFilter' - _max: - $ref: '#/components/schemas/NestedDateTimeFilter' - FloatWithAggregatesFilter: - type: object - properties: - equals: - type: number - in: - type: array - items: - type: number - notIn: - type: array - items: - type: number - lt: - type: number - lte: - type: number - gt: - type: number - gte: - type: number - not: - oneOf: - - type: number - - $ref: '#/components/schemas/NestedFloatWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _avg: - $ref: '#/components/schemas/NestedFloatFilter' - _sum: - $ref: '#/components/schemas/NestedFloatFilter' - _min: - $ref: '#/components/schemas/NestedFloatFilter' - _max: - $ref: '#/components/schemas/NestedFloatFilter' - DecimalWithAggregatesFilter: - type: object - properties: - equals: - oneOf: - - type: string - - type: number - in: - type: array - items: - oneOf: - - type: string - - type: number - notIn: - type: array - items: - oneOf: - - type: string - - type: number - lt: - oneOf: - - type: string - - type: number - lte: - oneOf: - - type: string - - type: number - gt: - oneOf: - - type: string - - type: number - gte: - oneOf: - - type: string - - type: number - not: - oneOf: - - oneOf: - - type: string - - type: number - - $ref: '#/components/schemas/NestedDecimalWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _avg: - $ref: '#/components/schemas/NestedDecimalFilter' - _sum: - $ref: '#/components/schemas/NestedDecimalFilter' - _min: - $ref: '#/components/schemas/NestedDecimalFilter' - _max: - $ref: '#/components/schemas/NestedDecimalFilter' - BoolWithAggregatesFilter: - type: object - properties: - equals: - type: boolean - not: - oneOf: - - type: boolean - - $ref: '#/components/schemas/NestedBoolWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _min: - $ref: '#/components/schemas/NestedBoolFilter' - _max: - $ref: '#/components/schemas/NestedBoolFilter' - BytesNullableWithAggregatesFilter: - type: object - properties: - equals: - oneOf: - - type: 'null' - - type: string - format: byte - in: - oneOf: - - type: 'null' - - type: array - items: - type: string - format: byte - notIn: - oneOf: - - type: 'null' - - type: array - items: - type: string - format: byte - not: - oneOf: - - type: string - format: byte - - $ref: '#/components/schemas/NestedBytesNullableWithAggregatesFilter' - - type: 'null' - _count: - $ref: '#/components/schemas/NestedIntNullableFilter' - _min: - $ref: '#/components/schemas/NestedBytesNullableFilter' - _max: - $ref: '#/components/schemas/NestedBytesNullableFilter' - JsonNullableWithAggregatesFilter: - type: object - properties: - equals: - oneOf: - - {} - - $ref: '#/components/schemas/JsonNullValueFilter' - path: - type: array - items: - type: string - mode: - $ref: '#/components/schemas/QueryMode' - string_contains: - type: string - string_starts_with: - type: string - string_ends_with: - type: string - array_starts_with: - oneOf: - - type: 'null' - - {} - array_ends_with: - oneOf: - - type: 'null' - - {} - array_contains: - oneOf: - - type: 'null' - - {} - lt: {} - lte: {} - gt: {} - gte: {} - not: - oneOf: - - {} - - $ref: '#/components/schemas/JsonNullValueFilter' - _count: - $ref: '#/components/schemas/NestedIntNullableFilter' - _min: - $ref: '#/components/schemas/NestedJsonNullableFilter' - _max: - $ref: '#/components/schemas/NestedJsonNullableFilter' - JsonWithAggregatesFilter: - type: object - properties: - equals: - oneOf: - - {} - - $ref: '#/components/schemas/JsonNullValueFilter' - path: - type: array - items: - type: string - mode: - $ref: '#/components/schemas/QueryMode' - string_contains: - type: string - string_starts_with: - type: string - string_ends_with: - type: string - array_starts_with: - oneOf: - - type: 'null' - - {} - array_ends_with: - oneOf: - - type: 'null' - - {} - array_contains: - oneOf: - - type: 'null' - - {} - lt: {} - lte: {} - gt: {} - gte: {} - not: - oneOf: - - {} - - $ref: '#/components/schemas/JsonNullValueFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _min: - $ref: '#/components/schemas/NestedJsonFilter' - _max: - $ref: '#/components/schemas/NestedJsonFilter' - StringFieldUpdateOperationsInput: - type: object - properties: - set: - type: string - IntFieldUpdateOperationsInput: - type: object - properties: - set: - type: integer - increment: - type: integer - decrement: - type: integer - multiply: - type: integer - divide: - type: integer - BigIntFieldUpdateOperationsInput: - type: object - properties: - set: - type: integer - increment: - type: integer - decrement: - type: integer - multiply: - type: integer - divide: - type: integer - DateTimeFieldUpdateOperationsInput: - type: object - properties: - set: - type: string - format: date-time - FloatFieldUpdateOperationsInput: - type: object - properties: - set: - type: number - increment: - type: number - decrement: - type: number - multiply: - type: number - divide: - type: number - DecimalFieldUpdateOperationsInput: - type: object - properties: - set: - oneOf: - - type: string - - type: number - increment: - oneOf: - - type: string - - type: number - decrement: - oneOf: - - type: string - - type: number - multiply: - oneOf: - - type: string - - type: number - divide: - oneOf: - - type: string - - type: number - BoolFieldUpdateOperationsInput: - type: object - properties: - set: - type: boolean - NullableBytesFieldUpdateOperationsInput: - type: object - properties: - set: - oneOf: - - type: 'null' - - type: string - format: byte - NestedStringFilter: - type: object - properties: - equals: - type: string - in: - type: array - items: - type: string - notIn: - type: array - items: - type: string - lt: - type: string - lte: - type: string - gt: - type: string - gte: - type: string - contains: - type: string - startsWith: - type: string - endsWith: - type: string - not: - oneOf: - - type: string - - $ref: '#/components/schemas/NestedStringFilter' - NestedIntFilter: - type: object - properties: - equals: - type: integer - in: - type: array - items: - type: integer - notIn: - type: array - items: - type: integer - lt: - type: integer - lte: - type: integer - gt: - type: integer - gte: - type: integer - not: - oneOf: - - type: integer - - $ref: '#/components/schemas/NestedIntFilter' - NestedBigIntFilter: - type: object - properties: - equals: - type: integer - in: - type: array - items: - type: integer - notIn: - type: array - items: - type: integer - lt: - type: integer - lte: - type: integer - gt: - type: integer - gte: - type: integer - not: - oneOf: - - type: integer - - $ref: '#/components/schemas/NestedBigIntFilter' - NestedDateTimeFilter: - type: object - properties: - equals: - type: string - format: date-time - in: - type: array - items: - type: string - format: date-time - notIn: - type: array - items: - type: string - format: date-time - lt: - type: string - format: date-time - lte: - type: string - format: date-time - gt: - type: string - format: date-time - gte: - type: string - format: date-time - not: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/NestedDateTimeFilter' - NestedFloatFilter: - type: object - properties: - equals: - type: number - in: - type: array - items: - type: number - notIn: - type: array - items: - type: number - lt: - type: number - lte: - type: number - gt: - type: number - gte: - type: number - not: - oneOf: - - type: number - - $ref: '#/components/schemas/NestedFloatFilter' - NestedDecimalFilter: - type: object - properties: - equals: - oneOf: - - type: string - - type: number - in: - type: array - items: - oneOf: - - type: string - - type: number - notIn: - type: array - items: - oneOf: - - type: string - - type: number - lt: - oneOf: - - type: string - - type: number - lte: - oneOf: - - type: string - - type: number - gt: - oneOf: - - type: string - - type: number - gte: - oneOf: - - type: string - - type: number - not: - oneOf: - - oneOf: - - type: string - - type: number - - $ref: '#/components/schemas/NestedDecimalFilter' - NestedBoolFilter: - type: object - properties: - equals: - type: boolean - not: - oneOf: - - type: boolean - - $ref: '#/components/schemas/NestedBoolFilter' - NestedBytesNullableFilter: - type: object - properties: - equals: - oneOf: - - type: 'null' - - type: string - format: byte - in: - oneOf: - - type: 'null' - - type: array - items: - type: string - format: byte - notIn: - oneOf: - - type: 'null' - - type: array - items: - type: string - format: byte - not: - oneOf: - - type: string - format: byte - - $ref: '#/components/schemas/NestedBytesNullableFilter' - - type: 'null' - NestedStringWithAggregatesFilter: - type: object - properties: - equals: - type: string - in: - type: array - items: - type: string - notIn: - type: array - items: - type: string - lt: - type: string - lte: - type: string - gt: - type: string - gte: - type: string - contains: - type: string - startsWith: - type: string - endsWith: - type: string - not: - oneOf: - - type: string - - $ref: '#/components/schemas/NestedStringWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _min: - $ref: '#/components/schemas/NestedStringFilter' - _max: - $ref: '#/components/schemas/NestedStringFilter' - NestedIntWithAggregatesFilter: - type: object - properties: - equals: - type: integer - in: - type: array - items: - type: integer - notIn: - type: array - items: - type: integer - lt: - type: integer - lte: - type: integer - gt: - type: integer - gte: - type: integer - not: - oneOf: - - type: integer - - $ref: '#/components/schemas/NestedIntWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _avg: - $ref: '#/components/schemas/NestedFloatFilter' - _sum: - $ref: '#/components/schemas/NestedIntFilter' - _min: - $ref: '#/components/schemas/NestedIntFilter' - _max: - $ref: '#/components/schemas/NestedIntFilter' - NestedBigIntWithAggregatesFilter: - type: object - properties: - equals: - type: integer - in: - type: array - items: - type: integer - notIn: - type: array - items: - type: integer - lt: - type: integer - lte: - type: integer - gt: - type: integer - gte: - type: integer - not: - oneOf: - - type: integer - - $ref: '#/components/schemas/NestedBigIntWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _avg: - $ref: '#/components/schemas/NestedFloatFilter' - _sum: - $ref: '#/components/schemas/NestedBigIntFilter' - _min: - $ref: '#/components/schemas/NestedBigIntFilter' - _max: - $ref: '#/components/schemas/NestedBigIntFilter' - NestedDateTimeWithAggregatesFilter: - type: object - properties: - equals: - type: string - format: date-time - in: - type: array - items: - type: string - format: date-time - notIn: - type: array - items: - type: string - format: date-time - lt: - type: string - format: date-time - lte: - type: string - format: date-time - gt: - type: string - format: date-time - gte: - type: string - format: date-time - not: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/NestedDateTimeWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _min: - $ref: '#/components/schemas/NestedDateTimeFilter' - _max: - $ref: '#/components/schemas/NestedDateTimeFilter' - NestedFloatWithAggregatesFilter: - type: object - properties: - equals: - type: number - in: - type: array - items: - type: number - notIn: - type: array - items: - type: number - lt: - type: number - lte: - type: number - gt: - type: number - gte: - type: number - not: - oneOf: - - type: number - - $ref: '#/components/schemas/NestedFloatWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _avg: - $ref: '#/components/schemas/NestedFloatFilter' - _sum: - $ref: '#/components/schemas/NestedFloatFilter' - _min: - $ref: '#/components/schemas/NestedFloatFilter' - _max: - $ref: '#/components/schemas/NestedFloatFilter' - NestedDecimalWithAggregatesFilter: - type: object - properties: - equals: - oneOf: - - type: string - - type: number - in: - type: array - items: - oneOf: - - type: string - - type: number - notIn: - type: array - items: - oneOf: - - type: string - - type: number - lt: - oneOf: - - type: string - - type: number - lte: - oneOf: - - type: string - - type: number - gt: - oneOf: - - type: string - - type: number - gte: - oneOf: - - type: string - - type: number - not: - oneOf: - - oneOf: - - type: string - - type: number - - $ref: '#/components/schemas/NestedDecimalWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _avg: - $ref: '#/components/schemas/NestedDecimalFilter' - _sum: - $ref: '#/components/schemas/NestedDecimalFilter' - _min: - $ref: '#/components/schemas/NestedDecimalFilter' - _max: - $ref: '#/components/schemas/NestedDecimalFilter' - NestedBoolWithAggregatesFilter: - type: object - properties: - equals: - type: boolean - not: - oneOf: - - type: boolean - - $ref: '#/components/schemas/NestedBoolWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _min: - $ref: '#/components/schemas/NestedBoolFilter' - _max: - $ref: '#/components/schemas/NestedBoolFilter' - NestedBytesNullableWithAggregatesFilter: - type: object - properties: - equals: - oneOf: - - type: 'null' - - type: string - format: byte - in: - oneOf: - - type: 'null' - - type: array - items: - type: string - format: byte - notIn: - oneOf: - - type: 'null' - - type: array - items: - type: string - format: byte - not: - oneOf: - - type: string - format: byte - - $ref: '#/components/schemas/NestedBytesNullableWithAggregatesFilter' - - type: 'null' - _count: - $ref: '#/components/schemas/NestedIntNullableFilter' - _min: - $ref: '#/components/schemas/NestedBytesNullableFilter' - _max: - $ref: '#/components/schemas/NestedBytesNullableFilter' - NestedIntNullableFilter: - type: object - properties: - equals: - oneOf: - - type: 'null' - - type: integer - in: - oneOf: - - type: 'null' - - type: array - items: - type: integer - notIn: - oneOf: - - type: 'null' - - type: array - items: - type: integer - lt: - type: integer - lte: - type: integer - gt: - type: integer - gte: - type: integer - not: - oneOf: - - type: integer - - $ref: '#/components/schemas/NestedIntNullableFilter' - - type: 'null' - NestedJsonNullableFilter: - type: object - properties: - equals: - oneOf: - - {} - - $ref: '#/components/schemas/JsonNullValueFilter' - path: - type: array - items: - type: string - mode: - $ref: '#/components/schemas/QueryMode' - string_contains: - type: string - string_starts_with: - type: string - string_ends_with: - type: string - array_starts_with: - oneOf: - - type: 'null' - - {} - array_ends_with: - oneOf: - - type: 'null' - - {} - array_contains: - oneOf: - - type: 'null' - - {} - lt: {} - lte: {} - gt: {} - gte: {} - not: - oneOf: - - {} - - $ref: '#/components/schemas/JsonNullValueFilter' - NestedJsonFilter: - type: object - properties: - equals: - oneOf: - - {} - - $ref: '#/components/schemas/JsonNullValueFilter' - path: - type: array - items: - type: string - mode: - $ref: '#/components/schemas/QueryMode' - string_contains: - type: string - string_starts_with: - type: string - string_ends_with: - type: string - array_starts_with: - oneOf: - - type: 'null' - - {} - array_ends_with: - oneOf: - - type: 'null' - - {} - array_contains: - oneOf: - - type: 'null' - - {} - lt: {} - lte: {} - gt: {} - gte: {} - not: - oneOf: - - {} - - $ref: '#/components/schemas/JsonNullValueFilter' - FooSelect: - type: object - properties: - id: - type: boolean - string: - type: boolean - int: - type: boolean - bigInt: - type: boolean - date: - type: boolean - float: - type: boolean - decimal: - type: boolean - boolean: - type: boolean - bytes: - type: boolean - json: - type: boolean - plainJson: - type: boolean - FooCountAggregateInput: - type: object - properties: - id: - type: boolean - string: - type: boolean - int: - type: boolean - bigInt: - type: boolean - date: - type: boolean - float: - type: boolean - decimal: - type: boolean - boolean: - type: boolean - bytes: - type: boolean - json: - type: boolean - plainJson: - type: boolean - _all: - type: boolean - FooAvgAggregateInput: - type: object - properties: - int: - type: boolean - bigInt: - type: boolean - float: - type: boolean - decimal: - type: boolean - FooSumAggregateInput: - type: object - properties: - int: - type: boolean - bigInt: - type: boolean - float: - type: boolean - decimal: - type: boolean - FooMinAggregateInput: - type: object - properties: - id: - type: boolean - string: - type: boolean - int: - type: boolean - bigInt: - type: boolean - date: - type: boolean - float: - type: boolean - decimal: - type: boolean - boolean: - type: boolean - bytes: - type: boolean - FooMaxAggregateInput: - type: object - properties: - id: - type: boolean - string: - type: boolean - int: - type: boolean - bigInt: - type: boolean - date: - type: boolean - float: - type: boolean - decimal: - type: boolean - boolean: - type: boolean - bytes: - type: boolean - AggregateFoo: - type: object - properties: - _count: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/FooCountAggregateOutputType' - _avg: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/FooAvgAggregateOutputType' - _sum: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/FooSumAggregateOutputType' - _min: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/FooMinAggregateOutputType' - _max: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/FooMaxAggregateOutputType' - FooGroupByOutputType: - type: object - properties: - id: - type: string - string: - type: string - int: - type: integer - bigInt: - type: integer - date: - type: string - format: date-time - float: - type: number - decimal: - oneOf: - - type: string - - type: number - boolean: - type: boolean - bytes: - oneOf: - - type: 'null' - - type: string - format: byte - json: - oneOf: - - type: 'null' - - {} - plainJson: {} - _count: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/FooCountAggregateOutputType' - _avg: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/FooAvgAggregateOutputType' - _sum: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/FooSumAggregateOutputType' - _min: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/FooMinAggregateOutputType' - _max: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/FooMaxAggregateOutputType' - required: - - id - - string - - int - - bigInt - - date - - float - - decimal - - boolean - - plainJson - FooCountAggregateOutputType: - type: object - properties: - id: - type: integer - string: - type: integer - int: - type: integer - bigInt: - type: integer - date: - type: integer - float: - type: integer - decimal: - type: integer - boolean: - type: integer - bytes: - type: integer - json: - type: integer - plainJson: - type: integer - _all: - type: integer - required: - - id - - string - - int - - bigInt - - date - - float - - decimal - - boolean - - bytes - - json - - plainJson - - _all - FooAvgAggregateOutputType: - type: object - properties: - int: - oneOf: - - type: 'null' - - type: number - bigInt: - oneOf: - - type: 'null' - - type: number - float: - oneOf: - - type: 'null' - - type: number - decimal: - oneOf: - - type: string - - type: number - - type: 'null' - FooSumAggregateOutputType: - type: object - properties: - int: - oneOf: - - type: 'null' - - type: integer - bigInt: - oneOf: - - type: 'null' - - type: integer - float: - oneOf: - - type: 'null' - - type: number - decimal: - oneOf: - - type: string - - type: number - - type: 'null' - FooMinAggregateOutputType: - type: object - properties: - id: - oneOf: - - type: 'null' - - type: string - string: - oneOf: - - type: 'null' - - type: string - int: - oneOf: - - type: 'null' - - type: integer - bigInt: - oneOf: - - type: 'null' - - type: integer - date: - oneOf: - - type: 'null' - - type: string - format: date-time - float: - oneOf: - - type: 'null' - - type: number - decimal: - oneOf: - - type: string - - type: number - - type: 'null' - boolean: - oneOf: - - type: 'null' - - type: boolean - bytes: - oneOf: - - type: 'null' - - type: string - format: byte - FooMaxAggregateOutputType: - type: object - properties: - id: - oneOf: - - type: 'null' - - type: string - string: - oneOf: - - type: 'null' - - type: string - int: - oneOf: - - type: 'null' - - type: integer - bigInt: - oneOf: - - type: 'null' - - type: integer - date: - oneOf: - - type: 'null' - - type: string - format: date-time - float: - oneOf: - - type: 'null' - - type: number - decimal: - oneOf: - - type: string - - type: number - - type: 'null' - boolean: - oneOf: - - type: 'null' - - type: boolean - bytes: - oneOf: - - type: 'null' - - type: string - format: byte - _Meta: - type: object - description: Meta information about the request or response - properties: - serialization: - description: Serialization metadata - additionalProperties: true - _Error: - type: object - required: - - error - properties: - error: - type: object - required: - - message - properties: - prisma: - type: boolean - description: Indicates if the error occurred during a Prisma call - rejectedByPolicy: - type: boolean - description: Indicates if the error was due to rejection by a policy - code: - type: string - description: Prisma error code. Only available when "prisma" field is true. - message: - type: string - description: Error message - reason: - type: string - description: Detailed error reason - zodErrors: - type: object - additionalProperties: true - description: Zod validation errors if the error is due to data validation - failure - additionalProperties: true - BatchPayload: - type: object - properties: - count: - type: integer - FooCreateArgs: - type: object - required: - - data - properties: - select: - $ref: '#/components/schemas/FooSelect' - data: - $ref: '#/components/schemas/FooCreateInput' - meta: - $ref: '#/components/schemas/_Meta' - FooCreateManyArgs: - type: object - required: - - data - properties: - data: - oneOf: - - $ref: '#/components/schemas/FooCreateManyInput' - - type: array - items: - $ref: '#/components/schemas/FooCreateManyInput' - skipDuplicates: - type: boolean - description: Do not insert records with unique fields or ID fields that already - exist. - meta: - $ref: '#/components/schemas/_Meta' - FooFindUniqueArgs: - type: object - required: - - where - properties: - select: - $ref: '#/components/schemas/FooSelect' - where: - $ref: '#/components/schemas/FooWhereUniqueInput' - meta: - $ref: '#/components/schemas/_Meta' - FooFindFirstArgs: - type: object - properties: - select: - $ref: '#/components/schemas/FooSelect' - where: - $ref: '#/components/schemas/FooWhereInput' - meta: - $ref: '#/components/schemas/_Meta' - FooFindManyArgs: - type: object - properties: - select: - $ref: '#/components/schemas/FooSelect' - where: - $ref: '#/components/schemas/FooWhereInput' - orderBy: - oneOf: - - $ref: '#/components/schemas/FooOrderByWithRelationInput' - - type: array - items: - $ref: '#/components/schemas/FooOrderByWithRelationInput' - cursor: - $ref: '#/components/schemas/FooWhereUniqueInput' - take: - type: integer - skip: - type: integer - meta: - $ref: '#/components/schemas/_Meta' - FooUpdateArgs: - type: object - required: - - where - - data - properties: - select: - $ref: '#/components/schemas/FooSelect' - where: - $ref: '#/components/schemas/FooWhereUniqueInput' - data: - $ref: '#/components/schemas/FooUpdateInput' - meta: - $ref: '#/components/schemas/_Meta' - FooUpdateManyArgs: - type: object - required: - - data - properties: - where: - $ref: '#/components/schemas/FooWhereInput' - data: - $ref: '#/components/schemas/FooUpdateManyMutationInput' - meta: - $ref: '#/components/schemas/_Meta' - FooUpsertArgs: - type: object - required: - - create - - update - - where - properties: - select: - $ref: '#/components/schemas/FooSelect' - where: - $ref: '#/components/schemas/FooWhereUniqueInput' - create: - $ref: '#/components/schemas/FooCreateInput' - update: - $ref: '#/components/schemas/FooUpdateInput' - meta: - $ref: '#/components/schemas/_Meta' - FooDeleteUniqueArgs: - type: object - required: - - where - properties: - select: - $ref: '#/components/schemas/FooSelect' - where: - $ref: '#/components/schemas/FooWhereUniqueInput' - meta: - $ref: '#/components/schemas/_Meta' - FooDeleteManyArgs: - type: object - properties: - where: - $ref: '#/components/schemas/FooWhereInput' - meta: - $ref: '#/components/schemas/_Meta' - FooCountArgs: - type: object - properties: - select: - $ref: '#/components/schemas/FooSelect' - where: - $ref: '#/components/schemas/FooWhereInput' - meta: - $ref: '#/components/schemas/_Meta' - FooAggregateArgs: - type: object - properties: - where: - $ref: '#/components/schemas/FooWhereInput' - orderBy: - $ref: '#/components/schemas/FooOrderByWithRelationInput' - cursor: - $ref: '#/components/schemas/FooWhereUniqueInput' - take: - type: integer - skip: - type: integer - _count: - oneOf: - - type: boolean - - $ref: '#/components/schemas/FooCountAggregateInput' - _min: - $ref: '#/components/schemas/FooMinAggregateInput' - _max: - $ref: '#/components/schemas/FooMaxAggregateInput' - _sum: - $ref: '#/components/schemas/FooSumAggregateInput' - _avg: - $ref: '#/components/schemas/FooAvgAggregateInput' - meta: - $ref: '#/components/schemas/_Meta' - FooGroupByArgs: - type: object - properties: - where: - $ref: '#/components/schemas/FooWhereInput' - orderBy: - $ref: '#/components/schemas/FooOrderByWithRelationInput' - by: - $ref: '#/components/schemas/FooScalarFieldEnum' - having: - $ref: '#/components/schemas/FooScalarWhereWithAggregatesInput' - take: - type: integer - skip: - type: integer - _count: - oneOf: - - type: boolean - - $ref: '#/components/schemas/FooCountAggregateInput' - _min: - $ref: '#/components/schemas/FooMinAggregateInput' - _max: - $ref: '#/components/schemas/FooMaxAggregateInput' - _sum: - $ref: '#/components/schemas/FooSumAggregateInput' - _avg: - $ref: '#/components/schemas/FooAvgAggregateInput' - meta: - $ref: '#/components/schemas/_Meta' -paths: - /foo/create: - post: - operationId: createFoo - description: Create a new Foo - tags: - - foo - security: [] - responses: - '201': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Foo' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/FooCreateArgs' - /foo/createMany: - post: - operationId: createManyFoo - description: Create several Foo - tags: - - foo - security: [] - responses: - '201': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BatchPayload' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/FooCreateManyArgs' - /foo/findUnique: - get: - operationId: findUniqueFoo - description: Find one unique Foo - tags: - - foo - security: [] - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Foo' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/FooFindUniqueArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /foo/findFirst: - get: - operationId: findFirstFoo - description: Find the first Foo matching the given condition - tags: - - foo - security: [] - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Foo' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/FooFindFirstArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /foo/findMany: - get: - operationId: findManyFoo - description: Find a list of Foo - tags: - - foo - security: [] - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - type: array - items: - $ref: '#/components/schemas/Foo' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/FooFindManyArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /foo/update: - patch: - operationId: updateFoo - description: Update a Foo - tags: - - foo - security: [] - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Foo' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/FooUpdateArgs' - /foo/updateMany: - patch: - operationId: updateManyFoo - description: Update Foos matching the given condition - tags: - - foo - security: [] - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BatchPayload' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/FooUpdateManyArgs' - /foo/upsert: - post: - operationId: upsertFoo - description: Upsert a Foo - tags: - - foo - security: [] - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Foo' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/FooUpsertArgs' - /foo/delete: - delete: - operationId: deleteFoo - description: Delete one unique Foo - tags: - - foo - security: [] - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Foo' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/FooDeleteUniqueArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /foo/deleteMany: - delete: - operationId: deleteManyFoo - description: Delete Foos matching the given condition - tags: - - foo - security: [] - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BatchPayload' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/FooDeleteManyArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /foo/count: - get: - operationId: countFoo - description: Find a list of Foo - tags: - - foo - security: [] - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - oneOf: - - type: integer - - $ref: '#/components/schemas/FooCountAggregateOutputType' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/FooCountArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /foo/aggregate: - get: - operationId: aggregateFoo - description: Aggregate Foos - tags: - - foo - security: [] - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/AggregateFoo' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/FooAggregateArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /foo/groupBy: - get: - operationId: groupByFoo - description: Group Foos by fields - tags: - - foo - security: [] - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - type: array - items: - $ref: '#/components/schemas/FooGroupByOutputType' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/FooGroupByArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} From 76b634c292f0db03ff3cffe0392248602e9572a7 Mon Sep 17 00:00:00 2001 From: ymc9 <104139426+ymc9@users.noreply.github.com> Date: Thu, 19 Mar 2026 15:09:30 -0700 Subject: [PATCH 07/16] feat(server): add operation slicing, meta descriptions, and queryOptions validation to OpenAPI generators - REST OpenAPI generator now respects `slicing.excludedOperations`/`includedOperations` per model, mapping REST verbs to ORM operations (findMany, create, findUnique, update, delete) - Add proper zod validation schema for `queryOptions` in both REST and RPC handlers - Support `@@meta("description")` and `@meta("description")` for model/field schema descriptions - Use named arg lookup in `getMetaDescription` for reliability Co-Authored-By: Claude Opus 4.6 --- packages/server/src/api/common/schemas.ts | 24 ++++ packages/server/src/api/common/spec-utils.ts | 10 +- packages/server/src/api/rest/index.ts | 4 +- packages/server/src/api/rest/openapi.ts | 123 +++++++++++------- packages/server/src/api/rpc/index.ts | 4 +- packages/server/src/api/rpc/openapi.ts | 7 +- .../server/test/openapi/rest-openapi.test.ts | 119 ++++++++++++++++- .../server/test/openapi/rpc-openapi.test.ts | 21 ++- 8 files changed, 245 insertions(+), 67 deletions(-) diff --git a/packages/server/src/api/common/schemas.ts b/packages/server/src/api/common/schemas.ts index 44e30665c..e11c885e6 100644 --- a/packages/server/src/api/common/schemas.ts +++ b/packages/server/src/api/common/schemas.ts @@ -1,3 +1,27 @@ import z from 'zod'; export const loggerSchema = z.union([z.enum(['debug', 'info', 'warn', 'error']).array(), z.function()]); + +const fieldSlicingSchema = z.looseObject({ + includedFilterKinds: z.string().array().optional(), + excludedFilterKinds: z.string().array().optional(), +}); + +const modelSlicingSchema = z.looseObject({ + includedOperations: z.array(z.string()).optional(), + excludedOperations: z.array(z.string()).optional(), + fields: z.record(z.string(), fieldSlicingSchema).optional(), +}); + +const slicingSchema = z.looseObject({ + includedModels: z.array(z.string()).optional(), + excludedModels: z.array(z.string()).optional(), + models: z.record(z.string(), modelSlicingSchema).optional(), + includedProcedures: z.array(z.string()).optional(), + excludedProcedures: z.array(z.string()).optional(), +}); + +export const queryOptionsSchema = z.looseObject({ + omit: z.record(z.string(), z.record(z.string(), z.boolean())).optional(), + slicing: slicingSchema.optional(), +}); diff --git a/packages/server/src/api/common/spec-utils.ts b/packages/server/src/api/common/spec-utils.ts index 8bba4329d..f469f79aa 100644 --- a/packages/server/src/api/common/spec-utils.ts +++ b/packages/server/src/api/common/spec-utils.ts @@ -104,11 +104,11 @@ export function getMetaDescription(attributes: readonly AttributeApplication[] | if (!attributes) return undefined; for (const attr of attributes) { if (attr.name !== '@meta' && attr.name !== '@@meta') continue; - const nameExpr = attr.args?.[0]?.value; - if (!nameExpr || ExpressionUtils.getLiteralValue(nameExpr) !== 'description') continue; - const valueExpr = attr.args?.[1]?.value; - if (valueExpr) { - return ExpressionUtils.getLiteralValue(valueExpr) as string | undefined; + const nameArg = attr.args?.find((a) => a.name === 'name'); + if (!nameArg || ExpressionUtils.getLiteralValue(nameArg.value) !== 'description') continue; + const valueArg = attr.args?.find((a) => a.name === 'value'); + if (valueArg) { + return ExpressionUtils.getLiteralValue(valueArg.value) as string | undefined; } } return undefined; diff --git a/packages/server/src/api/rest/index.ts b/packages/server/src/api/rest/index.ts index c25686ce9..2e31fdb63 100644 --- a/packages/server/src/api/rest/index.ts +++ b/packages/server/src/api/rest/index.ts @@ -10,7 +10,7 @@ import z from 'zod'; import { fromError } from 'zod-validation-error/v4'; import type { ApiHandler, LogConfig, RequestContext, Response } from '../../types'; import { getProcedureDef, mapProcedureArgs } from '../common/procedures'; -import { loggerSchema } from '../common/schemas'; +import { loggerSchema, queryOptionsSchema } from '../common/schemas'; import type { CommonHandlerOptions, OpenApiSpecGenerator, OpenApiSpecOptions } from '../common/types'; import { processSuperJsonRequestPayload } from '../common/utils'; import { getZodErrorMessage, log, registerCustomSerializers } from '../utils'; @@ -300,7 +300,7 @@ export class RestApiHandler implements Api urlSegmentCharset: z.string().min(1).optional(), modelNameMapping: z.record(z.string(), z.string()).optional(), externalIdMapping: z.record(z.string(), z.string()).optional(), - queryOptions: z.object().optional(), + queryOptions: queryOptionsSchema.optional(), }); const parseResult = schema.safeParse(options); if (!parseResult.success) { diff --git a/packages/server/src/api/rest/openapi.ts b/packages/server/src/api/rest/openapi.ts index 7d60d9cac..8bf9cc093 100644 --- a/packages/server/src/api/rest/openapi.ts +++ b/packages/server/src/api/rest/openapi.ts @@ -7,6 +7,7 @@ import { getMetaDescription, isFieldOmitted, isFilterKindIncluded, + isOperationIncluded, isProcedureIncluded, } from '../common/spec-utils'; import type { OpenApiSpecOptions } from '../common/types'; @@ -88,10 +89,16 @@ export class RestApiSpecGenerator { const tag = lowerCaseFirst(modelName); // Collection: GET (list) + POST (create) - paths[`/${modelPath}`] = this.buildCollectionPath(modelName, modelDef, tag) as any; + const collectionPath = this.buildCollectionPath(modelName, modelDef, tag); + if (Object.keys(collectionPath).length > 0) { + paths[`/${modelPath}`] = collectionPath; + } // Single resource: GET + PATCH + DELETE - paths[`/${modelPath}/{id}`] = this.buildSinglePath(modelName, tag) as any; + const singlePath = this.buildSinglePath(modelName, tag); + if (Object.keys(singlePath).length > 0) { + paths[`/${modelPath}/{id}`] = singlePath; + } // Relation paths for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { @@ -191,69 +198,83 @@ export class RestApiSpecGenerator { }, }; - return { get: listOp, post: createOp }; + const result: Record = {}; + if (isOperationIncluded(modelName, 'findMany', this.queryOptions)) { + result['get'] = listOp; + } + if (isOperationIncluded(modelName, 'create', this.queryOptions)) { + result['post'] = createOp; + } + return result; } private buildSinglePath(modelName: string, tag: string): Record { const idParam = { $ref: '#/components/parameters/id' }; + const result: Record = {}; - const getOp = { - tags: [tag], - summary: `Get a ${modelName} resource by ID`, - operationId: `get${modelName}`, - parameters: [idParam, { $ref: '#/components/parameters/include' }], - responses: { - '200': { - description: `${modelName} resource`, - content: { - 'application/vnd.api+json': { - schema: { $ref: `#/components/schemas/${modelName}Response` }, + if (isOperationIncluded(modelName, 'findUnique', this.queryOptions)) { + result['get'] = { + tags: [tag], + summary: `Get a ${modelName} resource by ID`, + operationId: `get${modelName}`, + parameters: [idParam, { $ref: '#/components/parameters/include' }], + responses: { + '200': { + description: `${modelName} resource`, + content: { + 'application/vnd.api+json': { + schema: { $ref: `#/components/schemas/${modelName}Response` }, + }, }, }, + '404': { $ref: '#/components/schemas/_errorResponse' }, }, - '404': { $ref: '#/components/schemas/_errorResponse' }, - }, - }; + }; + } - const patchOp = { - tags: [tag], - summary: `Update a ${modelName} resource`, - operationId: `update${modelName}`, - parameters: [idParam], - requestBody: { - required: true, - content: { - 'application/vnd.api+json': { - schema: { $ref: `#/components/schemas/${modelName}UpdateRequest` }, - }, - }, - }, - responses: { - '200': { - description: `Updated ${modelName} resource`, + if (isOperationIncluded(modelName, 'update', this.queryOptions)) { + result['patch'] = { + tags: [tag], + summary: `Update a ${modelName} resource`, + operationId: `update${modelName}`, + parameters: [idParam], + requestBody: { + required: true, content: { 'application/vnd.api+json': { - schema: { $ref: `#/components/schemas/${modelName}Response` }, + schema: { $ref: `#/components/schemas/${modelName}UpdateRequest` }, }, }, }, - '400': { $ref: '#/components/schemas/_errorResponse' }, - '404': { $ref: '#/components/schemas/_errorResponse' }, - }, - }; + responses: { + '200': { + description: `Updated ${modelName} resource`, + content: { + 'application/vnd.api+json': { + schema: { $ref: `#/components/schemas/${modelName}Response` }, + }, + }, + }, + '400': { $ref: '#/components/schemas/_errorResponse' }, + '404': { $ref: '#/components/schemas/_errorResponse' }, + }, + }; + } - const deleteOp = { - tags: [tag], - summary: `Delete a ${modelName} resource`, - operationId: `delete${modelName}`, - parameters: [idParam], - responses: { - '200': { description: 'Deleted successfully' }, - '404': { $ref: '#/components/schemas/_errorResponse' }, - }, - }; + if (isOperationIncluded(modelName, 'delete', this.queryOptions)) { + result['delete'] = { + tags: [tag], + summary: `Delete a ${modelName} resource`, + operationId: `delete${modelName}`, + parameters: [idParam], + responses: { + '200': { description: 'Deleted successfully' }, + '404': { $ref: '#/components/schemas/_errorResponse' }, + }, + }; + } - return { get: getOp, patch: patchOp, delete: deleteOp }; + return result; } private buildFetchRelatedPath( @@ -683,6 +704,10 @@ export class RestApiSpecGenerator { if (isFieldOmitted(modelName, fieldName, this.queryOptions)) continue; const schema = this.fieldToSchema(fieldDef); + const fieldDescription = getMetaDescription(fieldDef.attributes); + if (fieldDescription && !('$ref' in schema)) { + schema.description = fieldDescription; + } properties[fieldName] = schema; if (!fieldDef.optional && !fieldDef.array) { diff --git a/packages/server/src/api/rpc/index.ts b/packages/server/src/api/rpc/index.ts index f5c09335c..80d10ec1f 100644 --- a/packages/server/src/api/rpc/index.ts +++ b/packages/server/src/api/rpc/index.ts @@ -7,7 +7,7 @@ import z from 'zod'; import { fromError } from 'zod-validation-error/v4'; import type { ApiHandler, LogConfig, RequestContext, Response } from '../../types'; import { getProcedureDef, mapProcedureArgs, PROCEDURE_ROUTE_PREFIXES } from '../common/procedures'; -import { loggerSchema } from '../common/schemas'; +import { loggerSchema, queryOptionsSchema } from '../common/schemas'; import type { CommonHandlerOptions, OpenApiSpecGenerator } from '../common/types'; import { processSuperJsonRequestPayload, unmarshalQ } from '../common/utils'; import { log, registerCustomSerializers } from '../utils'; @@ -45,7 +45,7 @@ export class RPCApiHandler implements ApiH const schema = z.strictObject({ schema: z.object(), log: loggerSchema.optional(), - queryOptions: z.object().optional(), + queryOptions: queryOptionsSchema.optional(), }); const parseResult = schema.safeParse(options); if (!parseResult.success) { diff --git a/packages/server/src/api/rpc/openapi.ts b/packages/server/src/api/rpc/openapi.ts index 93a4d3e33..7ce755dbd 100644 --- a/packages/server/src/api/rpc/openapi.ts +++ b/packages/server/src/api/rpc/openapi.ts @@ -381,7 +381,12 @@ export class RPCApiSpecGenerator { for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { if (fieldDef.omit) continue; if (isFieldOmitted(modelName, fieldName, this.queryOptions)) continue; - properties[fieldName] = this.fieldToSchema(fieldDef); + const schema = this.fieldToSchema(fieldDef); + const fieldDescription = getMetaDescription(fieldDef.attributes); + if (fieldDescription && !('$ref' in schema)) { + schema.description = fieldDescription; + } + properties[fieldName] = schema; if (!fieldDef.optional && !fieldDef.array) { required.push(fieldName); } diff --git a/packages/server/test/openapi/rest-openapi.test.ts b/packages/server/test/openapi/rest-openapi.test.ts index 8df3f5b2e..a8dd89baf 100644 --- a/packages/server/test/openapi/rest-openapi.test.ts +++ b/packages/server/test/openapi/rest-openapi.test.ts @@ -279,6 +279,101 @@ describe('REST OpenAPI spec generation - queryOptions', () => { expect(s.paths?.['/post']).toBeUndefined(); }); + it('slicing excludedOperations removes HTTP methods from paths', async () => { + const client = await createTestClient(schema); + const handler = new RestApiHandler({ + schema: client.$schema, + endpoint: 'http://localhost/api', + queryOptions: { + slicing: { + models: { + post: { excludedOperations: ['create', 'delete'] }, + }, + } as any, + }, + }); + const s = await handler.generateSpec(); + + // Collection path: GET (findMany) should exist, POST (create) should not + expect((s.paths as any)['/post'].get).toBeDefined(); + expect((s.paths as any)['/post'].post).toBeUndefined(); + + // Single path: GET (findUnique) and PATCH (update) should exist, DELETE should not + expect((s.paths as any)['/post/{id}'].get).toBeDefined(); + expect((s.paths as any)['/post/{id}'].patch).toBeDefined(); + expect((s.paths as any)['/post/{id}'].delete).toBeUndefined(); + }); + + it('slicing excludedOperations on all CRUD ops removes paths entirely', async () => { + const client = await createTestClient(schema); + const handler = new RestApiHandler({ + schema: client.$schema, + endpoint: 'http://localhost/api', + queryOptions: { + slicing: { + models: { + post: { excludedOperations: ['findMany', 'create', 'findUnique', 'update', 'delete'] }, + }, + } as any, + }, + }); + const s = await handler.generateSpec(); + + // Both collection and single paths should be absent (empty path objects are not emitted) + expect(s.paths?.['/post']).toBeUndefined(); + expect(s.paths?.['/post/{id}']).toBeUndefined(); + }); + + it('slicing includedOperations limits HTTP methods in paths', async () => { + const client = await createTestClient(schema); + const handler = new RestApiHandler({ + schema: client.$schema, + endpoint: 'http://localhost/api', + queryOptions: { + slicing: { + models: { + post: { includedOperations: ['findMany', 'findUnique'] }, + }, + } as any, + }, + }); + const s = await handler.generateSpec(); + + // Collection: only GET + expect((s.paths as any)['/post'].get).toBeDefined(); + expect((s.paths as any)['/post'].post).toBeUndefined(); + + // Single: only GET + expect((s.paths as any)['/post/{id}'].get).toBeDefined(); + expect((s.paths as any)['/post/{id}'].patch).toBeUndefined(); + expect((s.paths as any)['/post/{id}'].delete).toBeUndefined(); + }); + + it('slicing $all excludedOperations applies to all models', async () => { + const client = await createTestClient(schema); + const handler = new RestApiHandler({ + schema: client.$schema, + endpoint: 'http://localhost/api', + queryOptions: { + slicing: { + models: { + $all: { excludedOperations: ['delete'] }, + }, + } as any, + }, + }); + const s = await handler.generateSpec(); + + // DELETE should be absent on all models + expect((s.paths as any)['/user/{id}'].delete).toBeUndefined(); + expect((s.paths as any)['/post/{id}'].delete).toBeUndefined(); + expect((s.paths as any)['/comment/{id}'].delete).toBeUndefined(); + + // Other methods should still exist + expect((s.paths as any)['/user/{id}'].get).toBeDefined(); + expect((s.paths as any)['/user/{id}'].patch).toBeDefined(); + }); + it('slicing excludedFilterKinds removes filter params for a field', async () => { const client = await createTestClient(schema); const handler = new RestApiHandler({ @@ -433,12 +528,11 @@ describe('REST OpenAPI spec generation - queryOptions', () => { }); }); -describe('REST OpenAPI spec generation - @@meta description', () => { - it('model @@meta description is used as schema description', async () => { - const metaSchema = ` +describe('REST OpenAPI spec generation - @meta description', () => { + const metaSchema = ` model User { id String @id @default(cuid()) - email String @unique + email String @unique @meta("description", "The user's email address") @@meta("description", "A user of the system") } @@ -447,6 +541,8 @@ model Post { title String } `; + + it('model @@meta description is used as schema description', async () => { const client = await createTestClient(metaSchema); const handler = new RestApiHandler({ schema: client.$schema, @@ -461,6 +557,21 @@ model Post { const postSchema = s.components?.schemas?.['Post'] as any; expect(postSchema.description).toBeUndefined(); }); + + it('field @meta description is used as field schema description', async () => { + const client = await createTestClient(metaSchema); + const handler = new RestApiHandler({ + schema: client.$schema, + endpoint: 'http://localhost/api', + }); + const s = await handler.generateSpec(); + + const userSchema = s.components?.schemas?.['User'] as any; + expect(userSchema.properties['email'].description).toBe("The user's email address"); + + // id has no @meta description + expect(userSchema.properties['id'].description).toBeUndefined(); + }); }); describe('REST OpenAPI spec generation - with enum schema', () => { diff --git a/packages/server/test/openapi/rpc-openapi.test.ts b/packages/server/test/openapi/rpc-openapi.test.ts index 3aefa03b9..499654893 100644 --- a/packages/server/test/openapi/rpc-openapi.test.ts +++ b/packages/server/test/openapi/rpc-openapi.test.ts @@ -423,12 +423,11 @@ enum PostStatus { }); }); -describe('RPC OpenAPI spec generation - @@meta description', () => { - it('model @@meta description is used as schema description', async () => { - const metaSchema = ` +describe('RPC OpenAPI spec generation - @meta description', () => { + const metaSchema = ` model User { id String @id @default(cuid()) - email String @unique + email String @unique @meta("description", "The user's email address") @@meta("description", "A user of the system") } @@ -437,6 +436,8 @@ model Post { title String } `; + + it('model @@meta description is used as schema description', async () => { const client = await createTestClient(metaSchema); const handler = new RPCApiHandler({ schema: client.$schema }); const s = await handler.generateSpec(); @@ -448,6 +449,18 @@ model Post { const postSchema = s.components?.schemas?.['Post'] as any; expect(postSchema.description).toBeUndefined(); }); + + it('field @meta description is used as field schema description', async () => { + const client = await createTestClient(metaSchema); + const handler = new RPCApiHandler({ schema: client.$schema }); + const s = await handler.generateSpec(); + + const userSchema = s.components?.schemas?.['User'] as any; + expect(userSchema.properties['email'].description).toBe("The user's email address"); + + // id has no @meta description + expect(userSchema.properties['id'].description).toBeUndefined(); + }); }); describe('RPC OpenAPI spec generation - with procedures', () => { From 4e7cad4e416283e11d58284acd4702fdbda8b506 Mon Sep 17 00:00:00 2001 From: ymc9 <104139426+ymc9@users.noreply.github.com> Date: Thu, 19 Mar 2026 15:21:16 -0700 Subject: [PATCH 08/16] fix(server): hide relations to excluded models in REST OpenAPI spec and remove unnecessary `as any` casts - Skip relation paths, read schema fields, and create/update relationship entries when the related model is excluded by slicing - Replace `as any` with `as OpenAPIV3_1.PathItemObject` where possible and remove unnecessary cast on `generateSharedParams()` Co-Authored-By: Claude Opus 4.6 --- packages/server/src/api/rest/openapi.ts | 23 +++++++++++-------- packages/server/src/api/rpc/openapi.ts | 16 ++++++------- .../server/test/openapi/rest-openapi.test.ts | 9 ++++++++ 3 files changed, 31 insertions(+), 17 deletions(-) diff --git a/packages/server/src/api/rest/openapi.ts b/packages/server/src/api/rest/openapi.ts index 8bf9cc093..48face905 100644 --- a/packages/server/src/api/rest/openapi.ts +++ b/packages/server/src/api/rest/openapi.ts @@ -7,6 +7,7 @@ import { getMetaDescription, isFieldOmitted, isFilterKindIncluded, + isModelIncluded, isOperationIncluded, isProcedureIncluded, } from '../common/spec-utils'; @@ -60,7 +61,7 @@ export class RestApiSpecGenerator { paths: this.generatePaths(), components: { schemas: this.generateSchemas(), - parameters: this.generateSharedParams() as any, + parameters: this.generateSharedParams(), }, } as OpenAPIV3_1.Document; } @@ -103,6 +104,7 @@ export class RestApiSpecGenerator { // Relation paths for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { if (!fieldDef.relation) continue; + if (!isModelIncluded(fieldDef.type, this.queryOptions)) continue; const relModelDef = this.schema.models[fieldDef.type]; if (!relModelDef) continue; const relIdFields = this.getIdFields(relModelDef); @@ -114,7 +116,7 @@ export class RestApiSpecGenerator { fieldName, fieldDef, tag, - ) as any; + ); // Relationship management path paths[`/${modelPath}/{id}/relationships/${fieldName}`] = this.buildRelationshipPath( @@ -122,7 +124,7 @@ export class RestApiSpecGenerator { fieldName, fieldDef, tag, - ) as any; + ); } } @@ -131,15 +133,15 @@ export class RestApiSpecGenerator { for (const [procName, procDef] of Object.entries(this.schema.procedures)) { if (!isProcedureIncluded(procName, this.queryOptions)) continue; const isMutation = !!procDef.mutation; - const pathItem: Record = {}; - if (isMutation) { - pathItem['post'] = this.buildProcedureOperation(procName, 'post'); + paths[`/${PROCEDURE_ROUTE_PREFIXES}/${procName}`] = { + post: this.buildProcedureOperation(procName, 'post'), + } as OpenAPIV3_1.PathItemObject; } else { - pathItem['get'] = this.buildProcedureOperation(procName, 'get'); + paths[`/${PROCEDURE_ROUTE_PREFIXES}/${procName}`] = { + get: this.buildProcedureOperation(procName, 'get'), + } as OpenAPIV3_1.PathItemObject; } - - paths[`/${PROCEDURE_ROUTE_PREFIXES}/${procName}`] = pathItem as any; } } @@ -702,6 +704,7 @@ export class RestApiSpecGenerator { for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { if (fieldDef.omit) continue; if (isFieldOmitted(modelName, fieldName, this.queryOptions)) continue; + if (fieldDef.relation && !isModelIncluded(fieldDef.type, this.queryOptions)) continue; const schema = this.fieldToSchema(fieldDef); const fieldDescription = getMetaDescription(fieldDef.attributes); @@ -738,6 +741,7 @@ export class RestApiSpecGenerator { if (fieldDef.foreignKeyFor) continue; // Skip auto-generated id fields if (idFieldNames.has(fieldName) && fieldDef.default !== undefined) continue; + if (fieldDef.relation && !isModelIncluded(fieldDef.type, this.queryOptions)) continue; if (fieldDef.relation) { relationships[fieldName] = fieldDef.array @@ -799,6 +803,7 @@ export class RestApiSpecGenerator { if (fieldDef.omit) continue; if (fieldDef.updatedAt) continue; if (fieldDef.foreignKeyFor) continue; + if (fieldDef.relation && !isModelIncluded(fieldDef.type, this.queryOptions)) continue; if (fieldDef.relation) { relationships[fieldName] = fieldDef.array diff --git a/packages/server/src/api/rpc/openapi.ts b/packages/server/src/api/rpc/openapi.ts index 7ce755dbd..ef62453e6 100644 --- a/packages/server/src/api/rpc/openapi.ts +++ b/packages/server/src/api/rpc/openapi.ts @@ -68,7 +68,7 @@ export class RPCApiSpecGenerator { const argsSchemaName = `${modelName}${this.opToArgsSchema(op)}`; paths[`/${modelPath}/${op}`] = { get: this.buildGetOperation(modelName, op, tag, argsSchemaName), - } as any; + } as OpenAPIV3_1.PathItemObject; } // Write operations @@ -137,15 +137,15 @@ export class RPCApiSpecGenerator { if (!isProcedureIncluded(procName, this.queryOptions)) continue; const isMutation = !!procDef.mutation; - const pathItem: Record = {}; - if (isMutation) { - pathItem['post'] = this.buildProcedureOperation(procName, 'post'); + paths[`/${PROCEDURE_ROUTE_PREFIXES}/${procName}`] = { + post: this.buildProcedureOperation(procName, 'post'), + } as OpenAPIV3_1.PathItemObject; } else { - pathItem['get'] = this.buildProcedureOperation(procName, 'get'); + paths[`/${PROCEDURE_ROUTE_PREFIXES}/${procName}`] = { + get: this.buildProcedureOperation(procName, 'get'), + } as OpenAPIV3_1.PathItemObject; } - - paths[`/${PROCEDURE_ROUTE_PREFIXES}/${procName}`] = pathItem as any; } } @@ -457,7 +457,7 @@ export class RPCApiSpecGenerator { // Unique fields for (const [uniqueName, uniqueInfo] of Object.entries(modelDef.uniqueFields)) { - if (typeof (uniqueInfo as any).type === 'string') { + if ('type' in uniqueInfo && typeof uniqueInfo.type === 'string') { // Single unique field const fieldDef = modelDef.fields[uniqueName]; if (fieldDef && !properties[uniqueName]) { diff --git a/packages/server/test/openapi/rest-openapi.test.ts b/packages/server/test/openapi/rest-openapi.test.ts index a8dd89baf..1a66310a8 100644 --- a/packages/server/test/openapi/rest-openapi.test.ts +++ b/packages/server/test/openapi/rest-openapi.test.ts @@ -265,6 +265,15 @@ describe('REST OpenAPI spec generation - queryOptions', () => { expect(s.paths?.['/user']).toBeDefined(); expect(s.paths?.['/post']).toBeUndefined(); expect(s.components?.schemas?.['Post']).toBeUndefined(); + + // Relation paths to excluded model should not exist + expect(s.paths?.['/user/{id}/posts']).toBeUndefined(); + expect(s.paths?.['/user/{id}/relationships/posts']).toBeUndefined(); + + // Relation fields to excluded model should not appear in read schema + const userSchema = s.components?.schemas?.['User'] as any; + expect(userSchema.properties['posts']).toBeUndefined(); + expect(userSchema.properties['email']).toBeDefined(); }); it('slicing includedModels limits models in spec', async () => { From ac2e936af0e83ba337a8f9ddd0422d1d168d76fc Mon Sep 17 00:00:00 2001 From: ymc9 <104139426+ymc9@users.noreply.github.com> Date: Thu, 19 Mar 2026 15:36:35 -0700 Subject: [PATCH 09/16] fix(server): use proper OpenAPI Response Objects for error responses and add fetch-related response schemas Error responses were using `$ref` to schemas directly in response positions, which is invalid per OpenAPI spec. Replace with inline Response Objects containing description and content. Also add proper response schema references to fetch-related endpoints. Co-Authored-By: Claude Opus 4.6 --- packages/server/src/api/rest/openapi.ts | 44 +++++++++++++------ packages/server/src/api/rpc/openapi.ts | 21 ++++++--- .../server/test/openapi/rest-openapi.test.ts | 12 +++++ 3 files changed, 58 insertions(+), 19 deletions(-) diff --git a/packages/server/src/api/rest/openapi.ts b/packages/server/src/api/rest/openapi.ts index 48face905..4a077667f 100644 --- a/packages/server/src/api/rest/openapi.ts +++ b/packages/server/src/api/rest/openapi.ts @@ -18,6 +18,15 @@ type SchemaObject = OpenAPIV3_1.SchemaObject; type ReferenceObject = OpenAPIV3_1.ReferenceObject; type ParameterObject = OpenAPIV3_1.ParameterObject; +const ERROR_RESPONSE = { + description: 'Error', + content: { + 'application/vnd.api+json': { + schema: { $ref: '#/components/schemas/_errorResponse' }, + }, + }, +}; + const SCALAR_STRING_OPS = ['$contains', '$icontains', '$search', '$startsWith', '$endsWith']; const SCALAR_COMPARABLE_OPS = ['$lt', '$lte', '$gt', '$gte']; const SCALAR_ARRAY_OPS = ['$has', '$hasEvery', '$hasSome', '$isEmpty']; @@ -171,7 +180,7 @@ export class RestApiSpecGenerator { }, }, }, - '400': { $ref: '#/components/schemas/_errorResponse' }, + '400': ERROR_RESPONSE, }, }; @@ -196,7 +205,7 @@ export class RestApiSpecGenerator { }, }, }, - '400': { $ref: '#/components/schemas/_errorResponse' }, + '400': ERROR_RESPONSE, }, }; @@ -229,7 +238,7 @@ export class RestApiSpecGenerator { }, }, }, - '404': { $ref: '#/components/schemas/_errorResponse' }, + '404': ERROR_RESPONSE, }, }; } @@ -257,8 +266,8 @@ export class RestApiSpecGenerator { }, }, }, - '400': { $ref: '#/components/schemas/_errorResponse' }, - '404': { $ref: '#/components/schemas/_errorResponse' }, + '400': ERROR_RESPONSE, + '404': ERROR_RESPONSE, }, }; } @@ -271,7 +280,7 @@ export class RestApiSpecGenerator { parameters: [idParam], responses: { '200': { description: 'Deleted successfully' }, - '404': { $ref: '#/components/schemas/_errorResponse' }, + '404': ERROR_RESPONSE, }, }; } @@ -305,8 +314,17 @@ export class RestApiSpecGenerator { operationId: `get${modelName}_${fieldName}`, parameters: params, responses: { - '200': { description: `Related ${fieldDef.type} resource(s)` }, - '404': { $ref: '#/components/schemas/_errorResponse' }, + '200': { + description: `Related ${fieldDef.type} resource(s)`, + content: { + 'application/vnd.api+json': { + schema: isCollection + ? { $ref: `#/components/schemas/${fieldDef.type}ListResponse` } + : { $ref: `#/components/schemas/${fieldDef.type}Response` }, + }, + }, + }, + '404': ERROR_RESPONSE, }, }, }; @@ -339,7 +357,7 @@ export class RestApiSpecGenerator { description: `${fieldName} relationship`, content: { 'application/vnd.api+json': { schema: relSchemaRef } }, }, - '404': { $ref: '#/components/schemas/_errorResponse' }, + '404': ERROR_RESPONSE, }, }, put: { @@ -353,7 +371,7 @@ export class RestApiSpecGenerator { }, responses: { '200': { description: 'Relationship updated' }, - '400': { $ref: '#/components/schemas/_errorResponse' }, + '400': ERROR_RESPONSE, }, }, patch: { @@ -367,7 +385,7 @@ export class RestApiSpecGenerator { }, responses: { '200': { description: 'Relationship updated' }, - '400': { $ref: '#/components/schemas/_errorResponse' }, + '400': ERROR_RESPONSE, }, }, }; @@ -388,7 +406,7 @@ export class RestApiSpecGenerator { }, responses: { '200': { description: 'Added to relationship collection' }, - '400': { $ref: '#/components/schemas/_errorResponse' }, + '400': ERROR_RESPONSE, }, }; } @@ -403,7 +421,7 @@ export class RestApiSpecGenerator { operationId: `proc_${procName}`, responses: { '200': { description: `Result of ${procName}` }, - '400': { $ref: '#/components/schemas/_errorResponse' }, + '400': ERROR_RESPONSE, }, }; diff --git a/packages/server/src/api/rpc/openapi.ts b/packages/server/src/api/rpc/openapi.ts index ef62453e6..db9cb0771 100644 --- a/packages/server/src/api/rpc/openapi.ts +++ b/packages/server/src/api/rpc/openapi.ts @@ -16,6 +16,15 @@ import type { OpenApiSpecOptions } from '../common/types'; type SchemaObject = OpenAPIV3_1.SchemaObject; type ReferenceObject = OpenAPIV3_1.ReferenceObject; +const ERROR_RESPONSE = { + description: 'Error', + content: { + 'application/json': { + schema: { $ref: '#/components/schemas/_ErrorResponse' }, + }, + }, +}; + /** * Generates OpenAPI v3.1 specification for the RPC-style CRUD API. */ @@ -126,7 +135,7 @@ export class RPCApiSpecGenerator { }, responses: { '200': { description: 'Transaction results' }, - '400': { $ref: '#/components/schemas/_ErrorResponse' }, + '400': ERROR_RESPONSE, }, }, }; @@ -178,7 +187,7 @@ export class RPCApiSpecGenerator { }, }, }, - '400': { $ref: '#/components/schemas/_ErrorResponse' }, + '400': ERROR_RESPONSE, }, }; } @@ -210,7 +219,7 @@ export class RPCApiSpecGenerator { }, }, }, - '400': { $ref: '#/components/schemas/_ErrorResponse' }, + '400': ERROR_RESPONSE, }, }; } @@ -242,7 +251,7 @@ export class RPCApiSpecGenerator { }, }, }, - '400': { $ref: '#/components/schemas/_ErrorResponse' }, + '400': ERROR_RESPONSE, }, }; } @@ -274,7 +283,7 @@ export class RPCApiSpecGenerator { }, }, }, - '400': { $ref: '#/components/schemas/_ErrorResponse' }, + '400': ERROR_RESPONSE, }, }; } @@ -286,7 +295,7 @@ export class RPCApiSpecGenerator { operationId: `proc_${procName}`, responses: { '200': { description: `Result of ${procName}` }, - '400': { $ref: '#/components/schemas/_ErrorResponse' }, + '400': ERROR_RESPONSE, }, }; diff --git a/packages/server/test/openapi/rest-openapi.test.ts b/packages/server/test/openapi/rest-openapi.test.ts index 1a66310a8..8cfd0c12f 100644 --- a/packages/server/test/openapi/rest-openapi.test.ts +++ b/packages/server/test/openapi/rest-openapi.test.ts @@ -124,6 +124,18 @@ describe('REST OpenAPI spec generation', () => { expect(spec.paths['/post/{id}/comments']).toBeDefined(); }); + it('fetch related path has response schema', () => { + // Collection relation: should reference ListResponse + const collectionPath = spec.paths['/user/{id}/posts'] as any; + const collectionSchema = collectionPath.get.responses['200'].content['application/vnd.api+json'].schema; + expect(collectionSchema.$ref).toBe('#/components/schemas/PostListResponse'); + + // Singular relation: should reference Response + const singularPath = spec.paths['/post/{id}/setting'] as any; + const singularSchema = singularPath.get.responses['200'].content['application/vnd.api+json'].schema; + expect(singularSchema.$ref).toBe('#/components/schemas/SettingResponse'); + }); + it('relationship path has correct methods', () => { const relPath = spec.paths['/user/{id}/relationships/posts']; expect(relPath.get).toBeDefined(); From 913798eae9033f02f7b8985e585549f918e729e5 Mon Sep 17 00:00:00 2001 From: ymc9 <104139426+ymc9@users.noreply.github.com> Date: Thu, 19 Mar 2026 16:09:18 -0700 Subject: [PATCH 10/16] fix: precise select/include/omit schemas for rpc spec --- packages/server/src/api/rpc/openapi.ts | 115 ++++++++++++-- .../server/test/openapi/rpc-openapi.test.ts | 146 ++++++++++++++++++ 2 files changed, 248 insertions(+), 13 deletions(-) diff --git a/packages/server/src/api/rpc/openapi.ts b/packages/server/src/api/rpc/openapi.ts index db9cb0771..7fb1de1f9 100644 --- a/packages/server/src/api/rpc/openapi.ts +++ b/packages/server/src/api/rpc/openapi.ts @@ -8,6 +8,7 @@ import { getMetaDescription, isFieldOmitted, isFilterKindIncluded, + isModelIncluded, isOperationIncluded, isProcedureIncluded, } from '../common/spec-utils'; @@ -165,6 +166,12 @@ export class RPCApiSpecGenerator { return upperCaseFirst(op) + 'Args'; } + private modelHasRelations(modelName: string): boolean { + const modelDef = this.schema.models[modelName]; + if (!modelDef) return false; + return Object.values(modelDef.fields).some((f) => f.relation); + } + private buildGetOperation(modelName: string, op: string, tag: string, argsSchemaName: string): Record { return { tags: [tag], @@ -356,10 +363,17 @@ export class RPCApiSpecGenerator { schemas[`${modelName}UpdateInput`] = this.buildUpdateInputSchema(modelName, modelDef); schemas[`${modelName}WhereUniqueInput`] = this.buildWhereUniqueInputSchema(modelName, modelDef); schemas[`${modelName}WhereInput`] = this.buildWhereInputSchema(modelName, modelDef); + schemas[`${modelName}Select`] = this.buildSelectSchema(modelName, modelDef); + if (this.modelHasRelations(modelName)) { + schemas[`${modelName}Include`] = this.buildIncludeSchema(modelName, modelDef); + } + schemas[`${modelName}Omit`] = this.buildOmitSchema(modelName, modelDef); schemas[`${modelName}CreateArgs`] = this.buildCreateArgsSchema(modelName); schemas[`${modelName}CreateManyArgs`] = this.buildCreateManyArgsSchema(modelName); + schemas[`${modelName}CreateManyAndReturnArgs`] = this.buildCreateManyAndReturnArgsSchema(modelName); schemas[`${modelName}UpdateArgs`] = this.buildUpdateArgsSchema(modelName); schemas[`${modelName}UpdateManyArgs`] = this.buildUpdateManyArgsSchema(modelName); + schemas[`${modelName}UpdateManyAndReturnArgs`] = this.buildUpdateManyAndReturnArgsSchema(modelName); schemas[`${modelName}UpsertArgs`] = this.buildUpsertArgsSchema(modelName); schemas[`${modelName}DeleteArgs`] = this.buildDeleteArgsSchema(modelName); schemas[`${modelName}DeleteManyArgs`] = this.buildDeleteManyArgsSchema(modelName); @@ -383,6 +397,51 @@ export class RPCApiSpecGenerator { }; } + private buildSelectSchema(_modelName: string, modelDef: ModelDef): SchemaObject { + const properties: Record = {}; + for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { + if (fieldDef.relation) { + if (!isModelIncluded(fieldDef.type, this.queryOptions)) continue; + properties[fieldName] = this.buildRelationSelectProperty(fieldDef.type); + } else { + properties[fieldName] = { type: 'boolean' }; + } + } + return { type: 'object', properties }; + } + + private buildIncludeSchema(_modelName: string, modelDef: ModelDef): SchemaObject { + const properties: Record = {}; + for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { + if (!fieldDef.relation) continue; + if (!isModelIncluded(fieldDef.type, this.queryOptions)) continue; + properties[fieldName] = this.buildRelationSelectProperty(fieldDef.type); + } + return { type: 'object', properties }; + } + + private buildRelationSelectProperty(relatedModelName: string): SchemaObject { + const nestedProps: Record = { + select: { $ref: `#/components/schemas/${relatedModelName}Select` }, + omit: { $ref: `#/components/schemas/${relatedModelName}Omit` }, + }; + if (this.modelHasRelations(relatedModelName)) { + nestedProps['include'] = { $ref: `#/components/schemas/${relatedModelName}Include` }; + } + return { + oneOf: [{ type: 'boolean' }, { type: 'object', properties: nestedProps }], + }; + } + + private buildOmitSchema(_modelName: string, modelDef: ModelDef): SchemaObject { + const properties: Record = {}; + for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { + if (fieldDef.relation) continue; + properties[fieldName] = { type: 'boolean' }; + } + return { type: 'object', properties }; + } + private buildModelOutputSchema(modelName: string, modelDef: ModelDef): SchemaObject { const properties: Record = {}; const required: string[] = []; @@ -514,13 +573,22 @@ export class RPCApiSpecGenerator { return { type: 'object', properties }; } + private selectIncludeOmitProperties(modelName: string): Record { + return { + select: { $ref: `#/components/schemas/${modelName}Select` }, + ...(this.modelHasRelations(modelName) && { + include: { $ref: `#/components/schemas/${modelName}Include` }, + }), + omit: { $ref: `#/components/schemas/${modelName}Omit` }, + }; + } + private buildCreateArgsSchema(modelName: string): SchemaObject { return { type: 'object', properties: { data: { $ref: `#/components/schemas/${modelName}CreateInput` }, - select: { type: 'object' }, - include: { type: 'object' }, + ...this.selectIncludeOmitProperties(modelName), }, required: ['data'], }; @@ -539,14 +607,27 @@ export class RPCApiSpecGenerator { }; } + private buildCreateManyAndReturnArgsSchema(modelName: string): SchemaObject { + return { + type: 'object', + properties: { + data: { + type: 'array', + items: { $ref: `#/components/schemas/${modelName}CreateInput` }, + }, + ...this.selectIncludeOmitProperties(modelName), + }, + required: ['data'], + }; + } + private buildUpdateArgsSchema(modelName: string): SchemaObject { return { type: 'object', properties: { where: { $ref: `#/components/schemas/${modelName}WhereUniqueInput` }, data: { $ref: `#/components/schemas/${modelName}UpdateInput` }, - select: { type: 'object' }, - include: { type: 'object' }, + ...this.selectIncludeOmitProperties(modelName), }, required: ['where', 'data'], }; @@ -563,6 +644,18 @@ export class RPCApiSpecGenerator { }; } + private buildUpdateManyAndReturnArgsSchema(modelName: string): SchemaObject { + return { + type: 'object', + properties: { + where: { $ref: `#/components/schemas/${modelName}WhereInput` }, + data: { $ref: `#/components/schemas/${modelName}UpdateInput` }, + ...this.selectIncludeOmitProperties(modelName), + }, + required: ['data'], + }; + } + private buildUpsertArgsSchema(modelName: string): SchemaObject { return { type: 'object', @@ -570,8 +663,7 @@ export class RPCApiSpecGenerator { where: { $ref: `#/components/schemas/${modelName}WhereUniqueInput` }, create: { $ref: `#/components/schemas/${modelName}CreateInput` }, update: { $ref: `#/components/schemas/${modelName}UpdateInput` }, - select: { type: 'object' }, - include: { type: 'object' }, + ...this.selectIncludeOmitProperties(modelName), }, required: ['where', 'create', 'update'], }; @@ -582,7 +674,7 @@ export class RPCApiSpecGenerator { type: 'object', properties: { where: { $ref: `#/components/schemas/${modelName}WhereUniqueInput` }, - select: { type: 'object' }, + ...this.selectIncludeOmitProperties(modelName), }, required: ['where'], }; @@ -605,8 +697,7 @@ export class RPCApiSpecGenerator { orderBy: { type: 'object' }, take: { type: 'integer' }, skip: { type: 'integer' }, - select: { type: 'object' }, - include: { type: 'object' }, + ...this.selectIncludeOmitProperties(modelName), }, }; } @@ -616,8 +707,7 @@ export class RPCApiSpecGenerator { type: 'object', properties: { where: { $ref: `#/components/schemas/${modelName}WhereUniqueInput` }, - select: { type: 'object' }, - include: { type: 'object' }, + ...this.selectIncludeOmitProperties(modelName), }, required: ['where'], }; @@ -631,8 +721,7 @@ export class RPCApiSpecGenerator { orderBy: { type: 'object' }, take: { type: 'integer' }, skip: { type: 'integer' }, - select: { type: 'object' }, - include: { type: 'object' }, + ...this.selectIncludeOmitProperties(modelName), }, }; } diff --git a/packages/server/test/openapi/rpc-openapi.test.ts b/packages/server/test/openapi/rpc-openapi.test.ts index 499654893..3f7d7f9a4 100644 --- a/packages/server/test/openapi/rpc-openapi.test.ts +++ b/packages/server/test/openapi/rpc-openapi.test.ts @@ -399,6 +399,152 @@ describe('RPC OpenAPI spec generation - queryOptions', () => { }); }); +describe('RPC OpenAPI spec generation - select/include/omit schemas', () => { + let spec: any; + + beforeAll(async () => { + const client = await createTestClient(schema); + const handler = new RPCApiHandler({ schema: client.$schema }); + spec = await handler.generateSpec(); + }); + + it('Select schema lists all fields with boolean type', () => { + const userSelect = spec.components.schemas['UserSelect']; + expect(userSelect).toBeDefined(); + expect(userSelect.type).toBe('object'); + // Scalar fields are boolean + expect(userSelect.properties['id']).toEqual({ type: 'boolean' }); + expect(userSelect.properties['email']).toEqual({ type: 'boolean' }); + expect(userSelect.properties['createdAt']).toEqual({ type: 'boolean' }); + }); + + it('Select schema allows nested select/include/omit for relation fields', () => { + const userSelect = spec.components.schemas['UserSelect']; + // Relation field: oneOf [boolean, nested object] + const postsField = userSelect.properties['posts']; + expect(postsField.oneOf).toHaveLength(2); + expect(postsField.oneOf[0]).toEqual({ type: 'boolean' }); + const nested = postsField.oneOf[1]; + expect(nested.type).toBe('object'); + expect(nested.properties['select'].$ref).toBe('#/components/schemas/PostSelect'); + expect(nested.properties['include'].$ref).toBe('#/components/schemas/PostInclude'); + expect(nested.properties['omit'].$ref).toBe('#/components/schemas/PostOmit'); + }); + + it('Select schema includes FK fields', () => { + const postSelect = spec.components.schemas['PostSelect']; + expect(postSelect.properties['authorId']).toEqual({ type: 'boolean' }); + }); + + it('Include schema lists only relation fields', () => { + const userInclude = spec.components.schemas['UserInclude']; + expect(userInclude).toBeDefined(); + expect(userInclude.type).toBe('object'); + // Relation field present with nested select/include/omit + expect(userInclude.properties['posts']).toBeDefined(); + expect(userInclude.properties['posts'].oneOf).toHaveLength(2); + // Scalar fields absent + expect(userInclude.properties['id']).toBeUndefined(); + expect(userInclude.properties['email']).toBeUndefined(); + }); + + it('Include schema is not generated for models without relations', async () => { + const noRelSchema = ` +model Item { + id Int @id @default(autoincrement()) + name String +} +`; + const client = await createTestClient(noRelSchema); + const handler = new RPCApiHandler({ schema: client.$schema }); + const s = await handler.generateSpec(); + expect(s.components?.schemas?.['ItemSelect']).toBeDefined(); + expect(s.components?.schemas?.['ItemInclude']).toBeUndefined(); + expect(s.components?.schemas?.['ItemOmit']).toBeDefined(); + // Args should not have include + const findManyArgs = s.components?.schemas?.['ItemFindManyArgs'] as any; + expect(findManyArgs.properties['select']).toBeDefined(); + expect(findManyArgs.properties['include']).toBeUndefined(); + expect(findManyArgs.properties['omit']).toBeDefined(); + }); + + it('Omit schema lists only non-relation fields', () => { + const userOmit = spec.components.schemas['UserOmit']; + expect(userOmit).toBeDefined(); + expect(userOmit.type).toBe('object'); + // Scalar fields present + expect(userOmit.properties['id']).toEqual({ type: 'boolean' }); + expect(userOmit.properties['email']).toEqual({ type: 'boolean' }); + // Relation fields absent + expect(userOmit.properties['posts']).toBeUndefined(); + + // FK fields included + const postOmit = spec.components.schemas['PostOmit']; + expect(postOmit.properties['authorId']).toEqual({ type: 'boolean' }); + }); + + it('Args schemas reference Select/Include/Omit via $ref', () => { + const createArgs = spec.components.schemas['UserCreateArgs']; + expect(createArgs.properties['select'].$ref).toBe('#/components/schemas/UserSelect'); + expect(createArgs.properties['include'].$ref).toBe('#/components/schemas/UserInclude'); + expect(createArgs.properties['omit'].$ref).toBe('#/components/schemas/UserOmit'); + + const findManyArgs = spec.components.schemas['UserFindManyArgs']; + expect(findManyArgs.properties['select'].$ref).toBe('#/components/schemas/UserSelect'); + expect(findManyArgs.properties['include'].$ref).toBe('#/components/schemas/UserInclude'); + expect(findManyArgs.properties['omit'].$ref).toBe('#/components/schemas/UserOmit'); + }); + + it('createManyAndReturn and updateManyAndReturn args have select/include/omit', () => { + const createManyAndReturnArgs = spec.components.schemas['UserCreateManyAndReturnArgs']; + expect(createManyAndReturnArgs).toBeDefined(); + expect(createManyAndReturnArgs.properties['data']).toBeDefined(); + expect(createManyAndReturnArgs.properties['select'].$ref).toBe('#/components/schemas/UserSelect'); + expect(createManyAndReturnArgs.properties['include'].$ref).toBe('#/components/schemas/UserInclude'); + expect(createManyAndReturnArgs.properties['omit'].$ref).toBe('#/components/schemas/UserOmit'); + + const updateManyAndReturnArgs = spec.components.schemas['UserUpdateManyAndReturnArgs']; + expect(updateManyAndReturnArgs).toBeDefined(); + expect(updateManyAndReturnArgs.properties['data']).toBeDefined(); + expect(updateManyAndReturnArgs.properties['select'].$ref).toBe('#/components/schemas/UserSelect'); + expect(updateManyAndReturnArgs.properties['include'].$ref).toBe('#/components/schemas/UserInclude'); + expect(updateManyAndReturnArgs.properties['omit'].$ref).toBe('#/components/schemas/UserOmit'); + }); + + it('createMany and updateMany args do not have select/include/omit', () => { + const createManyArgs = spec.components.schemas['UserCreateManyArgs']; + expect(createManyArgs.properties['select']).toBeUndefined(); + expect(createManyArgs.properties['include']).toBeUndefined(); + expect(createManyArgs.properties['omit']).toBeUndefined(); + + const updateManyArgs = spec.components.schemas['UserUpdateManyArgs']; + expect(updateManyArgs.properties['select']).toBeUndefined(); + expect(updateManyArgs.properties['include']).toBeUndefined(); + expect(updateManyArgs.properties['omit']).toBeUndefined(); + }); + + it('select/include exclude relations to excluded models', async () => { + const client = await createTestClient(schema); + const handler = new RPCApiHandler({ + schema: client.$schema, + queryOptions: { slicing: { excludedModels: ['Post'] as any } }, + }); + const s = await handler.generateSpec(); + + const userSelect = s.components?.schemas?.['UserSelect'] as any; + expect(userSelect.properties['id']).toBeDefined(); + // posts relation to excluded Post model should be absent + expect(userSelect.properties['posts']).toBeUndefined(); + + // Include should not have posts either + // User still has relations in schema, but all are excluded so Include may or may not exist + const userInclude = s.components?.schemas?.['UserInclude'] as any; + if (userInclude) { + expect(userInclude.properties['posts']).toBeUndefined(); + } + }); +}); + describe('RPC OpenAPI spec generation - with enum', () => { it('enum schemas appear in components', async () => { const enumSchema = ` From 3983beb5cd9a066569cda0c5eaeb02398504c754 Mon Sep 17 00:00:00 2001 From: ymc9 <104139426+ymc9@users.noreply.github.com> Date: Thu, 19 Mar 2026 16:35:45 -0700 Subject: [PATCH 11/16] fix: detailed spec for count/aggregate/groupby --- packages/server/src/api/rpc/openapi.ts | 252 +++++++++++++++++- .../server/test/openapi/rpc-openapi.test.ts | 166 ++++++++++++ 2 files changed, 404 insertions(+), 14 deletions(-) diff --git a/packages/server/src/api/rpc/openapi.ts b/packages/server/src/api/rpc/openapi.ts index 7fb1de1f9..13aa5b2ed 100644 --- a/packages/server/src/api/rpc/openapi.ts +++ b/packages/server/src/api/rpc/openapi.ts @@ -76,8 +76,9 @@ export class RPCApiSpecGenerator { for (const op of readOps) { if (!isOperationIncluded(modelName, op, this.queryOptions)) continue; const argsSchemaName = `${modelName}${this.opToArgsSchema(op)}`; + const responseSchemaName = this.opToResponseSchema(modelName, op); paths[`/${modelPath}/${op}`] = { - get: this.buildGetOperation(modelName, op, tag, argsSchemaName), + get: this.buildGetOperation(modelName, op, tag, argsSchemaName, responseSchemaName), } as OpenAPIV3_1.PathItemObject; } @@ -97,6 +98,7 @@ export class RPCApiSpecGenerator { for (const { op, method } of writeOps) { if (!isOperationIncluded(modelName, op, this.queryOptions)) continue; const argsSchemaName = `${modelName}${this.opToArgsSchema(op)}`; + const responseSchemaName = this.opToResponseSchema(modelName, op); const buildOp = method === 'post' ? this.buildPostOperation @@ -104,7 +106,7 @@ export class RPCApiSpecGenerator { ? this.buildPatchOperation : this.buildDeleteOperation; paths[`/${modelPath}/${op}`] = { - [method]: buildOp.call(this, modelName, op, tag, argsSchemaName), + [method]: buildOp.call(this, modelName, op, tag, argsSchemaName, responseSchemaName), }; } } @@ -166,13 +168,43 @@ export class RPCApiSpecGenerator { return upperCaseFirst(op) + 'Args'; } + private opToResponseSchema(modelName: string, op: string): string { + switch (op) { + case 'findMany': + case 'createManyAndReturn': + case 'updateManyAndReturn': + return `${modelName}ListResponse`; + case 'createMany': + case 'updateMany': + case 'deleteMany': + return '_BatchResponse'; + case 'count': + return `${modelName}CountResponse`; + case 'aggregate': + return `${modelName}AggregateResponse`; + case 'groupBy': + return `${modelName}GroupByResponse`; + case 'exists': + return '_ExistsResponse'; + default: + // findUnique, findFirst, create, update, upsert, delete + return `${modelName}Response`; + } + } + private modelHasRelations(modelName: string): boolean { const modelDef = this.schema.models[modelName]; if (!modelDef) return false; return Object.values(modelDef.fields).some((f) => f.relation); } - private buildGetOperation(modelName: string, op: string, tag: string, argsSchemaName: string): Record { + private buildGetOperation( + modelName: string, + op: string, + tag: string, + argsSchemaName: string, + responseSchemaName: string, + ): Record { return { tags: [tag], summary: `${op} ${modelName}`, @@ -190,7 +222,7 @@ export class RPCApiSpecGenerator { description: `Result of ${op}`, content: { 'application/json': { - schema: { $ref: `#/components/schemas/${modelName}Response` }, + schema: { $ref: `#/components/schemas/${responseSchemaName}` }, }, }, }, @@ -204,6 +236,7 @@ export class RPCApiSpecGenerator { op: string, tag: string, argsSchemaName: string, + responseSchemaName: string, ): Record { return { tags: [tag], @@ -222,7 +255,7 @@ export class RPCApiSpecGenerator { description: `Result of ${op}`, content: { 'application/json': { - schema: { $ref: `#/components/schemas/${modelName}Response` }, + schema: { $ref: `#/components/schemas/${responseSchemaName}` }, }, }, }, @@ -236,6 +269,7 @@ export class RPCApiSpecGenerator { op: string, tag: string, argsSchemaName: string, + responseSchemaName: string, ): Record { return { tags: [tag], @@ -254,7 +288,7 @@ export class RPCApiSpecGenerator { description: `Result of ${op}`, content: { 'application/json': { - schema: { $ref: `#/components/schemas/${modelName}Response` }, + schema: { $ref: `#/components/schemas/${responseSchemaName}` }, }, }, }, @@ -268,6 +302,7 @@ export class RPCApiSpecGenerator { op: string, tag: string, argsSchemaName: string, + responseSchemaName: string, ): Record { return { tags: [tag], @@ -286,7 +321,7 @@ export class RPCApiSpecGenerator { description: `Result of ${op}`, content: { 'application/json': { - schema: { $ref: `#/components/schemas/${modelName}Response` }, + schema: { $ref: `#/components/schemas/${responseSchemaName}` }, }, }, }, @@ -348,6 +383,26 @@ export class RPCApiSpecGenerator { }, }; + // Shared response schemas + schemas['_BatchResponse'] = { + type: 'object', + properties: { + data: { + type: 'object', + properties: { count: { type: 'integer' } }, + required: ['count'], + }, + meta: { $ref: '#/components/schemas/_Meta' }, + }, + }; + schemas['_ExistsResponse'] = { + type: 'object', + properties: { + data: { type: 'boolean' }, + meta: { $ref: '#/components/schemas/_Meta' }, + }, + }; + // Per-enum schemas if (this.schema.enums) { for (const [enumName, enumDef] of Object.entries(this.schema.enums)) { @@ -385,6 +440,51 @@ export class RPCApiSpecGenerator { schemas[`${modelName}GroupByArgs`] = this.buildGroupByArgsSchema(modelName); schemas[`${modelName}ExistsArgs`] = this.buildExistsArgsSchema(modelName); schemas[`${modelName}Response`] = this.buildResponseSchema(modelName); + schemas[`${modelName}CountAggregateOutputType`] = this.buildCountAggregateOutputTypeSchema(modelName, modelDef); + schemas[`${modelName}MinAggregateOutputType`] = this.buildMinAggregateOutputTypeSchema(modelName, modelDef); + schemas[`${modelName}MaxAggregateOutputType`] = this.buildMaxAggregateOutputTypeSchema(modelName, modelDef); + if (this.modelHasNumericFields(modelDef)) { + schemas[`${modelName}AvgAggregateOutputType`] = this.buildAvgAggregateOutputTypeSchema(modelName, modelDef); + schemas[`${modelName}SumAggregateOutputType`] = this.buildSumAggregateOutputTypeSchema(modelName, modelDef); + } + schemas[`Aggregate${modelName}`] = this.buildAggregateSchema(modelName, modelDef); + schemas[`${modelName}GroupByOutputType`] = this.buildGroupByOutputTypeSchema(modelName, modelDef); + schemas[`${modelName}CountResponse`] = { + type: 'object', + properties: { + data: { + oneOf: [ + { type: 'integer' }, + { $ref: `#/components/schemas/${modelName}CountAggregateOutputType` }, + ], + }, + meta: { $ref: '#/components/schemas/_Meta' }, + }, + }; + schemas[`${modelName}ListResponse`] = { + type: 'object', + properties: { + data: { type: 'array', items: { $ref: `#/components/schemas/${modelName}` } }, + meta: { $ref: '#/components/schemas/_Meta' }, + }, + }; + schemas[`${modelName}AggregateResponse`] = { + type: 'object', + properties: { + data: { $ref: `#/components/schemas/Aggregate${modelName}` }, + meta: { $ref: '#/components/schemas/_Meta' }, + }, + }; + schemas[`${modelName}GroupByResponse`] = { + type: 'object', + properties: { + data: { + type: 'array', + items: { $ref: `#/components/schemas/${modelName}GroupByOutputType` }, + }, + meta: { $ref: '#/components/schemas/_Meta' }, + }, + }; } return schemas; @@ -540,13 +640,13 @@ export class RPCApiSpecGenerator { return { type: 'object', properties }; } - private buildWhereInputSchema(_modelName: string, modelDef: ModelDef): SchemaObject { + private buildWhereInputSchema(modelName: string, modelDef: ModelDef): SchemaObject { const properties: Record = {}; for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { if (fieldDef.relation) continue; if (fieldDef.omit) continue; - const filterSchema = this.buildFieldFilterSchema(_modelName, fieldName, fieldDef); + const filterSchema = this.buildFieldFilterSchema(modelName, fieldName, fieldDef); if (filterSchema) { properties[fieldName] = filterSchema; } @@ -555,18 +655,18 @@ export class RPCApiSpecGenerator { // Logical combinators properties['AND'] = { oneOf: [ - { $ref: `#/components/schemas/_${_modelName}WhereInput` }, - { type: 'array', items: { $ref: `#/components/schemas/_${_modelName}WhereInput` } }, + { $ref: `#/components/schemas/${modelName}WhereInput` }, + { type: 'array', items: { $ref: `#/components/schemas/${modelName}WhereInput` } }, ], }; properties['OR'] = { type: 'array', - items: { $ref: `#/components/schemas/_${_modelName}WhereInput` }, + items: { $ref: `#/components/schemas/${modelName}WhereInput` }, }; properties['NOT'] = { oneOf: [ - { $ref: `#/components/schemas/_${_modelName}WhereInput` }, - { type: 'array', items: { $ref: `#/components/schemas/_${_modelName}WhereInput` } }, + { $ref: `#/components/schemas/${modelName}WhereInput` }, + { type: 'array', items: { $ref: `#/components/schemas/${modelName}WhereInput` } }, ], }; @@ -730,6 +830,7 @@ export class RPCApiSpecGenerator { return { type: 'object', properties: { + select: { $ref: `#/components/schemas/${modelName}Select` }, where: { $ref: `#/components/schemas/${modelName}WhereInput` }, take: { type: 'integer' }, skip: { type: 'integer' }, @@ -737,6 +838,129 @@ export class RPCApiSpecGenerator { }; } + private modelHasNumericFields(modelDef: ModelDef): boolean { + return Object.values(modelDef.fields).some( + (f) => !f.relation && (f.type === 'Int' || f.type === 'Float' || f.type === 'BigInt' || f.type === 'Decimal') + ); + } + + private buildCountAggregateOutputTypeSchema(_modelName: string, modelDef: ModelDef): SchemaObject { + const properties: Record = {}; + const required: string[] = []; + for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { + if (fieldDef.relation) continue; + properties[fieldName] = { type: 'integer' }; + required.push(fieldName); + } + properties['_all'] = { type: 'integer' }; + required.push('_all'); + return { type: 'object', properties, required }; + } + + private buildMinAggregateOutputTypeSchema(_modelName: string, modelDef: ModelDef): SchemaObject { + const properties: Record = {}; + for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { + if (fieldDef.relation) continue; + properties[fieldName] = { oneOf: [{ type: 'null' as const }, this.typeToSchema(fieldDef.type)] }; + } + return { type: 'object', properties }; + } + + private buildMaxAggregateOutputTypeSchema(_modelName: string, modelDef: ModelDef): SchemaObject { + const properties: Record = {}; + for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { + if (fieldDef.relation) continue; + properties[fieldName] = { oneOf: [{ type: 'null' as const }, this.typeToSchema(fieldDef.type)] }; + } + return { type: 'object', properties }; + } + + private buildAvgAggregateOutputTypeSchema(_modelName: string, modelDef: ModelDef): SchemaObject { + const properties: Record = {}; + for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { + if (fieldDef.relation) continue; + if (fieldDef.type !== 'Int' && fieldDef.type !== 'Float' && fieldDef.type !== 'BigInt' && fieldDef.type !== 'Decimal') + continue; + // avg always returns a float + properties[fieldName] = { oneOf: [{ type: 'null' as const }, { type: 'number' }] }; + } + return { type: 'object', properties }; + } + + private buildSumAggregateOutputTypeSchema(_modelName: string, modelDef: ModelDef): SchemaObject { + const properties: Record = {}; + for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { + if (fieldDef.relation) continue; + if (fieldDef.type !== 'Int' && fieldDef.type !== 'Float' && fieldDef.type !== 'BigInt' && fieldDef.type !== 'Decimal') + continue; + // sum preserves the original type + properties[fieldName] = { oneOf: [{ type: 'null' as const }, this.typeToSchema(fieldDef.type)] }; + } + return { type: 'object', properties }; + } + + private buildAggregateSchema(modelName: string, modelDef: ModelDef): SchemaObject { + const properties: Record = { + _count: { + oneOf: [{ type: 'null' as const }, { $ref: `#/components/schemas/${modelName}CountAggregateOutputType` }], + }, + _min: { + oneOf: [{ type: 'null' as const }, { $ref: `#/components/schemas/${modelName}MinAggregateOutputType` }], + }, + _max: { + oneOf: [{ type: 'null' as const }, { $ref: `#/components/schemas/${modelName}MaxAggregateOutputType` }], + }, + }; + if (this.modelHasNumericFields(modelDef)) { + properties['_avg'] = { + oneOf: [{ type: 'null' as const }, { $ref: `#/components/schemas/${modelName}AvgAggregateOutputType` }], + }; + properties['_sum'] = { + oneOf: [{ type: 'null' as const }, { $ref: `#/components/schemas/${modelName}SumAggregateOutputType` }], + }; + } + return { type: 'object', properties }; + } + + private buildGroupByOutputTypeSchema(modelName: string, modelDef: ModelDef): SchemaObject { + const properties: Record = {}; + const required: string[] = []; + + // Scalar fields with proper types + for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { + if (fieldDef.relation) continue; + properties[fieldName] = this.fieldToSchema(fieldDef); + if (!fieldDef.optional && !fieldDef.array) { + required.push(fieldName); + } + } + + // Aggregate properties + properties['_count'] = { + oneOf: [{ type: 'null' as const }, { $ref: `#/components/schemas/${modelName}CountAggregateOutputType` }], + }; + properties['_min'] = { + oneOf: [{ type: 'null' as const }, { $ref: `#/components/schemas/${modelName}MinAggregateOutputType` }], + }; + properties['_max'] = { + oneOf: [{ type: 'null' as const }, { $ref: `#/components/schemas/${modelName}MaxAggregateOutputType` }], + }; + if (this.modelHasNumericFields(modelDef)) { + properties['_avg'] = { + oneOf: [{ type: 'null' as const }, { $ref: `#/components/schemas/${modelName}AvgAggregateOutputType` }], + }; + properties['_sum'] = { + oneOf: [{ type: 'null' as const }, { $ref: `#/components/schemas/${modelName}SumAggregateOutputType` }], + }; + } + + const result: SchemaObject = { type: 'object', properties }; + if (required.length > 0) { + result.required = required; + } + return result; + } + private buildAggregateArgsSchema(modelName: string): SchemaObject { return { type: 'object', diff --git a/packages/server/test/openapi/rpc-openapi.test.ts b/packages/server/test/openapi/rpc-openapi.test.ts index 3f7d7f9a4..6cf1a8c5d 100644 --- a/packages/server/test/openapi/rpc-openapi.test.ts +++ b/packages/server/test/openapi/rpc-openapi.test.ts @@ -609,6 +609,172 @@ model Post { }); }); +describe('RPC OpenAPI spec generation - aggregate and groupby schemas', () => { + let spec: any; + + beforeAll(async () => { + const client = await createTestClient(schema); + const handler = new RPCApiHandler({ schema: client.$schema }); + spec = await handler.generateSpec(); + }); + + describe('aggregate and groupby schemas', () => { + it('Aggregate schema has _count, _min, _max', () => { + const agg = spec.components.schemas['AggregateUser']; + expect(agg).toBeDefined(); + expect(agg.properties._count.oneOf).toEqual([ + { type: 'null' }, + { $ref: '#/components/schemas/UserCountAggregateOutputType' }, + ]); + expect(agg.properties._min.oneOf).toEqual([ + { type: 'null' }, + { $ref: '#/components/schemas/UserMinAggregateOutputType' }, + ]); + expect(agg.properties._max.oneOf).toEqual([ + { type: 'null' }, + { $ref: '#/components/schemas/UserMaxAggregateOutputType' }, + ]); + }); + + it('Aggregate schema includes _avg and _sum for models with numeric fields', () => { + const agg = spec.components.schemas['AggregatePost']; + expect(agg).toBeDefined(); + expect(agg.properties._avg).toBeDefined(); + expect(agg.properties._avg.oneOf).toEqual([ + { type: 'null' }, + { $ref: '#/components/schemas/PostAvgAggregateOutputType' }, + ]); + expect(agg.properties._sum).toBeDefined(); + expect(agg.properties._sum.oneOf).toEqual([ + { type: 'null' }, + { $ref: '#/components/schemas/PostSumAggregateOutputType' }, + ]); + }); + + it('Aggregate schema omits _avg and _sum for models without numeric fields', () => { + const agg = spec.components.schemas['AggregateUser']; + expect(agg.properties._avg).toBeUndefined(); + expect(agg.properties._sum).toBeUndefined(); + }); + + it('MinAggregateOutputType has all non-relation fields as nullable', () => { + const min = spec.components.schemas['UserMinAggregateOutputType']; + expect(min).toBeDefined(); + expect(min.properties.id.oneOf).toEqual([{ type: 'null' }, { type: 'string' }]); + expect(min.properties.email.oneOf).toEqual([{ type: 'null' }, { type: 'string' }]); + expect(min.properties.createdAt.oneOf).toEqual([{ type: 'null' }, { type: 'string', format: 'date-time' }]); + // No relation fields + expect(min.properties.posts).toBeUndefined(); + }); + + it('AvgAggregateOutputType only has numeric fields as nullable number', () => { + const avg = spec.components.schemas['PostAvgAggregateOutputType']; + expect(avg).toBeDefined(); + expect(avg.properties.viewCount.oneOf).toEqual([{ type: 'null' }, { type: 'number' }]); + // Non-numeric fields excluded + expect(avg.properties.title).toBeUndefined(); + expect(avg.properties.id).toBeUndefined(); + }); + + it('SumAggregateOutputType only has numeric fields preserving original type', () => { + const sum = spec.components.schemas['PostSumAggregateOutputType']; + expect(sum).toBeDefined(); + expect(sum.properties.viewCount.oneOf).toEqual([{ type: 'null' }, { type: 'integer' }]); + expect(sum.properties.title).toBeUndefined(); + }); + + it('GroupByOutputType has scalar fields and aggregate properties', () => { + const groupBy = spec.components.schemas['UserGroupByOutputType']; + expect(groupBy).toBeDefined(); + // Scalar fields with proper types + expect(groupBy.properties.id).toEqual({ type: 'string' }); + expect(groupBy.properties.email).toEqual({ type: 'string' }); + expect(groupBy.properties.createdAt).toEqual({ type: 'string', format: 'date-time' }); + // Required non-nullable fields + expect(groupBy.required).toContain('id'); + expect(groupBy.required).toContain('email'); + // No relation fields + expect(groupBy.properties.posts).toBeUndefined(); + // Aggregate properties + expect(groupBy.properties._count).toBeDefined(); + expect(groupBy.properties._min).toBeDefined(); + expect(groupBy.properties._max).toBeDefined(); + }); + + it('GroupByOutputType includes _avg and _sum for models with numeric fields', () => { + const groupBy = spec.components.schemas['PostGroupByOutputType']; + expect(groupBy).toBeDefined(); + expect(groupBy.properties._avg).toBeDefined(); + expect(groupBy.properties._sum).toBeDefined(); + // viewCount is non-optional so should be required + expect(groupBy.properties.viewCount).toEqual({ type: 'integer' }); + expect(groupBy.required).toContain('viewCount'); + }); + + it('AggregateResponse references Aggregate schema', () => { + const resp = spec.components.schemas['UserAggregateResponse']; + expect(resp.properties.data).toEqual({ $ref: '#/components/schemas/AggregateUser' }); + expect(resp.properties.meta).toEqual({ $ref: '#/components/schemas/_Meta' }); + }); + + it('GroupByResponse references GroupByOutputType as array', () => { + const resp = spec.components.schemas['UserGroupByResponse']; + expect(resp.properties.data).toEqual({ + type: 'array', + items: { $ref: '#/components/schemas/UserGroupByOutputType' }, + }); + expect(resp.properties.meta).toEqual({ $ref: '#/components/schemas/_Meta' }); + }); + }); + + describe('count schemas', () => { + it('CountAggregateOutputType has all non-relation fields as integer plus _all', () => { + const countType = spec.components.schemas['UserCountAggregateOutputType']; + expect(countType).toBeDefined(); + expect(countType.type).toBe('object'); + // All non-relation fields as integer + expect(countType.properties.id).toEqual({ type: 'integer' }); + expect(countType.properties.email).toEqual({ type: 'integer' }); + expect(countType.properties.createdAt).toEqual({ type: 'integer' }); + expect(countType.properties.updatedAt).toEqual({ type: 'integer' }); + // _all field + expect(countType.properties._all).toEqual({ type: 'integer' }); + // No relation fields + expect(countType.properties.posts).toBeUndefined(); + // All fields required + expect(countType.required).toContain('id'); + expect(countType.required).toContain('email'); + expect(countType.required).toContain('_all'); + }); + + it('CountResponse data is oneOf integer or CountAggregateOutputType', () => { + const resp = spec.components.schemas['UserCountResponse']; + expect(resp).toBeDefined(); + expect(resp.properties.data.oneOf).toEqual([ + { type: 'integer' }, + { $ref: '#/components/schemas/UserCountAggregateOutputType' }, + ]); + expect(resp.properties.meta).toEqual({ $ref: '#/components/schemas/_Meta' }); + }); + + it('CountArgs has select and where', () => { + const args = spec.components.schemas['UserCountArgs']; + expect(args).toBeDefined(); + expect(args.properties.select).toEqual({ $ref: '#/components/schemas/UserSelect' }); + expect(args.properties.where).toEqual({ $ref: '#/components/schemas/UserWhereInput' }); + expect(args.properties.take).toEqual({ type: 'integer' }); + expect(args.properties.skip).toEqual({ type: 'integer' }); + }); + + it('CountAggregateOutputType includes FK fields', () => { + const countType = spec.components.schemas['PostCountAggregateOutputType']; + expect(countType).toBeDefined(); + expect(countType.properties.authorId).toEqual({ type: 'integer' }); + expect(countType.required).toContain('authorId'); + }); + }); +}); + describe('RPC OpenAPI spec generation - with procedures', () => { it('procedure paths are generated', async () => { const schemaWithProc = ` From 6ab9b8ad495ec7f29a5ad3e3b151113f9b5c7174 Mon Sep 17 00:00:00 2001 From: ymc9 <104139426+ymc9@users.noreply.github.com> Date: Thu, 19 Mar 2026 18:51:08 -0700 Subject: [PATCH 12/16] refactor: consolidate OpenAPI baseline tests and add spec validation Merge migrated baseline tests into main test files, add @readme/openapi-parser validation, and regenerate baselines with 4-space indent. Co-Authored-By: Claude Opus 4.6 --- packages/server/package.json | 1 + packages/server/src/api/rest/openapi.ts | 5 - .../test/openapi/baseline/rest.baseline.yaml | 3312 ++++++++++ .../test/openapi/baseline/rpc.baseline.yaml | 2036 ++++++ .../baseline/rest-3.1.0.baseline.yaml | 3279 --------- .../rest-type-coverage-3.1.0.baseline.yaml | 876 --- .../baseline/rpc-3.1.0-omit.baseline.yaml | 3058 --------- .../migrated/baseline/rpc-3.1.0.baseline.yaml | 5853 ----------------- .../rpc-type-coverage-3.1.0.baseline.yaml | 3174 --------- .../openapi/migrated/rest-migrated.test.ts | 220 - .../openapi/migrated/rpc-migrated.test.ts | 198 - .../server/test/openapi/rest-openapi.test.ts | 37 +- .../server/test/openapi/rpc-openapi.test.ts | 33 + pnpm-lock.yaml | 94 +- 14 files changed, 5506 insertions(+), 16670 deletions(-) create mode 100644 packages/server/test/openapi/baseline/rest.baseline.yaml create mode 100644 packages/server/test/openapi/baseline/rpc.baseline.yaml delete mode 100644 packages/server/test/openapi/migrated/baseline/rest-3.1.0.baseline.yaml delete mode 100644 packages/server/test/openapi/migrated/baseline/rest-type-coverage-3.1.0.baseline.yaml delete mode 100644 packages/server/test/openapi/migrated/baseline/rpc-3.1.0-omit.baseline.yaml delete mode 100644 packages/server/test/openapi/migrated/baseline/rpc-3.1.0.baseline.yaml delete mode 100644 packages/server/test/openapi/migrated/baseline/rpc-type-coverage-3.1.0.baseline.yaml delete mode 100644 packages/server/test/openapi/migrated/rest-migrated.test.ts delete mode 100644 packages/server/test/openapi/migrated/rpc-migrated.test.ts diff --git a/packages/server/package.json b/packages/server/package.json index b4904c31e..7fbc5e86a 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -132,6 +132,7 @@ "zod-validation-error": "catalog:" }, "devDependencies": { + "@readme/openapi-parser": "^6.0.0", "@sveltejs/kit": "catalog:", "@types/body-parser": "^1.19.6", "@types/express": "^5.0.0", diff --git a/packages/server/src/api/rest/openapi.ts b/packages/server/src/api/rest/openapi.ts index 4a077667f..e5b238d58 100644 --- a/packages/server/src/api/rest/openapi.ts +++ b/packages/server/src/api/rest/openapi.ts @@ -38,10 +38,6 @@ export class RestApiSpecGenerator { return this.handlerOptions.schema; } - private get endpoint(): string { - return this.handlerOptions.endpoint; - } - private get modelNameMapping(): Record { const mapping: Record = {}; if (this.handlerOptions.modelNameMapping) { @@ -65,7 +61,6 @@ export class RestApiSpecGenerator { ...(options?.description && { description: options.description }), ...(options?.summary && { summary: options.summary }), }, - servers: [{ url: this.endpoint }], tags: this.generateTags(), paths: this.generatePaths(), components: { diff --git a/packages/server/test/openapi/baseline/rest.baseline.yaml b/packages/server/test/openapi/baseline/rest.baseline.yaml new file mode 100644 index 000000000..5111ca88a --- /dev/null +++ b/packages/server/test/openapi/baseline/rest.baseline.yaml @@ -0,0 +1,3312 @@ +openapi: 3.1.0 +info: + title: ZenStack Generated API + version: 1.0.0 +tags: + - name: user + description: User operations + - name: profile + description: Profile operations + - name: post + description: Post operations + - name: comment + description: Comment operations + - name: setting + description: Setting operations + - name: postLike + description: PostLike operations + - name: postLikeInfo + description: PostLikeInfo operations +paths: + /user: + get: + tags: + - user + summary: List User resources + operationId: listUser + parameters: + - $ref: "#/components/parameters/include" + - $ref: "#/components/parameters/sort" + - $ref: "#/components/parameters/pageOffset" + - $ref: "#/components/parameters/pageLimit" + - name: filter[id] + in: query + schema: + type: string + description: Filter by User ID + - name: filter[createdAt] + in: query + schema: + type: string + description: Filter by createdAt + - name: filter[createdAt][$lt] + in: query + schema: + type: string + - name: filter[createdAt][$lte] + in: query + schema: + type: string + - name: filter[createdAt][$gt] + in: query + schema: + type: string + - name: filter[createdAt][$gte] + in: query + schema: + type: string + - name: filter[updatedAt] + in: query + schema: + type: string + description: Filter by updatedAt + - name: filter[updatedAt][$lt] + in: query + schema: + type: string + - name: filter[updatedAt][$lte] + in: query + schema: + type: string + - name: filter[updatedAt][$gt] + in: query + schema: + type: string + - name: filter[updatedAt][$gte] + in: query + schema: + type: string + - name: filter[email] + in: query + schema: + type: string + description: Filter by email + - name: filter[email][$contains] + in: query + schema: + type: string + - name: filter[email][$icontains] + in: query + schema: + type: string + - name: filter[email][$search] + in: query + schema: + type: string + - name: filter[email][$startsWith] + in: query + schema: + type: string + - name: filter[email][$endsWith] + in: query + schema: + type: string + - name: filter[address] + in: query + schema: + type: string + description: Filter by address + - name: filter[someJson] + in: query + schema: + type: string + description: Filter by someJson + responses: + "200": + description: List of User resources + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/UserListResponse" + "400": &a1 + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" + post: + tags: + - user + summary: Create a User resource + operationId: createUser + requestBody: + required: true + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/UserCreateRequest" + responses: + "201": + description: Created User resource + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/UserResponse" + "400": *a1 + /user/{id}: + get: + tags: + - user + summary: Get a User resource by ID + operationId: getUser + parameters: + - &a2 + $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/include" + responses: + "200": + description: User resource + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/UserResponse" + "404": *a1 + patch: + tags: + - user + summary: Update a User resource + operationId: updateUser + parameters: + - *a2 + requestBody: + required: true + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/UserUpdateRequest" + responses: + "200": + description: Updated User resource + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/UserResponse" + "400": *a1 + "404": *a1 + delete: + tags: + - user + summary: Delete a User resource + operationId: deleteUser + parameters: + - *a2 + responses: + "200": + description: Deleted successfully + "404": *a1 + /user/{id}/posts: + get: + tags: + - user + summary: Fetch related Post for User + operationId: getUser_posts + parameters: + - $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/include" + - $ref: "#/components/parameters/sort" + - $ref: "#/components/parameters/pageOffset" + - $ref: "#/components/parameters/pageLimit" + - name: filter[id] + in: query + schema: + type: string + description: Filter by Post ID + - name: filter[createdAt] + in: query + schema: + type: string + description: Filter by createdAt + - name: filter[createdAt][$lt] + in: query + schema: + type: string + - name: filter[createdAt][$lte] + in: query + schema: + type: string + - name: filter[createdAt][$gt] + in: query + schema: + type: string + - name: filter[createdAt][$gte] + in: query + schema: + type: string + - name: filter[updatedAt] + in: query + schema: + type: string + description: Filter by updatedAt + - name: filter[updatedAt][$lt] + in: query + schema: + type: string + - name: filter[updatedAt][$lte] + in: query + schema: + type: string + - name: filter[updatedAt][$gt] + in: query + schema: + type: string + - name: filter[updatedAt][$gte] + in: query + schema: + type: string + - name: filter[title] + in: query + schema: + type: string + description: Filter by title + - name: filter[title][$contains] + in: query + schema: + type: string + - name: filter[title][$icontains] + in: query + schema: + type: string + - name: filter[title][$search] + in: query + schema: + type: string + - name: filter[title][$startsWith] + in: query + schema: + type: string + - name: filter[title][$endsWith] + in: query + schema: + type: string + - name: filter[published] + in: query + schema: + type: string + description: Filter by published + - name: filter[publishedAt] + in: query + schema: + type: string + description: Filter by publishedAt + - name: filter[publishedAt][$lt] + in: query + schema: + type: string + - name: filter[publishedAt][$lte] + in: query + schema: + type: string + - name: filter[publishedAt][$gt] + in: query + schema: + type: string + - name: filter[publishedAt][$gte] + in: query + schema: + type: string + - name: filter[viewCount] + in: query + schema: + type: string + description: Filter by viewCount + - name: filter[viewCount][$lt] + in: query + schema: + type: string + - name: filter[viewCount][$lte] + in: query + schema: + type: string + - name: filter[viewCount][$gt] + in: query + schema: + type: string + - name: filter[viewCount][$gte] + in: query + schema: + type: string + responses: + "200": + description: Related Post resource(s) + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/PostListResponse" + "404": *a1 + /user/{id}/relationships/posts: + get: + tags: + - user + summary: Fetch posts relationship + operationId: getUser_relationships_posts + parameters: + - &a3 + $ref: "#/components/parameters/id" + responses: + "200": + description: posts relationship + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_toManyRelationshipWithLinks" + "404": *a1 + put: + tags: + - user + summary: Replace posts relationship + operationId: putUser_relationships_posts + parameters: + - *a3 + requestBody: + required: true + content: + application/vnd.api+json: + schema: &a4 + $ref: "#/components/schemas/_toManyRelationshipRequest" + responses: + "200": + description: Relationship updated + "400": *a1 + patch: + tags: + - user + summary: Update posts relationship + operationId: patchUser_relationships_posts + parameters: + - *a3 + requestBody: + required: true + content: + application/vnd.api+json: + schema: *a4 + responses: + "200": + description: Relationship updated + "400": *a1 + post: + tags: + - user + summary: Add to posts collection relationship + operationId: postUser_relationships_posts + parameters: + - *a3 + requestBody: + required: true + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_toManyRelationshipRequest" + responses: + "200": + description: Added to relationship collection + "400": *a1 + /user/{id}/likes: + get: + tags: + - user + summary: Fetch related PostLike for User + operationId: getUser_likes + parameters: + - $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/include" + - $ref: "#/components/parameters/sort" + - $ref: "#/components/parameters/pageOffset" + - $ref: "#/components/parameters/pageLimit" + - name: filter[id] + in: query + schema: + type: string + description: Filter by PostLike ID + - name: filter[superLike] + in: query + schema: + type: string + description: Filter by superLike + responses: + "200": + description: Related PostLike resource(s) + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/PostLikeListResponse" + "404": *a1 + /user/{id}/relationships/likes: + get: + tags: + - user + summary: Fetch likes relationship + operationId: getUser_relationships_likes + parameters: + - &a5 + $ref: "#/components/parameters/id" + responses: + "200": + description: likes relationship + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_toManyRelationshipWithLinks" + "404": *a1 + put: + tags: + - user + summary: Replace likes relationship + operationId: putUser_relationships_likes + parameters: + - *a5 + requestBody: + required: true + content: + application/vnd.api+json: + schema: &a6 + $ref: "#/components/schemas/_toManyRelationshipRequest" + responses: + "200": + description: Relationship updated + "400": *a1 + patch: + tags: + - user + summary: Update likes relationship + operationId: patchUser_relationships_likes + parameters: + - *a5 + requestBody: + required: true + content: + application/vnd.api+json: + schema: *a6 + responses: + "200": + description: Relationship updated + "400": *a1 + post: + tags: + - user + summary: Add to likes collection relationship + operationId: postUser_relationships_likes + parameters: + - *a5 + requestBody: + required: true + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_toManyRelationshipRequest" + responses: + "200": + description: Added to relationship collection + "400": *a1 + /user/{id}/profile: + get: + tags: + - user + summary: Fetch related Profile for User + operationId: getUser_profile + parameters: + - $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/include" + responses: + "200": + description: Related Profile resource(s) + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/ProfileResponse" + "404": *a1 + /user/{id}/relationships/profile: + get: + tags: + - user + summary: Fetch profile relationship + operationId: getUser_relationships_profile + parameters: + - &a7 + $ref: "#/components/parameters/id" + responses: + "200": + description: profile relationship + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_toOneRelationshipWithLinks" + "404": *a1 + put: + tags: + - user + summary: Replace profile relationship + operationId: putUser_relationships_profile + parameters: + - *a7 + requestBody: + required: true + content: + application/vnd.api+json: + schema: &a8 + $ref: "#/components/schemas/_toOneRelationshipRequest" + responses: + "200": + description: Relationship updated + "400": *a1 + patch: + tags: + - user + summary: Update profile relationship + operationId: patchUser_relationships_profile + parameters: + - *a7 + requestBody: + required: true + content: + application/vnd.api+json: + schema: *a8 + responses: + "200": + description: Relationship updated + "400": *a1 + /profile: + get: + tags: + - profile + summary: List Profile resources + operationId: listProfile + parameters: + - $ref: "#/components/parameters/include" + - $ref: "#/components/parameters/sort" + - $ref: "#/components/parameters/pageOffset" + - $ref: "#/components/parameters/pageLimit" + - name: filter[id] + in: query + schema: + type: string + description: Filter by Profile ID + - name: filter[gender] + in: query + schema: + type: string + description: Filter by gender + - name: filter[gender][$contains] + in: query + schema: + type: string + - name: filter[gender][$icontains] + in: query + schema: + type: string + - name: filter[gender][$search] + in: query + schema: + type: string + - name: filter[gender][$startsWith] + in: query + schema: + type: string + - name: filter[gender][$endsWith] + in: query + schema: + type: string + responses: + "200": + description: List of Profile resources + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/ProfileListResponse" + "400": *a1 + post: + tags: + - profile + summary: Create a Profile resource + operationId: createProfile + requestBody: + required: true + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/ProfileCreateRequest" + responses: + "201": + description: Created Profile resource + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/ProfileResponse" + "400": *a1 + /profile/{id}: + get: + tags: + - profile + summary: Get a Profile resource by ID + operationId: getProfile + parameters: + - &a9 + $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/include" + responses: + "200": + description: Profile resource + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/ProfileResponse" + "404": *a1 + patch: + tags: + - profile + summary: Update a Profile resource + operationId: updateProfile + parameters: + - *a9 + requestBody: + required: true + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/ProfileUpdateRequest" + responses: + "200": + description: Updated Profile resource + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/ProfileResponse" + "400": *a1 + "404": *a1 + delete: + tags: + - profile + summary: Delete a Profile resource + operationId: deleteProfile + parameters: + - *a9 + responses: + "200": + description: Deleted successfully + "404": *a1 + /profile/{id}/user: + get: + tags: + - profile + summary: Fetch related User for Profile + operationId: getProfile_user + parameters: + - $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/include" + responses: + "200": + description: Related User resource(s) + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/UserResponse" + "404": *a1 + /profile/{id}/relationships/user: + get: + tags: + - profile + summary: Fetch user relationship + operationId: getProfile_relationships_user + parameters: + - &a10 + $ref: "#/components/parameters/id" + responses: + "200": + description: user relationship + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_toOneRelationshipWithLinks" + "404": *a1 + put: + tags: + - profile + summary: Replace user relationship + operationId: putProfile_relationships_user + parameters: + - *a10 + requestBody: + required: true + content: + application/vnd.api+json: + schema: &a11 + $ref: "#/components/schemas/_toOneRelationshipRequest" + responses: + "200": + description: Relationship updated + "400": *a1 + patch: + tags: + - profile + summary: Update user relationship + operationId: patchProfile_relationships_user + parameters: + - *a10 + requestBody: + required: true + content: + application/vnd.api+json: + schema: *a11 + responses: + "200": + description: Relationship updated + "400": *a1 + /post: + get: + tags: + - post + summary: List Post resources + operationId: listPost + parameters: + - $ref: "#/components/parameters/include" + - $ref: "#/components/parameters/sort" + - $ref: "#/components/parameters/pageOffset" + - $ref: "#/components/parameters/pageLimit" + - name: filter[id] + in: query + schema: + type: string + description: Filter by Post ID + - name: filter[createdAt] + in: query + schema: + type: string + description: Filter by createdAt + - name: filter[createdAt][$lt] + in: query + schema: + type: string + - name: filter[createdAt][$lte] + in: query + schema: + type: string + - name: filter[createdAt][$gt] + in: query + schema: + type: string + - name: filter[createdAt][$gte] + in: query + schema: + type: string + - name: filter[updatedAt] + in: query + schema: + type: string + description: Filter by updatedAt + - name: filter[updatedAt][$lt] + in: query + schema: + type: string + - name: filter[updatedAt][$lte] + in: query + schema: + type: string + - name: filter[updatedAt][$gt] + in: query + schema: + type: string + - name: filter[updatedAt][$gte] + in: query + schema: + type: string + - name: filter[title] + in: query + schema: + type: string + description: Filter by title + - name: filter[title][$contains] + in: query + schema: + type: string + - name: filter[title][$icontains] + in: query + schema: + type: string + - name: filter[title][$search] + in: query + schema: + type: string + - name: filter[title][$startsWith] + in: query + schema: + type: string + - name: filter[title][$endsWith] + in: query + schema: + type: string + - name: filter[published] + in: query + schema: + type: string + description: Filter by published + - name: filter[publishedAt] + in: query + schema: + type: string + description: Filter by publishedAt + - name: filter[publishedAt][$lt] + in: query + schema: + type: string + - name: filter[publishedAt][$lte] + in: query + schema: + type: string + - name: filter[publishedAt][$gt] + in: query + schema: + type: string + - name: filter[publishedAt][$gte] + in: query + schema: + type: string + - name: filter[viewCount] + in: query + schema: + type: string + description: Filter by viewCount + - name: filter[viewCount][$lt] + in: query + schema: + type: string + - name: filter[viewCount][$lte] + in: query + schema: + type: string + - name: filter[viewCount][$gt] + in: query + schema: + type: string + - name: filter[viewCount][$gte] + in: query + schema: + type: string + responses: + "200": + description: List of Post resources + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/PostListResponse" + "400": *a1 + post: + tags: + - post + summary: Create a Post resource + operationId: createPost + requestBody: + required: true + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/PostCreateRequest" + responses: + "201": + description: Created Post resource + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/PostResponse" + "400": *a1 + /post/{id}: + get: + tags: + - post + summary: Get a Post resource by ID + operationId: getPost + parameters: + - &a12 + $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/include" + responses: + "200": + description: Post resource + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/PostResponse" + "404": *a1 + patch: + tags: + - post + summary: Update a Post resource + operationId: updatePost + parameters: + - *a12 + requestBody: + required: true + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/PostUpdateRequest" + responses: + "200": + description: Updated Post resource + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/PostResponse" + "400": *a1 + "404": *a1 + delete: + tags: + - post + summary: Delete a Post resource + operationId: deletePost + parameters: + - *a12 + responses: + "200": + description: Deleted successfully + "404": *a1 + /post/{id}/author: + get: + tags: + - post + summary: Fetch related User for Post + operationId: getPost_author + parameters: + - $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/include" + responses: + "200": + description: Related User resource(s) + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/UserResponse" + "404": *a1 + /post/{id}/relationships/author: + get: + tags: + - post + summary: Fetch author relationship + operationId: getPost_relationships_author + parameters: + - &a13 + $ref: "#/components/parameters/id" + responses: + "200": + description: author relationship + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_toOneRelationshipWithLinks" + "404": *a1 + put: + tags: + - post + summary: Replace author relationship + operationId: putPost_relationships_author + parameters: + - *a13 + requestBody: + required: true + content: + application/vnd.api+json: + schema: &a14 + $ref: "#/components/schemas/_toOneRelationshipRequest" + responses: + "200": + description: Relationship updated + "400": *a1 + patch: + tags: + - post + summary: Update author relationship + operationId: patchPost_relationships_author + parameters: + - *a13 + requestBody: + required: true + content: + application/vnd.api+json: + schema: *a14 + responses: + "200": + description: Relationship updated + "400": *a1 + /post/{id}/comments: + get: + tags: + - post + summary: Fetch related Comment for Post + operationId: getPost_comments + parameters: + - $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/include" + - $ref: "#/components/parameters/sort" + - $ref: "#/components/parameters/pageOffset" + - $ref: "#/components/parameters/pageLimit" + - name: filter[id] + in: query + schema: + type: string + description: Filter by Comment ID + - name: filter[content] + in: query + schema: + type: string + description: Filter by content + - name: filter[content][$contains] + in: query + schema: + type: string + - name: filter[content][$icontains] + in: query + schema: + type: string + - name: filter[content][$search] + in: query + schema: + type: string + - name: filter[content][$startsWith] + in: query + schema: + type: string + - name: filter[content][$endsWith] + in: query + schema: + type: string + responses: + "200": + description: Related Comment resource(s) + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/CommentListResponse" + "404": *a1 + /post/{id}/relationships/comments: + get: + tags: + - post + summary: Fetch comments relationship + operationId: getPost_relationships_comments + parameters: + - &a15 + $ref: "#/components/parameters/id" + responses: + "200": + description: comments relationship + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_toManyRelationshipWithLinks" + "404": *a1 + put: + tags: + - post + summary: Replace comments relationship + operationId: putPost_relationships_comments + parameters: + - *a15 + requestBody: + required: true + content: + application/vnd.api+json: + schema: &a16 + $ref: "#/components/schemas/_toManyRelationshipRequest" + responses: + "200": + description: Relationship updated + "400": *a1 + patch: + tags: + - post + summary: Update comments relationship + operationId: patchPost_relationships_comments + parameters: + - *a15 + requestBody: + required: true + content: + application/vnd.api+json: + schema: *a16 + responses: + "200": + description: Relationship updated + "400": *a1 + post: + tags: + - post + summary: Add to comments collection relationship + operationId: postPost_relationships_comments + parameters: + - *a15 + requestBody: + required: true + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_toManyRelationshipRequest" + responses: + "200": + description: Added to relationship collection + "400": *a1 + /post/{id}/likes: + get: + tags: + - post + summary: Fetch related PostLike for Post + operationId: getPost_likes + parameters: + - $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/include" + - $ref: "#/components/parameters/sort" + - $ref: "#/components/parameters/pageOffset" + - $ref: "#/components/parameters/pageLimit" + - name: filter[id] + in: query + schema: + type: string + description: Filter by PostLike ID + - name: filter[superLike] + in: query + schema: + type: string + description: Filter by superLike + responses: + "200": + description: Related PostLike resource(s) + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/PostLikeListResponse" + "404": *a1 + /post/{id}/relationships/likes: + get: + tags: + - post + summary: Fetch likes relationship + operationId: getPost_relationships_likes + parameters: + - &a17 + $ref: "#/components/parameters/id" + responses: + "200": + description: likes relationship + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_toManyRelationshipWithLinks" + "404": *a1 + put: + tags: + - post + summary: Replace likes relationship + operationId: putPost_relationships_likes + parameters: + - *a17 + requestBody: + required: true + content: + application/vnd.api+json: + schema: &a18 + $ref: "#/components/schemas/_toManyRelationshipRequest" + responses: + "200": + description: Relationship updated + "400": *a1 + patch: + tags: + - post + summary: Update likes relationship + operationId: patchPost_relationships_likes + parameters: + - *a17 + requestBody: + required: true + content: + application/vnd.api+json: + schema: *a18 + responses: + "200": + description: Relationship updated + "400": *a1 + post: + tags: + - post + summary: Add to likes collection relationship + operationId: postPost_relationships_likes + parameters: + - *a17 + requestBody: + required: true + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_toManyRelationshipRequest" + responses: + "200": + description: Added to relationship collection + "400": *a1 + /post/{id}/setting: + get: + tags: + - post + summary: Fetch related Setting for Post + operationId: getPost_setting + parameters: + - $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/include" + responses: + "200": + description: Related Setting resource(s) + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/SettingResponse" + "404": *a1 + /post/{id}/relationships/setting: + get: + tags: + - post + summary: Fetch setting relationship + operationId: getPost_relationships_setting + parameters: + - &a19 + $ref: "#/components/parameters/id" + responses: + "200": + description: setting relationship + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_toOneRelationshipWithLinks" + "404": *a1 + put: + tags: + - post + summary: Replace setting relationship + operationId: putPost_relationships_setting + parameters: + - *a19 + requestBody: + required: true + content: + application/vnd.api+json: + schema: &a20 + $ref: "#/components/schemas/_toOneRelationshipRequest" + responses: + "200": + description: Relationship updated + "400": *a1 + patch: + tags: + - post + summary: Update setting relationship + operationId: patchPost_relationships_setting + parameters: + - *a19 + requestBody: + required: true + content: + application/vnd.api+json: + schema: *a20 + responses: + "200": + description: Relationship updated + "400": *a1 + /comment: + get: + tags: + - comment + summary: List Comment resources + operationId: listComment + parameters: + - $ref: "#/components/parameters/include" + - $ref: "#/components/parameters/sort" + - $ref: "#/components/parameters/pageOffset" + - $ref: "#/components/parameters/pageLimit" + - name: filter[id] + in: query + schema: + type: string + description: Filter by Comment ID + - name: filter[content] + in: query + schema: + type: string + description: Filter by content + - name: filter[content][$contains] + in: query + schema: + type: string + - name: filter[content][$icontains] + in: query + schema: + type: string + - name: filter[content][$search] + in: query + schema: + type: string + - name: filter[content][$startsWith] + in: query + schema: + type: string + - name: filter[content][$endsWith] + in: query + schema: + type: string + responses: + "200": + description: List of Comment resources + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/CommentListResponse" + "400": *a1 + post: + tags: + - comment + summary: Create a Comment resource + operationId: createComment + requestBody: + required: true + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/CommentCreateRequest" + responses: + "201": + description: Created Comment resource + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/CommentResponse" + "400": *a1 + /comment/{id}: + get: + tags: + - comment + summary: Get a Comment resource by ID + operationId: getComment + parameters: + - &a21 + $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/include" + responses: + "200": + description: Comment resource + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/CommentResponse" + "404": *a1 + patch: + tags: + - comment + summary: Update a Comment resource + operationId: updateComment + parameters: + - *a21 + requestBody: + required: true + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/CommentUpdateRequest" + responses: + "200": + description: Updated Comment resource + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/CommentResponse" + "400": *a1 + "404": *a1 + delete: + tags: + - comment + summary: Delete a Comment resource + operationId: deleteComment + parameters: + - *a21 + responses: + "200": + description: Deleted successfully + "404": *a1 + /comment/{id}/post: + get: + tags: + - comment + summary: Fetch related Post for Comment + operationId: getComment_post + parameters: + - $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/include" + responses: + "200": + description: Related Post resource(s) + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/PostResponse" + "404": *a1 + /comment/{id}/relationships/post: + get: + tags: + - comment + summary: Fetch post relationship + operationId: getComment_relationships_post + parameters: + - &a22 + $ref: "#/components/parameters/id" + responses: + "200": + description: post relationship + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_toOneRelationshipWithLinks" + "404": *a1 + put: + tags: + - comment + summary: Replace post relationship + operationId: putComment_relationships_post + parameters: + - *a22 + requestBody: + required: true + content: + application/vnd.api+json: + schema: &a23 + $ref: "#/components/schemas/_toOneRelationshipRequest" + responses: + "200": + description: Relationship updated + "400": *a1 + patch: + tags: + - comment + summary: Update post relationship + operationId: patchComment_relationships_post + parameters: + - *a22 + requestBody: + required: true + content: + application/vnd.api+json: + schema: *a23 + responses: + "200": + description: Relationship updated + "400": *a1 + /setting: + get: + tags: + - setting + summary: List Setting resources + operationId: listSetting + parameters: + - $ref: "#/components/parameters/include" + - $ref: "#/components/parameters/sort" + - $ref: "#/components/parameters/pageOffset" + - $ref: "#/components/parameters/pageLimit" + - name: filter[id] + in: query + schema: + type: string + description: Filter by Setting ID + - name: filter[boost] + in: query + schema: + type: string + description: Filter by boost + - name: filter[boost][$lt] + in: query + schema: + type: string + - name: filter[boost][$lte] + in: query + schema: + type: string + - name: filter[boost][$gt] + in: query + schema: + type: string + - name: filter[boost][$gte] + in: query + schema: + type: string + responses: + "200": + description: List of Setting resources + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/SettingListResponse" + "400": *a1 + post: + tags: + - setting + summary: Create a Setting resource + operationId: createSetting + requestBody: + required: true + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/SettingCreateRequest" + responses: + "201": + description: Created Setting resource + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/SettingResponse" + "400": *a1 + /setting/{id}: + get: + tags: + - setting + summary: Get a Setting resource by ID + operationId: getSetting + parameters: + - &a24 + $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/include" + responses: + "200": + description: Setting resource + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/SettingResponse" + "404": *a1 + patch: + tags: + - setting + summary: Update a Setting resource + operationId: updateSetting + parameters: + - *a24 + requestBody: + required: true + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/SettingUpdateRequest" + responses: + "200": + description: Updated Setting resource + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/SettingResponse" + "400": *a1 + "404": *a1 + delete: + tags: + - setting + summary: Delete a Setting resource + operationId: deleteSetting + parameters: + - *a24 + responses: + "200": + description: Deleted successfully + "404": *a1 + /setting/{id}/post: + get: + tags: + - setting + summary: Fetch related Post for Setting + operationId: getSetting_post + parameters: + - $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/include" + responses: + "200": + description: Related Post resource(s) + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/PostResponse" + "404": *a1 + /setting/{id}/relationships/post: + get: + tags: + - setting + summary: Fetch post relationship + operationId: getSetting_relationships_post + parameters: + - &a25 + $ref: "#/components/parameters/id" + responses: + "200": + description: post relationship + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_toOneRelationshipWithLinks" + "404": *a1 + put: + tags: + - setting + summary: Replace post relationship + operationId: putSetting_relationships_post + parameters: + - *a25 + requestBody: + required: true + content: + application/vnd.api+json: + schema: &a26 + $ref: "#/components/schemas/_toOneRelationshipRequest" + responses: + "200": + description: Relationship updated + "400": *a1 + patch: + tags: + - setting + summary: Update post relationship + operationId: patchSetting_relationships_post + parameters: + - *a25 + requestBody: + required: true + content: + application/vnd.api+json: + schema: *a26 + responses: + "200": + description: Relationship updated + "400": *a1 + /postLike: + get: + tags: + - postLike + summary: List PostLike resources + operationId: listPostLike + parameters: + - $ref: "#/components/parameters/include" + - $ref: "#/components/parameters/sort" + - $ref: "#/components/parameters/pageOffset" + - $ref: "#/components/parameters/pageLimit" + - name: filter[id] + in: query + schema: + type: string + description: Filter by PostLike ID + - name: filter[superLike] + in: query + schema: + type: string + description: Filter by superLike + responses: + "200": + description: List of PostLike resources + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/PostLikeListResponse" + "400": *a1 + post: + tags: + - postLike + summary: Create a PostLike resource + operationId: createPostLike + requestBody: + required: true + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/PostLikeCreateRequest" + responses: + "201": + description: Created PostLike resource + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/PostLikeResponse" + "400": *a1 + /postLike/{id}: + get: + tags: + - postLike + summary: Get a PostLike resource by ID + operationId: getPostLike + parameters: + - &a27 + $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/include" + responses: + "200": + description: PostLike resource + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/PostLikeResponse" + "404": *a1 + patch: + tags: + - postLike + summary: Update a PostLike resource + operationId: updatePostLike + parameters: + - *a27 + requestBody: + required: true + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/PostLikeUpdateRequest" + responses: + "200": + description: Updated PostLike resource + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/PostLikeResponse" + "400": *a1 + "404": *a1 + delete: + tags: + - postLike + summary: Delete a PostLike resource + operationId: deletePostLike + parameters: + - *a27 + responses: + "200": + description: Deleted successfully + "404": *a1 + /postLike/{id}/post: + get: + tags: + - postLike + summary: Fetch related Post for PostLike + operationId: getPostLike_post + parameters: + - $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/include" + responses: + "200": + description: Related Post resource(s) + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/PostResponse" + "404": *a1 + /postLike/{id}/relationships/post: + get: + tags: + - postLike + summary: Fetch post relationship + operationId: getPostLike_relationships_post + parameters: + - &a28 + $ref: "#/components/parameters/id" + responses: + "200": + description: post relationship + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_toOneRelationshipWithLinks" + "404": *a1 + put: + tags: + - postLike + summary: Replace post relationship + operationId: putPostLike_relationships_post + parameters: + - *a28 + requestBody: + required: true + content: + application/vnd.api+json: + schema: &a29 + $ref: "#/components/schemas/_toOneRelationshipRequest" + responses: + "200": + description: Relationship updated + "400": *a1 + patch: + tags: + - postLike + summary: Update post relationship + operationId: patchPostLike_relationships_post + parameters: + - *a28 + requestBody: + required: true + content: + application/vnd.api+json: + schema: *a29 + responses: + "200": + description: Relationship updated + "400": *a1 + /postLike/{id}/user: + get: + tags: + - postLike + summary: Fetch related User for PostLike + operationId: getPostLike_user + parameters: + - $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/include" + responses: + "200": + description: Related User resource(s) + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/UserResponse" + "404": *a1 + /postLike/{id}/relationships/user: + get: + tags: + - postLike + summary: Fetch user relationship + operationId: getPostLike_relationships_user + parameters: + - &a30 + $ref: "#/components/parameters/id" + responses: + "200": + description: user relationship + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_toOneRelationshipWithLinks" + "404": *a1 + put: + tags: + - postLike + summary: Replace user relationship + operationId: putPostLike_relationships_user + parameters: + - *a30 + requestBody: + required: true + content: + application/vnd.api+json: + schema: &a31 + $ref: "#/components/schemas/_toOneRelationshipRequest" + responses: + "200": + description: Relationship updated + "400": *a1 + patch: + tags: + - postLike + summary: Update user relationship + operationId: patchPostLike_relationships_user + parameters: + - *a30 + requestBody: + required: true + content: + application/vnd.api+json: + schema: *a31 + responses: + "200": + description: Relationship updated + "400": *a1 + /postLike/{id}/likeInfos: + get: + tags: + - postLike + summary: Fetch related PostLikeInfo for PostLike + operationId: getPostLike_likeInfos + parameters: + - $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/include" + - $ref: "#/components/parameters/sort" + - $ref: "#/components/parameters/pageOffset" + - $ref: "#/components/parameters/pageLimit" + - name: filter[id] + in: query + schema: + type: string + description: Filter by PostLikeInfo ID + - name: filter[text] + in: query + schema: + type: string + description: Filter by text + - name: filter[text][$contains] + in: query + schema: + type: string + - name: filter[text][$icontains] + in: query + schema: + type: string + - name: filter[text][$search] + in: query + schema: + type: string + - name: filter[text][$startsWith] + in: query + schema: + type: string + - name: filter[text][$endsWith] + in: query + schema: + type: string + responses: + "200": + description: Related PostLikeInfo resource(s) + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/PostLikeInfoListResponse" + "404": *a1 + /postLike/{id}/relationships/likeInfos: + get: + tags: + - postLike + summary: Fetch likeInfos relationship + operationId: getPostLike_relationships_likeInfos + parameters: + - &a32 + $ref: "#/components/parameters/id" + responses: + "200": + description: likeInfos relationship + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_toManyRelationshipWithLinks" + "404": *a1 + put: + tags: + - postLike + summary: Replace likeInfos relationship + operationId: putPostLike_relationships_likeInfos + parameters: + - *a32 + requestBody: + required: true + content: + application/vnd.api+json: + schema: &a33 + $ref: "#/components/schemas/_toManyRelationshipRequest" + responses: + "200": + description: Relationship updated + "400": *a1 + patch: + tags: + - postLike + summary: Update likeInfos relationship + operationId: patchPostLike_relationships_likeInfos + parameters: + - *a32 + requestBody: + required: true + content: + application/vnd.api+json: + schema: *a33 + responses: + "200": + description: Relationship updated + "400": *a1 + post: + tags: + - postLike + summary: Add to likeInfos collection relationship + operationId: postPostLike_relationships_likeInfos + parameters: + - *a32 + requestBody: + required: true + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_toManyRelationshipRequest" + responses: + "200": + description: Added to relationship collection + "400": *a1 + /postLikeInfo: + get: + tags: + - postLikeInfo + summary: List PostLikeInfo resources + operationId: listPostLikeInfo + parameters: + - $ref: "#/components/parameters/include" + - $ref: "#/components/parameters/sort" + - $ref: "#/components/parameters/pageOffset" + - $ref: "#/components/parameters/pageLimit" + - name: filter[id] + in: query + schema: + type: string + description: Filter by PostLikeInfo ID + - name: filter[text] + in: query + schema: + type: string + description: Filter by text + - name: filter[text][$contains] + in: query + schema: + type: string + - name: filter[text][$icontains] + in: query + schema: + type: string + - name: filter[text][$search] + in: query + schema: + type: string + - name: filter[text][$startsWith] + in: query + schema: + type: string + - name: filter[text][$endsWith] + in: query + schema: + type: string + responses: + "200": + description: List of PostLikeInfo resources + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/PostLikeInfoListResponse" + "400": *a1 + post: + tags: + - postLikeInfo + summary: Create a PostLikeInfo resource + operationId: createPostLikeInfo + requestBody: + required: true + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/PostLikeInfoCreateRequest" + responses: + "201": + description: Created PostLikeInfo resource + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/PostLikeInfoResponse" + "400": *a1 + /postLikeInfo/{id}: + get: + tags: + - postLikeInfo + summary: Get a PostLikeInfo resource by ID + operationId: getPostLikeInfo + parameters: + - &a34 + $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/include" + responses: + "200": + description: PostLikeInfo resource + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/PostLikeInfoResponse" + "404": *a1 + patch: + tags: + - postLikeInfo + summary: Update a PostLikeInfo resource + operationId: updatePostLikeInfo + parameters: + - *a34 + requestBody: + required: true + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/PostLikeInfoUpdateRequest" + responses: + "200": + description: Updated PostLikeInfo resource + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/PostLikeInfoResponse" + "400": *a1 + "404": *a1 + delete: + tags: + - postLikeInfo + summary: Delete a PostLikeInfo resource + operationId: deletePostLikeInfo + parameters: + - *a34 + responses: + "200": + description: Deleted successfully + "404": *a1 + /postLikeInfo/{id}/postLike: + get: + tags: + - postLikeInfo + summary: Fetch related PostLike for PostLikeInfo + operationId: getPostLikeInfo_postLike + parameters: + - $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/include" + responses: + "200": + description: Related PostLike resource(s) + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/PostLikeResponse" + "404": *a1 + /postLikeInfo/{id}/relationships/postLike: + get: + tags: + - postLikeInfo + summary: Fetch postLike relationship + operationId: getPostLikeInfo_relationships_postLike + parameters: + - &a35 + $ref: "#/components/parameters/id" + responses: + "200": + description: postLike relationship + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_toOneRelationshipWithLinks" + "404": *a1 + put: + tags: + - postLikeInfo + summary: Replace postLike relationship + operationId: putPostLikeInfo_relationships_postLike + parameters: + - *a35 + requestBody: + required: true + content: + application/vnd.api+json: + schema: &a36 + $ref: "#/components/schemas/_toOneRelationshipRequest" + responses: + "200": + description: Relationship updated + "400": *a1 + patch: + tags: + - postLikeInfo + summary: Update postLike relationship + operationId: patchPostLikeInfo_relationships_postLike + parameters: + - *a35 + requestBody: + required: true + content: + application/vnd.api+json: + schema: *a36 + responses: + "200": + description: Relationship updated + "400": *a1 +components: + schemas: + _jsonapi: + type: object + properties: + version: + type: string + meta: + type: object + _meta: + type: object + additionalProperties: true + _links: + type: object + properties: + self: + type: string + related: + type: string + _pagination: + type: object + properties: + first: &a37 + oneOf: + - type: string + - type: "null" + last: *a37 + prev: *a37 + next: *a37 + _errors: + type: array + items: + type: object + properties: + status: + type: integer + code: + type: string + title: + type: string + detail: + type: string + required: + - status + - title + _errorResponse: + type: object + properties: + errors: + $ref: "#/components/schemas/_errors" + required: + - errors + _resourceIdentifier: + type: object + properties: + type: + type: string + id: + type: string + required: + - type + - id + _resource: + type: object + properties: + type: + type: string + id: + type: string + attributes: + type: object + relationships: + type: object + links: + $ref: "#/components/schemas/_links" + meta: + $ref: "#/components/schemas/_meta" + required: + - type + - id + _relationLinks: + type: object + properties: + self: + type: string + related: + type: string + _pagedRelationLinks: + type: object + allOf: + - $ref: "#/components/schemas/_relationLinks" + - $ref: "#/components/schemas/_pagination" + _toOneRelationship: + type: object + properties: + data: + oneOf: + - $ref: "#/components/schemas/_resourceIdentifier" + - type: "null" + _toManyRelationship: + type: object + properties: + data: + type: array + items: + $ref: "#/components/schemas/_resourceIdentifier" + _toOneRelationshipWithLinks: + type: object + allOf: + - $ref: "#/components/schemas/_toOneRelationship" + - properties: + links: + $ref: "#/components/schemas/_relationLinks" + _toManyRelationshipWithLinks: + type: object + allOf: + - $ref: "#/components/schemas/_toManyRelationship" + - properties: + links: + $ref: "#/components/schemas/_pagedRelationLinks" + _toManyRelationshipRequest: + type: object + properties: + data: + type: array + items: + $ref: "#/components/schemas/_resourceIdentifier" + required: + - data + _toOneRelationshipRequest: + type: object + properties: + data: + oneOf: + - $ref: "#/components/schemas/_resourceIdentifier" + - type: "null" + required: + - data + _toManyRelationshipResponse: + type: object + properties: + data: + type: array + items: + $ref: "#/components/schemas/_resourceIdentifier" + links: + $ref: "#/components/schemas/_pagedRelationLinks" + meta: + $ref: "#/components/schemas/_meta" + _toOneRelationshipResponse: + type: object + properties: + data: + oneOf: + - $ref: "#/components/schemas/_resourceIdentifier" + - type: "null" + links: + $ref: "#/components/schemas/_relationLinks" + meta: + $ref: "#/components/schemas/_meta" + User: + type: object + properties: + myId: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + email: + type: string + posts: + type: array + items: + $ref: "#/components/schemas/Post" + likes: + type: array + items: + $ref: "#/components/schemas/PostLike" + profile: + oneOf: + - $ref: "#/components/schemas/Profile" + - type: "null" + address: + oneOf: + - $ref: "#/components/schemas/Address" + - type: "null" + someJson: + oneOf: + - {} + - type: "null" + required: + - myId + - createdAt + - updatedAt + - email + UserCreateRequest: + type: object + properties: + data: + type: object + properties: + type: + type: string + attributes: + type: object + properties: + createdAt: + type: string + format: date-time + email: + type: string + address: + oneOf: + - $ref: "#/components/schemas/Address" + - type: "null" + someJson: + oneOf: + - {} + - type: "null" + required: + - email + relationships: + type: object + properties: + posts: + type: object + properties: + data: + type: array + items: + $ref: "#/components/schemas/_resourceIdentifier" + likes: + type: object + properties: + data: + type: array + items: + $ref: "#/components/schemas/_resourceIdentifier" + profile: + type: object + properties: + data: + $ref: "#/components/schemas/_resourceIdentifier" + required: + - type + required: + - data + UserUpdateRequest: + type: object + properties: + data: + type: object + properties: + type: + type: string + id: + type: string + attributes: + type: object + properties: + myId: + type: string + createdAt: + type: string + format: date-time + email: + type: string + address: + oneOf: + - $ref: "#/components/schemas/Address" + - type: "null" + someJson: + oneOf: + - {} + - type: "null" + relationships: + type: object + properties: + posts: + type: object + properties: + data: + type: array + items: + $ref: "#/components/schemas/_resourceIdentifier" + likes: + type: object + properties: + data: + type: array + items: + $ref: "#/components/schemas/_resourceIdentifier" + profile: + type: object + properties: + data: + $ref: "#/components/schemas/_resourceIdentifier" + required: + - type + - id + required: + - data + UserResponse: + type: object + properties: + jsonapi: + $ref: "#/components/schemas/_jsonapi" + data: + allOf: + - $ref: "#/components/schemas/User" + - $ref: "#/components/schemas/_resource" + meta: + $ref: "#/components/schemas/_meta" + UserListResponse: + type: object + properties: + jsonapi: + $ref: "#/components/schemas/_jsonapi" + data: + type: array + items: + allOf: + - $ref: "#/components/schemas/User" + - $ref: "#/components/schemas/_resource" + links: + allOf: + - $ref: "#/components/schemas/_pagination" + - $ref: "#/components/schemas/_links" + meta: + $ref: "#/components/schemas/_meta" + Profile: + type: object + properties: + id: + type: integer + gender: + type: string + user: + $ref: "#/components/schemas/User" + userId: + type: string + required: + - id + - gender + - user + - userId + ProfileCreateRequest: + type: object + properties: + data: + type: object + properties: + type: + type: string + attributes: + type: object + properties: + gender: + type: string + required: + - gender + relationships: + type: object + properties: + user: + type: object + properties: + data: + $ref: "#/components/schemas/_resourceIdentifier" + required: + - type + required: + - data + ProfileUpdateRequest: + type: object + properties: + data: + type: object + properties: + type: + type: string + id: + type: string + attributes: + type: object + properties: + id: + type: integer + gender: + type: string + relationships: + type: object + properties: + user: + type: object + properties: + data: + $ref: "#/components/schemas/_resourceIdentifier" + required: + - type + - id + required: + - data + ProfileResponse: + type: object + properties: + jsonapi: + $ref: "#/components/schemas/_jsonapi" + data: + allOf: + - $ref: "#/components/schemas/Profile" + - $ref: "#/components/schemas/_resource" + meta: + $ref: "#/components/schemas/_meta" + ProfileListResponse: + type: object + properties: + jsonapi: + $ref: "#/components/schemas/_jsonapi" + data: + type: array + items: + allOf: + - $ref: "#/components/schemas/Profile" + - $ref: "#/components/schemas/_resource" + links: + allOf: + - $ref: "#/components/schemas/_pagination" + - $ref: "#/components/schemas/_links" + meta: + $ref: "#/components/schemas/_meta" + Post: + type: object + properties: + id: + type: integer + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + title: + type: string + author: + oneOf: + - $ref: "#/components/schemas/User" + - type: "null" + authorId: + oneOf: + - type: string + - type: "null" + published: + type: boolean + publishedAt: + oneOf: + - type: string + format: date-time + - type: "null" + viewCount: + type: integer + comments: + type: array + items: + $ref: "#/components/schemas/Comment" + likes: + type: array + items: + $ref: "#/components/schemas/PostLike" + setting: + oneOf: + - $ref: "#/components/schemas/Setting" + - type: "null" + required: + - id + - createdAt + - updatedAt + - title + - published + - viewCount + PostCreateRequest: + type: object + properties: + data: + type: object + properties: + type: + type: string + attributes: + type: object + properties: + createdAt: + type: string + format: date-time + title: + type: string + published: + type: boolean + publishedAt: + oneOf: + - type: string + format: date-time + - type: "null" + viewCount: + type: integer + required: + - title + relationships: + type: object + properties: + author: + type: object + properties: + data: + $ref: "#/components/schemas/_resourceIdentifier" + comments: + type: object + properties: + data: + type: array + items: + $ref: "#/components/schemas/_resourceIdentifier" + likes: + type: object + properties: + data: + type: array + items: + $ref: "#/components/schemas/_resourceIdentifier" + setting: + type: object + properties: + data: + $ref: "#/components/schemas/_resourceIdentifier" + required: + - type + required: + - data + PostUpdateRequest: + type: object + properties: + data: + type: object + properties: + type: + type: string + id: + type: string + attributes: + type: object + properties: + id: + type: integer + createdAt: + type: string + format: date-time + title: + type: string + published: + type: boolean + publishedAt: + oneOf: + - type: string + format: date-time + - type: "null" + viewCount: + type: integer + relationships: + type: object + properties: + author: + type: object + properties: + data: + $ref: "#/components/schemas/_resourceIdentifier" + comments: + type: object + properties: + data: + type: array + items: + $ref: "#/components/schemas/_resourceIdentifier" + likes: + type: object + properties: + data: + type: array + items: + $ref: "#/components/schemas/_resourceIdentifier" + setting: + type: object + properties: + data: + $ref: "#/components/schemas/_resourceIdentifier" + required: + - type + - id + required: + - data + PostResponse: + type: object + properties: + jsonapi: + $ref: "#/components/schemas/_jsonapi" + data: + allOf: + - $ref: "#/components/schemas/Post" + - $ref: "#/components/schemas/_resource" + meta: + $ref: "#/components/schemas/_meta" + PostListResponse: + type: object + properties: + jsonapi: + $ref: "#/components/schemas/_jsonapi" + data: + type: array + items: + allOf: + - $ref: "#/components/schemas/Post" + - $ref: "#/components/schemas/_resource" + links: + allOf: + - $ref: "#/components/schemas/_pagination" + - $ref: "#/components/schemas/_links" + meta: + $ref: "#/components/schemas/_meta" + Comment: + type: object + properties: + id: + type: integer + post: + $ref: "#/components/schemas/Post" + postId: + type: integer + content: + type: string + required: + - id + - post + - postId + - content + CommentCreateRequest: + type: object + properties: + data: + type: object + properties: + type: + type: string + attributes: + type: object + properties: + content: + type: string + required: + - content + relationships: + type: object + properties: + post: + type: object + properties: + data: + $ref: "#/components/schemas/_resourceIdentifier" + required: + - type + required: + - data + CommentUpdateRequest: + type: object + properties: + data: + type: object + properties: + type: + type: string + id: + type: string + attributes: + type: object + properties: + id: + type: integer + content: + type: string + relationships: + type: object + properties: + post: + type: object + properties: + data: + $ref: "#/components/schemas/_resourceIdentifier" + required: + - type + - id + required: + - data + CommentResponse: + type: object + properties: + jsonapi: + $ref: "#/components/schemas/_jsonapi" + data: + allOf: + - $ref: "#/components/schemas/Comment" + - $ref: "#/components/schemas/_resource" + meta: + $ref: "#/components/schemas/_meta" + CommentListResponse: + type: object + properties: + jsonapi: + $ref: "#/components/schemas/_jsonapi" + data: + type: array + items: + allOf: + - $ref: "#/components/schemas/Comment" + - $ref: "#/components/schemas/_resource" + links: + allOf: + - $ref: "#/components/schemas/_pagination" + - $ref: "#/components/schemas/_links" + meta: + $ref: "#/components/schemas/_meta" + Setting: + type: object + properties: + id: + type: integer + boost: + type: integer + post: + $ref: "#/components/schemas/Post" + postId: + type: integer + required: + - id + - boost + - post + - postId + SettingCreateRequest: + type: object + properties: + data: + type: object + properties: + type: + type: string + attributes: + type: object + properties: + boost: + type: integer + required: + - boost + relationships: + type: object + properties: + post: + type: object + properties: + data: + $ref: "#/components/schemas/_resourceIdentifier" + required: + - type + required: + - data + SettingUpdateRequest: + type: object + properties: + data: + type: object + properties: + type: + type: string + id: + type: string + attributes: + type: object + properties: + id: + type: integer + boost: + type: integer + relationships: + type: object + properties: + post: + type: object + properties: + data: + $ref: "#/components/schemas/_resourceIdentifier" + required: + - type + - id + required: + - data + SettingResponse: + type: object + properties: + jsonapi: + $ref: "#/components/schemas/_jsonapi" + data: + allOf: + - $ref: "#/components/schemas/Setting" + - $ref: "#/components/schemas/_resource" + meta: + $ref: "#/components/schemas/_meta" + SettingListResponse: + type: object + properties: + jsonapi: + $ref: "#/components/schemas/_jsonapi" + data: + type: array + items: + allOf: + - $ref: "#/components/schemas/Setting" + - $ref: "#/components/schemas/_resource" + links: + allOf: + - $ref: "#/components/schemas/_pagination" + - $ref: "#/components/schemas/_links" + meta: + $ref: "#/components/schemas/_meta" + PostLike: + type: object + properties: + postId: + type: integer + userId: + type: string + superLike: + type: boolean + post: + $ref: "#/components/schemas/Post" + user: + $ref: "#/components/schemas/User" + likeInfos: + type: array + items: + $ref: "#/components/schemas/PostLikeInfo" + required: + - postId + - userId + - superLike + - post + - user + PostLikeCreateRequest: + type: object + properties: + data: + type: object + properties: + type: + type: string + attributes: + type: object + properties: + superLike: + type: boolean + required: + - superLike + relationships: + type: object + properties: + post: + type: object + properties: + data: + $ref: "#/components/schemas/_resourceIdentifier" + user: + type: object + properties: + data: + $ref: "#/components/schemas/_resourceIdentifier" + likeInfos: + type: object + properties: + data: + type: array + items: + $ref: "#/components/schemas/_resourceIdentifier" + required: + - type + required: + - data + PostLikeUpdateRequest: + type: object + properties: + data: + type: object + properties: + type: + type: string + id: + type: string + attributes: + type: object + properties: + superLike: + type: boolean + relationships: + type: object + properties: + post: + type: object + properties: + data: + $ref: "#/components/schemas/_resourceIdentifier" + user: + type: object + properties: + data: + $ref: "#/components/schemas/_resourceIdentifier" + likeInfos: + type: object + properties: + data: + type: array + items: + $ref: "#/components/schemas/_resourceIdentifier" + required: + - type + - id + required: + - data + PostLikeResponse: + type: object + properties: + jsonapi: + $ref: "#/components/schemas/_jsonapi" + data: + allOf: + - $ref: "#/components/schemas/PostLike" + - $ref: "#/components/schemas/_resource" + meta: + $ref: "#/components/schemas/_meta" + PostLikeListResponse: + type: object + properties: + jsonapi: + $ref: "#/components/schemas/_jsonapi" + data: + type: array + items: + allOf: + - $ref: "#/components/schemas/PostLike" + - $ref: "#/components/schemas/_resource" + links: + allOf: + - $ref: "#/components/schemas/_pagination" + - $ref: "#/components/schemas/_links" + meta: + $ref: "#/components/schemas/_meta" + PostLikeInfo: + type: object + properties: + id: + type: integer + text: + type: string + postId: + type: integer + userId: + type: string + postLike: + $ref: "#/components/schemas/PostLike" + required: + - id + - text + - postId + - userId + - postLike + PostLikeInfoCreateRequest: + type: object + properties: + data: + type: object + properties: + type: + type: string + attributes: + type: object + properties: + text: + type: string + required: + - text + relationships: + type: object + properties: + postLike: + type: object + properties: + data: + $ref: "#/components/schemas/_resourceIdentifier" + required: + - type + required: + - data + PostLikeInfoUpdateRequest: + type: object + properties: + data: + type: object + properties: + type: + type: string + id: + type: string + attributes: + type: object + properties: + id: + type: integer + text: + type: string + relationships: + type: object + properties: + postLike: + type: object + properties: + data: + $ref: "#/components/schemas/_resourceIdentifier" + required: + - type + - id + required: + - data + PostLikeInfoResponse: + type: object + properties: + jsonapi: + $ref: "#/components/schemas/_jsonapi" + data: + allOf: + - $ref: "#/components/schemas/PostLikeInfo" + - $ref: "#/components/schemas/_resource" + meta: + $ref: "#/components/schemas/_meta" + PostLikeInfoListResponse: + type: object + properties: + jsonapi: + $ref: "#/components/schemas/_jsonapi" + data: + type: array + items: + allOf: + - $ref: "#/components/schemas/PostLikeInfo" + - $ref: "#/components/schemas/_resource" + links: + allOf: + - $ref: "#/components/schemas/_pagination" + - $ref: "#/components/schemas/_links" + meta: + $ref: "#/components/schemas/_meta" + parameters: + id: + name: id + in: path + required: true + schema: + type: string + description: Resource ID + include: + name: include + in: query + schema: + type: string + description: Comma-separated list of relationships to include + sort: + name: sort + in: query + schema: + type: string + description: Comma-separated list of fields to sort by. Prefix with - for descending + pageOffset: + name: page[offset] + in: query + schema: + type: integer + minimum: 0 + description: Page offset + pageLimit: + name: page[limit] + in: query + schema: + type: integer + minimum: 1 + description: Page limit diff --git a/packages/server/test/openapi/baseline/rpc.baseline.yaml b/packages/server/test/openapi/baseline/rpc.baseline.yaml new file mode 100644 index 000000000..b19f5243a --- /dev/null +++ b/packages/server/test/openapi/baseline/rpc.baseline.yaml @@ -0,0 +1,2036 @@ +openapi: 3.1.0 +info: + title: ZenStack Generated API + version: 1.0.0 +tags: + - name: user + description: User operations + - name: post + description: Post operations +paths: + /user/findMany: + get: + tags: + - user + summary: findMany User + operationId: user_findMany + parameters: + - name: q + in: query + description: Arguments as JSON (UserFindManyArgs) + schema: + type: string + responses: + "200": + description: Result of findMany + content: + application/json: + schema: + $ref: "#/components/schemas/UserListResponse" + "400": &a1 + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/_ErrorResponse" + /user/findUnique: + get: + tags: + - user + summary: findUnique User + operationId: user_findUnique + parameters: + - name: q + in: query + description: Arguments as JSON (UserFindUniqueArgs) + schema: + type: string + responses: + "200": + description: Result of findUnique + content: + application/json: + schema: + $ref: "#/components/schemas/UserResponse" + "400": *a1 + /user/findFirst: + get: + tags: + - user + summary: findFirst User + operationId: user_findFirst + parameters: + - name: q + in: query + description: Arguments as JSON (UserFindFirstArgs) + schema: + type: string + responses: + "200": + description: Result of findFirst + content: + application/json: + schema: + $ref: "#/components/schemas/UserResponse" + "400": *a1 + /user/count: + get: + tags: + - user + summary: count User + operationId: user_count + parameters: + - name: q + in: query + description: Arguments as JSON (UserCountArgs) + schema: + type: string + responses: + "200": + description: Result of count + content: + application/json: + schema: + $ref: "#/components/schemas/UserCountResponse" + "400": *a1 + /user/aggregate: + get: + tags: + - user + summary: aggregate User + operationId: user_aggregate + parameters: + - name: q + in: query + description: Arguments as JSON (UserAggregateArgs) + schema: + type: string + responses: + "200": + description: Result of aggregate + content: + application/json: + schema: + $ref: "#/components/schemas/UserAggregateResponse" + "400": *a1 + /user/groupBy: + get: + tags: + - user + summary: groupBy User + operationId: user_groupBy + parameters: + - name: q + in: query + description: Arguments as JSON (UserGroupByArgs) + schema: + type: string + responses: + "200": + description: Result of groupBy + content: + application/json: + schema: + $ref: "#/components/schemas/UserGroupByResponse" + "400": *a1 + /user/exists: + get: + tags: + - user + summary: exists User + operationId: user_exists + parameters: + - name: q + in: query + description: Arguments as JSON (UserExistsArgs) + schema: + type: string + responses: + "200": + description: Result of exists + content: + application/json: + schema: + $ref: "#/components/schemas/_ExistsResponse" + "400": *a1 + /user/create: + post: + tags: + - user + summary: create User + operationId: user_create + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/UserCreateArgs" + responses: + "201": + description: Result of create + content: + application/json: + schema: + $ref: "#/components/schemas/UserResponse" + "400": *a1 + /user/createMany: + post: + tags: + - user + summary: createMany User + operationId: user_createMany + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/UserCreateManyArgs" + responses: + "201": + description: Result of createMany + content: + application/json: + schema: + $ref: "#/components/schemas/_BatchResponse" + "400": *a1 + /user/createManyAndReturn: + post: + tags: + - user + summary: createManyAndReturn User + operationId: user_createManyAndReturn + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/UserCreateManyAndReturnArgs" + responses: + "201": + description: Result of createManyAndReturn + content: + application/json: + schema: + $ref: "#/components/schemas/UserListResponse" + "400": *a1 + /user/upsert: + post: + tags: + - user + summary: upsert User + operationId: user_upsert + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/UserUpsertArgs" + responses: + "201": + description: Result of upsert + content: + application/json: + schema: + $ref: "#/components/schemas/UserResponse" + "400": *a1 + /user/update: + patch: + tags: + - user + summary: update User + operationId: user_update + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/UserUpdateArgs" + responses: + "200": + description: Result of update + content: + application/json: + schema: + $ref: "#/components/schemas/UserResponse" + "400": *a1 + /user/updateMany: + patch: + tags: + - user + summary: updateMany User + operationId: user_updateMany + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/UserUpdateManyArgs" + responses: + "200": + description: Result of updateMany + content: + application/json: + schema: + $ref: "#/components/schemas/_BatchResponse" + "400": *a1 + /user/updateManyAndReturn: + patch: + tags: + - user + summary: updateManyAndReturn User + operationId: user_updateManyAndReturn + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/UserUpdateManyAndReturnArgs" + responses: + "200": + description: Result of updateManyAndReturn + content: + application/json: + schema: + $ref: "#/components/schemas/UserListResponse" + "400": *a1 + /user/delete: + delete: + tags: + - user + summary: delete User + operationId: user_delete + parameters: + - name: q + in: query + description: Arguments as JSON (UserDeleteArgs) + schema: + type: string + responses: + "200": + description: Result of delete + content: + application/json: + schema: + $ref: "#/components/schemas/UserResponse" + "400": *a1 + /user/deleteMany: + delete: + tags: + - user + summary: deleteMany User + operationId: user_deleteMany + parameters: + - name: q + in: query + description: Arguments as JSON (UserDeleteManyArgs) + schema: + type: string + responses: + "200": + description: Result of deleteMany + content: + application/json: + schema: + $ref: "#/components/schemas/_BatchResponse" + "400": *a1 + /post/findMany: + get: + tags: + - post + summary: findMany Post + operationId: post_findMany + parameters: + - name: q + in: query + description: Arguments as JSON (PostFindManyArgs) + schema: + type: string + responses: + "200": + description: Result of findMany + content: + application/json: + schema: + $ref: "#/components/schemas/PostListResponse" + "400": *a1 + /post/findUnique: + get: + tags: + - post + summary: findUnique Post + operationId: post_findUnique + parameters: + - name: q + in: query + description: Arguments as JSON (PostFindUniqueArgs) + schema: + type: string + responses: + "200": + description: Result of findUnique + content: + application/json: + schema: + $ref: "#/components/schemas/PostResponse" + "400": *a1 + /post/findFirst: + get: + tags: + - post + summary: findFirst Post + operationId: post_findFirst + parameters: + - name: q + in: query + description: Arguments as JSON (PostFindFirstArgs) + schema: + type: string + responses: + "200": + description: Result of findFirst + content: + application/json: + schema: + $ref: "#/components/schemas/PostResponse" + "400": *a1 + /post/count: + get: + tags: + - post + summary: count Post + operationId: post_count + parameters: + - name: q + in: query + description: Arguments as JSON (PostCountArgs) + schema: + type: string + responses: + "200": + description: Result of count + content: + application/json: + schema: + $ref: "#/components/schemas/PostCountResponse" + "400": *a1 + /post/aggregate: + get: + tags: + - post + summary: aggregate Post + operationId: post_aggregate + parameters: + - name: q + in: query + description: Arguments as JSON (PostAggregateArgs) + schema: + type: string + responses: + "200": + description: Result of aggregate + content: + application/json: + schema: + $ref: "#/components/schemas/PostAggregateResponse" + "400": *a1 + /post/groupBy: + get: + tags: + - post + summary: groupBy Post + operationId: post_groupBy + parameters: + - name: q + in: query + description: Arguments as JSON (PostGroupByArgs) + schema: + type: string + responses: + "200": + description: Result of groupBy + content: + application/json: + schema: + $ref: "#/components/schemas/PostGroupByResponse" + "400": *a1 + /post/exists: + get: + tags: + - post + summary: exists Post + operationId: post_exists + parameters: + - name: q + in: query + description: Arguments as JSON (PostExistsArgs) + schema: + type: string + responses: + "200": + description: Result of exists + content: + application/json: + schema: + $ref: "#/components/schemas/_ExistsResponse" + "400": *a1 + /post/create: + post: + tags: + - post + summary: create Post + operationId: post_create + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/PostCreateArgs" + responses: + "201": + description: Result of create + content: + application/json: + schema: + $ref: "#/components/schemas/PostResponse" + "400": *a1 + /post/createMany: + post: + tags: + - post + summary: createMany Post + operationId: post_createMany + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/PostCreateManyArgs" + responses: + "201": + description: Result of createMany + content: + application/json: + schema: + $ref: "#/components/schemas/_BatchResponse" + "400": *a1 + /post/createManyAndReturn: + post: + tags: + - post + summary: createManyAndReturn Post + operationId: post_createManyAndReturn + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/PostCreateManyAndReturnArgs" + responses: + "201": + description: Result of createManyAndReturn + content: + application/json: + schema: + $ref: "#/components/schemas/PostListResponse" + "400": *a1 + /post/upsert: + post: + tags: + - post + summary: upsert Post + operationId: post_upsert + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/PostUpsertArgs" + responses: + "201": + description: Result of upsert + content: + application/json: + schema: + $ref: "#/components/schemas/PostResponse" + "400": *a1 + /post/update: + patch: + tags: + - post + summary: update Post + operationId: post_update + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/PostUpdateArgs" + responses: + "200": + description: Result of update + content: + application/json: + schema: + $ref: "#/components/schemas/PostResponse" + "400": *a1 + /post/updateMany: + patch: + tags: + - post + summary: updateMany Post + operationId: post_updateMany + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/PostUpdateManyArgs" + responses: + "200": + description: Result of updateMany + content: + application/json: + schema: + $ref: "#/components/schemas/_BatchResponse" + "400": *a1 + /post/updateManyAndReturn: + patch: + tags: + - post + summary: updateManyAndReturn Post + operationId: post_updateManyAndReturn + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/PostUpdateManyAndReturnArgs" + responses: + "200": + description: Result of updateManyAndReturn + content: + application/json: + schema: + $ref: "#/components/schemas/PostListResponse" + "400": *a1 + /post/delete: + delete: + tags: + - post + summary: delete Post + operationId: post_delete + parameters: + - name: q + in: query + description: Arguments as JSON (PostDeleteArgs) + schema: + type: string + responses: + "200": + description: Result of delete + content: + application/json: + schema: + $ref: "#/components/schemas/PostResponse" + "400": *a1 + /post/deleteMany: + delete: + tags: + - post + summary: deleteMany Post + operationId: post_deleteMany + parameters: + - name: q + in: query + description: Arguments as JSON (PostDeleteManyArgs) + schema: + type: string + responses: + "200": + description: Result of deleteMany + content: + application/json: + schema: + $ref: "#/components/schemas/_BatchResponse" + "400": *a1 + /$transaction/sequential: + post: + tags: + - $transaction + summary: Execute a sequential transaction + operationId: transaction_sequential + requestBody: + required: true + content: + application/json: + schema: + type: array + items: + type: object + properties: + model: + type: string + op: + type: string + args: + type: object + required: + - model + - op + responses: + "200": + description: Transaction results + "400": *a1 +components: + schemas: + _Meta: + type: object + properties: + serialization: {} + _ErrorResponse: + type: object + properties: + error: + type: object + properties: + message: + type: string + _BatchResponse: + type: object + properties: + data: + type: object + properties: + count: + type: integer + required: + - count + meta: + $ref: "#/components/schemas/_Meta" + _ExistsResponse: + type: object + properties: + data: + type: boolean + meta: + $ref: "#/components/schemas/_Meta" + User: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + email: + type: string + posts: + type: array + items: + $ref: "#/components/schemas/Post" + required: + - id + - createdAt + - updatedAt + - email + UserCreateInput: + type: object + properties: + createdAt: + type: string + format: date-time + email: + type: string + required: + - email + UserUpdateInput: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + email: + type: string + UserWhereUniqueInput: + type: object + properties: + id: + type: string + email: + type: string + UserWhereInput: + type: object + properties: + id: + oneOf: + - &a2 + type: string + - type: object + properties: + equals: *a2 + not: *a2 + in: + type: array + items: *a2 + notIn: + type: array + items: *a2 + contains: + type: string + startsWith: + type: string + endsWith: + type: string + mode: + type: string + enum: + - default + - insensitive + createdAt: + oneOf: + - &a3 + type: string + format: date-time + - type: object + properties: + equals: *a3 + not: *a3 + in: + type: array + items: *a3 + notIn: + type: array + items: *a3 + lt: *a3 + lte: *a3 + gt: *a3 + gte: *a3 + updatedAt: + oneOf: + - &a4 + type: string + format: date-time + - type: object + properties: + equals: *a4 + not: *a4 + in: + type: array + items: *a4 + notIn: + type: array + items: *a4 + lt: *a4 + lte: *a4 + gt: *a4 + gte: *a4 + email: + oneOf: + - &a5 + type: string + - type: object + properties: + equals: *a5 + not: *a5 + in: + type: array + items: *a5 + notIn: + type: array + items: *a5 + contains: + type: string + startsWith: + type: string + endsWith: + type: string + mode: + type: string + enum: + - default + - insensitive + AND: + oneOf: + - $ref: "#/components/schemas/UserWhereInput" + - type: array + items: + $ref: "#/components/schemas/UserWhereInput" + OR: + type: array + items: + $ref: "#/components/schemas/UserWhereInput" + NOT: + oneOf: + - $ref: "#/components/schemas/UserWhereInput" + - type: array + items: + $ref: "#/components/schemas/UserWhereInput" + UserSelect: + type: object + properties: + id: + type: boolean + createdAt: + type: boolean + updatedAt: + type: boolean + email: + type: boolean + posts: + oneOf: + - type: boolean + - type: object + properties: + select: + $ref: "#/components/schemas/PostSelect" + omit: + $ref: "#/components/schemas/PostOmit" + include: + $ref: "#/components/schemas/PostInclude" + UserInclude: + type: object + properties: + posts: + oneOf: + - type: boolean + - type: object + properties: + select: + $ref: "#/components/schemas/PostSelect" + omit: + $ref: "#/components/schemas/PostOmit" + include: + $ref: "#/components/schemas/PostInclude" + UserOmit: + type: object + properties: + id: + type: boolean + createdAt: + type: boolean + updatedAt: + type: boolean + email: + type: boolean + UserCreateArgs: + type: object + properties: + data: + $ref: "#/components/schemas/UserCreateInput" + select: + $ref: "#/components/schemas/UserSelect" + include: + $ref: "#/components/schemas/UserInclude" + omit: + $ref: "#/components/schemas/UserOmit" + required: + - data + UserCreateManyArgs: + type: object + properties: + data: + type: array + items: + $ref: "#/components/schemas/UserCreateInput" + required: + - data + UserCreateManyAndReturnArgs: + type: object + properties: + data: + type: array + items: + $ref: "#/components/schemas/UserCreateInput" + select: + $ref: "#/components/schemas/UserSelect" + include: + $ref: "#/components/schemas/UserInclude" + omit: + $ref: "#/components/schemas/UserOmit" + required: + - data + UserUpdateArgs: + type: object + properties: + where: + $ref: "#/components/schemas/UserWhereUniqueInput" + data: + $ref: "#/components/schemas/UserUpdateInput" + select: + $ref: "#/components/schemas/UserSelect" + include: + $ref: "#/components/schemas/UserInclude" + omit: + $ref: "#/components/schemas/UserOmit" + required: + - where + - data + UserUpdateManyArgs: + type: object + properties: + where: + $ref: "#/components/schemas/UserWhereInput" + data: + $ref: "#/components/schemas/UserUpdateInput" + required: + - data + UserUpdateManyAndReturnArgs: + type: object + properties: + where: + $ref: "#/components/schemas/UserWhereInput" + data: + $ref: "#/components/schemas/UserUpdateInput" + select: + $ref: "#/components/schemas/UserSelect" + include: + $ref: "#/components/schemas/UserInclude" + omit: + $ref: "#/components/schemas/UserOmit" + required: + - data + UserUpsertArgs: + type: object + properties: + where: + $ref: "#/components/schemas/UserWhereUniqueInput" + create: + $ref: "#/components/schemas/UserCreateInput" + update: + $ref: "#/components/schemas/UserUpdateInput" + select: + $ref: "#/components/schemas/UserSelect" + include: + $ref: "#/components/schemas/UserInclude" + omit: + $ref: "#/components/schemas/UserOmit" + required: + - where + - create + - update + UserDeleteArgs: + type: object + properties: + where: + $ref: "#/components/schemas/UserWhereUniqueInput" + select: + $ref: "#/components/schemas/UserSelect" + include: + $ref: "#/components/schemas/UserInclude" + omit: + $ref: "#/components/schemas/UserOmit" + required: + - where + UserDeleteManyArgs: + type: object + properties: + where: + $ref: "#/components/schemas/UserWhereInput" + UserFindManyArgs: + type: object + properties: + where: + $ref: "#/components/schemas/UserWhereInput" + orderBy: + type: object + take: + type: integer + skip: + type: integer + select: + $ref: "#/components/schemas/UserSelect" + include: + $ref: "#/components/schemas/UserInclude" + omit: + $ref: "#/components/schemas/UserOmit" + UserFindUniqueArgs: + type: object + properties: + where: + $ref: "#/components/schemas/UserWhereUniqueInput" + select: + $ref: "#/components/schemas/UserSelect" + include: + $ref: "#/components/schemas/UserInclude" + omit: + $ref: "#/components/schemas/UserOmit" + required: + - where + UserFindFirstArgs: + type: object + properties: + where: + $ref: "#/components/schemas/UserWhereInput" + orderBy: + type: object + take: + type: integer + skip: + type: integer + select: + $ref: "#/components/schemas/UserSelect" + include: + $ref: "#/components/schemas/UserInclude" + omit: + $ref: "#/components/schemas/UserOmit" + UserCountArgs: + type: object + properties: + select: + $ref: "#/components/schemas/UserSelect" + where: + $ref: "#/components/schemas/UserWhereInput" + take: + type: integer + skip: + type: integer + UserAggregateArgs: + type: object + properties: + where: + $ref: "#/components/schemas/UserWhereInput" + orderBy: + type: object + take: + type: integer + skip: + type: integer + UserGroupByArgs: + type: object + properties: + where: + $ref: "#/components/schemas/UserWhereInput" + by: + type: array + items: + type: string + orderBy: + type: object + take: + type: integer + skip: + type: integer + UserExistsArgs: + type: object + properties: + where: + $ref: "#/components/schemas/UserWhereUniqueInput" + required: + - where + UserResponse: + type: object + properties: + data: + $ref: "#/components/schemas/User" + meta: + $ref: "#/components/schemas/_Meta" + UserCountAggregateOutputType: + type: object + properties: + id: + type: integer + createdAt: + type: integer + updatedAt: + type: integer + email: + type: integer + _all: + type: integer + required: + - id + - createdAt + - updatedAt + - email + - _all + UserMinAggregateOutputType: + type: object + properties: + id: + oneOf: + - type: "null" + - type: string + createdAt: + oneOf: + - type: "null" + - type: string + format: date-time + updatedAt: + oneOf: + - type: "null" + - type: string + format: date-time + email: + oneOf: + - type: "null" + - type: string + UserMaxAggregateOutputType: + type: object + properties: + id: + oneOf: + - type: "null" + - type: string + createdAt: + oneOf: + - type: "null" + - type: string + format: date-time + updatedAt: + oneOf: + - type: "null" + - type: string + format: date-time + email: + oneOf: + - type: "null" + - type: string + AggregateUser: + type: object + properties: + _count: + oneOf: + - type: "null" + - $ref: "#/components/schemas/UserCountAggregateOutputType" + _min: + oneOf: + - type: "null" + - $ref: "#/components/schemas/UserMinAggregateOutputType" + _max: + oneOf: + - type: "null" + - $ref: "#/components/schemas/UserMaxAggregateOutputType" + UserGroupByOutputType: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + email: + type: string + _count: + oneOf: + - type: "null" + - $ref: "#/components/schemas/UserCountAggregateOutputType" + _min: + oneOf: + - type: "null" + - $ref: "#/components/schemas/UserMinAggregateOutputType" + _max: + oneOf: + - type: "null" + - $ref: "#/components/schemas/UserMaxAggregateOutputType" + required: + - id + - createdAt + - updatedAt + - email + UserCountResponse: + type: object + properties: + data: + oneOf: + - type: integer + - $ref: "#/components/schemas/UserCountAggregateOutputType" + meta: + $ref: "#/components/schemas/_Meta" + UserListResponse: + type: object + properties: + data: + type: array + items: + $ref: "#/components/schemas/User" + meta: + $ref: "#/components/schemas/_Meta" + UserAggregateResponse: + type: object + properties: + data: + $ref: "#/components/schemas/AggregateUser" + meta: + $ref: "#/components/schemas/_Meta" + UserGroupByResponse: + type: object + properties: + data: + type: array + items: + $ref: "#/components/schemas/UserGroupByOutputType" + meta: + $ref: "#/components/schemas/_Meta" + Post: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + title: + type: string + author: + oneOf: + - $ref: "#/components/schemas/User" + - type: "null" + authorId: + oneOf: + - type: string + - type: "null" + published: + type: boolean + publishedAt: + oneOf: + - type: string + format: date-time + - type: "null" + viewCount: + type: integer + required: + - id + - createdAt + - updatedAt + - title + - published + - viewCount + PostCreateInput: + type: object + properties: + createdAt: + type: string + format: date-time + title: + type: string + published: + type: boolean + publishedAt: + type: string + format: date-time + viewCount: + type: integer + required: + - title + PostUpdateInput: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + title: + type: string + published: + type: boolean + publishedAt: + type: string + format: date-time + viewCount: + type: integer + PostWhereUniqueInput: + type: object + properties: + id: + type: string + PostWhereInput: + type: object + properties: + id: + oneOf: + - &a6 + type: string + - type: object + properties: + equals: *a6 + not: *a6 + in: + type: array + items: *a6 + notIn: + type: array + items: *a6 + contains: + type: string + startsWith: + type: string + endsWith: + type: string + mode: + type: string + enum: + - default + - insensitive + createdAt: + oneOf: + - &a7 + type: string + format: date-time + - type: object + properties: + equals: *a7 + not: *a7 + in: + type: array + items: *a7 + notIn: + type: array + items: *a7 + lt: *a7 + lte: *a7 + gt: *a7 + gte: *a7 + updatedAt: + oneOf: + - &a8 + type: string + format: date-time + - type: object + properties: + equals: *a8 + not: *a8 + in: + type: array + items: *a8 + notIn: + type: array + items: *a8 + lt: *a8 + lte: *a8 + gt: *a8 + gte: *a8 + title: + oneOf: + - &a9 + type: string + - type: object + properties: + equals: *a9 + not: *a9 + in: + type: array + items: *a9 + notIn: + type: array + items: *a9 + contains: + type: string + startsWith: + type: string + endsWith: + type: string + mode: + type: string + enum: + - default + - insensitive + authorId: + oneOf: + - &a10 + type: string + - type: object + properties: + equals: *a10 + not: *a10 + in: + type: array + items: *a10 + notIn: + type: array + items: *a10 + contains: + type: string + startsWith: + type: string + endsWith: + type: string + mode: + type: string + enum: + - default + - insensitive + published: + oneOf: + - &a11 + type: boolean + - type: object + properties: + equals: *a11 + not: *a11 + in: + type: array + items: *a11 + notIn: + type: array + items: *a11 + publishedAt: + oneOf: + - &a12 + type: string + format: date-time + - type: object + properties: + equals: *a12 + not: *a12 + in: + type: array + items: *a12 + notIn: + type: array + items: *a12 + lt: *a12 + lte: *a12 + gt: *a12 + gte: *a12 + viewCount: + oneOf: + - &a13 + type: integer + - type: object + properties: + equals: *a13 + not: *a13 + in: + type: array + items: *a13 + notIn: + type: array + items: *a13 + lt: *a13 + lte: *a13 + gt: *a13 + gte: *a13 + AND: + oneOf: + - $ref: "#/components/schemas/PostWhereInput" + - type: array + items: + $ref: "#/components/schemas/PostWhereInput" + OR: + type: array + items: + $ref: "#/components/schemas/PostWhereInput" + NOT: + oneOf: + - $ref: "#/components/schemas/PostWhereInput" + - type: array + items: + $ref: "#/components/schemas/PostWhereInput" + PostSelect: + type: object + properties: + id: + type: boolean + createdAt: + type: boolean + updatedAt: + type: boolean + title: + type: boolean + author: + oneOf: + - type: boolean + - type: object + properties: + select: + $ref: "#/components/schemas/UserSelect" + omit: + $ref: "#/components/schemas/UserOmit" + include: + $ref: "#/components/schemas/UserInclude" + authorId: + type: boolean + published: + type: boolean + publishedAt: + type: boolean + viewCount: + type: boolean + PostInclude: + type: object + properties: + author: + oneOf: + - type: boolean + - type: object + properties: + select: + $ref: "#/components/schemas/UserSelect" + omit: + $ref: "#/components/schemas/UserOmit" + include: + $ref: "#/components/schemas/UserInclude" + PostOmit: + type: object + properties: + id: + type: boolean + createdAt: + type: boolean + updatedAt: + type: boolean + title: + type: boolean + authorId: + type: boolean + published: + type: boolean + publishedAt: + type: boolean + viewCount: + type: boolean + PostCreateArgs: + type: object + properties: + data: + $ref: "#/components/schemas/PostCreateInput" + select: + $ref: "#/components/schemas/PostSelect" + include: + $ref: "#/components/schemas/PostInclude" + omit: + $ref: "#/components/schemas/PostOmit" + required: + - data + PostCreateManyArgs: + type: object + properties: + data: + type: array + items: + $ref: "#/components/schemas/PostCreateInput" + required: + - data + PostCreateManyAndReturnArgs: + type: object + properties: + data: + type: array + items: + $ref: "#/components/schemas/PostCreateInput" + select: + $ref: "#/components/schemas/PostSelect" + include: + $ref: "#/components/schemas/PostInclude" + omit: + $ref: "#/components/schemas/PostOmit" + required: + - data + PostUpdateArgs: + type: object + properties: + where: + $ref: "#/components/schemas/PostWhereUniqueInput" + data: + $ref: "#/components/schemas/PostUpdateInput" + select: + $ref: "#/components/schemas/PostSelect" + include: + $ref: "#/components/schemas/PostInclude" + omit: + $ref: "#/components/schemas/PostOmit" + required: + - where + - data + PostUpdateManyArgs: + type: object + properties: + where: + $ref: "#/components/schemas/PostWhereInput" + data: + $ref: "#/components/schemas/PostUpdateInput" + required: + - data + PostUpdateManyAndReturnArgs: + type: object + properties: + where: + $ref: "#/components/schemas/PostWhereInput" + data: + $ref: "#/components/schemas/PostUpdateInput" + select: + $ref: "#/components/schemas/PostSelect" + include: + $ref: "#/components/schemas/PostInclude" + omit: + $ref: "#/components/schemas/PostOmit" + required: + - data + PostUpsertArgs: + type: object + properties: + where: + $ref: "#/components/schemas/PostWhereUniqueInput" + create: + $ref: "#/components/schemas/PostCreateInput" + update: + $ref: "#/components/schemas/PostUpdateInput" + select: + $ref: "#/components/schemas/PostSelect" + include: + $ref: "#/components/schemas/PostInclude" + omit: + $ref: "#/components/schemas/PostOmit" + required: + - where + - create + - update + PostDeleteArgs: + type: object + properties: + where: + $ref: "#/components/schemas/PostWhereUniqueInput" + select: + $ref: "#/components/schemas/PostSelect" + include: + $ref: "#/components/schemas/PostInclude" + omit: + $ref: "#/components/schemas/PostOmit" + required: + - where + PostDeleteManyArgs: + type: object + properties: + where: + $ref: "#/components/schemas/PostWhereInput" + PostFindManyArgs: + type: object + properties: + where: + $ref: "#/components/schemas/PostWhereInput" + orderBy: + type: object + take: + type: integer + skip: + type: integer + select: + $ref: "#/components/schemas/PostSelect" + include: + $ref: "#/components/schemas/PostInclude" + omit: + $ref: "#/components/schemas/PostOmit" + PostFindUniqueArgs: + type: object + properties: + where: + $ref: "#/components/schemas/PostWhereUniqueInput" + select: + $ref: "#/components/schemas/PostSelect" + include: + $ref: "#/components/schemas/PostInclude" + omit: + $ref: "#/components/schemas/PostOmit" + required: + - where + PostFindFirstArgs: + type: object + properties: + where: + $ref: "#/components/schemas/PostWhereInput" + orderBy: + type: object + take: + type: integer + skip: + type: integer + select: + $ref: "#/components/schemas/PostSelect" + include: + $ref: "#/components/schemas/PostInclude" + omit: + $ref: "#/components/schemas/PostOmit" + PostCountArgs: + type: object + properties: + select: + $ref: "#/components/schemas/PostSelect" + where: + $ref: "#/components/schemas/PostWhereInput" + take: + type: integer + skip: + type: integer + PostAggregateArgs: + type: object + properties: + where: + $ref: "#/components/schemas/PostWhereInput" + orderBy: + type: object + take: + type: integer + skip: + type: integer + PostGroupByArgs: + type: object + properties: + where: + $ref: "#/components/schemas/PostWhereInput" + by: + type: array + items: + type: string + orderBy: + type: object + take: + type: integer + skip: + type: integer + PostExistsArgs: + type: object + properties: + where: + $ref: "#/components/schemas/PostWhereUniqueInput" + required: + - where + PostResponse: + type: object + properties: + data: + $ref: "#/components/schemas/Post" + meta: + $ref: "#/components/schemas/_Meta" + PostCountAggregateOutputType: + type: object + properties: + id: + type: integer + createdAt: + type: integer + updatedAt: + type: integer + title: + type: integer + authorId: + type: integer + published: + type: integer + publishedAt: + type: integer + viewCount: + type: integer + _all: + type: integer + required: + - id + - createdAt + - updatedAt + - title + - authorId + - published + - publishedAt + - viewCount + - _all + PostMinAggregateOutputType: + type: object + properties: + id: + oneOf: + - type: "null" + - type: string + createdAt: + oneOf: + - type: "null" + - type: string + format: date-time + updatedAt: + oneOf: + - type: "null" + - type: string + format: date-time + title: + oneOf: + - type: "null" + - type: string + authorId: + oneOf: + - type: "null" + - type: string + published: + oneOf: + - type: "null" + - type: boolean + publishedAt: + oneOf: + - type: "null" + - type: string + format: date-time + viewCount: + oneOf: + - type: "null" + - type: integer + PostMaxAggregateOutputType: + type: object + properties: + id: + oneOf: + - type: "null" + - type: string + createdAt: + oneOf: + - type: "null" + - type: string + format: date-time + updatedAt: + oneOf: + - type: "null" + - type: string + format: date-time + title: + oneOf: + - type: "null" + - type: string + authorId: + oneOf: + - type: "null" + - type: string + published: + oneOf: + - type: "null" + - type: boolean + publishedAt: + oneOf: + - type: "null" + - type: string + format: date-time + viewCount: + oneOf: + - type: "null" + - type: integer + PostAvgAggregateOutputType: + type: object + properties: + viewCount: + oneOf: + - type: "null" + - type: number + PostSumAggregateOutputType: + type: object + properties: + viewCount: + oneOf: + - type: "null" + - type: integer + AggregatePost: + type: object + properties: + _count: + oneOf: + - type: "null" + - $ref: "#/components/schemas/PostCountAggregateOutputType" + _min: + oneOf: + - type: "null" + - $ref: "#/components/schemas/PostMinAggregateOutputType" + _max: + oneOf: + - type: "null" + - $ref: "#/components/schemas/PostMaxAggregateOutputType" + _avg: + oneOf: + - type: "null" + - $ref: "#/components/schemas/PostAvgAggregateOutputType" + _sum: + oneOf: + - type: "null" + - $ref: "#/components/schemas/PostSumAggregateOutputType" + PostGroupByOutputType: + type: object + properties: + id: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + title: + type: string + authorId: + oneOf: + - type: string + - type: "null" + published: + type: boolean + publishedAt: + oneOf: + - type: string + format: date-time + - type: "null" + viewCount: + type: integer + _count: + oneOf: + - type: "null" + - $ref: "#/components/schemas/PostCountAggregateOutputType" + _min: + oneOf: + - type: "null" + - $ref: "#/components/schemas/PostMinAggregateOutputType" + _max: + oneOf: + - type: "null" + - $ref: "#/components/schemas/PostMaxAggregateOutputType" + _avg: + oneOf: + - type: "null" + - $ref: "#/components/schemas/PostAvgAggregateOutputType" + _sum: + oneOf: + - type: "null" + - $ref: "#/components/schemas/PostSumAggregateOutputType" + required: + - id + - createdAt + - updatedAt + - title + - published + - viewCount + PostCountResponse: + type: object + properties: + data: + oneOf: + - type: integer + - $ref: "#/components/schemas/PostCountAggregateOutputType" + meta: + $ref: "#/components/schemas/_Meta" + PostListResponse: + type: object + properties: + data: + type: array + items: + $ref: "#/components/schemas/Post" + meta: + $ref: "#/components/schemas/_Meta" + PostAggregateResponse: + type: object + properties: + data: + $ref: "#/components/schemas/AggregatePost" + meta: + $ref: "#/components/schemas/_Meta" + PostGroupByResponse: + type: object + properties: + data: + type: array + items: + $ref: "#/components/schemas/PostGroupByOutputType" + meta: + $ref: "#/components/schemas/_Meta" diff --git a/packages/server/test/openapi/migrated/baseline/rest-3.1.0.baseline.yaml b/packages/server/test/openapi/migrated/baseline/rest-3.1.0.baseline.yaml deleted file mode 100644 index 1e331ab8e..000000000 --- a/packages/server/test/openapi/migrated/baseline/rest-3.1.0.baseline.yaml +++ /dev/null @@ -1,3279 +0,0 @@ -openapi: 3.1.0 -info: - title: ZenStack Generated API - version: 1.0.0 -tags: - - name: user - description: User operations - - name: profile - description: Profile operations - - name: post_Item - description: Post-related operations - - name: postLike - description: PostLike operations -paths: - /user: - get: - operationId: list-User - description: List "User" resources - tags: - - user - parameters: - - $ref: '#/components/parameters/include' - - $ref: '#/components/parameters/sort' - - $ref: '#/components/parameters/page-offset' - - $ref: '#/components/parameters/page-limit' - - name: filter[id] - required: false - description: Id filter - in: query - style: form - explode: false - schema: - type: string - - name: filter[createdAt] - required: false - description: Equality filter for "createdAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[createdAt$lt] - required: false - description: Less-than filter for "createdAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[createdAt$lte] - required: false - description: Less-than or equal filter for "createdAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[createdAt$gt] - required: false - description: Greater-than filter for "createdAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[createdAt$gte] - required: false - description: Greater-than or equal filter for "createdAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[updatedAt] - required: false - description: Equality filter for "updatedAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[updatedAt$lt] - required: false - description: Less-than filter for "updatedAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[updatedAt$lte] - required: false - description: Less-than or equal filter for "updatedAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[updatedAt$gt] - required: false - description: Greater-than filter for "updatedAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[updatedAt$gte] - required: false - description: Greater-than or equal filter for "updatedAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[email] - required: false - description: Equality filter for "email" - in: query - style: form - explode: false - schema: - type: string - - name: filter[email$contains] - required: false - description: String contains filter for "email" - in: query - style: form - explode: false - schema: - type: string - - name: filter[email$icontains] - required: false - description: String case-insensitive contains filter for "email" - in: query - style: form - explode: false - schema: - type: string - - name: filter[email$search] - required: false - description: String full-text search filter for "email" - in: query - style: form - explode: false - schema: - type: string - - name: filter[email$startsWith] - required: false - description: String startsWith filter for "email" - in: query - style: form - explode: false - schema: - type: string - - name: filter[email$endsWith] - required: false - description: String endsWith filter for "email" - in: query - style: form - explode: false - schema: - type: string - - name: filter[role] - required: false - description: Equality filter for "role" - in: query - style: form - explode: false - schema: - $ref: '#/components/schemas/role' - - name: filter[posts] - required: false - description: Equality filter for "posts" - in: query - style: form - explode: false - schema: - type: array - items: - type: string - - name: filter[profile] - required: false - description: Equality filter for "profile" - in: query - style: form - explode: false - schema: - type: string - - name: filter[likes] - required: false - description: Equality filter for "likes" - in: query - style: form - explode: false - schema: - type: array - items: - type: string - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/UserListResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - post: - operationId: create-User - description: Create a "User" resource - tags: - - user - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/UserCreateRequest' - responses: - '201': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/UserResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '422': - description: Request is unprocessable due to validation errors - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - /user/{id}: - get: - operationId: fetch-User - description: Fetch a "User" resource - tags: - - user - parameters: - - $ref: '#/components/parameters/id' - - $ref: '#/components/parameters/include' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/UserResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - put: - operationId: update-User-put - description: Update a "User" resource - tags: - - user - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/UserUpdateRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/UserResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '422': - description: Request is unprocessable due to validation errors - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - patch: - operationId: update-User-patch - description: Update a "User" resource - tags: - - user - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/UserUpdateRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/UserResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '422': - description: Request is unprocessable due to validation errors - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - delete: - operationId: delete-User - description: Delete a "User" resource - tags: - - user - parameters: - - $ref: '#/components/parameters/id' - responses: - '200': - description: Successful operation - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - /user/{id}/posts: - get: - operationId: fetch-User-related-posts - description: Fetch the related "posts" resource for "User" - tags: - - user - parameters: - - $ref: '#/components/parameters/id' - - $ref: '#/components/parameters/include' - - $ref: '#/components/parameters/sort' - - $ref: '#/components/parameters/page-offset' - - $ref: '#/components/parameters/page-limit' - - name: filter[id] - required: false - description: Id filter - in: query - style: form - explode: false - schema: - type: string - - name: filter[createdAt] - required: false - description: Equality filter for "createdAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[createdAt$lt] - required: false - description: Less-than filter for "createdAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[createdAt$lte] - required: false - description: Less-than or equal filter for "createdAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[createdAt$gt] - required: false - description: Greater-than filter for "createdAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[createdAt$gte] - required: false - description: Greater-than or equal filter for "createdAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[updatedAt] - required: false - description: Equality filter for "updatedAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[updatedAt$lt] - required: false - description: Less-than filter for "updatedAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[updatedAt$lte] - required: false - description: Less-than or equal filter for "updatedAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[updatedAt$gt] - required: false - description: Greater-than filter for "updatedAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[updatedAt$gte] - required: false - description: Greater-than or equal filter for "updatedAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[email] - required: false - description: Equality filter for "email" - in: query - style: form - explode: false - schema: - type: string - - name: filter[email$contains] - required: false - description: String contains filter for "email" - in: query - style: form - explode: false - schema: - type: string - - name: filter[email$icontains] - required: false - description: String case-insensitive contains filter for "email" - in: query - style: form - explode: false - schema: - type: string - - name: filter[email$search] - required: false - description: String full-text search filter for "email" - in: query - style: form - explode: false - schema: - type: string - - name: filter[email$startsWith] - required: false - description: String startsWith filter for "email" - in: query - style: form - explode: false - schema: - type: string - - name: filter[email$endsWith] - required: false - description: String endsWith filter for "email" - in: query - style: form - explode: false - schema: - type: string - - name: filter[role] - required: false - description: Equality filter for "role" - in: query - style: form - explode: false - schema: - $ref: '#/components/schemas/role' - - name: filter[posts] - required: false - description: Equality filter for "posts" - in: query - style: form - explode: false - schema: - type: array - items: - type: string - - name: filter[profile] - required: false - description: Equality filter for "profile" - in: query - style: form - explode: false - schema: - type: string - - name: filter[likes] - required: false - description: Equality filter for "likes" - in: query - style: form - explode: false - schema: - type: array - items: - type: string - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/post_ItemListResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - /user/{id}/relationships/posts: - get: - operationId: fetch-User-relationship-posts - description: Fetch the "posts" relationships for a "User" - tags: - - user - parameters: - - $ref: '#/components/parameters/id' - - $ref: '#/components/parameters/sort' - - $ref: '#/components/parameters/page-offset' - - $ref: '#/components/parameters/page-limit' - - name: filter[id] - required: false - description: Id filter - in: query - style: form - explode: false - schema: - type: string - - name: filter[createdAt] - required: false - description: Equality filter for "createdAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[createdAt$lt] - required: false - description: Less-than filter for "createdAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[createdAt$lte] - required: false - description: Less-than or equal filter for "createdAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[createdAt$gt] - required: false - description: Greater-than filter for "createdAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[createdAt$gte] - required: false - description: Greater-than or equal filter for "createdAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[updatedAt] - required: false - description: Equality filter for "updatedAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[updatedAt$lt] - required: false - description: Less-than filter for "updatedAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[updatedAt$lte] - required: false - description: Less-than or equal filter for "updatedAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[updatedAt$gt] - required: false - description: Greater-than filter for "updatedAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[updatedAt$gte] - required: false - description: Greater-than or equal filter for "updatedAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[email] - required: false - description: Equality filter for "email" - in: query - style: form - explode: false - schema: - type: string - - name: filter[email$contains] - required: false - description: String contains filter for "email" - in: query - style: form - explode: false - schema: - type: string - - name: filter[email$icontains] - required: false - description: String case-insensitive contains filter for "email" - in: query - style: form - explode: false - schema: - type: string - - name: filter[email$search] - required: false - description: String full-text search filter for "email" - in: query - style: form - explode: false - schema: - type: string - - name: filter[email$startsWith] - required: false - description: String startsWith filter for "email" - in: query - style: form - explode: false - schema: - type: string - - name: filter[email$endsWith] - required: false - description: String endsWith filter for "email" - in: query - style: form - explode: false - schema: - type: string - - name: filter[role] - required: false - description: Equality filter for "role" - in: query - style: form - explode: false - schema: - $ref: '#/components/schemas/role' - - name: filter[posts] - required: false - description: Equality filter for "posts" - in: query - style: form - explode: false - schema: - type: array - items: - type: string - - name: filter[profile] - required: false - description: Equality filter for "profile" - in: query - style: form - explode: false - schema: - type: string - - name: filter[likes] - required: false - description: Equality filter for "likes" - in: query - style: form - explode: false - schema: - type: array - items: - type: string - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toManyRelationshipResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - put: - operationId: update-User-relationship-posts-put - description: Update "posts" relationships for a "User" - tags: - - user - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toManyRelationshipRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toManyRelationshipResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - patch: - operationId: update-User-relationship-posts-patch - description: Update "posts" relationships for a "User" - tags: - - user - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toManyRelationshipRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toManyRelationshipResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - post: - operationId: create-User-relationship-posts - description: Create new "posts" relationships for a "User" - tags: - - user - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toManyRelationshipRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toManyRelationshipResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - /user/{id}/profile: - get: - operationId: fetch-User-related-profile - description: Fetch the related "profile" resource for "User" - tags: - - user - parameters: - - $ref: '#/components/parameters/id' - - $ref: '#/components/parameters/include' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/ProfileResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - /user/{id}/relationships/profile: - get: - operationId: fetch-User-relationship-profile - description: Fetch the "profile" relationships for a "User" - tags: - - user - parameters: - - $ref: '#/components/parameters/id' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - put: - operationId: update-User-relationship-profile-put - description: Update "profile" relationship for a "User" - tags: - - user - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - patch: - operationId: update-User-relationship-profile-patch - description: Update "profile" relationship for a "User" - tags: - - user - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - /profile: - get: - operationId: list-Profile - description: List "Profile" resources - tags: - - profile - parameters: - - $ref: '#/components/parameters/include' - - $ref: '#/components/parameters/sort' - - $ref: '#/components/parameters/page-offset' - - $ref: '#/components/parameters/page-limit' - - name: filter[id] - required: false - description: Id filter - in: query - style: form - explode: false - schema: - type: string - - name: filter[image] - required: false - description: Equality filter for "image" - in: query - style: form - explode: false - schema: - type: string - - name: filter[image$contains] - required: false - description: String contains filter for "image" - in: query - style: form - explode: false - schema: - type: string - - name: filter[image$icontains] - required: false - description: String case-insensitive contains filter for "image" - in: query - style: form - explode: false - schema: - type: string - - name: filter[image$search] - required: false - description: String full-text search filter for "image" - in: query - style: form - explode: false - schema: - type: string - - name: filter[image$startsWith] - required: false - description: String startsWith filter for "image" - in: query - style: form - explode: false - schema: - type: string - - name: filter[image$endsWith] - required: false - description: String endsWith filter for "image" - in: query - style: form - explode: false - schema: - type: string - - name: filter[user] - required: false - description: Equality filter for "user" - in: query - style: form - explode: false - schema: - type: string - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/ProfileListResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - post: - operationId: create-Profile - description: Create a "Profile" resource - tags: - - profile - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/ProfileCreateRequest' - responses: - '201': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/ProfileResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '422': - description: Request is unprocessable due to validation errors - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - /profile/{id}: - get: - operationId: fetch-Profile - description: Fetch a "Profile" resource - tags: - - profile - parameters: - - $ref: '#/components/parameters/id' - - $ref: '#/components/parameters/include' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/ProfileResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - put: - operationId: update-Profile-put - description: Update a "Profile" resource - tags: - - profile - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/ProfileUpdateRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/ProfileResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '422': - description: Request is unprocessable due to validation errors - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - patch: - operationId: update-Profile-patch - description: Update a "Profile" resource - tags: - - profile - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/ProfileUpdateRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/ProfileResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '422': - description: Request is unprocessable due to validation errors - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - delete: - operationId: delete-Profile - description: Delete a "Profile" resource - tags: - - profile - parameters: - - $ref: '#/components/parameters/id' - responses: - '200': - description: Successful operation - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - /profile/{id}/user: - get: - operationId: fetch-Profile-related-user - description: Fetch the related "user" resource for "Profile" - tags: - - profile - parameters: - - $ref: '#/components/parameters/id' - - $ref: '#/components/parameters/include' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/UserResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - /profile/{id}/relationships/user: - get: - operationId: fetch-Profile-relationship-user - description: Fetch the "user" relationships for a "Profile" - tags: - - profile - parameters: - - $ref: '#/components/parameters/id' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - put: - operationId: update-Profile-relationship-user-put - description: Update "user" relationship for a "Profile" - tags: - - profile - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - patch: - operationId: update-Profile-relationship-user-patch - description: Update "user" relationship for a "Profile" - tags: - - profile - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - /post_Item: - get: - operationId: list-post_Item - description: List "post_Item" resources - tags: - - post_Item - parameters: - - $ref: '#/components/parameters/include' - - $ref: '#/components/parameters/sort' - - $ref: '#/components/parameters/page-offset' - - $ref: '#/components/parameters/page-limit' - - name: filter[id] - required: false - description: Id filter - in: query - style: form - explode: false - schema: - type: string - - name: filter[createdAt] - required: false - description: Equality filter for "createdAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[createdAt$lt] - required: false - description: Less-than filter for "createdAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[createdAt$lte] - required: false - description: Less-than or equal filter for "createdAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[createdAt$gt] - required: false - description: Greater-than filter for "createdAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[createdAt$gte] - required: false - description: Greater-than or equal filter for "createdAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[updatedAt] - required: false - description: Equality filter for "updatedAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[updatedAt$lt] - required: false - description: Less-than filter for "updatedAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[updatedAt$lte] - required: false - description: Less-than or equal filter for "updatedAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[updatedAt$gt] - required: false - description: Greater-than filter for "updatedAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[updatedAt$gte] - required: false - description: Greater-than or equal filter for "updatedAt" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[title] - required: false - description: Equality filter for "title" - in: query - style: form - explode: false - schema: - type: string - - name: filter[title$contains] - required: false - description: String contains filter for "title" - in: query - style: form - explode: false - schema: - type: string - - name: filter[title$icontains] - required: false - description: String case-insensitive contains filter for "title" - in: query - style: form - explode: false - schema: - type: string - - name: filter[title$search] - required: false - description: String full-text search filter for "title" - in: query - style: form - explode: false - schema: - type: string - - name: filter[title$startsWith] - required: false - description: String startsWith filter for "title" - in: query - style: form - explode: false - schema: - type: string - - name: filter[title$endsWith] - required: false - description: String endsWith filter for "title" - in: query - style: form - explode: false - schema: - type: string - - name: filter[author] - required: false - description: Equality filter for "author" - in: query - style: form - explode: false - schema: - type: string - - name: filter[published] - required: false - description: Equality filter for "published" - in: query - style: form - explode: false - schema: - type: boolean - - name: filter[viewCount] - required: false - description: Equality filter for "viewCount" - in: query - style: form - explode: false - schema: - type: integer - - name: filter[viewCount$lt] - required: false - description: Less-than filter for "viewCount" - in: query - style: form - explode: false - schema: - type: integer - - name: filter[viewCount$lte] - required: false - description: Less-than or equal filter for "viewCount" - in: query - style: form - explode: false - schema: - type: integer - - name: filter[viewCount$gt] - required: false - description: Greater-than filter for "viewCount" - in: query - style: form - explode: false - schema: - type: integer - - name: filter[viewCount$gte] - required: false - description: Greater-than or equal filter for "viewCount" - in: query - style: form - explode: false - schema: - type: integer - - name: filter[notes] - required: false - description: Equality filter for "notes" - in: query - style: form - explode: false - schema: - type: string - - name: filter[notes$contains] - required: false - description: String contains filter for "notes" - in: query - style: form - explode: false - schema: - type: string - - name: filter[notes$icontains] - required: false - description: String case-insensitive contains filter for "notes" - in: query - style: form - explode: false - schema: - type: string - - name: filter[notes$search] - required: false - description: String full-text search filter for "notes" - in: query - style: form - explode: false - schema: - type: string - - name: filter[notes$startsWith] - required: false - description: String startsWith filter for "notes" - in: query - style: form - explode: false - schema: - type: string - - name: filter[notes$endsWith] - required: false - description: String endsWith filter for "notes" - in: query - style: form - explode: false - schema: - type: string - - name: filter[likes] - required: false - description: Equality filter for "likes" - in: query - style: form - explode: false - schema: - type: array - items: - type: string - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/post_ItemListResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - post: - operationId: create-post_Item - description: Create a "post_Item" resource - tags: - - post_Item - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/post_ItemCreateRequest' - responses: - '201': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/post_ItemResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '422': - description: Request is unprocessable due to validation errors - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - /post_Item/{id}: - get: - operationId: fetch-post_Item - description: Fetch a "post_Item" resource - tags: - - post_Item - parameters: - - $ref: '#/components/parameters/id' - - $ref: '#/components/parameters/include' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/post_ItemResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - put: - operationId: update-post_Item-put - description: Update a "post_Item" resource - tags: - - post_Item - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/post_ItemUpdateRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/post_ItemResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '422': - description: Request is unprocessable due to validation errors - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - patch: - operationId: update-post_Item-patch - description: Update a "post_Item" resource - tags: - - post_Item - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/post_ItemUpdateRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/post_ItemResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '422': - description: Request is unprocessable due to validation errors - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - delete: - operationId: delete-post_Item - description: Delete a "post_Item" resource - tags: - - post_Item - parameters: - - $ref: '#/components/parameters/id' - responses: - '200': - description: Successful operation - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - /post_Item/{id}/author: - get: - operationId: fetch-post_Item-related-author - description: Fetch the related "author" resource for "post_Item" - tags: - - post_Item - parameters: - - $ref: '#/components/parameters/id' - - $ref: '#/components/parameters/include' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/UserResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - /post_Item/{id}/relationships/author: - get: - operationId: fetch-post_Item-relationship-author - description: Fetch the "author" relationships for a "post_Item" - tags: - - post_Item - parameters: - - $ref: '#/components/parameters/id' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - put: - operationId: update-post_Item-relationship-author-put - description: Update "author" relationship for a "post_Item" - tags: - - post_Item - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - patch: - operationId: update-post_Item-relationship-author-patch - description: Update "author" relationship for a "post_Item" - tags: - - post_Item - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - /postLike: - get: - operationId: list-PostLike - description: List "PostLike" resources - tags: - - postLike - parameters: - - $ref: '#/components/parameters/include' - - $ref: '#/components/parameters/sort' - - $ref: '#/components/parameters/page-offset' - - $ref: '#/components/parameters/page-limit' - - name: filter[post] - required: false - description: Equality filter for "post" - in: query - style: form - explode: false - schema: - type: string - - name: filter[user] - required: false - description: Equality filter for "user" - in: query - style: form - explode: false - schema: - type: string - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/PostLikeListResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - post: - operationId: create-PostLike - description: Create a "PostLike" resource - tags: - - postLike - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/PostLikeCreateRequest' - responses: - '201': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/PostLikeResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '422': - description: Request is unprocessable due to validation errors - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - /postLike/{id}: - get: - operationId: fetch-PostLike - description: Fetch a "PostLike" resource - tags: - - postLike - parameters: - - $ref: '#/components/parameters/id' - - $ref: '#/components/parameters/include' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/PostLikeResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - put: - operationId: update-PostLike-put - description: Update a "PostLike" resource - tags: - - postLike - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/PostLikeUpdateRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/PostLikeResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '422': - description: Request is unprocessable due to validation errors - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - patch: - operationId: update-PostLike-patch - description: Update a "PostLike" resource - tags: - - postLike - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/PostLikeUpdateRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/PostLikeResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '422': - description: Request is unprocessable due to validation errors - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - delete: - operationId: delete-PostLike - description: Delete a "PostLike" resource - tags: - - postLike - parameters: - - $ref: '#/components/parameters/id' - responses: - '200': - description: Successful operation - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - /postLike/{id}/post: - get: - operationId: fetch-PostLike-related-post - description: Fetch the related "post" resource for "PostLike" - tags: - - postLike - parameters: - - $ref: '#/components/parameters/id' - - $ref: '#/components/parameters/include' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/post_ItemResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - /postLike/{id}/relationships/post: - get: - operationId: fetch-PostLike-relationship-post - description: Fetch the "post" relationships for a "PostLike" - tags: - - postLike - parameters: - - $ref: '#/components/parameters/id' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - put: - operationId: update-PostLike-relationship-post-put - description: Update "post" relationship for a "PostLike" - tags: - - postLike - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - patch: - operationId: update-PostLike-relationship-post-patch - description: Update "post" relationship for a "PostLike" - tags: - - postLike - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - /postLike/{id}/user: - get: - operationId: fetch-PostLike-related-user - description: Fetch the related "user" resource for "PostLike" - tags: - - postLike - parameters: - - $ref: '#/components/parameters/id' - - $ref: '#/components/parameters/include' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/UserResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - /postLike/{id}/relationships/user: - get: - operationId: fetch-PostLike-relationship-user - description: Fetch the "user" relationships for a "PostLike" - tags: - - postLike - parameters: - - $ref: '#/components/parameters/id' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - put: - operationId: update-PostLike-relationship-user-put - description: Update "user" relationship for a "PostLike" - tags: - - postLike - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - patch: - operationId: update-PostLike-relationship-user-patch - description: Update "user" relationship for a "PostLike" - tags: - - postLike - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_toOneRelationshipResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' -components: - schemas: - _jsonapi: - type: object - description: An object describing the server’s implementation - required: - - version - properties: - version: - type: string - _meta: - type: object - description: Meta information about the request or response - properties: - serialization: - description: Superjson serialization metadata - additionalProperties: true - _resourceIdentifier: - type: object - description: Identifier for a resource - required: - - type - - id - properties: - type: - type: string - description: Resource type - id: - type: string - description: Resource id - _resource: - allOf: - - $ref: '#/components/schemas/_resourceIdentifier' - - type: object - description: A resource with attributes and relationships - properties: - attributes: - type: object - description: Resource attributes - relationships: - type: object - description: Resource relationships - _links: - type: object - required: - - self - description: Links related to the resource - properties: - self: - type: string - description: Link for refetching the curent results - _pagination: - type: object - description: Pagination information - required: - - first - - last - - prev - - next - properties: - first: - oneOf: - - type: 'null' - - type: string - description: Link to the first page - last: - oneOf: - - type: 'null' - - type: string - description: Link to the last page - prev: - oneOf: - - type: 'null' - - type: string - description: Link to the previous page - next: - oneOf: - - type: 'null' - - type: string - description: Link to the next page - _errors: - type: array - description: An array of error objects - items: - type: object - required: - - status - - code - properties: - status: - type: string - description: HTTP status - code: - type: string - description: Error code - prismaCode: - type: string - description: Prisma error code if the error is thrown by Prisma - title: - type: string - description: Error title - detail: - type: string - description: Error detail - reason: - type: string - description: Detailed error reason - zodErrors: - type: object - additionalProperties: true - description: Zod validation errors if the error is due to data validation - failure - _errorResponse: - type: object - required: - - errors - description: An error response - properties: - jsonapi: - $ref: '#/components/schemas/_jsonapi' - errors: - $ref: '#/components/schemas/_errors' - _relationLinks: - type: object - required: - - self - - related - description: Links related to a relationship - properties: - self: - type: string - description: Link for fetching this relationship - related: - type: string - description: Link for fetching the resource represented by this relationship - _toOneRelationship: - type: object - description: A to-one relationship - properties: - data: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/_resourceIdentifier' - _toOneRelationshipWithLinks: - type: object - required: - - links - - data - description: A to-one relationship with links - properties: - links: - $ref: '#/components/schemas/_relationLinks' - data: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/_resourceIdentifier' - _toManyRelationship: - type: object - required: - - data - description: A to-many relationship - properties: - data: - type: array - items: - $ref: '#/components/schemas/_resourceIdentifier' - _toManyRelationshipWithLinks: - type: object - required: - - links - - data - description: A to-many relationship with links - properties: - links: - $ref: '#/components/schemas/_pagedRelationLinks' - data: - type: array - items: - $ref: '#/components/schemas/_resourceIdentifier' - _pagedRelationLinks: - description: Relationship links with pagination information - allOf: - - $ref: '#/components/schemas/_pagination' - - $ref: '#/components/schemas/_relationLinks' - _toManyRelationshipRequest: - type: object - required: - - data - description: Input for manipulating a to-many relationship - properties: - data: - type: array - items: - $ref: '#/components/schemas/_resourceIdentifier' - _toOneRelationshipRequest: - description: Input for manipulating a to-one relationship - oneOf: - - type: 'null' - - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/_resourceIdentifier' - _toManyRelationshipResponse: - description: Response for a to-many relationship - allOf: - - $ref: '#/components/schemas/_toManyRelationshipWithLinks' - - type: object - properties: - jsonapi: - $ref: '#/components/schemas/_jsonapi' - _toOneRelationshipResponse: - description: Response for a to-one relationship - allOf: - - $ref: '#/components/schemas/_toOneRelationshipWithLinks' - - type: object - properties: - jsonapi: - $ref: '#/components/schemas/_jsonapi' - role: - type: string - description: The "role" Enum - enum: - - USER - - ADMIN - User: - type: object - description: The "User" model - required: - - id - - type - - attributes - properties: - id: - type: string - type: - type: string - attributes: - type: object - properties: - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - email: - type: string - role: - $ref: '#/components/schemas/role' - required: - - createdAt - - updatedAt - - email - - role - relationships: - type: object - properties: - posts: - $ref: '#/components/schemas/_toManyRelationshipWithLinks' - profile: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/_toOneRelationshipWithLinks' - UserCreateRequest: - type: object - description: Input for creating a "User" - required: - - data - properties: - data: - type: object - description: The "User" model - required: - - type - - attributes - properties: - type: - type: string - attributes: - type: object - required: - - updatedAt - - email - properties: - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - email: - type: string - role: - $ref: '#/components/schemas/role' - relationships: - type: object - properties: - posts: - $ref: '#/components/schemas/_toManyRelationship' - profile: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/_toOneRelationship' - meta: - $ref: '#/components/schemas/_meta' - UserUpdateRequest: - type: object - description: Input for updating a "User" - required: - - data - properties: - data: - type: object - description: The "User" model - required: - - id - - type - - attributes - properties: - id: - type: string - type: - type: string - attributes: - type: object - properties: - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - email: - type: string - role: - $ref: '#/components/schemas/role' - relationships: - type: object - properties: - posts: - $ref: '#/components/schemas/_toManyRelationship' - profile: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/_toOneRelationship' - meta: - $ref: '#/components/schemas/_meta' - UserResponse: - type: object - description: Response for a "User" - required: - - data - properties: - jsonapi: - $ref: '#/components/schemas/_jsonapi' - data: - allOf: - - $ref: '#/components/schemas/User' - - type: object - properties: - relationships: - type: object - properties: &a1 - posts: - $ref: '#/components/schemas/_toManyRelationship' - profile: - $ref: '#/components/schemas/_toOneRelationship' - meta: - $ref: '#/components/schemas/_meta' - included: - type: array - items: - $ref: '#/components/schemas/_resource' - links: - $ref: '#/components/schemas/_links' - UserListResponse: - type: object - description: Response for a list of "User" - required: - - data - - links - properties: - jsonapi: - $ref: '#/components/schemas/_jsonapi' - data: - type: array - items: - allOf: - - $ref: '#/components/schemas/User' - - type: object - properties: - relationships: - type: object - properties: *a1 - meta: - $ref: '#/components/schemas/_meta' - included: - type: array - items: - $ref: '#/components/schemas/_resource' - links: - allOf: - - $ref: '#/components/schemas/_links' - - $ref: '#/components/schemas/_pagination' - Profile: - type: object - description: The "Profile" model - required: - - id - - type - - attributes - properties: - id: - type: string - type: - type: string - attributes: - type: object - properties: - image: - oneOf: - - type: 'null' - - type: string - userId: - type: string - required: - - image - - userId - relationships: - type: object - properties: - user: - $ref: '#/components/schemas/_toOneRelationshipWithLinks' - ProfileCreateRequest: - type: object - description: Input for creating a "Profile" - required: - - data - properties: - data: - type: object - description: The "Profile" model - required: - - type - - attributes - properties: - type: - type: string - attributes: - type: object - properties: - image: - oneOf: - - type: 'null' - - type: string - relationships: - type: object - properties: - user: - $ref: '#/components/schemas/_toOneRelationship' - meta: - $ref: '#/components/schemas/_meta' - ProfileUpdateRequest: - type: object - description: Input for updating a "Profile" - required: - - data - properties: - data: - type: object - description: The "Profile" model - required: - - id - - type - - attributes - properties: - id: - type: string - type: - type: string - attributes: - type: object - properties: - image: - oneOf: - - type: 'null' - - type: string - relationships: - type: object - properties: - user: - $ref: '#/components/schemas/_toOneRelationship' - meta: - $ref: '#/components/schemas/_meta' - ProfileResponse: - type: object - description: Response for a "Profile" - required: - - data - properties: - jsonapi: - $ref: '#/components/schemas/_jsonapi' - data: - allOf: - - $ref: '#/components/schemas/Profile' - - type: object - properties: - relationships: - type: object - properties: &a2 - user: - $ref: '#/components/schemas/_toOneRelationship' - meta: - $ref: '#/components/schemas/_meta' - included: - type: array - items: - $ref: '#/components/schemas/_resource' - links: - $ref: '#/components/schemas/_links' - ProfileListResponse: - type: object - description: Response for a list of "Profile" - required: - - data - - links - properties: - jsonapi: - $ref: '#/components/schemas/_jsonapi' - data: - type: array - items: - allOf: - - $ref: '#/components/schemas/Profile' - - type: object - properties: - relationships: - type: object - properties: *a2 - meta: - $ref: '#/components/schemas/_meta' - included: - type: array - items: - $ref: '#/components/schemas/_resource' - links: - allOf: - - $ref: '#/components/schemas/_links' - - $ref: '#/components/schemas/_pagination' - post_Item: - type: object - description: The "post_Item" model - required: - - id - - type - - attributes - properties: - id: - type: string - type: - type: string - attributes: - type: object - properties: - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - title: - type: string - authorId: - oneOf: - - type: 'null' - - type: string - published: - type: boolean - viewCount: - type: integer - notes: - oneOf: - - type: 'null' - - type: string - required: - - createdAt - - updatedAt - - title - - authorId - - published - - viewCount - - notes - relationships: - type: object - properties: - author: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/_toOneRelationshipWithLinks' - post_ItemCreateRequest: - type: object - description: Input for creating a "post_Item" - required: - - data - properties: - data: - type: object - description: The "post_Item" model - required: - - id - - type - - attributes - properties: - id: - type: string - type: - type: string - attributes: - type: object - required: - - updatedAt - - title - properties: - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - title: - type: string - published: - type: boolean - viewCount: - type: integer - notes: - oneOf: - - type: 'null' - - type: string - relationships: - type: object - properties: - author: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/_toOneRelationship' - meta: - $ref: '#/components/schemas/_meta' - post_ItemUpdateRequest: - type: object - description: Input for updating a "post_Item" - required: - - data - properties: - data: - type: object - description: The "post_Item" model - required: - - id - - type - - attributes - properties: - id: - type: string - type: - type: string - attributes: - type: object - properties: - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - title: - type: string - published: - type: boolean - viewCount: - type: integer - notes: - oneOf: - - type: 'null' - - type: string - relationships: - type: object - properties: - author: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/_toOneRelationship' - meta: - $ref: '#/components/schemas/_meta' - post_ItemResponse: - type: object - description: Response for a "post_Item" - required: - - data - properties: - jsonapi: - $ref: '#/components/schemas/_jsonapi' - data: - allOf: - - $ref: '#/components/schemas/post_Item' - - type: object - properties: - relationships: - type: object - properties: &a3 - author: - $ref: '#/components/schemas/_toOneRelationship' - meta: - $ref: '#/components/schemas/_meta' - included: - type: array - items: - $ref: '#/components/schemas/_resource' - links: - $ref: '#/components/schemas/_links' - post_ItemListResponse: - type: object - description: Response for a list of "post_Item" - required: - - data - - links - properties: - jsonapi: - $ref: '#/components/schemas/_jsonapi' - data: - type: array - items: - allOf: - - $ref: '#/components/schemas/post_Item' - - type: object - properties: - relationships: - type: object - properties: *a3 - meta: - $ref: '#/components/schemas/_meta' - included: - type: array - items: - $ref: '#/components/schemas/_resource' - links: - allOf: - - $ref: '#/components/schemas/_links' - - $ref: '#/components/schemas/_pagination' - PostLike: - type: object - description: The "PostLike" model - required: - - id - - type - - attributes - properties: - id: - type: string - type: - type: string - attributes: - type: object - properties: - postId: - type: string - userId: - type: string - required: - - postId - - userId - relationships: - type: object - properties: - post: - $ref: '#/components/schemas/_toOneRelationshipWithLinks' - user: - $ref: '#/components/schemas/_toOneRelationshipWithLinks' - PostLikeCreateRequest: - type: object - description: Input for creating a "PostLike" - required: - - data - properties: - data: - type: object - description: The "PostLike" model - required: - - type - - attributes - properties: - type: - type: string - relationships: - type: object - properties: - post: - $ref: '#/components/schemas/_toOneRelationship' - user: - $ref: '#/components/schemas/_toOneRelationship' - meta: - $ref: '#/components/schemas/_meta' - PostLikeUpdateRequest: - type: object - description: Input for updating a "PostLike" - required: - - data - properties: - data: - type: object - description: The "PostLike" model - required: - - id - - type - - attributes - properties: - id: - type: string - type: - type: string - relationships: - type: object - properties: - post: - $ref: '#/components/schemas/_toOneRelationship' - user: - $ref: '#/components/schemas/_toOneRelationship' - meta: - $ref: '#/components/schemas/_meta' - PostLikeResponse: - type: object - description: Response for a "PostLike" - required: - - data - properties: - jsonapi: - $ref: '#/components/schemas/_jsonapi' - data: - allOf: - - $ref: '#/components/schemas/PostLike' - - type: object - properties: - relationships: - type: object - properties: - post: - $ref: '#/components/schemas/_toOneRelationship' - user: - $ref: '#/components/schemas/_toOneRelationship' - meta: - $ref: '#/components/schemas/_meta' - included: - type: array - items: - $ref: '#/components/schemas/_resource' - links: - $ref: '#/components/schemas/_links' - PostLikeListResponse: - type: object - description: Response for a list of "PostLike" - required: - - data - - links - properties: - jsonapi: - $ref: '#/components/schemas/_jsonapi' - data: - type: array - items: - allOf: - - $ref: '#/components/schemas/PostLike' - - type: object - properties: - relationships: - type: object - properties: - post: - $ref: '#/components/schemas/_toOneRelationship' - user: - $ref: '#/components/schemas/_toOneRelationship' - meta: - $ref: '#/components/schemas/_meta' - included: - type: array - items: - $ref: '#/components/schemas/_resource' - links: - allOf: - - $ref: '#/components/schemas/_links' - - $ref: '#/components/schemas/_pagination' - parameters: - id: - name: id - in: path - description: The resource id - required: true - schema: - type: string - include: - name: include - in: query - description: Relationships to include - required: false - style: form - schema: - type: string - sort: - name: sort - in: query - description: Fields to sort by - required: false - style: form - schema: - type: string - page-offset: - name: page[offset] - in: query - description: Offset for pagination - required: false - style: form - schema: - type: integer - page-limit: - name: page[limit] - in: query - description: Limit for pagination - required: false - style: form - schema: - type: integer diff --git a/packages/server/test/openapi/migrated/baseline/rest-type-coverage-3.1.0.baseline.yaml b/packages/server/test/openapi/migrated/baseline/rest-type-coverage-3.1.0.baseline.yaml deleted file mode 100644 index 6d41ebdf6..000000000 --- a/packages/server/test/openapi/migrated/baseline/rest-type-coverage-3.1.0.baseline.yaml +++ /dev/null @@ -1,876 +0,0 @@ -openapi: 3.1.0 -info: - title: ZenStack Generated API - version: 1.0.0 -tags: - - name: foo - description: Foo operations -paths: - /foo: - get: - operationId: list-Foo - description: List "Foo" resources - tags: - - foo - parameters: - - $ref: '#/components/parameters/include' - - $ref: '#/components/parameters/sort' - - $ref: '#/components/parameters/page-offset' - - $ref: '#/components/parameters/page-limit' - - name: filter[id] - required: false - description: Id filter - in: query - style: form - explode: false - schema: - type: string - - name: filter[string] - required: false - description: Equality filter for "string" - in: query - style: form - explode: false - schema: - type: string - - name: filter[string$contains] - required: false - description: String contains filter for "string" - in: query - style: form - explode: false - schema: - type: string - - name: filter[string$icontains] - required: false - description: String case-insensitive contains filter for "string" - in: query - style: form - explode: false - schema: - type: string - - name: filter[string$search] - required: false - description: String full-text search filter for "string" - in: query - style: form - explode: false - schema: - type: string - - name: filter[string$startsWith] - required: false - description: String startsWith filter for "string" - in: query - style: form - explode: false - schema: - type: string - - name: filter[string$endsWith] - required: false - description: String endsWith filter for "string" - in: query - style: form - explode: false - schema: - type: string - - name: filter[int] - required: false - description: Equality filter for "int" - in: query - style: form - explode: false - schema: - type: integer - - name: filter[int$lt] - required: false - description: Less-than filter for "int" - in: query - style: form - explode: false - schema: - type: integer - - name: filter[int$lte] - required: false - description: Less-than or equal filter for "int" - in: query - style: form - explode: false - schema: - type: integer - - name: filter[int$gt] - required: false - description: Greater-than filter for "int" - in: query - style: form - explode: false - schema: - type: integer - - name: filter[int$gte] - required: false - description: Greater-than or equal filter for "int" - in: query - style: form - explode: false - schema: - type: integer - - name: filter[bigInt] - required: false - description: Equality filter for "bigInt" - in: query - style: form - explode: false - schema: - type: integer - - name: filter[bigInt$lt] - required: false - description: Less-than filter for "bigInt" - in: query - style: form - explode: false - schema: - type: integer - - name: filter[bigInt$lte] - required: false - description: Less-than or equal filter for "bigInt" - in: query - style: form - explode: false - schema: - type: integer - - name: filter[bigInt$gt] - required: false - description: Greater-than filter for "bigInt" - in: query - style: form - explode: false - schema: - type: integer - - name: filter[bigInt$gte] - required: false - description: Greater-than or equal filter for "bigInt" - in: query - style: form - explode: false - schema: - type: integer - - name: filter[date] - required: false - description: Equality filter for "date" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[date$lt] - required: false - description: Less-than filter for "date" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[date$lte] - required: false - description: Less-than or equal filter for "date" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[date$gt] - required: false - description: Greater-than filter for "date" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[date$gte] - required: false - description: Greater-than or equal filter for "date" - in: query - style: form - explode: false - schema: - type: string - format: date-time - - name: filter[float] - required: false - description: Equality filter for "float" - in: query - style: form - explode: false - schema: - type: number - - name: filter[float$lt] - required: false - description: Less-than filter for "float" - in: query - style: form - explode: false - schema: - type: number - - name: filter[float$lte] - required: false - description: Less-than or equal filter for "float" - in: query - style: form - explode: false - schema: - type: number - - name: filter[float$gt] - required: false - description: Greater-than filter for "float" - in: query - style: form - explode: false - schema: - type: number - - name: filter[float$gte] - required: false - description: Greater-than or equal filter for "float" - in: query - style: form - explode: false - schema: - type: number - - name: filter[decimal] - required: false - description: Equality filter for "decimal" - in: query - style: form - explode: false - schema: - oneOf: - - type: number - - type: string - - name: filter[decimal$lt] - required: false - description: Less-than filter for "decimal" - in: query - style: form - explode: false - schema: - oneOf: - - type: number - - type: string - - name: filter[decimal$lte] - required: false - description: Less-than or equal filter for "decimal" - in: query - style: form - explode: false - schema: - oneOf: - - type: number - - type: string - - name: filter[decimal$gt] - required: false - description: Greater-than filter for "decimal" - in: query - style: form - explode: false - schema: - oneOf: - - type: number - - type: string - - name: filter[decimal$gte] - required: false - description: Greater-than or equal filter for "decimal" - in: query - style: form - explode: false - schema: - oneOf: - - type: number - - type: string - - name: filter[boolean] - required: false - description: Equality filter for "boolean" - in: query - style: form - explode: false - schema: - type: boolean - - name: filter[bytes] - required: false - description: Equality filter for "bytes" - in: query - style: form - explode: false - schema: - type: string - format: byte - description: Base64 encoded byte array - - name: filter[json] - required: false - description: Equality filter for "json" - in: query - style: form - explode: false - schema: - type: string - format: json - - name: filter[plainJson] - required: false - description: Equality filter for "plainJson" - in: query - style: form - explode: false - schema: - type: string - format: json - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/FooListResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - security: [] - post: - operationId: create-Foo - description: Create a "Foo" resource - tags: - - foo - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/FooCreateRequest' - responses: - '201': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/FooResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '422': - description: Request is unprocessable due to validation errors - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - security: [] - /foo/{id}: - get: - operationId: fetch-Foo - description: Fetch a "Foo" resource - tags: - - foo - parameters: - - $ref: '#/components/parameters/id' - - $ref: '#/components/parameters/include' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/FooResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - security: [] - put: - operationId: update-Foo-put - description: Update a "Foo" resource - tags: - - foo - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/FooUpdateRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/FooResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '422': - description: Request is unprocessable due to validation errors - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - security: [] - patch: - operationId: update-Foo-patch - description: Update a "Foo" resource - tags: - - foo - parameters: - - $ref: '#/components/parameters/id' - requestBody: - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/FooUpdateRequest' - responses: - '200': - description: Successful operation - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/FooResponse' - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '422': - description: Request is unprocessable due to validation errors - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - security: [] - delete: - operationId: delete-Foo - description: Delete a "Foo" resource - tags: - - foo - parameters: - - $ref: '#/components/parameters/id' - responses: - '200': - description: Successful operation - '403': - description: Request is forbidden - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - '404': - description: Resource is not found - content: - application/vnd.api+json: - schema: - $ref: '#/components/schemas/_errorResponse' - security: [] -components: - schemas: - _jsonapi: - type: object - description: An object describing the server’s implementation - required: - - version - properties: - version: - type: string - _meta: - type: object - description: Meta information about the request or response - properties: - serialization: - description: Superjson serialization metadata - additionalProperties: true - _resourceIdentifier: - type: object - description: Identifier for a resource - required: - - type - - id - properties: - type: - type: string - description: Resource type - id: - type: string - description: Resource id - _resource: - allOf: - - $ref: '#/components/schemas/_resourceIdentifier' - - type: object - description: A resource with attributes and relationships - properties: - attributes: - type: object - description: Resource attributes - relationships: - type: object - description: Resource relationships - _links: - type: object - required: - - self - description: Links related to the resource - properties: - self: - type: string - description: Link for refetching the curent results - _pagination: - type: object - description: Pagination information - required: - - first - - last - - prev - - next - properties: - first: - oneOf: - - type: 'null' - - type: string - description: Link to the first page - last: - oneOf: - - type: 'null' - - type: string - description: Link to the last page - prev: - oneOf: - - type: 'null' - - type: string - description: Link to the previous page - next: - oneOf: - - type: 'null' - - type: string - description: Link to the next page - _errors: - type: array - description: An array of error objects - items: - type: object - required: - - status - - code - properties: - status: - type: string - description: HTTP status - code: - type: string - description: Error code - prismaCode: - type: string - description: Prisma error code if the error is thrown by Prisma - title: - type: string - description: Error title - detail: - type: string - description: Error detail - reason: - type: string - description: Detailed error reason - zodErrors: - type: object - additionalProperties: true - description: Zod validation errors if the error is due to data validation - failure - _errorResponse: - type: object - required: - - errors - description: An error response - properties: - jsonapi: - $ref: '#/components/schemas/_jsonapi' - errors: - $ref: '#/components/schemas/_errors' - Foo: - type: object - description: The "Foo" model - required: - - id - - type - - attributes - properties: - id: - type: string - type: - type: string - attributes: - type: object - required: - - string - - int - - bigInt - - date - - float - - decimal - - boolean - - bytes - - json - - plainJson - properties: - string: - type: string - int: - type: integer - bigInt: - type: integer - date: - type: string - format: date-time - float: - type: number - decimal: - oneOf: - - type: number - - type: string - boolean: - type: boolean - bytes: - type: string - format: byte - description: Base64 encoded byte array - json: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Meta' - plainJson: {} - FooCreateRequest: - type: object - description: Input for creating a "Foo" - required: - - data - properties: - data: - type: object - description: The "Foo" model - required: - - type - - attributes - properties: - type: - type: string - attributes: - type: object - required: - - string - - int - - bigInt - - date - - float - - decimal - - boolean - - bytes - - plainJson - properties: - string: - type: string - int: - type: integer - bigInt: - type: integer - date: - type: string - format: date-time - float: - type: number - decimal: - oneOf: - - type: number - - type: string - boolean: - type: boolean - bytes: - type: string - format: byte - description: Base64 encoded byte array - json: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Meta' - plainJson: {} - meta: - $ref: '#/components/schemas/_meta' - FooUpdateRequest: - type: object - description: Input for updating a "Foo" - required: - - data - properties: - data: - type: object - description: The "Foo" model - required: - - id - - type - - attributes - properties: - id: - type: string - type: - type: string - attributes: - type: object - properties: - string: - type: string - int: - type: integer - bigInt: - type: integer - date: - type: string - format: date-time - float: - type: number - decimal: - oneOf: - - type: number - - type: string - boolean: - type: boolean - bytes: - type: string - format: byte - description: Base64 encoded byte array - json: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Meta' - plainJson: {} - meta: - $ref: '#/components/schemas/_meta' - FooResponse: - type: object - description: Response for a "Foo" - required: - - data - properties: - jsonapi: - $ref: '#/components/schemas/_jsonapi' - data: - allOf: - - $ref: '#/components/schemas/Foo' - - type: object - properties: - relationships: - type: object - properties: &a1 {} - meta: - $ref: '#/components/schemas/_meta' - included: - type: array - items: - $ref: '#/components/schemas/_resource' - links: - $ref: '#/components/schemas/_links' - FooListResponse: - type: object - description: Response for a list of "Foo" - required: - - data - - links - properties: - jsonapi: - $ref: '#/components/schemas/_jsonapi' - data: - type: array - items: - allOf: - - $ref: '#/components/schemas/Foo' - - type: object - properties: - relationships: - type: object - properties: *a1 - meta: - $ref: '#/components/schemas/_meta' - included: - type: array - items: - $ref: '#/components/schemas/_resource' - links: - allOf: - - $ref: '#/components/schemas/_links' - - $ref: '#/components/schemas/_pagination' - Meta: - type: object - description: The "Meta" TypeDef - properties: - something: - type: string - parameters: - id: - name: id - in: path - description: The resource id - required: true - schema: - type: string - include: - name: include - in: query - description: Relationships to include - required: false - style: form - schema: - type: string - sort: - name: sort - in: query - description: Fields to sort by - required: false - style: form - schema: - type: string - page-offset: - name: page[offset] - in: query - description: Offset for pagination - required: false - style: form - schema: - type: integer - page-limit: - name: page[limit] - in: query - description: Limit for pagination - required: false - style: form - schema: - type: integer diff --git a/packages/server/test/openapi/migrated/baseline/rpc-3.1.0-omit.baseline.yaml b/packages/server/test/openapi/migrated/baseline/rpc-3.1.0-omit.baseline.yaml deleted file mode 100644 index 11369e7d0..000000000 --- a/packages/server/test/openapi/migrated/baseline/rpc-3.1.0-omit.baseline.yaml +++ /dev/null @@ -1,3058 +0,0 @@ -openapi: 3.1.0 -info: - title: ZenStack Generated API - version: 1.0.0 -tags: - - name: user - description: User operations - - name: profile - description: Profile operations - - name: post_Item - description: Post-related operations -components: - schemas: - _AnyObject: - type: object - additionalProperties: true - Role: - type: string - enum: - - USER - - ADMIN - User: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - email: - type: string - role: - $ref: '#/components/schemas/Role' - posts: - type: array - items: - $ref: '#/components/schemas/Post_Item' - profile: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Profile' - required: - - id - - createdAt - - updatedAt - - email - - role - Profile: - type: object - properties: - id: - type: string - image: - oneOf: - - type: 'null' - - type: string - user: - $ref: '#/components/schemas/User' - userId: - type: string - required: - - id - - user - - userId - Post_Item: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - title: - type: string - author: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/User' - authorId: - oneOf: - - type: 'null' - - type: string - published: - type: boolean - viewCount: - type: integer - notes: - oneOf: - - type: 'null' - - type: string - required: - - id - - createdAt - - updatedAt - - title - - published - - viewCount - AggregateUser: - type: object - properties: - _count: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/UserCountAggregateOutputType' - _min: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/UserMinAggregateOutputType' - _max: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/UserMaxAggregateOutputType' - UserGroupByOutputType: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - email: - type: string - role: - $ref: '#/components/schemas/Role' - _count: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/UserCountAggregateOutputType' - _min: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/UserMinAggregateOutputType' - _max: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/UserMaxAggregateOutputType' - required: - - id - - createdAt - - updatedAt - - email - - role - AggregateProfile: - type: object - properties: - _count: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/ProfileCountAggregateOutputType' - _min: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/ProfileMinAggregateOutputType' - _max: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/ProfileMaxAggregateOutputType' - ProfileGroupByOutputType: - type: object - properties: - id: - type: string - image: - oneOf: - - type: 'null' - - type: string - userId: - type: string - _count: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/ProfileCountAggregateOutputType' - _min: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/ProfileMinAggregateOutputType' - _max: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/ProfileMaxAggregateOutputType' - required: - - id - - userId - AggregatePost_Item: - type: object - properties: - _count: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Post_ItemCountAggregateOutputType' - _avg: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Post_ItemAvgAggregateOutputType' - _sum: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Post_ItemSumAggregateOutputType' - _min: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Post_ItemMinAggregateOutputType' - _max: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Post_ItemMaxAggregateOutputType' - Post_ItemGroupByOutputType: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - title: - type: string - authorId: - oneOf: - - type: 'null' - - type: string - published: - type: boolean - viewCount: - type: integer - notes: - oneOf: - - type: 'null' - - type: string - _count: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Post_ItemCountAggregateOutputType' - _avg: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Post_ItemAvgAggregateOutputType' - _sum: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Post_ItemSumAggregateOutputType' - _min: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Post_ItemMinAggregateOutputType' - _max: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Post_ItemMaxAggregateOutputType' - required: - - id - - createdAt - - updatedAt - - title - - published - - viewCount - UserCountAggregateOutputType: - type: object - properties: - id: - type: integer - createdAt: - type: integer - updatedAt: - type: integer - email: - type: integer - role: - type: integer - _all: - type: integer - required: - - id - - createdAt - - updatedAt - - email - - role - - _all - UserMinAggregateOutputType: - type: object - properties: - id: - oneOf: - - type: 'null' - - type: string - createdAt: - oneOf: - - type: 'null' - - type: string - format: date-time - updatedAt: - oneOf: - - type: 'null' - - type: string - format: date-time - email: - oneOf: - - type: 'null' - - type: string - role: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Role' - UserMaxAggregateOutputType: - type: object - properties: - id: - oneOf: - - type: 'null' - - type: string - createdAt: - oneOf: - - type: 'null' - - type: string - format: date-time - updatedAt: - oneOf: - - type: 'null' - - type: string - format: date-time - email: - oneOf: - - type: 'null' - - type: string - role: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Role' - ProfileCountAggregateOutputType: - type: object - properties: - id: - type: integer - image: - type: integer - userId: - type: integer - _all: - type: integer - required: - - id - - image - - userId - - _all - ProfileMinAggregateOutputType: - type: object - properties: - id: - oneOf: - - type: 'null' - - type: string - image: - oneOf: - - type: 'null' - - type: string - userId: - oneOf: - - type: 'null' - - type: string - ProfileMaxAggregateOutputType: - type: object - properties: - id: - oneOf: - - type: 'null' - - type: string - image: - oneOf: - - type: 'null' - - type: string - userId: - oneOf: - - type: 'null' - - type: string - Post_ItemCountAggregateOutputType: - type: object - properties: - id: - type: integer - createdAt: - type: integer - updatedAt: - type: integer - title: - type: integer - authorId: - type: integer - published: - type: integer - viewCount: - type: integer - notes: - type: integer - _all: - type: integer - required: - - id - - createdAt - - updatedAt - - title - - authorId - - published - - viewCount - - notes - - _all - Post_ItemAvgAggregateOutputType: - type: object - properties: - viewCount: - oneOf: - - type: 'null' - - type: number - Post_ItemSumAggregateOutputType: - type: object - properties: - viewCount: - oneOf: - - type: 'null' - - type: integer - Post_ItemMinAggregateOutputType: - type: object - properties: - id: - oneOf: - - type: 'null' - - type: string - createdAt: - oneOf: - - type: 'null' - - type: string - format: date-time - updatedAt: - oneOf: - - type: 'null' - - type: string - format: date-time - title: - oneOf: - - type: 'null' - - type: string - authorId: - oneOf: - - type: 'null' - - type: string - published: - oneOf: - - type: 'null' - - type: boolean - viewCount: - oneOf: - - type: 'null' - - type: integer - notes: - oneOf: - - type: 'null' - - type: string - Post_ItemMaxAggregateOutputType: - type: object - properties: - id: - oneOf: - - type: 'null' - - type: string - createdAt: - oneOf: - - type: 'null' - - type: string - format: date-time - updatedAt: - oneOf: - - type: 'null' - - type: string - format: date-time - title: - oneOf: - - type: 'null' - - type: string - authorId: - oneOf: - - type: 'null' - - type: string - published: - oneOf: - - type: 'null' - - type: boolean - viewCount: - oneOf: - - type: 'null' - - type: integer - notes: - oneOf: - - type: 'null' - - type: string - _Meta: - type: object - description: Meta information about the request or response - properties: - serialization: - description: Serialization metadata - additionalProperties: true - _Error: - type: object - required: - - error - properties: - error: - type: object - required: - - message - properties: - prisma: - type: boolean - description: Indicates if the error occurred during a Prisma call - rejectedByPolicy: - type: boolean - description: Indicates if the error was due to rejection by a policy - code: - type: string - description: Prisma error code. Only available when "prisma" field is true. - message: - type: string - description: Error message - reason: - type: string - description: Detailed error reason - zodErrors: - type: object - additionalProperties: true - description: Zod validation errors if the error is due to data validation - failure - additionalProperties: true - BatchPayload: - type: object - properties: - count: - type: integer - UserCreateArgs: - type: object - required: - - data - properties: - select: - $ref: '#/components/schemas/_AnyObject' - include: - $ref: '#/components/schemas/_AnyObject' - data: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - UserCreateManyArgs: - type: object - required: - - data - properties: - data: - oneOf: - - $ref: '#/components/schemas/_AnyObject' - - type: array - items: - $ref: '#/components/schemas/_AnyObject' - skipDuplicates: - type: boolean - description: Do not insert records with unique fields or ID fields that already - exist. - meta: - $ref: '#/components/schemas/_Meta' - UserFindUniqueArgs: - type: object - required: - - where - properties: - select: - $ref: '#/components/schemas/_AnyObject' - include: - $ref: '#/components/schemas/_AnyObject' - where: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - UserFindFirstArgs: - type: object - properties: - select: - $ref: '#/components/schemas/_AnyObject' - include: - $ref: '#/components/schemas/_AnyObject' - where: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - UserFindManyArgs: - type: object - properties: - select: - $ref: '#/components/schemas/_AnyObject' - include: - $ref: '#/components/schemas/_AnyObject' - where: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - orderBy: - oneOf: - - $ref: '#/components/schemas/_AnyObject' - - type: array - items: - $ref: '#/components/schemas/_AnyObject' - cursor: - $ref: '#/components/schemas/_AnyObject' - take: - type: integer - skip: - type: integer - UserUpdateArgs: - type: object - required: - - where - - data - properties: - select: - $ref: '#/components/schemas/_AnyObject' - include: - $ref: '#/components/schemas/_AnyObject' - where: - $ref: '#/components/schemas/_AnyObject' - data: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - UserUpdateManyArgs: - type: object - required: - - data - properties: - where: - $ref: '#/components/schemas/_AnyObject' - data: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - UserUpsertArgs: - type: object - required: - - create - - update - - where - properties: - select: - $ref: '#/components/schemas/_AnyObject' - include: - $ref: '#/components/schemas/_AnyObject' - where: - $ref: '#/components/schemas/_AnyObject' - create: - $ref: '#/components/schemas/_AnyObject' - update: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - UserDeleteUniqueArgs: - type: object - required: - - where - properties: - select: - $ref: '#/components/schemas/_AnyObject' - include: - $ref: '#/components/schemas/_AnyObject' - where: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - UserDeleteManyArgs: - type: object - properties: - where: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - UserCountArgs: - type: object - properties: - select: - $ref: '#/components/schemas/_AnyObject' - where: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - UserAggregateArgs: - type: object - properties: - where: - $ref: '#/components/schemas/_AnyObject' - orderBy: - $ref: '#/components/schemas/_AnyObject' - cursor: - $ref: '#/components/schemas/_AnyObject' - take: - type: integer - skip: - type: integer - _count: - oneOf: - - type: boolean - - $ref: '#/components/schemas/_AnyObject' - _min: - $ref: '#/components/schemas/_AnyObject' - _max: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - UserGroupByArgs: - type: object - properties: - where: - $ref: '#/components/schemas/_AnyObject' - orderBy: - $ref: '#/components/schemas/_AnyObject' - by: - $ref: '#/components/schemas/_AnyObject' - having: - $ref: '#/components/schemas/_AnyObject' - take: - type: integer - skip: - type: integer - _count: - oneOf: - - type: boolean - - $ref: '#/components/schemas/_AnyObject' - _min: - $ref: '#/components/schemas/_AnyObject' - _max: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - ProfileCreateArgs: - type: object - required: - - data - properties: - select: - $ref: '#/components/schemas/_AnyObject' - include: - $ref: '#/components/schemas/_AnyObject' - data: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - ProfileCreateManyArgs: - type: object - required: - - data - properties: - data: - oneOf: - - $ref: '#/components/schemas/_AnyObject' - - type: array - items: - $ref: '#/components/schemas/_AnyObject' - skipDuplicates: - type: boolean - description: Do not insert records with unique fields or ID fields that already - exist. - meta: - $ref: '#/components/schemas/_Meta' - ProfileFindUniqueArgs: - type: object - required: - - where - properties: - select: - $ref: '#/components/schemas/_AnyObject' - include: - $ref: '#/components/schemas/_AnyObject' - where: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - ProfileFindFirstArgs: - type: object - properties: - select: - $ref: '#/components/schemas/_AnyObject' - include: - $ref: '#/components/schemas/_AnyObject' - where: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - ProfileFindManyArgs: - type: object - properties: - select: - $ref: '#/components/schemas/_AnyObject' - include: - $ref: '#/components/schemas/_AnyObject' - where: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - orderBy: - oneOf: - - $ref: '#/components/schemas/_AnyObject' - - type: array - items: - $ref: '#/components/schemas/_AnyObject' - cursor: - $ref: '#/components/schemas/_AnyObject' - take: - type: integer - skip: - type: integer - ProfileUpdateArgs: - type: object - required: - - where - - data - properties: - select: - $ref: '#/components/schemas/_AnyObject' - include: - $ref: '#/components/schemas/_AnyObject' - where: - $ref: '#/components/schemas/_AnyObject' - data: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - ProfileUpdateManyArgs: - type: object - required: - - data - properties: - where: - $ref: '#/components/schemas/_AnyObject' - data: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - ProfileUpsertArgs: - type: object - required: - - create - - update - - where - properties: - select: - $ref: '#/components/schemas/_AnyObject' - include: - $ref: '#/components/schemas/_AnyObject' - where: - $ref: '#/components/schemas/_AnyObject' - create: - $ref: '#/components/schemas/_AnyObject' - update: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - ProfileDeleteUniqueArgs: - type: object - required: - - where - properties: - select: - $ref: '#/components/schemas/_AnyObject' - include: - $ref: '#/components/schemas/_AnyObject' - where: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - ProfileDeleteManyArgs: - type: object - properties: - where: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - ProfileCountArgs: - type: object - properties: - select: - $ref: '#/components/schemas/_AnyObject' - where: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - ProfileAggregateArgs: - type: object - properties: - where: - $ref: '#/components/schemas/_AnyObject' - orderBy: - $ref: '#/components/schemas/_AnyObject' - cursor: - $ref: '#/components/schemas/_AnyObject' - take: - type: integer - skip: - type: integer - _count: - oneOf: - - type: boolean - - $ref: '#/components/schemas/_AnyObject' - _min: - $ref: '#/components/schemas/_AnyObject' - _max: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - ProfileGroupByArgs: - type: object - properties: - where: - $ref: '#/components/schemas/_AnyObject' - orderBy: - $ref: '#/components/schemas/_AnyObject' - by: - $ref: '#/components/schemas/_AnyObject' - having: - $ref: '#/components/schemas/_AnyObject' - take: - type: integer - skip: - type: integer - _count: - oneOf: - - type: boolean - - $ref: '#/components/schemas/_AnyObject' - _min: - $ref: '#/components/schemas/_AnyObject' - _max: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemCreateArgs: - type: object - required: - - data - properties: - select: - $ref: '#/components/schemas/_AnyObject' - include: - $ref: '#/components/schemas/_AnyObject' - data: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemCreateManyArgs: - type: object - required: - - data - properties: - data: - oneOf: - - $ref: '#/components/schemas/_AnyObject' - - type: array - items: - $ref: '#/components/schemas/_AnyObject' - skipDuplicates: - type: boolean - description: Do not insert records with unique fields or ID fields that already - exist. - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemFindUniqueArgs: - type: object - required: - - where - properties: - select: - $ref: '#/components/schemas/_AnyObject' - include: - $ref: '#/components/schemas/_AnyObject' - where: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemFindFirstArgs: - type: object - properties: - select: - $ref: '#/components/schemas/_AnyObject' - include: - $ref: '#/components/schemas/_AnyObject' - where: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemUpdateArgs: - type: object - required: - - where - - data - properties: - select: - $ref: '#/components/schemas/_AnyObject' - include: - $ref: '#/components/schemas/_AnyObject' - where: - $ref: '#/components/schemas/_AnyObject' - data: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemUpdateManyArgs: - type: object - required: - - data - properties: - where: - $ref: '#/components/schemas/_AnyObject' - data: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemUpsertArgs: - type: object - required: - - create - - update - - where - properties: - select: - $ref: '#/components/schemas/_AnyObject' - include: - $ref: '#/components/schemas/_AnyObject' - where: - $ref: '#/components/schemas/_AnyObject' - create: - $ref: '#/components/schemas/_AnyObject' - update: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemDeleteUniqueArgs: - type: object - required: - - where - properties: - select: - $ref: '#/components/schemas/_AnyObject' - include: - $ref: '#/components/schemas/_AnyObject' - where: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemDeleteManyArgs: - type: object - properties: - where: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemCountArgs: - type: object - properties: - select: - $ref: '#/components/schemas/_AnyObject' - where: - $ref: '#/components/schemas/_AnyObject' - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemAggregateArgs: - type: object - properties: - where: - $ref: '#/components/schemas/_AnyObject' - orderBy: - $ref: '#/components/schemas/_AnyObject' - cursor: - $ref: '#/components/schemas/_AnyObject' - take: - type: integer - skip: - type: integer - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemGroupByArgs: - type: object - properties: - where: - $ref: '#/components/schemas/_AnyObject' - orderBy: - $ref: '#/components/schemas/_AnyObject' - by: - $ref: '#/components/schemas/_AnyObject' - having: - $ref: '#/components/schemas/_AnyObject' - take: - type: integer - skip: - type: integer - meta: - $ref: '#/components/schemas/_Meta' -paths: - /user/create: - post: - operationId: createUser - description: Create a new User - tags: - - user - responses: - '201': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/User' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/UserCreateArgs' - /user/createMany: - post: - operationId: createManyUser - description: Create several User - tags: - - user - responses: - '201': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BatchPayload' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/UserCreateManyArgs' - /user/findUnique: - get: - operationId: findUniqueUser - description: Find one unique User - tags: - - user - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/User' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/UserFindUniqueArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /user/findFirst: - get: - operationId: findFirstUser - description: Find the first User matching the given condition - tags: - - user - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/User' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/UserFindFirstArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /user/findMany: - get: - operationId: findManyUser - description: Find users matching the given conditions - tags: - - user - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - type: array - items: - $ref: '#/components/schemas/User' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/UserFindManyArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /user/update: - patch: - operationId: updateUser - description: Update a User - tags: - - user - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/User' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/UserUpdateArgs' - /user/updateMany: - patch: - operationId: updateManyUser - description: Update Users matching the given condition - tags: - - user - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BatchPayload' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/UserUpdateManyArgs' - /user/upsert: - post: - operationId: upsertUser - description: Upsert a User - tags: - - user - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/User' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/UserUpsertArgs' - /user/dodelete: - put: - operationId: deleteUser - description: Delete a unique user - tags: - - delete - - user - summary: Delete a user yeah yeah - deprecated: true - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/User' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/UserDeleteUniqueArgs' - /user/deleteMany: - delete: - operationId: deleteManyUser - description: Delete Users matching the given condition - tags: - - user - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BatchPayload' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/UserDeleteManyArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /user/count: - get: - operationId: countUser - description: Find a list of User - tags: - - user - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - oneOf: - - type: integer - - $ref: '#/components/schemas/UserCountAggregateOutputType' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/UserCountArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /user/aggregate: - get: - operationId: aggregateUser - description: Aggregate Users - tags: - - user - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/AggregateUser' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/UserAggregateArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /user/groupBy: - get: - operationId: groupByUser - description: Group Users by fields - tags: - - user - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - type: array - items: - $ref: '#/components/schemas/UserGroupByOutputType' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/UserGroupByArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /profile/create: - post: - operationId: createProfile - description: Create a new Profile - tags: - - profile - responses: - '201': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Profile' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileCreateArgs' - /profile/createMany: - post: - operationId: createManyProfile - description: Create several Profile - tags: - - profile - responses: - '201': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BatchPayload' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileCreateManyArgs' - /profile/findUnique: - get: - operationId: findUniqueProfile - description: Find one unique Profile - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Profile' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileFindUniqueArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /profile/findFirst: - get: - operationId: findFirstProfile - description: Find the first Profile matching the given condition - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Profile' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileFindFirstArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /profile/findMany: - get: - operationId: findManyProfile - description: Find a list of Profile - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - type: array - items: - $ref: '#/components/schemas/Profile' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileFindManyArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /profile/update: - patch: - operationId: updateProfile - description: Update a Profile - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Profile' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileUpdateArgs' - /profile/updateMany: - patch: - operationId: updateManyProfile - description: Update Profiles matching the given condition - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BatchPayload' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileUpdateManyArgs' - /profile/upsert: - post: - operationId: upsertProfile - description: Upsert a Profile - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Profile' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileUpsertArgs' - /profile/delete: - delete: - operationId: deleteProfile - description: Delete one unique Profile - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Profile' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileDeleteUniqueArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /profile/deleteMany: - delete: - operationId: deleteManyProfile - description: Delete Profiles matching the given condition - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BatchPayload' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileDeleteManyArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /profile/count: - get: - operationId: countProfile - description: Find a list of Profile - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - oneOf: - - type: integer - - $ref: '#/components/schemas/ProfileCountAggregateOutputType' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileCountArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /profile/aggregate: - get: - operationId: aggregateProfile - description: Aggregate Profiles - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/AggregateProfile' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileAggregateArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /profile/groupBy: - get: - operationId: groupByProfile - description: Group Profiles by fields - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - type: array - items: - $ref: '#/components/schemas/ProfileGroupByOutputType' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileGroupByArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /post_Item/create: - post: - operationId: createPost_Item - description: Create a new Post_Item - tags: - - post_Item - responses: - '201': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Post_Item' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemCreateArgs' - /post_Item/createMany: - post: - operationId: createManyPost_Item - description: Create several Post_Item - tags: - - post_Item - responses: - '201': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BatchPayload' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemCreateManyArgs' - /post_Item/findUnique: - get: - operationId: findUniquePost_Item - description: Find one unique Post_Item - tags: - - post_Item - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Post_Item' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemFindUniqueArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /post_Item/findFirst: - get: - operationId: findFirstPost_Item - description: Find the first Post_Item matching the given condition - tags: - - post_Item - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Post_Item' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemFindFirstArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /post_Item/update: - patch: - operationId: updatePost_Item - description: Update a Post_Item - tags: - - post_Item - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Post_Item' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemUpdateArgs' - /post_Item/updateMany: - patch: - operationId: updateManyPost_Item - description: Update Post_Items matching the given condition - tags: - - post_Item - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BatchPayload' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemUpdateManyArgs' - /post_Item/upsert: - post: - operationId: upsertPost_Item - description: Upsert a Post_Item - tags: - - post_Item - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Post_Item' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemUpsertArgs' - /post_Item/delete: - delete: - operationId: deletePost_Item - description: Delete one unique Post_Item - tags: - - post_Item - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Post_Item' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemDeleteUniqueArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /post_Item/deleteMany: - delete: - operationId: deleteManyPost_Item - description: Delete Post_Items matching the given condition - tags: - - post_Item - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BatchPayload' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemDeleteManyArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /post_Item/count: - get: - operationId: countPost_Item - description: Find a list of Post_Item - tags: - - post_Item - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - oneOf: - - type: integer - - $ref: '#/components/schemas/Post_ItemCountAggregateOutputType' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemCountArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /post_Item/aggregate: - get: - operationId: aggregatePost_Item - description: Aggregate Post_Items - tags: - - post_Item - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/AggregatePost_Item' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemAggregateArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /post_Item/groupBy: - get: - operationId: groupByPost_Item - description: Group Post_Items by fields - tags: - - post_Item - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - type: array - items: - $ref: '#/components/schemas/Post_ItemGroupByOutputType' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemGroupByArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} diff --git a/packages/server/test/openapi/migrated/baseline/rpc-3.1.0.baseline.yaml b/packages/server/test/openapi/migrated/baseline/rpc-3.1.0.baseline.yaml deleted file mode 100644 index 5c5103e09..000000000 --- a/packages/server/test/openapi/migrated/baseline/rpc-3.1.0.baseline.yaml +++ /dev/null @@ -1,5853 +0,0 @@ -openapi: 3.1.0 -info: - title: ZenStack Generated API - version: 1.0.0 -tags: - - name: user - description: User operations - - name: profile - description: Profile operations - - name: post_Item - description: Post-related operations -components: - schemas: - Role: - type: string - enum: - - USER - - ADMIN - UserScalarFieldEnum: - type: string - enum: - - id - - createdAt - - updatedAt - - email - - role - ProfileScalarFieldEnum: - type: string - enum: - - id - - image - - userId - Post_ItemScalarFieldEnum: - type: string - enum: - - id - - createdAt - - updatedAt - - title - - authorId - - published - - viewCount - - notes - SortOrder: - type: string - enum: - - asc - - desc - QueryMode: - type: string - enum: - - default - - insensitive - NullsOrder: - type: string - enum: - - first - - last - User: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - email: - type: string - role: - $ref: '#/components/schemas/Role' - posts: - type: array - items: - $ref: '#/components/schemas/Post_Item' - profile: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Profile' - required: - - id - - createdAt - - updatedAt - - email - - role - Profile: - type: object - properties: - id: - type: string - image: - oneOf: - - type: 'null' - - type: string - user: - $ref: '#/components/schemas/User' - userId: - type: string - required: - - id - - user - - userId - Post_Item: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - title: - type: string - author: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/User' - authorId: - oneOf: - - type: 'null' - - type: string - published: - type: boolean - viewCount: - type: integer - notes: - oneOf: - - type: 'null' - - type: string - required: - - id - - createdAt - - updatedAt - - title - - published - - viewCount - UserWhereInput: - type: object - properties: - AND: - oneOf: - - $ref: '#/components/schemas/UserWhereInput' - - type: array - items: - $ref: '#/components/schemas/UserWhereInput' - OR: - type: array - items: - $ref: '#/components/schemas/UserWhereInput' - NOT: - oneOf: - - $ref: '#/components/schemas/UserWhereInput' - - type: array - items: - $ref: '#/components/schemas/UserWhereInput' - id: - oneOf: - - $ref: '#/components/schemas/StringFilter' - - type: string - createdAt: - oneOf: - - $ref: '#/components/schemas/DateTimeFilter' - - type: string - format: date-time - updatedAt: - oneOf: - - $ref: '#/components/schemas/DateTimeFilter' - - type: string - format: date-time - email: - oneOf: - - $ref: '#/components/schemas/StringFilter' - - type: string - role: - oneOf: - - $ref: '#/components/schemas/EnumroleFilter' - - $ref: '#/components/schemas/Role' - posts: - $ref: '#/components/schemas/Post_ItemListRelationFilter' - profile: - oneOf: - - $ref: '#/components/schemas/ProfileNullableScalarRelationFilter' - - $ref: '#/components/schemas/ProfileWhereInput' - - type: 'null' - UserOrderByWithRelationInput: - type: object - properties: - id: - $ref: '#/components/schemas/SortOrder' - createdAt: - $ref: '#/components/schemas/SortOrder' - updatedAt: - $ref: '#/components/schemas/SortOrder' - email: - $ref: '#/components/schemas/SortOrder' - role: - $ref: '#/components/schemas/SortOrder' - posts: - $ref: '#/components/schemas/Post_ItemOrderByRelationAggregateInput' - profile: - $ref: '#/components/schemas/ProfileOrderByWithRelationInput' - UserWhereUniqueInput: - type: object - properties: - id: - type: string - email: - type: string - AND: - oneOf: - - $ref: '#/components/schemas/UserWhereInput' - - type: array - items: - $ref: '#/components/schemas/UserWhereInput' - OR: - type: array - items: - $ref: '#/components/schemas/UserWhereInput' - NOT: - oneOf: - - $ref: '#/components/schemas/UserWhereInput' - - type: array - items: - $ref: '#/components/schemas/UserWhereInput' - createdAt: - oneOf: - - $ref: '#/components/schemas/DateTimeFilter' - - type: string - format: date-time - updatedAt: - oneOf: - - $ref: '#/components/schemas/DateTimeFilter' - - type: string - format: date-time - role: - oneOf: - - $ref: '#/components/schemas/EnumroleFilter' - - $ref: '#/components/schemas/Role' - posts: - $ref: '#/components/schemas/Post_ItemListRelationFilter' - profile: - oneOf: - - $ref: '#/components/schemas/ProfileNullableScalarRelationFilter' - - $ref: '#/components/schemas/ProfileWhereInput' - - type: 'null' - UserScalarWhereWithAggregatesInput: - type: object - properties: - AND: - oneOf: - - $ref: '#/components/schemas/UserScalarWhereWithAggregatesInput' - - type: array - items: - $ref: '#/components/schemas/UserScalarWhereWithAggregatesInput' - OR: - type: array - items: - $ref: '#/components/schemas/UserScalarWhereWithAggregatesInput' - NOT: - oneOf: - - $ref: '#/components/schemas/UserScalarWhereWithAggregatesInput' - - type: array - items: - $ref: '#/components/schemas/UserScalarWhereWithAggregatesInput' - id: - oneOf: - - $ref: '#/components/schemas/StringWithAggregatesFilter' - - type: string - createdAt: - oneOf: - - $ref: '#/components/schemas/DateTimeWithAggregatesFilter' - - type: string - format: date-time - updatedAt: - oneOf: - - $ref: '#/components/schemas/DateTimeWithAggregatesFilter' - - type: string - format: date-time - email: - oneOf: - - $ref: '#/components/schemas/StringWithAggregatesFilter' - - type: string - role: - oneOf: - - $ref: '#/components/schemas/EnumroleWithAggregatesFilter' - - $ref: '#/components/schemas/Role' - ProfileWhereInput: - type: object - properties: - AND: - oneOf: - - $ref: '#/components/schemas/ProfileWhereInput' - - type: array - items: - $ref: '#/components/schemas/ProfileWhereInput' - OR: - type: array - items: - $ref: '#/components/schemas/ProfileWhereInput' - NOT: - oneOf: - - $ref: '#/components/schemas/ProfileWhereInput' - - type: array - items: - $ref: '#/components/schemas/ProfileWhereInput' - id: - oneOf: - - $ref: '#/components/schemas/StringFilter' - - type: string - image: - oneOf: - - $ref: '#/components/schemas/StringNullableFilter' - - type: string - - type: 'null' - userId: - oneOf: - - $ref: '#/components/schemas/StringFilter' - - type: string - user: - oneOf: - - $ref: '#/components/schemas/UserScalarRelationFilter' - - $ref: '#/components/schemas/UserWhereInput' - ProfileOrderByWithRelationInput: - type: object - properties: - id: - $ref: '#/components/schemas/SortOrder' - image: - oneOf: - - $ref: '#/components/schemas/SortOrder' - - $ref: '#/components/schemas/SortOrderInput' - userId: - $ref: '#/components/schemas/SortOrder' - user: - $ref: '#/components/schemas/UserOrderByWithRelationInput' - ProfileWhereUniqueInput: - type: object - properties: - id: - type: string - userId: - type: string - AND: - oneOf: - - $ref: '#/components/schemas/ProfileWhereInput' - - type: array - items: - $ref: '#/components/schemas/ProfileWhereInput' - OR: - type: array - items: - $ref: '#/components/schemas/ProfileWhereInput' - NOT: - oneOf: - - $ref: '#/components/schemas/ProfileWhereInput' - - type: array - items: - $ref: '#/components/schemas/ProfileWhereInput' - image: - oneOf: - - $ref: '#/components/schemas/StringNullableFilter' - - type: string - - type: 'null' - user: - oneOf: - - $ref: '#/components/schemas/UserScalarRelationFilter' - - $ref: '#/components/schemas/UserWhereInput' - ProfileScalarWhereWithAggregatesInput: - type: object - properties: - AND: - oneOf: - - $ref: '#/components/schemas/ProfileScalarWhereWithAggregatesInput' - - type: array - items: - $ref: '#/components/schemas/ProfileScalarWhereWithAggregatesInput' - OR: - type: array - items: - $ref: '#/components/schemas/ProfileScalarWhereWithAggregatesInput' - NOT: - oneOf: - - $ref: '#/components/schemas/ProfileScalarWhereWithAggregatesInput' - - type: array - items: - $ref: '#/components/schemas/ProfileScalarWhereWithAggregatesInput' - id: - oneOf: - - $ref: '#/components/schemas/StringWithAggregatesFilter' - - type: string - image: - oneOf: - - $ref: '#/components/schemas/StringNullableWithAggregatesFilter' - - type: string - - type: 'null' - userId: - oneOf: - - $ref: '#/components/schemas/StringWithAggregatesFilter' - - type: string - Post_ItemWhereInput: - type: object - properties: - AND: - oneOf: - - $ref: '#/components/schemas/Post_ItemWhereInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemWhereInput' - OR: - type: array - items: - $ref: '#/components/schemas/Post_ItemWhereInput' - NOT: - oneOf: - - $ref: '#/components/schemas/Post_ItemWhereInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemWhereInput' - id: - oneOf: - - $ref: '#/components/schemas/StringFilter' - - type: string - createdAt: - oneOf: - - $ref: '#/components/schemas/DateTimeFilter' - - type: string - format: date-time - updatedAt: - oneOf: - - $ref: '#/components/schemas/DateTimeFilter' - - type: string - format: date-time - title: - oneOf: - - $ref: '#/components/schemas/StringFilter' - - type: string - authorId: - oneOf: - - $ref: '#/components/schemas/StringNullableFilter' - - type: string - - type: 'null' - published: - oneOf: - - $ref: '#/components/schemas/BoolFilter' - - type: boolean - viewCount: - oneOf: - - $ref: '#/components/schemas/IntFilter' - - type: integer - notes: - oneOf: - - $ref: '#/components/schemas/StringNullableFilter' - - type: string - - type: 'null' - author: - oneOf: - - $ref: '#/components/schemas/UserNullableScalarRelationFilter' - - $ref: '#/components/schemas/UserWhereInput' - - type: 'null' - Post_ItemOrderByWithRelationInput: - type: object - properties: - id: - $ref: '#/components/schemas/SortOrder' - createdAt: - $ref: '#/components/schemas/SortOrder' - updatedAt: - $ref: '#/components/schemas/SortOrder' - title: - $ref: '#/components/schemas/SortOrder' - authorId: - oneOf: - - $ref: '#/components/schemas/SortOrder' - - $ref: '#/components/schemas/SortOrderInput' - published: - $ref: '#/components/schemas/SortOrder' - viewCount: - $ref: '#/components/schemas/SortOrder' - notes: - oneOf: - - $ref: '#/components/schemas/SortOrder' - - $ref: '#/components/schemas/SortOrderInput' - author: - $ref: '#/components/schemas/UserOrderByWithRelationInput' - Post_ItemWhereUniqueInput: - type: object - properties: - id: - type: string - AND: - oneOf: - - $ref: '#/components/schemas/Post_ItemWhereInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemWhereInput' - OR: - type: array - items: - $ref: '#/components/schemas/Post_ItemWhereInput' - NOT: - oneOf: - - $ref: '#/components/schemas/Post_ItemWhereInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemWhereInput' - createdAt: - oneOf: - - $ref: '#/components/schemas/DateTimeFilter' - - type: string - format: date-time - updatedAt: - oneOf: - - $ref: '#/components/schemas/DateTimeFilter' - - type: string - format: date-time - title: - oneOf: - - $ref: '#/components/schemas/StringFilter' - - type: string - authorId: - oneOf: - - $ref: '#/components/schemas/StringNullableFilter' - - type: string - - type: 'null' - published: - oneOf: - - $ref: '#/components/schemas/BoolFilter' - - type: boolean - viewCount: - oneOf: - - $ref: '#/components/schemas/IntFilter' - - type: integer - notes: - oneOf: - - $ref: '#/components/schemas/StringNullableFilter' - - type: string - - type: 'null' - author: - oneOf: - - $ref: '#/components/schemas/UserNullableScalarRelationFilter' - - $ref: '#/components/schemas/UserWhereInput' - - type: 'null' - Post_ItemScalarWhereWithAggregatesInput: - type: object - properties: - AND: - oneOf: - - $ref: '#/components/schemas/Post_ItemScalarWhereWithAggregatesInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemScalarWhereWithAggregatesInput' - OR: - type: array - items: - $ref: '#/components/schemas/Post_ItemScalarWhereWithAggregatesInput' - NOT: - oneOf: - - $ref: '#/components/schemas/Post_ItemScalarWhereWithAggregatesInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemScalarWhereWithAggregatesInput' - id: - oneOf: - - $ref: '#/components/schemas/StringWithAggregatesFilter' - - type: string - createdAt: - oneOf: - - $ref: '#/components/schemas/DateTimeWithAggregatesFilter' - - type: string - format: date-time - updatedAt: - oneOf: - - $ref: '#/components/schemas/DateTimeWithAggregatesFilter' - - type: string - format: date-time - title: - oneOf: - - $ref: '#/components/schemas/StringWithAggregatesFilter' - - type: string - authorId: - oneOf: - - $ref: '#/components/schemas/StringNullableWithAggregatesFilter' - - type: string - - type: 'null' - published: - oneOf: - - $ref: '#/components/schemas/BoolWithAggregatesFilter' - - type: boolean - viewCount: - oneOf: - - $ref: '#/components/schemas/IntWithAggregatesFilter' - - type: integer - notes: - oneOf: - - $ref: '#/components/schemas/StringNullableWithAggregatesFilter' - - type: string - - type: 'null' - UserCreateInput: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - email: - type: string - role: - $ref: '#/components/schemas/Role' - posts: - $ref: '#/components/schemas/Post_ItemCreateNestedManyWithoutAuthorInput' - profile: - $ref: '#/components/schemas/ProfileCreateNestedOneWithoutUserInput' - required: - - email - UserUpdateInput: - type: object - properties: - id: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - createdAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - updatedAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - email: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - role: - oneOf: - - $ref: '#/components/schemas/Role' - - $ref: '#/components/schemas/EnumroleFieldUpdateOperationsInput' - posts: - $ref: '#/components/schemas/Post_ItemUpdateManyWithoutAuthorNestedInput' - profile: - $ref: '#/components/schemas/ProfileUpdateOneWithoutUserNestedInput' - UserCreateManyInput: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - email: - type: string - role: - $ref: '#/components/schemas/Role' - required: - - email - UserUpdateManyMutationInput: - type: object - properties: - id: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - createdAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - updatedAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - email: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - role: - oneOf: - - $ref: '#/components/schemas/Role' - - $ref: '#/components/schemas/EnumroleFieldUpdateOperationsInput' - ProfileCreateInput: - type: object - properties: - id: - type: string - image: - oneOf: - - type: 'null' - - type: string - user: - $ref: '#/components/schemas/UserCreateNestedOneWithoutProfileInput' - required: - - user - ProfileUpdateInput: - type: object - properties: - id: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - image: - oneOf: - - type: string - - $ref: '#/components/schemas/NullableStringFieldUpdateOperationsInput' - - type: 'null' - user: - $ref: '#/components/schemas/UserUpdateOneRequiredWithoutProfileNestedInput' - ProfileCreateManyInput: - type: object - properties: - id: - type: string - image: - oneOf: - - type: 'null' - - type: string - userId: - type: string - required: - - userId - ProfileUpdateManyMutationInput: - type: object - properties: - id: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - image: - oneOf: - - type: string - - $ref: '#/components/schemas/NullableStringFieldUpdateOperationsInput' - - type: 'null' - Post_ItemCreateInput: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - title: - type: string - published: - type: boolean - viewCount: - type: integer - notes: - oneOf: - - type: 'null' - - type: string - author: - $ref: '#/components/schemas/UserCreateNestedOneWithoutPostsInput' - required: - - id - - title - Post_ItemUpdateInput: - type: object - properties: - id: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - createdAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - updatedAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - title: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - published: - oneOf: - - type: boolean - - $ref: '#/components/schemas/BoolFieldUpdateOperationsInput' - viewCount: - oneOf: - - type: integer - - $ref: '#/components/schemas/IntFieldUpdateOperationsInput' - notes: - oneOf: - - type: string - - $ref: '#/components/schemas/NullableStringFieldUpdateOperationsInput' - - type: 'null' - author: - $ref: '#/components/schemas/UserUpdateOneWithoutPostsNestedInput' - Post_ItemCreateManyInput: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - title: - type: string - authorId: - oneOf: - - type: 'null' - - type: string - published: - type: boolean - viewCount: - type: integer - notes: - oneOf: - - type: 'null' - - type: string - required: - - id - - title - Post_ItemUpdateManyMutationInput: - type: object - properties: - id: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - createdAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - updatedAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - title: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - published: - oneOf: - - type: boolean - - $ref: '#/components/schemas/BoolFieldUpdateOperationsInput' - viewCount: - oneOf: - - type: integer - - $ref: '#/components/schemas/IntFieldUpdateOperationsInput' - notes: - oneOf: - - type: string - - $ref: '#/components/schemas/NullableStringFieldUpdateOperationsInput' - - type: 'null' - StringFilter: - type: object - properties: - equals: - type: string - in: - type: array - items: - type: string - notIn: - type: array - items: - type: string - lt: - type: string - lte: - type: string - gt: - type: string - gte: - type: string - contains: - type: string - startsWith: - type: string - endsWith: - type: string - mode: - $ref: '#/components/schemas/QueryMode' - not: - oneOf: - - type: string - - $ref: '#/components/schemas/NestedStringFilter' - DateTimeFilter: - type: object - properties: - equals: - type: string - format: date-time - in: - type: array - items: - type: string - format: date-time - notIn: - type: array - items: - type: string - format: date-time - lt: - type: string - format: date-time - lte: - type: string - format: date-time - gt: - type: string - format: date-time - gte: - type: string - format: date-time - not: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/NestedDateTimeFilter' - EnumroleFilter: - type: object - properties: - equals: - $ref: '#/components/schemas/Role' - in: - type: array - items: - $ref: '#/components/schemas/Role' - notIn: - type: array - items: - $ref: '#/components/schemas/Role' - not: - oneOf: - - $ref: '#/components/schemas/Role' - - $ref: '#/components/schemas/NestedEnumroleFilter' - Post_ItemListRelationFilter: - type: object - properties: - every: - $ref: '#/components/schemas/Post_ItemWhereInput' - some: - $ref: '#/components/schemas/Post_ItemWhereInput' - none: - $ref: '#/components/schemas/Post_ItemWhereInput' - ProfileNullableScalarRelationFilter: - type: object - properties: - is: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/ProfileWhereInput' - isNot: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/ProfileWhereInput' - Post_ItemOrderByRelationAggregateInput: - type: object - properties: - _count: - $ref: '#/components/schemas/SortOrder' - StringWithAggregatesFilter: - type: object - properties: - equals: - type: string - in: - type: array - items: - type: string - notIn: - type: array - items: - type: string - lt: - type: string - lte: - type: string - gt: - type: string - gte: - type: string - contains: - type: string - startsWith: - type: string - endsWith: - type: string - mode: - $ref: '#/components/schemas/QueryMode' - not: - oneOf: - - type: string - - $ref: '#/components/schemas/NestedStringWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _min: - $ref: '#/components/schemas/NestedStringFilter' - _max: - $ref: '#/components/schemas/NestedStringFilter' - DateTimeWithAggregatesFilter: - type: object - properties: - equals: - type: string - format: date-time - in: - type: array - items: - type: string - format: date-time - notIn: - type: array - items: - type: string - format: date-time - lt: - type: string - format: date-time - lte: - type: string - format: date-time - gt: - type: string - format: date-time - gte: - type: string - format: date-time - not: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/NestedDateTimeWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _min: - $ref: '#/components/schemas/NestedDateTimeFilter' - _max: - $ref: '#/components/schemas/NestedDateTimeFilter' - EnumroleWithAggregatesFilter: - type: object - properties: - equals: - $ref: '#/components/schemas/Role' - in: - type: array - items: - $ref: '#/components/schemas/Role' - notIn: - type: array - items: - $ref: '#/components/schemas/Role' - not: - oneOf: - - $ref: '#/components/schemas/Role' - - $ref: '#/components/schemas/NestedEnumroleWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _min: - $ref: '#/components/schemas/NestedEnumroleFilter' - _max: - $ref: '#/components/schemas/NestedEnumroleFilter' - StringNullableFilter: - type: object - properties: - equals: - oneOf: - - type: 'null' - - type: string - in: - oneOf: - - type: 'null' - - type: array - items: - type: string - notIn: - oneOf: - - type: 'null' - - type: array - items: - type: string - lt: - type: string - lte: - type: string - gt: - type: string - gte: - type: string - contains: - type: string - startsWith: - type: string - endsWith: - type: string - mode: - $ref: '#/components/schemas/QueryMode' - not: - oneOf: - - type: string - - $ref: '#/components/schemas/NestedStringNullableFilter' - - type: 'null' - UserScalarRelationFilter: - type: object - properties: - is: - $ref: '#/components/schemas/UserWhereInput' - isNot: - $ref: '#/components/schemas/UserWhereInput' - SortOrderInput: - type: object - properties: - sort: - $ref: '#/components/schemas/SortOrder' - nulls: - $ref: '#/components/schemas/NullsOrder' - required: - - sort - StringNullableWithAggregatesFilter: - type: object - properties: - equals: - oneOf: - - type: 'null' - - type: string - in: - oneOf: - - type: 'null' - - type: array - items: - type: string - notIn: - oneOf: - - type: 'null' - - type: array - items: - type: string - lt: - type: string - lte: - type: string - gt: - type: string - gte: - type: string - contains: - type: string - startsWith: - type: string - endsWith: - type: string - mode: - $ref: '#/components/schemas/QueryMode' - not: - oneOf: - - type: string - - $ref: '#/components/schemas/NestedStringNullableWithAggregatesFilter' - - type: 'null' - _count: - $ref: '#/components/schemas/NestedIntNullableFilter' - _min: - $ref: '#/components/schemas/NestedStringNullableFilter' - _max: - $ref: '#/components/schemas/NestedStringNullableFilter' - BoolFilter: - type: object - properties: - equals: - type: boolean - not: - oneOf: - - type: boolean - - $ref: '#/components/schemas/NestedBoolFilter' - IntFilter: - type: object - properties: - equals: - type: integer - in: - type: array - items: - type: integer - notIn: - type: array - items: - type: integer - lt: - type: integer - lte: - type: integer - gt: - type: integer - gte: - type: integer - not: - oneOf: - - type: integer - - $ref: '#/components/schemas/NestedIntFilter' - UserNullableScalarRelationFilter: - type: object - properties: - is: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/UserWhereInput' - isNot: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/UserWhereInput' - BoolWithAggregatesFilter: - type: object - properties: - equals: - type: boolean - not: - oneOf: - - type: boolean - - $ref: '#/components/schemas/NestedBoolWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _min: - $ref: '#/components/schemas/NestedBoolFilter' - _max: - $ref: '#/components/schemas/NestedBoolFilter' - IntWithAggregatesFilter: - type: object - properties: - equals: - type: integer - in: - type: array - items: - type: integer - notIn: - type: array - items: - type: integer - lt: - type: integer - lte: - type: integer - gt: - type: integer - gte: - type: integer - not: - oneOf: - - type: integer - - $ref: '#/components/schemas/NestedIntWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _avg: - $ref: '#/components/schemas/NestedFloatFilter' - _sum: - $ref: '#/components/schemas/NestedIntFilter' - _min: - $ref: '#/components/schemas/NestedIntFilter' - _max: - $ref: '#/components/schemas/NestedIntFilter' - Post_ItemCreateNestedManyWithoutAuthorInput: - type: object - properties: - create: - oneOf: - - $ref: '#/components/schemas/Post_ItemCreateWithoutAuthorInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemCreateWithoutAuthorInput' - - $ref: '#/components/schemas/Post_ItemUncheckedCreateWithoutAuthorInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemUncheckedCreateWithoutAuthorInput' - connectOrCreate: - oneOf: - - $ref: '#/components/schemas/Post_ItemCreateOrConnectWithoutAuthorInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemCreateOrConnectWithoutAuthorInput' - createMany: - $ref: '#/components/schemas/Post_ItemCreateManyAuthorInputEnvelope' - connect: - oneOf: - - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - ProfileCreateNestedOneWithoutUserInput: - type: object - properties: - create: - oneOf: - - $ref: '#/components/schemas/ProfileCreateWithoutUserInput' - - $ref: '#/components/schemas/ProfileUncheckedCreateWithoutUserInput' - connectOrCreate: - $ref: '#/components/schemas/ProfileCreateOrConnectWithoutUserInput' - connect: - $ref: '#/components/schemas/ProfileWhereUniqueInput' - Post_ItemUncheckedCreateNestedManyWithoutAuthorInput: - type: object - properties: - create: - oneOf: - - $ref: '#/components/schemas/Post_ItemCreateWithoutAuthorInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemCreateWithoutAuthorInput' - - $ref: '#/components/schemas/Post_ItemUncheckedCreateWithoutAuthorInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemUncheckedCreateWithoutAuthorInput' - connectOrCreate: - oneOf: - - $ref: '#/components/schemas/Post_ItemCreateOrConnectWithoutAuthorInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemCreateOrConnectWithoutAuthorInput' - createMany: - $ref: '#/components/schemas/Post_ItemCreateManyAuthorInputEnvelope' - connect: - oneOf: - - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - ProfileUncheckedCreateNestedOneWithoutUserInput: - type: object - properties: - create: - oneOf: - - $ref: '#/components/schemas/ProfileCreateWithoutUserInput' - - $ref: '#/components/schemas/ProfileUncheckedCreateWithoutUserInput' - connectOrCreate: - $ref: '#/components/schemas/ProfileCreateOrConnectWithoutUserInput' - connect: - $ref: '#/components/schemas/ProfileWhereUniqueInput' - StringFieldUpdateOperationsInput: - type: object - properties: - set: - type: string - DateTimeFieldUpdateOperationsInput: - type: object - properties: - set: - type: string - format: date-time - EnumroleFieldUpdateOperationsInput: - type: object - properties: - set: - $ref: '#/components/schemas/Role' - Post_ItemUpdateManyWithoutAuthorNestedInput: - type: object - properties: - create: - oneOf: - - $ref: '#/components/schemas/Post_ItemCreateWithoutAuthorInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemCreateWithoutAuthorInput' - - $ref: '#/components/schemas/Post_ItemUncheckedCreateWithoutAuthorInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemUncheckedCreateWithoutAuthorInput' - connectOrCreate: - oneOf: - - $ref: '#/components/schemas/Post_ItemCreateOrConnectWithoutAuthorInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemCreateOrConnectWithoutAuthorInput' - upsert: - oneOf: - - $ref: '#/components/schemas/Post_ItemUpsertWithWhereUniqueWithoutAuthorInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemUpsertWithWhereUniqueWithoutAuthorInput' - createMany: - $ref: '#/components/schemas/Post_ItemCreateManyAuthorInputEnvelope' - set: - oneOf: - - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - disconnect: - oneOf: - - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - delete: - oneOf: - - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - connect: - oneOf: - - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - update: - oneOf: - - $ref: '#/components/schemas/Post_ItemUpdateWithWhereUniqueWithoutAuthorInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemUpdateWithWhereUniqueWithoutAuthorInput' - updateMany: - oneOf: - - $ref: '#/components/schemas/Post_ItemUpdateManyWithWhereWithoutAuthorInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemUpdateManyWithWhereWithoutAuthorInput' - deleteMany: - oneOf: - - $ref: '#/components/schemas/Post_ItemScalarWhereInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemScalarWhereInput' - ProfileUpdateOneWithoutUserNestedInput: - type: object - properties: - create: - oneOf: - - $ref: '#/components/schemas/ProfileCreateWithoutUserInput' - - $ref: '#/components/schemas/ProfileUncheckedCreateWithoutUserInput' - connectOrCreate: - $ref: '#/components/schemas/ProfileCreateOrConnectWithoutUserInput' - upsert: - $ref: '#/components/schemas/ProfileUpsertWithoutUserInput' - disconnect: - oneOf: - - type: boolean - - $ref: '#/components/schemas/ProfileWhereInput' - delete: - oneOf: - - type: boolean - - $ref: '#/components/schemas/ProfileWhereInput' - connect: - $ref: '#/components/schemas/ProfileWhereUniqueInput' - update: - oneOf: - - $ref: '#/components/schemas/ProfileUpdateToOneWithWhereWithoutUserInput' - - $ref: '#/components/schemas/ProfileUpdateWithoutUserInput' - - $ref: '#/components/schemas/ProfileUncheckedUpdateWithoutUserInput' - Post_ItemUncheckedUpdateManyWithoutAuthorNestedInput: - type: object - properties: - create: - oneOf: - - $ref: '#/components/schemas/Post_ItemCreateWithoutAuthorInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemCreateWithoutAuthorInput' - - $ref: '#/components/schemas/Post_ItemUncheckedCreateWithoutAuthorInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemUncheckedCreateWithoutAuthorInput' - connectOrCreate: - oneOf: - - $ref: '#/components/schemas/Post_ItemCreateOrConnectWithoutAuthorInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemCreateOrConnectWithoutAuthorInput' - upsert: - oneOf: - - $ref: '#/components/schemas/Post_ItemUpsertWithWhereUniqueWithoutAuthorInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemUpsertWithWhereUniqueWithoutAuthorInput' - createMany: - $ref: '#/components/schemas/Post_ItemCreateManyAuthorInputEnvelope' - set: - oneOf: - - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - disconnect: - oneOf: - - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - delete: - oneOf: - - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - connect: - oneOf: - - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - update: - oneOf: - - $ref: '#/components/schemas/Post_ItemUpdateWithWhereUniqueWithoutAuthorInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemUpdateWithWhereUniqueWithoutAuthorInput' - updateMany: - oneOf: - - $ref: '#/components/schemas/Post_ItemUpdateManyWithWhereWithoutAuthorInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemUpdateManyWithWhereWithoutAuthorInput' - deleteMany: - oneOf: - - $ref: '#/components/schemas/Post_ItemScalarWhereInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemScalarWhereInput' - ProfileUncheckedUpdateOneWithoutUserNestedInput: - type: object - properties: - create: - oneOf: - - $ref: '#/components/schemas/ProfileCreateWithoutUserInput' - - $ref: '#/components/schemas/ProfileUncheckedCreateWithoutUserInput' - connectOrCreate: - $ref: '#/components/schemas/ProfileCreateOrConnectWithoutUserInput' - upsert: - $ref: '#/components/schemas/ProfileUpsertWithoutUserInput' - disconnect: - oneOf: - - type: boolean - - $ref: '#/components/schemas/ProfileWhereInput' - delete: - oneOf: - - type: boolean - - $ref: '#/components/schemas/ProfileWhereInput' - connect: - $ref: '#/components/schemas/ProfileWhereUniqueInput' - update: - oneOf: - - $ref: '#/components/schemas/ProfileUpdateToOneWithWhereWithoutUserInput' - - $ref: '#/components/schemas/ProfileUpdateWithoutUserInput' - - $ref: '#/components/schemas/ProfileUncheckedUpdateWithoutUserInput' - UserCreateNestedOneWithoutProfileInput: - type: object - properties: - create: - oneOf: - - $ref: '#/components/schemas/UserCreateWithoutProfileInput' - - $ref: '#/components/schemas/UserUncheckedCreateWithoutProfileInput' - connectOrCreate: - $ref: '#/components/schemas/UserCreateOrConnectWithoutProfileInput' - connect: - $ref: '#/components/schemas/UserWhereUniqueInput' - NullableStringFieldUpdateOperationsInput: - type: object - properties: - set: - oneOf: - - type: 'null' - - type: string - UserUpdateOneRequiredWithoutProfileNestedInput: - type: object - properties: - create: - oneOf: - - $ref: '#/components/schemas/UserCreateWithoutProfileInput' - - $ref: '#/components/schemas/UserUncheckedCreateWithoutProfileInput' - connectOrCreate: - $ref: '#/components/schemas/UserCreateOrConnectWithoutProfileInput' - upsert: - $ref: '#/components/schemas/UserUpsertWithoutProfileInput' - connect: - $ref: '#/components/schemas/UserWhereUniqueInput' - update: - oneOf: - - $ref: '#/components/schemas/UserUpdateToOneWithWhereWithoutProfileInput' - - $ref: '#/components/schemas/UserUpdateWithoutProfileInput' - - $ref: '#/components/schemas/UserUncheckedUpdateWithoutProfileInput' - UserCreateNestedOneWithoutPostsInput: - type: object - properties: - create: - oneOf: - - $ref: '#/components/schemas/UserCreateWithoutPostsInput' - - $ref: '#/components/schemas/UserUncheckedCreateWithoutPostsInput' - connectOrCreate: - $ref: '#/components/schemas/UserCreateOrConnectWithoutPostsInput' - connect: - $ref: '#/components/schemas/UserWhereUniqueInput' - BoolFieldUpdateOperationsInput: - type: object - properties: - set: - type: boolean - IntFieldUpdateOperationsInput: - type: object - properties: - set: - type: integer - increment: - type: integer - decrement: - type: integer - multiply: - type: integer - divide: - type: integer - UserUpdateOneWithoutPostsNestedInput: - type: object - properties: - create: - oneOf: - - $ref: '#/components/schemas/UserCreateWithoutPostsInput' - - $ref: '#/components/schemas/UserUncheckedCreateWithoutPostsInput' - connectOrCreate: - $ref: '#/components/schemas/UserCreateOrConnectWithoutPostsInput' - upsert: - $ref: '#/components/schemas/UserUpsertWithoutPostsInput' - disconnect: - oneOf: - - type: boolean - - $ref: '#/components/schemas/UserWhereInput' - delete: - oneOf: - - type: boolean - - $ref: '#/components/schemas/UserWhereInput' - connect: - $ref: '#/components/schemas/UserWhereUniqueInput' - update: - oneOf: - - $ref: '#/components/schemas/UserUpdateToOneWithWhereWithoutPostsInput' - - $ref: '#/components/schemas/UserUpdateWithoutPostsInput' - - $ref: '#/components/schemas/UserUncheckedUpdateWithoutPostsInput' - NestedStringFilter: - type: object - properties: - equals: - type: string - in: - type: array - items: - type: string - notIn: - type: array - items: - type: string - lt: - type: string - lte: - type: string - gt: - type: string - gte: - type: string - contains: - type: string - startsWith: - type: string - endsWith: - type: string - not: - oneOf: - - type: string - - $ref: '#/components/schemas/NestedStringFilter' - NestedDateTimeFilter: - type: object - properties: - equals: - type: string - format: date-time - in: - type: array - items: - type: string - format: date-time - notIn: - type: array - items: - type: string - format: date-time - lt: - type: string - format: date-time - lte: - type: string - format: date-time - gt: - type: string - format: date-time - gte: - type: string - format: date-time - not: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/NestedDateTimeFilter' - NestedEnumroleFilter: - type: object - properties: - equals: - $ref: '#/components/schemas/Role' - in: - type: array - items: - $ref: '#/components/schemas/Role' - notIn: - type: array - items: - $ref: '#/components/schemas/Role' - not: - oneOf: - - $ref: '#/components/schemas/Role' - - $ref: '#/components/schemas/NestedEnumroleFilter' - NestedStringWithAggregatesFilter: - type: object - properties: - equals: - type: string - in: - type: array - items: - type: string - notIn: - type: array - items: - type: string - lt: - type: string - lte: - type: string - gt: - type: string - gte: - type: string - contains: - type: string - startsWith: - type: string - endsWith: - type: string - not: - oneOf: - - type: string - - $ref: '#/components/schemas/NestedStringWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _min: - $ref: '#/components/schemas/NestedStringFilter' - _max: - $ref: '#/components/schemas/NestedStringFilter' - NestedIntFilter: - type: object - properties: - equals: - type: integer - in: - type: array - items: - type: integer - notIn: - type: array - items: - type: integer - lt: - type: integer - lte: - type: integer - gt: - type: integer - gte: - type: integer - not: - oneOf: - - type: integer - - $ref: '#/components/schemas/NestedIntFilter' - NestedDateTimeWithAggregatesFilter: - type: object - properties: - equals: - type: string - format: date-time - in: - type: array - items: - type: string - format: date-time - notIn: - type: array - items: - type: string - format: date-time - lt: - type: string - format: date-time - lte: - type: string - format: date-time - gt: - type: string - format: date-time - gte: - type: string - format: date-time - not: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/NestedDateTimeWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _min: - $ref: '#/components/schemas/NestedDateTimeFilter' - _max: - $ref: '#/components/schemas/NestedDateTimeFilter' - NestedEnumroleWithAggregatesFilter: - type: object - properties: - equals: - $ref: '#/components/schemas/Role' - in: - type: array - items: - $ref: '#/components/schemas/Role' - notIn: - type: array - items: - $ref: '#/components/schemas/Role' - not: - oneOf: - - $ref: '#/components/schemas/Role' - - $ref: '#/components/schemas/NestedEnumroleWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _min: - $ref: '#/components/schemas/NestedEnumroleFilter' - _max: - $ref: '#/components/schemas/NestedEnumroleFilter' - NestedStringNullableFilter: - type: object - properties: - equals: - oneOf: - - type: 'null' - - type: string - in: - oneOf: - - type: 'null' - - type: array - items: - type: string - notIn: - oneOf: - - type: 'null' - - type: array - items: - type: string - lt: - type: string - lte: - type: string - gt: - type: string - gte: - type: string - contains: - type: string - startsWith: - type: string - endsWith: - type: string - not: - oneOf: - - type: string - - $ref: '#/components/schemas/NestedStringNullableFilter' - - type: 'null' - NestedStringNullableWithAggregatesFilter: - type: object - properties: - equals: - oneOf: - - type: 'null' - - type: string - in: - oneOf: - - type: 'null' - - type: array - items: - type: string - notIn: - oneOf: - - type: 'null' - - type: array - items: - type: string - lt: - type: string - lte: - type: string - gt: - type: string - gte: - type: string - contains: - type: string - startsWith: - type: string - endsWith: - type: string - not: - oneOf: - - type: string - - $ref: '#/components/schemas/NestedStringNullableWithAggregatesFilter' - - type: 'null' - _count: - $ref: '#/components/schemas/NestedIntNullableFilter' - _min: - $ref: '#/components/schemas/NestedStringNullableFilter' - _max: - $ref: '#/components/schemas/NestedStringNullableFilter' - NestedIntNullableFilter: - type: object - properties: - equals: - oneOf: - - type: 'null' - - type: integer - in: - oneOf: - - type: 'null' - - type: array - items: - type: integer - notIn: - oneOf: - - type: 'null' - - type: array - items: - type: integer - lt: - type: integer - lte: - type: integer - gt: - type: integer - gte: - type: integer - not: - oneOf: - - type: integer - - $ref: '#/components/schemas/NestedIntNullableFilter' - - type: 'null' - NestedBoolFilter: - type: object - properties: - equals: - type: boolean - not: - oneOf: - - type: boolean - - $ref: '#/components/schemas/NestedBoolFilter' - NestedBoolWithAggregatesFilter: - type: object - properties: - equals: - type: boolean - not: - oneOf: - - type: boolean - - $ref: '#/components/schemas/NestedBoolWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _min: - $ref: '#/components/schemas/NestedBoolFilter' - _max: - $ref: '#/components/schemas/NestedBoolFilter' - NestedIntWithAggregatesFilter: - type: object - properties: - equals: - type: integer - in: - type: array - items: - type: integer - notIn: - type: array - items: - type: integer - lt: - type: integer - lte: - type: integer - gt: - type: integer - gte: - type: integer - not: - oneOf: - - type: integer - - $ref: '#/components/schemas/NestedIntWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _avg: - $ref: '#/components/schemas/NestedFloatFilter' - _sum: - $ref: '#/components/schemas/NestedIntFilter' - _min: - $ref: '#/components/schemas/NestedIntFilter' - _max: - $ref: '#/components/schemas/NestedIntFilter' - NestedFloatFilter: - type: object - properties: - equals: - type: number - in: - type: array - items: - type: number - notIn: - type: array - items: - type: number - lt: - type: number - lte: - type: number - gt: - type: number - gte: - type: number - not: - oneOf: - - type: number - - $ref: '#/components/schemas/NestedFloatFilter' - Post_ItemCreateWithoutAuthorInput: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - title: - type: string - published: - type: boolean - viewCount: - type: integer - notes: - oneOf: - - type: 'null' - - type: string - required: - - id - - title - Post_ItemUncheckedCreateWithoutAuthorInput: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - title: - type: string - published: - type: boolean - viewCount: - type: integer - notes: - oneOf: - - type: 'null' - - type: string - required: - - id - - title - Post_ItemCreateOrConnectWithoutAuthorInput: - type: object - properties: - where: - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - create: - oneOf: - - $ref: '#/components/schemas/Post_ItemCreateWithoutAuthorInput' - - $ref: '#/components/schemas/Post_ItemUncheckedCreateWithoutAuthorInput' - required: - - where - - create - Post_ItemCreateManyAuthorInputEnvelope: - type: object - properties: - data: - oneOf: - - $ref: '#/components/schemas/Post_ItemCreateManyAuthorInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemCreateManyAuthorInput' - skipDuplicates: - type: boolean - required: - - data - ProfileCreateWithoutUserInput: - type: object - properties: - id: - type: string - image: - oneOf: - - type: 'null' - - type: string - ProfileUncheckedCreateWithoutUserInput: - type: object - properties: - id: - type: string - image: - oneOf: - - type: 'null' - - type: string - ProfileCreateOrConnectWithoutUserInput: - type: object - properties: - where: - $ref: '#/components/schemas/ProfileWhereUniqueInput' - create: - oneOf: - - $ref: '#/components/schemas/ProfileCreateWithoutUserInput' - - $ref: '#/components/schemas/ProfileUncheckedCreateWithoutUserInput' - required: - - where - - create - Post_ItemUpsertWithWhereUniqueWithoutAuthorInput: - type: object - properties: - where: - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - update: - oneOf: - - $ref: '#/components/schemas/Post_ItemUpdateWithoutAuthorInput' - - $ref: '#/components/schemas/Post_ItemUncheckedUpdateWithoutAuthorInput' - create: - oneOf: - - $ref: '#/components/schemas/Post_ItemCreateWithoutAuthorInput' - - $ref: '#/components/schemas/Post_ItemUncheckedCreateWithoutAuthorInput' - required: - - where - - update - - create - Post_ItemUpdateWithWhereUniqueWithoutAuthorInput: - type: object - properties: - where: - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - data: - oneOf: - - $ref: '#/components/schemas/Post_ItemUpdateWithoutAuthorInput' - - $ref: '#/components/schemas/Post_ItemUncheckedUpdateWithoutAuthorInput' - required: - - where - - data - Post_ItemUpdateManyWithWhereWithoutAuthorInput: - type: object - properties: - where: - $ref: '#/components/schemas/Post_ItemScalarWhereInput' - data: - oneOf: - - $ref: '#/components/schemas/Post_ItemUpdateManyMutationInput' - - $ref: '#/components/schemas/Post_ItemUncheckedUpdateManyWithoutAuthorInput' - required: - - where - - data - Post_ItemScalarWhereInput: - type: object - properties: - AND: - oneOf: - - $ref: '#/components/schemas/Post_ItemScalarWhereInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemScalarWhereInput' - OR: - type: array - items: - $ref: '#/components/schemas/Post_ItemScalarWhereInput' - NOT: - oneOf: - - $ref: '#/components/schemas/Post_ItemScalarWhereInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemScalarWhereInput' - id: - oneOf: - - $ref: '#/components/schemas/StringFilter' - - type: string - createdAt: - oneOf: - - $ref: '#/components/schemas/DateTimeFilter' - - type: string - format: date-time - updatedAt: - oneOf: - - $ref: '#/components/schemas/DateTimeFilter' - - type: string - format: date-time - title: - oneOf: - - $ref: '#/components/schemas/StringFilter' - - type: string - authorId: - oneOf: - - $ref: '#/components/schemas/StringNullableFilter' - - type: string - - type: 'null' - published: - oneOf: - - $ref: '#/components/schemas/BoolFilter' - - type: boolean - viewCount: - oneOf: - - $ref: '#/components/schemas/IntFilter' - - type: integer - notes: - oneOf: - - $ref: '#/components/schemas/StringNullableFilter' - - type: string - - type: 'null' - ProfileUpsertWithoutUserInput: - type: object - properties: - update: - oneOf: - - $ref: '#/components/schemas/ProfileUpdateWithoutUserInput' - - $ref: '#/components/schemas/ProfileUncheckedUpdateWithoutUserInput' - create: - oneOf: - - $ref: '#/components/schemas/ProfileCreateWithoutUserInput' - - $ref: '#/components/schemas/ProfileUncheckedCreateWithoutUserInput' - where: - $ref: '#/components/schemas/ProfileWhereInput' - required: - - update - - create - ProfileUpdateToOneWithWhereWithoutUserInput: - type: object - properties: - where: - $ref: '#/components/schemas/ProfileWhereInput' - data: - oneOf: - - $ref: '#/components/schemas/ProfileUpdateWithoutUserInput' - - $ref: '#/components/schemas/ProfileUncheckedUpdateWithoutUserInput' - required: - - data - ProfileUpdateWithoutUserInput: - type: object - properties: - id: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - image: - oneOf: - - type: string - - $ref: '#/components/schemas/NullableStringFieldUpdateOperationsInput' - - type: 'null' - ProfileUncheckedUpdateWithoutUserInput: - type: object - properties: - id: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - image: - oneOf: - - type: string - - $ref: '#/components/schemas/NullableStringFieldUpdateOperationsInput' - - type: 'null' - UserCreateWithoutProfileInput: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - email: - type: string - role: - $ref: '#/components/schemas/Role' - posts: - $ref: '#/components/schemas/Post_ItemCreateNestedManyWithoutAuthorInput' - required: - - email - UserUncheckedCreateWithoutProfileInput: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - email: - type: string - role: - $ref: '#/components/schemas/Role' - posts: - $ref: "#/components/schemas/Post_ItemUncheckedCreateNestedManyWithoutAuthorInpu\ - t" - required: - - email - UserCreateOrConnectWithoutProfileInput: - type: object - properties: - where: - $ref: '#/components/schemas/UserWhereUniqueInput' - create: - oneOf: - - $ref: '#/components/schemas/UserCreateWithoutProfileInput' - - $ref: '#/components/schemas/UserUncheckedCreateWithoutProfileInput' - required: - - where - - create - UserUpsertWithoutProfileInput: - type: object - properties: - update: - oneOf: - - $ref: '#/components/schemas/UserUpdateWithoutProfileInput' - - $ref: '#/components/schemas/UserUncheckedUpdateWithoutProfileInput' - create: - oneOf: - - $ref: '#/components/schemas/UserCreateWithoutProfileInput' - - $ref: '#/components/schemas/UserUncheckedCreateWithoutProfileInput' - where: - $ref: '#/components/schemas/UserWhereInput' - required: - - update - - create - UserUpdateToOneWithWhereWithoutProfileInput: - type: object - properties: - where: - $ref: '#/components/schemas/UserWhereInput' - data: - oneOf: - - $ref: '#/components/schemas/UserUpdateWithoutProfileInput' - - $ref: '#/components/schemas/UserUncheckedUpdateWithoutProfileInput' - required: - - data - UserUpdateWithoutProfileInput: - type: object - properties: - id: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - createdAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - updatedAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - email: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - role: - oneOf: - - $ref: '#/components/schemas/Role' - - $ref: '#/components/schemas/EnumroleFieldUpdateOperationsInput' - posts: - $ref: '#/components/schemas/Post_ItemUpdateManyWithoutAuthorNestedInput' - UserUncheckedUpdateWithoutProfileInput: - type: object - properties: - id: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - createdAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - updatedAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - email: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - role: - oneOf: - - $ref: '#/components/schemas/Role' - - $ref: '#/components/schemas/EnumroleFieldUpdateOperationsInput' - posts: - $ref: "#/components/schemas/Post_ItemUncheckedUpdateManyWithoutAuthorNestedInpu\ - t" - UserCreateWithoutPostsInput: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - email: - type: string - role: - $ref: '#/components/schemas/Role' - profile: - $ref: '#/components/schemas/ProfileCreateNestedOneWithoutUserInput' - required: - - email - UserUncheckedCreateWithoutPostsInput: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - email: - type: string - role: - $ref: '#/components/schemas/Role' - profile: - $ref: '#/components/schemas/ProfileUncheckedCreateNestedOneWithoutUserInput' - required: - - email - UserCreateOrConnectWithoutPostsInput: - type: object - properties: - where: - $ref: '#/components/schemas/UserWhereUniqueInput' - create: - oneOf: - - $ref: '#/components/schemas/UserCreateWithoutPostsInput' - - $ref: '#/components/schemas/UserUncheckedCreateWithoutPostsInput' - required: - - where - - create - UserUpsertWithoutPostsInput: - type: object - properties: - update: - oneOf: - - $ref: '#/components/schemas/UserUpdateWithoutPostsInput' - - $ref: '#/components/schemas/UserUncheckedUpdateWithoutPostsInput' - create: - oneOf: - - $ref: '#/components/schemas/UserCreateWithoutPostsInput' - - $ref: '#/components/schemas/UserUncheckedCreateWithoutPostsInput' - where: - $ref: '#/components/schemas/UserWhereInput' - required: - - update - - create - UserUpdateToOneWithWhereWithoutPostsInput: - type: object - properties: - where: - $ref: '#/components/schemas/UserWhereInput' - data: - oneOf: - - $ref: '#/components/schemas/UserUpdateWithoutPostsInput' - - $ref: '#/components/schemas/UserUncheckedUpdateWithoutPostsInput' - required: - - data - UserUpdateWithoutPostsInput: - type: object - properties: - id: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - createdAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - updatedAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - email: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - role: - oneOf: - - $ref: '#/components/schemas/Role' - - $ref: '#/components/schemas/EnumroleFieldUpdateOperationsInput' - profile: - $ref: '#/components/schemas/ProfileUpdateOneWithoutUserNestedInput' - UserUncheckedUpdateWithoutPostsInput: - type: object - properties: - id: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - createdAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - updatedAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - email: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - role: - oneOf: - - $ref: '#/components/schemas/Role' - - $ref: '#/components/schemas/EnumroleFieldUpdateOperationsInput' - profile: - $ref: '#/components/schemas/ProfileUncheckedUpdateOneWithoutUserNestedInput' - Post_ItemCreateManyAuthorInput: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - title: - type: string - published: - type: boolean - viewCount: - type: integer - notes: - oneOf: - - type: 'null' - - type: string - required: - - id - - title - Post_ItemUpdateWithoutAuthorInput: - type: object - properties: - id: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - createdAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - updatedAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - title: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - published: - oneOf: - - type: boolean - - $ref: '#/components/schemas/BoolFieldUpdateOperationsInput' - viewCount: - oneOf: - - type: integer - - $ref: '#/components/schemas/IntFieldUpdateOperationsInput' - notes: - oneOf: - - type: string - - $ref: '#/components/schemas/NullableStringFieldUpdateOperationsInput' - - type: 'null' - Post_ItemUncheckedUpdateWithoutAuthorInput: - type: object - properties: - id: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - createdAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - updatedAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - title: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - published: - oneOf: - - type: boolean - - $ref: '#/components/schemas/BoolFieldUpdateOperationsInput' - viewCount: - oneOf: - - type: integer - - $ref: '#/components/schemas/IntFieldUpdateOperationsInput' - notes: - oneOf: - - type: string - - $ref: '#/components/schemas/NullableStringFieldUpdateOperationsInput' - - type: 'null' - Post_ItemUncheckedUpdateManyWithoutAuthorInput: - type: object - properties: - id: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - createdAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - updatedAt: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - title: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - published: - oneOf: - - type: boolean - - $ref: '#/components/schemas/BoolFieldUpdateOperationsInput' - viewCount: - oneOf: - - type: integer - - $ref: '#/components/schemas/IntFieldUpdateOperationsInput' - notes: - oneOf: - - type: string - - $ref: '#/components/schemas/NullableStringFieldUpdateOperationsInput' - - type: 'null' - UserDefaultArgs: - type: object - properties: - select: - $ref: '#/components/schemas/UserSelect' - include: - $ref: '#/components/schemas/UserInclude' - ProfileDefaultArgs: - type: object - properties: - select: - $ref: '#/components/schemas/ProfileSelect' - include: - $ref: '#/components/schemas/ProfileInclude' - UserInclude: - type: object - properties: - posts: - oneOf: - - type: boolean - - $ref: '#/components/schemas/Post_ItemFindManyArgs' - profile: - oneOf: - - type: boolean - - $ref: '#/components/schemas/ProfileDefaultArgs' - _count: - oneOf: - - type: boolean - - $ref: '#/components/schemas/UserCountOutputTypeDefaultArgs' - ProfileInclude: - type: object - properties: - user: - oneOf: - - type: boolean - - $ref: '#/components/schemas/UserDefaultArgs' - Post_ItemInclude: - type: object - properties: - author: - oneOf: - - type: boolean - - $ref: '#/components/schemas/UserDefaultArgs' - UserCountOutputTypeSelect: - type: object - properties: - posts: - type: boolean - UserCountOutputTypeDefaultArgs: - type: object - properties: - select: - $ref: '#/components/schemas/UserCountOutputTypeSelect' - UserSelect: - type: object - properties: - id: - type: boolean - createdAt: - type: boolean - updatedAt: - type: boolean - email: - type: boolean - role: - type: boolean - posts: - oneOf: - - type: boolean - - $ref: '#/components/schemas/Post_ItemFindManyArgs' - profile: - oneOf: - - type: boolean - - $ref: '#/components/schemas/ProfileDefaultArgs' - _count: - oneOf: - - type: boolean - - $ref: '#/components/schemas/UserCountOutputTypeDefaultArgs' - ProfileSelect: - type: object - properties: - id: - type: boolean - image: - type: boolean - user: - oneOf: - - type: boolean - - $ref: '#/components/schemas/UserDefaultArgs' - userId: - type: boolean - Post_ItemSelect: - type: object - properties: - id: - type: boolean - createdAt: - type: boolean - updatedAt: - type: boolean - title: - type: boolean - author: - oneOf: - - type: boolean - - $ref: '#/components/schemas/UserDefaultArgs' - authorId: - type: boolean - published: - type: boolean - viewCount: - type: boolean - notes: - type: boolean - UserCountAggregateInput: - type: object - properties: - id: - type: boolean - createdAt: - type: boolean - updatedAt: - type: boolean - email: - type: boolean - role: - type: boolean - _all: - type: boolean - UserMinAggregateInput: - type: object - properties: - id: - type: boolean - createdAt: - type: boolean - updatedAt: - type: boolean - email: - type: boolean - role: - type: boolean - UserMaxAggregateInput: - type: object - properties: - id: - type: boolean - createdAt: - type: boolean - updatedAt: - type: boolean - email: - type: boolean - role: - type: boolean - ProfileCountAggregateInput: - type: object - properties: - id: - type: boolean - image: - type: boolean - userId: - type: boolean - _all: - type: boolean - ProfileMinAggregateInput: - type: object - properties: - id: - type: boolean - image: - type: boolean - userId: - type: boolean - ProfileMaxAggregateInput: - type: object - properties: - id: - type: boolean - image: - type: boolean - userId: - type: boolean - AggregateUser: - type: object - properties: - _count: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/UserCountAggregateOutputType' - _min: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/UserMinAggregateOutputType' - _max: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/UserMaxAggregateOutputType' - UserGroupByOutputType: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - email: - type: string - role: - $ref: '#/components/schemas/Role' - _count: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/UserCountAggregateOutputType' - _min: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/UserMinAggregateOutputType' - _max: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/UserMaxAggregateOutputType' - required: - - id - - createdAt - - updatedAt - - email - - role - AggregateProfile: - type: object - properties: - _count: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/ProfileCountAggregateOutputType' - _min: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/ProfileMinAggregateOutputType' - _max: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/ProfileMaxAggregateOutputType' - ProfileGroupByOutputType: - type: object - properties: - id: - type: string - image: - oneOf: - - type: 'null' - - type: string - userId: - type: string - _count: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/ProfileCountAggregateOutputType' - _min: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/ProfileMinAggregateOutputType' - _max: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/ProfileMaxAggregateOutputType' - required: - - id - - userId - AggregatePost_Item: - type: object - properties: - _count: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Post_ItemCountAggregateOutputType' - _avg: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Post_ItemAvgAggregateOutputType' - _sum: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Post_ItemSumAggregateOutputType' - _min: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Post_ItemMinAggregateOutputType' - _max: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Post_ItemMaxAggregateOutputType' - Post_ItemGroupByOutputType: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - title: - type: string - authorId: - oneOf: - - type: 'null' - - type: string - published: - type: boolean - viewCount: - type: integer - notes: - oneOf: - - type: 'null' - - type: string - _count: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Post_ItemCountAggregateOutputType' - _avg: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Post_ItemAvgAggregateOutputType' - _sum: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Post_ItemSumAggregateOutputType' - _min: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Post_ItemMinAggregateOutputType' - _max: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Post_ItemMaxAggregateOutputType' - required: - - id - - createdAt - - updatedAt - - title - - published - - viewCount - UserCountAggregateOutputType: - type: object - properties: - id: - type: integer - createdAt: - type: integer - updatedAt: - type: integer - email: - type: integer - role: - type: integer - _all: - type: integer - required: - - id - - createdAt - - updatedAt - - email - - role - - _all - UserMinAggregateOutputType: - type: object - properties: - id: - oneOf: - - type: 'null' - - type: string - createdAt: - oneOf: - - type: 'null' - - type: string - format: date-time - updatedAt: - oneOf: - - type: 'null' - - type: string - format: date-time - email: - oneOf: - - type: 'null' - - type: string - role: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Role' - UserMaxAggregateOutputType: - type: object - properties: - id: - oneOf: - - type: 'null' - - type: string - createdAt: - oneOf: - - type: 'null' - - type: string - format: date-time - updatedAt: - oneOf: - - type: 'null' - - type: string - format: date-time - email: - oneOf: - - type: 'null' - - type: string - role: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Role' - ProfileCountAggregateOutputType: - type: object - properties: - id: - type: integer - image: - type: integer - userId: - type: integer - _all: - type: integer - required: - - id - - image - - userId - - _all - ProfileMinAggregateOutputType: - type: object - properties: - id: - oneOf: - - type: 'null' - - type: string - image: - oneOf: - - type: 'null' - - type: string - userId: - oneOf: - - type: 'null' - - type: string - ProfileMaxAggregateOutputType: - type: object - properties: - id: - oneOf: - - type: 'null' - - type: string - image: - oneOf: - - type: 'null' - - type: string - userId: - oneOf: - - type: 'null' - - type: string - Post_ItemCountAggregateOutputType: - type: object - properties: - id: - type: integer - createdAt: - type: integer - updatedAt: - type: integer - title: - type: integer - authorId: - type: integer - published: - type: integer - viewCount: - type: integer - notes: - type: integer - _all: - type: integer - required: - - id - - createdAt - - updatedAt - - title - - authorId - - published - - viewCount - - notes - - _all - Post_ItemAvgAggregateOutputType: - type: object - properties: - viewCount: - oneOf: - - type: 'null' - - type: number - Post_ItemSumAggregateOutputType: - type: object - properties: - viewCount: - oneOf: - - type: 'null' - - type: integer - Post_ItemMinAggregateOutputType: - type: object - properties: - id: - oneOf: - - type: 'null' - - type: string - createdAt: - oneOf: - - type: 'null' - - type: string - format: date-time - updatedAt: - oneOf: - - type: 'null' - - type: string - format: date-time - title: - oneOf: - - type: 'null' - - type: string - authorId: - oneOf: - - type: 'null' - - type: string - published: - oneOf: - - type: 'null' - - type: boolean - viewCount: - oneOf: - - type: 'null' - - type: integer - notes: - oneOf: - - type: 'null' - - type: string - Post_ItemMaxAggregateOutputType: - type: object - properties: - id: - oneOf: - - type: 'null' - - type: string - createdAt: - oneOf: - - type: 'null' - - type: string - format: date-time - updatedAt: - oneOf: - - type: 'null' - - type: string - format: date-time - title: - oneOf: - - type: 'null' - - type: string - authorId: - oneOf: - - type: 'null' - - type: string - published: - oneOf: - - type: 'null' - - type: boolean - viewCount: - oneOf: - - type: 'null' - - type: integer - notes: - oneOf: - - type: 'null' - - type: string - _Meta: - type: object - description: Meta information about the request or response - properties: - serialization: - description: Serialization metadata - additionalProperties: true - _Error: - type: object - required: - - error - properties: - error: - type: object - required: - - message - properties: - prisma: - type: boolean - description: Indicates if the error occurred during a Prisma call - rejectedByPolicy: - type: boolean - description: Indicates if the error was due to rejection by a policy - code: - type: string - description: Prisma error code. Only available when "prisma" field is true. - message: - type: string - description: Error message - reason: - type: string - description: Detailed error reason - zodErrors: - type: object - additionalProperties: true - description: Zod validation errors if the error is due to data validation - failure - additionalProperties: true - BatchPayload: - type: object - properties: - count: - type: integer - UserCreateArgs: - type: object - required: - - data - properties: - select: - $ref: '#/components/schemas/UserSelect' - include: - $ref: '#/components/schemas/UserInclude' - data: - $ref: '#/components/schemas/UserCreateInput' - meta: - $ref: '#/components/schemas/_Meta' - UserCreateManyArgs: - type: object - required: - - data - properties: - data: - oneOf: - - $ref: '#/components/schemas/UserCreateManyInput' - - type: array - items: - $ref: '#/components/schemas/UserCreateManyInput' - skipDuplicates: - type: boolean - description: Do not insert records with unique fields or ID fields that already - exist. - meta: - $ref: '#/components/schemas/_Meta' - UserFindUniqueArgs: - type: object - required: - - where - properties: - select: - $ref: '#/components/schemas/UserSelect' - include: - $ref: '#/components/schemas/UserInclude' - where: - $ref: '#/components/schemas/UserWhereUniqueInput' - meta: - $ref: '#/components/schemas/_Meta' - UserFindFirstArgs: - type: object - properties: - select: - $ref: '#/components/schemas/UserSelect' - include: - $ref: '#/components/schemas/UserInclude' - where: - $ref: '#/components/schemas/UserWhereInput' - meta: - $ref: '#/components/schemas/_Meta' - UserFindManyArgs: - type: object - properties: - select: - $ref: '#/components/schemas/UserSelect' - include: - $ref: '#/components/schemas/UserInclude' - where: - $ref: '#/components/schemas/UserWhereInput' - meta: - $ref: '#/components/schemas/_Meta' - orderBy: - oneOf: - - $ref: '#/components/schemas/UserOrderByWithRelationInput' - - type: array - items: - $ref: '#/components/schemas/UserOrderByWithRelationInput' - cursor: - $ref: '#/components/schemas/UserWhereUniqueInput' - take: - type: integer - skip: - type: integer - UserUpdateArgs: - type: object - required: - - where - - data - properties: - select: - $ref: '#/components/schemas/UserSelect' - include: - $ref: '#/components/schemas/UserInclude' - where: - $ref: '#/components/schemas/UserWhereUniqueInput' - data: - $ref: '#/components/schemas/UserUpdateInput' - meta: - $ref: '#/components/schemas/_Meta' - UserUpdateManyArgs: - type: object - required: - - data - properties: - where: - $ref: '#/components/schemas/UserWhereInput' - data: - $ref: '#/components/schemas/UserUpdateManyMutationInput' - meta: - $ref: '#/components/schemas/_Meta' - UserUpsertArgs: - type: object - required: - - create - - update - - where - properties: - select: - $ref: '#/components/schemas/UserSelect' - include: - $ref: '#/components/schemas/UserInclude' - where: - $ref: '#/components/schemas/UserWhereUniqueInput' - create: - $ref: '#/components/schemas/UserCreateInput' - update: - $ref: '#/components/schemas/UserUpdateInput' - meta: - $ref: '#/components/schemas/_Meta' - UserDeleteUniqueArgs: - type: object - required: - - where - properties: - select: - $ref: '#/components/schemas/UserSelect' - include: - $ref: '#/components/schemas/UserInclude' - where: - $ref: '#/components/schemas/UserWhereUniqueInput' - meta: - $ref: '#/components/schemas/_Meta' - UserDeleteManyArgs: - type: object - properties: - where: - $ref: '#/components/schemas/UserWhereInput' - meta: - $ref: '#/components/schemas/_Meta' - UserCountArgs: - type: object - properties: - select: - $ref: '#/components/schemas/UserSelect' - where: - $ref: '#/components/schemas/UserWhereInput' - meta: - $ref: '#/components/schemas/_Meta' - UserAggregateArgs: - type: object - properties: - where: - $ref: '#/components/schemas/UserWhereInput' - orderBy: - $ref: '#/components/schemas/UserOrderByWithRelationInput' - cursor: - $ref: '#/components/schemas/UserWhereUniqueInput' - take: - type: integer - skip: - type: integer - _count: - oneOf: - - type: boolean - - $ref: '#/components/schemas/UserCountAggregateInput' - _min: - $ref: '#/components/schemas/UserMinAggregateInput' - _max: - $ref: '#/components/schemas/UserMaxAggregateInput' - meta: - $ref: '#/components/schemas/_Meta' - UserGroupByArgs: - type: object - properties: - where: - $ref: '#/components/schemas/UserWhereInput' - orderBy: - $ref: '#/components/schemas/UserOrderByWithRelationInput' - by: - $ref: '#/components/schemas/UserScalarFieldEnum' - having: - $ref: '#/components/schemas/UserScalarWhereWithAggregatesInput' - take: - type: integer - skip: - type: integer - _count: - oneOf: - - type: boolean - - $ref: '#/components/schemas/UserCountAggregateInput' - _min: - $ref: '#/components/schemas/UserMinAggregateInput' - _max: - $ref: '#/components/schemas/UserMaxAggregateInput' - meta: - $ref: '#/components/schemas/_Meta' - ProfileCreateArgs: - type: object - required: - - data - properties: - select: - $ref: '#/components/schemas/ProfileSelect' - include: - $ref: '#/components/schemas/ProfileInclude' - data: - $ref: '#/components/schemas/ProfileCreateInput' - meta: - $ref: '#/components/schemas/_Meta' - ProfileCreateManyArgs: - type: object - required: - - data - properties: - data: - oneOf: - - $ref: '#/components/schemas/ProfileCreateManyInput' - - type: array - items: - $ref: '#/components/schemas/ProfileCreateManyInput' - skipDuplicates: - type: boolean - description: Do not insert records with unique fields or ID fields that already - exist. - meta: - $ref: '#/components/schemas/_Meta' - ProfileFindUniqueArgs: - type: object - required: - - where - properties: - select: - $ref: '#/components/schemas/ProfileSelect' - include: - $ref: '#/components/schemas/ProfileInclude' - where: - $ref: '#/components/schemas/ProfileWhereUniqueInput' - meta: - $ref: '#/components/schemas/_Meta' - ProfileFindFirstArgs: - type: object - properties: - select: - $ref: '#/components/schemas/ProfileSelect' - include: - $ref: '#/components/schemas/ProfileInclude' - where: - $ref: '#/components/schemas/ProfileWhereInput' - meta: - $ref: '#/components/schemas/_Meta' - ProfileFindManyArgs: - type: object - properties: - select: - $ref: '#/components/schemas/ProfileSelect' - include: - $ref: '#/components/schemas/ProfileInclude' - where: - $ref: '#/components/schemas/ProfileWhereInput' - meta: - $ref: '#/components/schemas/_Meta' - orderBy: - oneOf: - - $ref: '#/components/schemas/ProfileOrderByWithRelationInput' - - type: array - items: - $ref: '#/components/schemas/ProfileOrderByWithRelationInput' - cursor: - $ref: '#/components/schemas/ProfileWhereUniqueInput' - take: - type: integer - skip: - type: integer - ProfileUpdateArgs: - type: object - required: - - where - - data - properties: - select: - $ref: '#/components/schemas/ProfileSelect' - include: - $ref: '#/components/schemas/ProfileInclude' - where: - $ref: '#/components/schemas/ProfileWhereUniqueInput' - data: - $ref: '#/components/schemas/ProfileUpdateInput' - meta: - $ref: '#/components/schemas/_Meta' - ProfileUpdateManyArgs: - type: object - required: - - data - properties: - where: - $ref: '#/components/schemas/ProfileWhereInput' - data: - $ref: '#/components/schemas/ProfileUpdateManyMutationInput' - meta: - $ref: '#/components/schemas/_Meta' - ProfileUpsertArgs: - type: object - required: - - create - - update - - where - properties: - select: - $ref: '#/components/schemas/ProfileSelect' - include: - $ref: '#/components/schemas/ProfileInclude' - where: - $ref: '#/components/schemas/ProfileWhereUniqueInput' - create: - $ref: '#/components/schemas/ProfileCreateInput' - update: - $ref: '#/components/schemas/ProfileUpdateInput' - meta: - $ref: '#/components/schemas/_Meta' - ProfileDeleteUniqueArgs: - type: object - required: - - where - properties: - select: - $ref: '#/components/schemas/ProfileSelect' - include: - $ref: '#/components/schemas/ProfileInclude' - where: - $ref: '#/components/schemas/ProfileWhereUniqueInput' - meta: - $ref: '#/components/schemas/_Meta' - ProfileDeleteManyArgs: - type: object - properties: - where: - $ref: '#/components/schemas/ProfileWhereInput' - meta: - $ref: '#/components/schemas/_Meta' - ProfileCountArgs: - type: object - properties: - select: - $ref: '#/components/schemas/ProfileSelect' - where: - $ref: '#/components/schemas/ProfileWhereInput' - meta: - $ref: '#/components/schemas/_Meta' - ProfileAggregateArgs: - type: object - properties: - where: - $ref: '#/components/schemas/ProfileWhereInput' - orderBy: - $ref: '#/components/schemas/ProfileOrderByWithRelationInput' - cursor: - $ref: '#/components/schemas/ProfileWhereUniqueInput' - take: - type: integer - skip: - type: integer - _count: - oneOf: - - type: boolean - - $ref: '#/components/schemas/ProfileCountAggregateInput' - _min: - $ref: '#/components/schemas/ProfileMinAggregateInput' - _max: - $ref: '#/components/schemas/ProfileMaxAggregateInput' - meta: - $ref: '#/components/schemas/_Meta' - ProfileGroupByArgs: - type: object - properties: - where: - $ref: '#/components/schemas/ProfileWhereInput' - orderBy: - $ref: '#/components/schemas/ProfileOrderByWithRelationInput' - by: - $ref: '#/components/schemas/ProfileScalarFieldEnum' - having: - $ref: '#/components/schemas/ProfileScalarWhereWithAggregatesInput' - take: - type: integer - skip: - type: integer - _count: - oneOf: - - type: boolean - - $ref: '#/components/schemas/ProfileCountAggregateInput' - _min: - $ref: '#/components/schemas/ProfileMinAggregateInput' - _max: - $ref: '#/components/schemas/ProfileMaxAggregateInput' - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemCreateArgs: - type: object - required: - - data - properties: - select: - $ref: '#/components/schemas/Post_ItemSelect' - include: - $ref: '#/components/schemas/Post_ItemInclude' - data: - $ref: '#/components/schemas/Post_ItemCreateInput' - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemCreateManyArgs: - type: object - required: - - data - properties: - data: - oneOf: - - $ref: '#/components/schemas/Post_ItemCreateManyInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemCreateManyInput' - skipDuplicates: - type: boolean - description: Do not insert records with unique fields or ID fields that already - exist. - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemFindUniqueArgs: - type: object - required: - - where - properties: - select: - $ref: '#/components/schemas/Post_ItemSelect' - include: - $ref: '#/components/schemas/Post_ItemInclude' - where: - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemFindFirstArgs: - type: object - properties: - select: - $ref: '#/components/schemas/Post_ItemSelect' - include: - $ref: '#/components/schemas/Post_ItemInclude' - where: - $ref: '#/components/schemas/Post_ItemWhereInput' - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemFindManyArgs: - type: object - properties: - select: - $ref: '#/components/schemas/Post_ItemSelect' - include: - $ref: '#/components/schemas/Post_ItemInclude' - where: - $ref: '#/components/schemas/Post_ItemWhereInput' - meta: - $ref: '#/components/schemas/_Meta' - orderBy: - oneOf: - - $ref: '#/components/schemas/Post_ItemOrderByWithRelationInput' - - type: array - items: - $ref: '#/components/schemas/Post_ItemOrderByWithRelationInput' - cursor: - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - take: - type: integer - skip: - type: integer - Post_ItemUpdateArgs: - type: object - required: - - where - - data - properties: - select: - $ref: '#/components/schemas/Post_ItemSelect' - include: - $ref: '#/components/schemas/Post_ItemInclude' - where: - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - data: - $ref: '#/components/schemas/Post_ItemUpdateInput' - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemUpdateManyArgs: - type: object - required: - - data - properties: - where: - $ref: '#/components/schemas/Post_ItemWhereInput' - data: - $ref: '#/components/schemas/Post_ItemUpdateManyMutationInput' - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemUpsertArgs: - type: object - required: - - create - - update - - where - properties: - select: - $ref: '#/components/schemas/Post_ItemSelect' - include: - $ref: '#/components/schemas/Post_ItemInclude' - where: - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - create: - $ref: '#/components/schemas/Post_ItemCreateInput' - update: - $ref: '#/components/schemas/Post_ItemUpdateInput' - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemDeleteUniqueArgs: - type: object - required: - - where - properties: - select: - $ref: '#/components/schemas/Post_ItemSelect' - include: - $ref: '#/components/schemas/Post_ItemInclude' - where: - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemDeleteManyArgs: - type: object - properties: - where: - $ref: '#/components/schemas/Post_ItemWhereInput' - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemCountArgs: - type: object - properties: - select: - $ref: '#/components/schemas/Post_ItemSelect' - where: - $ref: '#/components/schemas/Post_ItemWhereInput' - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemAggregateArgs: - type: object - properties: - where: - $ref: '#/components/schemas/Post_ItemWhereInput' - orderBy: - $ref: '#/components/schemas/Post_ItemOrderByWithRelationInput' - cursor: - $ref: '#/components/schemas/Post_ItemWhereUniqueInput' - take: - type: integer - skip: - type: integer - meta: - $ref: '#/components/schemas/_Meta' - Post_ItemGroupByArgs: - type: object - properties: - where: - $ref: '#/components/schemas/Post_ItemWhereInput' - orderBy: - $ref: '#/components/schemas/Post_ItemOrderByWithRelationInput' - by: - $ref: '#/components/schemas/Post_ItemScalarFieldEnum' - having: - $ref: '#/components/schemas/Post_ItemScalarWhereWithAggregatesInput' - take: - type: integer - skip: - type: integer - meta: - $ref: '#/components/schemas/_Meta' -paths: - /user/create: - post: - operationId: createUser - description: Create a new User - tags: - - user - responses: - '201': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/User' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/UserCreateArgs' - /user/createMany: - post: - operationId: createManyUser - description: Create several User - tags: - - user - responses: - '201': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BatchPayload' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/UserCreateManyArgs' - /user/findUnique: - get: - operationId: findUniqueUser - description: Find one unique User - tags: - - user - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/User' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/UserFindUniqueArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /user/findFirst: - get: - operationId: findFirstUser - description: Find the first User matching the given condition - tags: - - user - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/User' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/UserFindFirstArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /user/findMany: - get: - operationId: findManyUser - description: Find users matching the given conditions - tags: - - user - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - type: array - items: - $ref: '#/components/schemas/User' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/UserFindManyArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /user/update: - patch: - operationId: updateUser - description: Update a User - tags: - - user - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/User' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/UserUpdateArgs' - /user/updateMany: - patch: - operationId: updateManyUser - description: Update Users matching the given condition - tags: - - user - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BatchPayload' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/UserUpdateManyArgs' - /user/upsert: - post: - operationId: upsertUser - description: Upsert a User - tags: - - user - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/User' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/UserUpsertArgs' - /user/dodelete: - put: - operationId: deleteUser - description: Delete a unique user - tags: - - delete - - user - summary: Delete a user yeah yeah - deprecated: true - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/User' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/UserDeleteUniqueArgs' - /user/deleteMany: - delete: - operationId: deleteManyUser - description: Delete Users matching the given condition - tags: - - user - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BatchPayload' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/UserDeleteManyArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /user/count: - get: - operationId: countUser - description: Find a list of User - tags: - - user - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - oneOf: - - type: integer - - $ref: '#/components/schemas/UserCountAggregateOutputType' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/UserCountArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /user/aggregate: - get: - operationId: aggregateUser - description: Aggregate Users - tags: - - user - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/AggregateUser' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/UserAggregateArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /user/groupBy: - get: - operationId: groupByUser - description: Group Users by fields - tags: - - user - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - type: array - items: - $ref: '#/components/schemas/UserGroupByOutputType' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/UserGroupByArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /profile/create: - post: - operationId: createProfile - description: Create a new Profile - tags: - - profile - responses: - '201': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Profile' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileCreateArgs' - /profile/createMany: - post: - operationId: createManyProfile - description: Create several Profile - tags: - - profile - responses: - '201': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BatchPayload' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileCreateManyArgs' - /profile/findUnique: - get: - operationId: findUniqueProfile - description: Find one unique Profile - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Profile' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileFindUniqueArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /profile/findFirst: - get: - operationId: findFirstProfile - description: Find the first Profile matching the given condition - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Profile' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileFindFirstArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /profile/findMany: - get: - operationId: findManyProfile - description: Find a list of Profile - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - type: array - items: - $ref: '#/components/schemas/Profile' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileFindManyArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /profile/update: - patch: - operationId: updateProfile - description: Update a Profile - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Profile' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileUpdateArgs' - /profile/updateMany: - patch: - operationId: updateManyProfile - description: Update Profiles matching the given condition - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BatchPayload' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileUpdateManyArgs' - /profile/upsert: - post: - operationId: upsertProfile - description: Upsert a Profile - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Profile' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileUpsertArgs' - /profile/delete: - delete: - operationId: deleteProfile - description: Delete one unique Profile - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Profile' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileDeleteUniqueArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /profile/deleteMany: - delete: - operationId: deleteManyProfile - description: Delete Profiles matching the given condition - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BatchPayload' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileDeleteManyArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /profile/count: - get: - operationId: countProfile - description: Find a list of Profile - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - oneOf: - - type: integer - - $ref: '#/components/schemas/ProfileCountAggregateOutputType' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileCountArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /profile/aggregate: - get: - operationId: aggregateProfile - description: Aggregate Profiles - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/AggregateProfile' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileAggregateArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /profile/groupBy: - get: - operationId: groupByProfile - description: Group Profiles by fields - tags: - - profile - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - type: array - items: - $ref: '#/components/schemas/ProfileGroupByOutputType' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/ProfileGroupByArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /post_Item/create: - post: - operationId: createPost_Item - description: Create a new Post_Item - tags: - - post_Item - responses: - '201': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Post_Item' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemCreateArgs' - /post_Item/createMany: - post: - operationId: createManyPost_Item - description: Create several Post_Item - tags: - - post_Item - responses: - '201': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BatchPayload' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemCreateManyArgs' - /post_Item/findUnique: - get: - operationId: findUniquePost_Item - description: Find one unique Post_Item - tags: - - post_Item - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Post_Item' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemFindUniqueArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /post_Item/findFirst: - get: - operationId: findFirstPost_Item - description: Find the first Post_Item matching the given condition - tags: - - post_Item - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Post_Item' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemFindFirstArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /post_Item/update: - patch: - operationId: updatePost_Item - description: Update a Post_Item - tags: - - post_Item - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Post_Item' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemUpdateArgs' - /post_Item/updateMany: - patch: - operationId: updateManyPost_Item - description: Update Post_Items matching the given condition - tags: - - post_Item - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BatchPayload' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemUpdateManyArgs' - /post_Item/upsert: - post: - operationId: upsertPost_Item - description: Upsert a Post_Item - tags: - - post_Item - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Post_Item' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemUpsertArgs' - /post_Item/delete: - delete: - operationId: deletePost_Item - description: Delete one unique Post_Item - tags: - - post_Item - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Post_Item' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemDeleteUniqueArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /post_Item/deleteMany: - delete: - operationId: deleteManyPost_Item - description: Delete Post_Items matching the given condition - tags: - - post_Item - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BatchPayload' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemDeleteManyArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /post_Item/count: - get: - operationId: countPost_Item - description: Find a list of Post_Item - tags: - - post_Item - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - oneOf: - - type: integer - - $ref: '#/components/schemas/Post_ItemCountAggregateOutputType' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemCountArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /post_Item/aggregate: - get: - operationId: aggregatePost_Item - description: Aggregate Post_Items - tags: - - post_Item - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/AggregatePost_Item' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemAggregateArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /post_Item/groupBy: - get: - operationId: groupByPost_Item - description: Group Post_Items by fields - tags: - - post_Item - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - type: array - items: - $ref: '#/components/schemas/Post_ItemGroupByOutputType' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/Post_ItemGroupByArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} diff --git a/packages/server/test/openapi/migrated/baseline/rpc-type-coverage-3.1.0.baseline.yaml b/packages/server/test/openapi/migrated/baseline/rpc-type-coverage-3.1.0.baseline.yaml deleted file mode 100644 index 5f3e59136..000000000 --- a/packages/server/test/openapi/migrated/baseline/rpc-type-coverage-3.1.0.baseline.yaml +++ /dev/null @@ -1,3174 +0,0 @@ -openapi: 3.1.0 -info: - title: ZenStack Generated API - version: 1.0.0 -tags: - - name: foo - description: Foo operations -components: - schemas: - FooScalarFieldEnum: - type: string - enum: - - id - - string - - int - - bigInt - - date - - float - - decimal - - boolean - - bytes - - json - - plainJson - SortOrder: - type: string - enum: - - asc - - desc - NullableJsonNullValueInput: - type: string - enum: - - DbNull - - JsonNull - JsonNullValueInput: - type: string - enum: - - JsonNull - QueryMode: - type: string - enum: - - default - - insensitive - JsonNullValueFilter: - type: string - enum: - - DbNull - - JsonNull - - AnyNull - NullsOrder: - type: string - enum: - - first - - last - Foo: - type: object - properties: - id: - type: string - string: - type: string - int: - type: integer - bigInt: - type: integer - date: - type: string - format: date-time - float: - type: number - decimal: - oneOf: - - type: string - - type: number - boolean: - type: boolean - bytes: - oneOf: - - type: 'null' - - type: string - format: byte - json: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/Meta' - plainJson: {} - required: - - id - - string - - int - - bigInt - - date - - float - - decimal - - boolean - - plainJson - Meta: - type: object - description: The "Meta" TypeDef - properties: - something: - type: string - required: - - something - FooWhereInput: - type: object - properties: - AND: - oneOf: - - $ref: '#/components/schemas/FooWhereInput' - - type: array - items: - $ref: '#/components/schemas/FooWhereInput' - OR: - type: array - items: - $ref: '#/components/schemas/FooWhereInput' - NOT: - oneOf: - - $ref: '#/components/schemas/FooWhereInput' - - type: array - items: - $ref: '#/components/schemas/FooWhereInput' - id: - oneOf: - - $ref: '#/components/schemas/StringFilter' - - type: string - string: - oneOf: - - $ref: '#/components/schemas/StringFilter' - - type: string - int: - oneOf: - - $ref: '#/components/schemas/IntFilter' - - type: integer - bigInt: - oneOf: - - $ref: '#/components/schemas/BigIntFilter' - - type: integer - date: - oneOf: - - $ref: '#/components/schemas/DateTimeFilter' - - type: string - format: date-time - float: - oneOf: - - $ref: '#/components/schemas/FloatFilter' - - type: number - decimal: - oneOf: - - $ref: '#/components/schemas/DecimalFilter' - - oneOf: - - type: string - - type: number - boolean: - oneOf: - - $ref: '#/components/schemas/BoolFilter' - - type: boolean - bytes: - oneOf: - - $ref: '#/components/schemas/BytesNullableFilter' - - type: string - format: byte - - type: 'null' - json: - $ref: '#/components/schemas/JsonNullableFilter' - plainJson: - $ref: '#/components/schemas/JsonFilter' - FooOrderByWithRelationInput: - type: object - properties: - id: - $ref: '#/components/schemas/SortOrder' - string: - $ref: '#/components/schemas/SortOrder' - int: - $ref: '#/components/schemas/SortOrder' - bigInt: - $ref: '#/components/schemas/SortOrder' - date: - $ref: '#/components/schemas/SortOrder' - float: - $ref: '#/components/schemas/SortOrder' - decimal: - $ref: '#/components/schemas/SortOrder' - boolean: - $ref: '#/components/schemas/SortOrder' - bytes: - oneOf: - - $ref: '#/components/schemas/SortOrder' - - $ref: '#/components/schemas/SortOrderInput' - json: - oneOf: - - $ref: '#/components/schemas/SortOrder' - - $ref: '#/components/schemas/SortOrderInput' - plainJson: - $ref: '#/components/schemas/SortOrder' - FooWhereUniqueInput: - type: object - properties: - id: - type: string - AND: - oneOf: - - $ref: '#/components/schemas/FooWhereInput' - - type: array - items: - $ref: '#/components/schemas/FooWhereInput' - OR: - type: array - items: - $ref: '#/components/schemas/FooWhereInput' - NOT: - oneOf: - - $ref: '#/components/schemas/FooWhereInput' - - type: array - items: - $ref: '#/components/schemas/FooWhereInput' - string: - oneOf: - - $ref: '#/components/schemas/StringFilter' - - type: string - int: - oneOf: - - $ref: '#/components/schemas/IntFilter' - - type: integer - bigInt: - oneOf: - - $ref: '#/components/schemas/BigIntFilter' - - type: integer - date: - oneOf: - - $ref: '#/components/schemas/DateTimeFilter' - - type: string - format: date-time - float: - oneOf: - - $ref: '#/components/schemas/FloatFilter' - - type: number - decimal: - oneOf: - - $ref: '#/components/schemas/DecimalFilter' - - oneOf: - - type: string - - type: number - boolean: - oneOf: - - $ref: '#/components/schemas/BoolFilter' - - type: boolean - bytes: - oneOf: - - $ref: '#/components/schemas/BytesNullableFilter' - - type: string - format: byte - - type: 'null' - json: - $ref: '#/components/schemas/JsonNullableFilter' - plainJson: - $ref: '#/components/schemas/JsonFilter' - FooScalarWhereWithAggregatesInput: - type: object - properties: - AND: - oneOf: - - $ref: '#/components/schemas/FooScalarWhereWithAggregatesInput' - - type: array - items: - $ref: '#/components/schemas/FooScalarWhereWithAggregatesInput' - OR: - type: array - items: - $ref: '#/components/schemas/FooScalarWhereWithAggregatesInput' - NOT: - oneOf: - - $ref: '#/components/schemas/FooScalarWhereWithAggregatesInput' - - type: array - items: - $ref: '#/components/schemas/FooScalarWhereWithAggregatesInput' - id: - oneOf: - - $ref: '#/components/schemas/StringWithAggregatesFilter' - - type: string - string: - oneOf: - - $ref: '#/components/schemas/StringWithAggregatesFilter' - - type: string - int: - oneOf: - - $ref: '#/components/schemas/IntWithAggregatesFilter' - - type: integer - bigInt: - oneOf: - - $ref: '#/components/schemas/BigIntWithAggregatesFilter' - - type: integer - date: - oneOf: - - $ref: '#/components/schemas/DateTimeWithAggregatesFilter' - - type: string - format: date-time - float: - oneOf: - - $ref: '#/components/schemas/FloatWithAggregatesFilter' - - type: number - decimal: - oneOf: - - $ref: '#/components/schemas/DecimalWithAggregatesFilter' - - oneOf: - - type: string - - type: number - boolean: - oneOf: - - $ref: '#/components/schemas/BoolWithAggregatesFilter' - - type: boolean - bytes: - oneOf: - - $ref: '#/components/schemas/BytesNullableWithAggregatesFilter' - - type: string - format: byte - - type: 'null' - json: - $ref: '#/components/schemas/JsonNullableWithAggregatesFilter' - plainJson: - $ref: '#/components/schemas/JsonWithAggregatesFilter' - FooCreateInput: - type: object - properties: - id: - type: string - string: - type: string - int: - type: integer - bigInt: - type: integer - date: - type: string - format: date-time - float: - type: number - decimal: - oneOf: - - type: string - - type: number - boolean: - type: boolean - bytes: - oneOf: - - type: 'null' - - type: string - format: byte - json: - oneOf: - - $ref: '#/components/schemas/NullableJsonNullValueInput' - - {} - plainJson: - oneOf: - - $ref: '#/components/schemas/JsonNullValueInput' - - {} - required: - - string - - int - - bigInt - - date - - float - - decimal - - boolean - - plainJson - FooUpdateInput: - type: object - properties: - id: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - string: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - int: - oneOf: - - type: integer - - $ref: '#/components/schemas/IntFieldUpdateOperationsInput' - bigInt: - oneOf: - - type: integer - - $ref: '#/components/schemas/BigIntFieldUpdateOperationsInput' - date: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - float: - oneOf: - - type: number - - $ref: '#/components/schemas/FloatFieldUpdateOperationsInput' - decimal: - oneOf: - - oneOf: - - type: string - - type: number - - $ref: '#/components/schemas/DecimalFieldUpdateOperationsInput' - boolean: - oneOf: - - type: boolean - - $ref: '#/components/schemas/BoolFieldUpdateOperationsInput' - bytes: - oneOf: - - type: string - format: byte - - $ref: '#/components/schemas/NullableBytesFieldUpdateOperationsInput' - - type: 'null' - json: - oneOf: - - $ref: '#/components/schemas/NullableJsonNullValueInput' - - {} - plainJson: - oneOf: - - $ref: '#/components/schemas/JsonNullValueInput' - - {} - FooCreateManyInput: - type: object - properties: - id: - type: string - string: - type: string - int: - type: integer - bigInt: - type: integer - date: - type: string - format: date-time - float: - type: number - decimal: - oneOf: - - type: string - - type: number - boolean: - type: boolean - bytes: - oneOf: - - type: 'null' - - type: string - format: byte - json: - oneOf: - - $ref: '#/components/schemas/NullableJsonNullValueInput' - - {} - plainJson: - oneOf: - - $ref: '#/components/schemas/JsonNullValueInput' - - {} - required: - - string - - int - - bigInt - - date - - float - - decimal - - boolean - - plainJson - FooUpdateManyMutationInput: - type: object - properties: - id: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - string: - oneOf: - - type: string - - $ref: '#/components/schemas/StringFieldUpdateOperationsInput' - int: - oneOf: - - type: integer - - $ref: '#/components/schemas/IntFieldUpdateOperationsInput' - bigInt: - oneOf: - - type: integer - - $ref: '#/components/schemas/BigIntFieldUpdateOperationsInput' - date: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/DateTimeFieldUpdateOperationsInput' - float: - oneOf: - - type: number - - $ref: '#/components/schemas/FloatFieldUpdateOperationsInput' - decimal: - oneOf: - - oneOf: - - type: string - - type: number - - $ref: '#/components/schemas/DecimalFieldUpdateOperationsInput' - boolean: - oneOf: - - type: boolean - - $ref: '#/components/schemas/BoolFieldUpdateOperationsInput' - bytes: - oneOf: - - type: string - format: byte - - $ref: '#/components/schemas/NullableBytesFieldUpdateOperationsInput' - - type: 'null' - json: - oneOf: - - $ref: '#/components/schemas/NullableJsonNullValueInput' - - {} - plainJson: - oneOf: - - $ref: '#/components/schemas/JsonNullValueInput' - - {} - StringFilter: - type: object - properties: - equals: - type: string - in: - type: array - items: - type: string - notIn: - type: array - items: - type: string - lt: - type: string - lte: - type: string - gt: - type: string - gte: - type: string - contains: - type: string - startsWith: - type: string - endsWith: - type: string - mode: - $ref: '#/components/schemas/QueryMode' - not: - oneOf: - - type: string - - $ref: '#/components/schemas/NestedStringFilter' - IntFilter: - type: object - properties: - equals: - type: integer - in: - type: array - items: - type: integer - notIn: - type: array - items: - type: integer - lt: - type: integer - lte: - type: integer - gt: - type: integer - gte: - type: integer - not: - oneOf: - - type: integer - - $ref: '#/components/schemas/NestedIntFilter' - BigIntFilter: - type: object - properties: - equals: - type: integer - in: - type: array - items: - type: integer - notIn: - type: array - items: - type: integer - lt: - type: integer - lte: - type: integer - gt: - type: integer - gte: - type: integer - not: - oneOf: - - type: integer - - $ref: '#/components/schemas/NestedBigIntFilter' - DateTimeFilter: - type: object - properties: - equals: - type: string - format: date-time - in: - type: array - items: - type: string - format: date-time - notIn: - type: array - items: - type: string - format: date-time - lt: - type: string - format: date-time - lte: - type: string - format: date-time - gt: - type: string - format: date-time - gte: - type: string - format: date-time - not: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/NestedDateTimeFilter' - FloatFilter: - type: object - properties: - equals: - type: number - in: - type: array - items: - type: number - notIn: - type: array - items: - type: number - lt: - type: number - lte: - type: number - gt: - type: number - gte: - type: number - not: - oneOf: - - type: number - - $ref: '#/components/schemas/NestedFloatFilter' - DecimalFilter: - type: object - properties: - equals: - oneOf: - - type: string - - type: number - in: - type: array - items: - oneOf: - - type: string - - type: number - notIn: - type: array - items: - oneOf: - - type: string - - type: number - lt: - oneOf: - - type: string - - type: number - lte: - oneOf: - - type: string - - type: number - gt: - oneOf: - - type: string - - type: number - gte: - oneOf: - - type: string - - type: number - not: - oneOf: - - oneOf: - - type: string - - type: number - - $ref: '#/components/schemas/NestedDecimalFilter' - BoolFilter: - type: object - properties: - equals: - type: boolean - not: - oneOf: - - type: boolean - - $ref: '#/components/schemas/NestedBoolFilter' - BytesNullableFilter: - type: object - properties: - equals: - oneOf: - - type: 'null' - - type: string - format: byte - in: - oneOf: - - type: 'null' - - type: array - items: - type: string - format: byte - notIn: - oneOf: - - type: 'null' - - type: array - items: - type: string - format: byte - not: - oneOf: - - type: string - format: byte - - $ref: '#/components/schemas/NestedBytesNullableFilter' - - type: 'null' - JsonNullableFilter: - type: object - properties: - equals: - oneOf: - - {} - - $ref: '#/components/schemas/JsonNullValueFilter' - path: - type: array - items: - type: string - mode: - $ref: '#/components/schemas/QueryMode' - string_contains: - type: string - string_starts_with: - type: string - string_ends_with: - type: string - array_starts_with: - oneOf: - - type: 'null' - - {} - array_ends_with: - oneOf: - - type: 'null' - - {} - array_contains: - oneOf: - - type: 'null' - - {} - lt: {} - lte: {} - gt: {} - gte: {} - not: - oneOf: - - {} - - $ref: '#/components/schemas/JsonNullValueFilter' - JsonFilter: - type: object - properties: - equals: - oneOf: - - {} - - $ref: '#/components/schemas/JsonNullValueFilter' - path: - type: array - items: - type: string - mode: - $ref: '#/components/schemas/QueryMode' - string_contains: - type: string - string_starts_with: - type: string - string_ends_with: - type: string - array_starts_with: - oneOf: - - type: 'null' - - {} - array_ends_with: - oneOf: - - type: 'null' - - {} - array_contains: - oneOf: - - type: 'null' - - {} - lt: {} - lte: {} - gt: {} - gte: {} - not: - oneOf: - - {} - - $ref: '#/components/schemas/JsonNullValueFilter' - SortOrderInput: - type: object - properties: - sort: - $ref: '#/components/schemas/SortOrder' - nulls: - $ref: '#/components/schemas/NullsOrder' - required: - - sort - StringWithAggregatesFilter: - type: object - properties: - equals: - type: string - in: - type: array - items: - type: string - notIn: - type: array - items: - type: string - lt: - type: string - lte: - type: string - gt: - type: string - gte: - type: string - contains: - type: string - startsWith: - type: string - endsWith: - type: string - mode: - $ref: '#/components/schemas/QueryMode' - not: - oneOf: - - type: string - - $ref: '#/components/schemas/NestedStringWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _min: - $ref: '#/components/schemas/NestedStringFilter' - _max: - $ref: '#/components/schemas/NestedStringFilter' - IntWithAggregatesFilter: - type: object - properties: - equals: - type: integer - in: - type: array - items: - type: integer - notIn: - type: array - items: - type: integer - lt: - type: integer - lte: - type: integer - gt: - type: integer - gte: - type: integer - not: - oneOf: - - type: integer - - $ref: '#/components/schemas/NestedIntWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _avg: - $ref: '#/components/schemas/NestedFloatFilter' - _sum: - $ref: '#/components/schemas/NestedIntFilter' - _min: - $ref: '#/components/schemas/NestedIntFilter' - _max: - $ref: '#/components/schemas/NestedIntFilter' - BigIntWithAggregatesFilter: - type: object - properties: - equals: - type: integer - in: - type: array - items: - type: integer - notIn: - type: array - items: - type: integer - lt: - type: integer - lte: - type: integer - gt: - type: integer - gte: - type: integer - not: - oneOf: - - type: integer - - $ref: '#/components/schemas/NestedBigIntWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _avg: - $ref: '#/components/schemas/NestedFloatFilter' - _sum: - $ref: '#/components/schemas/NestedBigIntFilter' - _min: - $ref: '#/components/schemas/NestedBigIntFilter' - _max: - $ref: '#/components/schemas/NestedBigIntFilter' - DateTimeWithAggregatesFilter: - type: object - properties: - equals: - type: string - format: date-time - in: - type: array - items: - type: string - format: date-time - notIn: - type: array - items: - type: string - format: date-time - lt: - type: string - format: date-time - lte: - type: string - format: date-time - gt: - type: string - format: date-time - gte: - type: string - format: date-time - not: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/NestedDateTimeWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _min: - $ref: '#/components/schemas/NestedDateTimeFilter' - _max: - $ref: '#/components/schemas/NestedDateTimeFilter' - FloatWithAggregatesFilter: - type: object - properties: - equals: - type: number - in: - type: array - items: - type: number - notIn: - type: array - items: - type: number - lt: - type: number - lte: - type: number - gt: - type: number - gte: - type: number - not: - oneOf: - - type: number - - $ref: '#/components/schemas/NestedFloatWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _avg: - $ref: '#/components/schemas/NestedFloatFilter' - _sum: - $ref: '#/components/schemas/NestedFloatFilter' - _min: - $ref: '#/components/schemas/NestedFloatFilter' - _max: - $ref: '#/components/schemas/NestedFloatFilter' - DecimalWithAggregatesFilter: - type: object - properties: - equals: - oneOf: - - type: string - - type: number - in: - type: array - items: - oneOf: - - type: string - - type: number - notIn: - type: array - items: - oneOf: - - type: string - - type: number - lt: - oneOf: - - type: string - - type: number - lte: - oneOf: - - type: string - - type: number - gt: - oneOf: - - type: string - - type: number - gte: - oneOf: - - type: string - - type: number - not: - oneOf: - - oneOf: - - type: string - - type: number - - $ref: '#/components/schemas/NestedDecimalWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _avg: - $ref: '#/components/schemas/NestedDecimalFilter' - _sum: - $ref: '#/components/schemas/NestedDecimalFilter' - _min: - $ref: '#/components/schemas/NestedDecimalFilter' - _max: - $ref: '#/components/schemas/NestedDecimalFilter' - BoolWithAggregatesFilter: - type: object - properties: - equals: - type: boolean - not: - oneOf: - - type: boolean - - $ref: '#/components/schemas/NestedBoolWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _min: - $ref: '#/components/schemas/NestedBoolFilter' - _max: - $ref: '#/components/schemas/NestedBoolFilter' - BytesNullableWithAggregatesFilter: - type: object - properties: - equals: - oneOf: - - type: 'null' - - type: string - format: byte - in: - oneOf: - - type: 'null' - - type: array - items: - type: string - format: byte - notIn: - oneOf: - - type: 'null' - - type: array - items: - type: string - format: byte - not: - oneOf: - - type: string - format: byte - - $ref: '#/components/schemas/NestedBytesNullableWithAggregatesFilter' - - type: 'null' - _count: - $ref: '#/components/schemas/NestedIntNullableFilter' - _min: - $ref: '#/components/schemas/NestedBytesNullableFilter' - _max: - $ref: '#/components/schemas/NestedBytesNullableFilter' - JsonNullableWithAggregatesFilter: - type: object - properties: - equals: - oneOf: - - {} - - $ref: '#/components/schemas/JsonNullValueFilter' - path: - type: array - items: - type: string - mode: - $ref: '#/components/schemas/QueryMode' - string_contains: - type: string - string_starts_with: - type: string - string_ends_with: - type: string - array_starts_with: - oneOf: - - type: 'null' - - {} - array_ends_with: - oneOf: - - type: 'null' - - {} - array_contains: - oneOf: - - type: 'null' - - {} - lt: {} - lte: {} - gt: {} - gte: {} - not: - oneOf: - - {} - - $ref: '#/components/schemas/JsonNullValueFilter' - _count: - $ref: '#/components/schemas/NestedIntNullableFilter' - _min: - $ref: '#/components/schemas/NestedJsonNullableFilter' - _max: - $ref: '#/components/schemas/NestedJsonNullableFilter' - JsonWithAggregatesFilter: - type: object - properties: - equals: - oneOf: - - {} - - $ref: '#/components/schemas/JsonNullValueFilter' - path: - type: array - items: - type: string - mode: - $ref: '#/components/schemas/QueryMode' - string_contains: - type: string - string_starts_with: - type: string - string_ends_with: - type: string - array_starts_with: - oneOf: - - type: 'null' - - {} - array_ends_with: - oneOf: - - type: 'null' - - {} - array_contains: - oneOf: - - type: 'null' - - {} - lt: {} - lte: {} - gt: {} - gte: {} - not: - oneOf: - - {} - - $ref: '#/components/schemas/JsonNullValueFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _min: - $ref: '#/components/schemas/NestedJsonFilter' - _max: - $ref: '#/components/schemas/NestedJsonFilter' - StringFieldUpdateOperationsInput: - type: object - properties: - set: - type: string - IntFieldUpdateOperationsInput: - type: object - properties: - set: - type: integer - increment: - type: integer - decrement: - type: integer - multiply: - type: integer - divide: - type: integer - BigIntFieldUpdateOperationsInput: - type: object - properties: - set: - type: integer - increment: - type: integer - decrement: - type: integer - multiply: - type: integer - divide: - type: integer - DateTimeFieldUpdateOperationsInput: - type: object - properties: - set: - type: string - format: date-time - FloatFieldUpdateOperationsInput: - type: object - properties: - set: - type: number - increment: - type: number - decrement: - type: number - multiply: - type: number - divide: - type: number - DecimalFieldUpdateOperationsInput: - type: object - properties: - set: - oneOf: - - type: string - - type: number - increment: - oneOf: - - type: string - - type: number - decrement: - oneOf: - - type: string - - type: number - multiply: - oneOf: - - type: string - - type: number - divide: - oneOf: - - type: string - - type: number - BoolFieldUpdateOperationsInput: - type: object - properties: - set: - type: boolean - NullableBytesFieldUpdateOperationsInput: - type: object - properties: - set: - oneOf: - - type: 'null' - - type: string - format: byte - NestedStringFilter: - type: object - properties: - equals: - type: string - in: - type: array - items: - type: string - notIn: - type: array - items: - type: string - lt: - type: string - lte: - type: string - gt: - type: string - gte: - type: string - contains: - type: string - startsWith: - type: string - endsWith: - type: string - not: - oneOf: - - type: string - - $ref: '#/components/schemas/NestedStringFilter' - NestedIntFilter: - type: object - properties: - equals: - type: integer - in: - type: array - items: - type: integer - notIn: - type: array - items: - type: integer - lt: - type: integer - lte: - type: integer - gt: - type: integer - gte: - type: integer - not: - oneOf: - - type: integer - - $ref: '#/components/schemas/NestedIntFilter' - NestedBigIntFilter: - type: object - properties: - equals: - type: integer - in: - type: array - items: - type: integer - notIn: - type: array - items: - type: integer - lt: - type: integer - lte: - type: integer - gt: - type: integer - gte: - type: integer - not: - oneOf: - - type: integer - - $ref: '#/components/schemas/NestedBigIntFilter' - NestedDateTimeFilter: - type: object - properties: - equals: - type: string - format: date-time - in: - type: array - items: - type: string - format: date-time - notIn: - type: array - items: - type: string - format: date-time - lt: - type: string - format: date-time - lte: - type: string - format: date-time - gt: - type: string - format: date-time - gte: - type: string - format: date-time - not: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/NestedDateTimeFilter' - NestedFloatFilter: - type: object - properties: - equals: - type: number - in: - type: array - items: - type: number - notIn: - type: array - items: - type: number - lt: - type: number - lte: - type: number - gt: - type: number - gte: - type: number - not: - oneOf: - - type: number - - $ref: '#/components/schemas/NestedFloatFilter' - NestedDecimalFilter: - type: object - properties: - equals: - oneOf: - - type: string - - type: number - in: - type: array - items: - oneOf: - - type: string - - type: number - notIn: - type: array - items: - oneOf: - - type: string - - type: number - lt: - oneOf: - - type: string - - type: number - lte: - oneOf: - - type: string - - type: number - gt: - oneOf: - - type: string - - type: number - gte: - oneOf: - - type: string - - type: number - not: - oneOf: - - oneOf: - - type: string - - type: number - - $ref: '#/components/schemas/NestedDecimalFilter' - NestedBoolFilter: - type: object - properties: - equals: - type: boolean - not: - oneOf: - - type: boolean - - $ref: '#/components/schemas/NestedBoolFilter' - NestedBytesNullableFilter: - type: object - properties: - equals: - oneOf: - - type: 'null' - - type: string - format: byte - in: - oneOf: - - type: 'null' - - type: array - items: - type: string - format: byte - notIn: - oneOf: - - type: 'null' - - type: array - items: - type: string - format: byte - not: - oneOf: - - type: string - format: byte - - $ref: '#/components/schemas/NestedBytesNullableFilter' - - type: 'null' - NestedStringWithAggregatesFilter: - type: object - properties: - equals: - type: string - in: - type: array - items: - type: string - notIn: - type: array - items: - type: string - lt: - type: string - lte: - type: string - gt: - type: string - gte: - type: string - contains: - type: string - startsWith: - type: string - endsWith: - type: string - not: - oneOf: - - type: string - - $ref: '#/components/schemas/NestedStringWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _min: - $ref: '#/components/schemas/NestedStringFilter' - _max: - $ref: '#/components/schemas/NestedStringFilter' - NestedIntWithAggregatesFilter: - type: object - properties: - equals: - type: integer - in: - type: array - items: - type: integer - notIn: - type: array - items: - type: integer - lt: - type: integer - lte: - type: integer - gt: - type: integer - gte: - type: integer - not: - oneOf: - - type: integer - - $ref: '#/components/schemas/NestedIntWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _avg: - $ref: '#/components/schemas/NestedFloatFilter' - _sum: - $ref: '#/components/schemas/NestedIntFilter' - _min: - $ref: '#/components/schemas/NestedIntFilter' - _max: - $ref: '#/components/schemas/NestedIntFilter' - NestedBigIntWithAggregatesFilter: - type: object - properties: - equals: - type: integer - in: - type: array - items: - type: integer - notIn: - type: array - items: - type: integer - lt: - type: integer - lte: - type: integer - gt: - type: integer - gte: - type: integer - not: - oneOf: - - type: integer - - $ref: '#/components/schemas/NestedBigIntWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _avg: - $ref: '#/components/schemas/NestedFloatFilter' - _sum: - $ref: '#/components/schemas/NestedBigIntFilter' - _min: - $ref: '#/components/schemas/NestedBigIntFilter' - _max: - $ref: '#/components/schemas/NestedBigIntFilter' - NestedDateTimeWithAggregatesFilter: - type: object - properties: - equals: - type: string - format: date-time - in: - type: array - items: - type: string - format: date-time - notIn: - type: array - items: - type: string - format: date-time - lt: - type: string - format: date-time - lte: - type: string - format: date-time - gt: - type: string - format: date-time - gte: - type: string - format: date-time - not: - oneOf: - - type: string - format: date-time - - $ref: '#/components/schemas/NestedDateTimeWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _min: - $ref: '#/components/schemas/NestedDateTimeFilter' - _max: - $ref: '#/components/schemas/NestedDateTimeFilter' - NestedFloatWithAggregatesFilter: - type: object - properties: - equals: - type: number - in: - type: array - items: - type: number - notIn: - type: array - items: - type: number - lt: - type: number - lte: - type: number - gt: - type: number - gte: - type: number - not: - oneOf: - - type: number - - $ref: '#/components/schemas/NestedFloatWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _avg: - $ref: '#/components/schemas/NestedFloatFilter' - _sum: - $ref: '#/components/schemas/NestedFloatFilter' - _min: - $ref: '#/components/schemas/NestedFloatFilter' - _max: - $ref: '#/components/schemas/NestedFloatFilter' - NestedDecimalWithAggregatesFilter: - type: object - properties: - equals: - oneOf: - - type: string - - type: number - in: - type: array - items: - oneOf: - - type: string - - type: number - notIn: - type: array - items: - oneOf: - - type: string - - type: number - lt: - oneOf: - - type: string - - type: number - lte: - oneOf: - - type: string - - type: number - gt: - oneOf: - - type: string - - type: number - gte: - oneOf: - - type: string - - type: number - not: - oneOf: - - oneOf: - - type: string - - type: number - - $ref: '#/components/schemas/NestedDecimalWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _avg: - $ref: '#/components/schemas/NestedDecimalFilter' - _sum: - $ref: '#/components/schemas/NestedDecimalFilter' - _min: - $ref: '#/components/schemas/NestedDecimalFilter' - _max: - $ref: '#/components/schemas/NestedDecimalFilter' - NestedBoolWithAggregatesFilter: - type: object - properties: - equals: - type: boolean - not: - oneOf: - - type: boolean - - $ref: '#/components/schemas/NestedBoolWithAggregatesFilter' - _count: - $ref: '#/components/schemas/NestedIntFilter' - _min: - $ref: '#/components/schemas/NestedBoolFilter' - _max: - $ref: '#/components/schemas/NestedBoolFilter' - NestedBytesNullableWithAggregatesFilter: - type: object - properties: - equals: - oneOf: - - type: 'null' - - type: string - format: byte - in: - oneOf: - - type: 'null' - - type: array - items: - type: string - format: byte - notIn: - oneOf: - - type: 'null' - - type: array - items: - type: string - format: byte - not: - oneOf: - - type: string - format: byte - - $ref: '#/components/schemas/NestedBytesNullableWithAggregatesFilter' - - type: 'null' - _count: - $ref: '#/components/schemas/NestedIntNullableFilter' - _min: - $ref: '#/components/schemas/NestedBytesNullableFilter' - _max: - $ref: '#/components/schemas/NestedBytesNullableFilter' - NestedIntNullableFilter: - type: object - properties: - equals: - oneOf: - - type: 'null' - - type: integer - in: - oneOf: - - type: 'null' - - type: array - items: - type: integer - notIn: - oneOf: - - type: 'null' - - type: array - items: - type: integer - lt: - type: integer - lte: - type: integer - gt: - type: integer - gte: - type: integer - not: - oneOf: - - type: integer - - $ref: '#/components/schemas/NestedIntNullableFilter' - - type: 'null' - NestedJsonNullableFilter: - type: object - properties: - equals: - oneOf: - - {} - - $ref: '#/components/schemas/JsonNullValueFilter' - path: - type: array - items: - type: string - mode: - $ref: '#/components/schemas/QueryMode' - string_contains: - type: string - string_starts_with: - type: string - string_ends_with: - type: string - array_starts_with: - oneOf: - - type: 'null' - - {} - array_ends_with: - oneOf: - - type: 'null' - - {} - array_contains: - oneOf: - - type: 'null' - - {} - lt: {} - lte: {} - gt: {} - gte: {} - not: - oneOf: - - {} - - $ref: '#/components/schemas/JsonNullValueFilter' - NestedJsonFilter: - type: object - properties: - equals: - oneOf: - - {} - - $ref: '#/components/schemas/JsonNullValueFilter' - path: - type: array - items: - type: string - mode: - $ref: '#/components/schemas/QueryMode' - string_contains: - type: string - string_starts_with: - type: string - string_ends_with: - type: string - array_starts_with: - oneOf: - - type: 'null' - - {} - array_ends_with: - oneOf: - - type: 'null' - - {} - array_contains: - oneOf: - - type: 'null' - - {} - lt: {} - lte: {} - gt: {} - gte: {} - not: - oneOf: - - {} - - $ref: '#/components/schemas/JsonNullValueFilter' - FooSelect: - type: object - properties: - id: - type: boolean - string: - type: boolean - int: - type: boolean - bigInt: - type: boolean - date: - type: boolean - float: - type: boolean - decimal: - type: boolean - boolean: - type: boolean - bytes: - type: boolean - json: - type: boolean - plainJson: - type: boolean - FooCountAggregateInput: - type: object - properties: - id: - type: boolean - string: - type: boolean - int: - type: boolean - bigInt: - type: boolean - date: - type: boolean - float: - type: boolean - decimal: - type: boolean - boolean: - type: boolean - bytes: - type: boolean - json: - type: boolean - plainJson: - type: boolean - _all: - type: boolean - FooAvgAggregateInput: - type: object - properties: - int: - type: boolean - bigInt: - type: boolean - float: - type: boolean - decimal: - type: boolean - FooSumAggregateInput: - type: object - properties: - int: - type: boolean - bigInt: - type: boolean - float: - type: boolean - decimal: - type: boolean - FooMinAggregateInput: - type: object - properties: - id: - type: boolean - string: - type: boolean - int: - type: boolean - bigInt: - type: boolean - date: - type: boolean - float: - type: boolean - decimal: - type: boolean - boolean: - type: boolean - bytes: - type: boolean - FooMaxAggregateInput: - type: object - properties: - id: - type: boolean - string: - type: boolean - int: - type: boolean - bigInt: - type: boolean - date: - type: boolean - float: - type: boolean - decimal: - type: boolean - boolean: - type: boolean - bytes: - type: boolean - AggregateFoo: - type: object - properties: - _count: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/FooCountAggregateOutputType' - _avg: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/FooAvgAggregateOutputType' - _sum: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/FooSumAggregateOutputType' - _min: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/FooMinAggregateOutputType' - _max: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/FooMaxAggregateOutputType' - FooGroupByOutputType: - type: object - properties: - id: - type: string - string: - type: string - int: - type: integer - bigInt: - type: integer - date: - type: string - format: date-time - float: - type: number - decimal: - oneOf: - - type: string - - type: number - boolean: - type: boolean - bytes: - oneOf: - - type: 'null' - - type: string - format: byte - json: - oneOf: - - type: 'null' - - {} - plainJson: {} - _count: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/FooCountAggregateOutputType' - _avg: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/FooAvgAggregateOutputType' - _sum: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/FooSumAggregateOutputType' - _min: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/FooMinAggregateOutputType' - _max: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/FooMaxAggregateOutputType' - required: - - id - - string - - int - - bigInt - - date - - float - - decimal - - boolean - - plainJson - FooCountAggregateOutputType: - type: object - properties: - id: - type: integer - string: - type: integer - int: - type: integer - bigInt: - type: integer - date: - type: integer - float: - type: integer - decimal: - type: integer - boolean: - type: integer - bytes: - type: integer - json: - type: integer - plainJson: - type: integer - _all: - type: integer - required: - - id - - string - - int - - bigInt - - date - - float - - decimal - - boolean - - bytes - - json - - plainJson - - _all - FooAvgAggregateOutputType: - type: object - properties: - int: - oneOf: - - type: 'null' - - type: number - bigInt: - oneOf: - - type: 'null' - - type: number - float: - oneOf: - - type: 'null' - - type: number - decimal: - oneOf: - - type: string - - type: number - - type: 'null' - FooSumAggregateOutputType: - type: object - properties: - int: - oneOf: - - type: 'null' - - type: integer - bigInt: - oneOf: - - type: 'null' - - type: integer - float: - oneOf: - - type: 'null' - - type: number - decimal: - oneOf: - - type: string - - type: number - - type: 'null' - FooMinAggregateOutputType: - type: object - properties: - id: - oneOf: - - type: 'null' - - type: string - string: - oneOf: - - type: 'null' - - type: string - int: - oneOf: - - type: 'null' - - type: integer - bigInt: - oneOf: - - type: 'null' - - type: integer - date: - oneOf: - - type: 'null' - - type: string - format: date-time - float: - oneOf: - - type: 'null' - - type: number - decimal: - oneOf: - - type: string - - type: number - - type: 'null' - boolean: - oneOf: - - type: 'null' - - type: boolean - bytes: - oneOf: - - type: 'null' - - type: string - format: byte - FooMaxAggregateOutputType: - type: object - properties: - id: - oneOf: - - type: 'null' - - type: string - string: - oneOf: - - type: 'null' - - type: string - int: - oneOf: - - type: 'null' - - type: integer - bigInt: - oneOf: - - type: 'null' - - type: integer - date: - oneOf: - - type: 'null' - - type: string - format: date-time - float: - oneOf: - - type: 'null' - - type: number - decimal: - oneOf: - - type: string - - type: number - - type: 'null' - boolean: - oneOf: - - type: 'null' - - type: boolean - bytes: - oneOf: - - type: 'null' - - type: string - format: byte - _Meta: - type: object - description: Meta information about the request or response - properties: - serialization: - description: Serialization metadata - additionalProperties: true - _Error: - type: object - required: - - error - properties: - error: - type: object - required: - - message - properties: - prisma: - type: boolean - description: Indicates if the error occurred during a Prisma call - rejectedByPolicy: - type: boolean - description: Indicates if the error was due to rejection by a policy - code: - type: string - description: Prisma error code. Only available when "prisma" field is true. - message: - type: string - description: Error message - reason: - type: string - description: Detailed error reason - zodErrors: - type: object - additionalProperties: true - description: Zod validation errors if the error is due to data validation - failure - additionalProperties: true - BatchPayload: - type: object - properties: - count: - type: integer - FooCreateArgs: - type: object - required: - - data - properties: - select: - $ref: '#/components/schemas/FooSelect' - data: - $ref: '#/components/schemas/FooCreateInput' - meta: - $ref: '#/components/schemas/_Meta' - FooCreateManyArgs: - type: object - required: - - data - properties: - data: - oneOf: - - $ref: '#/components/schemas/FooCreateManyInput' - - type: array - items: - $ref: '#/components/schemas/FooCreateManyInput' - skipDuplicates: - type: boolean - description: Do not insert records with unique fields or ID fields that already - exist. - meta: - $ref: '#/components/schemas/_Meta' - FooFindUniqueArgs: - type: object - required: - - where - properties: - select: - $ref: '#/components/schemas/FooSelect' - where: - $ref: '#/components/schemas/FooWhereUniqueInput' - meta: - $ref: '#/components/schemas/_Meta' - FooFindFirstArgs: - type: object - properties: - select: - $ref: '#/components/schemas/FooSelect' - where: - $ref: '#/components/schemas/FooWhereInput' - meta: - $ref: '#/components/schemas/_Meta' - FooFindManyArgs: - type: object - properties: - select: - $ref: '#/components/schemas/FooSelect' - where: - $ref: '#/components/schemas/FooWhereInput' - orderBy: - oneOf: - - $ref: '#/components/schemas/FooOrderByWithRelationInput' - - type: array - items: - $ref: '#/components/schemas/FooOrderByWithRelationInput' - cursor: - $ref: '#/components/schemas/FooWhereUniqueInput' - take: - type: integer - skip: - type: integer - meta: - $ref: '#/components/schemas/_Meta' - FooUpdateArgs: - type: object - required: - - where - - data - properties: - select: - $ref: '#/components/schemas/FooSelect' - where: - $ref: '#/components/schemas/FooWhereUniqueInput' - data: - $ref: '#/components/schemas/FooUpdateInput' - meta: - $ref: '#/components/schemas/_Meta' - FooUpdateManyArgs: - type: object - required: - - data - properties: - where: - $ref: '#/components/schemas/FooWhereInput' - data: - $ref: '#/components/schemas/FooUpdateManyMutationInput' - meta: - $ref: '#/components/schemas/_Meta' - FooUpsertArgs: - type: object - required: - - create - - update - - where - properties: - select: - $ref: '#/components/schemas/FooSelect' - where: - $ref: '#/components/schemas/FooWhereUniqueInput' - create: - $ref: '#/components/schemas/FooCreateInput' - update: - $ref: '#/components/schemas/FooUpdateInput' - meta: - $ref: '#/components/schemas/_Meta' - FooDeleteUniqueArgs: - type: object - required: - - where - properties: - select: - $ref: '#/components/schemas/FooSelect' - where: - $ref: '#/components/schemas/FooWhereUniqueInput' - meta: - $ref: '#/components/schemas/_Meta' - FooDeleteManyArgs: - type: object - properties: - where: - $ref: '#/components/schemas/FooWhereInput' - meta: - $ref: '#/components/schemas/_Meta' - FooCountArgs: - type: object - properties: - select: - $ref: '#/components/schemas/FooSelect' - where: - $ref: '#/components/schemas/FooWhereInput' - meta: - $ref: '#/components/schemas/_Meta' - FooAggregateArgs: - type: object - properties: - where: - $ref: '#/components/schemas/FooWhereInput' - orderBy: - $ref: '#/components/schemas/FooOrderByWithRelationInput' - cursor: - $ref: '#/components/schemas/FooWhereUniqueInput' - take: - type: integer - skip: - type: integer - _count: - oneOf: - - type: boolean - - $ref: '#/components/schemas/FooCountAggregateInput' - _min: - $ref: '#/components/schemas/FooMinAggregateInput' - _max: - $ref: '#/components/schemas/FooMaxAggregateInput' - _sum: - $ref: '#/components/schemas/FooSumAggregateInput' - _avg: - $ref: '#/components/schemas/FooAvgAggregateInput' - meta: - $ref: '#/components/schemas/_Meta' - FooGroupByArgs: - type: object - properties: - where: - $ref: '#/components/schemas/FooWhereInput' - orderBy: - $ref: '#/components/schemas/FooOrderByWithRelationInput' - by: - $ref: '#/components/schemas/FooScalarFieldEnum' - having: - $ref: '#/components/schemas/FooScalarWhereWithAggregatesInput' - take: - type: integer - skip: - type: integer - _count: - oneOf: - - type: boolean - - $ref: '#/components/schemas/FooCountAggregateInput' - _min: - $ref: '#/components/schemas/FooMinAggregateInput' - _max: - $ref: '#/components/schemas/FooMaxAggregateInput' - _sum: - $ref: '#/components/schemas/FooSumAggregateInput' - _avg: - $ref: '#/components/schemas/FooAvgAggregateInput' - meta: - $ref: '#/components/schemas/_Meta' -paths: - /foo/create: - post: - operationId: createFoo - description: Create a new Foo - tags: - - foo - security: [] - responses: - '201': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Foo' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/FooCreateArgs' - /foo/createMany: - post: - operationId: createManyFoo - description: Create several Foo - tags: - - foo - security: [] - responses: - '201': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BatchPayload' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/FooCreateManyArgs' - /foo/findUnique: - get: - operationId: findUniqueFoo - description: Find one unique Foo - tags: - - foo - security: [] - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Foo' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/FooFindUniqueArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /foo/findFirst: - get: - operationId: findFirstFoo - description: Find the first Foo matching the given condition - tags: - - foo - security: [] - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Foo' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/FooFindFirstArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /foo/findMany: - get: - operationId: findManyFoo - description: Find a list of Foo - tags: - - foo - security: [] - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - type: array - items: - $ref: '#/components/schemas/Foo' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/FooFindManyArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /foo/update: - patch: - operationId: updateFoo - description: Update a Foo - tags: - - foo - security: [] - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Foo' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/FooUpdateArgs' - /foo/updateMany: - patch: - operationId: updateManyFoo - description: Update Foos matching the given condition - tags: - - foo - security: [] - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BatchPayload' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/FooUpdateManyArgs' - /foo/upsert: - post: - operationId: upsertFoo - description: Upsert a Foo - tags: - - foo - security: [] - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Foo' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/FooUpsertArgs' - /foo/delete: - delete: - operationId: deleteFoo - description: Delete one unique Foo - tags: - - foo - security: [] - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Foo' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/FooDeleteUniqueArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /foo/deleteMany: - delete: - operationId: deleteManyFoo - description: Delete Foos matching the given condition - tags: - - foo - security: [] - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BatchPayload' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/FooDeleteManyArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /foo/count: - get: - operationId: countFoo - description: Find a list of Foo - tags: - - foo - security: [] - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - oneOf: - - type: integer - - $ref: '#/components/schemas/FooCountAggregateOutputType' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/FooCountArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /foo/aggregate: - get: - operationId: aggregateFoo - description: Aggregate Foos - tags: - - foo - security: [] - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/AggregateFoo' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/FooAggregateArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} - /foo/groupBy: - get: - operationId: groupByFoo - description: Group Foos by fields - tags: - - foo - security: [] - responses: - '200': - description: Successful operation - content: - application/json: - schema: - type: object - required: - - data - properties: - data: - type: array - items: - $ref: '#/components/schemas/FooGroupByOutputType' - description: The Prisma response data serialized with superjson - meta: - $ref: '#/components/schemas/_Meta' - description: The superjson serialization metadata for the "data" field - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Invalid request - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is forbidden - '422': - content: - application/json: - schema: - $ref: '#/components/schemas/_Error' - description: Request is unprocessable due to validation errors - parameters: - - name: q - in: query - required: true - description: Superjson-serialized Prisma query object - content: - application/json: - schema: - $ref: '#/components/schemas/FooGroupByArgs' - - name: meta - in: query - description: Superjson serialization metadata for parameter "q" - content: - application/json: - schema: {} diff --git a/packages/server/test/openapi/migrated/rest-migrated.test.ts b/packages/server/test/openapi/migrated/rest-migrated.test.ts deleted file mode 100644 index 8e0919897..000000000 --- a/packages/server/test/openapi/migrated/rest-migrated.test.ts +++ /dev/null @@ -1,220 +0,0 @@ -/** - * Migrated from zenstack-v2/packages/plugins/openapi/tests/openapi-restful.test.ts - * Only v3.1 related tests are included. - */ -import { createTestClient } from '@zenstackhq/testtools'; -import fs from 'fs'; -import path from 'path'; -import { describe, expect, it } from 'vitest'; -import YAML from 'yaml'; -import { RestApiHandler } from '../../../src/api/rest'; - -const mainSchema = ` -enum role { - USER - ADMIN -} - -model User { - id String @id @default(cuid()) - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - email String @unique - role role @default(USER) - posts Post_Item[] - profile Profile? - likes PostLike[] -} - -model Profile { - id String @id @default(cuid()) - image String? - user User @relation(fields: [userId], references: [id]) - userId String @unique -} - -model Post_Item { - id String @id - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - title String - author User? @relation(fields: [authorId], references: [id]) - authorId String? - published Boolean @default(false) - viewCount Int @default(0) - notes String? - likes PostLike[] -} - -model PostLike { - postId String - userId String - post Post_Item @relation(fields: [postId], references: [id]) - user User @relation(fields: [userId], references: [id]) - @@id([postId, userId]) -} -`; - -const typeCoverageSchema = ` -type Meta { - something String -} - -model Foo { - id String @id @default(cuid()) - string String - int Int - bigInt BigInt - date DateTime - float Float - decimal Decimal - boolean Boolean - bytes Bytes - json Meta? @json - plainJson Json -} -`; - -describe('Migrated REST OpenAPI v3.1 tests', () => { - it('generates valid v3.1 spec for main schema', async () => { - const client = await createTestClient(mainSchema); - const handler = new RestApiHandler({ - schema: client.$schema, - endpoint: 'http://localhost/api', - }); - const spec = await handler.generateSpec(); - - expect(spec.openapi).toBe('3.1.0'); - - // Tags - const tagNames = spec.tags?.map((t: any) => t.name) ?? []; - expect(tagNames).toContain('user'); - expect(tagNames).toContain('post_Item'); - - // Collection paths - expect(spec.paths?.['/user']?.get).toBeDefined(); - expect(spec.paths?.['/user']?.post).toBeDefined(); - expect(spec.paths?.['/user']?.put).toBeUndefined(); - - // Single resource paths - expect(spec.paths?.['/user/{id}']?.get).toBeDefined(); - expect(spec.paths?.['/user/{id}']?.patch).toBeDefined(); - expect(spec.paths?.['/user/{id}']?.delete).toBeDefined(); - - // Related resource paths - expect(spec.paths?.['/user/{id}/posts']?.get).toBeDefined(); - - // Relationship management paths - expect(spec.paths?.['/user/{id}/relationships/posts']?.get).toBeDefined(); - expect(spec.paths?.['/user/{id}/relationships/posts']?.post).toBeDefined(); - expect(spec.paths?.['/user/{id}/relationships/posts']?.patch).toBeDefined(); - expect(spec.paths?.['/user/{id}/relationships/likes']?.get).toBeDefined(); - expect(spec.paths?.['/user/{id}/relationships/likes']?.post).toBeDefined(); - expect(spec.paths?.['/user/{id}/relationships/likes']?.patch).toBeDefined(); - - // To-one relationship: no POST - expect(spec.paths?.['/post_Item/{id}/relationships/author']?.get).toBeDefined(); - expect(spec.paths?.['/post_Item/{id}/relationships/author']?.post).toBeUndefined(); - expect(spec.paths?.['/post_Item/{id}/relationships/author']?.patch).toBeDefined(); - - // To-many relationship on Post_Item - expect(spec.paths?.['/post_Item/{id}/relationships/likes']?.get).toBeDefined(); - expect(spec.paths?.['/post_Item/{id}/relationships/likes']?.post).toBeDefined(); - expect(spec.paths?.['/post_Item/{id}/relationships/likes']?.patch).toBeDefined(); - - // Schemas - expect(spec.components?.schemas?.['User']).toBeDefined(); - expect(spec.components?.schemas?.['Post_Item']).toBeDefined(); - expect(spec.components?.schemas?.['PostLike']).toBeDefined(); - - // Enum schema - expect(spec.components?.schemas?.['role']).toBeDefined(); - const roleSchema = spec.components?.schemas?.['role'] as any; - expect(roleSchema.type).toBe('string'); - expect(roleSchema.enum).toContain('USER'); - expect(roleSchema.enum).toContain('ADMIN'); - }); - - it('compound id model paths exist', async () => { - const client = await createTestClient(mainSchema); - const handler = new RestApiHandler({ - schema: client.$schema, - endpoint: 'http://localhost/api', - }); - const spec = await handler.generateSpec(); - - // PostLike has @@id([postId, userId]) - expect(spec.paths?.['/postLike']).toBeDefined(); - expect(spec.paths?.['/postLike/{id}']).toBeDefined(); - }); - - it('field type coverage matches expectations', async () => { - const client = await createTestClient(typeCoverageSchema); - const handler = new RestApiHandler({ - schema: client.$schema, - endpoint: 'http://localhost/api', - }); - const spec = await handler.generateSpec(); - - expect(spec.openapi).toBe('3.1.0'); - - const fooSchema = spec.components?.schemas?.['Foo'] as any; - expect(fooSchema).toBeDefined(); - expect(fooSchema.properties.string).toMatchObject({ type: 'string' }); - expect(fooSchema.properties.int).toMatchObject({ type: 'integer' }); - expect(fooSchema.properties.bigInt).toMatchObject({ type: 'integer' }); - expect(fooSchema.properties.date).toMatchObject({ type: 'string', format: 'date-time' }); - expect(fooSchema.properties.float).toMatchObject({ type: 'number' }); - expect(fooSchema.properties.boolean).toMatchObject({ type: 'boolean' }); - expect(fooSchema.properties.bytes).toMatchObject({ type: 'string', format: 'byte' }); - - // Decimal -> oneOf number | string - const decimalProp = fooSchema.properties.decimal; - expect(decimalProp.oneOf).toBeDefined(); - - // Meta? @json -> optional ref or null (v3.1 pattern) - const jsonProp = fooSchema.properties.json; - expect(jsonProp).toBeDefined(); - - // Plain Json -> generic - const plainJsonProp = fooSchema.properties.plainJson; - expect(plainJsonProp).toBeDefined(); - }); - - it('works with mapped model names', async () => { - const client = await createTestClient(mainSchema); - const handler = new RestApiHandler({ - schema: client.$schema, - endpoint: 'http://localhost/api', - modelNameMapping: { User: 'myUser' }, - }); - const spec = await handler.generateSpec(); - - expect(spec.paths?.['/myUser']).toBeDefined(); - expect(spec.paths?.['/user']).toBeUndefined(); - expect(spec.paths?.['/post_Item']).toBeDefined(); - }); - - it('baseline comparison - rest-3.1.0', async () => { - const baselinePath = path.join(__dirname, 'baseline', 'rest-3.1.0.baseline.yaml'); - if (!fs.existsSync(baselinePath)) { - console.warn('Skipping baseline comparison: rest-3.1.0.baseline.yaml not found'); - return; - } - const baseline = YAML.parse(fs.readFileSync(baselinePath, 'utf-8')); - expect(baseline.openapi).toBe('3.1.0'); - expect(baseline.components?.schemas).toBeDefined(); - expect(baseline.paths).toBeDefined(); - }); - - it('baseline comparison - rest-type-coverage-3.1.0', async () => { - const baselinePath = path.join(__dirname, 'baseline', 'rest-type-coverage-3.1.0.baseline.yaml'); - if (!fs.existsSync(baselinePath)) { - console.warn('Skipping baseline comparison: rest-type-coverage-3.1.0.baseline.yaml not found'); - return; - } - const baseline = YAML.parse(fs.readFileSync(baselinePath, 'utf-8')); - expect(baseline.openapi).toBe('3.1.0'); - expect(baseline.components?.schemas?.Foo).toBeDefined(); - }); -}); diff --git a/packages/server/test/openapi/migrated/rpc-migrated.test.ts b/packages/server/test/openapi/migrated/rpc-migrated.test.ts deleted file mode 100644 index 81b22ea62..000000000 --- a/packages/server/test/openapi/migrated/rpc-migrated.test.ts +++ /dev/null @@ -1,198 +0,0 @@ -/** - * Migrated from zenstack-v2/packages/plugins/openapi/tests/openapi-rpc.test.ts - * Only v3.1 related tests are included. - */ -import { createTestClient } from '@zenstackhq/testtools'; -import fs from 'fs'; -import path from 'path'; -import { describe, expect, it } from 'vitest'; -import YAML from 'yaml'; -import { RPCApiHandler } from '../../../src/api/rpc'; - -const mainSchema = ` -enum role { - USER - ADMIN -} - -model User { - id String @id @default(cuid()) - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - email String @unique - role role @default(USER) - posts Post_Item[] - profile Profile? -} - -model Profile { - id String @id @default(cuid()) - image String? - user User @relation(fields: [userId], references: [id]) - userId String @unique -} - -model Post_Item { - id String @id - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - title String - author User? @relation(fields: [authorId], references: [id]) - authorId String? - published Boolean @default(false) - viewCount Int @default(0) - notes String? -} -`; - -const typeCoverageSchema = ` -type Meta { - something String -} - -model Foo { - id String @id @default(cuid()) - string String - int Int - bigInt BigInt - date DateTime - float Float - decimal Decimal - boolean Boolean - bytes Bytes? - json Meta? @json - plainJson Json -} -`; - -describe('Migrated RPC OpenAPI v3.1 tests', () => { - it('generates valid v3.1 spec for main schema', async () => { - const client = await createTestClient(mainSchema); - const handler = new RPCApiHandler({ schema: client.$schema }); - const spec = await handler.generateSpec(); - - expect(spec.openapi).toBe('3.1.0'); - - // Tags are generated for included models - const tagNames = spec.tags?.map((t: any) => t.name) ?? []; - expect(tagNames).toContain('user'); - expect(tagNames).toContain('profile'); - expect(tagNames).toContain('post_Item'); - - // CRUD operation paths exist - expect(spec.paths?.['/user/findMany']).toBeDefined(); - expect(spec.paths?.['/user/findMany']?.get).toBeDefined(); - expect(spec.paths?.['/user/create']).toBeDefined(); - expect(spec.paths?.['/user/create']?.post).toBeDefined(); - expect(spec.paths?.['/user/delete']).toBeDefined(); - - // Post paths exist - expect(spec.paths?.['/post_Item/findMany']).toBeDefined(); - - // Schemas are generated - expect(spec.components?.schemas?.['User']).toBeDefined(); - expect(spec.components?.schemas?.['Profile']).toBeDefined(); - expect(spec.components?.schemas?.['Post_Item']).toBeDefined(); - - // Enum schema - expect(spec.components?.schemas?.['role']).toBeDefined(); - const roleSchema = spec.components?.schemas?.['role'] as any; - expect(roleSchema.type).toBe('string'); - expect(roleSchema.enum).toContain('USER'); - expect(roleSchema.enum).toContain('ADMIN'); - - // User schema field types - const userSchema = spec.components?.schemas?.['User'] as any; - expect(userSchema.properties.id).toMatchObject({ type: 'string' }); - expect(userSchema.properties.createdAt).toMatchObject({ type: 'string', format: 'date-time' }); - expect(userSchema.properties.email).toMatchObject({ type: 'string' }); - - // Optional relation uses oneOf with null (v3.1 pattern) - const profileProp = userSchema.properties.profile; - expect(profileProp).toBeDefined(); - }); - - it('generates spec with custom title and version', async () => { - const client = await createTestClient(mainSchema); - const handler = new RPCApiHandler({ schema: client.$schema }); - const spec = await handler.generateSpec({ - title: 'My RPC API', - version: '2.0.0', - description: 'A custom API', - summary: 'awesome api', - }); - - expect(spec.openapi).toBe('3.1.0'); - expect(spec.info.title).toBe('My RPC API'); - expect(spec.info.version).toBe('2.0.0'); - expect((spec.info as any).description).toBe('A custom API'); - expect((spec.info as any).summary).toBe('awesome api'); - }); - - it('field type coverage matches expectations', async () => { - const client = await createTestClient(typeCoverageSchema); - const handler = new RPCApiHandler({ schema: client.$schema }); - const spec = await handler.generateSpec(); - - expect(spec.openapi).toBe('3.1.0'); - - const fooSchema = spec.components?.schemas?.['Foo'] as any; - expect(fooSchema).toBeDefined(); - expect(fooSchema.properties.string).toMatchObject({ type: 'string' }); - expect(fooSchema.properties.int).toMatchObject({ type: 'integer' }); - expect(fooSchema.properties.bigInt).toMatchObject({ type: 'integer' }); - expect(fooSchema.properties.date).toMatchObject({ type: 'string', format: 'date-time' }); - expect(fooSchema.properties.float).toMatchObject({ type: 'number' }); - expect(fooSchema.properties.boolean).toMatchObject({ type: 'boolean' }); - - // Decimal -> oneOf number | string - const decimalProp = fooSchema.properties.decimal; - expect(decimalProp.oneOf).toBeDefined(); - - // Bytes? -> optional byte string - const bytesProp = fooSchema.properties.bytes; - expect(bytesProp).toBeDefined(); - - // Meta? @json -> optional ref or null (v3.1) - const jsonProp = fooSchema.properties.json; - expect(jsonProp).toBeDefined(); - - // Plain Json -> generic - const plainJsonProp = fooSchema.properties.plainJson; - expect(plainJsonProp).toBeDefined(); - }); - - it('baseline comparison - rpc-3.1.0', async () => { - const baselinePath = path.join(__dirname, 'baseline', 'rpc-3.1.0.baseline.yaml'); - if (!fs.existsSync(baselinePath)) { - console.warn('Skipping baseline comparison: rpc-3.1.0.baseline.yaml not found'); - return; - } - const baseline = YAML.parse(fs.readFileSync(baselinePath, 'utf-8')); - // Baseline is from v2 plugin, just verify it parses correctly - expect(baseline.openapi).toBe('3.1.0'); - expect(baseline.components?.schemas).toBeDefined(); - }); - - it('baseline comparison - rpc-3.1.0-omit', async () => { - const baselinePath = path.join(__dirname, 'baseline', 'rpc-3.1.0-omit.baseline.yaml'); - if (!fs.existsSync(baselinePath)) { - console.warn('Skipping baseline comparison: rpc-3.1.0-omit.baseline.yaml not found'); - return; - } - const baseline = YAML.parse(fs.readFileSync(baselinePath, 'utf-8')); - expect(baseline.openapi).toBe('3.1.0'); - expect(baseline.components?.schemas).toBeDefined(); - }); - - it('baseline comparison - rpc-type-coverage-3.1.0', async () => { - const baselinePath = path.join(__dirname, 'baseline', 'rpc-type-coverage-3.1.0.baseline.yaml'); - if (!fs.existsSync(baselinePath)) { - console.warn('Skipping baseline comparison: rpc-type-coverage-3.1.0.baseline.yaml not found'); - return; - } - const baseline = YAML.parse(fs.readFileSync(baselinePath, 'utf-8')); - expect(baseline.openapi).toBe('3.1.0'); - expect(baseline.components?.schemas?.Foo).toBeDefined(); - }); -}); diff --git a/packages/server/test/openapi/rest-openapi.test.ts b/packages/server/test/openapi/rest-openapi.test.ts index 8cfd0c12f..739470534 100644 --- a/packages/server/test/openapi/rest-openapi.test.ts +++ b/packages/server/test/openapi/rest-openapi.test.ts @@ -1,7 +1,21 @@ import { createTestClient } from '@zenstackhq/testtools'; +import fs from 'fs'; +import path from 'path'; import { beforeAll, describe, expect, it } from 'vitest'; +import YAML from 'yaml'; +import { validate } from '@readme/openapi-parser'; import { RestApiHandler } from '../../src/api/rest'; +const UPDATE_BASELINE = process.env.UPDATE_BASELINE === '1'; + +function loadBaseline(name: string) { + return YAML.parse(fs.readFileSync(path.join(__dirname, 'baseline', name), 'utf-8'), { maxAliasCount: 10000 }); +} + +function saveBaseline(name: string, spec: any) { + fs.writeFileSync(path.join(__dirname, 'baseline', name), YAML.stringify(spec, { lineWidth: 0, indent: 4 })); +} + const schema = ` type Address { city String @@ -92,7 +106,6 @@ describe('REST OpenAPI spec generation', () => { expect(spec.info).toBeDefined(); expect(spec.info.title).toBe('ZenStack Generated API'); expect(spec.info.version).toBe('1.0.0'); - expect(spec.servers).toEqual([{ url: 'http://localhost/api' }]); expect(spec.paths).toBeDefined(); expect(spec.components).toBeDefined(); expect(spec.components.schemas).toBeDefined(); @@ -595,6 +608,28 @@ model Post { }); }); +describe('REST OpenAPI spec generation - baseline', () => { + it('matches baseline', async () => { + const client = await createTestClient(schema); + const handler = new RestApiHandler({ + schema: client.$schema, + endpoint: 'http://localhost/api', + }); + const spec = await handler.generateSpec(); + const baselineFile = 'rest.baseline.yaml'; + + if (UPDATE_BASELINE) { + saveBaseline(baselineFile, spec); + return; + } + + const baseline = loadBaseline(baselineFile); + expect(spec).toEqual(baseline); + + await validate(spec); + }); +}); + describe('REST OpenAPI spec generation - with enum schema', () => { it('enum schemas exist in components', async () => { const enumSchema = ` diff --git a/packages/server/test/openapi/rpc-openapi.test.ts b/packages/server/test/openapi/rpc-openapi.test.ts index 6cf1a8c5d..ecf036e7a 100644 --- a/packages/server/test/openapi/rpc-openapi.test.ts +++ b/packages/server/test/openapi/rpc-openapi.test.ts @@ -1,8 +1,22 @@ import { createTestClient } from '@zenstackhq/testtools'; +import fs from 'fs'; +import path from 'path'; import { beforeAll, describe, expect, it } from 'vitest'; +import YAML from 'yaml'; +import { validate } from '@readme/openapi-parser'; import { RPCApiHandler } from '../../src/api/rpc'; import { schema } from '../utils'; +const UPDATE_BASELINE = process.env.UPDATE_BASELINE === '1'; + +function loadBaseline(name: string) { + return YAML.parse(fs.readFileSync(path.join(__dirname, 'baseline', name), 'utf-8')); +} + +function saveBaseline(name: string, spec: any) { + fs.writeFileSync(path.join(__dirname, 'baseline', name), YAML.stringify(spec, { lineWidth: 0, indent: 4 })); +} + describe('RPC OpenAPI spec generation', () => { let handler: RPCApiHandler; let spec: any; @@ -775,6 +789,25 @@ describe('RPC OpenAPI spec generation - aggregate and groupby schemas', () => { }); }); +describe('RPC OpenAPI spec generation - baseline', () => { + it('matches baseline', async () => { + const client = await createTestClient(schema); + const handler = new RPCApiHandler({ schema: client.$schema }); + const spec = await handler.generateSpec(); + const baselineFile = 'rpc.baseline.yaml'; + + if (UPDATE_BASELINE) { + saveBaseline(baselineFile, spec); + return; + } + + const baseline = loadBaseline(baselineFile); + expect(spec).toEqual(baseline); + + await validate(spec); + }); +}); + describe('RPC OpenAPI spec generation - with procedures', () => { it('procedure paths are generated', async () => { const schemaWithProc = ` diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 63cecc9cd..2a4c2023a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -721,6 +721,9 @@ importers: specifier: 'catalog:' version: 4.0.1(zod@4.1.12) devDependencies: + '@readme/openapi-parser': + specifier: ^6.0.0 + version: 6.0.0(openapi-types@12.1.3) '@sveltejs/kit': specifier: 'catalog:' version: 2.53.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.53.5)(vite@7.3.1(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.1(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)) @@ -1269,6 +1272,12 @@ packages: resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} engines: {node: '>=10'} + '@apidevtools/json-schema-ref-parser@14.2.1': + resolution: {integrity: sha512-HmdFw9CDYqM6B25pqGBpNeLCKvGPlIx1EbLrVL0zPvj50CJQUHyBNBw45Muk0kEIkogo1VZvOKHajdMuAzSxRg==} + engines: {node: '>= 20'} + peerDependencies: + '@types/json-schema': ^7.0.15 + '@asamuzakjp/css-color@4.1.2': resolution: {integrity: sha512-NfBUvBaYgKIuq6E/RBLY1m0IohzNHAYyaJGuTK79Z23uNwmz2jl1mPsC5ZxCCxylinKhT1Amn5oNTlx1wN8cQg==} @@ -2194,6 +2203,10 @@ packages: resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} engines: {node: '>=12.22'} + '@humanwhocodes/momoa@2.0.4': + resolution: {integrity: sha512-RE815I4arJFtt+FVeU1Tgp9/Xvecacji8w/V6XtXsWWH/wz/eNkNbhb+ny/+PlVZjV0rxQpRSQKNKE3lcktHEA==} + engines: {node: '>=10.10.0'} + '@humanwhocodes/retry@0.3.1': resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} engines: {node: '>=18.18'} @@ -3049,6 +3062,22 @@ packages: '@prisma/get-platform@6.19.0': resolution: {integrity: sha512-ym85WDO2yDhC3fIXHWYpG3kVMBA49cL1XD2GCsCF8xbwoy2OkDQY44gEbAt2X46IQ4Apq9H6g0Ex1iFfPqEkHA==} + '@readme/better-ajv-errors@2.4.0': + resolution: {integrity: sha512-9WODaOAKSl/mU+MYNZ2aHCrkoRSvmQ+1YkLj589OEqqjOAhbn8j7Z+ilYoiTu/he6X63/clsxxAB4qny9/dDzg==} + engines: {node: '>=18'} + peerDependencies: + ajv: 4.11.8 - 8 + + '@readme/openapi-parser@6.0.0': + resolution: {integrity: sha512-PaTnrKlKgEJZzjJ77AAhGe28NiyLBdiKMx95rJ9xlLZ8QLqYitMpPBQAKhsuEGOWQQbsIMfBZEPavbXghACQHA==} + engines: {node: '>=20'} + peerDependencies: + openapi-types: '>=7' + + '@readme/openapi-schemas@3.1.0': + resolution: {integrity: sha512-9FC/6ho8uFa8fV50+FPy/ngWN53jaUu4GRXlAjcxIRrzhltJnpKkBG2Tp0IDraFJeWrOpk84RJ9EMEEYzaI1Bw==} + engines: {node: '>=18'} + '@rolldown/pluginutils@1.0.0-rc.2': resolution: {integrity: sha512-izyXV/v+cHiRfozX62W9htOAvwMo4/bXKDrQ+vom1L1qRuexPock/7VZDAhnpHCLNejd3NJ6hiab+tO0D44Rgw==} @@ -4205,6 +4234,14 @@ packages: resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} engines: {node: '>= 14'} + ajv-draft-04@1.0.0: + resolution: {integrity: sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==} + peerDependencies: + ajv: ^8.5.0 + peerDependenciesMeta: + ajv: + optional: true + ajv-formats@3.0.1: resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} peerDependencies: @@ -6266,6 +6303,10 @@ packages: jsonify@0.0.1: resolution: {integrity: sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==} + jsonpointer@5.0.1: + resolution: {integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==} + engines: {node: '>=0.10.0'} + jsonschema@1.4.1: resolution: {integrity: sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==} @@ -6327,6 +6368,10 @@ packages: resolution: {integrity: sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==} engines: {node: '>= 0.6.3'} + leven@3.1.0: + resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} + engines: {node: '>=6'} + levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -9036,6 +9081,11 @@ snapshots: '@alloc/quick-lru@5.2.0': {} + '@apidevtools/json-schema-ref-parser@14.2.1(@types/json-schema@7.0.15)': + dependencies: + '@types/json-schema': 7.0.15 + js-yaml: 4.1.1 + '@asamuzakjp/css-color@4.1.2': dependencies: '@csstools/css-calc': 3.1.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) @@ -9081,7 +9131,7 @@ snapshots: '@babel/core@7.28.5': dependencies: - '@babel/code-frame': 7.27.1 + '@babel/code-frame': 7.29.0 '@babel/generator': 7.28.5 '@babel/helper-compilation-targets': 7.27.2 '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.5) @@ -9352,19 +9402,19 @@ snapshots: '@babel/template@7.27.2': dependencies: - '@babel/code-frame': 7.27.1 + '@babel/code-frame': 7.29.0 '@babel/parser': 7.28.5 '@babel/types': 7.28.5 '@babel/template@7.28.6': dependencies: - '@babel/code-frame': 7.28.6 + '@babel/code-frame': 7.29.0 '@babel/parser': 7.28.6 '@babel/types': 7.28.6 '@babel/traverse@7.28.5': dependencies: - '@babel/code-frame': 7.27.1 + '@babel/code-frame': 7.29.0 '@babel/generator': 7.28.5 '@babel/helper-globals': 7.28.0 '@babel/parser': 7.28.5 @@ -9376,7 +9426,7 @@ snapshots: '@babel/traverse@7.28.6': dependencies: - '@babel/code-frame': 7.28.6 + '@babel/code-frame': 7.29.0 '@babel/generator': 7.28.6 '@babel/helper-globals': 7.28.0 '@babel/parser': 7.28.6 @@ -9950,6 +10000,8 @@ snapshots: '@humanwhocodes/module-importer@1.0.1': {} + '@humanwhocodes/momoa@2.0.4': {} + '@humanwhocodes/retry@0.3.1': {} '@humanwhocodes/retry@0.4.3': {} @@ -10790,6 +10842,28 @@ snapshots: dependencies: '@prisma/debug': 6.19.0 + '@readme/better-ajv-errors@2.4.0(ajv@8.18.0)': + dependencies: + '@babel/code-frame': 7.29.0 + '@babel/runtime': 7.28.4 + '@humanwhocodes/momoa': 2.0.4 + ajv: 8.18.0 + jsonpointer: 5.0.1 + leven: 3.1.0 + picocolors: 1.1.1 + + '@readme/openapi-parser@6.0.0(openapi-types@12.1.3)': + dependencies: + '@apidevtools/json-schema-ref-parser': 14.2.1(@types/json-schema@7.0.15) + '@readme/better-ajv-errors': 2.4.0(ajv@8.18.0) + '@readme/openapi-schemas': 3.1.0 + '@types/json-schema': 7.0.15 + ajv: 8.18.0 + ajv-draft-04: 1.0.0(ajv@8.18.0) + openapi-types: 12.1.3 + + '@readme/openapi-schemas@3.1.0': {} + '@rolldown/pluginutils@1.0.0-rc.2': {} '@rolldown/pluginutils@1.0.0-rc.5': {} @@ -11857,7 +11931,7 @@ snapshots: '@vue/babel-plugin-resolve-type@2.0.1(@babel/core@7.29.0)': dependencies: - '@babel/code-frame': 7.28.6 + '@babel/code-frame': 7.29.0 '@babel/core': 7.29.0 '@babel/helper-module-imports': 7.28.6 '@babel/helper-plugin-utils': 7.28.6 @@ -12075,6 +12149,10 @@ snapshots: agent-base@7.1.4: {} + ajv-draft-04@1.0.0(ajv@8.18.0): + optionalDependencies: + ajv: 8.18.0 + ajv-formats@3.0.1(ajv@8.18.0): optionalDependencies: ajv: 8.18.0 @@ -14332,6 +14410,8 @@ snapshots: jsonify@0.0.1: {} + jsonpointer@5.0.1: {} + jsonschema@1.4.1: {} jsx-ast-utils@3.3.5: @@ -14398,6 +14478,8 @@ snapshots: dependencies: readable-stream: 2.3.8 + leven@3.1.0: {} + levn@0.4.1: dependencies: prelude-ls: 1.2.1 From 2a2fcd73af76b5eb54f336bf604e76e563b08810 Mon Sep 17 00:00:00 2001 From: ymc9 <104139426+ymc9@users.noreply.github.com> Date: Thu, 19 Mar 2026 19:23:36 -0700 Subject: [PATCH 13/16] refactor: extract shared filter schemas in RPC OpenAPI spec generation Unify filter schema creation into a single `buildFilterSchema` method with optional slicing context to eliminate duplication. Shared filter schemas (_StringFilter, _IntFilter, etc.) are now generated once and referenced via $ref. Also adds update-baseline npm script and regenerates baselines. Co-Authored-By: Claude Opus 4.6 --- packages/server/package.json | 1 + packages/server/src/api/rest/openapi.ts | 4 +- packages/server/src/api/rpc/openapi.ts | 139 +- .../test/openapi/baseline/rest.baseline.yaml | 1208 +++++++++++++---- .../test/openapi/baseline/rpc.baseline.yaml | 604 +++++---- .../server/test/openapi/rest-openapi.test.ts | 2 +- .../server/test/openapi/rpc-openapi.test.ts | 46 +- 7 files changed, 1445 insertions(+), 559 deletions(-) diff --git a/packages/server/package.json b/packages/server/package.json index 7fbc5e86a..78e287f06 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -8,6 +8,7 @@ "watch": "tsup-node --watch", "lint": "eslint src --ext ts", "test": "vitest run", + "update-baseline": "UPDATE_BASELINE=1 vitest run test/openapi", "pack": "pnpm pack" }, "keywords": [ diff --git a/packages/server/src/api/rest/openapi.ts b/packages/server/src/api/rest/openapi.ts index e5b238d58..1f4ec505c 100644 --- a/packages/server/src/api/rest/openapi.ts +++ b/packages/server/src/api/rest/openapi.ts @@ -457,7 +457,7 @@ export class RestApiSpecGenerator { } for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { - if (fieldDef.relation || fieldDef.omit || fieldDef.foreignKeyFor) continue; + if (fieldDef.relation) continue; if (idFieldNames.has(fieldName)) continue; const type = fieldDef.type; @@ -749,7 +749,6 @@ export class RestApiSpecGenerator { const relationships: Record = {}; for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { - if (fieldDef.omit) continue; if (fieldDef.updatedAt) continue; if (fieldDef.foreignKeyFor) continue; // Skip auto-generated id fields @@ -813,7 +812,6 @@ export class RestApiSpecGenerator { const relationships: Record = {}; for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { - if (fieldDef.omit) continue; if (fieldDef.updatedAt) continue; if (fieldDef.foreignKeyFor) continue; if (fieldDef.relation && !isModelIncluded(fieldDef.type, this.queryOptions)) continue; diff --git a/packages/server/src/api/rpc/openapi.ts b/packages/server/src/api/rpc/openapi.ts index 13aa5b2ed..7ff2844e3 100644 --- a/packages/server/src/api/rpc/openapi.ts +++ b/packages/server/src/api/rpc/openapi.ts @@ -410,6 +410,9 @@ export class RPCApiSpecGenerator { } } + // Shared filter schemas for where inputs + this.generateFilterSchemas(schemas); + // Per-model schemas for (const modelName of getIncludedModels(this.schema, this.queryOptions)) { const modelDef = this.schema.models[modelName]!; @@ -440,12 +443,21 @@ export class RPCApiSpecGenerator { schemas[`${modelName}GroupByArgs`] = this.buildGroupByArgsSchema(modelName); schemas[`${modelName}ExistsArgs`] = this.buildExistsArgsSchema(modelName); schemas[`${modelName}Response`] = this.buildResponseSchema(modelName); - schemas[`${modelName}CountAggregateOutputType`] = this.buildCountAggregateOutputTypeSchema(modelName, modelDef); + schemas[`${modelName}CountAggregateOutputType`] = this.buildCountAggregateOutputTypeSchema( + modelName, + modelDef, + ); schemas[`${modelName}MinAggregateOutputType`] = this.buildMinAggregateOutputTypeSchema(modelName, modelDef); schemas[`${modelName}MaxAggregateOutputType`] = this.buildMaxAggregateOutputTypeSchema(modelName, modelDef); if (this.modelHasNumericFields(modelDef)) { - schemas[`${modelName}AvgAggregateOutputType`] = this.buildAvgAggregateOutputTypeSchema(modelName, modelDef); - schemas[`${modelName}SumAggregateOutputType`] = this.buildSumAggregateOutputTypeSchema(modelName, modelDef); + schemas[`${modelName}AvgAggregateOutputType`] = this.buildAvgAggregateOutputTypeSchema( + modelName, + modelDef, + ); + schemas[`${modelName}SumAggregateOutputType`] = this.buildSumAggregateOutputTypeSchema( + modelName, + modelDef, + ); } schemas[`Aggregate${modelName}`] = this.buildAggregateSchema(modelName, modelDef); schemas[`${modelName}GroupByOutputType`] = this.buildGroupByOutputTypeSchema(modelName, modelDef); @@ -572,18 +584,11 @@ export class RPCApiSpecGenerator { } private buildCreateInputSchema(_modelName: string, modelDef: ModelDef): SchemaObject { - const idFieldNames = new Set(modelDef.idFields); const properties: Record = {}; const required: string[] = []; for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { if (fieldDef.relation) continue; - if (fieldDef.foreignKeyFor) continue; - if (fieldDef.omit) continue; - if (fieldDef.updatedAt) continue; - // Skip auto-generated id fields - if (idFieldNames.has(fieldName) && fieldDef.default !== undefined) continue; - properties[fieldName] = this.typeToSchema(fieldDef.type); if (!fieldDef.optional && fieldDef.default === undefined && !fieldDef.array) { required.push(fieldName); @@ -602,10 +607,6 @@ export class RPCApiSpecGenerator { for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { if (fieldDef.relation) continue; - if (fieldDef.foreignKeyFor) continue; - if (fieldDef.omit) continue; - if (fieldDef.updatedAt) continue; - properties[fieldName] = this.typeToSchema(fieldDef.type); } @@ -645,7 +646,6 @@ export class RPCApiSpecGenerator { for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { if (fieldDef.relation) continue; - if (fieldDef.omit) continue; const filterSchema = this.buildFieldFilterSchema(modelName, fieldName, fieldDef); if (filterSchema) { properties[fieldName] = filterSchema; @@ -840,7 +840,8 @@ export class RPCApiSpecGenerator { private modelHasNumericFields(modelDef: ModelDef): boolean { return Object.values(modelDef.fields).some( - (f) => !f.relation && (f.type === 'Int' || f.type === 'Float' || f.type === 'BigInt' || f.type === 'Decimal') + (f) => + !f.relation && (f.type === 'Int' || f.type === 'Float' || f.type === 'BigInt' || f.type === 'Decimal'), ); } @@ -879,7 +880,12 @@ export class RPCApiSpecGenerator { const properties: Record = {}; for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { if (fieldDef.relation) continue; - if (fieldDef.type !== 'Int' && fieldDef.type !== 'Float' && fieldDef.type !== 'BigInt' && fieldDef.type !== 'Decimal') + if ( + fieldDef.type !== 'Int' && + fieldDef.type !== 'Float' && + fieldDef.type !== 'BigInt' && + fieldDef.type !== 'Decimal' + ) continue; // avg always returns a float properties[fieldName] = { oneOf: [{ type: 'null' as const }, { type: 'number' }] }; @@ -891,7 +897,12 @@ export class RPCApiSpecGenerator { const properties: Record = {}; for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { if (fieldDef.relation) continue; - if (fieldDef.type !== 'Int' && fieldDef.type !== 'Float' && fieldDef.type !== 'BigInt' && fieldDef.type !== 'Decimal') + if ( + fieldDef.type !== 'Int' && + fieldDef.type !== 'Float' && + fieldDef.type !== 'BigInt' && + fieldDef.type !== 'Decimal' + ) continue; // sum preserves the original type properties[fieldName] = { oneOf: [{ type: 'null' as const }, this.typeToSchema(fieldDef.type)] }; @@ -902,7 +913,10 @@ export class RPCApiSpecGenerator { private buildAggregateSchema(modelName: string, modelDef: ModelDef): SchemaObject { const properties: Record = { _count: { - oneOf: [{ type: 'null' as const }, { $ref: `#/components/schemas/${modelName}CountAggregateOutputType` }], + oneOf: [ + { type: 'null' as const }, + { $ref: `#/components/schemas/${modelName}CountAggregateOutputType` }, + ], }, _min: { oneOf: [{ type: 'null' as const }, { $ref: `#/components/schemas/${modelName}MinAggregateOutputType` }], @@ -1017,13 +1031,54 @@ export class RPCApiSpecGenerator { return baseSchema; } - private buildFieldFilterSchema(modelName: string, fieldName: string, fieldDef: FieldDef): SchemaObject | undefined { - const baseSchema = this.typeToSchema(fieldDef.type); + /** + * Generates shared filter schemas for all field types used across models. + */ + private generateFilterSchemas(schemas: Record): void { + const filters = new Map(); + + for (const modelName of getIncludedModels(this.schema, this.queryOptions)) { + const modelDef = this.schema.models[modelName]!; + for (const [, fieldDef] of Object.entries(modelDef.fields)) { + if (fieldDef.relation) continue; + const name = this.filterSchemaName(fieldDef.type, !!fieldDef.array); + if (!filters.has(name)) { + filters.set(name, { type: fieldDef.type, array: !!fieldDef.array }); + } + } + } + + for (const [name, { type, array }] of filters) { + schemas[name] = this.buildFilterSchema(type, array)!; + } + } + + /** + * Returns the schema name for a shared filter (e.g. "_StringFilter", "_IntListFilter"). + */ + private filterSchemaName(type: string, array: boolean): string { + return array ? `_${type}ListFilter` : `_${type}Filter`; + } + + /** + * Builds a filter schema for a given field type. When `fieldContext` is provided, + * only filter kinds that pass `isFilterKindIncluded` are included; otherwise all + * applicable filter kinds are included (used for shared filter schemas). + */ + private buildFilterSchema( + type: string, + array: boolean, + fieldContext?: { modelName: string; fieldName: string }, + ): SchemaObject | undefined { + const includeKind = (kind: string) => + !fieldContext || + isFilterKindIncluded(fieldContext.modelName, fieldContext.fieldName, kind, this.queryOptions); + + const baseSchema = this.typeToSchema(type); const filterProps: Record = {}; - const type = fieldDef.type; // Equality operators - if (isFilterKindIncluded(modelName, fieldName, 'Equality', this.queryOptions)) { + if (includeKind('Equality')) { filterProps['equals'] = baseSchema; filterProps['not'] = baseSchema; filterProps['in'] = { type: 'array', items: baseSchema }; @@ -1033,7 +1088,7 @@ export class RPCApiSpecGenerator { // Range operators (numeric/datetime types) if ( (type === 'Int' || type === 'Float' || type === 'BigInt' || type === 'Decimal' || type === 'DateTime') && - isFilterKindIncluded(modelName, fieldName, 'Range', this.queryOptions) + includeKind('Range') ) { filterProps['lt'] = baseSchema; filterProps['lte'] = baseSchema; @@ -1042,7 +1097,7 @@ export class RPCApiSpecGenerator { } // Like operators (String type) - if (type === 'String' && isFilterKindIncluded(modelName, fieldName, 'Like', this.queryOptions)) { + if (type === 'String' && includeKind('Like')) { filterProps['contains'] = { type: 'string' }; filterProps['startsWith'] = { type: 'string' }; filterProps['endsWith'] = { type: 'string' }; @@ -1050,7 +1105,7 @@ export class RPCApiSpecGenerator { } // List operators (array fields) - if (fieldDef.array && isFilterKindIncluded(modelName, fieldName, 'List', this.queryOptions)) { + if (array && includeKind('List')) { filterProps['has'] = baseSchema; filterProps['hasEvery'] = { type: 'array', items: baseSchema }; filterProps['hasSome'] = { type: 'array', items: baseSchema }; @@ -1062,13 +1117,43 @@ export class RPCApiSpecGenerator { const filterObject: SchemaObject = { type: 'object', properties: filterProps }; // If Equality is included, allow shorthand (direct value) via oneOf - if (isFilterKindIncluded(modelName, fieldName, 'Equality', this.queryOptions)) { + if (includeKind('Equality')) { return { oneOf: [baseSchema, filterObject] }; } return filterObject; } + /** + * Returns true if no field-level filter slicing is configured for this model/field. + */ + private hasDefaultFilters(modelName: string, fieldName: string): boolean { + const slicing = this.queryOptions?.slicing; + if (!slicing?.models) return true; + + const modelKey = lowerCaseFirst(modelName); + const modelSlicing = (slicing.models as Record)[modelKey] ?? (slicing.models as any).$all; + if (!modelSlicing?.fields) return true; + + const fieldSlicing = modelSlicing.fields[fieldName] ?? modelSlicing.fields.$all; + return !fieldSlicing; + } + + private buildFieldFilterSchema( + modelName: string, + fieldName: string, + fieldDef: FieldDef, + ): SchemaObject | ReferenceObject | undefined { + // If no slicing customization, reference the shared filter schema + if (this.hasDefaultFilters(modelName, fieldName)) { + const name = this.filterSchemaName(fieldDef.type, !!fieldDef.array); + return { $ref: `#/components/schemas/${name}` }; + } + + // Slicing is active — build inline filter with only included filter kinds + return this.buildFilterSchema(fieldDef.type, !!fieldDef.array, { modelName, fieldName }); + } + private typeToSchema(type: string): SchemaObject | ReferenceObject { switch (type) { case 'String': diff --git a/packages/server/test/openapi/baseline/rest.baseline.yaml b/packages/server/test/openapi/baseline/rest.baseline.yaml index 5111ca88a..fb2cd3ce3 100644 --- a/packages/server/test/openapi/baseline/rest.baseline.yaml +++ b/packages/server/test/openapi/baseline/rest.baseline.yaml @@ -118,7 +118,7 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/UserListResponse" - "400": &a1 + "400": description: Error content: application/vnd.api+json: @@ -142,7 +142,12 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/UserResponse" - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" /user/{id}: get: tags: @@ -150,8 +155,7 @@ paths: summary: Get a User resource by ID operationId: getUser parameters: - - &a2 - $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/id" - $ref: "#/components/parameters/include" responses: "200": @@ -160,14 +164,19 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/UserResponse" - "404": *a1 + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" patch: tags: - user summary: Update a User resource operationId: updateUser parameters: - - *a2 + - $ref: "#/components/parameters/id" requestBody: required: true content: @@ -181,19 +190,34 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/UserResponse" - "400": *a1 - "404": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" delete: tags: - user summary: Delete a User resource operationId: deleteUser parameters: - - *a2 + - $ref: "#/components/parameters/id" responses: "200": description: Deleted successfully - "404": *a1 + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" /user/{id}/posts: get: tags: @@ -278,6 +302,31 @@ paths: in: query schema: type: string + - name: filter[authorId] + in: query + schema: + type: string + description: Filter by authorId + - name: filter[authorId][$contains] + in: query + schema: + type: string + - name: filter[authorId][$icontains] + in: query + schema: + type: string + - name: filter[authorId][$search] + in: query + schema: + type: string + - name: filter[authorId][$startsWith] + in: query + schema: + type: string + - name: filter[authorId][$endsWith] + in: query + schema: + type: string - name: filter[published] in: query schema: @@ -332,7 +381,12 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/PostListResponse" - "404": *a1 + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" /user/{id}/relationships/posts: get: tags: @@ -340,8 +394,7 @@ paths: summary: Fetch posts relationship operationId: getUser_relationships_posts parameters: - - &a3 - $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/id" responses: "200": description: posts relationship @@ -349,47 +402,63 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/_toManyRelationshipWithLinks" - "404": *a1 + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" put: tags: - user summary: Replace posts relationship operationId: putUser_relationships_posts parameters: - - *a3 + - $ref: "#/components/parameters/id" requestBody: required: true content: application/vnd.api+json: - schema: &a4 + schema: $ref: "#/components/schemas/_toManyRelationshipRequest" responses: "200": description: Relationship updated - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" patch: tags: - user summary: Update posts relationship operationId: patchUser_relationships_posts parameters: - - *a3 + - $ref: "#/components/parameters/id" requestBody: required: true content: application/vnd.api+json: - schema: *a4 + schema: + $ref: "#/components/schemas/_toManyRelationshipRequest" responses: "200": description: Relationship updated - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" post: tags: - user summary: Add to posts collection relationship operationId: postUser_relationships_posts parameters: - - *a3 + - $ref: "#/components/parameters/id" requestBody: required: true content: @@ -399,7 +468,12 @@ paths: responses: "200": description: Added to relationship collection - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" /user/{id}/likes: get: tags: @@ -429,7 +503,12 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/PostLikeListResponse" - "404": *a1 + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" /user/{id}/relationships/likes: get: tags: @@ -437,8 +516,7 @@ paths: summary: Fetch likes relationship operationId: getUser_relationships_likes parameters: - - &a5 - $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/id" responses: "200": description: likes relationship @@ -446,47 +524,63 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/_toManyRelationshipWithLinks" - "404": *a1 + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" put: tags: - user summary: Replace likes relationship operationId: putUser_relationships_likes parameters: - - *a5 + - $ref: "#/components/parameters/id" requestBody: required: true content: application/vnd.api+json: - schema: &a6 + schema: $ref: "#/components/schemas/_toManyRelationshipRequest" responses: "200": description: Relationship updated - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" patch: tags: - user summary: Update likes relationship operationId: patchUser_relationships_likes parameters: - - *a5 + - $ref: "#/components/parameters/id" requestBody: required: true content: application/vnd.api+json: - schema: *a6 + schema: + $ref: "#/components/schemas/_toManyRelationshipRequest" responses: "200": description: Relationship updated - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" post: tags: - user summary: Add to likes collection relationship operationId: postUser_relationships_likes parameters: - - *a5 + - $ref: "#/components/parameters/id" requestBody: required: true content: @@ -496,7 +590,12 @@ paths: responses: "200": description: Added to relationship collection - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" /user/{id}/profile: get: tags: @@ -513,7 +612,12 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/ProfileResponse" - "404": *a1 + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" /user/{id}/relationships/profile: get: tags: @@ -521,8 +625,7 @@ paths: summary: Fetch profile relationship operationId: getUser_relationships_profile parameters: - - &a7 - $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/id" responses: "200": description: profile relationship @@ -530,40 +633,56 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/_toOneRelationshipWithLinks" - "404": *a1 + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" put: tags: - user summary: Replace profile relationship operationId: putUser_relationships_profile parameters: - - *a7 + - $ref: "#/components/parameters/id" requestBody: required: true content: application/vnd.api+json: - schema: &a8 + schema: $ref: "#/components/schemas/_toOneRelationshipRequest" responses: "200": description: Relationship updated - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" patch: tags: - user summary: Update profile relationship operationId: patchUser_relationships_profile parameters: - - *a7 + - $ref: "#/components/parameters/id" requestBody: required: true content: application/vnd.api+json: - schema: *a8 + schema: + $ref: "#/components/schemas/_toOneRelationshipRequest" responses: "200": description: Relationship updated - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" /profile: get: tags: @@ -605,6 +724,31 @@ paths: in: query schema: type: string + - name: filter[userId] + in: query + schema: + type: string + description: Filter by userId + - name: filter[userId][$contains] + in: query + schema: + type: string + - name: filter[userId][$icontains] + in: query + schema: + type: string + - name: filter[userId][$search] + in: query + schema: + type: string + - name: filter[userId][$startsWith] + in: query + schema: + type: string + - name: filter[userId][$endsWith] + in: query + schema: + type: string responses: "200": description: List of Profile resources @@ -612,7 +756,12 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/ProfileListResponse" - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" post: tags: - profile @@ -631,7 +780,12 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/ProfileResponse" - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" /profile/{id}: get: tags: @@ -639,8 +793,7 @@ paths: summary: Get a Profile resource by ID operationId: getProfile parameters: - - &a9 - $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/id" - $ref: "#/components/parameters/include" responses: "200": @@ -649,14 +802,19 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/ProfileResponse" - "404": *a1 + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" patch: tags: - profile summary: Update a Profile resource operationId: updateProfile parameters: - - *a9 + - $ref: "#/components/parameters/id" requestBody: required: true content: @@ -670,19 +828,34 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/ProfileResponse" - "400": *a1 - "404": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" delete: tags: - profile summary: Delete a Profile resource operationId: deleteProfile parameters: - - *a9 + - $ref: "#/components/parameters/id" responses: "200": description: Deleted successfully - "404": *a1 + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" /profile/{id}/user: get: tags: @@ -699,7 +872,12 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/UserResponse" - "404": *a1 + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" /profile/{id}/relationships/user: get: tags: @@ -707,8 +885,7 @@ paths: summary: Fetch user relationship operationId: getProfile_relationships_user parameters: - - &a10 - $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/id" responses: "200": description: user relationship @@ -716,40 +893,56 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/_toOneRelationshipWithLinks" - "404": *a1 + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" put: tags: - profile summary: Replace user relationship operationId: putProfile_relationships_user parameters: - - *a10 + - $ref: "#/components/parameters/id" requestBody: required: true content: application/vnd.api+json: - schema: &a11 + schema: $ref: "#/components/schemas/_toOneRelationshipRequest" responses: "200": description: Relationship updated - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" patch: tags: - profile summary: Update user relationship operationId: patchProfile_relationships_user parameters: - - *a10 + - $ref: "#/components/parameters/id" requestBody: required: true content: application/vnd.api+json: - schema: *a11 + schema: + $ref: "#/components/schemas/_toOneRelationshipRequest" responses: "200": description: Relationship updated - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" /post: get: tags: @@ -833,6 +1026,31 @@ paths: in: query schema: type: string + - name: filter[authorId] + in: query + schema: + type: string + description: Filter by authorId + - name: filter[authorId][$contains] + in: query + schema: + type: string + - name: filter[authorId][$icontains] + in: query + schema: + type: string + - name: filter[authorId][$search] + in: query + schema: + type: string + - name: filter[authorId][$startsWith] + in: query + schema: + type: string + - name: filter[authorId][$endsWith] + in: query + schema: + type: string - name: filter[published] in: query schema: @@ -887,7 +1105,12 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/PostListResponse" - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" post: tags: - post @@ -906,7 +1129,12 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/PostResponse" - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" /post/{id}: get: tags: @@ -914,8 +1142,7 @@ paths: summary: Get a Post resource by ID operationId: getPost parameters: - - &a12 - $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/id" - $ref: "#/components/parameters/include" responses: "200": @@ -924,14 +1151,19 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/PostResponse" - "404": *a1 + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" patch: tags: - post summary: Update a Post resource operationId: updatePost parameters: - - *a12 + - $ref: "#/components/parameters/id" requestBody: required: true content: @@ -945,19 +1177,34 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/PostResponse" - "400": *a1 - "404": *a1 - delete: - tags: - - post - summary: Delete a Post resource - operationId: deletePost - parameters: - - *a12 - responses: - "200": + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" + delete: + tags: + - post + summary: Delete a Post resource + operationId: deletePost + parameters: + - $ref: "#/components/parameters/id" + responses: + "200": description: Deleted successfully - "404": *a1 + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" /post/{id}/author: get: tags: @@ -974,7 +1221,12 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/UserResponse" - "404": *a1 + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" /post/{id}/relationships/author: get: tags: @@ -982,8 +1234,7 @@ paths: summary: Fetch author relationship operationId: getPost_relationships_author parameters: - - &a13 - $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/id" responses: "200": description: author relationship @@ -991,40 +1242,56 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/_toOneRelationshipWithLinks" - "404": *a1 + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" put: tags: - post summary: Replace author relationship operationId: putPost_relationships_author parameters: - - *a13 + - $ref: "#/components/parameters/id" requestBody: required: true content: application/vnd.api+json: - schema: &a14 + schema: $ref: "#/components/schemas/_toOneRelationshipRequest" responses: "200": description: Relationship updated - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" patch: tags: - post summary: Update author relationship operationId: patchPost_relationships_author parameters: - - *a13 + - $ref: "#/components/parameters/id" requestBody: required: true content: application/vnd.api+json: - schema: *a14 + schema: + $ref: "#/components/schemas/_toOneRelationshipRequest" responses: "200": description: Relationship updated - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" /post/{id}/comments: get: tags: @@ -1042,6 +1309,27 @@ paths: schema: type: string description: Filter by Comment ID + - name: filter[postId] + in: query + schema: + type: string + description: Filter by postId + - name: filter[postId][$lt] + in: query + schema: + type: string + - name: filter[postId][$lte] + in: query + schema: + type: string + - name: filter[postId][$gt] + in: query + schema: + type: string + - name: filter[postId][$gte] + in: query + schema: + type: string - name: filter[content] in: query schema: @@ -1074,7 +1362,12 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/CommentListResponse" - "404": *a1 + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" /post/{id}/relationships/comments: get: tags: @@ -1082,8 +1375,7 @@ paths: summary: Fetch comments relationship operationId: getPost_relationships_comments parameters: - - &a15 - $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/id" responses: "200": description: comments relationship @@ -1091,47 +1383,63 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/_toManyRelationshipWithLinks" - "404": *a1 + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" put: tags: - post summary: Replace comments relationship operationId: putPost_relationships_comments parameters: - - *a15 + - $ref: "#/components/parameters/id" requestBody: required: true content: application/vnd.api+json: - schema: &a16 + schema: $ref: "#/components/schemas/_toManyRelationshipRequest" responses: "200": description: Relationship updated - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" patch: tags: - post summary: Update comments relationship operationId: patchPost_relationships_comments parameters: - - *a15 + - $ref: "#/components/parameters/id" requestBody: required: true content: application/vnd.api+json: - schema: *a16 + schema: + $ref: "#/components/schemas/_toManyRelationshipRequest" responses: "200": description: Relationship updated - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" post: tags: - post summary: Add to comments collection relationship operationId: postPost_relationships_comments parameters: - - *a15 + - $ref: "#/components/parameters/id" requestBody: required: true content: @@ -1141,7 +1449,12 @@ paths: responses: "200": description: Added to relationship collection - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" /post/{id}/likes: get: tags: @@ -1171,7 +1484,12 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/PostLikeListResponse" - "404": *a1 + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" /post/{id}/relationships/likes: get: tags: @@ -1179,8 +1497,7 @@ paths: summary: Fetch likes relationship operationId: getPost_relationships_likes parameters: - - &a17 - $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/id" responses: "200": description: likes relationship @@ -1188,47 +1505,63 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/_toManyRelationshipWithLinks" - "404": *a1 + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" put: tags: - post summary: Replace likes relationship operationId: putPost_relationships_likes parameters: - - *a17 + - $ref: "#/components/parameters/id" requestBody: required: true content: application/vnd.api+json: - schema: &a18 + schema: $ref: "#/components/schemas/_toManyRelationshipRequest" responses: "200": description: Relationship updated - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" patch: tags: - post summary: Update likes relationship operationId: patchPost_relationships_likes parameters: - - *a17 + - $ref: "#/components/parameters/id" requestBody: required: true content: application/vnd.api+json: - schema: *a18 + schema: + $ref: "#/components/schemas/_toManyRelationshipRequest" responses: "200": description: Relationship updated - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" post: tags: - post summary: Add to likes collection relationship operationId: postPost_relationships_likes parameters: - - *a17 + - $ref: "#/components/parameters/id" requestBody: required: true content: @@ -1238,7 +1571,12 @@ paths: responses: "200": description: Added to relationship collection - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" /post/{id}/setting: get: tags: @@ -1255,7 +1593,12 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/SettingResponse" - "404": *a1 + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" /post/{id}/relationships/setting: get: tags: @@ -1263,8 +1606,7 @@ paths: summary: Fetch setting relationship operationId: getPost_relationships_setting parameters: - - &a19 - $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/id" responses: "200": description: setting relationship @@ -1272,40 +1614,56 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/_toOneRelationshipWithLinks" - "404": *a1 + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" put: tags: - post summary: Replace setting relationship operationId: putPost_relationships_setting parameters: - - *a19 + - $ref: "#/components/parameters/id" requestBody: required: true content: application/vnd.api+json: - schema: &a20 + schema: $ref: "#/components/schemas/_toOneRelationshipRequest" responses: "200": description: Relationship updated - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" patch: tags: - post summary: Update setting relationship operationId: patchPost_relationships_setting parameters: - - *a19 + - $ref: "#/components/parameters/id" requestBody: required: true content: application/vnd.api+json: - schema: *a20 + schema: + $ref: "#/components/schemas/_toOneRelationshipRequest" responses: "200": description: Relationship updated - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" /comment: get: tags: @@ -1322,6 +1680,27 @@ paths: schema: type: string description: Filter by Comment ID + - name: filter[postId] + in: query + schema: + type: string + description: Filter by postId + - name: filter[postId][$lt] + in: query + schema: + type: string + - name: filter[postId][$lte] + in: query + schema: + type: string + - name: filter[postId][$gt] + in: query + schema: + type: string + - name: filter[postId][$gte] + in: query + schema: + type: string - name: filter[content] in: query schema: @@ -1354,7 +1733,12 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/CommentListResponse" - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" post: tags: - comment @@ -1373,7 +1757,12 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/CommentResponse" - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" /comment/{id}: get: tags: @@ -1381,8 +1770,7 @@ paths: summary: Get a Comment resource by ID operationId: getComment parameters: - - &a21 - $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/id" - $ref: "#/components/parameters/include" responses: "200": @@ -1391,14 +1779,19 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/CommentResponse" - "404": *a1 + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" patch: tags: - comment summary: Update a Comment resource operationId: updateComment parameters: - - *a21 + - $ref: "#/components/parameters/id" requestBody: required: true content: @@ -1412,19 +1805,34 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/CommentResponse" - "400": *a1 - "404": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" delete: tags: - comment summary: Delete a Comment resource operationId: deleteComment parameters: - - *a21 + - $ref: "#/components/parameters/id" responses: "200": description: Deleted successfully - "404": *a1 + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" /comment/{id}/post: get: tags: @@ -1441,7 +1849,12 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/PostResponse" - "404": *a1 + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" /comment/{id}/relationships/post: get: tags: @@ -1449,8 +1862,7 @@ paths: summary: Fetch post relationship operationId: getComment_relationships_post parameters: - - &a22 - $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/id" responses: "200": description: post relationship @@ -1458,40 +1870,56 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/_toOneRelationshipWithLinks" - "404": *a1 + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" put: tags: - comment summary: Replace post relationship operationId: putComment_relationships_post parameters: - - *a22 + - $ref: "#/components/parameters/id" requestBody: required: true content: application/vnd.api+json: - schema: &a23 + schema: $ref: "#/components/schemas/_toOneRelationshipRequest" responses: "200": description: Relationship updated - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" patch: tags: - comment summary: Update post relationship operationId: patchComment_relationships_post parameters: - - *a22 + - $ref: "#/components/parameters/id" requestBody: required: true content: application/vnd.api+json: - schema: *a23 + schema: + $ref: "#/components/schemas/_toOneRelationshipRequest" responses: "200": description: Relationship updated - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" /setting: get: tags: @@ -1529,6 +1957,27 @@ paths: in: query schema: type: string + - name: filter[postId] + in: query + schema: + type: string + description: Filter by postId + - name: filter[postId][$lt] + in: query + schema: + type: string + - name: filter[postId][$lte] + in: query + schema: + type: string + - name: filter[postId][$gt] + in: query + schema: + type: string + - name: filter[postId][$gte] + in: query + schema: + type: string responses: "200": description: List of Setting resources @@ -1536,7 +1985,12 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/SettingListResponse" - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" post: tags: - setting @@ -1555,7 +2009,12 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/SettingResponse" - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" /setting/{id}: get: tags: @@ -1563,8 +2022,7 @@ paths: summary: Get a Setting resource by ID operationId: getSetting parameters: - - &a24 - $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/id" - $ref: "#/components/parameters/include" responses: "200": @@ -1573,14 +2031,19 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/SettingResponse" - "404": *a1 - patch: + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" + patch: tags: - setting summary: Update a Setting resource operationId: updateSetting parameters: - - *a24 + - $ref: "#/components/parameters/id" requestBody: required: true content: @@ -1594,19 +2057,34 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/SettingResponse" - "400": *a1 - "404": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" delete: tags: - setting summary: Delete a Setting resource operationId: deleteSetting parameters: - - *a24 + - $ref: "#/components/parameters/id" responses: "200": description: Deleted successfully - "404": *a1 + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" /setting/{id}/post: get: tags: @@ -1623,7 +2101,12 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/PostResponse" - "404": *a1 + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" /setting/{id}/relationships/post: get: tags: @@ -1631,8 +2114,7 @@ paths: summary: Fetch post relationship operationId: getSetting_relationships_post parameters: - - &a25 - $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/id" responses: "200": description: post relationship @@ -1640,40 +2122,56 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/_toOneRelationshipWithLinks" - "404": *a1 + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" put: tags: - setting summary: Replace post relationship operationId: putSetting_relationships_post parameters: - - *a25 + - $ref: "#/components/parameters/id" requestBody: required: true content: application/vnd.api+json: - schema: &a26 + schema: $ref: "#/components/schemas/_toOneRelationshipRequest" responses: "200": description: Relationship updated - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" patch: tags: - setting summary: Update post relationship operationId: patchSetting_relationships_post parameters: - - *a25 + - $ref: "#/components/parameters/id" requestBody: required: true content: application/vnd.api+json: - schema: *a26 + schema: + $ref: "#/components/schemas/_toOneRelationshipRequest" responses: "200": description: Relationship updated - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" /postLike: get: tags: @@ -1702,7 +2200,12 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/PostLikeListResponse" - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" post: tags: - postLike @@ -1721,7 +2224,12 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/PostLikeResponse" - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" /postLike/{id}: get: tags: @@ -1729,8 +2237,7 @@ paths: summary: Get a PostLike resource by ID operationId: getPostLike parameters: - - &a27 - $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/id" - $ref: "#/components/parameters/include" responses: "200": @@ -1739,14 +2246,19 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/PostLikeResponse" - "404": *a1 + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" patch: tags: - postLike summary: Update a PostLike resource operationId: updatePostLike parameters: - - *a27 + - $ref: "#/components/parameters/id" requestBody: required: true content: @@ -1760,19 +2272,34 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/PostLikeResponse" - "400": *a1 - "404": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" delete: tags: - postLike summary: Delete a PostLike resource operationId: deletePostLike parameters: - - *a27 + - $ref: "#/components/parameters/id" responses: "200": description: Deleted successfully - "404": *a1 + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" /postLike/{id}/post: get: tags: @@ -1789,7 +2316,12 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/PostResponse" - "404": *a1 + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" /postLike/{id}/relationships/post: get: tags: @@ -1797,8 +2329,7 @@ paths: summary: Fetch post relationship operationId: getPostLike_relationships_post parameters: - - &a28 - $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/id" responses: "200": description: post relationship @@ -1806,40 +2337,56 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/_toOneRelationshipWithLinks" - "404": *a1 + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" put: tags: - postLike summary: Replace post relationship operationId: putPostLike_relationships_post parameters: - - *a28 + - $ref: "#/components/parameters/id" requestBody: required: true content: application/vnd.api+json: - schema: &a29 + schema: $ref: "#/components/schemas/_toOneRelationshipRequest" responses: "200": description: Relationship updated - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" patch: tags: - postLike summary: Update post relationship operationId: patchPostLike_relationships_post parameters: - - *a28 + - $ref: "#/components/parameters/id" requestBody: required: true content: application/vnd.api+json: - schema: *a29 + schema: + $ref: "#/components/schemas/_toOneRelationshipRequest" responses: "200": description: Relationship updated - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" /postLike/{id}/user: get: tags: @@ -1856,7 +2403,12 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/UserResponse" - "404": *a1 + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" /postLike/{id}/relationships/user: get: tags: @@ -1864,8 +2416,7 @@ paths: summary: Fetch user relationship operationId: getPostLike_relationships_user parameters: - - &a30 - $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/id" responses: "200": description: user relationship @@ -1873,40 +2424,56 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/_toOneRelationshipWithLinks" - "404": *a1 + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" put: tags: - postLike summary: Replace user relationship operationId: putPostLike_relationships_user parameters: - - *a30 + - $ref: "#/components/parameters/id" requestBody: required: true content: application/vnd.api+json: - schema: &a31 + schema: $ref: "#/components/schemas/_toOneRelationshipRequest" responses: "200": description: Relationship updated - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" patch: tags: - postLike summary: Update user relationship operationId: patchPostLike_relationships_user parameters: - - *a30 + - $ref: "#/components/parameters/id" requestBody: required: true content: application/vnd.api+json: - schema: *a31 + schema: + $ref: "#/components/schemas/_toOneRelationshipRequest" responses: "200": description: Relationship updated - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" /postLike/{id}/likeInfos: get: tags: @@ -1949,6 +2516,52 @@ paths: in: query schema: type: string + - name: filter[postId] + in: query + schema: + type: string + description: Filter by postId + - name: filter[postId][$lt] + in: query + schema: + type: string + - name: filter[postId][$lte] + in: query + schema: + type: string + - name: filter[postId][$gt] + in: query + schema: + type: string + - name: filter[postId][$gte] + in: query + schema: + type: string + - name: filter[userId] + in: query + schema: + type: string + description: Filter by userId + - name: filter[userId][$contains] + in: query + schema: + type: string + - name: filter[userId][$icontains] + in: query + schema: + type: string + - name: filter[userId][$search] + in: query + schema: + type: string + - name: filter[userId][$startsWith] + in: query + schema: + type: string + - name: filter[userId][$endsWith] + in: query + schema: + type: string responses: "200": description: Related PostLikeInfo resource(s) @@ -1956,7 +2569,12 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/PostLikeInfoListResponse" - "404": *a1 + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" /postLike/{id}/relationships/likeInfos: get: tags: @@ -1964,8 +2582,7 @@ paths: summary: Fetch likeInfos relationship operationId: getPostLike_relationships_likeInfos parameters: - - &a32 - $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/id" responses: "200": description: likeInfos relationship @@ -1973,47 +2590,63 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/_toManyRelationshipWithLinks" - "404": *a1 + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" put: tags: - postLike summary: Replace likeInfos relationship operationId: putPostLike_relationships_likeInfos parameters: - - *a32 + - $ref: "#/components/parameters/id" requestBody: required: true content: application/vnd.api+json: - schema: &a33 + schema: $ref: "#/components/schemas/_toManyRelationshipRequest" responses: "200": description: Relationship updated - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" patch: tags: - postLike summary: Update likeInfos relationship operationId: patchPostLike_relationships_likeInfos parameters: - - *a32 + - $ref: "#/components/parameters/id" requestBody: required: true content: application/vnd.api+json: - schema: *a33 + schema: + $ref: "#/components/schemas/_toManyRelationshipRequest" responses: "200": description: Relationship updated - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" post: tags: - postLike summary: Add to likeInfos collection relationship operationId: postPostLike_relationships_likeInfos parameters: - - *a32 + - $ref: "#/components/parameters/id" requestBody: required: true content: @@ -2023,7 +2656,12 @@ paths: responses: "200": description: Added to relationship collection - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" /postLikeInfo: get: tags: @@ -2065,6 +2703,52 @@ paths: in: query schema: type: string + - name: filter[postId] + in: query + schema: + type: string + description: Filter by postId + - name: filter[postId][$lt] + in: query + schema: + type: string + - name: filter[postId][$lte] + in: query + schema: + type: string + - name: filter[postId][$gt] + in: query + schema: + type: string + - name: filter[postId][$gte] + in: query + schema: + type: string + - name: filter[userId] + in: query + schema: + type: string + description: Filter by userId + - name: filter[userId][$contains] + in: query + schema: + type: string + - name: filter[userId][$icontains] + in: query + schema: + type: string + - name: filter[userId][$search] + in: query + schema: + type: string + - name: filter[userId][$startsWith] + in: query + schema: + type: string + - name: filter[userId][$endsWith] + in: query + schema: + type: string responses: "200": description: List of PostLikeInfo resources @@ -2072,7 +2756,12 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/PostLikeInfoListResponse" - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" post: tags: - postLikeInfo @@ -2091,7 +2780,12 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/PostLikeInfoResponse" - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" /postLikeInfo/{id}: get: tags: @@ -2099,8 +2793,7 @@ paths: summary: Get a PostLikeInfo resource by ID operationId: getPostLikeInfo parameters: - - &a34 - $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/id" - $ref: "#/components/parameters/include" responses: "200": @@ -2109,14 +2802,19 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/PostLikeInfoResponse" - "404": *a1 + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" patch: tags: - postLikeInfo summary: Update a PostLikeInfo resource operationId: updatePostLikeInfo parameters: - - *a34 + - $ref: "#/components/parameters/id" requestBody: required: true content: @@ -2130,19 +2828,34 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/PostLikeInfoResponse" - "400": *a1 - "404": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" delete: tags: - postLikeInfo summary: Delete a PostLikeInfo resource operationId: deletePostLikeInfo parameters: - - *a34 + - $ref: "#/components/parameters/id" responses: "200": description: Deleted successfully - "404": *a1 + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" /postLikeInfo/{id}/postLike: get: tags: @@ -2159,7 +2872,12 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/PostLikeResponse" - "404": *a1 + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" /postLikeInfo/{id}/relationships/postLike: get: tags: @@ -2167,8 +2885,7 @@ paths: summary: Fetch postLike relationship operationId: getPostLikeInfo_relationships_postLike parameters: - - &a35 - $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/id" responses: "200": description: postLike relationship @@ -2176,40 +2893,56 @@ paths: application/vnd.api+json: schema: $ref: "#/components/schemas/_toOneRelationshipWithLinks" - "404": *a1 + "404": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" put: tags: - postLikeInfo summary: Replace postLike relationship operationId: putPostLikeInfo_relationships_postLike parameters: - - *a35 + - $ref: "#/components/parameters/id" requestBody: required: true content: application/vnd.api+json: - schema: &a36 + schema: $ref: "#/components/schemas/_toOneRelationshipRequest" responses: "200": description: Relationship updated - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" patch: tags: - postLikeInfo summary: Update postLike relationship operationId: patchPostLikeInfo_relationships_postLike parameters: - - *a35 + - $ref: "#/components/parameters/id" requestBody: required: true content: application/vnd.api+json: - schema: *a36 + schema: + $ref: "#/components/schemas/_toOneRelationshipRequest" responses: "200": description: Relationship updated - "400": *a1 + "400": + description: Error + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/_errorResponse" components: schemas: _jsonapi: @@ -2232,13 +2965,22 @@ components: _pagination: type: object properties: - first: &a37 + first: + oneOf: + - type: string + - type: "null" + last: + oneOf: + - type: string + - type: "null" + prev: + oneOf: + - type: string + - type: "null" + next: oneOf: - type: string - type: "null" - last: *a37 - prev: *a37 - next: *a37 _errors: type: array items: diff --git a/packages/server/test/openapi/baseline/rpc.baseline.yaml b/packages/server/test/openapi/baseline/rpc.baseline.yaml index b19f5243a..750a8fb8f 100644 --- a/packages/server/test/openapi/baseline/rpc.baseline.yaml +++ b/packages/server/test/openapi/baseline/rpc.baseline.yaml @@ -27,7 +27,7 @@ paths: application/json: schema: $ref: "#/components/schemas/UserListResponse" - "400": &a1 + "400": description: Error content: application/json: @@ -52,7 +52,12 @@ paths: application/json: schema: $ref: "#/components/schemas/UserResponse" - "400": *a1 + "400": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/_ErrorResponse" /user/findFirst: get: tags: @@ -72,7 +77,12 @@ paths: application/json: schema: $ref: "#/components/schemas/UserResponse" - "400": *a1 + "400": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/_ErrorResponse" /user/count: get: tags: @@ -92,7 +102,12 @@ paths: application/json: schema: $ref: "#/components/schemas/UserCountResponse" - "400": *a1 + "400": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/_ErrorResponse" /user/aggregate: get: tags: @@ -112,7 +127,12 @@ paths: application/json: schema: $ref: "#/components/schemas/UserAggregateResponse" - "400": *a1 + "400": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/_ErrorResponse" /user/groupBy: get: tags: @@ -132,7 +152,12 @@ paths: application/json: schema: $ref: "#/components/schemas/UserGroupByResponse" - "400": *a1 + "400": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/_ErrorResponse" /user/exists: get: tags: @@ -152,7 +177,12 @@ paths: application/json: schema: $ref: "#/components/schemas/_ExistsResponse" - "400": *a1 + "400": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/_ErrorResponse" /user/create: post: tags: @@ -172,7 +202,12 @@ paths: application/json: schema: $ref: "#/components/schemas/UserResponse" - "400": *a1 + "400": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/_ErrorResponse" /user/createMany: post: tags: @@ -192,7 +227,12 @@ paths: application/json: schema: $ref: "#/components/schemas/_BatchResponse" - "400": *a1 + "400": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/_ErrorResponse" /user/createManyAndReturn: post: tags: @@ -212,7 +252,12 @@ paths: application/json: schema: $ref: "#/components/schemas/UserListResponse" - "400": *a1 + "400": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/_ErrorResponse" /user/upsert: post: tags: @@ -232,7 +277,12 @@ paths: application/json: schema: $ref: "#/components/schemas/UserResponse" - "400": *a1 + "400": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/_ErrorResponse" /user/update: patch: tags: @@ -252,7 +302,12 @@ paths: application/json: schema: $ref: "#/components/schemas/UserResponse" - "400": *a1 + "400": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/_ErrorResponse" /user/updateMany: patch: tags: @@ -272,7 +327,12 @@ paths: application/json: schema: $ref: "#/components/schemas/_BatchResponse" - "400": *a1 + "400": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/_ErrorResponse" /user/updateManyAndReturn: patch: tags: @@ -292,7 +352,12 @@ paths: application/json: schema: $ref: "#/components/schemas/UserListResponse" - "400": *a1 + "400": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/_ErrorResponse" /user/delete: delete: tags: @@ -312,7 +377,12 @@ paths: application/json: schema: $ref: "#/components/schemas/UserResponse" - "400": *a1 + "400": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/_ErrorResponse" /user/deleteMany: delete: tags: @@ -332,7 +402,12 @@ paths: application/json: schema: $ref: "#/components/schemas/_BatchResponse" - "400": *a1 + "400": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/_ErrorResponse" /post/findMany: get: tags: @@ -352,7 +427,12 @@ paths: application/json: schema: $ref: "#/components/schemas/PostListResponse" - "400": *a1 + "400": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/_ErrorResponse" /post/findUnique: get: tags: @@ -372,7 +452,12 @@ paths: application/json: schema: $ref: "#/components/schemas/PostResponse" - "400": *a1 + "400": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/_ErrorResponse" /post/findFirst: get: tags: @@ -392,7 +477,12 @@ paths: application/json: schema: $ref: "#/components/schemas/PostResponse" - "400": *a1 + "400": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/_ErrorResponse" /post/count: get: tags: @@ -412,7 +502,12 @@ paths: application/json: schema: $ref: "#/components/schemas/PostCountResponse" - "400": *a1 + "400": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/_ErrorResponse" /post/aggregate: get: tags: @@ -432,7 +527,12 @@ paths: application/json: schema: $ref: "#/components/schemas/PostAggregateResponse" - "400": *a1 + "400": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/_ErrorResponse" /post/groupBy: get: tags: @@ -452,7 +552,12 @@ paths: application/json: schema: $ref: "#/components/schemas/PostGroupByResponse" - "400": *a1 + "400": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/_ErrorResponse" /post/exists: get: tags: @@ -472,7 +577,12 @@ paths: application/json: schema: $ref: "#/components/schemas/_ExistsResponse" - "400": *a1 + "400": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/_ErrorResponse" /post/create: post: tags: @@ -492,7 +602,12 @@ paths: application/json: schema: $ref: "#/components/schemas/PostResponse" - "400": *a1 + "400": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/_ErrorResponse" /post/createMany: post: tags: @@ -512,7 +627,12 @@ paths: application/json: schema: $ref: "#/components/schemas/_BatchResponse" - "400": *a1 + "400": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/_ErrorResponse" /post/createManyAndReturn: post: tags: @@ -532,7 +652,12 @@ paths: application/json: schema: $ref: "#/components/schemas/PostListResponse" - "400": *a1 + "400": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/_ErrorResponse" /post/upsert: post: tags: @@ -552,7 +677,12 @@ paths: application/json: schema: $ref: "#/components/schemas/PostResponse" - "400": *a1 + "400": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/_ErrorResponse" /post/update: patch: tags: @@ -572,7 +702,12 @@ paths: application/json: schema: $ref: "#/components/schemas/PostResponse" - "400": *a1 + "400": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/_ErrorResponse" /post/updateMany: patch: tags: @@ -592,7 +727,12 @@ paths: application/json: schema: $ref: "#/components/schemas/_BatchResponse" - "400": *a1 + "400": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/_ErrorResponse" /post/updateManyAndReturn: patch: tags: @@ -612,7 +752,12 @@ paths: application/json: schema: $ref: "#/components/schemas/PostListResponse" - "400": *a1 + "400": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/_ErrorResponse" /post/delete: delete: tags: @@ -632,7 +777,12 @@ paths: application/json: schema: $ref: "#/components/schemas/PostResponse" - "400": *a1 + "400": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/_ErrorResponse" /post/deleteMany: delete: tags: @@ -652,7 +802,12 @@ paths: application/json: schema: $ref: "#/components/schemas/_BatchResponse" - "400": *a1 + "400": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/_ErrorResponse" /$transaction/sequential: post: tags: @@ -680,7 +835,12 @@ paths: responses: "200": description: Transaction results - "400": *a1 + "400": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/_ErrorResponse" components: schemas: _Meta: @@ -714,6 +874,110 @@ components: type: boolean meta: $ref: "#/components/schemas/_Meta" + _StringFilter: + oneOf: + - type: string + - type: object + properties: + equals: + type: string + not: + type: string + in: + type: array + items: + type: string + notIn: + type: array + items: + type: string + contains: + type: string + startsWith: + type: string + endsWith: + type: string + mode: + type: string + enum: + - default + - insensitive + _DateTimeFilter: + oneOf: + - type: string + format: date-time + - type: object + properties: + equals: + type: string + format: date-time + not: + type: string + format: date-time + in: + type: array + items: + type: string + format: date-time + notIn: + type: array + items: + type: string + format: date-time + lt: + type: string + format: date-time + lte: + type: string + format: date-time + gt: + type: string + format: date-time + gte: + type: string + format: date-time + _BooleanFilter: + oneOf: + - type: boolean + - type: object + properties: + equals: + type: boolean + not: + type: boolean + in: + type: array + items: + type: boolean + notIn: + type: array + items: + type: boolean + _IntFilter: + oneOf: + - type: integer + - type: object + properties: + equals: + type: integer + not: + type: integer + in: + type: array + items: + type: integer + notIn: + type: array + items: + type: integer + lt: + type: integer + lte: + type: integer + gt: + type: integer + gte: + type: integer User: type: object properties: @@ -739,12 +1003,18 @@ components: UserCreateInput: type: object properties: + id: + type: string createdAt: type: string format: date-time + updatedAt: + type: string + format: date-time email: type: string required: + - updatedAt - email UserUpdateInput: type: object @@ -754,6 +1024,9 @@ components: createdAt: type: string format: date-time + updatedAt: + type: string + format: date-time email: type: string UserWhereUniqueInput: @@ -767,93 +1040,13 @@ components: type: object properties: id: - oneOf: - - &a2 - type: string - - type: object - properties: - equals: *a2 - not: *a2 - in: - type: array - items: *a2 - notIn: - type: array - items: *a2 - contains: - type: string - startsWith: - type: string - endsWith: - type: string - mode: - type: string - enum: - - default - - insensitive + $ref: "#/components/schemas/_StringFilter" createdAt: - oneOf: - - &a3 - type: string - format: date-time - - type: object - properties: - equals: *a3 - not: *a3 - in: - type: array - items: *a3 - notIn: - type: array - items: *a3 - lt: *a3 - lte: *a3 - gt: *a3 - gte: *a3 + $ref: "#/components/schemas/_DateTimeFilter" updatedAt: - oneOf: - - &a4 - type: string - format: date-time - - type: object - properties: - equals: *a4 - not: *a4 - in: - type: array - items: *a4 - notIn: - type: array - items: *a4 - lt: *a4 - lte: *a4 - gt: *a4 - gte: *a4 + $ref: "#/components/schemas/_DateTimeFilter" email: - oneOf: - - &a5 - type: string - - type: object - properties: - equals: *a5 - not: *a5 - in: - type: array - items: *a5 - notIn: - type: array - items: *a5 - contains: - type: string - startsWith: - type: string - endsWith: - type: string - mode: - type: string - enum: - - default - - insensitive + $ref: "#/components/schemas/_StringFilter" AND: oneOf: - $ref: "#/components/schemas/UserWhereInput" @@ -1309,11 +1502,18 @@ components: PostCreateInput: type: object properties: + id: + type: string createdAt: type: string format: date-time + updatedAt: + type: string + format: date-time title: type: string + authorId: + type: string published: type: boolean publishedAt: @@ -1322,6 +1522,7 @@ components: viewCount: type: integer required: + - updatedAt - title PostUpdateInput: type: object @@ -1331,8 +1532,13 @@ components: createdAt: type: string format: date-time + updatedAt: + type: string + format: date-time title: type: string + authorId: + type: string published: type: boolean publishedAt: @@ -1349,169 +1555,21 @@ components: type: object properties: id: - oneOf: - - &a6 - type: string - - type: object - properties: - equals: *a6 - not: *a6 - in: - type: array - items: *a6 - notIn: - type: array - items: *a6 - contains: - type: string - startsWith: - type: string - endsWith: - type: string - mode: - type: string - enum: - - default - - insensitive + $ref: "#/components/schemas/_StringFilter" createdAt: - oneOf: - - &a7 - type: string - format: date-time - - type: object - properties: - equals: *a7 - not: *a7 - in: - type: array - items: *a7 - notIn: - type: array - items: *a7 - lt: *a7 - lte: *a7 - gt: *a7 - gte: *a7 + $ref: "#/components/schemas/_DateTimeFilter" updatedAt: - oneOf: - - &a8 - type: string - format: date-time - - type: object - properties: - equals: *a8 - not: *a8 - in: - type: array - items: *a8 - notIn: - type: array - items: *a8 - lt: *a8 - lte: *a8 - gt: *a8 - gte: *a8 + $ref: "#/components/schemas/_DateTimeFilter" title: - oneOf: - - &a9 - type: string - - type: object - properties: - equals: *a9 - not: *a9 - in: - type: array - items: *a9 - notIn: - type: array - items: *a9 - contains: - type: string - startsWith: - type: string - endsWith: - type: string - mode: - type: string - enum: - - default - - insensitive + $ref: "#/components/schemas/_StringFilter" authorId: - oneOf: - - &a10 - type: string - - type: object - properties: - equals: *a10 - not: *a10 - in: - type: array - items: *a10 - notIn: - type: array - items: *a10 - contains: - type: string - startsWith: - type: string - endsWith: - type: string - mode: - type: string - enum: - - default - - insensitive + $ref: "#/components/schemas/_StringFilter" published: - oneOf: - - &a11 - type: boolean - - type: object - properties: - equals: *a11 - not: *a11 - in: - type: array - items: *a11 - notIn: - type: array - items: *a11 + $ref: "#/components/schemas/_BooleanFilter" publishedAt: - oneOf: - - &a12 - type: string - format: date-time - - type: object - properties: - equals: *a12 - not: *a12 - in: - type: array - items: *a12 - notIn: - type: array - items: *a12 - lt: *a12 - lte: *a12 - gt: *a12 - gte: *a12 + $ref: "#/components/schemas/_DateTimeFilter" viewCount: - oneOf: - - &a13 - type: integer - - type: object - properties: - equals: *a13 - not: *a13 - in: - type: array - items: *a13 - notIn: - type: array - items: *a13 - lt: *a13 - lte: *a13 - gt: *a13 - gte: *a13 + $ref: "#/components/schemas/_IntFilter" AND: oneOf: - $ref: "#/components/schemas/PostWhereInput" diff --git a/packages/server/test/openapi/rest-openapi.test.ts b/packages/server/test/openapi/rest-openapi.test.ts index 739470534..f235502af 100644 --- a/packages/server/test/openapi/rest-openapi.test.ts +++ b/packages/server/test/openapi/rest-openapi.test.ts @@ -13,7 +13,7 @@ function loadBaseline(name: string) { } function saveBaseline(name: string, spec: any) { - fs.writeFileSync(path.join(__dirname, 'baseline', name), YAML.stringify(spec, { lineWidth: 0, indent: 4 })); + fs.writeFileSync(path.join(__dirname, 'baseline', name), YAML.stringify(spec, { lineWidth: 0, indent: 4, aliasDuplicateObjects: false })); } const schema = ` diff --git a/packages/server/test/openapi/rpc-openapi.test.ts b/packages/server/test/openapi/rpc-openapi.test.ts index ecf036e7a..9d3117013 100644 --- a/packages/server/test/openapi/rpc-openapi.test.ts +++ b/packages/server/test/openapi/rpc-openapi.test.ts @@ -14,7 +14,7 @@ function loadBaseline(name: string) { } function saveBaseline(name: string, spec: any) { - fs.writeFileSync(path.join(__dirname, 'baseline', name), YAML.stringify(spec, { lineWidth: 0, indent: 4 })); + fs.writeFileSync(path.join(__dirname, 'baseline', name), YAML.stringify(spec, { lineWidth: 0, indent: 4, aliasDuplicateObjects: false })); } describe('RPC OpenAPI spec generation', () => { @@ -241,28 +241,30 @@ describe('RPC OpenAPI spec generation - queryOptions', () => { const s = await handler.generateSpec(); const whereInput = s.components?.schemas?.['PostWhereInput'] as any; - // String field (title): Equality + Like operators - const titleFilter = whereInput.properties['title']; - expect(titleFilter).toBeDefined(); - // oneOf [baseType, filterObject] - expect(titleFilter.oneOf).toHaveLength(2); - const titleFilterObj = titleFilter.oneOf[1]; - expect(titleFilterObj.properties['equals']).toBeDefined(); - expect(titleFilterObj.properties['not']).toBeDefined(); - expect(titleFilterObj.properties['in']).toBeDefined(); - expect(titleFilterObj.properties['contains']).toBeDefined(); - expect(titleFilterObj.properties['startsWith']).toBeDefined(); - expect(titleFilterObj.properties['endsWith']).toBeDefined(); - - // Int field (viewCount): Equality + Range operators - const vcFilter = whereInput.properties['viewCount']; - expect(vcFilter).toBeDefined(); - const vcFilterObj = vcFilter.oneOf[1]; - expect(vcFilterObj.properties['equals']).toBeDefined(); - expect(vcFilterObj.properties['lt']).toBeDefined(); - expect(vcFilterObj.properties['gte']).toBeDefined(); + // Default (no slicing) uses $ref to shared filter schemas + expect(whereInput.properties['title'].$ref).toBe('#/components/schemas/_StringFilter'); + expect(whereInput.properties['viewCount'].$ref).toBe('#/components/schemas/_IntFilter'); + + // Shared String filter: Equality + Like operators + const stringFilter = s.components?.schemas?.['_StringFilter'] as any; + expect(stringFilter.oneOf).toHaveLength(2); + const stringFilterObj = stringFilter.oneOf[1]; + expect(stringFilterObj.properties['equals']).toBeDefined(); + expect(stringFilterObj.properties['not']).toBeDefined(); + expect(stringFilterObj.properties['in']).toBeDefined(); + expect(stringFilterObj.properties['contains']).toBeDefined(); + expect(stringFilterObj.properties['startsWith']).toBeDefined(); + expect(stringFilterObj.properties['endsWith']).toBeDefined(); + + // Shared Int filter: Equality + Range operators + const intFilter = s.components?.schemas?.['_IntFilter'] as any; + expect(intFilter.oneOf).toHaveLength(2); + const intFilterObj = intFilter.oneOf[1]; + expect(intFilterObj.properties['equals']).toBeDefined(); + expect(intFilterObj.properties['lt']).toBeDefined(); + expect(intFilterObj.properties['gte']).toBeDefined(); // Should not have Like operators - expect(vcFilterObj.properties['contains']).toBeUndefined(); + expect(intFilterObj.properties['contains']).toBeUndefined(); }); it('slicing excludedFilterKinds removes specific operators from where input', async () => { From 63a5e4ee4b6d8cef438756f80d12758689374d84 Mon Sep 17 00:00:00 2001 From: ymc9 <104139426+ymc9@users.noreply.github.com> Date: Thu, 19 Mar 2026 19:50:40 -0700 Subject: [PATCH 14/16] refactor: temporarily remove rpc schema generator --- packages/server/src/api/index.ts | 3 +- packages/server/src/api/rpc/index.ts | 12 +- packages/server/src/api/rpc/openapi.ts | 1181 ---------- .../test/openapi/baseline/rpc.baseline.yaml | 2094 ----------------- .../server/test/openapi/rpc-openapi.test.ts | 832 ------- 5 files changed, 3 insertions(+), 4119 deletions(-) delete mode 100644 packages/server/src/api/rpc/openapi.ts delete mode 100644 packages/server/test/openapi/baseline/rpc.baseline.yaml delete mode 100644 packages/server/test/openapi/rpc-openapi.test.ts diff --git a/packages/server/src/api/index.ts b/packages/server/src/api/index.ts index 3efdc460b..b32662201 100644 --- a/packages/server/src/api/index.ts +++ b/packages/server/src/api/index.ts @@ -1,3 +1,2 @@ -export { RestApiHandler, type RestApiHandlerOptions } from './rest'; -export { RPCApiHandler, type RPCApiHandlerOptions } from './rpc'; export type { OpenApiSpecGenerator, OpenApiSpecOptions } from './common/types'; +export { RestApiHandler, type RestApiHandlerOptions } from './rest'; diff --git a/packages/server/src/api/rpc/index.ts b/packages/server/src/api/rpc/index.ts index 80d10ec1f..712170f9f 100644 --- a/packages/server/src/api/rpc/index.ts +++ b/packages/server/src/api/rpc/index.ts @@ -8,10 +8,9 @@ import { fromError } from 'zod-validation-error/v4'; import type { ApiHandler, LogConfig, RequestContext, Response } from '../../types'; import { getProcedureDef, mapProcedureArgs, PROCEDURE_ROUTE_PREFIXES } from '../common/procedures'; import { loggerSchema, queryOptionsSchema } from '../common/schemas'; -import type { CommonHandlerOptions, OpenApiSpecGenerator } from '../common/types'; +import type { CommonHandlerOptions } from '../common/types'; import { processSuperJsonRequestPayload, unmarshalQ } from '../common/utils'; import { log, registerCustomSerializers } from '../utils'; -import { RPCApiSpecGenerator } from './openapi'; const TRANSACTION_ROUTE_PREFIX = '$transaction' as const; const VALID_OPS = new Set(CoreCrudOperations as unknown as string[]); @@ -36,7 +35,7 @@ export type RPCApiHandlerOptions = { /** * RPC style API request handler that mirrors the ZenStackClient API */ -export class RPCApiHandler implements ApiHandler, OpenApiSpecGenerator { +export class RPCApiHandler implements ApiHandler { constructor(private readonly options: RPCApiHandlerOptions) { this.validateOptions(options); } @@ -450,11 +449,4 @@ export class RPCApiHandler implements ApiH } return { result: args, error: undefined }; } - - async generateSpec(options?: import('../common/types').OpenApiSpecOptions) { - const generator = new RPCApiSpecGenerator(this.options); - return generator.generateSpec(options); - } } - -export { RPCApiSpecGenerator } from './openapi'; diff --git a/packages/server/src/api/rpc/openapi.ts b/packages/server/src/api/rpc/openapi.ts deleted file mode 100644 index 7ff2844e3..000000000 --- a/packages/server/src/api/rpc/openapi.ts +++ /dev/null @@ -1,1181 +0,0 @@ -import { lowerCaseFirst, upperCaseFirst } from '@zenstackhq/common-helpers'; -import type { EnumDef, FieldDef, ModelDef, SchemaDef } from '@zenstackhq/orm/schema'; -import type { OpenAPIV3_1 } from 'openapi-types'; -import type { RPCApiHandlerOptions } from '.'; -import { PROCEDURE_ROUTE_PREFIXES } from '../common/procedures'; -import { - getIncludedModels, - getMetaDescription, - isFieldOmitted, - isFilterKindIncluded, - isModelIncluded, - isOperationIncluded, - isProcedureIncluded, -} from '../common/spec-utils'; -import type { OpenApiSpecOptions } from '../common/types'; - -type SchemaObject = OpenAPIV3_1.SchemaObject; -type ReferenceObject = OpenAPIV3_1.ReferenceObject; - -const ERROR_RESPONSE = { - description: 'Error', - content: { - 'application/json': { - schema: { $ref: '#/components/schemas/_ErrorResponse' }, - }, - }, -}; - -/** - * Generates OpenAPI v3.1 specification for the RPC-style CRUD API. - */ -export class RPCApiSpecGenerator { - constructor(private readonly handlerOptions: RPCApiHandlerOptions) {} - - private get schema(): SchemaDef { - return this.handlerOptions.schema; - } - - private get queryOptions() { - return this.handlerOptions?.queryOptions; - } - - generateSpec(options?: OpenApiSpecOptions): OpenAPIV3_1.Document { - return { - openapi: '3.1.0', - info: { - title: options?.title ?? 'ZenStack Generated API', - version: options?.version ?? '1.0.0', - ...(options?.description && { description: options.description }), - ...(options?.summary && { summary: options.summary }), - }, - tags: this.generateTags(), - paths: this.generatePaths(), - components: { - schemas: this.generateSchemas(), - }, - } as OpenAPIV3_1.Document; - } - - private generateTags(): OpenAPIV3_1.TagObject[] { - return getIncludedModels(this.schema, this.queryOptions).map((modelName) => ({ - name: lowerCaseFirst(modelName), - description: `${modelName} operations`, - })); - } - - private generatePaths(): OpenAPIV3_1.PathsObject { - const paths: OpenAPIV3_1.PathsObject = {}; - - for (const modelName of getIncludedModels(this.schema, this.queryOptions)) { - const modelPath = lowerCaseFirst(modelName); - const tag = modelPath; - - // Read operations (GET) - const readOps = ['findMany', 'findUnique', 'findFirst', 'count', 'aggregate', 'groupBy', 'exists']; - for (const op of readOps) { - if (!isOperationIncluded(modelName, op, this.queryOptions)) continue; - const argsSchemaName = `${modelName}${this.opToArgsSchema(op)}`; - const responseSchemaName = this.opToResponseSchema(modelName, op); - paths[`/${modelPath}/${op}`] = { - get: this.buildGetOperation(modelName, op, tag, argsSchemaName, responseSchemaName), - } as OpenAPIV3_1.PathItemObject; - } - - // Write operations - const writeOps: Array<{ op: string; method: 'post' | 'patch' | 'delete' }> = [ - { op: 'create', method: 'post' }, - { op: 'createMany', method: 'post' }, - { op: 'createManyAndReturn', method: 'post' }, - { op: 'upsert', method: 'post' }, - { op: 'update', method: 'patch' }, - { op: 'updateMany', method: 'patch' }, - { op: 'updateManyAndReturn', method: 'patch' }, - { op: 'delete', method: 'delete' }, - { op: 'deleteMany', method: 'delete' }, - ]; - - for (const { op, method } of writeOps) { - if (!isOperationIncluded(modelName, op, this.queryOptions)) continue; - const argsSchemaName = `${modelName}${this.opToArgsSchema(op)}`; - const responseSchemaName = this.opToResponseSchema(modelName, op); - const buildOp = - method === 'post' - ? this.buildPostOperation - : method === 'patch' - ? this.buildPatchOperation - : this.buildDeleteOperation; - paths[`/${modelPath}/${op}`] = { - [method]: buildOp.call(this, modelName, op, tag, argsSchemaName, responseSchemaName), - }; - } - } - - // Transaction path - paths['/$transaction/sequential'] = { - post: { - tags: ['$transaction'], - summary: 'Execute a sequential transaction', - operationId: 'transaction_sequential', - requestBody: { - required: true, - content: { - 'application/json': { - schema: { - type: 'array', - items: { - type: 'object', - properties: { - model: { type: 'string' }, - op: { type: 'string' }, - args: { type: 'object' }, - }, - required: ['model', 'op'], - }, - }, - }, - }, - }, - responses: { - '200': { description: 'Transaction results' }, - '400': ERROR_RESPONSE, - }, - }, - }; - - // Procedure paths - if (this.schema.procedures) { - for (const [procName, procDef] of Object.entries(this.schema.procedures)) { - if (!isProcedureIncluded(procName, this.queryOptions)) continue; - - const isMutation = !!procDef.mutation; - if (isMutation) { - paths[`/${PROCEDURE_ROUTE_PREFIXES}/${procName}`] = { - post: this.buildProcedureOperation(procName, 'post'), - } as OpenAPIV3_1.PathItemObject; - } else { - paths[`/${PROCEDURE_ROUTE_PREFIXES}/${procName}`] = { - get: this.buildProcedureOperation(procName, 'get'), - } as OpenAPIV3_1.PathItemObject; - } - } - } - - return paths; - } - - private opToArgsSchema(op: string): string { - return upperCaseFirst(op) + 'Args'; - } - - private opToResponseSchema(modelName: string, op: string): string { - switch (op) { - case 'findMany': - case 'createManyAndReturn': - case 'updateManyAndReturn': - return `${modelName}ListResponse`; - case 'createMany': - case 'updateMany': - case 'deleteMany': - return '_BatchResponse'; - case 'count': - return `${modelName}CountResponse`; - case 'aggregate': - return `${modelName}AggregateResponse`; - case 'groupBy': - return `${modelName}GroupByResponse`; - case 'exists': - return '_ExistsResponse'; - default: - // findUnique, findFirst, create, update, upsert, delete - return `${modelName}Response`; - } - } - - private modelHasRelations(modelName: string): boolean { - const modelDef = this.schema.models[modelName]; - if (!modelDef) return false; - return Object.values(modelDef.fields).some((f) => f.relation); - } - - private buildGetOperation( - modelName: string, - op: string, - tag: string, - argsSchemaName: string, - responseSchemaName: string, - ): Record { - return { - tags: [tag], - summary: `${op} ${modelName}`, - operationId: `${lowerCaseFirst(modelName)}_${op}`, - parameters: [ - { - name: 'q', - in: 'query', - description: `Arguments as JSON (${argsSchemaName})`, - schema: { type: 'string' }, - }, - ], - responses: { - '200': { - description: `Result of ${op}`, - content: { - 'application/json': { - schema: { $ref: `#/components/schemas/${responseSchemaName}` }, - }, - }, - }, - '400': ERROR_RESPONSE, - }, - }; - } - - private buildPostOperation( - modelName: string, - op: string, - tag: string, - argsSchemaName: string, - responseSchemaName: string, - ): Record { - return { - tags: [tag], - summary: `${op} ${modelName}`, - operationId: `${lowerCaseFirst(modelName)}_${op}`, - requestBody: { - required: true, - content: { - 'application/json': { - schema: { $ref: `#/components/schemas/${argsSchemaName}` }, - }, - }, - }, - responses: { - '201': { - description: `Result of ${op}`, - content: { - 'application/json': { - schema: { $ref: `#/components/schemas/${responseSchemaName}` }, - }, - }, - }, - '400': ERROR_RESPONSE, - }, - }; - } - - private buildPatchOperation( - modelName: string, - op: string, - tag: string, - argsSchemaName: string, - responseSchemaName: string, - ): Record { - return { - tags: [tag], - summary: `${op} ${modelName}`, - operationId: `${lowerCaseFirst(modelName)}_${op}`, - requestBody: { - required: true, - content: { - 'application/json': { - schema: { $ref: `#/components/schemas/${argsSchemaName}` }, - }, - }, - }, - responses: { - '200': { - description: `Result of ${op}`, - content: { - 'application/json': { - schema: { $ref: `#/components/schemas/${responseSchemaName}` }, - }, - }, - }, - '400': ERROR_RESPONSE, - }, - }; - } - - private buildDeleteOperation( - modelName: string, - op: string, - tag: string, - argsSchemaName: string, - responseSchemaName: string, - ): Record { - return { - tags: [tag], - summary: `${op} ${modelName}`, - operationId: `${lowerCaseFirst(modelName)}_${op}`, - parameters: [ - { - name: 'q', - in: 'query', - description: `Arguments as JSON (${argsSchemaName})`, - schema: { type: 'string' }, - }, - ], - responses: { - '200': { - description: `Result of ${op}`, - content: { - 'application/json': { - schema: { $ref: `#/components/schemas/${responseSchemaName}` }, - }, - }, - }, - '400': ERROR_RESPONSE, - }, - }; - } - - private buildProcedureOperation(procName: string, method: 'get' | 'post'): Record { - const op: Record = { - tags: [PROCEDURE_ROUTE_PREFIXES], - summary: `Execute procedure ${procName}`, - operationId: `proc_${procName}`, - responses: { - '200': { description: `Result of ${procName}` }, - '400': ERROR_RESPONSE, - }, - }; - - if (method === 'get') { - op['parameters'] = [ - { - name: 'q', - in: 'query', - description: 'Procedure arguments as JSON', - schema: { type: 'string' }, - }, - ]; - } else { - op['requestBody'] = { - content: { - 'application/json': { - schema: { type: 'object' }, - }, - }, - }; - } - - return op; - } - - private generateSchemas(): Record { - const schemas: Record = {}; - - // Shared schemas - schemas['_Meta'] = { - type: 'object', - properties: { serialization: {} }, - }; - schemas['_ErrorResponse'] = { - type: 'object', - properties: { - error: { - type: 'object', - properties: { - message: { type: 'string' }, - }, - }, - }, - }; - - // Shared response schemas - schemas['_BatchResponse'] = { - type: 'object', - properties: { - data: { - type: 'object', - properties: { count: { type: 'integer' } }, - required: ['count'], - }, - meta: { $ref: '#/components/schemas/_Meta' }, - }, - }; - schemas['_ExistsResponse'] = { - type: 'object', - properties: { - data: { type: 'boolean' }, - meta: { $ref: '#/components/schemas/_Meta' }, - }, - }; - - // Per-enum schemas - if (this.schema.enums) { - for (const [enumName, enumDef] of Object.entries(this.schema.enums)) { - schemas[enumName] = this.buildEnumSchema(enumDef); - } - } - - // Shared filter schemas for where inputs - this.generateFilterSchemas(schemas); - - // Per-model schemas - for (const modelName of getIncludedModels(this.schema, this.queryOptions)) { - const modelDef = this.schema.models[modelName]!; - schemas[modelName] = this.buildModelOutputSchema(modelName, modelDef); - schemas[`${modelName}CreateInput`] = this.buildCreateInputSchema(modelName, modelDef); - schemas[`${modelName}UpdateInput`] = this.buildUpdateInputSchema(modelName, modelDef); - schemas[`${modelName}WhereUniqueInput`] = this.buildWhereUniqueInputSchema(modelName, modelDef); - schemas[`${modelName}WhereInput`] = this.buildWhereInputSchema(modelName, modelDef); - schemas[`${modelName}Select`] = this.buildSelectSchema(modelName, modelDef); - if (this.modelHasRelations(modelName)) { - schemas[`${modelName}Include`] = this.buildIncludeSchema(modelName, modelDef); - } - schemas[`${modelName}Omit`] = this.buildOmitSchema(modelName, modelDef); - schemas[`${modelName}CreateArgs`] = this.buildCreateArgsSchema(modelName); - schemas[`${modelName}CreateManyArgs`] = this.buildCreateManyArgsSchema(modelName); - schemas[`${modelName}CreateManyAndReturnArgs`] = this.buildCreateManyAndReturnArgsSchema(modelName); - schemas[`${modelName}UpdateArgs`] = this.buildUpdateArgsSchema(modelName); - schemas[`${modelName}UpdateManyArgs`] = this.buildUpdateManyArgsSchema(modelName); - schemas[`${modelName}UpdateManyAndReturnArgs`] = this.buildUpdateManyAndReturnArgsSchema(modelName); - schemas[`${modelName}UpsertArgs`] = this.buildUpsertArgsSchema(modelName); - schemas[`${modelName}DeleteArgs`] = this.buildDeleteArgsSchema(modelName); - schemas[`${modelName}DeleteManyArgs`] = this.buildDeleteManyArgsSchema(modelName); - schemas[`${modelName}FindManyArgs`] = this.buildFindManyArgsSchema(modelName); - schemas[`${modelName}FindUniqueArgs`] = this.buildFindUniqueArgsSchema(modelName); - schemas[`${modelName}FindFirstArgs`] = this.buildFindFirstArgsSchema(modelName); - schemas[`${modelName}CountArgs`] = this.buildCountArgsSchema(modelName); - schemas[`${modelName}AggregateArgs`] = this.buildAggregateArgsSchema(modelName); - schemas[`${modelName}GroupByArgs`] = this.buildGroupByArgsSchema(modelName); - schemas[`${modelName}ExistsArgs`] = this.buildExistsArgsSchema(modelName); - schemas[`${modelName}Response`] = this.buildResponseSchema(modelName); - schemas[`${modelName}CountAggregateOutputType`] = this.buildCountAggregateOutputTypeSchema( - modelName, - modelDef, - ); - schemas[`${modelName}MinAggregateOutputType`] = this.buildMinAggregateOutputTypeSchema(modelName, modelDef); - schemas[`${modelName}MaxAggregateOutputType`] = this.buildMaxAggregateOutputTypeSchema(modelName, modelDef); - if (this.modelHasNumericFields(modelDef)) { - schemas[`${modelName}AvgAggregateOutputType`] = this.buildAvgAggregateOutputTypeSchema( - modelName, - modelDef, - ); - schemas[`${modelName}SumAggregateOutputType`] = this.buildSumAggregateOutputTypeSchema( - modelName, - modelDef, - ); - } - schemas[`Aggregate${modelName}`] = this.buildAggregateSchema(modelName, modelDef); - schemas[`${modelName}GroupByOutputType`] = this.buildGroupByOutputTypeSchema(modelName, modelDef); - schemas[`${modelName}CountResponse`] = { - type: 'object', - properties: { - data: { - oneOf: [ - { type: 'integer' }, - { $ref: `#/components/schemas/${modelName}CountAggregateOutputType` }, - ], - }, - meta: { $ref: '#/components/schemas/_Meta' }, - }, - }; - schemas[`${modelName}ListResponse`] = { - type: 'object', - properties: { - data: { type: 'array', items: { $ref: `#/components/schemas/${modelName}` } }, - meta: { $ref: '#/components/schemas/_Meta' }, - }, - }; - schemas[`${modelName}AggregateResponse`] = { - type: 'object', - properties: { - data: { $ref: `#/components/schemas/Aggregate${modelName}` }, - meta: { $ref: '#/components/schemas/_Meta' }, - }, - }; - schemas[`${modelName}GroupByResponse`] = { - type: 'object', - properties: { - data: { - type: 'array', - items: { $ref: `#/components/schemas/${modelName}GroupByOutputType` }, - }, - meta: { $ref: '#/components/schemas/_Meta' }, - }, - }; - } - - return schemas; - } - - private buildEnumSchema(enumDef: EnumDef): SchemaObject { - return { - type: 'string', - enum: Object.values(enumDef.values), - }; - } - - private buildSelectSchema(_modelName: string, modelDef: ModelDef): SchemaObject { - const properties: Record = {}; - for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { - if (fieldDef.relation) { - if (!isModelIncluded(fieldDef.type, this.queryOptions)) continue; - properties[fieldName] = this.buildRelationSelectProperty(fieldDef.type); - } else { - properties[fieldName] = { type: 'boolean' }; - } - } - return { type: 'object', properties }; - } - - private buildIncludeSchema(_modelName: string, modelDef: ModelDef): SchemaObject { - const properties: Record = {}; - for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { - if (!fieldDef.relation) continue; - if (!isModelIncluded(fieldDef.type, this.queryOptions)) continue; - properties[fieldName] = this.buildRelationSelectProperty(fieldDef.type); - } - return { type: 'object', properties }; - } - - private buildRelationSelectProperty(relatedModelName: string): SchemaObject { - const nestedProps: Record = { - select: { $ref: `#/components/schemas/${relatedModelName}Select` }, - omit: { $ref: `#/components/schemas/${relatedModelName}Omit` }, - }; - if (this.modelHasRelations(relatedModelName)) { - nestedProps['include'] = { $ref: `#/components/schemas/${relatedModelName}Include` }; - } - return { - oneOf: [{ type: 'boolean' }, { type: 'object', properties: nestedProps }], - }; - } - - private buildOmitSchema(_modelName: string, modelDef: ModelDef): SchemaObject { - const properties: Record = {}; - for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { - if (fieldDef.relation) continue; - properties[fieldName] = { type: 'boolean' }; - } - return { type: 'object', properties }; - } - - private buildModelOutputSchema(modelName: string, modelDef: ModelDef): SchemaObject { - const properties: Record = {}; - const required: string[] = []; - - for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { - if (fieldDef.omit) continue; - if (isFieldOmitted(modelName, fieldName, this.queryOptions)) continue; - const schema = this.fieldToSchema(fieldDef); - const fieldDescription = getMetaDescription(fieldDef.attributes); - if (fieldDescription && !('$ref' in schema)) { - schema.description = fieldDescription; - } - properties[fieldName] = schema; - if (!fieldDef.optional && !fieldDef.array) { - required.push(fieldName); - } - } - - const result: SchemaObject = { type: 'object', properties }; - if (required.length > 0) { - result.required = required; - } - const description = getMetaDescription(modelDef.attributes); - if (description) { - result.description = description; - } - return result; - } - - private buildCreateInputSchema(_modelName: string, modelDef: ModelDef): SchemaObject { - const properties: Record = {}; - const required: string[] = []; - - for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { - if (fieldDef.relation) continue; - properties[fieldName] = this.typeToSchema(fieldDef.type); - if (!fieldDef.optional && fieldDef.default === undefined && !fieldDef.array) { - required.push(fieldName); - } - } - - const result: SchemaObject = { type: 'object', properties }; - if (required.length > 0) { - result.required = required; - } - return result; - } - - private buildUpdateInputSchema(_modelName: string, modelDef: ModelDef): SchemaObject { - const properties: Record = {}; - - for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { - if (fieldDef.relation) continue; - properties[fieldName] = this.typeToSchema(fieldDef.type); - } - - return { type: 'object', properties }; - } - - private buildWhereUniqueInputSchema(_modelName: string, modelDef: ModelDef): SchemaObject { - const properties: Record = {}; - - // ID fields - for (const idFieldName of modelDef.idFields) { - const fieldDef = modelDef.fields[idFieldName]; - if (fieldDef) { - properties[idFieldName] = this.typeToSchema(fieldDef.type); - } - } - - // Unique fields - for (const [uniqueName, uniqueInfo] of Object.entries(modelDef.uniqueFields)) { - if ('type' in uniqueInfo && typeof uniqueInfo.type === 'string') { - // Single unique field - const fieldDef = modelDef.fields[uniqueName]; - if (fieldDef && !properties[uniqueName]) { - properties[uniqueName] = this.typeToSchema(fieldDef.type); - } - } else { - // Compound unique - properties[uniqueName] = { type: 'object' }; - } - } - - return { type: 'object', properties }; - } - - private buildWhereInputSchema(modelName: string, modelDef: ModelDef): SchemaObject { - const properties: Record = {}; - - for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { - if (fieldDef.relation) continue; - const filterSchema = this.buildFieldFilterSchema(modelName, fieldName, fieldDef); - if (filterSchema) { - properties[fieldName] = filterSchema; - } - } - - // Logical combinators - properties['AND'] = { - oneOf: [ - { $ref: `#/components/schemas/${modelName}WhereInput` }, - { type: 'array', items: { $ref: `#/components/schemas/${modelName}WhereInput` } }, - ], - }; - properties['OR'] = { - type: 'array', - items: { $ref: `#/components/schemas/${modelName}WhereInput` }, - }; - properties['NOT'] = { - oneOf: [ - { $ref: `#/components/schemas/${modelName}WhereInput` }, - { type: 'array', items: { $ref: `#/components/schemas/${modelName}WhereInput` } }, - ], - }; - - return { type: 'object', properties }; - } - - private selectIncludeOmitProperties(modelName: string): Record { - return { - select: { $ref: `#/components/schemas/${modelName}Select` }, - ...(this.modelHasRelations(modelName) && { - include: { $ref: `#/components/schemas/${modelName}Include` }, - }), - omit: { $ref: `#/components/schemas/${modelName}Omit` }, - }; - } - - private buildCreateArgsSchema(modelName: string): SchemaObject { - return { - type: 'object', - properties: { - data: { $ref: `#/components/schemas/${modelName}CreateInput` }, - ...this.selectIncludeOmitProperties(modelName), - }, - required: ['data'], - }; - } - - private buildCreateManyArgsSchema(modelName: string): SchemaObject { - return { - type: 'object', - properties: { - data: { - type: 'array', - items: { $ref: `#/components/schemas/${modelName}CreateInput` }, - }, - }, - required: ['data'], - }; - } - - private buildCreateManyAndReturnArgsSchema(modelName: string): SchemaObject { - return { - type: 'object', - properties: { - data: { - type: 'array', - items: { $ref: `#/components/schemas/${modelName}CreateInput` }, - }, - ...this.selectIncludeOmitProperties(modelName), - }, - required: ['data'], - }; - } - - private buildUpdateArgsSchema(modelName: string): SchemaObject { - return { - type: 'object', - properties: { - where: { $ref: `#/components/schemas/${modelName}WhereUniqueInput` }, - data: { $ref: `#/components/schemas/${modelName}UpdateInput` }, - ...this.selectIncludeOmitProperties(modelName), - }, - required: ['where', 'data'], - }; - } - - private buildUpdateManyArgsSchema(modelName: string): SchemaObject { - return { - type: 'object', - properties: { - where: { $ref: `#/components/schemas/${modelName}WhereInput` }, - data: { $ref: `#/components/schemas/${modelName}UpdateInput` }, - }, - required: ['data'], - }; - } - - private buildUpdateManyAndReturnArgsSchema(modelName: string): SchemaObject { - return { - type: 'object', - properties: { - where: { $ref: `#/components/schemas/${modelName}WhereInput` }, - data: { $ref: `#/components/schemas/${modelName}UpdateInput` }, - ...this.selectIncludeOmitProperties(modelName), - }, - required: ['data'], - }; - } - - private buildUpsertArgsSchema(modelName: string): SchemaObject { - return { - type: 'object', - properties: { - where: { $ref: `#/components/schemas/${modelName}WhereUniqueInput` }, - create: { $ref: `#/components/schemas/${modelName}CreateInput` }, - update: { $ref: `#/components/schemas/${modelName}UpdateInput` }, - ...this.selectIncludeOmitProperties(modelName), - }, - required: ['where', 'create', 'update'], - }; - } - - private buildDeleteArgsSchema(modelName: string): SchemaObject { - return { - type: 'object', - properties: { - where: { $ref: `#/components/schemas/${modelName}WhereUniqueInput` }, - ...this.selectIncludeOmitProperties(modelName), - }, - required: ['where'], - }; - } - - private buildDeleteManyArgsSchema(modelName: string): SchemaObject { - return { - type: 'object', - properties: { - where: { $ref: `#/components/schemas/${modelName}WhereInput` }, - }, - }; - } - - private buildFindManyArgsSchema(modelName: string): SchemaObject { - return { - type: 'object', - properties: { - where: { $ref: `#/components/schemas/${modelName}WhereInput` }, - orderBy: { type: 'object' }, - take: { type: 'integer' }, - skip: { type: 'integer' }, - ...this.selectIncludeOmitProperties(modelName), - }, - }; - } - - private buildFindUniqueArgsSchema(modelName: string): SchemaObject { - return { - type: 'object', - properties: { - where: { $ref: `#/components/schemas/${modelName}WhereUniqueInput` }, - ...this.selectIncludeOmitProperties(modelName), - }, - required: ['where'], - }; - } - - private buildFindFirstArgsSchema(modelName: string): SchemaObject { - return { - type: 'object', - properties: { - where: { $ref: `#/components/schemas/${modelName}WhereInput` }, - orderBy: { type: 'object' }, - take: { type: 'integer' }, - skip: { type: 'integer' }, - ...this.selectIncludeOmitProperties(modelName), - }, - }; - } - - private buildCountArgsSchema(modelName: string): SchemaObject { - return { - type: 'object', - properties: { - select: { $ref: `#/components/schemas/${modelName}Select` }, - where: { $ref: `#/components/schemas/${modelName}WhereInput` }, - take: { type: 'integer' }, - skip: { type: 'integer' }, - }, - }; - } - - private modelHasNumericFields(modelDef: ModelDef): boolean { - return Object.values(modelDef.fields).some( - (f) => - !f.relation && (f.type === 'Int' || f.type === 'Float' || f.type === 'BigInt' || f.type === 'Decimal'), - ); - } - - private buildCountAggregateOutputTypeSchema(_modelName: string, modelDef: ModelDef): SchemaObject { - const properties: Record = {}; - const required: string[] = []; - for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { - if (fieldDef.relation) continue; - properties[fieldName] = { type: 'integer' }; - required.push(fieldName); - } - properties['_all'] = { type: 'integer' }; - required.push('_all'); - return { type: 'object', properties, required }; - } - - private buildMinAggregateOutputTypeSchema(_modelName: string, modelDef: ModelDef): SchemaObject { - const properties: Record = {}; - for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { - if (fieldDef.relation) continue; - properties[fieldName] = { oneOf: [{ type: 'null' as const }, this.typeToSchema(fieldDef.type)] }; - } - return { type: 'object', properties }; - } - - private buildMaxAggregateOutputTypeSchema(_modelName: string, modelDef: ModelDef): SchemaObject { - const properties: Record = {}; - for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { - if (fieldDef.relation) continue; - properties[fieldName] = { oneOf: [{ type: 'null' as const }, this.typeToSchema(fieldDef.type)] }; - } - return { type: 'object', properties }; - } - - private buildAvgAggregateOutputTypeSchema(_modelName: string, modelDef: ModelDef): SchemaObject { - const properties: Record = {}; - for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { - if (fieldDef.relation) continue; - if ( - fieldDef.type !== 'Int' && - fieldDef.type !== 'Float' && - fieldDef.type !== 'BigInt' && - fieldDef.type !== 'Decimal' - ) - continue; - // avg always returns a float - properties[fieldName] = { oneOf: [{ type: 'null' as const }, { type: 'number' }] }; - } - return { type: 'object', properties }; - } - - private buildSumAggregateOutputTypeSchema(_modelName: string, modelDef: ModelDef): SchemaObject { - const properties: Record = {}; - for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { - if (fieldDef.relation) continue; - if ( - fieldDef.type !== 'Int' && - fieldDef.type !== 'Float' && - fieldDef.type !== 'BigInt' && - fieldDef.type !== 'Decimal' - ) - continue; - // sum preserves the original type - properties[fieldName] = { oneOf: [{ type: 'null' as const }, this.typeToSchema(fieldDef.type)] }; - } - return { type: 'object', properties }; - } - - private buildAggregateSchema(modelName: string, modelDef: ModelDef): SchemaObject { - const properties: Record = { - _count: { - oneOf: [ - { type: 'null' as const }, - { $ref: `#/components/schemas/${modelName}CountAggregateOutputType` }, - ], - }, - _min: { - oneOf: [{ type: 'null' as const }, { $ref: `#/components/schemas/${modelName}MinAggregateOutputType` }], - }, - _max: { - oneOf: [{ type: 'null' as const }, { $ref: `#/components/schemas/${modelName}MaxAggregateOutputType` }], - }, - }; - if (this.modelHasNumericFields(modelDef)) { - properties['_avg'] = { - oneOf: [{ type: 'null' as const }, { $ref: `#/components/schemas/${modelName}AvgAggregateOutputType` }], - }; - properties['_sum'] = { - oneOf: [{ type: 'null' as const }, { $ref: `#/components/schemas/${modelName}SumAggregateOutputType` }], - }; - } - return { type: 'object', properties }; - } - - private buildGroupByOutputTypeSchema(modelName: string, modelDef: ModelDef): SchemaObject { - const properties: Record = {}; - const required: string[] = []; - - // Scalar fields with proper types - for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { - if (fieldDef.relation) continue; - properties[fieldName] = this.fieldToSchema(fieldDef); - if (!fieldDef.optional && !fieldDef.array) { - required.push(fieldName); - } - } - - // Aggregate properties - properties['_count'] = { - oneOf: [{ type: 'null' as const }, { $ref: `#/components/schemas/${modelName}CountAggregateOutputType` }], - }; - properties['_min'] = { - oneOf: [{ type: 'null' as const }, { $ref: `#/components/schemas/${modelName}MinAggregateOutputType` }], - }; - properties['_max'] = { - oneOf: [{ type: 'null' as const }, { $ref: `#/components/schemas/${modelName}MaxAggregateOutputType` }], - }; - if (this.modelHasNumericFields(modelDef)) { - properties['_avg'] = { - oneOf: [{ type: 'null' as const }, { $ref: `#/components/schemas/${modelName}AvgAggregateOutputType` }], - }; - properties['_sum'] = { - oneOf: [{ type: 'null' as const }, { $ref: `#/components/schemas/${modelName}SumAggregateOutputType` }], - }; - } - - const result: SchemaObject = { type: 'object', properties }; - if (required.length > 0) { - result.required = required; - } - return result; - } - - private buildAggregateArgsSchema(modelName: string): SchemaObject { - return { - type: 'object', - properties: { - where: { $ref: `#/components/schemas/${modelName}WhereInput` }, - orderBy: { type: 'object' }, - take: { type: 'integer' }, - skip: { type: 'integer' }, - }, - }; - } - - private buildGroupByArgsSchema(modelName: string): SchemaObject { - return { - type: 'object', - properties: { - where: { $ref: `#/components/schemas/${modelName}WhereInput` }, - by: { type: 'array', items: { type: 'string' } }, - orderBy: { type: 'object' }, - take: { type: 'integer' }, - skip: { type: 'integer' }, - }, - }; - } - - private buildExistsArgsSchema(modelName: string): SchemaObject { - return { - type: 'object', - properties: { - where: { $ref: `#/components/schemas/${modelName}WhereUniqueInput` }, - }, - required: ['where'], - }; - } - - private buildResponseSchema(modelName: string): SchemaObject { - return { - type: 'object', - properties: { - data: { $ref: `#/components/schemas/${modelName}` }, - meta: { $ref: '#/components/schemas/_Meta' }, - }, - }; - } - - private fieldToSchema(fieldDef: FieldDef): SchemaObject | ReferenceObject { - const baseSchema = this.typeToSchema(fieldDef.type); - if (fieldDef.array) { - return { type: 'array', items: baseSchema }; - } - if (fieldDef.optional) { - return { oneOf: [baseSchema, { type: 'null' }] }; - } - return baseSchema; - } - - /** - * Generates shared filter schemas for all field types used across models. - */ - private generateFilterSchemas(schemas: Record): void { - const filters = new Map(); - - for (const modelName of getIncludedModels(this.schema, this.queryOptions)) { - const modelDef = this.schema.models[modelName]!; - for (const [, fieldDef] of Object.entries(modelDef.fields)) { - if (fieldDef.relation) continue; - const name = this.filterSchemaName(fieldDef.type, !!fieldDef.array); - if (!filters.has(name)) { - filters.set(name, { type: fieldDef.type, array: !!fieldDef.array }); - } - } - } - - for (const [name, { type, array }] of filters) { - schemas[name] = this.buildFilterSchema(type, array)!; - } - } - - /** - * Returns the schema name for a shared filter (e.g. "_StringFilter", "_IntListFilter"). - */ - private filterSchemaName(type: string, array: boolean): string { - return array ? `_${type}ListFilter` : `_${type}Filter`; - } - - /** - * Builds a filter schema for a given field type. When `fieldContext` is provided, - * only filter kinds that pass `isFilterKindIncluded` are included; otherwise all - * applicable filter kinds are included (used for shared filter schemas). - */ - private buildFilterSchema( - type: string, - array: boolean, - fieldContext?: { modelName: string; fieldName: string }, - ): SchemaObject | undefined { - const includeKind = (kind: string) => - !fieldContext || - isFilterKindIncluded(fieldContext.modelName, fieldContext.fieldName, kind, this.queryOptions); - - const baseSchema = this.typeToSchema(type); - const filterProps: Record = {}; - - // Equality operators - if (includeKind('Equality')) { - filterProps['equals'] = baseSchema; - filterProps['not'] = baseSchema; - filterProps['in'] = { type: 'array', items: baseSchema }; - filterProps['notIn'] = { type: 'array', items: baseSchema }; - } - - // Range operators (numeric/datetime types) - if ( - (type === 'Int' || type === 'Float' || type === 'BigInt' || type === 'Decimal' || type === 'DateTime') && - includeKind('Range') - ) { - filterProps['lt'] = baseSchema; - filterProps['lte'] = baseSchema; - filterProps['gt'] = baseSchema; - filterProps['gte'] = baseSchema; - } - - // Like operators (String type) - if (type === 'String' && includeKind('Like')) { - filterProps['contains'] = { type: 'string' }; - filterProps['startsWith'] = { type: 'string' }; - filterProps['endsWith'] = { type: 'string' }; - filterProps['mode'] = { type: 'string', enum: ['default', 'insensitive'] }; - } - - // List operators (array fields) - if (array && includeKind('List')) { - filterProps['has'] = baseSchema; - filterProps['hasEvery'] = { type: 'array', items: baseSchema }; - filterProps['hasSome'] = { type: 'array', items: baseSchema }; - filterProps['isEmpty'] = { type: 'boolean' }; - } - - if (Object.keys(filterProps).length === 0) return undefined; - - const filterObject: SchemaObject = { type: 'object', properties: filterProps }; - - // If Equality is included, allow shorthand (direct value) via oneOf - if (includeKind('Equality')) { - return { oneOf: [baseSchema, filterObject] }; - } - - return filterObject; - } - - /** - * Returns true if no field-level filter slicing is configured for this model/field. - */ - private hasDefaultFilters(modelName: string, fieldName: string): boolean { - const slicing = this.queryOptions?.slicing; - if (!slicing?.models) return true; - - const modelKey = lowerCaseFirst(modelName); - const modelSlicing = (slicing.models as Record)[modelKey] ?? (slicing.models as any).$all; - if (!modelSlicing?.fields) return true; - - const fieldSlicing = modelSlicing.fields[fieldName] ?? modelSlicing.fields.$all; - return !fieldSlicing; - } - - private buildFieldFilterSchema( - modelName: string, - fieldName: string, - fieldDef: FieldDef, - ): SchemaObject | ReferenceObject | undefined { - // If no slicing customization, reference the shared filter schema - if (this.hasDefaultFilters(modelName, fieldName)) { - const name = this.filterSchemaName(fieldDef.type, !!fieldDef.array); - return { $ref: `#/components/schemas/${name}` }; - } - - // Slicing is active — build inline filter with only included filter kinds - return this.buildFilterSchema(fieldDef.type, !!fieldDef.array, { modelName, fieldName }); - } - - private typeToSchema(type: string): SchemaObject | ReferenceObject { - switch (type) { - case 'String': - return { type: 'string' }; - case 'Int': - case 'BigInt': - return { type: 'integer' }; - case 'Float': - return { type: 'number' }; - case 'Decimal': - return { oneOf: [{ type: 'number' }, { type: 'string' }] }; - case 'Boolean': - return { type: 'boolean' }; - case 'DateTime': - return { type: 'string', format: 'date-time' }; - case 'Bytes': - return { type: 'string', format: 'byte' }; - case 'Json': - case 'Unsupported': - return {}; - default: - return { $ref: `#/components/schemas/${type}` }; - } - } -} diff --git a/packages/server/test/openapi/baseline/rpc.baseline.yaml b/packages/server/test/openapi/baseline/rpc.baseline.yaml deleted file mode 100644 index 750a8fb8f..000000000 --- a/packages/server/test/openapi/baseline/rpc.baseline.yaml +++ /dev/null @@ -1,2094 +0,0 @@ -openapi: 3.1.0 -info: - title: ZenStack Generated API - version: 1.0.0 -tags: - - name: user - description: User operations - - name: post - description: Post operations -paths: - /user/findMany: - get: - tags: - - user - summary: findMany User - operationId: user_findMany - parameters: - - name: q - in: query - description: Arguments as JSON (UserFindManyArgs) - schema: - type: string - responses: - "200": - description: Result of findMany - content: - application/json: - schema: - $ref: "#/components/schemas/UserListResponse" - "400": - description: Error - content: - application/json: - schema: - $ref: "#/components/schemas/_ErrorResponse" - /user/findUnique: - get: - tags: - - user - summary: findUnique User - operationId: user_findUnique - parameters: - - name: q - in: query - description: Arguments as JSON (UserFindUniqueArgs) - schema: - type: string - responses: - "200": - description: Result of findUnique - content: - application/json: - schema: - $ref: "#/components/schemas/UserResponse" - "400": - description: Error - content: - application/json: - schema: - $ref: "#/components/schemas/_ErrorResponse" - /user/findFirst: - get: - tags: - - user - summary: findFirst User - operationId: user_findFirst - parameters: - - name: q - in: query - description: Arguments as JSON (UserFindFirstArgs) - schema: - type: string - responses: - "200": - description: Result of findFirst - content: - application/json: - schema: - $ref: "#/components/schemas/UserResponse" - "400": - description: Error - content: - application/json: - schema: - $ref: "#/components/schemas/_ErrorResponse" - /user/count: - get: - tags: - - user - summary: count User - operationId: user_count - parameters: - - name: q - in: query - description: Arguments as JSON (UserCountArgs) - schema: - type: string - responses: - "200": - description: Result of count - content: - application/json: - schema: - $ref: "#/components/schemas/UserCountResponse" - "400": - description: Error - content: - application/json: - schema: - $ref: "#/components/schemas/_ErrorResponse" - /user/aggregate: - get: - tags: - - user - summary: aggregate User - operationId: user_aggregate - parameters: - - name: q - in: query - description: Arguments as JSON (UserAggregateArgs) - schema: - type: string - responses: - "200": - description: Result of aggregate - content: - application/json: - schema: - $ref: "#/components/schemas/UserAggregateResponse" - "400": - description: Error - content: - application/json: - schema: - $ref: "#/components/schemas/_ErrorResponse" - /user/groupBy: - get: - tags: - - user - summary: groupBy User - operationId: user_groupBy - parameters: - - name: q - in: query - description: Arguments as JSON (UserGroupByArgs) - schema: - type: string - responses: - "200": - description: Result of groupBy - content: - application/json: - schema: - $ref: "#/components/schemas/UserGroupByResponse" - "400": - description: Error - content: - application/json: - schema: - $ref: "#/components/schemas/_ErrorResponse" - /user/exists: - get: - tags: - - user - summary: exists User - operationId: user_exists - parameters: - - name: q - in: query - description: Arguments as JSON (UserExistsArgs) - schema: - type: string - responses: - "200": - description: Result of exists - content: - application/json: - schema: - $ref: "#/components/schemas/_ExistsResponse" - "400": - description: Error - content: - application/json: - schema: - $ref: "#/components/schemas/_ErrorResponse" - /user/create: - post: - tags: - - user - summary: create User - operationId: user_create - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/UserCreateArgs" - responses: - "201": - description: Result of create - content: - application/json: - schema: - $ref: "#/components/schemas/UserResponse" - "400": - description: Error - content: - application/json: - schema: - $ref: "#/components/schemas/_ErrorResponse" - /user/createMany: - post: - tags: - - user - summary: createMany User - operationId: user_createMany - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/UserCreateManyArgs" - responses: - "201": - description: Result of createMany - content: - application/json: - schema: - $ref: "#/components/schemas/_BatchResponse" - "400": - description: Error - content: - application/json: - schema: - $ref: "#/components/schemas/_ErrorResponse" - /user/createManyAndReturn: - post: - tags: - - user - summary: createManyAndReturn User - operationId: user_createManyAndReturn - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/UserCreateManyAndReturnArgs" - responses: - "201": - description: Result of createManyAndReturn - content: - application/json: - schema: - $ref: "#/components/schemas/UserListResponse" - "400": - description: Error - content: - application/json: - schema: - $ref: "#/components/schemas/_ErrorResponse" - /user/upsert: - post: - tags: - - user - summary: upsert User - operationId: user_upsert - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/UserUpsertArgs" - responses: - "201": - description: Result of upsert - content: - application/json: - schema: - $ref: "#/components/schemas/UserResponse" - "400": - description: Error - content: - application/json: - schema: - $ref: "#/components/schemas/_ErrorResponse" - /user/update: - patch: - tags: - - user - summary: update User - operationId: user_update - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/UserUpdateArgs" - responses: - "200": - description: Result of update - content: - application/json: - schema: - $ref: "#/components/schemas/UserResponse" - "400": - description: Error - content: - application/json: - schema: - $ref: "#/components/schemas/_ErrorResponse" - /user/updateMany: - patch: - tags: - - user - summary: updateMany User - operationId: user_updateMany - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/UserUpdateManyArgs" - responses: - "200": - description: Result of updateMany - content: - application/json: - schema: - $ref: "#/components/schemas/_BatchResponse" - "400": - description: Error - content: - application/json: - schema: - $ref: "#/components/schemas/_ErrorResponse" - /user/updateManyAndReturn: - patch: - tags: - - user - summary: updateManyAndReturn User - operationId: user_updateManyAndReturn - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/UserUpdateManyAndReturnArgs" - responses: - "200": - description: Result of updateManyAndReturn - content: - application/json: - schema: - $ref: "#/components/schemas/UserListResponse" - "400": - description: Error - content: - application/json: - schema: - $ref: "#/components/schemas/_ErrorResponse" - /user/delete: - delete: - tags: - - user - summary: delete User - operationId: user_delete - parameters: - - name: q - in: query - description: Arguments as JSON (UserDeleteArgs) - schema: - type: string - responses: - "200": - description: Result of delete - content: - application/json: - schema: - $ref: "#/components/schemas/UserResponse" - "400": - description: Error - content: - application/json: - schema: - $ref: "#/components/schemas/_ErrorResponse" - /user/deleteMany: - delete: - tags: - - user - summary: deleteMany User - operationId: user_deleteMany - parameters: - - name: q - in: query - description: Arguments as JSON (UserDeleteManyArgs) - schema: - type: string - responses: - "200": - description: Result of deleteMany - content: - application/json: - schema: - $ref: "#/components/schemas/_BatchResponse" - "400": - description: Error - content: - application/json: - schema: - $ref: "#/components/schemas/_ErrorResponse" - /post/findMany: - get: - tags: - - post - summary: findMany Post - operationId: post_findMany - parameters: - - name: q - in: query - description: Arguments as JSON (PostFindManyArgs) - schema: - type: string - responses: - "200": - description: Result of findMany - content: - application/json: - schema: - $ref: "#/components/schemas/PostListResponse" - "400": - description: Error - content: - application/json: - schema: - $ref: "#/components/schemas/_ErrorResponse" - /post/findUnique: - get: - tags: - - post - summary: findUnique Post - operationId: post_findUnique - parameters: - - name: q - in: query - description: Arguments as JSON (PostFindUniqueArgs) - schema: - type: string - responses: - "200": - description: Result of findUnique - content: - application/json: - schema: - $ref: "#/components/schemas/PostResponse" - "400": - description: Error - content: - application/json: - schema: - $ref: "#/components/schemas/_ErrorResponse" - /post/findFirst: - get: - tags: - - post - summary: findFirst Post - operationId: post_findFirst - parameters: - - name: q - in: query - description: Arguments as JSON (PostFindFirstArgs) - schema: - type: string - responses: - "200": - description: Result of findFirst - content: - application/json: - schema: - $ref: "#/components/schemas/PostResponse" - "400": - description: Error - content: - application/json: - schema: - $ref: "#/components/schemas/_ErrorResponse" - /post/count: - get: - tags: - - post - summary: count Post - operationId: post_count - parameters: - - name: q - in: query - description: Arguments as JSON (PostCountArgs) - schema: - type: string - responses: - "200": - description: Result of count - content: - application/json: - schema: - $ref: "#/components/schemas/PostCountResponse" - "400": - description: Error - content: - application/json: - schema: - $ref: "#/components/schemas/_ErrorResponse" - /post/aggregate: - get: - tags: - - post - summary: aggregate Post - operationId: post_aggregate - parameters: - - name: q - in: query - description: Arguments as JSON (PostAggregateArgs) - schema: - type: string - responses: - "200": - description: Result of aggregate - content: - application/json: - schema: - $ref: "#/components/schemas/PostAggregateResponse" - "400": - description: Error - content: - application/json: - schema: - $ref: "#/components/schemas/_ErrorResponse" - /post/groupBy: - get: - tags: - - post - summary: groupBy Post - operationId: post_groupBy - parameters: - - name: q - in: query - description: Arguments as JSON (PostGroupByArgs) - schema: - type: string - responses: - "200": - description: Result of groupBy - content: - application/json: - schema: - $ref: "#/components/schemas/PostGroupByResponse" - "400": - description: Error - content: - application/json: - schema: - $ref: "#/components/schemas/_ErrorResponse" - /post/exists: - get: - tags: - - post - summary: exists Post - operationId: post_exists - parameters: - - name: q - in: query - description: Arguments as JSON (PostExistsArgs) - schema: - type: string - responses: - "200": - description: Result of exists - content: - application/json: - schema: - $ref: "#/components/schemas/_ExistsResponse" - "400": - description: Error - content: - application/json: - schema: - $ref: "#/components/schemas/_ErrorResponse" - /post/create: - post: - tags: - - post - summary: create Post - operationId: post_create - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/PostCreateArgs" - responses: - "201": - description: Result of create - content: - application/json: - schema: - $ref: "#/components/schemas/PostResponse" - "400": - description: Error - content: - application/json: - schema: - $ref: "#/components/schemas/_ErrorResponse" - /post/createMany: - post: - tags: - - post - summary: createMany Post - operationId: post_createMany - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/PostCreateManyArgs" - responses: - "201": - description: Result of createMany - content: - application/json: - schema: - $ref: "#/components/schemas/_BatchResponse" - "400": - description: Error - content: - application/json: - schema: - $ref: "#/components/schemas/_ErrorResponse" - /post/createManyAndReturn: - post: - tags: - - post - summary: createManyAndReturn Post - operationId: post_createManyAndReturn - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/PostCreateManyAndReturnArgs" - responses: - "201": - description: Result of createManyAndReturn - content: - application/json: - schema: - $ref: "#/components/schemas/PostListResponse" - "400": - description: Error - content: - application/json: - schema: - $ref: "#/components/schemas/_ErrorResponse" - /post/upsert: - post: - tags: - - post - summary: upsert Post - operationId: post_upsert - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/PostUpsertArgs" - responses: - "201": - description: Result of upsert - content: - application/json: - schema: - $ref: "#/components/schemas/PostResponse" - "400": - description: Error - content: - application/json: - schema: - $ref: "#/components/schemas/_ErrorResponse" - /post/update: - patch: - tags: - - post - summary: update Post - operationId: post_update - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/PostUpdateArgs" - responses: - "200": - description: Result of update - content: - application/json: - schema: - $ref: "#/components/schemas/PostResponse" - "400": - description: Error - content: - application/json: - schema: - $ref: "#/components/schemas/_ErrorResponse" - /post/updateMany: - patch: - tags: - - post - summary: updateMany Post - operationId: post_updateMany - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/PostUpdateManyArgs" - responses: - "200": - description: Result of updateMany - content: - application/json: - schema: - $ref: "#/components/schemas/_BatchResponse" - "400": - description: Error - content: - application/json: - schema: - $ref: "#/components/schemas/_ErrorResponse" - /post/updateManyAndReturn: - patch: - tags: - - post - summary: updateManyAndReturn Post - operationId: post_updateManyAndReturn - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/PostUpdateManyAndReturnArgs" - responses: - "200": - description: Result of updateManyAndReturn - content: - application/json: - schema: - $ref: "#/components/schemas/PostListResponse" - "400": - description: Error - content: - application/json: - schema: - $ref: "#/components/schemas/_ErrorResponse" - /post/delete: - delete: - tags: - - post - summary: delete Post - operationId: post_delete - parameters: - - name: q - in: query - description: Arguments as JSON (PostDeleteArgs) - schema: - type: string - responses: - "200": - description: Result of delete - content: - application/json: - schema: - $ref: "#/components/schemas/PostResponse" - "400": - description: Error - content: - application/json: - schema: - $ref: "#/components/schemas/_ErrorResponse" - /post/deleteMany: - delete: - tags: - - post - summary: deleteMany Post - operationId: post_deleteMany - parameters: - - name: q - in: query - description: Arguments as JSON (PostDeleteManyArgs) - schema: - type: string - responses: - "200": - description: Result of deleteMany - content: - application/json: - schema: - $ref: "#/components/schemas/_BatchResponse" - "400": - description: Error - content: - application/json: - schema: - $ref: "#/components/schemas/_ErrorResponse" - /$transaction/sequential: - post: - tags: - - $transaction - summary: Execute a sequential transaction - operationId: transaction_sequential - requestBody: - required: true - content: - application/json: - schema: - type: array - items: - type: object - properties: - model: - type: string - op: - type: string - args: - type: object - required: - - model - - op - responses: - "200": - description: Transaction results - "400": - description: Error - content: - application/json: - schema: - $ref: "#/components/schemas/_ErrorResponse" -components: - schemas: - _Meta: - type: object - properties: - serialization: {} - _ErrorResponse: - type: object - properties: - error: - type: object - properties: - message: - type: string - _BatchResponse: - type: object - properties: - data: - type: object - properties: - count: - type: integer - required: - - count - meta: - $ref: "#/components/schemas/_Meta" - _ExistsResponse: - type: object - properties: - data: - type: boolean - meta: - $ref: "#/components/schemas/_Meta" - _StringFilter: - oneOf: - - type: string - - type: object - properties: - equals: - type: string - not: - type: string - in: - type: array - items: - type: string - notIn: - type: array - items: - type: string - contains: - type: string - startsWith: - type: string - endsWith: - type: string - mode: - type: string - enum: - - default - - insensitive - _DateTimeFilter: - oneOf: - - type: string - format: date-time - - type: object - properties: - equals: - type: string - format: date-time - not: - type: string - format: date-time - in: - type: array - items: - type: string - format: date-time - notIn: - type: array - items: - type: string - format: date-time - lt: - type: string - format: date-time - lte: - type: string - format: date-time - gt: - type: string - format: date-time - gte: - type: string - format: date-time - _BooleanFilter: - oneOf: - - type: boolean - - type: object - properties: - equals: - type: boolean - not: - type: boolean - in: - type: array - items: - type: boolean - notIn: - type: array - items: - type: boolean - _IntFilter: - oneOf: - - type: integer - - type: object - properties: - equals: - type: integer - not: - type: integer - in: - type: array - items: - type: integer - notIn: - type: array - items: - type: integer - lt: - type: integer - lte: - type: integer - gt: - type: integer - gte: - type: integer - User: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - email: - type: string - posts: - type: array - items: - $ref: "#/components/schemas/Post" - required: - - id - - createdAt - - updatedAt - - email - UserCreateInput: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - email: - type: string - required: - - updatedAt - - email - UserUpdateInput: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - email: - type: string - UserWhereUniqueInput: - type: object - properties: - id: - type: string - email: - type: string - UserWhereInput: - type: object - properties: - id: - $ref: "#/components/schemas/_StringFilter" - createdAt: - $ref: "#/components/schemas/_DateTimeFilter" - updatedAt: - $ref: "#/components/schemas/_DateTimeFilter" - email: - $ref: "#/components/schemas/_StringFilter" - AND: - oneOf: - - $ref: "#/components/schemas/UserWhereInput" - - type: array - items: - $ref: "#/components/schemas/UserWhereInput" - OR: - type: array - items: - $ref: "#/components/schemas/UserWhereInput" - NOT: - oneOf: - - $ref: "#/components/schemas/UserWhereInput" - - type: array - items: - $ref: "#/components/schemas/UserWhereInput" - UserSelect: - type: object - properties: - id: - type: boolean - createdAt: - type: boolean - updatedAt: - type: boolean - email: - type: boolean - posts: - oneOf: - - type: boolean - - type: object - properties: - select: - $ref: "#/components/schemas/PostSelect" - omit: - $ref: "#/components/schemas/PostOmit" - include: - $ref: "#/components/schemas/PostInclude" - UserInclude: - type: object - properties: - posts: - oneOf: - - type: boolean - - type: object - properties: - select: - $ref: "#/components/schemas/PostSelect" - omit: - $ref: "#/components/schemas/PostOmit" - include: - $ref: "#/components/schemas/PostInclude" - UserOmit: - type: object - properties: - id: - type: boolean - createdAt: - type: boolean - updatedAt: - type: boolean - email: - type: boolean - UserCreateArgs: - type: object - properties: - data: - $ref: "#/components/schemas/UserCreateInput" - select: - $ref: "#/components/schemas/UserSelect" - include: - $ref: "#/components/schemas/UserInclude" - omit: - $ref: "#/components/schemas/UserOmit" - required: - - data - UserCreateManyArgs: - type: object - properties: - data: - type: array - items: - $ref: "#/components/schemas/UserCreateInput" - required: - - data - UserCreateManyAndReturnArgs: - type: object - properties: - data: - type: array - items: - $ref: "#/components/schemas/UserCreateInput" - select: - $ref: "#/components/schemas/UserSelect" - include: - $ref: "#/components/schemas/UserInclude" - omit: - $ref: "#/components/schemas/UserOmit" - required: - - data - UserUpdateArgs: - type: object - properties: - where: - $ref: "#/components/schemas/UserWhereUniqueInput" - data: - $ref: "#/components/schemas/UserUpdateInput" - select: - $ref: "#/components/schemas/UserSelect" - include: - $ref: "#/components/schemas/UserInclude" - omit: - $ref: "#/components/schemas/UserOmit" - required: - - where - - data - UserUpdateManyArgs: - type: object - properties: - where: - $ref: "#/components/schemas/UserWhereInput" - data: - $ref: "#/components/schemas/UserUpdateInput" - required: - - data - UserUpdateManyAndReturnArgs: - type: object - properties: - where: - $ref: "#/components/schemas/UserWhereInput" - data: - $ref: "#/components/schemas/UserUpdateInput" - select: - $ref: "#/components/schemas/UserSelect" - include: - $ref: "#/components/schemas/UserInclude" - omit: - $ref: "#/components/schemas/UserOmit" - required: - - data - UserUpsertArgs: - type: object - properties: - where: - $ref: "#/components/schemas/UserWhereUniqueInput" - create: - $ref: "#/components/schemas/UserCreateInput" - update: - $ref: "#/components/schemas/UserUpdateInput" - select: - $ref: "#/components/schemas/UserSelect" - include: - $ref: "#/components/schemas/UserInclude" - omit: - $ref: "#/components/schemas/UserOmit" - required: - - where - - create - - update - UserDeleteArgs: - type: object - properties: - where: - $ref: "#/components/schemas/UserWhereUniqueInput" - select: - $ref: "#/components/schemas/UserSelect" - include: - $ref: "#/components/schemas/UserInclude" - omit: - $ref: "#/components/schemas/UserOmit" - required: - - where - UserDeleteManyArgs: - type: object - properties: - where: - $ref: "#/components/schemas/UserWhereInput" - UserFindManyArgs: - type: object - properties: - where: - $ref: "#/components/schemas/UserWhereInput" - orderBy: - type: object - take: - type: integer - skip: - type: integer - select: - $ref: "#/components/schemas/UserSelect" - include: - $ref: "#/components/schemas/UserInclude" - omit: - $ref: "#/components/schemas/UserOmit" - UserFindUniqueArgs: - type: object - properties: - where: - $ref: "#/components/schemas/UserWhereUniqueInput" - select: - $ref: "#/components/schemas/UserSelect" - include: - $ref: "#/components/schemas/UserInclude" - omit: - $ref: "#/components/schemas/UserOmit" - required: - - where - UserFindFirstArgs: - type: object - properties: - where: - $ref: "#/components/schemas/UserWhereInput" - orderBy: - type: object - take: - type: integer - skip: - type: integer - select: - $ref: "#/components/schemas/UserSelect" - include: - $ref: "#/components/schemas/UserInclude" - omit: - $ref: "#/components/schemas/UserOmit" - UserCountArgs: - type: object - properties: - select: - $ref: "#/components/schemas/UserSelect" - where: - $ref: "#/components/schemas/UserWhereInput" - take: - type: integer - skip: - type: integer - UserAggregateArgs: - type: object - properties: - where: - $ref: "#/components/schemas/UserWhereInput" - orderBy: - type: object - take: - type: integer - skip: - type: integer - UserGroupByArgs: - type: object - properties: - where: - $ref: "#/components/schemas/UserWhereInput" - by: - type: array - items: - type: string - orderBy: - type: object - take: - type: integer - skip: - type: integer - UserExistsArgs: - type: object - properties: - where: - $ref: "#/components/schemas/UserWhereUniqueInput" - required: - - where - UserResponse: - type: object - properties: - data: - $ref: "#/components/schemas/User" - meta: - $ref: "#/components/schemas/_Meta" - UserCountAggregateOutputType: - type: object - properties: - id: - type: integer - createdAt: - type: integer - updatedAt: - type: integer - email: - type: integer - _all: - type: integer - required: - - id - - createdAt - - updatedAt - - email - - _all - UserMinAggregateOutputType: - type: object - properties: - id: - oneOf: - - type: "null" - - type: string - createdAt: - oneOf: - - type: "null" - - type: string - format: date-time - updatedAt: - oneOf: - - type: "null" - - type: string - format: date-time - email: - oneOf: - - type: "null" - - type: string - UserMaxAggregateOutputType: - type: object - properties: - id: - oneOf: - - type: "null" - - type: string - createdAt: - oneOf: - - type: "null" - - type: string - format: date-time - updatedAt: - oneOf: - - type: "null" - - type: string - format: date-time - email: - oneOf: - - type: "null" - - type: string - AggregateUser: - type: object - properties: - _count: - oneOf: - - type: "null" - - $ref: "#/components/schemas/UserCountAggregateOutputType" - _min: - oneOf: - - type: "null" - - $ref: "#/components/schemas/UserMinAggregateOutputType" - _max: - oneOf: - - type: "null" - - $ref: "#/components/schemas/UserMaxAggregateOutputType" - UserGroupByOutputType: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - email: - type: string - _count: - oneOf: - - type: "null" - - $ref: "#/components/schemas/UserCountAggregateOutputType" - _min: - oneOf: - - type: "null" - - $ref: "#/components/schemas/UserMinAggregateOutputType" - _max: - oneOf: - - type: "null" - - $ref: "#/components/schemas/UserMaxAggregateOutputType" - required: - - id - - createdAt - - updatedAt - - email - UserCountResponse: - type: object - properties: - data: - oneOf: - - type: integer - - $ref: "#/components/schemas/UserCountAggregateOutputType" - meta: - $ref: "#/components/schemas/_Meta" - UserListResponse: - type: object - properties: - data: - type: array - items: - $ref: "#/components/schemas/User" - meta: - $ref: "#/components/schemas/_Meta" - UserAggregateResponse: - type: object - properties: - data: - $ref: "#/components/schemas/AggregateUser" - meta: - $ref: "#/components/schemas/_Meta" - UserGroupByResponse: - type: object - properties: - data: - type: array - items: - $ref: "#/components/schemas/UserGroupByOutputType" - meta: - $ref: "#/components/schemas/_Meta" - Post: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - title: - type: string - author: - oneOf: - - $ref: "#/components/schemas/User" - - type: "null" - authorId: - oneOf: - - type: string - - type: "null" - published: - type: boolean - publishedAt: - oneOf: - - type: string - format: date-time - - type: "null" - viewCount: - type: integer - required: - - id - - createdAt - - updatedAt - - title - - published - - viewCount - PostCreateInput: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - title: - type: string - authorId: - type: string - published: - type: boolean - publishedAt: - type: string - format: date-time - viewCount: - type: integer - required: - - updatedAt - - title - PostUpdateInput: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - title: - type: string - authorId: - type: string - published: - type: boolean - publishedAt: - type: string - format: date-time - viewCount: - type: integer - PostWhereUniqueInput: - type: object - properties: - id: - type: string - PostWhereInput: - type: object - properties: - id: - $ref: "#/components/schemas/_StringFilter" - createdAt: - $ref: "#/components/schemas/_DateTimeFilter" - updatedAt: - $ref: "#/components/schemas/_DateTimeFilter" - title: - $ref: "#/components/schemas/_StringFilter" - authorId: - $ref: "#/components/schemas/_StringFilter" - published: - $ref: "#/components/schemas/_BooleanFilter" - publishedAt: - $ref: "#/components/schemas/_DateTimeFilter" - viewCount: - $ref: "#/components/schemas/_IntFilter" - AND: - oneOf: - - $ref: "#/components/schemas/PostWhereInput" - - type: array - items: - $ref: "#/components/schemas/PostWhereInput" - OR: - type: array - items: - $ref: "#/components/schemas/PostWhereInput" - NOT: - oneOf: - - $ref: "#/components/schemas/PostWhereInput" - - type: array - items: - $ref: "#/components/schemas/PostWhereInput" - PostSelect: - type: object - properties: - id: - type: boolean - createdAt: - type: boolean - updatedAt: - type: boolean - title: - type: boolean - author: - oneOf: - - type: boolean - - type: object - properties: - select: - $ref: "#/components/schemas/UserSelect" - omit: - $ref: "#/components/schemas/UserOmit" - include: - $ref: "#/components/schemas/UserInclude" - authorId: - type: boolean - published: - type: boolean - publishedAt: - type: boolean - viewCount: - type: boolean - PostInclude: - type: object - properties: - author: - oneOf: - - type: boolean - - type: object - properties: - select: - $ref: "#/components/schemas/UserSelect" - omit: - $ref: "#/components/schemas/UserOmit" - include: - $ref: "#/components/schemas/UserInclude" - PostOmit: - type: object - properties: - id: - type: boolean - createdAt: - type: boolean - updatedAt: - type: boolean - title: - type: boolean - authorId: - type: boolean - published: - type: boolean - publishedAt: - type: boolean - viewCount: - type: boolean - PostCreateArgs: - type: object - properties: - data: - $ref: "#/components/schemas/PostCreateInput" - select: - $ref: "#/components/schemas/PostSelect" - include: - $ref: "#/components/schemas/PostInclude" - omit: - $ref: "#/components/schemas/PostOmit" - required: - - data - PostCreateManyArgs: - type: object - properties: - data: - type: array - items: - $ref: "#/components/schemas/PostCreateInput" - required: - - data - PostCreateManyAndReturnArgs: - type: object - properties: - data: - type: array - items: - $ref: "#/components/schemas/PostCreateInput" - select: - $ref: "#/components/schemas/PostSelect" - include: - $ref: "#/components/schemas/PostInclude" - omit: - $ref: "#/components/schemas/PostOmit" - required: - - data - PostUpdateArgs: - type: object - properties: - where: - $ref: "#/components/schemas/PostWhereUniqueInput" - data: - $ref: "#/components/schemas/PostUpdateInput" - select: - $ref: "#/components/schemas/PostSelect" - include: - $ref: "#/components/schemas/PostInclude" - omit: - $ref: "#/components/schemas/PostOmit" - required: - - where - - data - PostUpdateManyArgs: - type: object - properties: - where: - $ref: "#/components/schemas/PostWhereInput" - data: - $ref: "#/components/schemas/PostUpdateInput" - required: - - data - PostUpdateManyAndReturnArgs: - type: object - properties: - where: - $ref: "#/components/schemas/PostWhereInput" - data: - $ref: "#/components/schemas/PostUpdateInput" - select: - $ref: "#/components/schemas/PostSelect" - include: - $ref: "#/components/schemas/PostInclude" - omit: - $ref: "#/components/schemas/PostOmit" - required: - - data - PostUpsertArgs: - type: object - properties: - where: - $ref: "#/components/schemas/PostWhereUniqueInput" - create: - $ref: "#/components/schemas/PostCreateInput" - update: - $ref: "#/components/schemas/PostUpdateInput" - select: - $ref: "#/components/schemas/PostSelect" - include: - $ref: "#/components/schemas/PostInclude" - omit: - $ref: "#/components/schemas/PostOmit" - required: - - where - - create - - update - PostDeleteArgs: - type: object - properties: - where: - $ref: "#/components/schemas/PostWhereUniqueInput" - select: - $ref: "#/components/schemas/PostSelect" - include: - $ref: "#/components/schemas/PostInclude" - omit: - $ref: "#/components/schemas/PostOmit" - required: - - where - PostDeleteManyArgs: - type: object - properties: - where: - $ref: "#/components/schemas/PostWhereInput" - PostFindManyArgs: - type: object - properties: - where: - $ref: "#/components/schemas/PostWhereInput" - orderBy: - type: object - take: - type: integer - skip: - type: integer - select: - $ref: "#/components/schemas/PostSelect" - include: - $ref: "#/components/schemas/PostInclude" - omit: - $ref: "#/components/schemas/PostOmit" - PostFindUniqueArgs: - type: object - properties: - where: - $ref: "#/components/schemas/PostWhereUniqueInput" - select: - $ref: "#/components/schemas/PostSelect" - include: - $ref: "#/components/schemas/PostInclude" - omit: - $ref: "#/components/schemas/PostOmit" - required: - - where - PostFindFirstArgs: - type: object - properties: - where: - $ref: "#/components/schemas/PostWhereInput" - orderBy: - type: object - take: - type: integer - skip: - type: integer - select: - $ref: "#/components/schemas/PostSelect" - include: - $ref: "#/components/schemas/PostInclude" - omit: - $ref: "#/components/schemas/PostOmit" - PostCountArgs: - type: object - properties: - select: - $ref: "#/components/schemas/PostSelect" - where: - $ref: "#/components/schemas/PostWhereInput" - take: - type: integer - skip: - type: integer - PostAggregateArgs: - type: object - properties: - where: - $ref: "#/components/schemas/PostWhereInput" - orderBy: - type: object - take: - type: integer - skip: - type: integer - PostGroupByArgs: - type: object - properties: - where: - $ref: "#/components/schemas/PostWhereInput" - by: - type: array - items: - type: string - orderBy: - type: object - take: - type: integer - skip: - type: integer - PostExistsArgs: - type: object - properties: - where: - $ref: "#/components/schemas/PostWhereUniqueInput" - required: - - where - PostResponse: - type: object - properties: - data: - $ref: "#/components/schemas/Post" - meta: - $ref: "#/components/schemas/_Meta" - PostCountAggregateOutputType: - type: object - properties: - id: - type: integer - createdAt: - type: integer - updatedAt: - type: integer - title: - type: integer - authorId: - type: integer - published: - type: integer - publishedAt: - type: integer - viewCount: - type: integer - _all: - type: integer - required: - - id - - createdAt - - updatedAt - - title - - authorId - - published - - publishedAt - - viewCount - - _all - PostMinAggregateOutputType: - type: object - properties: - id: - oneOf: - - type: "null" - - type: string - createdAt: - oneOf: - - type: "null" - - type: string - format: date-time - updatedAt: - oneOf: - - type: "null" - - type: string - format: date-time - title: - oneOf: - - type: "null" - - type: string - authorId: - oneOf: - - type: "null" - - type: string - published: - oneOf: - - type: "null" - - type: boolean - publishedAt: - oneOf: - - type: "null" - - type: string - format: date-time - viewCount: - oneOf: - - type: "null" - - type: integer - PostMaxAggregateOutputType: - type: object - properties: - id: - oneOf: - - type: "null" - - type: string - createdAt: - oneOf: - - type: "null" - - type: string - format: date-time - updatedAt: - oneOf: - - type: "null" - - type: string - format: date-time - title: - oneOf: - - type: "null" - - type: string - authorId: - oneOf: - - type: "null" - - type: string - published: - oneOf: - - type: "null" - - type: boolean - publishedAt: - oneOf: - - type: "null" - - type: string - format: date-time - viewCount: - oneOf: - - type: "null" - - type: integer - PostAvgAggregateOutputType: - type: object - properties: - viewCount: - oneOf: - - type: "null" - - type: number - PostSumAggregateOutputType: - type: object - properties: - viewCount: - oneOf: - - type: "null" - - type: integer - AggregatePost: - type: object - properties: - _count: - oneOf: - - type: "null" - - $ref: "#/components/schemas/PostCountAggregateOutputType" - _min: - oneOf: - - type: "null" - - $ref: "#/components/schemas/PostMinAggregateOutputType" - _max: - oneOf: - - type: "null" - - $ref: "#/components/schemas/PostMaxAggregateOutputType" - _avg: - oneOf: - - type: "null" - - $ref: "#/components/schemas/PostAvgAggregateOutputType" - _sum: - oneOf: - - type: "null" - - $ref: "#/components/schemas/PostSumAggregateOutputType" - PostGroupByOutputType: - type: object - properties: - id: - type: string - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - title: - type: string - authorId: - oneOf: - - type: string - - type: "null" - published: - type: boolean - publishedAt: - oneOf: - - type: string - format: date-time - - type: "null" - viewCount: - type: integer - _count: - oneOf: - - type: "null" - - $ref: "#/components/schemas/PostCountAggregateOutputType" - _min: - oneOf: - - type: "null" - - $ref: "#/components/schemas/PostMinAggregateOutputType" - _max: - oneOf: - - type: "null" - - $ref: "#/components/schemas/PostMaxAggregateOutputType" - _avg: - oneOf: - - type: "null" - - $ref: "#/components/schemas/PostAvgAggregateOutputType" - _sum: - oneOf: - - type: "null" - - $ref: "#/components/schemas/PostSumAggregateOutputType" - required: - - id - - createdAt - - updatedAt - - title - - published - - viewCount - PostCountResponse: - type: object - properties: - data: - oneOf: - - type: integer - - $ref: "#/components/schemas/PostCountAggregateOutputType" - meta: - $ref: "#/components/schemas/_Meta" - PostListResponse: - type: object - properties: - data: - type: array - items: - $ref: "#/components/schemas/Post" - meta: - $ref: "#/components/schemas/_Meta" - PostAggregateResponse: - type: object - properties: - data: - $ref: "#/components/schemas/AggregatePost" - meta: - $ref: "#/components/schemas/_Meta" - PostGroupByResponse: - type: object - properties: - data: - type: array - items: - $ref: "#/components/schemas/PostGroupByOutputType" - meta: - $ref: "#/components/schemas/_Meta" diff --git a/packages/server/test/openapi/rpc-openapi.test.ts b/packages/server/test/openapi/rpc-openapi.test.ts deleted file mode 100644 index 9d3117013..000000000 --- a/packages/server/test/openapi/rpc-openapi.test.ts +++ /dev/null @@ -1,832 +0,0 @@ -import { createTestClient } from '@zenstackhq/testtools'; -import fs from 'fs'; -import path from 'path'; -import { beforeAll, describe, expect, it } from 'vitest'; -import YAML from 'yaml'; -import { validate } from '@readme/openapi-parser'; -import { RPCApiHandler } from '../../src/api/rpc'; -import { schema } from '../utils'; - -const UPDATE_BASELINE = process.env.UPDATE_BASELINE === '1'; - -function loadBaseline(name: string) { - return YAML.parse(fs.readFileSync(path.join(__dirname, 'baseline', name), 'utf-8')); -} - -function saveBaseline(name: string, spec: any) { - fs.writeFileSync(path.join(__dirname, 'baseline', name), YAML.stringify(spec, { lineWidth: 0, indent: 4, aliasDuplicateObjects: false })); -} - -describe('RPC OpenAPI spec generation', () => { - let handler: RPCApiHandler; - let spec: any; - - beforeAll(async () => { - const client = await createTestClient(schema); - handler = new RPCApiHandler({ schema: client.$schema }); - spec = await handler.generateSpec(); - }); - - it('document structure is valid', () => { - expect(spec.openapi).toBe('3.1.0'); - expect(spec.info).toBeDefined(); - expect(spec.info.title).toBe('ZenStack Generated API'); - expect(spec.info.version).toBe('1.0.0'); - expect(spec.paths).toBeDefined(); - expect(spec.components).toBeDefined(); - expect(spec.components.schemas).toBeDefined(); - }); - - it('operation paths exist for User model', () => { - expect(spec.paths['/user/findMany']).toBeDefined(); - expect(spec.paths['/user/findUnique']).toBeDefined(); - expect(spec.paths['/user/findFirst']).toBeDefined(); - expect(spec.paths['/user/create']).toBeDefined(); - expect(spec.paths['/user/createMany']).toBeDefined(); - expect(spec.paths['/user/update']).toBeDefined(); - expect(spec.paths['/user/updateMany']).toBeDefined(); - expect(spec.paths['/user/upsert']).toBeDefined(); - expect(spec.paths['/user/delete']).toBeDefined(); - expect(spec.paths['/user/deleteMany']).toBeDefined(); - expect(spec.paths['/user/count']).toBeDefined(); - expect(spec.paths['/user/aggregate']).toBeDefined(); - expect(spec.paths['/user/groupBy']).toBeDefined(); - expect(spec.paths['/user/exists']).toBeDefined(); - }); - - it('operation paths exist for Post model', () => { - expect(spec.paths['/post/findMany']).toBeDefined(); - expect(spec.paths['/post/create']).toBeDefined(); - expect(spec.paths['/post/update']).toBeDefined(); - expect(spec.paths['/post/delete']).toBeDefined(); - }); - - it('HTTP methods are correct', () => { - // Read ops use GET - expect(spec.paths['/user/findMany'].get).toBeDefined(); - expect(spec.paths['/user/findUnique'].get).toBeDefined(); - expect(spec.paths['/user/count'].get).toBeDefined(); - expect(spec.paths['/user/exists'].get).toBeDefined(); - - // Write ops - expect(spec.paths['/user/create'].post).toBeDefined(); - expect(spec.paths['/user/createMany'].post).toBeDefined(); - expect(spec.paths['/user/upsert'].post).toBeDefined(); - - expect(spec.paths['/user/update'].patch).toBeDefined(); - expect(spec.paths['/user/updateMany'].patch).toBeDefined(); - - expect(spec.paths['/user/delete'].delete).toBeDefined(); - expect(spec.paths['/user/deleteMany'].delete).toBeDefined(); - }); - - it('transaction path exists', () => { - expect(spec.paths['/$transaction/sequential']).toBeDefined(); - expect(spec.paths['/$transaction/sequential'].post).toBeDefined(); - }); - - it('input schemas exist in components', () => { - expect(spec.components.schemas['UserCreateInput']).toBeDefined(); - expect(spec.components.schemas['UserUpdateInput']).toBeDefined(); - expect(spec.components.schemas['UserWhereInput']).toBeDefined(); - expect(spec.components.schemas['UserWhereUniqueInput']).toBeDefined(); - expect(spec.components.schemas['UserCreateArgs']).toBeDefined(); - expect(spec.components.schemas['UserUpdateArgs']).toBeDefined(); - expect(spec.components.schemas['UserFindManyArgs']).toBeDefined(); - expect(spec.components.schemas['UserFindUniqueArgs']).toBeDefined(); - }); - - it('output schema (User model) has correct fields', () => { - const userSchema = spec.components.schemas['User']; - expect(userSchema).toBeDefined(); - expect(userSchema.properties).toBeDefined(); - expect(userSchema.properties['id']).toMatchObject({ type: 'string' }); - expect(userSchema.properties['email']).toMatchObject({ type: 'string' }); - expect(userSchema.properties['viewCount']).toBeUndefined(); // on Post, not User - }); - - it('Post output schema has correct field types', () => { - const postSchema = spec.components.schemas['Post']; - expect(postSchema).toBeDefined(); - expect(postSchema.properties['viewCount']).toMatchObject({ type: 'integer' }); - expect(postSchema.properties['published']).toMatchObject({ type: 'boolean' }); - expect(postSchema.properties['createdAt']).toMatchObject({ type: 'string', format: 'date-time' }); - }); - - it('response wrapper has data and meta properties', () => { - const userResponse = spec.components.schemas['UserResponse']; - expect(userResponse).toBeDefined(); - expect(userResponse.properties?.data).toBeDefined(); - expect(userResponse.properties?.meta).toBeDefined(); - }); - - it('GET ops have q query parameter', () => { - const findManyOp = spec.paths['/user/findMany'].get; - expect(findManyOp.parameters).toBeDefined(); - const qParam = findManyOp.parameters.find((p: any) => p.name === 'q'); - expect(qParam).toBeDefined(); - expect(qParam.in).toBe('query'); - }); - - it('POST ops have request body', () => { - const createOp = spec.paths['/user/create'].post; - expect(createOp.requestBody).toBeDefined(); - expect(createOp.requestBody.required).toBe(true); - }); - - it('PATCH ops have request body', () => { - const updateOp = spec.paths['/user/update'].patch; - expect(updateOp.requestBody).toBeDefined(); - }); - - it('DELETE ops have q query parameter', () => { - const deleteOp = spec.paths['/user/delete'].delete; - expect(deleteOp.parameters).toBeDefined(); - const qParam = deleteOp.parameters.find((p: any) => p.name === 'q'); - expect(qParam).toBeDefined(); - }); - - it('shared error schema exists', () => { - expect(spec.components.schemas['_ErrorResponse']).toBeDefined(); - expect(spec.components.schemas['_Meta']).toBeDefined(); - }); - - it('custom openApiOptions are reflected in info', async () => { - const client = await createTestClient(schema); - const customHandler = new RPCApiHandler({ - schema: client.$schema, - }); - const customSpec = await customHandler.generateSpec({ - title: 'My RPC API', - version: '3.0.0', - }); - expect(customSpec.info.title).toBe('My RPC API'); - expect(customSpec.info.version).toBe('3.0.0'); - }); -}); - -describe('RPC OpenAPI spec generation - queryOptions', () => { - it('omit excludes fields from output schema', async () => { - const client = await createTestClient(schema); - const handler = new RPCApiHandler({ - schema: client.$schema, - queryOptions: { omit: { User: { email: true } } }, - }); - const s = await handler.generateSpec(); - const userSchema = s.components?.schemas?.['User'] as any; - expect(userSchema.properties['id']).toBeDefined(); - expect(userSchema.properties['email']).toBeUndefined(); - }); - - it('slicing excludedModels removes model from spec', async () => { - const client = await createTestClient(schema); - const handler = new RPCApiHandler({ - schema: client.$schema, - queryOptions: { slicing: { excludedModels: ['Post'] as any } }, - }); - const s = await handler.generateSpec(); - expect(s.paths?.['/user/findMany']).toBeDefined(); - expect(s.paths?.['/post/findMany']).toBeUndefined(); - expect(s.components?.schemas?.['Post']).toBeUndefined(); - }); - - it('slicing includedModels limits models in spec', async () => { - const client = await createTestClient(schema); - const handler = new RPCApiHandler({ - schema: client.$schema, - queryOptions: { slicing: { includedModels: ['User'] as any } }, - }); - const s = await handler.generateSpec(); - expect(s.paths?.['/user/findMany']).toBeDefined(); - expect(s.paths?.['/post/findMany']).toBeUndefined(); - }); - - it('slicing excludedOperations removes operations from spec', async () => { - const client = await createTestClient(schema); - const handler = new RPCApiHandler({ - schema: client.$schema, - queryOptions: { - slicing: { - models: { user: { excludedOperations: ['create', 'delete'] } } as any, - }, - }, - }); - const s = await handler.generateSpec(); - expect(s.paths?.['/user/findMany']).toBeDefined(); - expect(s.paths?.['/user/create']).toBeUndefined(); - expect(s.paths?.['/user/delete']).toBeUndefined(); - // Post unaffected - expect(s.paths?.['/post/create']).toBeDefined(); - }); - - it('slicing $all excludedOperations applies to all models', async () => { - const client = await createTestClient(schema); - const handler = new RPCApiHandler({ - schema: client.$schema, - queryOptions: { - slicing: { - models: { $all: { excludedOperations: ['delete', 'deleteMany'] } } as any, - }, - }, - }); - const s = await handler.generateSpec(); - expect(s.paths?.['/user/delete']).toBeUndefined(); - expect(s.paths?.['/post/delete']).toBeUndefined(); - expect(s.paths?.['/user/findMany']).toBeDefined(); - }); - - it('where input has filter operators by default', async () => { - const client = await createTestClient(schema); - const handler = new RPCApiHandler({ schema: client.$schema }); - const s = await handler.generateSpec(); - const whereInput = s.components?.schemas?.['PostWhereInput'] as any; - - // Default (no slicing) uses $ref to shared filter schemas - expect(whereInput.properties['title'].$ref).toBe('#/components/schemas/_StringFilter'); - expect(whereInput.properties['viewCount'].$ref).toBe('#/components/schemas/_IntFilter'); - - // Shared String filter: Equality + Like operators - const stringFilter = s.components?.schemas?.['_StringFilter'] as any; - expect(stringFilter.oneOf).toHaveLength(2); - const stringFilterObj = stringFilter.oneOf[1]; - expect(stringFilterObj.properties['equals']).toBeDefined(); - expect(stringFilterObj.properties['not']).toBeDefined(); - expect(stringFilterObj.properties['in']).toBeDefined(); - expect(stringFilterObj.properties['contains']).toBeDefined(); - expect(stringFilterObj.properties['startsWith']).toBeDefined(); - expect(stringFilterObj.properties['endsWith']).toBeDefined(); - - // Shared Int filter: Equality + Range operators - const intFilter = s.components?.schemas?.['_IntFilter'] as any; - expect(intFilter.oneOf).toHaveLength(2); - const intFilterObj = intFilter.oneOf[1]; - expect(intFilterObj.properties['equals']).toBeDefined(); - expect(intFilterObj.properties['lt']).toBeDefined(); - expect(intFilterObj.properties['gte']).toBeDefined(); - // Should not have Like operators - expect(intFilterObj.properties['contains']).toBeUndefined(); - }); - - it('slicing excludedFilterKinds removes specific operators from where input', async () => { - const client = await createTestClient(schema); - const handler = new RPCApiHandler({ - schema: client.$schema, - queryOptions: { - slicing: { - models: { - post: { - fields: { - title: { excludedFilterKinds: ['Like'] }, - viewCount: { excludedFilterKinds: ['Range'] }, - }, - }, - }, - } as any, - }, - }); - const s = await handler.generateSpec(); - const whereInput = s.components?.schemas?.['PostWhereInput'] as any; - - // title: Equality operators remain, Like operators removed - const titleFilter = whereInput.properties['title']; - expect(titleFilter).toBeDefined(); - const titleFilterObj = titleFilter.oneOf[1]; - expect(titleFilterObj.properties['equals']).toBeDefined(); - expect(titleFilterObj.properties['in']).toBeDefined(); - expect(titleFilterObj.properties['contains']).toBeUndefined(); - expect(titleFilterObj.properties['startsWith']).toBeUndefined(); - - // viewCount: Equality operators remain, Range operators removed - const vcFilter = whereInput.properties['viewCount']; - expect(vcFilter).toBeDefined(); - const vcFilterObj = vcFilter.oneOf[1]; - expect(vcFilterObj.properties['equals']).toBeDefined(); - expect(vcFilterObj.properties['lt']).toBeUndefined(); - expect(vcFilterObj.properties['gte']).toBeUndefined(); - }); - - it('slicing excludedFilterKinds removes all operators removes field entirely', async () => { - const client = await createTestClient(schema); - const handler = new RPCApiHandler({ - schema: client.$schema, - queryOptions: { - slicing: { - models: { - post: { - fields: { - title: { excludedFilterKinds: ['Equality', 'Like'] }, - }, - }, - }, - } as any, - }, - }); - const s = await handler.generateSpec(); - const whereInput = s.components?.schemas?.['PostWhereInput'] as any; - // All filter kinds for title excluded -> field removed - expect(whereInput.properties['title']).toBeUndefined(); - // viewCount unaffected - expect(whereInput.properties['viewCount']).toBeDefined(); - }); - - it('slicing includedFilterKinds limits operators in where input', async () => { - const client = await createTestClient(schema); - const handler = new RPCApiHandler({ - schema: client.$schema, - queryOptions: { - slicing: { - models: { - post: { - fields: { - title: { includedFilterKinds: ['Equality'] }, - }, - }, - }, - } as any, - }, - }); - const s = await handler.generateSpec(); - const whereInput = s.components?.schemas?.['PostWhereInput'] as any; - - // title: only Equality operators - const titleFilter = whereInput.properties['title']; - expect(titleFilter).toBeDefined(); - const titleFilterObj = titleFilter.oneOf[1]; - expect(titleFilterObj.properties['equals']).toBeDefined(); - expect(titleFilterObj.properties['not']).toBeDefined(); - // Like operators excluded - expect(titleFilterObj.properties['contains']).toBeUndefined(); - expect(titleFilterObj.properties['startsWith']).toBeUndefined(); - }); - - it('slicing excludedFilterKinds on Equality removes shorthand and equality ops', async () => { - const client = await createTestClient(schema); - const handler = new RPCApiHandler({ - schema: client.$schema, - queryOptions: { - slicing: { - models: { - post: { - fields: { - title: { excludedFilterKinds: ['Equality'] }, - }, - }, - }, - } as any, - }, - }); - const s = await handler.generateSpec(); - const whereInput = s.components?.schemas?.['PostWhereInput'] as any; - - // title: no shorthand (no oneOf), just the filter object with Like operators - const titleFilter = whereInput.properties['title']; - expect(titleFilter).toBeDefined(); - expect(titleFilter.oneOf).toBeUndefined(); - expect(titleFilter.type).toBe('object'); - expect(titleFilter.properties['equals']).toBeUndefined(); - expect(titleFilter.properties['contains']).toBeDefined(); - expect(titleFilter.properties['startsWith']).toBeDefined(); - }); - - it('slicing $all field applies filter kind restriction to all fields', async () => { - const client = await createTestClient(schema); - const handler = new RPCApiHandler({ - schema: client.$schema, - queryOptions: { - slicing: { - models: { - post: { - fields: { - $all: { excludedFilterKinds: ['Equality', 'Range', 'Like', 'List', 'Json'] }, - }, - }, - }, - } as any, - }, - }); - const s = await handler.generateSpec(); - const whereInput = s.components?.schemas?.['PostWhereInput'] as any; - // All filter kinds excluded -> no field properties - expect(whereInput.properties['title']).toBeUndefined(); - expect(whereInput.properties['viewCount']).toBeUndefined(); - // Logical combinators still exist - expect(whereInput.properties['AND']).toBeDefined(); - expect(whereInput.properties['OR']).toBeDefined(); - }); -}); - -describe('RPC OpenAPI spec generation - select/include/omit schemas', () => { - let spec: any; - - beforeAll(async () => { - const client = await createTestClient(schema); - const handler = new RPCApiHandler({ schema: client.$schema }); - spec = await handler.generateSpec(); - }); - - it('Select schema lists all fields with boolean type', () => { - const userSelect = spec.components.schemas['UserSelect']; - expect(userSelect).toBeDefined(); - expect(userSelect.type).toBe('object'); - // Scalar fields are boolean - expect(userSelect.properties['id']).toEqual({ type: 'boolean' }); - expect(userSelect.properties['email']).toEqual({ type: 'boolean' }); - expect(userSelect.properties['createdAt']).toEqual({ type: 'boolean' }); - }); - - it('Select schema allows nested select/include/omit for relation fields', () => { - const userSelect = spec.components.schemas['UserSelect']; - // Relation field: oneOf [boolean, nested object] - const postsField = userSelect.properties['posts']; - expect(postsField.oneOf).toHaveLength(2); - expect(postsField.oneOf[0]).toEqual({ type: 'boolean' }); - const nested = postsField.oneOf[1]; - expect(nested.type).toBe('object'); - expect(nested.properties['select'].$ref).toBe('#/components/schemas/PostSelect'); - expect(nested.properties['include'].$ref).toBe('#/components/schemas/PostInclude'); - expect(nested.properties['omit'].$ref).toBe('#/components/schemas/PostOmit'); - }); - - it('Select schema includes FK fields', () => { - const postSelect = spec.components.schemas['PostSelect']; - expect(postSelect.properties['authorId']).toEqual({ type: 'boolean' }); - }); - - it('Include schema lists only relation fields', () => { - const userInclude = spec.components.schemas['UserInclude']; - expect(userInclude).toBeDefined(); - expect(userInclude.type).toBe('object'); - // Relation field present with nested select/include/omit - expect(userInclude.properties['posts']).toBeDefined(); - expect(userInclude.properties['posts'].oneOf).toHaveLength(2); - // Scalar fields absent - expect(userInclude.properties['id']).toBeUndefined(); - expect(userInclude.properties['email']).toBeUndefined(); - }); - - it('Include schema is not generated for models without relations', async () => { - const noRelSchema = ` -model Item { - id Int @id @default(autoincrement()) - name String -} -`; - const client = await createTestClient(noRelSchema); - const handler = new RPCApiHandler({ schema: client.$schema }); - const s = await handler.generateSpec(); - expect(s.components?.schemas?.['ItemSelect']).toBeDefined(); - expect(s.components?.schemas?.['ItemInclude']).toBeUndefined(); - expect(s.components?.schemas?.['ItemOmit']).toBeDefined(); - // Args should not have include - const findManyArgs = s.components?.schemas?.['ItemFindManyArgs'] as any; - expect(findManyArgs.properties['select']).toBeDefined(); - expect(findManyArgs.properties['include']).toBeUndefined(); - expect(findManyArgs.properties['omit']).toBeDefined(); - }); - - it('Omit schema lists only non-relation fields', () => { - const userOmit = spec.components.schemas['UserOmit']; - expect(userOmit).toBeDefined(); - expect(userOmit.type).toBe('object'); - // Scalar fields present - expect(userOmit.properties['id']).toEqual({ type: 'boolean' }); - expect(userOmit.properties['email']).toEqual({ type: 'boolean' }); - // Relation fields absent - expect(userOmit.properties['posts']).toBeUndefined(); - - // FK fields included - const postOmit = spec.components.schemas['PostOmit']; - expect(postOmit.properties['authorId']).toEqual({ type: 'boolean' }); - }); - - it('Args schemas reference Select/Include/Omit via $ref', () => { - const createArgs = spec.components.schemas['UserCreateArgs']; - expect(createArgs.properties['select'].$ref).toBe('#/components/schemas/UserSelect'); - expect(createArgs.properties['include'].$ref).toBe('#/components/schemas/UserInclude'); - expect(createArgs.properties['omit'].$ref).toBe('#/components/schemas/UserOmit'); - - const findManyArgs = spec.components.schemas['UserFindManyArgs']; - expect(findManyArgs.properties['select'].$ref).toBe('#/components/schemas/UserSelect'); - expect(findManyArgs.properties['include'].$ref).toBe('#/components/schemas/UserInclude'); - expect(findManyArgs.properties['omit'].$ref).toBe('#/components/schemas/UserOmit'); - }); - - it('createManyAndReturn and updateManyAndReturn args have select/include/omit', () => { - const createManyAndReturnArgs = spec.components.schemas['UserCreateManyAndReturnArgs']; - expect(createManyAndReturnArgs).toBeDefined(); - expect(createManyAndReturnArgs.properties['data']).toBeDefined(); - expect(createManyAndReturnArgs.properties['select'].$ref).toBe('#/components/schemas/UserSelect'); - expect(createManyAndReturnArgs.properties['include'].$ref).toBe('#/components/schemas/UserInclude'); - expect(createManyAndReturnArgs.properties['omit'].$ref).toBe('#/components/schemas/UserOmit'); - - const updateManyAndReturnArgs = spec.components.schemas['UserUpdateManyAndReturnArgs']; - expect(updateManyAndReturnArgs).toBeDefined(); - expect(updateManyAndReturnArgs.properties['data']).toBeDefined(); - expect(updateManyAndReturnArgs.properties['select'].$ref).toBe('#/components/schemas/UserSelect'); - expect(updateManyAndReturnArgs.properties['include'].$ref).toBe('#/components/schemas/UserInclude'); - expect(updateManyAndReturnArgs.properties['omit'].$ref).toBe('#/components/schemas/UserOmit'); - }); - - it('createMany and updateMany args do not have select/include/omit', () => { - const createManyArgs = spec.components.schemas['UserCreateManyArgs']; - expect(createManyArgs.properties['select']).toBeUndefined(); - expect(createManyArgs.properties['include']).toBeUndefined(); - expect(createManyArgs.properties['omit']).toBeUndefined(); - - const updateManyArgs = spec.components.schemas['UserUpdateManyArgs']; - expect(updateManyArgs.properties['select']).toBeUndefined(); - expect(updateManyArgs.properties['include']).toBeUndefined(); - expect(updateManyArgs.properties['omit']).toBeUndefined(); - }); - - it('select/include exclude relations to excluded models', async () => { - const client = await createTestClient(schema); - const handler = new RPCApiHandler({ - schema: client.$schema, - queryOptions: { slicing: { excludedModels: ['Post'] as any } }, - }); - const s = await handler.generateSpec(); - - const userSelect = s.components?.schemas?.['UserSelect'] as any; - expect(userSelect.properties['id']).toBeDefined(); - // posts relation to excluded Post model should be absent - expect(userSelect.properties['posts']).toBeUndefined(); - - // Include should not have posts either - // User still has relations in schema, but all are excluded so Include may or may not exist - const userInclude = s.components?.schemas?.['UserInclude'] as any; - if (userInclude) { - expect(userInclude.properties['posts']).toBeUndefined(); - } - }); -}); - -describe('RPC OpenAPI spec generation - with enum', () => { - it('enum schemas appear in components', async () => { - const enumSchema = ` -model Post { - id Int @id @default(autoincrement()) - title String - status PostStatus @default(DRAFT) -} - -enum PostStatus { - DRAFT - PUBLISHED - ARCHIVED -} -`; - const client = await createTestClient(enumSchema); - const h = new RPCApiHandler({ schema: client.$schema }); - const s = await h.generateSpec(); - expect(s.components?.schemas?.['PostStatus']).toBeDefined(); - expect((s.components?.schemas?.['PostStatus'] as any).type).toBe('string'); - expect((s.components?.schemas?.['PostStatus'] as any).enum).toContain('DRAFT'); - }); -}); - -describe('RPC OpenAPI spec generation - @meta description', () => { - const metaSchema = ` -model User { - id String @id @default(cuid()) - email String @unique @meta("description", "The user's email address") - @@meta("description", "A user of the system") -} - -model Post { - id Int @id @default(autoincrement()) - title String -} -`; - - it('model @@meta description is used as schema description', async () => { - const client = await createTestClient(metaSchema); - const handler = new RPCApiHandler({ schema: client.$schema }); - const s = await handler.generateSpec(); - - const userSchema = s.components?.schemas?.['User'] as any; - expect(userSchema.description).toBe('A user of the system'); - - // Post has no @@meta description - const postSchema = s.components?.schemas?.['Post'] as any; - expect(postSchema.description).toBeUndefined(); - }); - - it('field @meta description is used as field schema description', async () => { - const client = await createTestClient(metaSchema); - const handler = new RPCApiHandler({ schema: client.$schema }); - const s = await handler.generateSpec(); - - const userSchema = s.components?.schemas?.['User'] as any; - expect(userSchema.properties['email'].description).toBe("The user's email address"); - - // id has no @meta description - expect(userSchema.properties['id'].description).toBeUndefined(); - }); -}); - -describe('RPC OpenAPI spec generation - aggregate and groupby schemas', () => { - let spec: any; - - beforeAll(async () => { - const client = await createTestClient(schema); - const handler = new RPCApiHandler({ schema: client.$schema }); - spec = await handler.generateSpec(); - }); - - describe('aggregate and groupby schemas', () => { - it('Aggregate schema has _count, _min, _max', () => { - const agg = spec.components.schemas['AggregateUser']; - expect(agg).toBeDefined(); - expect(agg.properties._count.oneOf).toEqual([ - { type: 'null' }, - { $ref: '#/components/schemas/UserCountAggregateOutputType' }, - ]); - expect(agg.properties._min.oneOf).toEqual([ - { type: 'null' }, - { $ref: '#/components/schemas/UserMinAggregateOutputType' }, - ]); - expect(agg.properties._max.oneOf).toEqual([ - { type: 'null' }, - { $ref: '#/components/schemas/UserMaxAggregateOutputType' }, - ]); - }); - - it('Aggregate schema includes _avg and _sum for models with numeric fields', () => { - const agg = spec.components.schemas['AggregatePost']; - expect(agg).toBeDefined(); - expect(agg.properties._avg).toBeDefined(); - expect(agg.properties._avg.oneOf).toEqual([ - { type: 'null' }, - { $ref: '#/components/schemas/PostAvgAggregateOutputType' }, - ]); - expect(agg.properties._sum).toBeDefined(); - expect(agg.properties._sum.oneOf).toEqual([ - { type: 'null' }, - { $ref: '#/components/schemas/PostSumAggregateOutputType' }, - ]); - }); - - it('Aggregate schema omits _avg and _sum for models without numeric fields', () => { - const agg = spec.components.schemas['AggregateUser']; - expect(agg.properties._avg).toBeUndefined(); - expect(agg.properties._sum).toBeUndefined(); - }); - - it('MinAggregateOutputType has all non-relation fields as nullable', () => { - const min = spec.components.schemas['UserMinAggregateOutputType']; - expect(min).toBeDefined(); - expect(min.properties.id.oneOf).toEqual([{ type: 'null' }, { type: 'string' }]); - expect(min.properties.email.oneOf).toEqual([{ type: 'null' }, { type: 'string' }]); - expect(min.properties.createdAt.oneOf).toEqual([{ type: 'null' }, { type: 'string', format: 'date-time' }]); - // No relation fields - expect(min.properties.posts).toBeUndefined(); - }); - - it('AvgAggregateOutputType only has numeric fields as nullable number', () => { - const avg = spec.components.schemas['PostAvgAggregateOutputType']; - expect(avg).toBeDefined(); - expect(avg.properties.viewCount.oneOf).toEqual([{ type: 'null' }, { type: 'number' }]); - // Non-numeric fields excluded - expect(avg.properties.title).toBeUndefined(); - expect(avg.properties.id).toBeUndefined(); - }); - - it('SumAggregateOutputType only has numeric fields preserving original type', () => { - const sum = spec.components.schemas['PostSumAggregateOutputType']; - expect(sum).toBeDefined(); - expect(sum.properties.viewCount.oneOf).toEqual([{ type: 'null' }, { type: 'integer' }]); - expect(sum.properties.title).toBeUndefined(); - }); - - it('GroupByOutputType has scalar fields and aggregate properties', () => { - const groupBy = spec.components.schemas['UserGroupByOutputType']; - expect(groupBy).toBeDefined(); - // Scalar fields with proper types - expect(groupBy.properties.id).toEqual({ type: 'string' }); - expect(groupBy.properties.email).toEqual({ type: 'string' }); - expect(groupBy.properties.createdAt).toEqual({ type: 'string', format: 'date-time' }); - // Required non-nullable fields - expect(groupBy.required).toContain('id'); - expect(groupBy.required).toContain('email'); - // No relation fields - expect(groupBy.properties.posts).toBeUndefined(); - // Aggregate properties - expect(groupBy.properties._count).toBeDefined(); - expect(groupBy.properties._min).toBeDefined(); - expect(groupBy.properties._max).toBeDefined(); - }); - - it('GroupByOutputType includes _avg and _sum for models with numeric fields', () => { - const groupBy = spec.components.schemas['PostGroupByOutputType']; - expect(groupBy).toBeDefined(); - expect(groupBy.properties._avg).toBeDefined(); - expect(groupBy.properties._sum).toBeDefined(); - // viewCount is non-optional so should be required - expect(groupBy.properties.viewCount).toEqual({ type: 'integer' }); - expect(groupBy.required).toContain('viewCount'); - }); - - it('AggregateResponse references Aggregate schema', () => { - const resp = spec.components.schemas['UserAggregateResponse']; - expect(resp.properties.data).toEqual({ $ref: '#/components/schemas/AggregateUser' }); - expect(resp.properties.meta).toEqual({ $ref: '#/components/schemas/_Meta' }); - }); - - it('GroupByResponse references GroupByOutputType as array', () => { - const resp = spec.components.schemas['UserGroupByResponse']; - expect(resp.properties.data).toEqual({ - type: 'array', - items: { $ref: '#/components/schemas/UserGroupByOutputType' }, - }); - expect(resp.properties.meta).toEqual({ $ref: '#/components/schemas/_Meta' }); - }); - }); - - describe('count schemas', () => { - it('CountAggregateOutputType has all non-relation fields as integer plus _all', () => { - const countType = spec.components.schemas['UserCountAggregateOutputType']; - expect(countType).toBeDefined(); - expect(countType.type).toBe('object'); - // All non-relation fields as integer - expect(countType.properties.id).toEqual({ type: 'integer' }); - expect(countType.properties.email).toEqual({ type: 'integer' }); - expect(countType.properties.createdAt).toEqual({ type: 'integer' }); - expect(countType.properties.updatedAt).toEqual({ type: 'integer' }); - // _all field - expect(countType.properties._all).toEqual({ type: 'integer' }); - // No relation fields - expect(countType.properties.posts).toBeUndefined(); - // All fields required - expect(countType.required).toContain('id'); - expect(countType.required).toContain('email'); - expect(countType.required).toContain('_all'); - }); - - it('CountResponse data is oneOf integer or CountAggregateOutputType', () => { - const resp = spec.components.schemas['UserCountResponse']; - expect(resp).toBeDefined(); - expect(resp.properties.data.oneOf).toEqual([ - { type: 'integer' }, - { $ref: '#/components/schemas/UserCountAggregateOutputType' }, - ]); - expect(resp.properties.meta).toEqual({ $ref: '#/components/schemas/_Meta' }); - }); - - it('CountArgs has select and where', () => { - const args = spec.components.schemas['UserCountArgs']; - expect(args).toBeDefined(); - expect(args.properties.select).toEqual({ $ref: '#/components/schemas/UserSelect' }); - expect(args.properties.where).toEqual({ $ref: '#/components/schemas/UserWhereInput' }); - expect(args.properties.take).toEqual({ type: 'integer' }); - expect(args.properties.skip).toEqual({ type: 'integer' }); - }); - - it('CountAggregateOutputType includes FK fields', () => { - const countType = spec.components.schemas['PostCountAggregateOutputType']; - expect(countType).toBeDefined(); - expect(countType.properties.authorId).toEqual({ type: 'integer' }); - expect(countType.required).toContain('authorId'); - }); - }); -}); - -describe('RPC OpenAPI spec generation - baseline', () => { - it('matches baseline', async () => { - const client = await createTestClient(schema); - const handler = new RPCApiHandler({ schema: client.$schema }); - const spec = await handler.generateSpec(); - const baselineFile = 'rpc.baseline.yaml'; - - if (UPDATE_BASELINE) { - saveBaseline(baselineFile, spec); - return; - } - - const baseline = loadBaseline(baselineFile); - expect(spec).toEqual(baseline); - - await validate(spec); - }); -}); - -describe('RPC OpenAPI spec generation - with procedures', () => { - it('procedure paths are generated', async () => { - const schemaWithProc = ` -model User { - id String @id @default(cuid()) - email String @unique -} - -procedure getUser(id: String): String -mutation procedure createUser(email: String): String -`; - const client = await createTestClient(schemaWithProc); - const h = new RPCApiHandler({ schema: client.$schema }); - const s = await h.generateSpec(); - expect(s.paths?.['/$procs/getUser']).toBeDefined(); - expect(s.paths?.['/$procs/getUser']?.get).toBeDefined(); - expect(s.paths?.['/$procs/createUser']).toBeDefined(); - expect(s.paths?.['/$procs/createUser']?.post).toBeDefined(); - }); -}); From 873b4e938e056b25e10d3d243dd54b6b653a439a Mon Sep 17 00:00:00 2001 From: ymc9 <104139426+ymc9@users.noreply.github.com> Date: Thu, 19 Mar 2026 20:08:49 -0700 Subject: [PATCH 15/16] fix build --- packages/server/src/api/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/server/src/api/index.ts b/packages/server/src/api/index.ts index b32662201..03c5d8819 100644 --- a/packages/server/src/api/index.ts +++ b/packages/server/src/api/index.ts @@ -1,2 +1,3 @@ export type { OpenApiSpecGenerator, OpenApiSpecOptions } from './common/types'; export { RestApiHandler, type RestApiHandlerOptions } from './rest'; +export { RPCApiHandler, type RPCApiHandlerOptions } from './rpc'; From 6a05ef0e13c1ddaa3fb67140d475a656d8b5bf28 Mon Sep 17 00:00:00 2001 From: ymc9 <104139426+ymc9@users.noreply.github.com> Date: Thu, 19 Mar 2026 21:24:06 -0700 Subject: [PATCH 16/16] fix: structure REST OpenAPI model schema with attributes/relationships Restructure buildModelReadSchema to nest scalar fields under `attributes` and relation fields under `relationships`, matching JSON:API resource structure. Relation fields now use proper relationship refs (_toManyRelationshipWithLinks/_toOneRelationshipWithLinks). Also generate schemas for composite type definitions (typeDefs). Co-Authored-By: Claude Opus 4.6 --- packages/server/src/api/rest/openapi.ts | 68 +++- .../test/openapi/baseline/rest.baseline.yaml | 343 ++++++++++-------- .../server/test/openapi/rest-openapi.test.ts | 32 +- 3 files changed, 262 insertions(+), 181 deletions(-) diff --git a/packages/server/src/api/rest/openapi.ts b/packages/server/src/api/rest/openapi.ts index 1f4ec505c..b3429d4dd 100644 --- a/packages/server/src/api/rest/openapi.ts +++ b/packages/server/src/api/rest/openapi.ts @@ -1,5 +1,5 @@ import { lowerCaseFirst } from '@zenstackhq/common-helpers'; -import type { EnumDef, FieldDef, ModelDef, SchemaDef } from '@zenstackhq/orm/schema'; +import type { EnumDef, FieldDef, ModelDef, SchemaDef, TypeDefDef } from '@zenstackhq/orm/schema'; import type { OpenAPIV3_1 } from 'openapi-types'; import { PROCEDURE_ROUTE_PREFIXES } from '../common/procedures'; import { @@ -524,6 +524,13 @@ export class RestApiSpecGenerator { } } + // Per-typeDef schemas + if (this.schema.typeDefs) { + for (const [typeName, typeDef] of Object.entries(this.schema.typeDefs)) { + schemas[typeName] = this.buildTypeDefSchema(typeDef); + } + } + // Per-model schemas for (const modelName of getIncludedModels(this.schema, this.queryOptions)) { const modelDef = this.schema.models[modelName]!; @@ -710,31 +717,66 @@ export class RestApiSpecGenerator { }; } - private buildModelReadSchema(modelName: string, modelDef: ModelDef): SchemaObject { + private buildTypeDefSchema(typeDef: TypeDefDef): SchemaObject { const properties: Record = {}; const required: string[] = []; + for (const [fieldName, fieldDef] of Object.entries(typeDef.fields)) { + properties[fieldName] = this.fieldToSchema(fieldDef); + if (!fieldDef.optional && !fieldDef.array) { + required.push(fieldName); + } + } + + const result: SchemaObject = { type: 'object', properties }; + if (required.length > 0) { + result.required = required; + } + return result; + } + + private buildModelReadSchema(modelName: string, modelDef: ModelDef): SchemaObject { + const attrProperties: Record = {}; + const attrRequired: string[] = []; + const relProperties: Record = {}; + for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) { if (fieldDef.omit) continue; if (isFieldOmitted(modelName, fieldName, this.queryOptions)) continue; if (fieldDef.relation && !isModelIncluded(fieldDef.type, this.queryOptions)) continue; - const schema = this.fieldToSchema(fieldDef); - const fieldDescription = getMetaDescription(fieldDef.attributes); - if (fieldDescription && !('$ref' in schema)) { - schema.description = fieldDescription; - } - properties[fieldName] = schema; + if (fieldDef.relation) { + const relRef: SchemaObject | ReferenceObject = fieldDef.array + ? { $ref: '#/components/schemas/_toManyRelationshipWithLinks' } + : { $ref: '#/components/schemas/_toOneRelationshipWithLinks' }; + relProperties[fieldName] = fieldDef.optional ? { oneOf: [{ type: 'null' }, relRef] } : relRef; + } else { + const schema = this.fieldToSchema(fieldDef); + const fieldDescription = getMetaDescription(fieldDef.attributes); + if (fieldDescription && !('$ref' in schema)) { + schema.description = fieldDescription; + } + attrProperties[fieldName] = schema; - if (!fieldDef.optional && !fieldDef.array) { - required.push(fieldName); + if (!fieldDef.optional && !fieldDef.array) { + attrRequired.push(fieldName); + } } } - const result: SchemaObject = { type: 'object', properties }; - if (required.length > 0) { - result.required = required; + const properties: Record = {}; + + if (Object.keys(attrProperties).length > 0) { + const attrSchema: SchemaObject = { type: 'object', properties: attrProperties }; + if (attrRequired.length > 0) attrSchema.required = attrRequired; + properties['attributes'] = attrSchema; } + + if (Object.keys(relProperties).length > 0) { + properties['relationships'] = { type: 'object', properties: relProperties }; + } + + const result: SchemaObject = { type: 'object', properties }; const description = getMetaDescription(modelDef.attributes); if (description) { result.description = description; diff --git a/packages/server/test/openapi/baseline/rest.baseline.yaml b/packages/server/test/openapi/baseline/rest.baseline.yaml index fb2cd3ce3..0bd8177b0 100644 --- a/packages/server/test/openapi/baseline/rest.baseline.yaml +++ b/packages/server/test/openapi/baseline/rest.baseline.yaml @@ -3112,44 +3112,53 @@ components: $ref: "#/components/schemas/_relationLinks" meta: $ref: "#/components/schemas/_meta" - User: + Address: type: object properties: - myId: - type: string - createdAt: - type: string - format: date-time - updatedAt: + city: type: string - format: date-time - email: - type: string - posts: - type: array - items: - $ref: "#/components/schemas/Post" - likes: - type: array - items: - $ref: "#/components/schemas/PostLike" - profile: - oneOf: - - $ref: "#/components/schemas/Profile" - - type: "null" - address: - oneOf: - - $ref: "#/components/schemas/Address" - - type: "null" - someJson: - oneOf: - - {} - - type: "null" required: - - myId - - createdAt - - updatedAt - - email + - city + User: + type: object + properties: + attributes: + type: object + properties: + myId: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + email: + type: string + address: + oneOf: + - $ref: "#/components/schemas/Address" + - type: "null" + someJson: + oneOf: + - {} + - type: "null" + required: + - myId + - createdAt + - updatedAt + - email + relationships: + type: object + properties: + posts: + $ref: "#/components/schemas/_toManyRelationshipWithLinks" + likes: + $ref: "#/components/schemas/_toManyRelationshipWithLinks" + profile: + oneOf: + - type: "null" + - $ref: "#/components/schemas/_toOneRelationshipWithLinks" UserCreateRequest: type: object properties: @@ -3288,19 +3297,24 @@ components: Profile: type: object properties: - id: - type: integer - gender: - type: string - user: - $ref: "#/components/schemas/User" - userId: - type: string - required: - - id - - gender - - user - - userId + attributes: + type: object + properties: + id: + type: integer + gender: + type: string + userId: + type: string + required: + - id + - gender + - userId + relationships: + type: object + properties: + user: + $ref: "#/components/schemas/_toOneRelationshipWithLinks" ProfileCreateRequest: type: object properties: @@ -3389,52 +3403,54 @@ components: Post: type: object properties: - id: - type: integer - createdAt: - type: string - format: date-time - updatedAt: - type: string - format: date-time - title: - type: string - author: - oneOf: - - $ref: "#/components/schemas/User" - - type: "null" - authorId: - oneOf: - - type: string - - type: "null" - published: - type: boolean - publishedAt: - oneOf: - - type: string - format: date-time - - type: "null" - viewCount: - type: integer - comments: - type: array - items: - $ref: "#/components/schemas/Comment" - likes: - type: array - items: - $ref: "#/components/schemas/PostLike" - setting: - oneOf: - - $ref: "#/components/schemas/Setting" - - type: "null" - required: - - id - - createdAt - - updatedAt - - title - - published - - viewCount + attributes: + type: object + properties: + id: + type: integer + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + title: + type: string + authorId: + oneOf: + - type: string + - type: "null" + published: + type: boolean + publishedAt: + oneOf: + - type: string + format: date-time + - type: "null" + viewCount: + type: integer + required: + - id + - createdAt + - updatedAt + - title + - published + - viewCount + relationships: + type: object + properties: + author: + oneOf: + - type: "null" + - $ref: "#/components/schemas/_toOneRelationshipWithLinks" + comments: + $ref: "#/components/schemas/_toManyRelationshipWithLinks" + likes: + $ref: "#/components/schemas/_toManyRelationshipWithLinks" + setting: + oneOf: + - type: "null" + - $ref: "#/components/schemas/_toOneRelationshipWithLinks" PostCreateRequest: type: object properties: @@ -3585,19 +3601,24 @@ components: Comment: type: object properties: - id: - type: integer - post: - $ref: "#/components/schemas/Post" - postId: - type: integer - content: - type: string - required: - - id - - post - - postId - - content + attributes: + type: object + properties: + id: + type: integer + postId: + type: integer + content: + type: string + required: + - id + - postId + - content + relationships: + type: object + properties: + post: + $ref: "#/components/schemas/_toOneRelationshipWithLinks" CommentCreateRequest: type: object properties: @@ -3686,19 +3707,24 @@ components: Setting: type: object properties: - id: - type: integer - boost: - type: integer - post: - $ref: "#/components/schemas/Post" - postId: - type: integer - required: - - id - - boost - - post - - postId + attributes: + type: object + properties: + id: + type: integer + boost: + type: integer + postId: + type: integer + required: + - id + - boost + - postId + relationships: + type: object + properties: + post: + $ref: "#/components/schemas/_toOneRelationshipWithLinks" SettingCreateRequest: type: object properties: @@ -3787,26 +3813,28 @@ components: PostLike: type: object properties: - postId: - type: integer - userId: - type: string - superLike: - type: boolean - post: - $ref: "#/components/schemas/Post" - user: - $ref: "#/components/schemas/User" - likeInfos: - type: array - items: - $ref: "#/components/schemas/PostLikeInfo" - required: - - postId - - userId - - superLike - - post - - user + attributes: + type: object + properties: + postId: + type: integer + userId: + type: string + superLike: + type: boolean + required: + - postId + - userId + - superLike + relationships: + type: object + properties: + post: + $ref: "#/components/schemas/_toOneRelationshipWithLinks" + user: + $ref: "#/components/schemas/_toOneRelationshipWithLinks" + likeInfos: + $ref: "#/components/schemas/_toManyRelationshipWithLinks" PostLikeCreateRequest: type: object properties: @@ -3917,22 +3945,27 @@ components: PostLikeInfo: type: object properties: - id: - type: integer - text: - type: string - postId: - type: integer - userId: - type: string - postLike: - $ref: "#/components/schemas/PostLike" - required: - - id - - text - - postId - - userId - - postLike + attributes: + type: object + properties: + id: + type: integer + text: + type: string + postId: + type: integer + userId: + type: string + required: + - id + - text + - postId + - userId + relationships: + type: object + properties: + postLike: + $ref: "#/components/schemas/_toOneRelationshipWithLinks" PostLikeInfoCreateRequest: type: object properties: diff --git a/packages/server/test/openapi/rest-openapi.test.ts b/packages/server/test/openapi/rest-openapi.test.ts index f235502af..87e2c246b 100644 --- a/packages/server/test/openapi/rest-openapi.test.ts +++ b/packages/server/test/openapi/rest-openapi.test.ts @@ -170,20 +170,22 @@ describe('REST OpenAPI spec generation', () => { it('field types in schemas', () => { const userSchema = spec.components.schemas['User']; - expect(userSchema.properties).toBeDefined(); + const userAttrs = userSchema.properties.attributes.properties; + expect(userAttrs).toBeDefined(); // email -> string - expect(userSchema.properties['email']).toMatchObject({ type: 'string' }); + expect(userAttrs['email']).toMatchObject({ type: 'string' }); // myId -> string - expect(userSchema.properties['myId']).toMatchObject({ type: 'string' }); + expect(userAttrs['myId']).toMatchObject({ type: 'string' }); const postSchema = spec.components.schemas['Post']; - expect(postSchema.properties).toBeDefined(); + const postAttrs = postSchema.properties.attributes.properties; + expect(postAttrs).toBeDefined(); // viewCount -> integer - expect(postSchema.properties['viewCount']).toMatchObject({ type: 'integer' }); + expect(postAttrs['viewCount']).toMatchObject({ type: 'integer' }); // published -> boolean - expect(postSchema.properties['published']).toMatchObject({ type: 'boolean' }); + expect(postAttrs['published']).toMatchObject({ type: 'boolean' }); // createdAt -> date-time - expect(postSchema.properties['createdAt']).toMatchObject({ type: 'string', format: 'date-time' }); + expect(postAttrs['createdAt']).toMatchObject({ type: 'string', format: 'date-time' }); }); it('required fields marked in create schema', () => { @@ -275,8 +277,9 @@ describe('REST OpenAPI spec generation - queryOptions', () => { }); const s = await handler.generateSpec(); const userSchema = s.components?.schemas?.['User'] as any; - expect(userSchema.properties['myId']).toBeDefined(); - expect(userSchema.properties['email']).toBeUndefined(); + const userAttrs = userSchema.properties.attributes.properties; + expect(userAttrs['myId']).toBeDefined(); + expect(userAttrs['email']).toBeUndefined(); }); it('slicing excludedModels removes model from spec', async () => { @@ -297,8 +300,10 @@ describe('REST OpenAPI spec generation - queryOptions', () => { // Relation fields to excluded model should not appear in read schema const userSchema = s.components?.schemas?.['User'] as any; - expect(userSchema.properties['posts']).toBeUndefined(); - expect(userSchema.properties['email']).toBeDefined(); + const userRels = userSchema.properties.relationships?.properties ?? {}; + expect(userRels['posts']).toBeUndefined(); + const userAttrs = userSchema.properties.attributes.properties; + expect(userAttrs['email']).toBeDefined(); }); it('slicing includedModels limits models in spec', async () => { @@ -601,10 +606,11 @@ model Post { const s = await handler.generateSpec(); const userSchema = s.components?.schemas?.['User'] as any; - expect(userSchema.properties['email'].description).toBe("The user's email address"); + const userAttrs = userSchema.properties.attributes.properties; + expect(userAttrs['email'].description).toBe("The user's email address"); // id has no @meta description - expect(userSchema.properties['id'].description).toBeUndefined(); + expect(userAttrs['id'].description).toBeUndefined(); }); });