Skip to content

Commit

Permalink
refactor: make input, meta and output optional
Browse files Browse the repository at this point in the history
  • Loading branch information
Siumauricio committed Jun 23, 2024
1 parent 8a4d0c5 commit f1e3d6e
Show file tree
Hide file tree
Showing 8 changed files with 133 additions and 94 deletions.
7 changes: 7 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
examples/
examples/with-nextjs/
examples/with-express/
examples/with-interop/
examples/with-serverless/
examples/with-fastify/
examples/with-nuxtjs/
19 changes: 10 additions & 9 deletions examples/with-nextjs/src/server/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ const authRouter = t.router({
register: publicProcedure
.meta({
openapi: {
additional: true,
method: "POST",
path: "/auth/register",
tags: ["auth"],
Expand All @@ -84,15 +85,15 @@ const authRouter = t.router({
name: z.string().min(3),
}),
)
.output(
z.object({
user: z.object({
id: z.string().uuid(),
email: z.string().email(),
name: z.string().min(3),
}),
}),
)
// .output(
// z.object({
// user: z.object({
// id: z.string().uuid(),
// email: z.string().email(),
// name: z.string().min(3),
// }),
// }),
// )
.mutation(({ input }) => {
let user = database.users.find((_user) => _user.email === input.email);

Expand Down
13 changes: 9 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@dokploy/trpc-openapi",
"version": "0.0.1",
"version": "0.0.4",
"description": "tRPC OpenAPI",
"author": "Mauricio Siu <[email protected]>",
"private": false,
Expand All @@ -13,9 +13,9 @@
"openapi",
"swagger"
],
"homepage": "https://github.com/jlalmes/trpc-openapi",
"repository": "github:jlalmes/trpc-openapi",
"bugs": "https://github.com/jlalmes/trpc-openapi/issues",
"homepage": "https://github.com/dokploy/trpc-openapi",
"repository": "github:dokploy/trpc-openapi",
"bugs": "https://github.com/dokploy/trpc-openapi/issues",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"workspaces": [
Expand All @@ -24,6 +24,11 @@
"examples/with-express",
"examples/with-interop"
],
"files": [
"dist",
"README.md",
"LICENSE"
],
"scripts": {
"test": "tsc --noEmit && jest --verbose",
"build": "rimraf dist && tsc -p tsconfig.build.json"
Expand Down
2 changes: 1 addition & 1 deletion src/generator/paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ export const getOpenApiPathsObject = (
openapi.example?.response,
openapi.responseHeaders,
),
// ...(openapi.deprecated ? { deprecated: openapi.deprecated } : {}),
...(openapi.deprecated ? { deprecated: openapi.deprecated } : {}),
},
};
} catch (error: any) {
Expand Down
4 changes: 2 additions & 2 deletions src/generator/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export const getParameterObjects = (
inType: "all" | "path" | "query",
example: Record<string, any> | undefined,
): OpenAPIV3.ParameterObject[] | undefined => {
const schema = currentSchema ?? z.void();
const schema = currentSchema || z.void();
const isRequired = !schema.isOptional();
const unwrappedSchema = unwrapZodType(schema, true);

Expand Down Expand Up @@ -130,7 +130,7 @@ export const getRequestBodyObject = (
// });
// }

const schema = currentSchema ?? z.void();
const schema = currentSchema || z.void();

const isRequired = !schema.isOptional();
const unwrappedSchema = unwrapZodType(schema, true);
Expand Down
129 changes: 71 additions & 58 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,79 +1,92 @@
import { Procedure, ProcedureParams, Router } from '@trpc/server';
import type { RootConfig } from '@trpc/server/dist/core/internals/config';
import { TRPC_ERROR_CODE_KEY } from '@trpc/server/rpc';
import type { RouterDef } from '@trpc/server/src/core/router';
import { OpenAPIV3 } from 'openapi-types';
import { ZodIssue } from 'zod';
import { Procedure, ProcedureParams, Router } from "@trpc/server";
import type { RootConfig } from "@trpc/server/dist/core/internals/config";
import { TRPC_ERROR_CODE_KEY } from "@trpc/server/rpc";
import type { RouterDef } from "@trpc/server/src/core/router";
import { OpenAPIV3 } from "openapi-types";
import { ZodIssue } from "zod";

export type OpenApiMethod = 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE';
export type OpenApiMethod = "GET" | "POST" | "PATCH" | "PUT" | "DELETE";

type TRPCMeta = Record<string, unknown>;

export type OpenApiContentType =
| 'application/json'
| 'application/x-www-form-urlencoded'
// eslint-disable-next-line @typescript-eslint/ban-types
| (string & {});
| "application/json"
| "application/x-www-form-urlencoded"
// eslint-disable-next-line @typescript-eslint/ban-types
| (string & {});

export type OpenApiMeta<TMeta = TRPCMeta> = TMeta & {
openapi?: {
enabled?: boolean;
method: OpenApiMethod;
path: `/${string}`;
summary?: string;
description?: string;
protect?: boolean;
tags?: string[];
headers?: (OpenAPIV3.ParameterBaseObject & { name: string; in?: 'header' })[];
contentTypes?: OpenApiContentType[];
deprecated?: boolean;
example?: {
request?: Record<string, any>;
response?: Record<string, any>;
};
responseHeaders?: Record<string, OpenAPIV3.HeaderObject | OpenAPIV3.ReferenceObject>;
};
openapi?: {
override?: boolean;
additional?: boolean;
enabled?: boolean;
method: OpenApiMethod;
path: `/${string}`;
summary?: string;
description?: string;
protect?: boolean;
tags?: string[];
headers?: (OpenAPIV3.ParameterBaseObject & {
name: string;
in?: "header";
})[];
contentTypes?: OpenApiContentType[];
deprecated?: boolean;
example?: {
request?: Record<string, any>;
response?: Record<string, any>;
};
responseHeaders?: Record<
string,
OpenAPIV3.HeaderObject | OpenAPIV3.ReferenceObject
>;
};
};

export type OpenApiProcedure<TMeta = TRPCMeta> = Procedure<
'query' | 'mutation',
ProcedureParams<
RootConfig<{
transformer: any;
errorShape: any;
ctx: any;
meta: OpenApiMeta<TMeta>;
}>,
any,
any,
any,
any,
any,
OpenApiMeta<TMeta>
>
"query" | "mutation",
ProcedureParams<
RootConfig<{
transformer: any;
errorShape: any;
ctx: any;
meta: OpenApiMeta<TMeta>;
}>,
any,
any,
any,
any,
any,
OpenApiMeta<TMeta>
>
>;

export type OpenApiProcedureRecord<TMeta = TRPCMeta> = Record<string, OpenApiProcedure<TMeta>>;
export type OpenApiProcedureRecord<TMeta = TRPCMeta> = Record<
string,
OpenApiProcedure<TMeta>
>;

export type OpenApiRouter<TMeta = TRPCMeta> = Router<
RouterDef<
RootConfig<{
transformer: any;
errorShape: any;
ctx: any;
meta: OpenApiMeta<TMeta>;
}>,
any,
any
>
RouterDef<
RootConfig<{
transformer: any;
errorShape: any;
ctx: any;
meta: OpenApiMeta<TMeta>;
}>,
any,
any
>
>;

export type OpenApiSuccessResponse<D = any> = D;

export type OpenApiErrorResponse = {
message: string;
code: TRPC_ERROR_CODE_KEY;
issues?: ZodIssue[];
message: string;
code: TRPC_ERROR_CODE_KEY;
issues?: ZodIssue[];
};

export type OpenApiResponse<D = any> = OpenApiSuccessResponse<D> | OpenApiErrorResponse;
export type OpenApiResponse<D = any> =
| OpenApiSuccessResponse<D>
| OpenApiErrorResponse;
43 changes: 24 additions & 19 deletions src/utils/procedure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { AnyZodObject, z } from "zod";

import {
OpenApiMeta,
OpenApiMethod,
OpenApiProcedure,
OpenApiProcedureRecord,
} from "../types";
Expand Down Expand Up @@ -31,6 +32,10 @@ const getProcedureType = (procedure: OpenApiProcedure): ProcedureType => {
throw new Error("Unknown procedure type");
};

export const getMethod = (procedure: OpenApiProcedure): OpenApiMethod => {
return getProcedureType(procedure) === "query" ? "GET" : "POST";
};

export const forEachOpenApiProcedure = (
procedureRecord: OpenApiProcedureRecord,
callback: (values: {
Expand All @@ -41,28 +46,28 @@ export const forEachOpenApiProcedure = (
}) => void,
) => {
for (const [path, procedure] of Object.entries(procedureRecord)) {
console.log(procedure, path);
const { openapi } = procedure._def.meta ?? {
openapi: {
method: getProcedureType(procedure) === "query" ? "GET" : "POST",
path: path,
enabled: procedure?._def?.meta ?? true,
tags: [path.split(".")[0]],
contentTypes: ["application/json"],
summary: "",
description: "",
example: {
request: {},
response: {},
},
responseHeaders: [],
deprecated: false,
headers: [],
protect: false,
},
const additional = procedure._def.meta?.openapi?.additional ?? false;
const override = procedure._def.meta?.openapi?.override ?? false;
const defaultOpenApiMeta = {
method: getMethod(procedure),
path: path,
enabled: true,
tags: [path.split(".")[0]],
protect: true,
};
let openapi: OpenApiMeta;

if (override) {
openapi = { ...procedure._def.meta?.openapi };
} else if (additional) {
openapi = { ...defaultOpenApiMeta, ...procedure._def.meta?.openapi };
} else {
openapi = { ...procedure._def.meta?.openapi, ...defaultOpenApiMeta };
}

if (openapi && openapi.enabled !== false) {
const type = getProcedureType(procedure);
// @ts-ignore
callback({ path, type, procedure, openapi });
}
}
Expand Down
10 changes: 9 additions & 1 deletion tsconfig.build.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
{
"extends": "./tsconfig.json",
"include": ["src"]
"include": ["src"],
"exclude": [
"examples/with-nextjs",
"examples/with-express",
"examples/with-interop",
"examples/with-serverless",
"examples/with-fastify",
"examples/with-nuxtjs"
]
}

0 comments on commit f1e3d6e

Please sign in to comment.