Skip to content

msw plugin #1614

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/openapi-ts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@
"express": "4.21.0",
"fastify": "5.2.0",
"glob": "10.4.3",
"msw": "2.7.0",
"node-fetch": "3.3.2",
"nuxt": "3.15.1",
"prettier": "3.4.2",
Expand Down
1 change: 1 addition & 0 deletions packages/openapi-ts/src/ir/operation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ interface OperationResponsesMap {
responses?: IR.SchemaObject;
}

// TODO: handle multiple content types
export const operationResponsesMap = (
operation: IR.OperationObject,
): OperationResponsesMap => {
Expand Down
5 changes: 5 additions & 0 deletions packages/openapi-ts/src/openApi/shared/types/schema.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ export type SchemaWithRequired<
[P in K]-?: S[P];
};

export interface SchemaWithType<T extends Required<IR.SchemaObject>['type']>
extends Omit<IR.SchemaObject, 'type'> {
type: Extract<Required<IR.SchemaObject>['type'], T>;
}

export type SchemaType<
S extends {
type?: unknown;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { compiler } from '../../../compiler';
import { operationResponsesMap } from '../../../ir/operation';
import { deduplicateSchema } from '../../../ir/schema';
import type { IR } from '../../../ir/types';
import type { SchemaWithType } from '../../../openApi/shared/types/schema';
import { escapeComment } from '../../../utils/escape';
import { irRef, isRefOpenApiComponent } from '../../../utils/ref';
import { numberRegExp } from '../../../utils/regexp';
Expand All @@ -15,11 +16,6 @@ import type { Plugin } from '../../types';
import { typesId } from './ref';
import type { Config } from './types';

interface SchemaWithType<T extends Required<IR.SchemaObject>['type']>
extends Omit<IR.SchemaObject, 'type'> {
type: Extract<Required<IR.SchemaObject>['type'], T>;
}

const parseSchemaJsDoc = ({ schema }: { schema: IR.SchemaObject }) => {
const comments = [
schema.description && escapeComment(schema.description),
Expand Down
4 changes: 4 additions & 0 deletions packages/openapi-ts/src/plugins/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import {
defaultConfig as tanStackVueQuery,
} from './@tanstack/vue-query';
import { type Config as Fastify, defaultConfig as fastify } from './fastify';
import { type Config as Msw, defaultConfig as msw } from './msw';
import type { DefaultPluginConfigs, Plugin } from './types';
import { type Config as Zod, defaultConfig as zod } from './zod';

Expand All @@ -52,6 +53,7 @@ export type UserPlugins =
| Plugin.UserConfig<TanStackSvelteQuery>
| Plugin.UserConfig<TanStackVueQuery>
| Plugin.UserConfig<Fastify>
| Plugin.UserConfig<Msw>
| Plugin.UserConfig<Zod>;

/**
Expand All @@ -68,6 +70,7 @@ export type ClientPlugins =
| Plugin.Config<TanStackSvelteQuery>
| Plugin.Config<TanStackVueQuery>
| Plugin.Config<Fastify>
| Plugin.Config<Msw>
| Plugin.Config<Zod>;

export const defaultPluginConfigs: DefaultPluginConfigs<ClientPlugins> = {
Expand All @@ -81,5 +84,6 @@ export const defaultPluginConfigs: DefaultPluginConfigs<ClientPlugins> = {
'@tanstack/svelte-query': tanStackSvelteQuery,
'@tanstack/vue-query': tanStackVueQuery,
fastify,
msw,
zod,
};
18 changes: 18 additions & 0 deletions packages/openapi-ts/src/plugins/msw/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import type { Plugin } from '../types';
import { handler } from './plugin';
import type { Config } from './types';

export const defaultConfig: Plugin.Config<Config> = {
_handler: handler,
_handlerLegacy: () => {},
name: 'msw',
output: 'msw',
};

/**
* Type helper for MSW plugin, returns {@link Plugin.Config} object
*/
export const defineConfig: Plugin.DefineConfig<Config> = (config) => ({
...defaultConfig,
...config,
});

Check warning on line 18 in packages/openapi-ts/src/plugins/msw/config.ts

View check run for this annotation

Codecov / codecov/patch

packages/openapi-ts/src/plugins/msw/config.ts#L16-L18

Added lines #L16 - L18 were not covered by tests
2 changes: 2 additions & 0 deletions packages/openapi-ts/src/plugins/msw/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { defaultConfig, defineConfig } from './config';
export type { Config } from './types';
126 changes: 126 additions & 0 deletions packages/openapi-ts/src/plugins/msw/interfaces.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import ts from 'typescript';

import { compiler } from '../../compiler';

const objectReference = compiler.typeReferenceNode({ typeName: 'object' });
const tReference = compiler.typeReferenceNode({ typeName: 'T' });
const uReference = compiler.typeReferenceNode({ typeName: 'U' });
export const undefinedReference = compiler.typeReferenceNode({
typeName: 'undefined',
});
export const neverReference = compiler.typeReferenceNode({ typeName: 'never' });

export const pathParamsTypeName = 'PathParams';
export const responseBodyTypeTypeName = 'ResponseBodyType';
const transformObjectTypeName = 'TransformObject';

export const createTransformObjectType = () => {
const tkType = compiler.indexedAccessTypeNode({
indexType: compiler.typeReferenceNode({ typeName: 'K' }),
objectType: tReference,
});
const nullType = compiler.literalTypeNode({ literal: compiler.null() });
const type = compiler.typeAliasDeclaration({
name: transformObjectTypeName,
type: compiler.mappedTypeNode({
type: ts.factory.createConditionalTypeNode(
tkType,
objectReference,
compiler.typeReferenceNode({
typeArguments: [tkType],
typeName: transformObjectTypeName,
}),
compiler.typeUnionNode({
types: [
compiler.typeReferenceNode({ typeName: 'string' }),
ts.factory.createConditionalTypeNode(
nullType,
tkType,
undefinedReference,
neverReference,
),
],
}),
),
typeParameter: compiler.typeParameterDeclaration({
constraint: compiler.typeOperatorNode({
operator: 'keyof',
type: tReference,
}),
name: 'K',
}),
}),
typeParameters: [
compiler.typeParameterDeclaration({
name: 'T',
}),
],
});
return type;
};

Check warning on line 60 in packages/openapi-ts/src/plugins/msw/interfaces.ts

View check run for this annotation

Codecov / codecov/patch

packages/openapi-ts/src/plugins/msw/interfaces.ts#L18-L60

Added lines #L18 - L60 were not covered by tests

export const createPathParamsType = () => {
const type = compiler.typeAliasDeclaration({
name: pathParamsTypeName,
type: ts.factory.createConditionalTypeNode(
tReference,
ts.factory.createTypeLiteralNode([
ts.factory.createPropertySignature(
undefined,
ts.factory.createIdentifier('path'),
ts.factory.createToken(ts.SyntaxKind.QuestionToken),
ts.factory.createInferTypeNode(
compiler.typeParameterDeclaration({
name: 'U',
}),
),
),
]),
ts.factory.createConditionalTypeNode(
uReference,
objectReference,
compiler.typeReferenceNode({
typeArguments: [uReference],
typeName: transformObjectTypeName,
}),
neverReference,
),
neverReference,
),
typeParameters: [
compiler.typeParameterDeclaration({
name: 'T',
}),
],
});
return type;
};

Check warning on line 97 in packages/openapi-ts/src/plugins/msw/interfaces.ts

View check run for this annotation

Codecov / codecov/patch

packages/openapi-ts/src/plugins/msw/interfaces.ts#L63-L97

Added lines #L63 - L97 were not covered by tests

export const createResponseBodyTypeType = () => {
const type = compiler.typeAliasDeclaration({
name: responseBodyTypeTypeName,
type: ts.factory.createConditionalTypeNode(
compiler.typeReferenceNode({ typeName: 'void' }),
tReference,
compiler.typeUnionNode({
types: [
compiler.typeReferenceNode({
typeArguments: [
tReference,
compiler.keywordTypeNode({ keyword: 'void' }),
],
typeName: 'Exclude',
}),
undefinedReference,
],
}),
tReference,
),
typeParameters: [
compiler.typeParameterDeclaration({
name: 'T',
}),
],
});
return type;
};

Check warning on line 126 in packages/openapi-ts/src/plugins/msw/interfaces.ts

View check run for this annotation

Codecov / codecov/patch

packages/openapi-ts/src/plugins/msw/interfaces.ts#L100-L126

Added lines #L100 - L126 were not covered by tests
Loading
Loading