@devup-api/generator 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +7 -3
- package/src/__tests__/convert-case.test.ts +0 -125
- package/src/__tests__/create-url-map.test.ts +0 -318
- package/src/__tests__/index.test.ts +0 -9
- package/src/__tests__/wrap-interface-key-guard.test.ts +0 -42
- package/src/convert-case.ts +0 -22
- package/src/create-url-map.ts +0 -43
- package/src/generate-interface.ts +0 -594
- package/src/generate-schema.ts +0 -482
- package/src/index.ts +0 -2
- package/src/wrap-interface-key-guard.ts +0 -6
- package/tsconfig.json +0 -34
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devup-api/generator",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"license": "Apache-2.0",
|
|
4
5
|
"type": "module",
|
|
5
6
|
"exports": {
|
|
6
7
|
".": {
|
|
@@ -9,6 +10,9 @@
|
|
|
9
10
|
"types": "./dist/index.d.ts"
|
|
10
11
|
}
|
|
11
12
|
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist"
|
|
15
|
+
],
|
|
12
16
|
"scripts": {
|
|
13
17
|
"build": "tsc && bun build --target node --outfile=dist/index.js src/index.ts --production --packages=external && bun build --target node --outfile=dist/index.cjs --format=cjs src/index.ts --production --packages=external"
|
|
14
18
|
},
|
|
@@ -16,8 +20,8 @@
|
|
|
16
20
|
"access": "public"
|
|
17
21
|
},
|
|
18
22
|
"dependencies": {
|
|
19
|
-
"@devup-api/core": "0.1.
|
|
20
|
-
"@devup-api/utils": "0.1.
|
|
23
|
+
"@devup-api/core": "0.1.1",
|
|
24
|
+
"@devup-api/utils": "0.1.1"
|
|
21
25
|
},
|
|
22
26
|
"devDependencies": {
|
|
23
27
|
"@types/node": "^24.10",
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
import { expect, test } from 'bun:test'
|
|
2
|
-
import { convertCase } from '../convert-case'
|
|
3
|
-
|
|
4
|
-
test.each([
|
|
5
|
-
['hello_world', 'snake', 'hello_world'],
|
|
6
|
-
['my_variable_name', 'snake', 'my_variable_name'],
|
|
7
|
-
['snake_case_string', 'snake', 'snake_case_string'],
|
|
8
|
-
])('converts to snake_case: %s -> %s', (input, caseType, expected) => {
|
|
9
|
-
expect(convertCase(input, caseType as 'snake')).toBe(expected)
|
|
10
|
-
})
|
|
11
|
-
|
|
12
|
-
test.each([
|
|
13
|
-
['HelloWorld', 'snake', 'hello_world'],
|
|
14
|
-
['MyVariableName', 'snake', 'my_variable_name'],
|
|
15
|
-
['PascalCaseString', 'snake', 'pascal_case_string'],
|
|
16
|
-
])('converts PascalCase to snake_case: %s -> %s', (input, caseType, expected) => {
|
|
17
|
-
expect(convertCase(input, caseType as 'snake')).toBe(expected)
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
test.each([
|
|
21
|
-
['helloWorld', 'snake', 'hello_world'],
|
|
22
|
-
['myVariableName', 'snake', 'my_variable_name'],
|
|
23
|
-
['camelCaseString', 'snake', 'camel_case_string'],
|
|
24
|
-
])('converts camelCase to snake_case: %s -> %s', (input, caseType, expected) => {
|
|
25
|
-
expect(convertCase(input, caseType as 'snake')).toBe(expected)
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
test.each([
|
|
29
|
-
['hello_world', 'camel', 'helloWorld'],
|
|
30
|
-
['my_variable_name', 'camel', 'myVariableName'],
|
|
31
|
-
['snake_case_string', 'camel', 'snakeCaseString'],
|
|
32
|
-
])('converts to camelCase: %s -> %s', (input, caseType, expected) => {
|
|
33
|
-
expect(convertCase(input, caseType as 'camel')).toBe(expected)
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
test.each([
|
|
37
|
-
['HelloWorld', 'camel', 'helloWorld'],
|
|
38
|
-
['MyVariableName', 'camel', 'myVariableName'],
|
|
39
|
-
['PascalCaseString', 'camel', 'pascalCaseString'],
|
|
40
|
-
])('converts PascalCase to camelCase: %s -> %s', (input, caseType, expected) => {
|
|
41
|
-
expect(convertCase(input, caseType as 'camel')).toBe(expected)
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
test.each([
|
|
45
|
-
['helloWorld', 'camel', 'helloWorld'],
|
|
46
|
-
['myVariableName', 'camel', 'myVariableName'],
|
|
47
|
-
['camelCaseString', 'camel', 'camelCaseString'],
|
|
48
|
-
])('returns camelCase strings unchanged: %s -> %s', (input, caseType, expected) => {
|
|
49
|
-
expect(convertCase(input, caseType as 'camel')).toBe(expected)
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
test.each([
|
|
53
|
-
['hello_world', 'pascal', 'HelloWorld'],
|
|
54
|
-
['my_variable_name', 'pascal', 'MyVariableName'],
|
|
55
|
-
['snake_case_string', 'pascal', 'SnakeCaseString'],
|
|
56
|
-
])('converts to PascalCase: %s -> %s', (input, caseType, expected) => {
|
|
57
|
-
expect(convertCase(input, caseType as 'pascal')).toBe(expected)
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
test.each([
|
|
61
|
-
['helloWorld', 'pascal', 'HelloWorld'],
|
|
62
|
-
['myVariableName', 'pascal', 'MyVariableName'],
|
|
63
|
-
['camelCaseString', 'pascal', 'CamelCaseString'],
|
|
64
|
-
])('converts camelCase to PascalCase: %s -> %s', (input, caseType, expected) => {
|
|
65
|
-
expect(convertCase(input, caseType as 'pascal')).toBe(expected)
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
test.each([
|
|
69
|
-
['HelloWorld', 'pascal', 'HelloWorld'],
|
|
70
|
-
['MyVariableName', 'pascal', 'MyVariableName'],
|
|
71
|
-
['PascalCaseString', 'pascal', 'PascalCaseString'],
|
|
72
|
-
])('returns PascalCase strings unchanged: %s -> %s', (input, caseType, expected) => {
|
|
73
|
-
expect(convertCase(input, caseType as 'pascal')).toBe(expected)
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
test.each([
|
|
77
|
-
['hello_world', 'maintain', 'hello_world'],
|
|
78
|
-
['myVariableName', 'maintain', 'myVariableName'],
|
|
79
|
-
['HelloWorld', 'maintain', 'HelloWorld'],
|
|
80
|
-
['any_string-here', 'maintain', 'any_string-here'],
|
|
81
|
-
])('maintains original case: %s -> %s', (input, caseType, expected) => {
|
|
82
|
-
expect(convertCase(input, caseType as 'maintain')).toBe(expected)
|
|
83
|
-
})
|
|
84
|
-
|
|
85
|
-
test.each([
|
|
86
|
-
['hello_world', undefined, 'helloWorld'],
|
|
87
|
-
['my_variable_name', undefined, 'myVariableName'],
|
|
88
|
-
['snake_case_string', undefined, 'snakeCaseString'],
|
|
89
|
-
])('defaults to camelCase when caseType is undefined: %s -> %s', (input, caseType, expected) => {
|
|
90
|
-
// biome-ignore lint/suspicious/noExplicitAny: Testing default behavior with undefined caseType
|
|
91
|
-
expect(convertCase(input, caseType as any)).toBe(expected)
|
|
92
|
-
})
|
|
93
|
-
|
|
94
|
-
test.each([
|
|
95
|
-
['hello_world', 'helloWorld'],
|
|
96
|
-
['my_variable_name', 'myVariableName'],
|
|
97
|
-
['snake_case_string', 'snakeCaseString'],
|
|
98
|
-
])('defaults to camelCase when caseType is not provided: %s -> %s', (input, expected) => {
|
|
99
|
-
expect(convertCase(input)).toBe(expected)
|
|
100
|
-
})
|
|
101
|
-
|
|
102
|
-
test.each([
|
|
103
|
-
['', 'camel', ''],
|
|
104
|
-
['a', 'camel', 'a'],
|
|
105
|
-
['A', 'camel', 'a'],
|
|
106
|
-
])('handles empty string and single characters: %s -> %s', (input, caseType, expected) => {
|
|
107
|
-
expect(convertCase(input, caseType as 'camel')).toBe(expected)
|
|
108
|
-
})
|
|
109
|
-
|
|
110
|
-
test.each([
|
|
111
|
-
['hello_world123', 'camel', 'helloWorld123'],
|
|
112
|
-
['my_variable2_name', 'camel', 'myVariable2Name'],
|
|
113
|
-
['test123_case', 'camel', 'test123Case'],
|
|
114
|
-
])('handles strings with numbers: %s -> %s', (input, caseType, expected) => {
|
|
115
|
-
expect(convertCase(input, caseType as 'camel')).toBe(expected)
|
|
116
|
-
})
|
|
117
|
-
|
|
118
|
-
test.each([
|
|
119
|
-
['hello_world', 'invalid', 'hello_world'],
|
|
120
|
-
['myVariableName', 'unknown', 'myVariableName'],
|
|
121
|
-
['HelloWorld', 'wrong', 'HelloWorld'],
|
|
122
|
-
])('default case returns original string for invalid caseType: %s -> %s', (input, caseType, expected) => {
|
|
123
|
-
// biome-ignore lint/suspicious/noExplicitAny: Testing default case with invalid caseType values
|
|
124
|
-
expect(convertCase(input, caseType as any)).toBe(expected)
|
|
125
|
-
})
|
|
@@ -1,318 +0,0 @@
|
|
|
1
|
-
import { expect, test } from 'bun:test'
|
|
2
|
-
import type { UrlMapValue } from '@devup-api/core'
|
|
3
|
-
import type { OpenAPIV3_1 } from 'openapi-types'
|
|
4
|
-
import { createUrlMap } from '../create-url-map'
|
|
5
|
-
|
|
6
|
-
test.each([
|
|
7
|
-
[
|
|
8
|
-
'camel',
|
|
9
|
-
undefined,
|
|
10
|
-
'get_users',
|
|
11
|
-
{
|
|
12
|
-
getUsers: { method: 'GET', url: '/users' },
|
|
13
|
-
'/users': { method: 'GET', url: '/users' },
|
|
14
|
-
},
|
|
15
|
-
],
|
|
16
|
-
[
|
|
17
|
-
'snake',
|
|
18
|
-
{ convertCase: 'snake' as const },
|
|
19
|
-
'getUsers',
|
|
20
|
-
{
|
|
21
|
-
get_users: { method: 'GET', url: '/users' },
|
|
22
|
-
'/users': { method: 'GET', url: '/users' },
|
|
23
|
-
},
|
|
24
|
-
],
|
|
25
|
-
[
|
|
26
|
-
'pascal',
|
|
27
|
-
{ convertCase: 'pascal' as const },
|
|
28
|
-
'get_users',
|
|
29
|
-
{
|
|
30
|
-
GetUsers: { method: 'GET', url: '/users' },
|
|
31
|
-
'/users': { method: 'GET', url: '/users' },
|
|
32
|
-
},
|
|
33
|
-
],
|
|
34
|
-
[
|
|
35
|
-
'maintain',
|
|
36
|
-
{ convertCase: 'maintain' as const },
|
|
37
|
-
'get_users',
|
|
38
|
-
{
|
|
39
|
-
get_users: { method: 'GET', url: '/users' },
|
|
40
|
-
'/users': { method: 'GET', url: '/users' },
|
|
41
|
-
},
|
|
42
|
-
],
|
|
43
|
-
])('creates url map with %s case conversion', (_, options, operationId, expected) => {
|
|
44
|
-
const schema: OpenAPIV3_1.Document = {
|
|
45
|
-
openapi: '3.1.0',
|
|
46
|
-
info: { title: 'Test API', version: '1.0.0' },
|
|
47
|
-
paths: {
|
|
48
|
-
'/users': {
|
|
49
|
-
get: {
|
|
50
|
-
operationId,
|
|
51
|
-
responses: {},
|
|
52
|
-
},
|
|
53
|
-
},
|
|
54
|
-
},
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const result = createUrlMap(schema, options)
|
|
58
|
-
|
|
59
|
-
expect(result).toEqual(expected as Record<string, UrlMapValue>)
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
test('converts path parameters based on convertCase', () => {
|
|
63
|
-
const schema: OpenAPIV3_1.Document = {
|
|
64
|
-
openapi: '3.1.0',
|
|
65
|
-
info: { title: 'Test API', version: '1.0.0' },
|
|
66
|
-
paths: {
|
|
67
|
-
'/users/{user_id}/posts/{post_id}': {
|
|
68
|
-
get: {
|
|
69
|
-
operationId: 'get_user_post',
|
|
70
|
-
responses: {},
|
|
71
|
-
},
|
|
72
|
-
},
|
|
73
|
-
},
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const result = createUrlMap(schema, { convertCase: 'camel' })
|
|
77
|
-
|
|
78
|
-
expect(result).toEqual({
|
|
79
|
-
getUserPost: {
|
|
80
|
-
method: 'GET',
|
|
81
|
-
url: '/users/{userId}/posts/{postId}',
|
|
82
|
-
},
|
|
83
|
-
'/users/{userId}/posts/{postId}': {
|
|
84
|
-
method: 'GET',
|
|
85
|
-
url: '/users/{userId}/posts/{postId}',
|
|
86
|
-
},
|
|
87
|
-
})
|
|
88
|
-
})
|
|
89
|
-
|
|
90
|
-
test.each([
|
|
91
|
-
['get', 'get_users', 'getUsers', 'GET'],
|
|
92
|
-
['post', 'create_user', 'createUser', 'POST'],
|
|
93
|
-
['put', 'update_user', 'updateUser', 'PUT'],
|
|
94
|
-
['delete', 'delete_user', 'deleteUser', 'DELETE'],
|
|
95
|
-
['patch', 'patch_user', 'patchUser', 'PATCH'],
|
|
96
|
-
])('handles %s HTTP method', (method, operationId, expectedKey, expectedMethod) => {
|
|
97
|
-
const schema: OpenAPIV3_1.Document = {
|
|
98
|
-
openapi: '3.1.0',
|
|
99
|
-
info: { title: 'Test API', version: '1.0.0' },
|
|
100
|
-
paths: {
|
|
101
|
-
'/users': {
|
|
102
|
-
[method]: {
|
|
103
|
-
operationId,
|
|
104
|
-
responses: {},
|
|
105
|
-
},
|
|
106
|
-
},
|
|
107
|
-
},
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
const result = createUrlMap(schema)
|
|
111
|
-
|
|
112
|
-
expect(result).toHaveProperty(expectedKey)
|
|
113
|
-
expect(result[expectedKey]?.method).toBe(
|
|
114
|
-
expectedMethod as 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH',
|
|
115
|
-
)
|
|
116
|
-
expect(result).toHaveProperty('/users')
|
|
117
|
-
expect(result['/users']?.method).toBe(
|
|
118
|
-
expectedMethod as 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH',
|
|
119
|
-
)
|
|
120
|
-
})
|
|
121
|
-
|
|
122
|
-
test('handles operation without operationId', () => {
|
|
123
|
-
const schema: OpenAPIV3_1.Document = {
|
|
124
|
-
openapi: '3.1.0',
|
|
125
|
-
info: { title: 'Test API', version: '1.0.0' },
|
|
126
|
-
paths: {
|
|
127
|
-
'/users': {
|
|
128
|
-
get: {
|
|
129
|
-
responses: {},
|
|
130
|
-
},
|
|
131
|
-
},
|
|
132
|
-
},
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
const result = createUrlMap(schema)
|
|
136
|
-
|
|
137
|
-
expect(result).toEqual({
|
|
138
|
-
'/users': {
|
|
139
|
-
method: 'GET',
|
|
140
|
-
url: '/users',
|
|
141
|
-
},
|
|
142
|
-
})
|
|
143
|
-
expect(result).not.toHaveProperty('getUsers')
|
|
144
|
-
})
|
|
145
|
-
|
|
146
|
-
test('handles multiple paths', () => {
|
|
147
|
-
const schema: OpenAPIV3_1.Document = {
|
|
148
|
-
openapi: '3.1.0',
|
|
149
|
-
info: { title: 'Test API', version: '1.0.0' },
|
|
150
|
-
paths: {
|
|
151
|
-
'/users': {
|
|
152
|
-
get: {
|
|
153
|
-
operationId: 'get_users',
|
|
154
|
-
responses: {},
|
|
155
|
-
},
|
|
156
|
-
},
|
|
157
|
-
'/posts': {
|
|
158
|
-
get: {
|
|
159
|
-
operationId: 'get_posts',
|
|
160
|
-
responses: {},
|
|
161
|
-
},
|
|
162
|
-
},
|
|
163
|
-
},
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
const result = createUrlMap(schema)
|
|
167
|
-
|
|
168
|
-
expect(result).toHaveProperty('getUsers')
|
|
169
|
-
expect(result).toHaveProperty('getPosts')
|
|
170
|
-
expect(result).toHaveProperty('/users')
|
|
171
|
-
expect(result).toHaveProperty('/posts')
|
|
172
|
-
})
|
|
173
|
-
|
|
174
|
-
test('handles empty paths', () => {
|
|
175
|
-
const schema: OpenAPIV3_1.Document = {
|
|
176
|
-
openapi: '3.1.0',
|
|
177
|
-
info: { title: 'Test API', version: '1.0.0' },
|
|
178
|
-
paths: {},
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
const result = createUrlMap(schema)
|
|
182
|
-
|
|
183
|
-
expect(result).toEqual({})
|
|
184
|
-
})
|
|
185
|
-
|
|
186
|
-
test('handles undefined paths', () => {
|
|
187
|
-
const schema: OpenAPIV3_1.Document = {
|
|
188
|
-
openapi: '3.1.0',
|
|
189
|
-
info: { title: 'Test API', version: '1.0.0' },
|
|
190
|
-
components: {},
|
|
191
|
-
paths: {},
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
const result = createUrlMap(schema)
|
|
195
|
-
|
|
196
|
-
expect(result).toEqual({})
|
|
197
|
-
})
|
|
198
|
-
|
|
199
|
-
test('handles undefined pathItem', () => {
|
|
200
|
-
const schema: OpenAPIV3_1.Document = {
|
|
201
|
-
openapi: '3.1.0',
|
|
202
|
-
info: { title: 'Test API', version: '1.0.0' },
|
|
203
|
-
paths: {
|
|
204
|
-
'/users': undefined,
|
|
205
|
-
},
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
const result = createUrlMap(schema)
|
|
209
|
-
|
|
210
|
-
expect(result).toEqual({})
|
|
211
|
-
})
|
|
212
|
-
|
|
213
|
-
test('skips operations that do not exist', () => {
|
|
214
|
-
const schema: OpenAPIV3_1.Document = {
|
|
215
|
-
openapi: '3.1.0',
|
|
216
|
-
info: { title: 'Test API', version: '1.0.0' },
|
|
217
|
-
paths: {
|
|
218
|
-
'/users': {
|
|
219
|
-
get: {
|
|
220
|
-
operationId: 'get_users',
|
|
221
|
-
responses: {},
|
|
222
|
-
},
|
|
223
|
-
// post, put, delete, patch are not defined
|
|
224
|
-
},
|
|
225
|
-
},
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
const result = createUrlMap(schema)
|
|
229
|
-
|
|
230
|
-
expect(result).toEqual({
|
|
231
|
-
getUsers: {
|
|
232
|
-
method: 'GET',
|
|
233
|
-
url: '/users',
|
|
234
|
-
},
|
|
235
|
-
'/users': {
|
|
236
|
-
method: 'GET',
|
|
237
|
-
url: '/users',
|
|
238
|
-
},
|
|
239
|
-
})
|
|
240
|
-
})
|
|
241
|
-
|
|
242
|
-
test('handles complex path with multiple parameters', () => {
|
|
243
|
-
const schema: OpenAPIV3_1.Document = {
|
|
244
|
-
openapi: '3.1.0',
|
|
245
|
-
info: { title: 'Test API', version: '1.0.0' },
|
|
246
|
-
paths: {
|
|
247
|
-
'/api/v1/users/{user_id}/posts/{post_id}/comments/{comment_id}': {
|
|
248
|
-
get: {
|
|
249
|
-
operationId: 'get_user_post_comment',
|
|
250
|
-
responses: {},
|
|
251
|
-
},
|
|
252
|
-
},
|
|
253
|
-
},
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
const result = createUrlMap(schema, { convertCase: 'snake' })
|
|
257
|
-
|
|
258
|
-
expect(result).toEqual({
|
|
259
|
-
get_user_post_comment: {
|
|
260
|
-
method: 'GET',
|
|
261
|
-
url: '/api/v1/users/{user_id}/posts/{post_id}/comments/{comment_id}',
|
|
262
|
-
},
|
|
263
|
-
'/api/v1/users/{user_id}/posts/{post_id}/comments/{comment_id}': {
|
|
264
|
-
method: 'GET',
|
|
265
|
-
url: '/api/v1/users/{user_id}/posts/{post_id}/comments/{comment_id}',
|
|
266
|
-
},
|
|
267
|
-
})
|
|
268
|
-
})
|
|
269
|
-
|
|
270
|
-
test.each([
|
|
271
|
-
['camel', '/users/{userId}', '/users/{userId}'],
|
|
272
|
-
['snake', '/users/{user_id}', '/users/{user_id}'],
|
|
273
|
-
['pascal', '/users/{UserId}', '/users/{UserId}'],
|
|
274
|
-
])('converts path parameters with %s case: %s', (caseType, expectedPath, expectedUrl) => {
|
|
275
|
-
const schema: OpenAPIV3_1.Document = {
|
|
276
|
-
openapi: '3.1.0',
|
|
277
|
-
info: { title: 'Test API', version: '1.0.0' },
|
|
278
|
-
paths: {
|
|
279
|
-
'/users/{user_id}': {
|
|
280
|
-
get: {
|
|
281
|
-
operationId: 'get_user',
|
|
282
|
-
responses: {},
|
|
283
|
-
},
|
|
284
|
-
},
|
|
285
|
-
},
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
const result = createUrlMap(schema, {
|
|
289
|
-
convertCase: caseType as 'camel' | 'snake' | 'pascal',
|
|
290
|
-
})
|
|
291
|
-
|
|
292
|
-
expect(result[expectedPath]?.url).toBe(expectedUrl)
|
|
293
|
-
})
|
|
294
|
-
|
|
295
|
-
test.each([
|
|
296
|
-
['camel', 'getUserList'],
|
|
297
|
-
['snake', 'get_user_list'],
|
|
298
|
-
['pascal', 'GetUserList'],
|
|
299
|
-
])('converts operationId with %s case: %s', (caseType, expectedKey) => {
|
|
300
|
-
const schema: OpenAPIV3_1.Document = {
|
|
301
|
-
openapi: '3.1.0',
|
|
302
|
-
info: { title: 'Test API', version: '1.0.0' },
|
|
303
|
-
paths: {
|
|
304
|
-
'/users': {
|
|
305
|
-
get: {
|
|
306
|
-
operationId: 'get_user_list',
|
|
307
|
-
responses: {},
|
|
308
|
-
},
|
|
309
|
-
},
|
|
310
|
-
},
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
const result = createUrlMap(schema, {
|
|
314
|
-
convertCase: caseType as 'camel' | 'snake' | 'pascal',
|
|
315
|
-
})
|
|
316
|
-
|
|
317
|
-
expect(result).toHaveProperty(expectedKey)
|
|
318
|
-
})
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { expect, test } from 'bun:test'
|
|
2
|
-
import { wrapInterfaceKeyGuard } from '../wrap-interface-key-guard'
|
|
3
|
-
|
|
4
|
-
test.each([
|
|
5
|
-
['getUsers', 'getUsers'],
|
|
6
|
-
['createUser', 'createUser'],
|
|
7
|
-
['updateUser', 'updateUser'],
|
|
8
|
-
['deleteUser', 'deleteUser'],
|
|
9
|
-
['testKey', 'testKey'],
|
|
10
|
-
['camelCase', 'camelCase'],
|
|
11
|
-
['snake_case', 'snake_case'],
|
|
12
|
-
['PascalCase', 'PascalCase'],
|
|
13
|
-
] as const)('wrapInterfaceKeyGuard returns key as-is when no slash: %s -> %s', (key, expected) => {
|
|
14
|
-
expect(wrapInterfaceKeyGuard(key)).toBe(expected)
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
test.each([
|
|
18
|
-
['/users', '[`/users`]'],
|
|
19
|
-
['/users/{id}', '[`/users/{id}`]'],
|
|
20
|
-
['/api/v1/users', '[`/api/v1/users`]'],
|
|
21
|
-
['/users/{userId}/posts/{postId}', '[`/users/{userId}/posts/{postId}`]'],
|
|
22
|
-
['/api/v1/users/{id}/profile', '[`/api/v1/users/{id}/profile`]'],
|
|
23
|
-
] as const)('wrapInterfaceKeyGuard wraps key with backticks when slash present: %s -> %s', (key, expected) => {
|
|
24
|
-
expect(wrapInterfaceKeyGuard(key)).toBe(expected)
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
test.each([
|
|
28
|
-
['', ''],
|
|
29
|
-
['/', '[`/`]'],
|
|
30
|
-
['//', '[`//`]'],
|
|
31
|
-
['///', '[`///`]'],
|
|
32
|
-
] as const)('wrapInterfaceKeyGuard handles edge cases: %s -> %s', (key, expected) => {
|
|
33
|
-
expect(wrapInterfaceKeyGuard(key)).toBe(expected)
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
test.each([
|
|
37
|
-
['users/123', '[`users/123`]'],
|
|
38
|
-
['test/path/here', '[`test/path/here`]'],
|
|
39
|
-
['a/b/c/d', '[`a/b/c/d`]'],
|
|
40
|
-
] as const)('wrapInterfaceKeyGuard wraps key with multiple slashes: %s -> %s', (key, expected) => {
|
|
41
|
-
expect(wrapInterfaceKeyGuard(key)).toBe(expected)
|
|
42
|
-
})
|
package/src/convert-case.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { toCamel, toPascal, toSnake } from '@devup-api/utils'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Convert string based on convertCase option
|
|
5
|
-
*/
|
|
6
|
-
export function convertCase(
|
|
7
|
-
str: string,
|
|
8
|
-
caseType: 'snake' | 'camel' | 'pascal' | 'maintain' = 'camel',
|
|
9
|
-
): string {
|
|
10
|
-
switch (caseType) {
|
|
11
|
-
case 'snake':
|
|
12
|
-
return toSnake(str)
|
|
13
|
-
case 'camel':
|
|
14
|
-
return toCamel(str)
|
|
15
|
-
case 'pascal':
|
|
16
|
-
return toPascal(str)
|
|
17
|
-
case 'maintain':
|
|
18
|
-
return str
|
|
19
|
-
default:
|
|
20
|
-
return str
|
|
21
|
-
}
|
|
22
|
-
}
|
package/src/create-url-map.ts
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import type { DevupApiTypeGeneratorOptions, UrlMapValue } from '@devup-api/core'
|
|
2
|
-
import type { OpenAPIV3_1 } from 'openapi-types'
|
|
3
|
-
import { convertCase } from './convert-case'
|
|
4
|
-
|
|
5
|
-
export function createUrlMap(
|
|
6
|
-
schema: OpenAPIV3_1.Document,
|
|
7
|
-
options?: DevupApiTypeGeneratorOptions,
|
|
8
|
-
) {
|
|
9
|
-
const convertCaseType = options?.convertCase ?? 'camel'
|
|
10
|
-
const urlMap: Record<string, UrlMapValue> = {}
|
|
11
|
-
for (const [path, pathItem] of Object.entries(schema.paths ?? {})) {
|
|
12
|
-
if (!pathItem) continue
|
|
13
|
-
for (const method of ['get', 'post', 'put', 'delete', 'patch'] as const) {
|
|
14
|
-
const operation = pathItem[method]
|
|
15
|
-
if (!operation) continue
|
|
16
|
-
const normalizedPath = path.replace(/\{([^}]+)\}/g, (_, param) => {
|
|
17
|
-
// Convert param name based on case type
|
|
18
|
-
return `{${convertCase(param, convertCaseType)}}`
|
|
19
|
-
})
|
|
20
|
-
if (operation.operationId) {
|
|
21
|
-
urlMap[convertCase(operation.operationId, convertCaseType)] = {
|
|
22
|
-
method: method.toUpperCase() as
|
|
23
|
-
| 'GET'
|
|
24
|
-
| 'POST'
|
|
25
|
-
| 'PUT'
|
|
26
|
-
| 'DELETE'
|
|
27
|
-
| 'PATCH',
|
|
28
|
-
url: normalizedPath,
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
urlMap[normalizedPath] = {
|
|
32
|
-
method: method.toUpperCase() as
|
|
33
|
-
| 'GET'
|
|
34
|
-
| 'POST'
|
|
35
|
-
| 'PUT'
|
|
36
|
-
| 'DELETE'
|
|
37
|
-
| 'PATCH',
|
|
38
|
-
url: normalizedPath,
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
return urlMap
|
|
43
|
-
}
|