Skip to content

Commit

Permalink
feat(clients): add zod (#785)
Browse files Browse the repository at this point in the history
* feat(clients): add zod

* feat(zod): add validations variables

* feat(zod): handling some format and escap regex

* fix(zod): package json version
  • Loading branch information
anymaniax authored Mar 27, 2023
1 parent 623b7e3 commit cebdb2e
Show file tree
Hide file tree
Showing 18 changed files with 504 additions and 502 deletions.
476 changes: 0 additions & 476 deletions docs/generated/endpoints.ts

This file was deleted.

4 changes: 2 additions & 2 deletions packages/core/src/getters/array.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { SchemaObject } from 'openapi3-ts';
import { ContextSpecs, ResolverValue } from '../types';
import { ContextSpecs, ScalarValue } from '../types';
import { resolveObject } from '../resolvers/object';

/**
Expand All @@ -15,7 +15,7 @@ export const getArray = ({
schema: SchemaObject;
name?: string;
context: ContextSpecs;
}): ResolverValue => {
}): ScalarValue => {
if (schema.items) {
const resolvedObject = resolveObject({
schema: schema.items,
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/getters/body.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { ReferenceObject, RequestBodyObject } from 'openapi3-ts';
import { generalJSTypesWithArray } from '../constants';
import { ContextSpecs, OverrideOutputContentType } from '../types';
import { GetterBody } from '../types';
import { ContextSpecs, GetterBody, OverrideOutputContentType } from '../types';
import { camel } from '../utils';
import { getResReqTypes } from './res-req-types';

Expand Down Expand Up @@ -51,6 +50,7 @@ export const getBody = ({
: camel(definition);

return {
originalSchema: requestBody,
definition,
implementation,
imports,
Expand Down
6 changes: 3 additions & 3 deletions packages/core/src/getters/combine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
ContextSpecs,
GeneratorImport,
GeneratorSchema,
ResolverValue,
ScalarValue,
SchemaType,
} from '../types';
import { getNumberWord, pascal } from '../utils';
Expand All @@ -30,7 +30,7 @@ const combineValues = ({
separator,
}: {
resolvedData: CombinedData;
resolvedValue?: ResolverValue;
resolvedValue?: ScalarValue;
separator: Separator;
}) => {
const isAllEnums = resolvedData.isEnum.every((v) => v);
Expand Down Expand Up @@ -68,7 +68,7 @@ export const combineSchemas = ({
separator: Separator;
context: ContextSpecs;
nullable: string;
}): ResolverValue => {
}): ScalarValue => {
const items = schema[separator] ?? [];

const resolvedData = items.reduce<CombinedData>(
Expand Down
6 changes: 3 additions & 3 deletions packages/core/src/getters/object.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ReferenceObject, SchemaObject } from 'openapi3-ts';
import { resolveObject, resolveValue } from '../resolvers';
import { ContextSpecs, ResolverValue, SchemaType } from '../types';
import { ContextSpecs, ScalarValue, SchemaType } from '../types';
import { isBoolean, isReference, jsDoc, pascal } from '../utils';
import { combineSchemas } from './combine';
import { getKey } from './keys';
Expand All @@ -21,7 +21,7 @@ export const getObject = ({
name?: string;
context: ContextSpecs;
nullable: string;
}): ResolverValue => {
}): ScalarValue => {
if (isReference(item)) {
const { name, specKey } = getRefInfo(item.$ref, context);
return {
Expand Down Expand Up @@ -137,7 +137,7 @@ export const getObject = ({
type: 'object' as SchemaType,
isRef: false,
schema: {},
} as ResolverValue,
} as ScalarValue,
);
}

Expand Down
1 change: 1 addition & 0 deletions packages/core/src/getters/params.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ export const getParams = ({
default: resolvedValue.originalSchema!.default,
required,
imports: resolvedValue.imports,
originalSchema: resolvedValue.originalSchema,
};
});
};
18 changes: 10 additions & 8 deletions packages/core/src/getters/query-params.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,13 +139,15 @@ describe('getQueryParams getter', () => {
operationName: '',
context,
});
expect(result?.schema.model.trim()).toBe([
'export type Params = {',
'/**',
' * Parameter description.',
' */',
'queryParamWithDescription?: string;',
'};',
].join('\n'));
expect(result?.schema.model.trim()).toBe(
[
'export type Params = {',
'/**',
' * Parameter description.',
' */',
'queryParamWithDescription?: string;',
'};',
].join('\n'),
);
});
});
4 changes: 4 additions & 0 deletions packages/core/src/getters/query-params.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ type QueryParamsType = {
definition: string;
imports: GeneratorImport[];
schemas: GeneratorSchema[];
originalSchema: SchemaObject;
};

