massimo-cli 1.3.0 → 1.5.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/lib/frontend-openapi-generator.js +22 -1
- package/lib/get-type.js +16 -12
- package/package.json +14 -14
|
@@ -68,6 +68,7 @@ function generateFrontendImplementationFromOpenAPI ({
|
|
|
68
68
|
useTabs: false,
|
|
69
69
|
useSingleQuote: true
|
|
70
70
|
})
|
|
71
|
+
const hasPathParameters = operations.some(operation => operation.path.includes('{'))
|
|
71
72
|
|
|
72
73
|
writer.write('// This client was generated by Platformatic from an OpenAPI specification.')
|
|
73
74
|
writer.blankLine()
|
|
@@ -132,6 +133,18 @@ function generateFrontendImplementationFromOpenAPI ({
|
|
|
132
133
|
writer.writeLine('return output')
|
|
133
134
|
})
|
|
134
135
|
}
|
|
136
|
+
if (hasPathParameters) {
|
|
137
|
+
writer.newLine()
|
|
138
|
+
writer
|
|
139
|
+
.write(`function encodePathParameter(value${isTsLang ? ': unknown' : ''})${isTsLang ? ': string' : ''} `)
|
|
140
|
+
.block(() => {
|
|
141
|
+
writer.writeLine(`const encoded = encodeURIComponent(value${isTsLang ? ' as string' : ''})`)
|
|
142
|
+
writer.write('if (encoded === \'.\' || encoded === \'..\') ').block(() => {
|
|
143
|
+
writer.writeLine('throw new Error(\'Path parameters cannot be "." or ".."\')')
|
|
144
|
+
})
|
|
145
|
+
writer.writeLine('return encoded')
|
|
146
|
+
})
|
|
147
|
+
}
|
|
135
148
|
writer.blankLine()
|
|
136
149
|
const allOperations = []
|
|
137
150
|
const originalFullResponse = fullResponse
|
|
@@ -192,7 +205,9 @@ function generateFrontendImplementationFromOpenAPI ({
|
|
|
192
205
|
// /organizations/{orgId}/members/{memberId}
|
|
193
206
|
// to
|
|
194
207
|
// /organizations/${request.orgId}/members/${request.memberId}
|
|
195
|
-
const stringLiteralPath = path
|
|
208
|
+
const stringLiteralPath = path
|
|
209
|
+
.replace(/\{/gm, '${encodePathParameter(' + req + "['")
|
|
210
|
+
.replace(/\}/gm, "'])}")
|
|
196
211
|
// GET methods need query strings instead of JSON bodies
|
|
197
212
|
if (queryParams.length) {
|
|
198
213
|
// query parameters should be appended to the url
|
|
@@ -446,6 +461,12 @@ function generateTypesFromOpenAPI ({ schema, name, fullRequest, fullResponse, pr
|
|
|
446
461
|
})
|
|
447
462
|
})
|
|
448
463
|
|
|
464
|
+
// Declare the module-level named exports emitted by the implementation file,
|
|
465
|
+
// so consumers relying on the .d.ts can `import { setBaseUrl, ... }` without type errors.
|
|
466
|
+
writer.writeLine(`export declare const setBaseUrl: ${camelCaseName}['setBaseUrl'];`)
|
|
467
|
+
writer.writeLine(`export declare const setDefaultHeaders: ${camelCaseName}['setDefaultHeaders'];`)
|
|
468
|
+
writer.writeLine(`export declare const setDefaultFetchParams: ${camelCaseName}['setDefaultFetchParams'];`)
|
|
469
|
+
|
|
449
470
|
writer.writeLine(`type PlatformaticFrontendClient = Omit<${camelCaseName}, 'setBaseUrl'>`)
|
|
450
471
|
writer.write('type BuildOptions = ').block(() => {
|
|
451
472
|
writer.writeLine('headers?: object')
|
package/lib/get-type.js
CHANGED
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
import jsonpointer from 'jsonpointer'
|
|
2
2
|
|
|
3
|
-
export function getType (typeDef, methodType, spec) {
|
|
3
|
+
export function getType (typeDef, methodType, spec, seenRefs = new Set()) {
|
|
4
4
|
if (typeDef.$ref) {
|
|
5
|
+
if (seenRefs.has(typeDef.$ref)) {
|
|
6
|
+
return 'unknown'
|
|
7
|
+
}
|
|
8
|
+
seenRefs = new Set(seenRefs)
|
|
9
|
+
seenRefs.add(typeDef.$ref)
|
|
5
10
|
typeDef = jsonpointer.get(spec, typeDef.$ref.replace('#', ''))
|
|
6
11
|
}
|
|
7
12
|
if (typeDef.schema) {
|
|
8
|
-
return getType(typeDef.schema, methodType, spec)
|
|
13
|
+
return getType(typeDef.schema, methodType, spec, seenRefs)
|
|
9
14
|
}
|
|
10
15
|
if (typeDef.anyOf) {
|
|
11
16
|
// recursively call this function
|
|
12
17
|
const mapped = typeDef.anyOf.map(t => {
|
|
13
|
-
return getType(t, methodType, spec)
|
|
18
|
+
return getType(t, methodType, spec, seenRefs)
|
|
14
19
|
})
|
|
15
20
|
return mapped.join(' | ')
|
|
16
21
|
}
|
|
@@ -18,7 +23,7 @@ export function getType (typeDef, methodType, spec) {
|
|
|
18
23
|
if (typeDef.oneOf) {
|
|
19
24
|
// recursively call this function
|
|
20
25
|
const mapped = typeDef.oneOf.map(t => {
|
|
21
|
-
return getType(t, methodType, spec)
|
|
26
|
+
return getType(t, methodType, spec, seenRefs)
|
|
22
27
|
})
|
|
23
28
|
|
|
24
29
|
if (typeDef.discriminator && typeDef.discriminator.propertyName) {
|
|
@@ -56,13 +61,13 @@ export function getType (typeDef, methodType, spec) {
|
|
|
56
61
|
// recursively call this function
|
|
57
62
|
return typeDef.allOf
|
|
58
63
|
.map(t => {
|
|
59
|
-
return getType(t, methodType, spec)
|
|
64
|
+
return getType(t, methodType, spec, seenRefs)
|
|
60
65
|
})
|
|
61
66
|
.join(' & ')
|
|
62
67
|
}
|
|
63
68
|
if (typeDef.type === 'array') {
|
|
64
69
|
const nullable = typeDef.nullable
|
|
65
|
-
return `Array<${getType(typeDef.items, methodType, spec)}>${nullable === true ? ' | null' : ''}`
|
|
70
|
+
return `Array<${getType(typeDef.items, methodType, spec, seenRefs)}>${nullable === true ? ' | null' : ''}`
|
|
66
71
|
}
|
|
67
72
|
if (typeDef.enum) {
|
|
68
73
|
// Note: null type represented with an enum have no types and single enum element 'null'
|
|
@@ -73,11 +78,10 @@ export function getType (typeDef, methodType, spec) {
|
|
|
73
78
|
const nullable = typeDef.nullable
|
|
74
79
|
const chainedTypes = typeDef.enum
|
|
75
80
|
.map(en => {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
81
|
+
// Quote by the runtime type of the value: the schema may omit `type`
|
|
82
|
+
if (en === null) return 'null'
|
|
83
|
+
if (typeof en === 'string') return `'${en.replace(/'/g, "\\'")}'`
|
|
84
|
+
return en
|
|
81
85
|
})
|
|
82
86
|
.join(' | ')
|
|
83
87
|
return nullable === true ? `${chainedTypes} | null` : chainedTypes
|
|
@@ -108,7 +112,7 @@ export function getType (typeDef, methodType, spec) {
|
|
|
108
112
|
if (additionalPropsRequired) {
|
|
109
113
|
required = required || !!additionalPropsRequired.includes(prop)
|
|
110
114
|
}
|
|
111
|
-
return `'${prop}'${required ? '' : '?'}: ${getType(objProperties[prop], methodType, spec)}`
|
|
115
|
+
return `'${prop}'${required ? '' : '?'}: ${getType(objProperties[prop], methodType, spec, seenRefs)}`
|
|
112
116
|
})
|
|
113
117
|
if (additionalProps === true) {
|
|
114
118
|
props.push('[key: string]: unknown')
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "massimo-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.1",
|
|
4
4
|
"description": "A client for HTTP services.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -25,21 +25,21 @@
|
|
|
25
25
|
"graphql": "^16.8.1",
|
|
26
26
|
"help-me": "^5.0.0",
|
|
27
27
|
"jsonpointer": "^5.0.1",
|
|
28
|
+
"massimo": "1.5.1",
|
|
28
29
|
"minimist": "^1.2.8",
|
|
29
30
|
"pino": "^9.9.0",
|
|
30
31
|
"pino-pretty": "^13.0.0",
|
|
31
32
|
"undici": "^7.0.0",
|
|
32
|
-
"yaml": "^2.4.1"
|
|
33
|
-
"massimo": "1.3.0"
|
|
33
|
+
"yaml": "^2.4.1"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
|
-
"@platformatic/composer": "3.
|
|
37
|
-
"@platformatic/db": "3.
|
|
38
|
-
"@platformatic/foundation": "3.
|
|
39
|
-
"@platformatic/runtime": "3.
|
|
40
|
-
"@platformatic/service": "3.
|
|
41
|
-
"@platformatic/sql-graphql": "3.
|
|
42
|
-
"@platformatic/sql-mapper": "3.
|
|
36
|
+
"@platformatic/composer": "3.68.0",
|
|
37
|
+
"@platformatic/db": "3.67.0",
|
|
38
|
+
"@platformatic/foundation": "3.68.0",
|
|
39
|
+
"@platformatic/runtime": "3.68.0",
|
|
40
|
+
"@platformatic/service": "3.67.0",
|
|
41
|
+
"@platformatic/sql-graphql": "3.68.0",
|
|
42
|
+
"@platformatic/sql-mapper": "3.68.0",
|
|
43
43
|
"@playwright/test": "^1.42.1",
|
|
44
44
|
"@types/react": "^19.1.6",
|
|
45
45
|
"@types/react-dom": "^19.1.5",
|
|
@@ -48,18 +48,18 @@
|
|
|
48
48
|
"dotenv": "^16.4.5",
|
|
49
49
|
"eslint": "9",
|
|
50
50
|
"execa": "^9.0.0",
|
|
51
|
-
"fastify": "^5.
|
|
51
|
+
"fastify": "^5.12.0",
|
|
52
52
|
"fastify-tsconfig": "^3.0.0",
|
|
53
53
|
"fs-extra": "^11.2.0",
|
|
54
|
-
"neostandard": "^0.
|
|
54
|
+
"neostandard": "^0.13.0",
|
|
55
55
|
"react": "^19.1.0",
|
|
56
56
|
"react-dom": "^19.1.0",
|
|
57
57
|
"scheduler": "^0.27.0",
|
|
58
58
|
"split2": "^4.2.0",
|
|
59
|
-
"tsd": "^0.
|
|
59
|
+
"tsd": "^0.33.0",
|
|
60
60
|
"typescript": "^5.5.4",
|
|
61
61
|
"vite": "^5.1.6",
|
|
62
|
-
"wattpm": "3.
|
|
62
|
+
"wattpm": "3.67.0",
|
|
63
63
|
"why-is-node-running": "^2.2.2"
|
|
64
64
|
},
|
|
65
65
|
"engines": {
|