Skip to content

Commit aaf3034

Browse files
committed
wip
1 parent cb5c858 commit aaf3034

File tree

5 files changed

+88
-3
lines changed

5 files changed

+88
-3
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
"repository": "unjs/fetchdts",
1414
"sideEffects": false,
1515
"exports": {
16-
".": "./dist/index.mjs"
16+
".": "./dist/index.mjs",
17+
"./runtime": "./dist/runtime.mjs"
1718
},
1819
"main": "./dist/index.mjs",
1920
"module": "./dist/index.mjs",

src/runtime.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import type { RouteTree } from './tree'
2+
import type * as Symbols from './tree'
3+
4+
import { DynamicParam, Endpoint, WildcardParam } from './tree'
5+
6+
export { DynamicParam, Endpoint, WildcardParam } from './tree'
7+
8+
interface RenderedFetchSchema {
9+
imports: string
10+
declaration: string
11+
}
12+
13+
interface GenerateFetchSchemaOptions<S> {
14+
name: string
15+
schema: S
16+
}
17+
18+
export function serializeFetchSchema<S extends RouteTree>(options: GenerateFetchSchemaOptions<S>): RenderedFetchSchema {
19+
const usedTypes = new Set<keyof typeof Symbols>()
20+
21+
const contents = _serialize(options.schema, usedTypes)
22+
23+
return {
24+
imports: `import type { ${[...usedTypes].join(', ')} } from 'fetchdts'`,
25+
declaration: `
26+
export interface ${options.name} {
27+
${contents}
28+
}`,
29+
}
30+
}
31+
32+
function _serialize(schema: RouteTree, usedTypes: Set<keyof typeof Symbols>, indent = 2) {
33+
let code = ''
34+
for (const key in schema) {
35+
if (typeof key === 'string') {
36+
const lines = [
37+
`${JSON.stringify(key)}: {`,
38+
_serialize(schema[key], usedTypes, indent + 2),
39+
'}',
40+
'',
41+
]
42+
code += lines.map(line => ' '.repeat(indent) + line).join('\n')
43+
}
44+
}
45+
return code
46+
}

src/tree.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@ export interface RouteTree {
99
[key: string | symbol]: Partial<Endpoints> | RouteTree
1010
}
1111

12-
export type Endpoints = Record<HTTPMethod, {
12+
export type Endpoints = Record<HTTPMethod, Partial<EndpointMeta>>
13+
14+
export interface EndpointMeta {
1315
query: never | Record<string, unknown>
1416
headers: Record<string, unknown>
1517
body: never | Record<string, unknown>
1618
response: unknown
17-
}>
19+
}

test/runtime.spec.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { describe, expect, it } from 'vitest'
2+
import { Endpoint, serializeFetchSchema } from '../src/runtime'
3+
4+
describe('runtime schema generation', () => {
5+
it('should generate types for fetch schema', async () => {
6+
const schema = serializeFetchSchema({
7+
name: 'MySchema',
8+
schema: {
9+
'/methods': {
10+
'/get': {
11+
[Endpoint]: { GET: { response: { method: 'GET' } } },
12+
},
13+
'/post': {
14+
[Endpoint]: { POST: { response: { method: 'POST' } } },
15+
},
16+
},
17+
},
18+
})
19+
20+
await expect(`${schema.imports}\n${schema.declaration}`).toMatchFileSnapshot('snapshots/schema.d.ts')
21+
})
22+
})

test/snapshots/schema.d.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import type { } from 'fetchdts'
2+
3+
export interface MySchema {
4+
"/methods": {
5+
"/get": {
6+
7+
}
8+
"/post": {
9+
10+
}
11+
12+
}
13+
14+
}

0 commit comments

Comments
 (0)