Skip to content

Commit

Permalink
Merge pull request #1529 from hey-api/feat/integer-int64
Browse files Browse the repository at this point in the history
fix: add support for long integers
  • Loading branch information
mrlubos authored Jan 6, 2025
2 parents 076bf07 + ccc0bbc commit 4ff09d2
Show file tree
Hide file tree
Showing 38 changed files with 602 additions and 138 deletions.
5 changes: 5 additions & 0 deletions .changeset/cool-days-scream.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@hey-api/openapi-ts': patch
---

fix: add support for long integers
2 changes: 1 addition & 1 deletion .changeset/nasty-comics-smoke.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
'@hey-api/openapi-ts': patch
---

fix: preserve leading indicators in enum keys
fix: preserve leading separators in enum keys
1 change: 1 addition & 0 deletions packages/openapi-ts/src/ir/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export const deduplicateSchema = <T extends IR.SchemaObject>({
// no `type` might still include `$ref` or `const`
!item.type ||
item.type === 'boolean' ||
item.type === 'integer' ||
item.type === 'null' ||
item.type === 'number' ||
item.type === 'string' ||
Expand Down
1 change: 1 addition & 0 deletions packages/openapi-ts/src/ir/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ interface IRSchemaObject
| 'array'
| 'boolean'
| 'enum'
| 'integer'
| 'never'
| 'null'
| 'number'
Expand Down
5 changes: 3 additions & 2 deletions packages/openapi-ts/src/openApi/2.0.x/parser/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,11 +163,12 @@ const parseBoolean = ({

const parseNumber = ({
irSchema = {},
schema,
}: SchemaContext & {
irSchema?: IR.SchemaObject;
schema: SchemaObject;
schema: SchemaWithRequired<SchemaObject, 'type'>;
}): IR.SchemaObject => {
irSchema.type = 'number';
irSchema.type = schema.type;

return irSchema;
};
Expand Down
5 changes: 3 additions & 2 deletions packages/openapi-ts/src/openApi/3.0.x/parser/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,11 +170,12 @@ const parseBoolean = ({

const parseNumber = ({
irSchema = {},
schema,
}: SchemaContext & {
irSchema?: IR.SchemaObject;
schema: SchemaObject;
schema: SchemaWithRequired<SchemaObject, 'type'>;
}): IR.SchemaObject => {
irSchema.type = 'number';
irSchema.type = schema.type;

return irSchema;
};
Expand Down
7 changes: 5 additions & 2 deletions packages/openapi-ts/src/openApi/3.1.x/parser/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,11 +223,14 @@ const parseNull = ({

const parseNumber = ({
irSchema = {},
schema,
}: SchemaContext & {
irSchema?: IR.SchemaObject;
schema: SchemaObject;
schema: Omit<SchemaObject, 'type'> & {
type: SchemaType<SchemaObject>;
};
}): IR.SchemaObject => {
irSchema.type = 'number';
irSchema.type = schema.type;

return irSchema;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export const defaultConfig: Plugin.Config<Config> = {
_handler: handler,
_handlerLegacy: handlerLegacy,
_tags: ['transformer'],
bigInt: true,
dates: true,
name: '@hey-api/transformers',
output: 'transformers',
Expand Down
100 changes: 75 additions & 25 deletions packages/openapi-ts/src/plugins/@hey-api/transformers/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,75 @@ interface OperationIRRef {
id: string;
}

const bigIntExpressions = ({
dataExpression,
}: {
dataExpression?: ts.Expression | string;
}): Array<ts.Expression> => {
const bigIntCallExpression =
dataExpression !== undefined
? compiler.callExpression({
functionName: 'BigInt',
parameters: [
compiler.callExpression({
functionName: compiler.propertyAccessExpression({
expression: dataExpression,
name: 'toString',
}),
}),
],
})
: undefined;

if (bigIntCallExpression) {
if (typeof dataExpression === 'string') {
return [bigIntCallExpression];
}

if (dataExpression) {
return [
compiler.assignment({
left: dataExpression,
right: bigIntCallExpression,
}),
];
}
}

return [];
};

const dateExpressions = ({
dataExpression,
}: {
dataExpression?: ts.Expression | string;
}): Array<ts.Expression> => {
const identifierDate = compiler.identifier({ text: 'Date' });

if (typeof dataExpression === 'string') {
return [
compiler.newExpression({
argumentsArray: [compiler.identifier({ text: dataExpression })],
expression: identifierDate,
}),
];
}

if (dataExpression) {
return [
compiler.assignment({
left: dataExpression,
right: compiler.newExpression({
argumentsArray: [dataExpression],
expression: identifierDate,
}),
}),
];
}

return [];
};

export const operationTransformerIrRef = ({
id,
type,
Expand Down Expand Up @@ -147,7 +216,7 @@ const processSchemaType = ({
parameters: [
{
name: dataVariableName,
// TODO: parser - add types, generate types without transformed dates
// TODO: parser - add types, generate types without transforms
type: compiler.keywordTypeNode({ keyword: 'any' }),
},
],
Expand Down Expand Up @@ -293,30 +362,11 @@ const processSchemaType = ({
schema.type === 'string' &&
(schema.format === 'date' || schema.format === 'date-time')
) {
const identifierDate = compiler.identifier({ text: 'Date' });

if (typeof dataExpression === 'string') {
return [
compiler.newExpression({
argumentsArray: [compiler.identifier({ text: dataExpression })],
expression: identifierDate,
}),
];
}

if (dataExpression) {
return [
compiler.assignment({
left: dataExpression,
right: compiler.newExpression({
argumentsArray: [dataExpression],
expression: identifierDate,
}),
}),
];
}
return dateExpressions({ dataExpression });
}

return [];
if (plugin.bigInt && schema.type === 'integer' && schema.format === 'int64') {
return bigIntExpressions({ dataExpression });
}

if (schema.items) {
Expand Down Expand Up @@ -447,7 +497,7 @@ export const handler: Plugin.Handler<Config> = ({ context, plugin }) => {
parameters: [
{
name: dataVariableName,
// TODO: parser - add types, generate types without transformed dates
// TODO: parser - add types, generate types without transforms
type: compiler.keywordTypeNode({ keyword: 'any' }),
},
],
Expand Down
10 changes: 10 additions & 0 deletions packages/openapi-ts/src/plugins/@hey-api/transformers/types.d.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
import type { Plugin } from '../../types';

export interface Config extends Plugin.Name<'@hey-api/transformers'> {
/**
* **This feature works only with the [experimental parser](https://heyapi.dev/openapi-ts/configuration#parser)**
*
* Convert long integers into BigInt values?
*
* @default true
*/
bigInt?: boolean;
/**
* Convert date strings into Date objects?
*
* @default true
*/
dates?: boolean;
/**
* Name of the generated file.
*
* @default 'transformers'
*/
output?: string;
Expand Down
23 changes: 16 additions & 7 deletions packages/openapi-ts/src/plugins/@hey-api/typescript/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -402,18 +402,26 @@ const enumTypeToIdentifier = ({
};

const numberTypeToIdentifier = ({
context,
schema,
}: {
context: IR.Context;
namespace: Array<ts.Statement>;
schema: SchemaWithType<'number'>;
schema: SchemaWithType<'integer' | 'number'>;
}) => {
if (schema.const !== undefined) {
return compiler.literalTypeNode({
literal: compiler.ots.number(schema.const as number),
});
}

if (schema.type === 'integer' && schema.format === 'int64') {
// TODO: parser - add ability to skip type transformers
if (context.config.plugins['@hey-api/transformers']?.bigInt) {
return compiler.typeReferenceNode({ typeName: 'BigInt' });
}
}

return compiler.keywordTypeNode({
keyword: 'number',
});
Expand Down Expand Up @@ -605,6 +613,13 @@ const schemaTypeToIdentifier = ({
plugin,
schema: schema as SchemaWithType<'enum'>,
});
case 'integer':
case 'number':
return numberTypeToIdentifier({
context,
namespace,
schema: schema as SchemaWithType<'integer' | 'number'>,
});
case 'never':
return compiler.keywordTypeNode({
keyword: 'never',
Expand All @@ -613,12 +628,6 @@ const schemaTypeToIdentifier = ({
return compiler.literalTypeNode({
literal: compiler.null(),
});
case 'number':
return numberTypeToIdentifier({
context,
namespace,
schema: schema as SchemaWithType<'number'>,
});
case 'object':
return objectTypeToIdentifier({
context,
Expand Down
28 changes: 21 additions & 7 deletions packages/openapi-ts/src/plugins/zod/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,15 +241,28 @@ const numberTypeToZodSchema = ({
schema,
}: {
context: IR.Context;
schema: SchemaWithType<'number'>;
schema: SchemaWithType<'integer' | 'number'>;
}) => {
const isBigInt = schema.type === 'integer' && schema.format === 'int64';

let numberExpression = compiler.callExpression({
functionName: compiler.propertyAccessExpression({
expression: zIdentifier,
name: compiler.identifier({ text: schema.type }),
name: isBigInt
? compiler.identifier({ text: 'bigint' })
: compiler.identifier({ text: 'number' }),
}),
});

if (!isBigInt && schema.type === 'integer') {
numberExpression = compiler.callExpression({
functionName: compiler.propertyAccessExpression({
expression: numberExpression,
name: compiler.identifier({ text: 'int' }),
}),
});
}

if (schema.const !== undefined) {
// TODO: parser - add constant
// return compiler.literalTypeNode({
Expand Down Expand Up @@ -584,6 +597,12 @@ const schemaTypeToZodSchema = ({
context,
schema: schema as SchemaWithType<'enum'>,
});
case 'integer':
case 'number':
return numberTypeToZodSchema({
context,
schema: schema as SchemaWithType<'integer' | 'number'>,
});
case 'never':
return neverTypeToZodSchema({
context,
Expand All @@ -594,11 +613,6 @@ const schemaTypeToZodSchema = ({
context,
schema: schema as SchemaWithType<'null'>,
});
case 'number':
return numberTypeToZodSchema({
context,
schema: schema as SchemaWithType<'number'>,
});
case 'object':
return objectTypeToZodSchema({
context,
Expand Down
10 changes: 5 additions & 5 deletions packages/openapi-ts/test/2.0.x.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ import { getFilePaths } from './utils';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const VERSION = '2.0.x';
const version = '2.0.x';

const outputDir = path.join(__dirname, 'generated', VERSION);
const outputDir = path.join(__dirname, 'generated', version);

describe(`OpenAPI ${VERSION}`, () => {
describe(`OpenAPI ${version}`, () => {
const createConfig = (userConfig: UserConfig): UserConfig => ({
client: '@hey-api/client-fetch',
experimentalParser: true,
Expand All @@ -24,7 +24,7 @@ describe(`OpenAPI ${VERSION}`, () => {
input: path.join(
__dirname,
'spec',
VERSION,
version,
typeof userConfig.input === 'string' ? userConfig.input : '',
),
output: path.join(
Expand Down Expand Up @@ -273,7 +273,7 @@ describe(`OpenAPI ${VERSION}`, () => {
path.join(
__dirname,
'__snapshots__',
VERSION,
version,
filePath.slice(outputDir.length + 1),
),
);
Expand Down
Loading

0 comments on commit 4ff09d2

Please sign in to comment.