Skip to content

Commit

Permalink
Merge pull request #1615 from hey-api/chore/compiler-updates
Browse files Browse the repository at this point in the history
  • Loading branch information
mrlubos authored Jan 23, 2025
2 parents 5cd4bb2 + 8040010 commit 3d17490
Show file tree
Hide file tree
Showing 16 changed files with 136 additions and 55 deletions.
3 changes: 3 additions & 0 deletions packages/openapi-ts/src/compiler/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export const compiler = {
isTsNode: utils.isTsNode,
keywordTypeNode: types.createKeywordTypeNode,
literalTypeNode: types.createLiteralTypeNode,
mappedTypeNode: types.createMappedTypeNode,
methodDeclaration: classes.createMethodDeclaration,
namedImportDeclarations: module.createNamedImportDeclarations,
namespaceDeclaration: types.createNamespaceDeclaration,
Expand Down Expand Up @@ -68,6 +69,8 @@ export const compiler = {
typeIntersectionNode: typedef.createTypeIntersectionNode,
typeNode: types.createTypeNode,
typeOfExpression: types.createTypeOfExpression,
typeOperatorNode: types.createTypeOperatorNode,
typeParameterDeclaration: types.createTypeParameterDeclaration,
typeParenthesizedNode: types.createTypeParenthesizedNode,
typeRecordNode: typedef.createTypeRecordNode,
typeReferenceNode: types.createTypeReferenceNode,
Expand Down
84 changes: 72 additions & 12 deletions packages/openapi-ts/src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -287,24 +287,84 @@ export const createKeywordTypeNode = ({

export const toTypeParameters = (types: FunctionTypeParameter[]) =>
types.map((type) =>
ts.factory.createTypeParameterDeclaration(
undefined,
type.name,
createTypeParameterDeclaration({
// TODO: support other extends values
type.extends
constraint: type.extends
? typeof type.extends === 'string'
? createKeywordTypeNode({ keyword: 'boolean' })
: type.extends
: undefined,
// TODO: support other default types
type.default !== undefined
? isTsNode(type.default)
? (type.default as unknown as ts.TypeNode)
: ts.factory.createLiteralTypeNode(
type.default ? ts.factory.createTrue() : ts.factory.createFalse(),
)
: undefined,
),
defaultType:
type.default !== undefined
? isTsNode(type.default)
? (type.default as unknown as ts.TypeNode)
: ts.factory.createLiteralTypeNode(
type.default
? ts.factory.createTrue()
: ts.factory.createFalse(),
)
: undefined,
name: type.name,
}),
);

export const createTypeOperatorNode = ({
operator,
type,
}: {
operator: 'keyof' | 'readonly' | 'unique';
type: ts.TypeNode;
}) => {
const operatorKeyword =
operator === 'keyof'
? ts.SyntaxKind.KeyOfKeyword
: operator === 'readonly'
? ts.SyntaxKind.ReadonlyKeyword
: ts.SyntaxKind.UniqueKeyword;
return ts.factory.createTypeOperatorNode(operatorKeyword, type);
};

export const createTypeParameterDeclaration = ({
constraint,
defaultType,
modifiers,
name,
}: {
constraint?: ts.TypeNode;
defaultType?: ts.TypeNode;
modifiers?: Array<ts.Modifier>;
name: string | ts.Identifier;
}) =>
ts.factory.createTypeParameterDeclaration(
modifiers,
name,
constraint,
defaultType,
);

export const createMappedTypeNode = ({
members,
nameType,
questionToken,
readonlyToken,
type,
typeParameter,
}: {
members?: ts.NodeArray<ts.TypeElement>;
nameType?: ts.TypeNode;
questionToken?: ts.QuestionToken | ts.PlusToken | ts.MinusToken;
readonlyToken?: ts.ReadonlyKeyword | ts.PlusToken | ts.MinusToken;
type?: ts.TypeNode;
typeParameter: ts.TypeParameterDeclaration;
}) =>
ts.factory.createMappedTypeNode(
readonlyToken,
typeParameter,
nameType,
questionToken,
type,
members,
);

export const createLiteralTypeNode = ({
Expand Down
22 changes: 8 additions & 14 deletions packages/openapi-ts/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,7 @@ import type {
PluginNames,
} from './plugins/types';
import type { Client } from './types/client';
import type {
ClientConfig,
Config,
Formatters,
Linters,
UserConfig,
} from './types/config';
import type { Config, Formatters, Linters, UserConfig } from './types/config';
import { CLIENTS } from './types/config';
import {
isLegacyClient,
Expand Down Expand Up @@ -103,7 +97,7 @@ const processOutput = ({ config }: { config: Config }) => {
}
};

const getClient = (userConfig: ClientConfig): Config['client'] => {
const getClient = (userConfig: UserConfig): Config['client'] => {
let client: Config['client'] = {
bundle: false,
name: '' as Config['client']['name'],
Expand All @@ -119,7 +113,7 @@ const getClient = (userConfig: ClientConfig): Config['client'] => {
return client;
};

const getInput = (userConfig: ClientConfig): Config['input'] => {
const getInput = (userConfig: UserConfig): Config['input'] => {
let input: Config['input'] = {
path: '',
};
Expand All @@ -139,7 +133,7 @@ const getInput = (userConfig: ClientConfig): Config['input'] => {
return input;
};

const getLogs = (userConfig: ClientConfig): Config['logs'] => {
const getLogs = (userConfig: UserConfig): Config['logs'] => {
let logs: Config['logs'] = {
level: 'info',
path: process.cwd(),
Expand All @@ -155,7 +149,7 @@ const getLogs = (userConfig: ClientConfig): Config['logs'] => {
return logs;
};

const getOutput = (userConfig: ClientConfig): Config['output'] => {
const getOutput = (userConfig: UserConfig): Config['output'] => {
let output: Config['output'] = {
clean: true,
format: false,
Expand Down Expand Up @@ -271,7 +265,7 @@ const getPluginsConfig = ({
};

const getPlugins = (
userConfig: ClientConfig,
userConfig: UserConfig,
): Pick<Config, 'plugins' | 'pluginOrder'> => {
const userPluginsConfig: Config['plugins'] = {};

Expand Down Expand Up @@ -438,7 +432,7 @@ const getSpec = async ({
};

const getWatch = (
userConfig: Pick<ClientConfig, 'watch'> & Pick<Config, 'input'>,
userConfig: Pick<UserConfig, 'watch'> & Pick<Config, 'input'>,
): Config['watch'] => {
let watch: Config['watch'] = {
enabled: false,
Expand Down Expand Up @@ -476,7 +470,7 @@ const initConfigs = async (userConfig: UserConfig): Promise<Config[]> => {
name: 'openapi-ts',
});

const userConfigs: ClientConfig[] = Array.isArray(userConfig)
const userConfigs: UserConfig[] = Array.isArray(userConfig)
? userConfig
: Array.isArray(configFromFile)
? configFromFile.map((config) => ({
Expand Down
2 changes: 2 additions & 0 deletions packages/openapi-ts/src/plugins/@hey-api/schemas/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,15 @@ export interface Config extends Plugin.Name<'@hey-api/schemas'> {
) => string;
/**
* Name of the generated file.
*
* @default 'schemas'
*/
output?: string;
/**
* Choose schema type to generate. Select 'form' if you don't want
* descriptions to reduce bundle size and you plan to use schemas
* for form validation
*
* @default 'json'
*/
type?: 'form' | 'json';
Expand Down
4 changes: 2 additions & 2 deletions packages/openapi-ts/src/plugins/@hey-api/sdk/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,11 @@ export interface Config extends Plugin.Name<'@hey-api/sdk'> {
*/
output?: string;
/**
* @deprecated
*
* Define shape of returned value from service calls
*
* @default 'body'
*
* @deprecated
*/
response?: 'body' | 'response';
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { irRef } from '../../../utils/ref';
import { stringCase } from '../../../utils/stringCase';
import { operationIrRef } from '../../shared/utils/ref';
import type { Plugin } from '../../types';
import { typesId } from '../typescript/ref';
import type { Config } from './types';

interface OperationIRRef {
Expand Down Expand Up @@ -460,7 +461,7 @@ export const handler: Plugin.Handler<Config> = ({ context, plugin }) => {
return;
}

const identifierResponse = context.file({ id: 'types' })!.identifier({
const identifierResponse = context.file({ id: typesId })!.identifier({
$ref: operationIrRef({ id: operation.id, type: 'response' }),
namespace: 'type',
});
Expand All @@ -486,7 +487,7 @@ export const handler: Plugin.Handler<Config> = ({ context, plugin }) => {
if (nodes.length) {
file.import({
asType: true,
module: file.relativePathToFile({ context, id: 'types' }),
module: file.relativePathToFile({ context, id: typesId }),
name: identifierResponse.name,
});
const responseTransformerNode = compiler.constVariable({
Expand Down
12 changes: 6 additions & 6 deletions packages/openapi-ts/src/plugins/@hey-api/typescript/ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ export const importIdentifierData = ({
file: TypeScriptFile;
operation: IR.OperationObject;
}): Identifier => {
const identifierData = context.file({ id: 'types' })!.identifier({
const identifierData = context.file({ id: typesId })!.identifier({
$ref: operationIrRef({ id: operation.id, type: 'data' }),
namespace: 'type',
});
return refIdentifier(identifierData, (identifier) => {
if (identifier.name) {
file.import({
asType: true,
module: file.relativePathToFile({ context, id: 'types' }),
module: file.relativePathToFile({ context, id: typesId }),
name: identifier.name,
});
}
Expand All @@ -50,15 +50,15 @@ export const importIdentifierError = ({
file: TypeScriptFile;
operation: IR.OperationObject;
}): Identifier => {
const identifierError = context.file({ id: 'types' })!.identifier({
const identifierError = context.file({ id: typesId })!.identifier({
$ref: operationIrRef({ id: operation.id, type: 'error' }),
namespace: 'type',
});
return refIdentifier(identifierError, (identifier) => {
if (identifier.name) {
file.import({
asType: true,
module: file.relativePathToFile({ context, id: 'types' }),
module: file.relativePathToFile({ context, id: typesId }),
name: identifier.name,
});
}
Expand All @@ -74,15 +74,15 @@ export const importIdentifierResponse = ({
file: TypeScriptFile;
operation: IR.OperationObject;
}): Identifier => {
const identifierResponse = context.file({ id: 'types' })!.identifier({
const identifierResponse = context.file({ id: typesId })!.identifier({
$ref: operationIrRef({ id: operation.id, type: 'response' }),
namespace: 'type',
});
return refIdentifier(identifierResponse, (identifier) => {
if (identifier.name) {
file.import({
asType: true,
module: file.relativePathToFile({ context, id: 'types' }),
module: file.relativePathToFile({ context, id: typesId }),
name: identifier.name,
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,26 @@ export interface Config
extends Plugin.Name<'@tanstack/angular-query-experimental'> {
/**
* Generate {@link https://tanstack.com/query/v5/docs/framework/angular/reference/infiniteQueryOptions `infiniteQueryOptions()`} helpers? These will be generated from GET and POST requests where a pagination parameter is detected.
*
* @default true
*/
infiniteQueryOptions?: boolean;
/**
* Generate {@link https://tanstack.com/query/v5/docs/framework/angular/reference/useMutation `useMutation()`} helpers? These will be generated from DELETE, PATCH, POST, and PUT requests.
*
* @default true
*/
mutationOptions?: boolean;
/**
* Name of the generated file.
*
* @default '@tanstack/angular-query-experimental'
*/
output?: string;
/**
* Generate {@link https://tanstack.com/query/v5/docs/framework/angular/reference/queryOptions `queryOptions()`} helpers?
* These will be generated from all requests.
*
* @default true
*/
queryOptions?: boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,26 @@ import type { Plugin } from '../../types';
export interface Config extends Plugin.Name<'@tanstack/react-query'> {
/**
* Generate {@link https://tanstack.com/query/v5/docs/framework/react/reference/infiniteQueryOptions `infiniteQueryOptions()`} helpers? These will be generated from GET and POST requests where a pagination parameter is detected.
*
* @default true
*/
infiniteQueryOptions?: boolean;
/**
* Generate {@link https://tanstack.com/query/v5/docs/framework/react/reference/useMutation `useMutation()`} helpers? These will be generated from DELETE, PATCH, POST, and PUT requests.
*
* @default true
*/
mutationOptions?: boolean;
/**
* Name of the generated file.
*
* @default '@tanstack/react-query'
*/
output?: string;
/**
* Generate {@link https://tanstack.com/query/v5/docs/framework/react/reference/queryOptions `queryOptions()`} helpers?
* These will be generated from all requests.
*
* @default true
*/
queryOptions?: boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,26 @@ import type { Plugin } from '../../types';
export interface Config extends Plugin.Name<'@tanstack/solid-query'> {
/**
* Generate `createInfiniteQuery()` helpers? These will be generated from GET and POST requests where a pagination parameter is detected.
*
* @default true
*/
infiniteQueryOptions?: boolean;
/**
* Generate `createMutation()` helpers? These will be generated from DELETE, PATCH, POST, and PUT requests.
*
* @default true
*/
mutationOptions?: boolean;
/**
* Name of the generated file.
*
* @default '@tanstack/solid-query'
*/
output?: string;
/**
* Generate {@link https://tanstack.com/query/v5/docs/framework/solid/reference/createQuery `createQuery()`} helpers?
* These will be generated from all requests.
*
* @default true
*/
queryOptions?: boolean;
Expand Down
Loading

0 comments on commit 3d17490

Please sign in to comment.