Skip to content

Commit 1d710a2

Browse files
committed
Add basic generator script
1 parent a83b1c4 commit 1d710a2

File tree

3 files changed

+308
-0
lines changed

3 files changed

+308
-0
lines changed

generate-routes.ts

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
import { camelCase, pascalCase, snakeCase } from 'change-case'
2+
import { format } from 'prettier'
3+
4+
interface Route {
5+
namespace: string
6+
endpoints: Endpoint[]
7+
}
8+
9+
interface Endpoint {
10+
name: string
11+
path: string
12+
namespace: string
13+
resource: string
14+
method: 'GET' | 'POST'
15+
requestFormat: 'params' | 'body'
16+
}
17+
18+
const renderRoute = (route: Route): string => `
19+
${renderImports()}
20+
21+
${renderClass(route)}
22+
23+
${renderExports(route)}
24+
`
25+
26+
const renderImports = (): string =>
27+
`
28+
import type { RouteRequestParams, RouteResponse } from '@seamapi/types/connect'
29+
import { Axios } from 'axios'
30+
import type { SetNonNullable } from 'type-fest'
31+
32+
import { createAxiosClient } from 'lib/seam/connect/axios.js'
33+
import type { SeamHttpOptions } from 'lib/seam/connect/client-options.js'
34+
import { parseOptions } from 'lib/seam/connect/parse-options.js'
35+
`
36+
37+
const renderClass = ({ endpoints }: Route): string =>
38+
`
39+
export class WorkspacesHttp {
40+
client: Axios
41+
42+
constructor(apiKeyOrOptionsOrClient: Axios | string | SeamHttpOptions) {
43+
if (apiKeyOrOptionsOrClient instanceof Axios) {
44+
this.client = apiKeyOrOptionsOrClient
45+
return
46+
}
47+
48+
const options = parseOptions(apiKeyOrOptionsOrClient)
49+
this.client = createAxiosClient(options)
50+
}
51+
52+
${endpoints.map(renderClassMethod).join('\n')}
53+
}
54+
`
55+
56+
const renderClassMethod = ({
57+
name,
58+
requestFormat,
59+
method,
60+
namespace,
61+
resource,
62+
path,
63+
}: Endpoint): string => `
64+
async ${camelCase(name)}(
65+
${requestFormat}: ${renderRequestType({
66+
name,
67+
namespace,
68+
requestFormat,
69+
})} = {},
70+
): Promise<${renderResponseType({ name, namespace })}['${resource}']> {
71+
const { data } = await this.client.request<${renderResponseType({
72+
name,
73+
namespace,
74+
})}>({
75+
url: '${path}',
76+
method: '${snakeCase(method)}', ${
77+
requestFormat === 'params' ? 'params,' : ''
78+
} ${requestFormat === 'body' ? 'data: body,' : ''}
79+
})
80+
return data.${resource}
81+
}
82+
`
83+
84+
const renderExports = (route: Route): string =>
85+
route.endpoints.map(renderEndpointExports).join('\n')
86+
87+
const renderEndpointExports = ({
88+
name,
89+
path,
90+
namespace,
91+
requestFormat,
92+
}: Endpoint): string => `
93+
export type ${renderRequestType({
94+
name,
95+
namespace,
96+
requestFormat,
97+
})} = SetNonNullable<
98+
Required<RouteRequest${requestFormat}<'${path}'>>
99+
>
100+
101+
export type ${renderResponseType({ name, namespace })}= SetNonNullable<
102+
Required<RouteResponse<'${path}'>>
103+
>
104+
`
105+
106+
const getRequestFormat = (
107+
method: Endpoint['method'],
108+
): Endpoint['requestFormat'] =>
109+
['GET', 'DELETE'].includes(method) ? 'params' : 'body'
110+
111+
const renderRequestType = ({
112+
name,
113+
namespace,
114+
requestFormat,
115+
}: Pick<Endpoint, 'name' | 'namespace' | 'requestFormat'>): string =>
116+
[pascalCase(namespace), pascalCase(name), pascalCase(requestFormat)].join('')
117+
118+
const renderResponseType = ({
119+
name,
120+
namespace,
121+
}: Pick<Endpoint, 'name' | 'namespace'>): string =>
122+
[pascalCase(namespace), pascalCase(name), 'Response'].join('')
123+
124+
const exampleRoute: Route = {
125+
namespace: 'workspaces',
126+
endpoints: [
127+
{
128+
name: 'get',
129+
namespace: 'workspaces',
130+
path: '/workspaces/get',
131+
method: 'GET',
132+
resource: 'workspace',
133+
requestFormat: getRequestFormat('GET'),
134+
},
135+
{
136+
name: 'create',
137+
namespace: 'workspaces',
138+
path: '/workspaces/create',
139+
method: 'POST',
140+
resource: 'workspace',
141+
requestFormat: getRequestFormat('POST'),
142+
},
143+
],
144+
}
145+
146+
console.log(await format(renderRoute(exampleRoute), { parser: 'typescript' }))

0 commit comments

Comments
 (0)