Skip to content

Commit

Permalink
refactor: generate cleaner type
Browse files Browse the repository at this point in the history
  • Loading branch information
Julien-R44 committed May 1, 2024
1 parent 8c9fcc6 commit 9b09b93
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 21 deletions.
6 changes: 4 additions & 2 deletions packages/core/commands/generate.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { Project, QuoteKind } from 'ts-morph'
import { BaseCommand } from '@adonisjs/core/ace'
import { BaseCommand, flags } from '@adonisjs/core/ace'
import type { CommandOptions } from '@adonisjs/core/types/ace'

import { ApiTypesGenerator } from '../src/codegen/api_types_generator.js'

export default class CodegenTypes extends BaseCommand {
static override commandName = 'tuyau:generate'
static override description = 'Tuyau generator command'

static override options: CommandOptions = { startApp: true }

@flags.boolean({ description: 'Verbose logs', default: false, alias: 'v' })
declare verbose: boolean

/**
* Get routes from the router instance
*/
Expand Down
8 changes: 3 additions & 5 deletions packages/core/src/codegen/api_types_generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,7 @@ export class ApiTypesGenerator {

file.insertText(0, (writer) => {
writer
.writeLine(
`import type { MakeOptional, Serialize, Simplify, ConvertReturnTypeToRecordStatusResponse } from '@tuyau/utils/types'`,
)
.writeLine(`import type { MakeTuyauRequest, MakeTuyauResponse } from '@tuyau/utils/types'`)
.writeLine(`import type { InferInput } from '@vinejs/vine/types'`)
.newLine()
.writeLine(`export interface AdonisApi {`)
Expand Down Expand Up @@ -242,8 +240,8 @@ export class ApiTypesGenerator {
currentLevel['$url'] = {}
for (const method of methods) {
currentLevel[method] = {
request: schemaImport ? `MakeOptional<${schemaImport}>` : 'unknown',
response: `Simplify<Serialize<ConvertReturnTypeToRecordStatusResponse<Awaited<ReturnType<typeof import('${relativePath}').default['prototype']['${routeHandler.method}']>>>>>`,
request: schemaImport ? `MakeTuyauRequest<${schemaImport}>` : 'unknown',
response: `MakeTuyauResponse<import('${relativePath}').default['${routeHandler.method}']>`,
}
}
}
Expand Down
10 changes: 5 additions & 5 deletions packages/core/tests/api_types_generator.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ test.group('Api Types Generator', () => {

const file = await fs.contents('./.adonisjs/types/api.d.ts')
assert.snapshot(file).matchInline(`
"import type { MakeOptional, Serialize, Simplify, ConvertReturnTypeToRecordStatusResponse } from '@tuyau/utils/types'
"import type { MakeTuyauRequest, MakeTuyauResponse } from '@tuyau/utils/types'
import type { InferInput } from '@vinejs/vine/types'
export interface AdonisApi {
Expand All @@ -63,7 +63,7 @@ test.group('Api Types Generator', () => {
};
'$get': {
'request': unknown;
'response': Simplify<Serialize<ConvertReturnTypeToRecordStatusResponse<Awaited<ReturnType<typeof import('../../app/controllers/users_controller.ts').default['prototype']['index']>>>>>;
'response': MakeTuyauResponse<import('../../app/controllers/users_controller.ts').default['index']>;
};
};
}
Expand Down Expand Up @@ -117,16 +117,16 @@ test.group('Api Types Generator', () => {

const file = await fs.contents('./.adonisjs/types/api.d.ts')
assert.snapshot(file).matchInline(`
"import type { MakeOptional, Serialize, Simplify, ConvertReturnTypeToRecordStatusResponse } from '@tuyau/utils/types'
"import type { MakeTuyauRequest, MakeTuyauResponse } from '@tuyau/utils/types'
import type { InferInput } from '@vinejs/vine/types'
export interface AdonisApi {
'users': {
'$url': {
};
'$get': {
'request': MakeOptional<InferInput<typeof import('../../app/controllers/validator.ts')['getUsersValidator']>>;
'response': Simplify<Serialize<ConvertReturnTypeToRecordStatusResponse<Awaited<ReturnType<typeof import('../../app/controllers/users_controller.ts').default['prototype']['index']>>>>>;
'request': MakeTuyauRequest<InferInput<typeof import('../../app/controllers/validator.ts')['getUsersValidator']>>;
'response': MakeTuyauResponse<import('../../app/controllers/users_controller.ts').default['index']>;
};
};
}
Expand Down
12 changes: 12 additions & 0 deletions packages/utils/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,15 @@ type UndefinedProps<T extends object> = {
* type Bar = MakeOptional<Foo> // { a: string, b?: number, c: boolean }
*/
export type MakeOptional<T extends object> = UndefinedProps<T> & Omit<T, keyof UndefinedProps<T>>

/**
* Shortcut for computing the Tuyau response type
*/
export type MakeTuyauResponse<T extends (...args: any) => any> = Simplify<
Serialize<ConvertReturnTypeToRecordStatusResponse<Awaited<ReturnType<T>>>>
>

/**
* Shortcut for computing the Tuyau request type
*/
export type MakeTuyauRequest<T extends object> = MakeOptional<T>
32 changes: 23 additions & 9 deletions playground/.adonisjs/types/api.d.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,37 @@
import type { MakeOptional, Serialize, Simplify, ConvertReturnTypeToRecordStatusResponse } from '@tuyau/utils/types'
import type { MakeTuyauRequest, MakeTuyauResponse } from '@tuyau/utils/types'
import type { InferInput } from '@vinejs/vine/types'

export interface AdonisApi {
'users': {
'get': {
'request': MakeOptional<InferInput<typeof import('../../app/validators/main.ts')['getUsersValidator']>>;
'response': Simplify<Serialize<ConvertReturnTypeToRecordStatusResponse<Awaited<ReturnType<typeof import('../../app/controllers/users_controller.ts').default['prototype']['index']>>>>>;
'$url': {
};
'$get': {
'request': MakeTuyauRequest<InferInput<typeof import('../../app/validators/main.ts')['getUsersValidator']>>;
'response': MakeTuyauResponse<import('../../app/controllers/users_controller.ts').default['index']>;
};
'$head': {
'request': MakeTuyauRequest<InferInput<typeof import('../../app/validators/main.ts')['getUsersValidator']>>;
'response': MakeTuyauResponse<import('../../app/controllers/users_controller.ts').default['index']>;
};
};
'simple-text': {
'get': {
'$url': {
};
'$get': {
'request': unknown;
'response': Simplify<Serialize<ConvertReturnTypeToRecordStatusResponse<Awaited<ReturnType<typeof import('../../app/controllers/users_controller.ts').default['prototype']['simpleText']>>>>>;
'response': MakeTuyauResponse<import('../../app/controllers/users_controller.ts').default['simpleText']>;
};
'$head': {
'request': unknown;
'response': MakeTuyauResponse<import('../../app/controllers/users_controller.ts').default['simpleText']>;
};
};
'file-upload': {
'post': {
'request': MakeOptional<InferInput<typeof import('../../app/validators/main.ts')['uploadFileValidator']>>;
'response': Simplify<Serialize<ConvertReturnTypeToRecordStatusResponse<Awaited<ReturnType<typeof import('../../app/controllers/users_controller.ts').default['prototype']['fileUpload']>>>>>;
'$url': {
};
'$post': {
'request': MakeTuyauRequest<InferInput<typeof import('../../app/validators/main.ts')['uploadFileValidator']>>;
'response': MakeTuyauResponse<import('../../app/controllers/users_controller.ts').default['fileUpload']>;
};
};
}

0 comments on commit 9b09b93

Please sign in to comment.