@bagelink/sdk 0.0.1121 → 0.0.1125
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/dist/index.cjs +112 -95
- package/dist/index.mjs +112 -95
- package/package.json +1 -1
- package/src/openAPITools/functionGenerator.ts +119 -45
- package/src/openAPITools/typeGenerator.ts +1 -1
- package/src/openAPITools/utils.ts +51 -10
package/dist/index.cjs
CHANGED
|
@@ -6,31 +6,32 @@ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'defau
|
|
|
6
6
|
|
|
7
7
|
const axios__default = /*#__PURE__*/_interopDefaultCompat(axios$1);
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
function toCamelCase(str) {
|
|
10
|
+
return str?.replaceAll(/[-._\s]+(.)?/g, (_, c) => c?.toUpperCase() || "").replace(/^./, (str2) => str2.toLowerCase()) || str || "";
|
|
11
|
+
}
|
|
12
|
+
function toPascalCase(str) {
|
|
13
|
+
return str?.replaceAll(/[-_\s]+(.)?/g, (_, c) => c?.toUpperCase() || "").replace(/^./, (str2) => str2.toUpperCase()) || str || "";
|
|
14
|
+
}
|
|
11
15
|
function formatType(typeName) {
|
|
12
|
-
typeName = typeName.replaceAll("-", "").replaceAll(/
|
|
16
|
+
typeName = typeName.replaceAll("-", "").replaceAll(/post|put$/gi, "").replaceAll(/^body_/gi, "");
|
|
13
17
|
return toPascalCase(typeName);
|
|
14
18
|
}
|
|
15
19
|
function resolveReference(ref) {
|
|
16
20
|
const t = ref.split("/").pop();
|
|
17
|
-
if (!t)
|
|
18
|
-
return "any";
|
|
21
|
+
if (!t) return "any";
|
|
19
22
|
return formatType(t);
|
|
20
23
|
}
|
|
21
24
|
function schemaToType(schema) {
|
|
22
|
-
if (!schema)
|
|
23
|
-
return "any";
|
|
25
|
+
if (!schema) return "any";
|
|
24
26
|
if (schema.anyOf) {
|
|
25
27
|
let _t = schema.anyOf.map((s) => schemaToType(s)).filter((p) => p !== "any").join(" | ");
|
|
26
|
-
if (_t === "" || _t === "null")
|
|
27
|
-
_t = "any";
|
|
28
|
+
if (_t === "" || _t === "null") _t = "any";
|
|
28
29
|
return _t;
|
|
29
30
|
}
|
|
30
|
-
if (schema.allOf)
|
|
31
|
+
if (schema.allOf) {
|
|
31
32
|
return schema.allOf.map((s) => schemaToType(s)).filter((p) => p !== "any").join(" & ");
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
}
|
|
34
|
+
if (schema.$ref) return resolveReference(schema.$ref);
|
|
34
35
|
switch (schema.type) {
|
|
35
36
|
case "object":
|
|
36
37
|
return "{ [key: string]: any }";
|
|
@@ -48,7 +49,7 @@ function schemaToType(schema) {
|
|
|
48
49
|
return "undefined";
|
|
49
50
|
case "null":
|
|
50
51
|
return "null";
|
|
51
|
-
case
|
|
52
|
+
case undefined:
|
|
52
53
|
return "any";
|
|
53
54
|
default:
|
|
54
55
|
console.log("Unknown type", schema.type);
|
|
@@ -60,10 +61,17 @@ function isOptional(schema) {
|
|
|
60
61
|
const splitType = type.split(/\s+\|\s+/);
|
|
61
62
|
const includesNull = splitType.includes("null");
|
|
62
63
|
const includesUndefined = splitType.includes("undefined");
|
|
63
|
-
return includesNull || includesUndefined || schema.default !==
|
|
64
|
+
return includesNull || includesUndefined || schema.default !== undefined;
|
|
64
65
|
}
|
|
65
|
-
|
|
66
|
-
|
|
66
|
+
function cleanOptionals(str) {
|
|
67
|
+
return str.split(" | ").filter((t) => t !== "null" && t !== "undefined").join(" | ");
|
|
68
|
+
}
|
|
69
|
+
function formatVarType({
|
|
70
|
+
varName,
|
|
71
|
+
schema,
|
|
72
|
+
required = false,
|
|
73
|
+
defaultValue
|
|
74
|
+
}) {
|
|
67
75
|
let type = schemaToType(schema);
|
|
68
76
|
type = cleanOptionals(type);
|
|
69
77
|
let defaultStr = "";
|
|
@@ -74,9 +82,8 @@ function formatVarType(varName, schema, required = false, defaultValue) {
|
|
|
74
82
|
defaultStr = ` = ${defaultValue}`;
|
|
75
83
|
}
|
|
76
84
|
}
|
|
77
|
-
let optionalStr = required
|
|
78
|
-
if (defaultStr)
|
|
79
|
-
optionalStr = "";
|
|
85
|
+
let optionalStr = !required && isOptional(schema) ? "?" : "";
|
|
86
|
+
if (defaultStr) optionalStr = "";
|
|
80
87
|
return `${varName}${optionalStr}: ${type}${defaultStr}`;
|
|
81
88
|
}
|
|
82
89
|
function cleanPath(path) {
|
|
@@ -84,35 +91,39 @@ function cleanPath(path) {
|
|
|
84
91
|
}
|
|
85
92
|
|
|
86
93
|
const allTypes = [];
|
|
87
|
-
const primitiveTypes = [
|
|
94
|
+
const primitiveTypes = [
|
|
95
|
+
"string",
|
|
96
|
+
"number",
|
|
97
|
+
"boolean",
|
|
98
|
+
"null",
|
|
99
|
+
"void",
|
|
100
|
+
"any",
|
|
101
|
+
"Record<string, any>",
|
|
102
|
+
"undefined",
|
|
103
|
+
"{ [key: string]: any }"
|
|
104
|
+
];
|
|
88
105
|
function collectTypeForImportStatement(typeName) {
|
|
89
106
|
typeName = typeName.trim().replace("[]", "");
|
|
90
107
|
if (typeName.includes("|")) {
|
|
91
|
-
typeName.split("|").forEach(
|
|
92
|
-
(singleType)
|
|
93
|
-
|
|
94
|
-
}
|
|
95
|
-
);
|
|
108
|
+
typeName.split("|").forEach((singleType) => {
|
|
109
|
+
collectTypeForImportStatement(singleType);
|
|
110
|
+
});
|
|
96
111
|
return;
|
|
97
112
|
}
|
|
98
113
|
const isPrimitive = primitiveTypes.includes(typeName);
|
|
99
114
|
typeName = formatType(typeName);
|
|
100
|
-
if (!typeName || isPrimitive)
|
|
101
|
-
|
|
102
|
-
if (!allTypes.includes(typeName))
|
|
103
|
-
allTypes.push(typeName);
|
|
115
|
+
if (!typeName || isPrimitive) return;
|
|
116
|
+
if (!allTypes.includes(typeName)) allTypes.push(typeName);
|
|
104
117
|
}
|
|
105
118
|
function getResponseType(response) {
|
|
106
119
|
const mediaTypeObject = response.content?.["application/json"];
|
|
107
|
-
if (!mediaTypeObject || !mediaTypeObject.schema)
|
|
108
|
-
return;
|
|
120
|
+
if (!mediaTypeObject || !mediaTypeObject.schema) return;
|
|
109
121
|
const responseType = schemaToType(mediaTypeObject.schema);
|
|
110
122
|
collectTypeForImportStatement(responseType);
|
|
111
123
|
return responseType;
|
|
112
124
|
}
|
|
113
125
|
function generateResponseType(responses) {
|
|
114
|
-
if (!responses)
|
|
115
|
-
return "";
|
|
126
|
+
if (!responses) return "";
|
|
116
127
|
const types = [];
|
|
117
128
|
for (const [statusCode, response] of Object.entries(responses)) {
|
|
118
129
|
if (statusCode.startsWith("2")) {
|
|
@@ -125,8 +136,7 @@ function generateResponseType(responses) {
|
|
|
125
136
|
return types.join(" | ");
|
|
126
137
|
}
|
|
127
138
|
function generateAxiosFunction(method, formattedPath, allParams, responseTypeStr, parameters, requestBodyPayload) {
|
|
128
|
-
if (allParams === "undefined")
|
|
129
|
-
allParams = "";
|
|
139
|
+
if (allParams === "undefined") allParams = "";
|
|
130
140
|
let axiosFunction = `async (${allParams})${responseTypeStr} => {`;
|
|
131
141
|
if (requestBodyPayload === "formData") {
|
|
132
142
|
const paramStr = parameters?.config?.params ? `params: {${parameters.config.params}}` : "";
|
|
@@ -175,21 +185,23 @@ function generateRequestBody(requestBody) {
|
|
|
175
185
|
const requestBodyType = schemaToType(bodySchema);
|
|
176
186
|
collectTypeForImportStatement(requestBodyType);
|
|
177
187
|
const requestBodyPayload = toCamelCase(bodySchema.title) || toCamelCase(requestBodyType) || "requestBody";
|
|
178
|
-
const requestBodyParam = formatVarType(
|
|
188
|
+
const requestBodyParam = formatVarType({
|
|
189
|
+
varName: requestBodyPayload,
|
|
190
|
+
schema: bodySchema,
|
|
191
|
+
defaultValue: bodySchema.default
|
|
192
|
+
});
|
|
179
193
|
return { requestBodyParam, requestBodyPayload };
|
|
180
194
|
}
|
|
181
195
|
function combineAllParams(parameters, requestBodyParam) {
|
|
182
196
|
let allParamsArray = [];
|
|
183
197
|
if (parameters && parameters.params)
|
|
184
198
|
allParamsArray = parameters.params.split(",").map((p) => p.trim());
|
|
185
|
-
if (requestBodyParam)
|
|
186
|
-
allParamsArray.push(requestBodyParam.trim());
|
|
199
|
+
if (requestBodyParam) allParamsArray.push(requestBodyParam.trim());
|
|
187
200
|
allParamsArray = allParamsArray.filter((p) => p).sort((a, b) => (a.includes("?") ? 1 : -1) - (b.includes("?") ? 1 : -1));
|
|
188
201
|
return allParamsArray.join(", ");
|
|
189
202
|
}
|
|
190
203
|
function generateFunctionParameters(params, isFileUpload = false) {
|
|
191
|
-
if (!params?.length)
|
|
192
|
-
return {};
|
|
204
|
+
if (!params?.length) return {};
|
|
193
205
|
if (isFileUpload) {
|
|
194
206
|
return {
|
|
195
207
|
config: {
|
|
@@ -207,10 +219,19 @@ function generateFunctionParameters(params, isFileUpload = false) {
|
|
|
207
219
|
const paramName = param.name;
|
|
208
220
|
const varName = toCamelCase(param.name);
|
|
209
221
|
if (param.in === "path" || param.in === "query" || param.in === "header") {
|
|
210
|
-
functionParams.push(
|
|
222
|
+
functionParams.push(
|
|
223
|
+
formatVarType({
|
|
224
|
+
varName,
|
|
225
|
+
schema: param.schema,
|
|
226
|
+
required: param.required,
|
|
227
|
+
defaultValue: param.schema.default
|
|
228
|
+
})
|
|
229
|
+
);
|
|
211
230
|
}
|
|
212
231
|
if (param.in === "query" || param.in === "header") {
|
|
213
|
-
paramList.push(
|
|
232
|
+
paramList.push(
|
|
233
|
+
paramName === varName ? paramName : `'${paramName}': ${varName}`
|
|
234
|
+
);
|
|
214
235
|
}
|
|
215
236
|
}
|
|
216
237
|
return {
|
|
@@ -219,11 +240,15 @@ function generateFunctionParameters(params, isFileUpload = false) {
|
|
|
219
240
|
};
|
|
220
241
|
}
|
|
221
242
|
function generateFunctionForOperation(method, path, operation) {
|
|
222
|
-
if (!operation)
|
|
223
|
-
return "";
|
|
243
|
+
if (!operation) return "";
|
|
224
244
|
const isFileUpload = operation.requestBody?.content["multipart/form-data"]?.schema?.$ref?.includes("Body_upload_files");
|
|
225
|
-
const parameters = generateFunctionParameters(
|
|
226
|
-
|
|
245
|
+
const parameters = generateFunctionParameters(
|
|
246
|
+
operation.parameters,
|
|
247
|
+
isFileUpload
|
|
248
|
+
);
|
|
249
|
+
const { requestBodyParam, requestBodyPayload } = generateRequestBody(
|
|
250
|
+
operation.requestBody
|
|
251
|
+
);
|
|
227
252
|
const allParams = isFileUpload ? "file: File, options?: UploadOptions & { dirPath?: string, tags?: string[] }" : combineAllParams(parameters, requestBodyParam);
|
|
228
253
|
const responseType = generateResponseType(operation.responses);
|
|
229
254
|
const responseTypeStr = responseType ? `: Promise<AxiosResponse<${responseType}>>` : "";
|
|
@@ -241,13 +266,13 @@ function fileTemplate(tsString, typeForImport, baseURL) {
|
|
|
241
266
|
const templateCode = `import ax from 'axios';
|
|
242
267
|
import type { AxiosResponse } from 'axios';
|
|
243
268
|
import type {${typeForImport.join(", ")}} from './types.d';
|
|
244
|
-
|
|
269
|
+
|
|
245
270
|
interface UploadOptions {
|
|
246
271
|
onUploadProgress?: (progressEvent: any) => void
|
|
247
272
|
dirPath?: string
|
|
248
273
|
tags?: string[]
|
|
249
274
|
}
|
|
250
|
-
|
|
275
|
+
|
|
251
276
|
export const axios = ax.create({baseURL:${baseURL}});
|
|
252
277
|
${tsString}`;
|
|
253
278
|
const doubleQuoteRegex = /"([^"]+)":/g;
|
|
@@ -257,13 +282,19 @@ const functionsInventory = {};
|
|
|
257
282
|
const pathOperations = [];
|
|
258
283
|
function hasConflict(path, method) {
|
|
259
284
|
const cleanPathName = path.split("/").filter((p) => p && !/\{|\}/.test(p)).join("/");
|
|
260
|
-
const matchingPaths = pathOperations.filter(
|
|
285
|
+
const matchingPaths = pathOperations.filter(
|
|
286
|
+
(p) => p.path === cleanPathName && p.method === method
|
|
287
|
+
);
|
|
261
288
|
pathOperations.push({ path: cleanPathName, method });
|
|
262
289
|
return matchingPaths.length > 0;
|
|
263
290
|
}
|
|
264
291
|
function createFunctionPlaceholder(path, method, operation) {
|
|
265
292
|
const funcID = generateRandomString();
|
|
266
|
-
functionsInventory[funcID] = generateFunctionForOperation(
|
|
293
|
+
functionsInventory[funcID] = generateFunctionForOperation(
|
|
294
|
+
method,
|
|
295
|
+
path,
|
|
296
|
+
operation
|
|
297
|
+
);
|
|
267
298
|
return funcID;
|
|
268
299
|
}
|
|
269
300
|
function handlePathSegment(path, operation, existingObj = {}) {
|
|
@@ -275,7 +306,11 @@ function handlePathSegment(path, operation, existingObj = {}) {
|
|
|
275
306
|
const params = getParamsFromPath(path);
|
|
276
307
|
functionName += params ? `By${toPascalCase(params.pop() || "")}` : "All";
|
|
277
308
|
}
|
|
278
|
-
obj[functionName] = createFunctionPlaceholder(
|
|
309
|
+
obj[functionName] = createFunctionPlaceholder(
|
|
310
|
+
path,
|
|
311
|
+
method,
|
|
312
|
+
operation[method]
|
|
313
|
+
);
|
|
279
314
|
}
|
|
280
315
|
return { ...obj, ...existingObj };
|
|
281
316
|
}
|
|
@@ -287,8 +322,7 @@ function generateFunctions(paths, baseUrl) {
|
|
|
287
322
|
const splitPath = path.split("/").filter((p) => p && !/\{|\}/.test(p));
|
|
288
323
|
splitPath.reduce((acc, key, index, array) => {
|
|
289
324
|
const objFuncKey = toCamelCase(key);
|
|
290
|
-
if (!objFuncKey)
|
|
291
|
-
return acc;
|
|
325
|
+
if (!objFuncKey) return acc;
|
|
292
326
|
const methods = Object.keys(operation);
|
|
293
327
|
if (index === array.length - 1 && methods.length === 1 && allPathsClean.filter((p) => p === cleanPath(path)).length === 1) {
|
|
294
328
|
const method = methods[0];
|
|
@@ -303,7 +337,7 @@ function generateFunctions(paths, baseUrl) {
|
|
|
303
337
|
}, body);
|
|
304
338
|
}
|
|
305
339
|
for (const [parent, object] of Object.entries(body)) {
|
|
306
|
-
tsString += `export const ${parent} = ${JSON.stringify(object,
|
|
340
|
+
tsString += `export const ${parent} = ${JSON.stringify(object, undefined, 2)};
|
|
307
341
|
`;
|
|
308
342
|
}
|
|
309
343
|
Object.entries(functionsInventory).forEach(([key, value]) => {
|
|
@@ -320,10 +354,9 @@ function generateTypes(schemas) {
|
|
|
320
354
|
return `export type ${typeName} = ${schema.enum.map((item) => `'${item}'`).join(" | ")};
|
|
321
355
|
`;
|
|
322
356
|
}
|
|
323
|
-
if (!schema.properties)
|
|
324
|
-
return "";
|
|
357
|
+
if (!schema.properties) return "";
|
|
325
358
|
const properties = Object.entries(schema.properties).map(([key, value]) => {
|
|
326
|
-
const varType = formatVarType(key, value);
|
|
359
|
+
const varType = formatVarType({ varName: key, schema: value });
|
|
327
360
|
return ` ${varType}`;
|
|
328
361
|
}).join(";\n ");
|
|
329
362
|
return `export type ${typeName} = {
|
|
@@ -338,12 +371,10 @@ const index = async (openApiUrl, baseUrl) => {
|
|
|
338
371
|
try {
|
|
339
372
|
const { data: openApi } = await axios__default.get(openApiUrl, { headers: basicAuthHeader });
|
|
340
373
|
const schemas = openApi.components?.schemas;
|
|
341
|
-
if (!schemas)
|
|
342
|
-
throw new Error("No schemas found in OpenAPI document");
|
|
374
|
+
if (!schemas) throw new Error("No schemas found in OpenAPI document");
|
|
343
375
|
const types = generateTypes(schemas);
|
|
344
376
|
const { paths } = openApi;
|
|
345
|
-
if (!paths)
|
|
346
|
-
throw new Error("No paths found in OpenAPI document");
|
|
377
|
+
if (!paths) throw new Error("No paths found in OpenAPI document");
|
|
347
378
|
const code = generateFunctions(paths, baseUrl);
|
|
348
379
|
return { types, code };
|
|
349
380
|
} catch (error) {
|
|
@@ -351,28 +382,21 @@ const index = async (openApiUrl, baseUrl) => {
|
|
|
351
382
|
}
|
|
352
383
|
};
|
|
353
384
|
|
|
354
|
-
var __defProp = Object.defineProperty;
|
|
355
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
356
|
-
var __publicField = (obj, key, value) => {
|
|
357
|
-
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
358
|
-
return value;
|
|
359
|
-
};
|
|
360
385
|
const axios = axios__default.create({
|
|
361
386
|
withCredentials: true
|
|
362
387
|
});
|
|
363
388
|
class DataRequest {
|
|
389
|
+
data_table;
|
|
390
|
+
bagel;
|
|
391
|
+
itemID;
|
|
392
|
+
_filter = {};
|
|
364
393
|
constructor(table, bagel) {
|
|
365
|
-
__publicField(this, "data_table");
|
|
366
|
-
__publicField(this, "bagel");
|
|
367
|
-
__publicField(this, "itemID");
|
|
368
|
-
__publicField(this, "_filter", {});
|
|
369
394
|
this.data_table = table;
|
|
370
395
|
this.bagel = bagel;
|
|
371
396
|
this.itemID = "";
|
|
372
397
|
}
|
|
373
398
|
async post(item) {
|
|
374
|
-
if (!this.data_table)
|
|
375
|
-
throw new Error("Data table not set");
|
|
399
|
+
if (!this.data_table) throw new Error("Data table not set");
|
|
376
400
|
const { data } = await axios.post(`/data/${this.data_table}`, item);
|
|
377
401
|
return data;
|
|
378
402
|
}
|
|
@@ -381,8 +405,7 @@ class DataRequest {
|
|
|
381
405
|
return this;
|
|
382
406
|
}
|
|
383
407
|
async get() {
|
|
384
|
-
if (!this.data_table)
|
|
385
|
-
throw new Error("Data table not set");
|
|
408
|
+
if (!this.data_table) throw new Error("Data table not set");
|
|
386
409
|
const filterStr = Object.keys(this._filter).length > 0 ? `?filter={${Object.entries(this._filter).map(([k, v]) => `${k}:${v}`).join(",")}}` : "";
|
|
387
410
|
const url = `/data/${this.data_table}${this.itemID ? `/${this.itemID}` : ""}${filterStr}`;
|
|
388
411
|
try {
|
|
@@ -391,7 +414,7 @@ class DataRequest {
|
|
|
391
414
|
} catch (err) {
|
|
392
415
|
console.log(err);
|
|
393
416
|
this.bagel.onError?.(err);
|
|
394
|
-
return
|
|
417
|
+
return undefined;
|
|
395
418
|
}
|
|
396
419
|
}
|
|
397
420
|
item(id) {
|
|
@@ -399,8 +422,7 @@ class DataRequest {
|
|
|
399
422
|
return this;
|
|
400
423
|
}
|
|
401
424
|
async delete() {
|
|
402
|
-
if (!this.data_table)
|
|
403
|
-
throw new Error("Data table not set");
|
|
425
|
+
if (!this.data_table) throw new Error("Data table not set");
|
|
404
426
|
const { data } = await axios.delete(
|
|
405
427
|
`/data/${this.data_table}/${this.itemID}`
|
|
406
428
|
);
|
|
@@ -408,10 +430,8 @@ class DataRequest {
|
|
|
408
430
|
}
|
|
409
431
|
async put(updatedItem) {
|
|
410
432
|
const { data_table, itemID } = this;
|
|
411
|
-
if (!data_table)
|
|
412
|
-
|
|
413
|
-
if (!itemID)
|
|
414
|
-
throw new Error("Item ID not set");
|
|
433
|
+
if (!data_table) throw new Error("Data table not set");
|
|
434
|
+
if (!itemID) throw new Error("Item ID not set");
|
|
415
435
|
const { data } = await axios.put(
|
|
416
436
|
`/data/${data_table}/${itemID}`,
|
|
417
437
|
updatedItem
|
|
@@ -429,9 +449,9 @@ function responses(key) {
|
|
|
429
449
|
class BagelAuth {
|
|
430
450
|
constructor(bagel) {
|
|
431
451
|
this.bagel = bagel;
|
|
432
|
-
__publicField(this, "user");
|
|
433
452
|
this.bagel = bagel;
|
|
434
453
|
}
|
|
454
|
+
user = undefined;
|
|
435
455
|
async validateUser() {
|
|
436
456
|
try {
|
|
437
457
|
const { data: usr } = await axios.get("/users/me", {
|
|
@@ -479,7 +499,7 @@ class BagelAuth {
|
|
|
479
499
|
this.bagel.onError?.(err);
|
|
480
500
|
console.log(err);
|
|
481
501
|
}
|
|
482
|
-
this.user =
|
|
502
|
+
this.user = undefined;
|
|
483
503
|
}
|
|
484
504
|
async acceptInvite(token, user) {
|
|
485
505
|
await axios.post(`/auth/accept-invite/${token}`, user);
|
|
@@ -497,12 +517,10 @@ class BagelAuth {
|
|
|
497
517
|
}
|
|
498
518
|
}
|
|
499
519
|
class Bagel {
|
|
520
|
+
host;
|
|
521
|
+
fileBaseUrl;
|
|
522
|
+
onError;
|
|
500
523
|
constructor({ host, fileBaseUrl, onError }) {
|
|
501
|
-
__publicField(this, "host");
|
|
502
|
-
__publicField(this, "fileBaseUrl");
|
|
503
|
-
__publicField(this, "onError");
|
|
504
|
-
__publicField(this, "read_table");
|
|
505
|
-
__publicField(this, "auth", new BagelAuth(this));
|
|
506
524
|
this.host = host?.replace(/\/$/, "");
|
|
507
525
|
this.fileBaseUrl = fileBaseUrl?.replace(/\/$/, "");
|
|
508
526
|
if (!this.host) {
|
|
@@ -511,9 +529,11 @@ class Bagel {
|
|
|
511
529
|
axios.defaults.baseURL = this.host;
|
|
512
530
|
this.onError = onError;
|
|
513
531
|
}
|
|
532
|
+
read_table = undefined;
|
|
514
533
|
data(table) {
|
|
515
534
|
return new DataRequest(table, this);
|
|
516
535
|
}
|
|
536
|
+
auth = new BagelAuth(this);
|
|
517
537
|
_endpointCleaner(endpoint) {
|
|
518
538
|
const url = `${endpoint.replace(/^\//, "").replaceAll(/\/$/g, "")}`;
|
|
519
539
|
return url;
|
|
@@ -528,12 +548,10 @@ class Bagel {
|
|
|
528
548
|
async get(endpoint, query) {
|
|
529
549
|
this._setAuthorization();
|
|
530
550
|
endpoint = this._endpointCleaner(endpoint);
|
|
531
|
-
if (/undefined|null/.test(endpoint))
|
|
532
|
-
throw new Error(`Invalid endpoint: ${endpoint}`);
|
|
551
|
+
if (/undefined|null/.test(endpoint)) throw new Error(`Invalid endpoint: ${endpoint}`);
|
|
533
552
|
if (query) {
|
|
534
553
|
const queryParams = Object.entries(query).filter(([_, value]) => !!value).map(([key, value]) => `${key}=${value}`).join("&");
|
|
535
|
-
if (queryParams)
|
|
536
|
-
endpoint = `${endpoint}?${queryParams}`;
|
|
554
|
+
if (queryParams) endpoint = `${endpoint}?${queryParams}`;
|
|
537
555
|
}
|
|
538
556
|
const url = `/${endpoint}`;
|
|
539
557
|
return axios.get(url).then(({ data }) => data).catch((err) => {
|
|
@@ -583,8 +601,7 @@ class Bagel {
|
|
|
583
601
|
const formData = new FormData();
|
|
584
602
|
formData.append("file", file);
|
|
585
603
|
let url = "/static_files/upload";
|
|
586
|
-
if (options?.topic)
|
|
587
|
-
url = `/static_files/upload?topic=${options.topic}`;
|
|
604
|
+
if (options?.topic) url = `/static_files/upload?topic=${options.topic}`;
|
|
588
605
|
const { data } = await axios.post(url, formData, {
|
|
589
606
|
headers: {
|
|
590
607
|
"Content-Type": "multipart/form-data"
|
package/dist/index.mjs
CHANGED
|
@@ -1,30 +1,31 @@
|
|
|
1
1
|
import axios$1 from 'axios';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
function toCamelCase(str) {
|
|
4
|
+
return str?.replaceAll(/[-._\s]+(.)?/g, (_, c) => c?.toUpperCase() || "").replace(/^./, (str2) => str2.toLowerCase()) || str || "";
|
|
5
|
+
}
|
|
6
|
+
function toPascalCase(str) {
|
|
7
|
+
return str?.replaceAll(/[-_\s]+(.)?/g, (_, c) => c?.toUpperCase() || "").replace(/^./, (str2) => str2.toUpperCase()) || str || "";
|
|
8
|
+
}
|
|
5
9
|
function formatType(typeName) {
|
|
6
|
-
typeName = typeName.replaceAll("-", "").replaceAll(/
|
|
10
|
+
typeName = typeName.replaceAll("-", "").replaceAll(/post|put$/gi, "").replaceAll(/^body_/gi, "");
|
|
7
11
|
return toPascalCase(typeName);
|
|
8
12
|
}
|
|
9
13
|
function resolveReference(ref) {
|
|
10
14
|
const t = ref.split("/").pop();
|
|
11
|
-
if (!t)
|
|
12
|
-
return "any";
|
|
15
|
+
if (!t) return "any";
|
|
13
16
|
return formatType(t);
|
|
14
17
|
}
|
|
15
18
|
function schemaToType(schema) {
|
|
16
|
-
if (!schema)
|
|
17
|
-
return "any";
|
|
19
|
+
if (!schema) return "any";
|
|
18
20
|
if (schema.anyOf) {
|
|
19
21
|
let _t = schema.anyOf.map((s) => schemaToType(s)).filter((p) => p !== "any").join(" | ");
|
|
20
|
-
if (_t === "" || _t === "null")
|
|
21
|
-
_t = "any";
|
|
22
|
+
if (_t === "" || _t === "null") _t = "any";
|
|
22
23
|
return _t;
|
|
23
24
|
}
|
|
24
|
-
if (schema.allOf)
|
|
25
|
+
if (schema.allOf) {
|
|
25
26
|
return schema.allOf.map((s) => schemaToType(s)).filter((p) => p !== "any").join(" & ");
|
|
26
|
-
|
|
27
|
-
|
|
27
|
+
}
|
|
28
|
+
if (schema.$ref) return resolveReference(schema.$ref);
|
|
28
29
|
switch (schema.type) {
|
|
29
30
|
case "object":
|
|
30
31
|
return "{ [key: string]: any }";
|
|
@@ -42,7 +43,7 @@ function schemaToType(schema) {
|
|
|
42
43
|
return "undefined";
|
|
43
44
|
case "null":
|
|
44
45
|
return "null";
|
|
45
|
-
case
|
|
46
|
+
case undefined:
|
|
46
47
|
return "any";
|
|
47
48
|
default:
|
|
48
49
|
console.log("Unknown type", schema.type);
|
|
@@ -54,10 +55,17 @@ function isOptional(schema) {
|
|
|
54
55
|
const splitType = type.split(/\s+\|\s+/);
|
|
55
56
|
const includesNull = splitType.includes("null");
|
|
56
57
|
const includesUndefined = splitType.includes("undefined");
|
|
57
|
-
return includesNull || includesUndefined || schema.default !==
|
|
58
|
+
return includesNull || includesUndefined || schema.default !== undefined;
|
|
58
59
|
}
|
|
59
|
-
|
|
60
|
-
|
|
60
|
+
function cleanOptionals(str) {
|
|
61
|
+
return str.split(" | ").filter((t) => t !== "null" && t !== "undefined").join(" | ");
|
|
62
|
+
}
|
|
63
|
+
function formatVarType({
|
|
64
|
+
varName,
|
|
65
|
+
schema,
|
|
66
|
+
required = false,
|
|
67
|
+
defaultValue
|
|
68
|
+
}) {
|
|
61
69
|
let type = schemaToType(schema);
|
|
62
70
|
type = cleanOptionals(type);
|
|
63
71
|
let defaultStr = "";
|
|
@@ -68,9 +76,8 @@ function formatVarType(varName, schema, required = false, defaultValue) {
|
|
|
68
76
|
defaultStr = ` = ${defaultValue}`;
|
|
69
77
|
}
|
|
70
78
|
}
|
|
71
|
-
let optionalStr = required
|
|
72
|
-
if (defaultStr)
|
|
73
|
-
optionalStr = "";
|
|
79
|
+
let optionalStr = !required && isOptional(schema) ? "?" : "";
|
|
80
|
+
if (defaultStr) optionalStr = "";
|
|
74
81
|
return `${varName}${optionalStr}: ${type}${defaultStr}`;
|
|
75
82
|
}
|
|
76
83
|
function cleanPath(path) {
|
|
@@ -78,35 +85,39 @@ function cleanPath(path) {
|
|
|
78
85
|
}
|
|
79
86
|
|
|
80
87
|
const allTypes = [];
|
|
81
|
-
const primitiveTypes = [
|
|
88
|
+
const primitiveTypes = [
|
|
89
|
+
"string",
|
|
90
|
+
"number",
|
|
91
|
+
"boolean",
|
|
92
|
+
"null",
|
|
93
|
+
"void",
|
|
94
|
+
"any",
|
|
95
|
+
"Record<string, any>",
|
|
96
|
+
"undefined",
|
|
97
|
+
"{ [key: string]: any }"
|
|
98
|
+
];
|
|
82
99
|
function collectTypeForImportStatement(typeName) {
|
|
83
100
|
typeName = typeName.trim().replace("[]", "");
|
|
84
101
|
if (typeName.includes("|")) {
|
|
85
|
-
typeName.split("|").forEach(
|
|
86
|
-
(singleType)
|
|
87
|
-
|
|
88
|
-
}
|
|
89
|
-
);
|
|
102
|
+
typeName.split("|").forEach((singleType) => {
|
|
103
|
+
collectTypeForImportStatement(singleType);
|
|
104
|
+
});
|
|
90
105
|
return;
|
|
91
106
|
}
|
|
92
107
|
const isPrimitive = primitiveTypes.includes(typeName);
|
|
93
108
|
typeName = formatType(typeName);
|
|
94
|
-
if (!typeName || isPrimitive)
|
|
95
|
-
|
|
96
|
-
if (!allTypes.includes(typeName))
|
|
97
|
-
allTypes.push(typeName);
|
|
109
|
+
if (!typeName || isPrimitive) return;
|
|
110
|
+
if (!allTypes.includes(typeName)) allTypes.push(typeName);
|
|
98
111
|
}
|
|
99
112
|
function getResponseType(response) {
|
|
100
113
|
const mediaTypeObject = response.content?.["application/json"];
|
|
101
|
-
if (!mediaTypeObject || !mediaTypeObject.schema)
|
|
102
|
-
return;
|
|
114
|
+
if (!mediaTypeObject || !mediaTypeObject.schema) return;
|
|
103
115
|
const responseType = schemaToType(mediaTypeObject.schema);
|
|
104
116
|
collectTypeForImportStatement(responseType);
|
|
105
117
|
return responseType;
|
|
106
118
|
}
|
|
107
119
|
function generateResponseType(responses) {
|
|
108
|
-
if (!responses)
|
|
109
|
-
return "";
|
|
120
|
+
if (!responses) return "";
|
|
110
121
|
const types = [];
|
|
111
122
|
for (const [statusCode, response] of Object.entries(responses)) {
|
|
112
123
|
if (statusCode.startsWith("2")) {
|
|
@@ -119,8 +130,7 @@ function generateResponseType(responses) {
|
|
|
119
130
|
return types.join(" | ");
|
|
120
131
|
}
|
|
121
132
|
function generateAxiosFunction(method, formattedPath, allParams, responseTypeStr, parameters, requestBodyPayload) {
|
|
122
|
-
if (allParams === "undefined")
|
|
123
|
-
allParams = "";
|
|
133
|
+
if (allParams === "undefined") allParams = "";
|
|
124
134
|
let axiosFunction = `async (${allParams})${responseTypeStr} => {`;
|
|
125
135
|
if (requestBodyPayload === "formData") {
|
|
126
136
|
const paramStr = parameters?.config?.params ? `params: {${parameters.config.params}}` : "";
|
|
@@ -169,21 +179,23 @@ function generateRequestBody(requestBody) {
|
|
|
169
179
|
const requestBodyType = schemaToType(bodySchema);
|
|
170
180
|
collectTypeForImportStatement(requestBodyType);
|
|
171
181
|
const requestBodyPayload = toCamelCase(bodySchema.title) || toCamelCase(requestBodyType) || "requestBody";
|
|
172
|
-
const requestBodyParam = formatVarType(
|
|
182
|
+
const requestBodyParam = formatVarType({
|
|
183
|
+
varName: requestBodyPayload,
|
|
184
|
+
schema: bodySchema,
|
|
185
|
+
defaultValue: bodySchema.default
|
|
186
|
+
});
|
|
173
187
|
return { requestBodyParam, requestBodyPayload };
|
|
174
188
|
}
|
|
175
189
|
function combineAllParams(parameters, requestBodyParam) {
|
|
176
190
|
let allParamsArray = [];
|
|
177
191
|
if (parameters && parameters.params)
|
|
178
192
|
allParamsArray = parameters.params.split(",").map((p) => p.trim());
|
|
179
|
-
if (requestBodyParam)
|
|
180
|
-
allParamsArray.push(requestBodyParam.trim());
|
|
193
|
+
if (requestBodyParam) allParamsArray.push(requestBodyParam.trim());
|
|
181
194
|
allParamsArray = allParamsArray.filter((p) => p).sort((a, b) => (a.includes("?") ? 1 : -1) - (b.includes("?") ? 1 : -1));
|
|
182
195
|
return allParamsArray.join(", ");
|
|
183
196
|
}
|
|
184
197
|
function generateFunctionParameters(params, isFileUpload = false) {
|
|
185
|
-
if (!params?.length)
|
|
186
|
-
return {};
|
|
198
|
+
if (!params?.length) return {};
|
|
187
199
|
if (isFileUpload) {
|
|
188
200
|
return {
|
|
189
201
|
config: {
|
|
@@ -201,10 +213,19 @@ function generateFunctionParameters(params, isFileUpload = false) {
|
|
|
201
213
|
const paramName = param.name;
|
|
202
214
|
const varName = toCamelCase(param.name);
|
|
203
215
|
if (param.in === "path" || param.in === "query" || param.in === "header") {
|
|
204
|
-
functionParams.push(
|
|
216
|
+
functionParams.push(
|
|
217
|
+
formatVarType({
|
|
218
|
+
varName,
|
|
219
|
+
schema: param.schema,
|
|
220
|
+
required: param.required,
|
|
221
|
+
defaultValue: param.schema.default
|
|
222
|
+
})
|
|
223
|
+
);
|
|
205
224
|
}
|
|
206
225
|
if (param.in === "query" || param.in === "header") {
|
|
207
|
-
paramList.push(
|
|
226
|
+
paramList.push(
|
|
227
|
+
paramName === varName ? paramName : `'${paramName}': ${varName}`
|
|
228
|
+
);
|
|
208
229
|
}
|
|
209
230
|
}
|
|
210
231
|
return {
|
|
@@ -213,11 +234,15 @@ function generateFunctionParameters(params, isFileUpload = false) {
|
|
|
213
234
|
};
|
|
214
235
|
}
|
|
215
236
|
function generateFunctionForOperation(method, path, operation) {
|
|
216
|
-
if (!operation)
|
|
217
|
-
return "";
|
|
237
|
+
if (!operation) return "";
|
|
218
238
|
const isFileUpload = operation.requestBody?.content["multipart/form-data"]?.schema?.$ref?.includes("Body_upload_files");
|
|
219
|
-
const parameters = generateFunctionParameters(
|
|
220
|
-
|
|
239
|
+
const parameters = generateFunctionParameters(
|
|
240
|
+
operation.parameters,
|
|
241
|
+
isFileUpload
|
|
242
|
+
);
|
|
243
|
+
const { requestBodyParam, requestBodyPayload } = generateRequestBody(
|
|
244
|
+
operation.requestBody
|
|
245
|
+
);
|
|
221
246
|
const allParams = isFileUpload ? "file: File, options?: UploadOptions & { dirPath?: string, tags?: string[] }" : combineAllParams(parameters, requestBodyParam);
|
|
222
247
|
const responseType = generateResponseType(operation.responses);
|
|
223
248
|
const responseTypeStr = responseType ? `: Promise<AxiosResponse<${responseType}>>` : "";
|
|
@@ -235,13 +260,13 @@ function fileTemplate(tsString, typeForImport, baseURL) {
|
|
|
235
260
|
const templateCode = `import ax from 'axios';
|
|
236
261
|
import type { AxiosResponse } from 'axios';
|
|
237
262
|
import type {${typeForImport.join(", ")}} from './types.d';
|
|
238
|
-
|
|
263
|
+
|
|
239
264
|
interface UploadOptions {
|
|
240
265
|
onUploadProgress?: (progressEvent: any) => void
|
|
241
266
|
dirPath?: string
|
|
242
267
|
tags?: string[]
|
|
243
268
|
}
|
|
244
|
-
|
|
269
|
+
|
|
245
270
|
export const axios = ax.create({baseURL:${baseURL}});
|
|
246
271
|
${tsString}`;
|
|
247
272
|
const doubleQuoteRegex = /"([^"]+)":/g;
|
|
@@ -251,13 +276,19 @@ const functionsInventory = {};
|
|
|
251
276
|
const pathOperations = [];
|
|
252
277
|
function hasConflict(path, method) {
|
|
253
278
|
const cleanPathName = path.split("/").filter((p) => p && !/\{|\}/.test(p)).join("/");
|
|
254
|
-
const matchingPaths = pathOperations.filter(
|
|
279
|
+
const matchingPaths = pathOperations.filter(
|
|
280
|
+
(p) => p.path === cleanPathName && p.method === method
|
|
281
|
+
);
|
|
255
282
|
pathOperations.push({ path: cleanPathName, method });
|
|
256
283
|
return matchingPaths.length > 0;
|
|
257
284
|
}
|
|
258
285
|
function createFunctionPlaceholder(path, method, operation) {
|
|
259
286
|
const funcID = generateRandomString();
|
|
260
|
-
functionsInventory[funcID] = generateFunctionForOperation(
|
|
287
|
+
functionsInventory[funcID] = generateFunctionForOperation(
|
|
288
|
+
method,
|
|
289
|
+
path,
|
|
290
|
+
operation
|
|
291
|
+
);
|
|
261
292
|
return funcID;
|
|
262
293
|
}
|
|
263
294
|
function handlePathSegment(path, operation, existingObj = {}) {
|
|
@@ -269,7 +300,11 @@ function handlePathSegment(path, operation, existingObj = {}) {
|
|
|
269
300
|
const params = getParamsFromPath(path);
|
|
270
301
|
functionName += params ? `By${toPascalCase(params.pop() || "")}` : "All";
|
|
271
302
|
}
|
|
272
|
-
obj[functionName] = createFunctionPlaceholder(
|
|
303
|
+
obj[functionName] = createFunctionPlaceholder(
|
|
304
|
+
path,
|
|
305
|
+
method,
|
|
306
|
+
operation[method]
|
|
307
|
+
);
|
|
273
308
|
}
|
|
274
309
|
return { ...obj, ...existingObj };
|
|
275
310
|
}
|
|
@@ -281,8 +316,7 @@ function generateFunctions(paths, baseUrl) {
|
|
|
281
316
|
const splitPath = path.split("/").filter((p) => p && !/\{|\}/.test(p));
|
|
282
317
|
splitPath.reduce((acc, key, index, array) => {
|
|
283
318
|
const objFuncKey = toCamelCase(key);
|
|
284
|
-
if (!objFuncKey)
|
|
285
|
-
return acc;
|
|
319
|
+
if (!objFuncKey) return acc;
|
|
286
320
|
const methods = Object.keys(operation);
|
|
287
321
|
if (index === array.length - 1 && methods.length === 1 && allPathsClean.filter((p) => p === cleanPath(path)).length === 1) {
|
|
288
322
|
const method = methods[0];
|
|
@@ -297,7 +331,7 @@ function generateFunctions(paths, baseUrl) {
|
|
|
297
331
|
}, body);
|
|
298
332
|
}
|
|
299
333
|
for (const [parent, object] of Object.entries(body)) {
|
|
300
|
-
tsString += `export const ${parent} = ${JSON.stringify(object,
|
|
334
|
+
tsString += `export const ${parent} = ${JSON.stringify(object, undefined, 2)};
|
|
301
335
|
`;
|
|
302
336
|
}
|
|
303
337
|
Object.entries(functionsInventory).forEach(([key, value]) => {
|
|
@@ -314,10 +348,9 @@ function generateTypes(schemas) {
|
|
|
314
348
|
return `export type ${typeName} = ${schema.enum.map((item) => `'${item}'`).join(" | ")};
|
|
315
349
|
`;
|
|
316
350
|
}
|
|
317
|
-
if (!schema.properties)
|
|
318
|
-
return "";
|
|
351
|
+
if (!schema.properties) return "";
|
|
319
352
|
const properties = Object.entries(schema.properties).map(([key, value]) => {
|
|
320
|
-
const varType = formatVarType(key, value);
|
|
353
|
+
const varType = formatVarType({ varName: key, schema: value });
|
|
321
354
|
return ` ${varType}`;
|
|
322
355
|
}).join(";\n ");
|
|
323
356
|
return `export type ${typeName} = {
|
|
@@ -332,12 +365,10 @@ const index = async (openApiUrl, baseUrl) => {
|
|
|
332
365
|
try {
|
|
333
366
|
const { data: openApi } = await axios$1.get(openApiUrl, { headers: basicAuthHeader });
|
|
334
367
|
const schemas = openApi.components?.schemas;
|
|
335
|
-
if (!schemas)
|
|
336
|
-
throw new Error("No schemas found in OpenAPI document");
|
|
368
|
+
if (!schemas) throw new Error("No schemas found in OpenAPI document");
|
|
337
369
|
const types = generateTypes(schemas);
|
|
338
370
|
const { paths } = openApi;
|
|
339
|
-
if (!paths)
|
|
340
|
-
throw new Error("No paths found in OpenAPI document");
|
|
371
|
+
if (!paths) throw new Error("No paths found in OpenAPI document");
|
|
341
372
|
const code = generateFunctions(paths, baseUrl);
|
|
342
373
|
return { types, code };
|
|
343
374
|
} catch (error) {
|
|
@@ -345,28 +376,21 @@ const index = async (openApiUrl, baseUrl) => {
|
|
|
345
376
|
}
|
|
346
377
|
};
|
|
347
378
|
|
|
348
|
-
var __defProp = Object.defineProperty;
|
|
349
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
350
|
-
var __publicField = (obj, key, value) => {
|
|
351
|
-
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
352
|
-
return value;
|
|
353
|
-
};
|
|
354
379
|
const axios = axios$1.create({
|
|
355
380
|
withCredentials: true
|
|
356
381
|
});
|
|
357
382
|
class DataRequest {
|
|
383
|
+
data_table;
|
|
384
|
+
bagel;
|
|
385
|
+
itemID;
|
|
386
|
+
_filter = {};
|
|
358
387
|
constructor(table, bagel) {
|
|
359
|
-
__publicField(this, "data_table");
|
|
360
|
-
__publicField(this, "bagel");
|
|
361
|
-
__publicField(this, "itemID");
|
|
362
|
-
__publicField(this, "_filter", {});
|
|
363
388
|
this.data_table = table;
|
|
364
389
|
this.bagel = bagel;
|
|
365
390
|
this.itemID = "";
|
|
366
391
|
}
|
|
367
392
|
async post(item) {
|
|
368
|
-
if (!this.data_table)
|
|
369
|
-
throw new Error("Data table not set");
|
|
393
|
+
if (!this.data_table) throw new Error("Data table not set");
|
|
370
394
|
const { data } = await axios.post(`/data/${this.data_table}`, item);
|
|
371
395
|
return data;
|
|
372
396
|
}
|
|
@@ -375,8 +399,7 @@ class DataRequest {
|
|
|
375
399
|
return this;
|
|
376
400
|
}
|
|
377
401
|
async get() {
|
|
378
|
-
if (!this.data_table)
|
|
379
|
-
throw new Error("Data table not set");
|
|
402
|
+
if (!this.data_table) throw new Error("Data table not set");
|
|
380
403
|
const filterStr = Object.keys(this._filter).length > 0 ? `?filter={${Object.entries(this._filter).map(([k, v]) => `${k}:${v}`).join(",")}}` : "";
|
|
381
404
|
const url = `/data/${this.data_table}${this.itemID ? `/${this.itemID}` : ""}${filterStr}`;
|
|
382
405
|
try {
|
|
@@ -385,7 +408,7 @@ class DataRequest {
|
|
|
385
408
|
} catch (err) {
|
|
386
409
|
console.log(err);
|
|
387
410
|
this.bagel.onError?.(err);
|
|
388
|
-
return
|
|
411
|
+
return undefined;
|
|
389
412
|
}
|
|
390
413
|
}
|
|
391
414
|
item(id) {
|
|
@@ -393,8 +416,7 @@ class DataRequest {
|
|
|
393
416
|
return this;
|
|
394
417
|
}
|
|
395
418
|
async delete() {
|
|
396
|
-
if (!this.data_table)
|
|
397
|
-
throw new Error("Data table not set");
|
|
419
|
+
if (!this.data_table) throw new Error("Data table not set");
|
|
398
420
|
const { data } = await axios.delete(
|
|
399
421
|
`/data/${this.data_table}/${this.itemID}`
|
|
400
422
|
);
|
|
@@ -402,10 +424,8 @@ class DataRequest {
|
|
|
402
424
|
}
|
|
403
425
|
async put(updatedItem) {
|
|
404
426
|
const { data_table, itemID } = this;
|
|
405
|
-
if (!data_table)
|
|
406
|
-
|
|
407
|
-
if (!itemID)
|
|
408
|
-
throw new Error("Item ID not set");
|
|
427
|
+
if (!data_table) throw new Error("Data table not set");
|
|
428
|
+
if (!itemID) throw new Error("Item ID not set");
|
|
409
429
|
const { data } = await axios.put(
|
|
410
430
|
`/data/${data_table}/${itemID}`,
|
|
411
431
|
updatedItem
|
|
@@ -423,9 +443,9 @@ function responses(key) {
|
|
|
423
443
|
class BagelAuth {
|
|
424
444
|
constructor(bagel) {
|
|
425
445
|
this.bagel = bagel;
|
|
426
|
-
__publicField(this, "user");
|
|
427
446
|
this.bagel = bagel;
|
|
428
447
|
}
|
|
448
|
+
user = undefined;
|
|
429
449
|
async validateUser() {
|
|
430
450
|
try {
|
|
431
451
|
const { data: usr } = await axios.get("/users/me", {
|
|
@@ -473,7 +493,7 @@ class BagelAuth {
|
|
|
473
493
|
this.bagel.onError?.(err);
|
|
474
494
|
console.log(err);
|
|
475
495
|
}
|
|
476
|
-
this.user =
|
|
496
|
+
this.user = undefined;
|
|
477
497
|
}
|
|
478
498
|
async acceptInvite(token, user) {
|
|
479
499
|
await axios.post(`/auth/accept-invite/${token}`, user);
|
|
@@ -491,12 +511,10 @@ class BagelAuth {
|
|
|
491
511
|
}
|
|
492
512
|
}
|
|
493
513
|
class Bagel {
|
|
514
|
+
host;
|
|
515
|
+
fileBaseUrl;
|
|
516
|
+
onError;
|
|
494
517
|
constructor({ host, fileBaseUrl, onError }) {
|
|
495
|
-
__publicField(this, "host");
|
|
496
|
-
__publicField(this, "fileBaseUrl");
|
|
497
|
-
__publicField(this, "onError");
|
|
498
|
-
__publicField(this, "read_table");
|
|
499
|
-
__publicField(this, "auth", new BagelAuth(this));
|
|
500
518
|
this.host = host?.replace(/\/$/, "");
|
|
501
519
|
this.fileBaseUrl = fileBaseUrl?.replace(/\/$/, "");
|
|
502
520
|
if (!this.host) {
|
|
@@ -505,9 +523,11 @@ class Bagel {
|
|
|
505
523
|
axios.defaults.baseURL = this.host;
|
|
506
524
|
this.onError = onError;
|
|
507
525
|
}
|
|
526
|
+
read_table = undefined;
|
|
508
527
|
data(table) {
|
|
509
528
|
return new DataRequest(table, this);
|
|
510
529
|
}
|
|
530
|
+
auth = new BagelAuth(this);
|
|
511
531
|
_endpointCleaner(endpoint) {
|
|
512
532
|
const url = `${endpoint.replace(/^\//, "").replaceAll(/\/$/g, "")}`;
|
|
513
533
|
return url;
|
|
@@ -522,12 +542,10 @@ class Bagel {
|
|
|
522
542
|
async get(endpoint, query) {
|
|
523
543
|
this._setAuthorization();
|
|
524
544
|
endpoint = this._endpointCleaner(endpoint);
|
|
525
|
-
if (/undefined|null/.test(endpoint))
|
|
526
|
-
throw new Error(`Invalid endpoint: ${endpoint}`);
|
|
545
|
+
if (/undefined|null/.test(endpoint)) throw new Error(`Invalid endpoint: ${endpoint}`);
|
|
527
546
|
if (query) {
|
|
528
547
|
const queryParams = Object.entries(query).filter(([_, value]) => !!value).map(([key, value]) => `${key}=${value}`).join("&");
|
|
529
|
-
if (queryParams)
|
|
530
|
-
endpoint = `${endpoint}?${queryParams}`;
|
|
548
|
+
if (queryParams) endpoint = `${endpoint}?${queryParams}`;
|
|
531
549
|
}
|
|
532
550
|
const url = `/${endpoint}`;
|
|
533
551
|
return axios.get(url).then(({ data }) => data).catch((err) => {
|
|
@@ -577,8 +595,7 @@ class Bagel {
|
|
|
577
595
|
const formData = new FormData();
|
|
578
596
|
formData.append("file", file);
|
|
579
597
|
let url = "/static_files/upload";
|
|
580
|
-
if (options?.topic)
|
|
581
|
-
url = `/static_files/upload?topic=${options.topic}`;
|
|
598
|
+
if (options?.topic) url = `/static_files/upload?topic=${options.topic}`;
|
|
582
599
|
const { data } = await axios.post(url, formData, {
|
|
583
600
|
headers: {
|
|
584
601
|
"Content-Type": "multipart/form-data"
|
package/package.json
CHANGED
|
@@ -18,14 +18,24 @@ import {
|
|
|
18
18
|
|
|
19
19
|
const allTypes: string[] = []
|
|
20
20
|
|
|
21
|
-
const primitiveTypes = [
|
|
21
|
+
const primitiveTypes = [
|
|
22
|
+
'string',
|
|
23
|
+
'number',
|
|
24
|
+
'boolean',
|
|
25
|
+
'null',
|
|
26
|
+
'void',
|
|
27
|
+
'any',
|
|
28
|
+
'Record<string, any>',
|
|
29
|
+
'undefined',
|
|
30
|
+
'{ [key: string]: any }',
|
|
31
|
+
]
|
|
22
32
|
|
|
23
33
|
function collectTypeForImportStatement(typeName: string) {
|
|
24
34
|
typeName = typeName.trim().replace('[]', '')
|
|
25
35
|
if (typeName.includes('|')) {
|
|
26
|
-
typeName.split('|').forEach(
|
|
27
|
-
|
|
28
|
-
)
|
|
36
|
+
typeName.split('|').forEach((singleType) => {
|
|
37
|
+
collectTypeForImportStatement(singleType)
|
|
38
|
+
})
|
|
29
39
|
return
|
|
30
40
|
}
|
|
31
41
|
const isPrimitive = primitiveTypes.includes(typeName)
|
|
@@ -73,7 +83,7 @@ function generateAxiosFunction(
|
|
|
73
83
|
allParams: string,
|
|
74
84
|
responseTypeStr: string,
|
|
75
85
|
parameters: any,
|
|
76
|
-
requestBodyPayload: string
|
|
86
|
+
requestBodyPayload: string
|
|
77
87
|
): string {
|
|
78
88
|
if (allParams === 'undefined') allParams = ''
|
|
79
89
|
|
|
@@ -92,7 +102,9 @@ function generateAxiosFunction(
|
|
|
92
102
|
onUploadProgress: options?.onUploadProgress${paramStr ? `,\n ${paramStr}` : ''}
|
|
93
103
|
})`
|
|
94
104
|
} else {
|
|
95
|
-
const paramStr = parameters?.config?.params
|
|
105
|
+
const paramStr = parameters?.config?.params
|
|
106
|
+
? `, { params: {${parameters.config.params}} }`
|
|
107
|
+
: ''
|
|
96
108
|
const bodyVar = requestBodyPayload ? `${requestBodyPayload}` : '{}'
|
|
97
109
|
axiosFunction += `return axios.${method}(${formattedPath}${['get', 'delete'].includes(method) ? paramStr : `, ${bodyVar}${paramStr}`})`
|
|
98
110
|
}
|
|
@@ -110,19 +122,25 @@ function getParamsFromPath(path: string) {
|
|
|
110
122
|
|
|
111
123
|
function formatPathWithParams(path: string) {
|
|
112
124
|
const params = getParamsFromPath(path)
|
|
113
|
-
const formattedPath = params
|
|
125
|
+
const formattedPath = params
|
|
126
|
+
? `\`${path.replace(pathParamRegex, v => `$${toCamelCase(v)}`)}\``
|
|
127
|
+
: `'${path}'`
|
|
114
128
|
return formattedPath
|
|
115
129
|
}
|
|
116
130
|
|
|
117
|
-
function generateRequestBody(requestBody?: RequestBodyObject): {
|
|
118
|
-
|
|
131
|
+
function generateRequestBody(requestBody?: RequestBodyObject): {
|
|
132
|
+
[key: string]: string
|
|
133
|
+
} {
|
|
134
|
+
if (!requestBody?.content)
|
|
135
|
+
return { requestBodyParam: '', requestBodyPayload: '' }
|
|
119
136
|
|
|
120
137
|
const { content } = requestBody
|
|
121
138
|
const multipartFormData = content['multipart/form-data'] || {}
|
|
122
139
|
if (multipartFormData.schema?.$ref?.includes('Body_upload_files')) {
|
|
123
140
|
return {
|
|
124
|
-
requestBodyParam:
|
|
125
|
-
|
|
141
|
+
requestBodyParam:
|
|
142
|
+
'file: File, options?: UploadOptions & { dirPath?: string, tags?: string[] }',
|
|
143
|
+
requestBodyPayload: 'formData',
|
|
126
144
|
}
|
|
127
145
|
}
|
|
128
146
|
|
|
@@ -135,8 +153,16 @@ function generateRequestBody(requestBody?: RequestBodyObject): { [key: string]:
|
|
|
135
153
|
const bodySchema = jsonContent.schema
|
|
136
154
|
const requestBodyType = schemaToType(bodySchema)
|
|
137
155
|
collectTypeForImportStatement(requestBodyType)
|
|
138
|
-
const requestBodyPayload
|
|
139
|
-
|
|
156
|
+
const requestBodyPayload
|
|
157
|
+
= toCamelCase(bodySchema.title)
|
|
158
|
+
|| toCamelCase(requestBodyType)
|
|
159
|
+
|| 'requestBody'
|
|
160
|
+
|
|
161
|
+
const requestBodyParam = formatVarType({
|
|
162
|
+
varName: requestBodyPayload,
|
|
163
|
+
schema: bodySchema,
|
|
164
|
+
defaultValue: bodySchema.default,
|
|
165
|
+
})
|
|
140
166
|
return { requestBodyParam, requestBodyPayload }
|
|
141
167
|
}
|
|
142
168
|
|
|
@@ -146,9 +172,13 @@ function generateRequestBody(requestBody?: RequestBodyObject): { [key: string]:
|
|
|
146
172
|
* @param requestBodyParam - The parameter representing the request body.
|
|
147
173
|
* @returns A string representing all combined parameters.
|
|
148
174
|
*/
|
|
149
|
-
function combineAllParams(
|
|
175
|
+
function combineAllParams(
|
|
176
|
+
parameters: { params?: string },
|
|
177
|
+
requestBodyParam: string
|
|
178
|
+
): string {
|
|
150
179
|
let allParamsArray: string[] = []
|
|
151
|
-
if (parameters && parameters.params)
|
|
180
|
+
if (parameters && parameters.params)
|
|
181
|
+
allParamsArray = parameters.params.split(',').map(p => p.trim())
|
|
152
182
|
if (requestBodyParam) allParamsArray.push(requestBodyParam.trim())
|
|
153
183
|
|
|
154
184
|
allParamsArray = allParamsArray
|
|
@@ -158,7 +188,10 @@ function combineAllParams(parameters: { params?: string }, requestBodyParam: str
|
|
|
158
188
|
return allParamsArray.join(', ')
|
|
159
189
|
}
|
|
160
190
|
|
|
161
|
-
function generateFunctionParameters(
|
|
191
|
+
function generateFunctionParameters(
|
|
192
|
+
params?: ParameterObject[],
|
|
193
|
+
isFileUpload = false
|
|
194
|
+
) {
|
|
162
195
|
if (!params?.length) return {}
|
|
163
196
|
|
|
164
197
|
// For file uploads, we want to handle query parameters differently
|
|
@@ -166,9 +199,9 @@ function generateFunctionParameters(params?: ParameterObject[], isFileUpload = f
|
|
|
166
199
|
// Don't include these as function parameters, they'll be part of options
|
|
167
200
|
return {
|
|
168
201
|
config: {
|
|
169
|
-
params: 'dir_path: options?.dirPath, tags: options?.tags'
|
|
202
|
+
params: 'dir_path: options?.dirPath, tags: options?.tags',
|
|
170
203
|
},
|
|
171
|
-
params: '' // Empty string to ensure file is the first parameter
|
|
204
|
+
params: '', // Empty string to ensure file is the first parameter
|
|
172
205
|
}
|
|
173
206
|
}
|
|
174
207
|
|
|
@@ -182,27 +215,48 @@ function generateFunctionParameters(params?: ParameterObject[], isFileUpload = f
|
|
|
182
215
|
const varName = toCamelCase(param.name)
|
|
183
216
|
|
|
184
217
|
if (param.in === 'path' || param.in === 'query' || param.in === 'header') {
|
|
185
|
-
functionParams.push(
|
|
218
|
+
functionParams.push(
|
|
219
|
+
formatVarType({
|
|
220
|
+
varName,
|
|
221
|
+
schema: param.schema,
|
|
222
|
+
required: param.required,
|
|
223
|
+
defaultValue: param.schema.default,
|
|
224
|
+
})
|
|
225
|
+
)
|
|
186
226
|
}
|
|
187
227
|
|
|
188
228
|
if (param.in === 'query' || param.in === 'header') {
|
|
189
|
-
paramList.push(
|
|
229
|
+
paramList.push(
|
|
230
|
+
paramName === varName ? paramName : `'${paramName}': ${varName}`
|
|
231
|
+
)
|
|
190
232
|
}
|
|
191
233
|
}
|
|
192
234
|
|
|
193
235
|
return {
|
|
194
236
|
params: functionParams.join(', '),
|
|
195
|
-
config: paramList.length ? { params: paramList.join(', ') } : {}
|
|
237
|
+
config: paramList.length ? { params: paramList.join(', ') } : {},
|
|
196
238
|
}
|
|
197
239
|
}
|
|
198
240
|
|
|
199
|
-
function generateFunctionForOperation(
|
|
241
|
+
function generateFunctionForOperation(
|
|
242
|
+
method: string,
|
|
243
|
+
path: string,
|
|
244
|
+
operation: OperationObject
|
|
245
|
+
): string {
|
|
200
246
|
if (!operation) return ''
|
|
201
247
|
|
|
202
248
|
// Check if this is a file upload operation by looking at the schema reference
|
|
203
|
-
const isFileUpload
|
|
204
|
-
|
|
205
|
-
|
|
249
|
+
const isFileUpload
|
|
250
|
+
= operation.requestBody?.content[
|
|
251
|
+
'multipart/form-data'
|
|
252
|
+
]?.schema?.$ref?.includes('Body_upload_files')
|
|
253
|
+
const parameters = generateFunctionParameters(
|
|
254
|
+
operation.parameters,
|
|
255
|
+
isFileUpload
|
|
256
|
+
)
|
|
257
|
+
const { requestBodyParam, requestBodyPayload } = generateRequestBody(
|
|
258
|
+
operation.requestBody
|
|
259
|
+
)
|
|
206
260
|
|
|
207
261
|
// For file uploads, ignore the regular parameter generation
|
|
208
262
|
const allParams = isFileUpload
|
|
@@ -210,7 +264,9 @@ function generateFunctionForOperation(method: string, path: string, operation: O
|
|
|
210
264
|
: combineAllParams(parameters, requestBodyParam)
|
|
211
265
|
|
|
212
266
|
const responseType = generateResponseType(operation.responses)
|
|
213
|
-
const responseTypeStr = responseType
|
|
267
|
+
const responseTypeStr = responseType
|
|
268
|
+
? `: Promise<AxiosResponse<${responseType}>>`
|
|
269
|
+
: ''
|
|
214
270
|
|
|
215
271
|
return generateAxiosFunction(
|
|
216
272
|
method,
|
|
@@ -224,21 +280,23 @@ function generateFunctionForOperation(method: string, path: string, operation: O
|
|
|
224
280
|
|
|
225
281
|
const generateRandomString = () => Math.random().toString(36).slice(7)
|
|
226
282
|
|
|
227
|
-
function fileTemplate(
|
|
228
|
-
|
|
229
|
-
|
|
283
|
+
function fileTemplate(
|
|
284
|
+
tsString: string,
|
|
285
|
+
typeForImport: string[],
|
|
286
|
+
baseURL: string
|
|
287
|
+
) {
|
|
288
|
+
const templateCode = `import ax from 'axios';
|
|
230
289
|
import type { AxiosResponse } from 'axios';
|
|
231
290
|
import type {${typeForImport.join(', ')}} from './types.d';
|
|
232
|
-
|
|
291
|
+
|
|
233
292
|
interface UploadOptions {
|
|
234
293
|
onUploadProgress?: (progressEvent: any) => void
|
|
235
294
|
dirPath?: string
|
|
236
295
|
tags?: string[]
|
|
237
296
|
}
|
|
238
|
-
|
|
297
|
+
|
|
239
298
|
export const axios = ax.create({baseURL:${baseURL}});
|
|
240
299
|
${tsString}`
|
|
241
|
-
)
|
|
242
300
|
const doubleQuoteRegex = /"([^"]+)":/g
|
|
243
301
|
return templateCode.replace(doubleQuoteRegex, '$1:')
|
|
244
302
|
}
|
|
@@ -252,23 +310,36 @@ const functionsInventory: Record<string, string> = {}
|
|
|
252
310
|
const pathOperations: PathOperation[] = []
|
|
253
311
|
|
|
254
312
|
function hasConflict(path: string, method: string) {
|
|
255
|
-
const cleanPathName = path
|
|
256
|
-
|
|
313
|
+
const cleanPathName = path
|
|
314
|
+
.split('/')
|
|
315
|
+
.filter(p => p && !/\{|\}/.test(p))
|
|
316
|
+
.join('/')
|
|
317
|
+
const matchingPaths = pathOperations.filter(
|
|
318
|
+
p => p.path === cleanPathName && p.method === method
|
|
319
|
+
)
|
|
257
320
|
pathOperations.push({ path: cleanPathName, method })
|
|
258
321
|
return matchingPaths.length > 0
|
|
259
322
|
}
|
|
260
323
|
|
|
261
324
|
// Creates a placeholder for a function and stores its body in the inventory
|
|
262
|
-
function createFunctionPlaceholder(
|
|
325
|
+
function createFunctionPlaceholder(
|
|
326
|
+
path: string,
|
|
327
|
+
method: string,
|
|
328
|
+
operation: any
|
|
329
|
+
) {
|
|
263
330
|
const funcID = generateRandomString()
|
|
264
|
-
functionsInventory[funcID] = generateFunctionForOperation(
|
|
331
|
+
functionsInventory[funcID] = generateFunctionForOperation(
|
|
332
|
+
method,
|
|
333
|
+
path,
|
|
334
|
+
operation
|
|
335
|
+
)
|
|
265
336
|
return funcID
|
|
266
337
|
}
|
|
267
338
|
|
|
268
339
|
function handlePathSegment(
|
|
269
340
|
path: string,
|
|
270
341
|
operation: any,
|
|
271
|
-
existingObj: { [key: string]: any } = {}
|
|
342
|
+
existingObj: { [key: string]: any } = {}
|
|
272
343
|
) {
|
|
273
344
|
const methods = Object.keys(operation)
|
|
274
345
|
const obj: { [key: string]: any } = {}
|
|
@@ -276,9 +347,13 @@ function handlePathSegment(
|
|
|
276
347
|
let functionName = method.toLowerCase()
|
|
277
348
|
if (hasConflict(path, method)) {
|
|
278
349
|
const params: string[] | undefined = getParamsFromPath(path)
|
|
279
|
-
functionName +=
|
|
350
|
+
functionName += params ? `By${toPascalCase(params.pop() || '')}` : 'All'
|
|
280
351
|
}
|
|
281
|
-
obj[functionName] = createFunctionPlaceholder(
|
|
352
|
+
obj[functionName] = createFunctionPlaceholder(
|
|
353
|
+
path,
|
|
354
|
+
method,
|
|
355
|
+
operation[method]
|
|
356
|
+
)
|
|
282
357
|
}
|
|
283
358
|
return { ...obj, ...existingObj }
|
|
284
359
|
}
|
|
@@ -288,7 +363,7 @@ export function generateFunctions(paths: PathsObject, baseUrl: string) {
|
|
|
288
363
|
const body: { [key: string]: any } = {}
|
|
289
364
|
const allPathsClean = Object.keys(paths).map(cleanPath)
|
|
290
365
|
for (const [path, operation] of Object.entries(paths)) {
|
|
291
|
-
const splitPath = path.split('/').filter(p => p &&
|
|
366
|
+
const splitPath = path.split('/').filter(p => p && !/\{|\}/.test(p))
|
|
292
367
|
splitPath.reduce((acc, key: string, index: number, array: string[]) => {
|
|
293
368
|
const objFuncKey = toCamelCase(key)
|
|
294
369
|
if (!objFuncKey) return acc
|
|
@@ -301,11 +376,10 @@ export function generateFunctions(paths: PathsObject, baseUrl: string) {
|
|
|
301
376
|
const method: string = methods[0]
|
|
302
377
|
const opp: any = { ...operation }[method]
|
|
303
378
|
acc[objFuncKey] = createFunctionPlaceholder(path, methods[0], opp)
|
|
304
|
-
} else if (
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
else if (!acc[objFuncKey] || typeof acc[objFuncKey] !== 'object') { acc[objFuncKey] = {}
|
|
379
|
+
} else if (index === array.length - 1) {
|
|
380
|
+
acc[objFuncKey] = handlePathSegment(path, operation, acc[objFuncKey])
|
|
381
|
+
} else if (!acc[objFuncKey] || typeof acc[objFuncKey] !== 'object') {
|
|
382
|
+
acc[objFuncKey] = {}
|
|
309
383
|
}
|
|
310
384
|
return acc[objFuncKey]
|
|
311
385
|
}, body)
|
|
@@ -11,7 +11,7 @@ export function generateTypes(schemas: SchemasObject): string {
|
|
|
11
11
|
if (!schema.properties) return ''
|
|
12
12
|
|
|
13
13
|
const properties = Object.entries(schema.properties).map(([key, value]) => {
|
|
14
|
-
const varType = formatVarType(key, value)
|
|
14
|
+
const varType = formatVarType({ varName: key, schema: value })
|
|
15
15
|
|
|
16
16
|
return `\t\t${varType}`
|
|
17
17
|
}).join(';\n ')
|
|
@@ -1,11 +1,25 @@
|
|
|
1
1
|
import type { SchemaObject } from './openApiTypes'
|
|
2
2
|
|
|
3
|
-
export
|
|
4
|
-
|
|
3
|
+
export function toCamelCase(str?: string) {
|
|
4
|
+
return str
|
|
5
|
+
?.replaceAll(/[-._\s]+(.)?/g, (_, c) => c?.toUpperCase() || '')
|
|
6
|
+
.replace(/^./, str => str.toLowerCase())
|
|
7
|
+
|| str
|
|
8
|
+
|| ''
|
|
9
|
+
}
|
|
10
|
+
export function toPascalCase(str?: string) {
|
|
11
|
+
return str
|
|
12
|
+
?.replaceAll(/[-_\s]+(.)?/g, (_, c) => c?.toUpperCase() || '')
|
|
13
|
+
.replace(/^./, str => str.toUpperCase())
|
|
14
|
+
|| str
|
|
15
|
+
|| ''
|
|
16
|
+
}
|
|
5
17
|
|
|
6
18
|
export function formatType(typeName: string): string {
|
|
7
|
-
|
|
8
|
-
|
|
19
|
+
typeName = typeName
|
|
20
|
+
.replaceAll('-', '')
|
|
21
|
+
.replaceAll(/post|put$/gi, '')
|
|
22
|
+
.replaceAll(/^body_/gi, '')
|
|
9
23
|
return toPascalCase(typeName)!
|
|
10
24
|
}
|
|
11
25
|
|
|
@@ -18,11 +32,19 @@ function resolveReference(ref: string): string {
|
|
|
18
32
|
export function schemaToType(schema?: SchemaObject): string {
|
|
19
33
|
if (!schema) return 'any'
|
|
20
34
|
if (schema.anyOf) {
|
|
21
|
-
let _t = schema.anyOf
|
|
35
|
+
let _t = schema.anyOf
|
|
36
|
+
.map(s => schemaToType(s))
|
|
37
|
+
.filter(p => p !== 'any')
|
|
38
|
+
.join(' | ')
|
|
22
39
|
if (_t === '' || _t === 'null') _t = 'any'
|
|
23
40
|
return _t
|
|
24
41
|
}
|
|
25
|
-
if (schema.allOf)
|
|
42
|
+
if (schema.allOf) {
|
|
43
|
+
return schema.allOf
|
|
44
|
+
.map(s => schemaToType(s))
|
|
45
|
+
.filter(p => p !== 'any')
|
|
46
|
+
.join(' & ')
|
|
47
|
+
}
|
|
26
48
|
if (schema.$ref) return resolveReference(schema.$ref)
|
|
27
49
|
switch (schema.type) {
|
|
28
50
|
case 'object':
|
|
@@ -59,9 +81,24 @@ export function isOptional(schema: SchemaObject) {
|
|
|
59
81
|
return includesNull || includesUndefined || schema.default !== undefined
|
|
60
82
|
}
|
|
61
83
|
|
|
62
|
-
export
|
|
84
|
+
export function cleanOptionals(str: string) {
|
|
85
|
+
return str
|
|
86
|
+
.split(' | ')
|
|
87
|
+
.filter(t => t !== 'null' && t !== 'undefined')
|
|
88
|
+
.join(' | ')
|
|
89
|
+
}
|
|
63
90
|
|
|
64
|
-
export function formatVarType(
|
|
91
|
+
export function formatVarType({
|
|
92
|
+
varName,
|
|
93
|
+
schema,
|
|
94
|
+
required = false,
|
|
95
|
+
defaultValue,
|
|
96
|
+
}: {
|
|
97
|
+
varName: string
|
|
98
|
+
schema: SchemaObject
|
|
99
|
+
required?: boolean
|
|
100
|
+
defaultValue?: unknown
|
|
101
|
+
}) {
|
|
65
102
|
let type = schemaToType(schema)
|
|
66
103
|
type = cleanOptionals(type)
|
|
67
104
|
|
|
@@ -74,12 +111,16 @@ export function formatVarType(varName: string, schema: any, required = false, de
|
|
|
74
111
|
}
|
|
75
112
|
}
|
|
76
113
|
|
|
77
|
-
let optionalStr = required
|
|
114
|
+
let optionalStr = (!required && isOptional(schema)) ? '?' : ''
|
|
115
|
+
|
|
78
116
|
if (defaultStr) optionalStr = ''
|
|
79
117
|
|
|
80
118
|
return `${varName}${optionalStr}: ${type}${defaultStr}`
|
|
81
119
|
}
|
|
82
120
|
|
|
83
121
|
export function cleanPath(path: string) {
|
|
84
|
-
return path
|
|
122
|
+
return path
|
|
123
|
+
.split('/')
|
|
124
|
+
.filter(p => p && !/\{|\}/.test(p))
|
|
125
|
+
.join('/')
|
|
85
126
|
}
|