const getQueryParamsTypes = (
Expand Down Expand Up @@ -61,6 +62,7 @@ const getQueryParamsTypes = (
};`,
imports: parameterImports,
schemas: [],
originalSchema: resolvedeValue.originalSchema,
};
}

Expand All @@ -82,6 +84,7 @@ const getQueryParamsTypes = (
...resolvedeValue.schemas,
{ name: enumName, model: enumValue, imports: resolvedeValue.imports },
],
originalSchema: resolvedeValue.originalSchema,
};
}

Expand All @@ -93,6 +96,7 @@ const getQueryParamsTypes = (
definition,
imports: resolvedeValue.imports,
schemas: resolvedeValue.schemas,
originalSchema: resolvedeValue.originalSchema,
};
});
};
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/getters/response.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,5 +93,6 @@ export const getResponse = ({
types: groupedByStatus,
contentTypes,
schemas,
originalSchema: responses,
};
};
4 changes: 2 additions & 2 deletions packages/core/src/getters/scalar.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { SchemaObject } from 'openapi3-ts';
import { ContextSpecs, ResolverValue } from '../types';
import { ContextSpecs, ScalarValue } from '../types';
import { escape, isString } from '../utils';
import { getArray } from './array';
import { getObject } from './object';
Expand All @@ -18,7 +18,7 @@ export const getScalar = ({
item: SchemaObject;
name?: string;
context: ContextSpecs;
}): ResolverValue => {
}): ScalarValue => {
const nullable = item.nullable ? ' | null' : '';

if (!item.type && item.items) {
Expand Down
20 changes: 16 additions & 4 deletions packages/core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import {
OpenAPIObject,
OperationObject,
ParameterObject,
ReferenceObject,
RequestBodyObject,
ResponsesObject,
SchemaObject,
} from 'openapi3-ts';
import swagger2openapi from 'swagger2openapi';
Expand Down Expand Up @@ -175,7 +178,8 @@ export type OutputClient =
| 'react-query'
| 'svelte-query'
| 'vue-query'
| 'swr';
| 'swr'
| 'zod';

export const OutputClient = {
ANGULAR: 'angular' as OutputClient,
Expand Down Expand Up @@ -591,9 +595,12 @@ export type GetterResponse = {
};
contentTypes: string[];
schemas: GeneratorSchema[];

originalSchema?: ResponsesObject;
};

export type GetterBody = {
originalSchema: ReferenceObject | RequestBodyObject;
imports: GeneratorImport[];
definition: string;
implementation: string;
Expand Down Expand Up @@ -623,6 +630,7 @@ export type GetterQueryParam = {
schema: GeneratorSchema;
deps: GeneratorSchema[];
isOptional: boolean;
originalSchema?: SchemaObject;
};

export type GetterPropType = 'param' | 'body' | 'queryParam' | 'header';
Expand Down Expand Up @@ -668,22 +676,26 @@ export const SchemaType = {
unknown: 'unknown',
};

export type ResolverValue = {
export type ScalarValue = {
value: string;
isEnum: boolean;
type: SchemaType;
imports: GeneratorImport[];
schemas: GeneratorSchema[];
originalSchema?: SchemaObject;
isRef: boolean;
};

export type ResReqTypesValue = ResolverValue & {
export type ResolverValue = ScalarValue & {
originalSchema: SchemaObject;
};

export type ResReqTypesValue = ScalarValue & {
formData?: string;
formUrlEncoded?: string;
isRef?: boolean;
key: string;
contentType: string;
originalSchema?: SchemaObject;
};

export type WriteSpecsBuilder = {
Expand Down
5 changes: 3 additions & 2 deletions packages/orval/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@
},
"scripts": {
"build": "tsup ./src/bin/orval.ts ./src/index.ts --target node12 --minify --clean --dts --splitting",
"dev": "tsup ./src/bin/orval.ts ./src/index.ts --target node12 --clean --watch src --onSuccess 'yarn generate-api'",
"dev": "tsup ./src/bin/orval.ts ./src/index.ts --target node12 --clean --watch ./src --onSuccess 'yarn generate-api'",
"lint": "eslint src/**/*.ts",
"generate-api": "node ./dist/bin/orval.js --config ../../samples/react-query/basic/orval.config.ts --watch"
"generate-api": "node ./dist/bin/orval.js --config ../../samples/react-query/basic/orval.config.ts"
},
"devDependencies": {
"@types/chalk": "^2.2.0",
Expand All @@ -60,6 +60,7 @@
"@orval/msw": "6.12.1",
"@orval/query": "6.12.1",
"@orval/swr": "6.12.1",
"@orval/zod": "6.12.1",
"ajv": "^8.11.0",
"cac": "^6.7.12",
"chalk": "^4.1.2",
Expand Down
6 changes: 6 additions & 0 deletions packages/orval/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
import { generateMSW } from '@orval/msw';
import query from '@orval/query';
import swr from '@orval/swr';
import zod from '@orval/zod';

const DEFAULT_CLIENT = OutputClient.AXIOS;

Expand All @@ -31,6 +32,7 @@ export const GENERATOR_CLIENT: GeneratorClients = {
'svelte-query': query({ type: 'svelte-query' })(),
'vue-query': query({ type: 'vue-query' })(),
swr: swr()(),
zod: zod()(),
};

const getGeneratorClient = (outputClient: OutputClient | OutputClientFunc) => {
Expand Down Expand Up @@ -201,6 +203,10 @@ export const generateOperations = (
const client = await generatorClient(verbOption, options, outputClient);
const msw = generateMock(verbOption, options);

if (!client.implementation) {
return acc;
}

acc[verbOption.operationId] = {
implementation: verbOption.doc + client.implementation,
imports: client.imports,
Expand Down
1 change: 1 addition & 0 deletions packages/query/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -909,6 +909,7 @@ const generateQueryHook = async (
}${body.implementation ? `, ${body.implementation}` : ''}];`;

const implementation = `${!queryKeyMutator ? queryKeyFn : ''}
${queries.reduce(
(acc, queryOption) =>
Expand Down
28 changes: 28 additions & 0 deletions packages/zod/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
[![npm version](https://badge.fury.io/js/orval.svg)](https://badge.fury.io/js/orval)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![tests](https://github.com/anymaniax/orval/actions/workflows/tests.yaml/badge.svg)](https://github.com/anymaniax/orval/actions/workflows/tests.yaml)

<p align="center">
<img src="./logo/orval-logo-horizontal.svg?raw=true" width="500" height="160" alt="orval - Restfull Client Generator" />
</p>
<h1 align="center">
Visit <a href="https://orval.dev" target="_blank">orval.dev</a> for docs, guides, API and beer!
</h1>

### Code Generation

`orval` is able to generate client with appropriate type-signatures (TypeScript) from any valid OpenAPI v3 or Swagger v2 specification, either in `yaml` or `json` formats.

`Generate`, `valid`, `cache` and `mock` in your React, Vue, Svelte and Angular applications all with your OpenAPI specification.

### Samples

You can find below some samples

- [react app](https://github.com/anymaniax/orval/tree/master/samples/react-app)
- [react query](https://github.com/anymaniax/orval/tree/master/samples/react-query)
- [svelte query](https://github.com/anymaniax/orval/tree/master/samples/svelte-query)
- [vue query](https://github.com/anymaniax/orval/tree/master/samples/vue-query)
- [react app with swr](https://github.com/anymaniax/orval/tree/master/samples/react-app-with-swr)
- [nx fastify react](https://github.com/anymaniax/orval/tree/master/samples/nx-fastify-react)
- [angular app](https://github.com/anymaniax/orval/tree/master/samples/angular-app)
18 changes: 18 additions & 0 deletions packages/zod/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "@orval/zod",
"version": "6.12.1",
"license": "MIT",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"files": [
"dist"
],
"scripts": {
"build": "tsup ./src/index.ts --target node12 --minify --clean --dts --splitting",
"dev": "tsup ./src/index.ts --target node12 --clean --watch src",
"lint": "eslint src/**/*.ts"
},
"dependencies": {
"@orval/core": "6.12.1"
}
}
Loading

1 comment on commit cebdb2e

@vercel
Copy link

@vercel vercel bot commented on cebdb2e Mar 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.