@bagelink/sdk 0.0.807 → 0.0.811
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/bin/index.ts +2 -2
- package/bin/utils.ts +2 -6
- package/dist/index.cjs +28 -24
- package/dist/index.d.cts +56 -18
- package/dist/index.d.mts +56 -18
- package/dist/index.d.ts +56 -18
- package/dist/index.mjs +28 -24
- package/package.json +1 -1
- package/src/index.ts +27 -26
- package/src/openAPITools/functionGenerator.ts +13 -12
- package/src/openAPITools/utils.ts +15 -9
package/bin/index.ts
CHANGED
|
@@ -19,7 +19,7 @@ export async function loadTypes() {
|
|
|
19
19
|
await formatAndWriteCode(typesPath, types)
|
|
20
20
|
|
|
21
21
|
const apiPath = join(bagelinkDir, 'api.ts')
|
|
22
|
-
await formatAndWriteCode(apiPath, code)
|
|
22
|
+
await formatAndWriteCode(apiPath, `// eslint-disable no-null \n${code}`)
|
|
23
23
|
|
|
24
24
|
await handleAuthCode(withAuth, bagelinkDir)
|
|
25
25
|
|
|
@@ -29,6 +29,6 @@ export async function loadTypes() {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
loadTypes().catch((error: unknown) => {
|
|
32
|
-
proc.exitCode = 1
|
|
33
32
|
console.error(error)
|
|
33
|
+
proc.exit(1)
|
|
34
34
|
})
|
package/bin/utils.ts
CHANGED
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
import fs from 'node:fs'
|
|
2
2
|
|
|
3
|
-
import { createRequire } from 'node:module'
|
|
4
3
|
import { join } from 'node:path'
|
|
4
|
+
import * as proc from 'node:process'
|
|
5
5
|
import { ESLint } from 'eslint'
|
|
6
6
|
import * as prettier from 'prettier'
|
|
7
7
|
import { loadEnv } from 'vite'
|
|
8
8
|
|
|
9
|
-
const _require = createRequire(import.meta.url)
|
|
10
|
-
|
|
11
|
-
const proc = _require('process') as typeof import('process')
|
|
12
|
-
|
|
13
9
|
const cwd = proc.cwd()
|
|
14
10
|
const env = loadEnv('', cwd)
|
|
15
11
|
|
|
@@ -70,7 +66,7 @@ export async function handleAuthCode(_withAuth: boolean, _bagelinkDir: string) {
|
|
|
70
66
|
if (_withAuth) {
|
|
71
67
|
const authCode = fs.readFileSync(
|
|
72
68
|
join(__dirname, 'authClientCode.ts'),
|
|
73
|
-
'
|
|
69
|
+
'utf8'
|
|
74
70
|
).replace(
|
|
75
71
|
'// @ts-expect-error - required for axios to work',
|
|
76
72
|
''
|
package/dist/index.cjs
CHANGED
|
@@ -6,10 +6,10 @@ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'defau
|
|
|
6
6
|
|
|
7
7
|
const axios__default = /*#__PURE__*/_interopDefaultCompat(axios$1);
|
|
8
8
|
|
|
9
|
-
const toCamelCase = (str) => str?.
|
|
10
|
-
const toPascalCase = (str) => str?.
|
|
9
|
+
const toCamelCase = (str) => str?.replaceAll(/[-._\s]+(.)?/g, (_, c) => c?.toUpperCase() || "").replace(/^./, (str2) => str2.toLowerCase()) || str;
|
|
10
|
+
const toPascalCase = (str) => str?.replaceAll(/[-_\s]+(.)?/g, (_, c) => c?.toUpperCase() || "").replace(/^./, (str2) => str2.toUpperCase()) || str;
|
|
11
11
|
function formatType(typeName) {
|
|
12
|
-
typeName = typeName.
|
|
12
|
+
typeName = typeName.replaceAll("-", "").replaceAll(/(post|put)$/gi, "").replaceAll(/^body_/gi, "");
|
|
13
13
|
return toPascalCase(typeName);
|
|
14
14
|
}
|
|
15
15
|
function resolveReference(ref) {
|
|
@@ -29,7 +29,7 @@ function schemaToType(schema) {
|
|
|
29
29
|
return resolveReference(schema.$ref);
|
|
30
30
|
switch (schema.type) {
|
|
31
31
|
case "object":
|
|
32
|
-
return "
|
|
32
|
+
return "{ [key: string]: any }";
|
|
33
33
|
case "string":
|
|
34
34
|
return "string";
|
|
35
35
|
case "integer":
|
|
@@ -40,6 +40,8 @@ function schemaToType(schema) {
|
|
|
40
40
|
return "boolean";
|
|
41
41
|
case "array":
|
|
42
42
|
return `${schemaToType(schema.items)}[]`;
|
|
43
|
+
case "undefined":
|
|
44
|
+
return "undefined";
|
|
43
45
|
case "null":
|
|
44
46
|
return "null";
|
|
45
47
|
default:
|
|
@@ -48,12 +50,15 @@ function schemaToType(schema) {
|
|
|
48
50
|
}
|
|
49
51
|
function isOptional(schema) {
|
|
50
52
|
const type = schemaToType(schema);
|
|
51
|
-
|
|
53
|
+
const splitType = type.split(/\s+\|\s+/);
|
|
54
|
+
const includesNull = splitType.includes("null");
|
|
55
|
+
const includesUndefined = splitType.includes("undefined");
|
|
56
|
+
return includesNull || includesUndefined || schema.default !== void 0;
|
|
52
57
|
}
|
|
53
|
-
const
|
|
54
|
-
function formatVarType(varName, schema, required = false, defaultValue
|
|
58
|
+
const cleanOptionals = (str) => str.split(" | ").filter((t) => t !== "null" && t !== "undefined").join(" | ");
|
|
59
|
+
function formatVarType(varName, schema, required = false, defaultValue) {
|
|
55
60
|
let type = schemaToType(schema);
|
|
56
|
-
type =
|
|
61
|
+
type = cleanOptionals(type);
|
|
57
62
|
let defaultStr = defaultValue ? ` = ${defaultValue}` : "";
|
|
58
63
|
if (defaultStr && type === "string")
|
|
59
64
|
defaultStr = ` = '${defaultValue}'`;
|
|
@@ -65,10 +70,11 @@ function formatVarType(varName, schema, required = false, defaultValue = null) {
|
|
|
65
70
|
return `${varName}${optionalStr}: ${type}${defaultStr}`;
|
|
66
71
|
}
|
|
67
72
|
function cleanPath(path) {
|
|
68
|
-
return path.split("/").filter((p) => p &&
|
|
73
|
+
return path.split("/").filter((p) => p && !/\{|\}/.test(p)).join("/");
|
|
69
74
|
}
|
|
70
75
|
|
|
71
76
|
const allTypes = [];
|
|
77
|
+
const primitiveTypes = ["string", "number", "boolean", "null", "void", "any", "Record<string, any>", "undefined", "{ [key: string]: any }"];
|
|
72
78
|
function collectTypeForImportStatement(typeName) {
|
|
73
79
|
typeName = typeName.trim().replace("[]", "");
|
|
74
80
|
if (typeName.includes("|")) {
|
|
@@ -79,7 +85,6 @@ function collectTypeForImportStatement(typeName) {
|
|
|
79
85
|
);
|
|
80
86
|
return;
|
|
81
87
|
}
|
|
82
|
-
const primitiveTypes = ["string", "number", "boolean", "null", "void", "any", "Record<string, any>"];
|
|
83
88
|
const isPrimitive = primitiveTypes.includes(typeName);
|
|
84
89
|
typeName = formatType(typeName);
|
|
85
90
|
if (!typeName || isPrimitive)
|
|
@@ -90,7 +95,7 @@ function collectTypeForImportStatement(typeName) {
|
|
|
90
95
|
function getResponseType(response) {
|
|
91
96
|
const mediaTypeObject = response.content?.["application/json"];
|
|
92
97
|
if (!mediaTypeObject || !mediaTypeObject.schema)
|
|
93
|
-
return
|
|
98
|
+
return;
|
|
94
99
|
const responseType = schemaToType(mediaTypeObject.schema);
|
|
95
100
|
collectTypeForImportStatement(responseType);
|
|
96
101
|
return responseType;
|
|
@@ -190,7 +195,7 @@ function generateFunctionForOperation(method, path, operation) {
|
|
|
190
195
|
const responseTypeStr = responseType ? `: Promise<AxiosResponse<${responseType}>>` : "";
|
|
191
196
|
return generateAxiosFunction(method, formattedPath, allParams, responseTypeStr, parameters, requestBodyPayload);
|
|
192
197
|
}
|
|
193
|
-
const generateRandomString = () => Math.random().toString(36).
|
|
198
|
+
const generateRandomString = () => Math.random().toString(36).slice(7);
|
|
194
199
|
function fileTemplate(tsString, typeForImport, baseURL) {
|
|
195
200
|
const templateCode = `import ax from 'axios';
|
|
196
201
|
import type { AxiosResponse } from 'axios';
|
|
@@ -204,7 +209,7 @@ function fileTemplate(tsString, typeForImport, baseURL) {
|
|
|
204
209
|
const functionsInventory = {};
|
|
205
210
|
const pathOperations = [];
|
|
206
211
|
function hasConflict(path, method) {
|
|
207
|
-
const cleanPathName = path.split("/").filter((p) => p &&
|
|
212
|
+
const cleanPathName = path.split("/").filter((p) => p && !/\{|\}/.test(p)).join("/");
|
|
208
213
|
const matchingPaths = pathOperations.filter((p) => p.path === cleanPathName && p.method === method);
|
|
209
214
|
pathOperations.push({ path: cleanPathName, method });
|
|
210
215
|
return matchingPaths.length > 0;
|
|
@@ -214,7 +219,7 @@ function createFunctionPlaceholder(path, method, operation) {
|
|
|
214
219
|
functionsInventory[funcID] = generateFunctionForOperation(method, path, operation);
|
|
215
220
|
return funcID;
|
|
216
221
|
}
|
|
217
|
-
function handlePathSegment(path, operation, existingObj =
|
|
222
|
+
function handlePathSegment(path, operation, existingObj = {}) {
|
|
218
223
|
const methods = Object.keys(operation);
|
|
219
224
|
const obj = {};
|
|
220
225
|
for (const method of methods) {
|
|
@@ -232,7 +237,7 @@ function generateFunctions(paths, baseUrl) {
|
|
|
232
237
|
const body = {};
|
|
233
238
|
const allPathsClean = Object.keys(paths).map(cleanPath);
|
|
234
239
|
for (const [path, operation] of Object.entries(paths)) {
|
|
235
|
-
const splitPath = path.split("/").filter((p) => p &&
|
|
240
|
+
const splitPath = path.split("/").filter((p) => p && !/\{|\}/.test(p));
|
|
236
241
|
splitPath.reduce((acc, key, index, array) => {
|
|
237
242
|
const objFuncKey = toCamelCase(key);
|
|
238
243
|
if (!objFuncKey)
|
|
@@ -251,7 +256,7 @@ function generateFunctions(paths, baseUrl) {
|
|
|
251
256
|
}, body);
|
|
252
257
|
}
|
|
253
258
|
for (const [parent, object] of Object.entries(body)) {
|
|
254
|
-
tsString += `export const ${parent} = ${JSON.stringify(object,
|
|
259
|
+
tsString += `export const ${parent} = ${JSON.stringify(object, void 0, 2)};
|
|
255
260
|
`;
|
|
256
261
|
}
|
|
257
262
|
Object.entries(functionsInventory).forEach(([key, value]) => {
|
|
@@ -330,7 +335,7 @@ class DataRequest {
|
|
|
330
335
|
async get() {
|
|
331
336
|
if (!this.data_table)
|
|
332
337
|
throw new Error("Data table not set");
|
|
333
|
-
const filterStr = Object.keys(this._filter).length ? `?filter={${Object.entries(this._filter).map(([k, v]) => `${k}:${v}`).join(",")}}` : "";
|
|
338
|
+
const filterStr = Object.keys(this._filter).length > 0 ? `?filter={${Object.entries(this._filter).map(([k, v]) => `${k}:${v}`).join(",")}}` : "";
|
|
334
339
|
const url = `/data/${this.data_table}${this.itemID ? `/${this.itemID}` : ""}${filterStr}`;
|
|
335
340
|
try {
|
|
336
341
|
const { data } = await axios.get(url);
|
|
@@ -376,7 +381,7 @@ function responses(key) {
|
|
|
376
381
|
class BagelAuth {
|
|
377
382
|
constructor(bagel) {
|
|
378
383
|
this.bagel = bagel;
|
|
379
|
-
__publicField(this, "user"
|
|
384
|
+
__publicField(this, "user");
|
|
380
385
|
this.bagel = bagel;
|
|
381
386
|
}
|
|
382
387
|
async validateUser() {
|
|
@@ -386,8 +391,7 @@ class BagelAuth {
|
|
|
386
391
|
});
|
|
387
392
|
this.user = usr;
|
|
388
393
|
return usr;
|
|
389
|
-
} catch
|
|
390
|
-
return null;
|
|
394
|
+
} catch {
|
|
391
395
|
}
|
|
392
396
|
}
|
|
393
397
|
async resetPassword(ctx) {
|
|
@@ -427,7 +431,7 @@ class BagelAuth {
|
|
|
427
431
|
this.bagel.onError?.(err);
|
|
428
432
|
console.log(err);
|
|
429
433
|
}
|
|
430
|
-
this.user =
|
|
434
|
+
this.user = void 0;
|
|
431
435
|
}
|
|
432
436
|
async acceptInvite(token, user) {
|
|
433
437
|
await axios.post(`/auth/accept-invite/${token}`, user);
|
|
@@ -448,7 +452,7 @@ class Bagel {
|
|
|
448
452
|
constructor({ host, onError }) {
|
|
449
453
|
__publicField(this, "host");
|
|
450
454
|
__publicField(this, "onError");
|
|
451
|
-
__publicField(this, "read_table"
|
|
455
|
+
__publicField(this, "read_table");
|
|
452
456
|
__publicField(this, "auth", new BagelAuth(this));
|
|
453
457
|
this.host = host?.replace(/\/$/, "");
|
|
454
458
|
if (!this.host) {
|
|
@@ -463,7 +467,7 @@ class Bagel {
|
|
|
463
467
|
return new DataRequest(table, this);
|
|
464
468
|
}
|
|
465
469
|
_endpointCleaner(endpoint) {
|
|
466
|
-
const url = `${endpoint.replace(/^\//, "").
|
|
470
|
+
const url = `${endpoint.replace(/^\//, "").replaceAll(/\/$/g, "")}`;
|
|
467
471
|
return url;
|
|
468
472
|
}
|
|
469
473
|
async api(endpoint, query) {
|
|
@@ -476,7 +480,7 @@ class Bagel {
|
|
|
476
480
|
async get(endpoint, query) {
|
|
477
481
|
this._setAuthorization();
|
|
478
482
|
endpoint = this._endpointCleaner(endpoint);
|
|
479
|
-
if (
|
|
483
|
+
if (/undefined|null/.test(endpoint))
|
|
480
484
|
throw new Error(`Invalid endpoint: ${endpoint}`);
|
|
481
485
|
if (query) {
|
|
482
486
|
const queryParams = Object.entries(query).filter(([_, value]) => !!value).map(([key, value]) => `${key}=${value}`).join("&");
|
package/dist/index.d.cts
CHANGED
|
@@ -25,45 +25,83 @@ declare class DataRequest<T extends Tables = Tables> {
|
|
|
25
25
|
data_table: T | Tables;
|
|
26
26
|
bagel: any;
|
|
27
27
|
itemID: string;
|
|
28
|
-
_filter:
|
|
28
|
+
_filter: {
|
|
29
|
+
[key: string]: any;
|
|
30
|
+
};
|
|
29
31
|
constructor(table: T, bagel: Bagel);
|
|
30
|
-
post(item:
|
|
31
|
-
|
|
32
|
+
post(item: {
|
|
33
|
+
[key: string]: any;
|
|
34
|
+
}): Promise<{
|
|
35
|
+
[key: string]: any;
|
|
36
|
+
}>;
|
|
37
|
+
filter(filter: {
|
|
38
|
+
[key: string]: any;
|
|
39
|
+
}): this;
|
|
32
40
|
get(): Promise<TableToTypeMapping[T] | TableToTypeMapping[T][] | undefined>;
|
|
33
41
|
item(id: string): this;
|
|
34
42
|
delete(): Promise<TableToTypeMapping[T][]>;
|
|
35
|
-
put(updatedItem:
|
|
43
|
+
put(updatedItem: {
|
|
44
|
+
[key: string]: any;
|
|
45
|
+
}): Promise<{
|
|
46
|
+
[key: string]: any;
|
|
47
|
+
}>;
|
|
36
48
|
}
|
|
37
49
|
declare class BagelAuth {
|
|
38
50
|
private bagel;
|
|
39
51
|
constructor(bagel: Bagel);
|
|
40
|
-
user: User |
|
|
41
|
-
validateUser(): Promise<User |
|
|
52
|
+
user: User | undefined;
|
|
53
|
+
validateUser(): Promise<User | undefined>;
|
|
42
54
|
resetPassword(ctx: {
|
|
43
55
|
token: string;
|
|
44
56
|
password: string;
|
|
45
|
-
}): Promise<
|
|
57
|
+
}): Promise<{
|
|
58
|
+
[key: string]: any;
|
|
59
|
+
}>;
|
|
46
60
|
forgotPassword(email: string): Promise<void>;
|
|
47
|
-
login(user: User): Promise<User |
|
|
61
|
+
login(user: User): Promise<User | undefined>;
|
|
48
62
|
logout(): Promise<void>;
|
|
49
|
-
acceptInvite(token: string, user:
|
|
50
|
-
|
|
63
|
+
acceptInvite(token: string, user: {
|
|
64
|
+
[key: string]: any;
|
|
65
|
+
}): Promise<void>;
|
|
66
|
+
register(user: {
|
|
67
|
+
[key: string]: any;
|
|
68
|
+
}, errors: {
|
|
69
|
+
[key: string]: any;
|
|
70
|
+
}): Promise<User | undefined>;
|
|
51
71
|
}
|
|
52
72
|
declare class Bagel {
|
|
53
73
|
host?: string;
|
|
54
74
|
onError?: (err: any) => void;
|
|
55
|
-
constructor({ host, onError }:
|
|
56
|
-
|
|
75
|
+
constructor({ host, onError }: {
|
|
76
|
+
[key: string]: any;
|
|
77
|
+
});
|
|
78
|
+
read_table: Tables | undefined;
|
|
57
79
|
data(table: Tables): DataRequest<Tables>;
|
|
58
80
|
auth: BagelAuth;
|
|
59
81
|
_endpointCleaner(endpoint: string): string;
|
|
60
|
-
api(endpoint: string, query?:
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
82
|
+
api(endpoint: string, query?: {
|
|
83
|
+
[key: string]: string;
|
|
84
|
+
}): Promise<{
|
|
85
|
+
[key: string]: any;
|
|
86
|
+
}>;
|
|
87
|
+
get<T = {
|
|
88
|
+
[key: string]: any;
|
|
89
|
+
}>(endpoint: string, query?: {
|
|
90
|
+
[key: string]: any;
|
|
91
|
+
}): Promise<T>;
|
|
92
|
+
delete(endpoint: string): Promise<{
|
|
93
|
+
[key: string]: any;
|
|
94
|
+
}>;
|
|
95
|
+
put(endpoint: string, payload: any): Promise<{
|
|
96
|
+
[key: string]: any;
|
|
97
|
+
}>;
|
|
98
|
+
patch(endpoint: string, payload?: any): Promise<{
|
|
99
|
+
[key: string]: any;
|
|
100
|
+
}>;
|
|
65
101
|
_setAuthorization(): void;
|
|
66
|
-
post(endpoint: string, payload?: any): Promise<
|
|
102
|
+
post(endpoint: string, payload?: any): Promise<{
|
|
103
|
+
[key: string]: any;
|
|
104
|
+
}>;
|
|
67
105
|
uploadFile<T = any>(file: File, options?: UploadOptions): Promise<T>;
|
|
68
106
|
}
|
|
69
107
|
|
package/dist/index.d.mts
CHANGED
|
@@ -25,45 +25,83 @@ declare class DataRequest<T extends Tables = Tables> {
|
|
|
25
25
|
data_table: T | Tables;
|
|
26
26
|
bagel: any;
|
|
27
27
|
itemID: string;
|
|
28
|
-
_filter:
|
|
28
|
+
_filter: {
|
|
29
|
+
[key: string]: any;
|
|
30
|
+
};
|
|
29
31
|
constructor(table: T, bagel: Bagel);
|
|
30
|
-
post(item:
|
|
31
|
-
|
|
32
|
+
post(item: {
|
|
33
|
+
[key: string]: any;
|
|
34
|
+
}): Promise<{
|
|
35
|
+
[key: string]: any;
|
|
36
|
+
}>;
|
|
37
|
+
filter(filter: {
|
|
38
|
+
[key: string]: any;
|
|
39
|
+
}): this;
|
|
32
40
|
get(): Promise<TableToTypeMapping[T] | TableToTypeMapping[T][] | undefined>;
|
|
33
41
|
item(id: string): this;
|
|
34
42
|
delete(): Promise<TableToTypeMapping[T][]>;
|
|
35
|
-
put(updatedItem:
|
|
43
|
+
put(updatedItem: {
|
|
44
|
+
[key: string]: any;
|
|
45
|
+
}): Promise<{
|
|
46
|
+
[key: string]: any;
|
|
47
|
+
}>;
|
|
36
48
|
}
|
|
37
49
|
declare class BagelAuth {
|
|
38
50
|
private bagel;
|
|
39
51
|
constructor(bagel: Bagel);
|
|
40
|
-
user: User |
|
|
41
|
-
validateUser(): Promise<User |
|
|
52
|
+
user: User | undefined;
|
|
53
|
+
validateUser(): Promise<User | undefined>;
|
|
42
54
|
resetPassword(ctx: {
|
|
43
55
|
token: string;
|
|
44
56
|
password: string;
|
|
45
|
-
}): Promise<
|
|
57
|
+
}): Promise<{
|
|
58
|
+
[key: string]: any;
|
|
59
|
+
}>;
|
|
46
60
|
forgotPassword(email: string): Promise<void>;
|
|
47
|
-
login(user: User): Promise<User |
|
|
61
|
+
login(user: User): Promise<User | undefined>;
|
|
48
62
|
logout(): Promise<void>;
|
|
49
|
-
acceptInvite(token: string, user:
|
|
50
|
-
|
|
63
|
+
acceptInvite(token: string, user: {
|
|
64
|
+
[key: string]: any;
|
|
65
|
+
}): Promise<void>;
|
|
66
|
+
register(user: {
|
|
67
|
+
[key: string]: any;
|
|
68
|
+
}, errors: {
|
|
69
|
+
[key: string]: any;
|
|
70
|
+
}): Promise<User | undefined>;
|
|
51
71
|
}
|
|
52
72
|
declare class Bagel {
|
|
53
73
|
host?: string;
|
|
54
74
|
onError?: (err: any) => void;
|
|
55
|
-
constructor({ host, onError }:
|
|
56
|
-
|
|
75
|
+
constructor({ host, onError }: {
|
|
76
|
+
[key: string]: any;
|
|
77
|
+
});
|
|
78
|
+
read_table: Tables | undefined;
|
|
57
79
|
data(table: Tables): DataRequest<Tables>;
|
|
58
80
|
auth: BagelAuth;
|
|
59
81
|
_endpointCleaner(endpoint: string): string;
|
|
60
|
-
api(endpoint: string, query?:
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
82
|
+
api(endpoint: string, query?: {
|
|
83
|
+
[key: string]: string;
|
|
84
|
+
}): Promise<{
|
|
85
|
+
[key: string]: any;
|
|
86
|
+
}>;
|
|
87
|
+
get<T = {
|
|
88
|
+
[key: string]: any;
|
|
89
|
+
}>(endpoint: string, query?: {
|
|
90
|
+
[key: string]: any;
|
|
91
|
+
}): Promise<T>;
|
|
92
|
+
delete(endpoint: string): Promise<{
|
|
93
|
+
[key: string]: any;
|
|
94
|
+
}>;
|
|
95
|
+
put(endpoint: string, payload: any): Promise<{
|
|
96
|
+
[key: string]: any;
|
|
97
|
+
}>;
|
|
98
|
+
patch(endpoint: string, payload?: any): Promise<{
|
|
99
|
+
[key: string]: any;
|
|
100
|
+
}>;
|
|
65
101
|
_setAuthorization(): void;
|
|
66
|
-
post(endpoint: string, payload?: any): Promise<
|
|
102
|
+
post(endpoint: string, payload?: any): Promise<{
|
|
103
|
+
[key: string]: any;
|
|
104
|
+
}>;
|
|
67
105
|
uploadFile<T = any>(file: File, options?: UploadOptions): Promise<T>;
|
|
68
106
|
}
|
|
69
107
|
|
package/dist/index.d.ts
CHANGED
|
@@ -25,45 +25,83 @@ declare class DataRequest<T extends Tables = Tables> {
|
|
|
25
25
|
data_table: T | Tables;
|
|
26
26
|
bagel: any;
|
|
27
27
|
itemID: string;
|
|
28
|
-
_filter:
|
|
28
|
+
_filter: {
|
|
29
|
+
[key: string]: any;
|
|
30
|
+
};
|
|
29
31
|
constructor(table: T, bagel: Bagel);
|
|
30
|
-
post(item:
|
|
31
|
-
|
|
32
|
+
post(item: {
|
|
33
|
+
[key: string]: any;
|
|
34
|
+
}): Promise<{
|
|
35
|
+
[key: string]: any;
|
|
36
|
+
}>;
|
|
37
|
+
filter(filter: {
|
|
38
|
+
[key: string]: any;
|
|
39
|
+
}): this;
|
|
32
40
|
get(): Promise<TableToTypeMapping[T] | TableToTypeMapping[T][] | undefined>;
|
|
33
41
|
item(id: string): this;
|
|
34
42
|
delete(): Promise<TableToTypeMapping[T][]>;
|
|
35
|
-
put(updatedItem:
|
|
43
|
+
put(updatedItem: {
|
|
44
|
+
[key: string]: any;
|
|
45
|
+
}): Promise<{
|
|
46
|
+
[key: string]: any;
|
|
47
|
+
}>;
|
|
36
48
|
}
|
|
37
49
|
declare class BagelAuth {
|
|
38
50
|
private bagel;
|
|
39
51
|
constructor(bagel: Bagel);
|
|
40
|
-
user: User |
|
|
41
|
-
validateUser(): Promise<User |
|
|
52
|
+
user: User | undefined;
|
|
53
|
+
validateUser(): Promise<User | undefined>;
|
|
42
54
|
resetPassword(ctx: {
|
|
43
55
|
token: string;
|
|
44
56
|
password: string;
|
|
45
|
-
}): Promise<
|
|
57
|
+
}): Promise<{
|
|
58
|
+
[key: string]: any;
|
|
59
|
+
}>;
|
|
46
60
|
forgotPassword(email: string): Promise<void>;
|
|
47
|
-
login(user: User): Promise<User |
|
|
61
|
+
login(user: User): Promise<User | undefined>;
|
|
48
62
|
logout(): Promise<void>;
|
|
49
|
-
acceptInvite(token: string, user:
|
|
50
|
-
|
|
63
|
+
acceptInvite(token: string, user: {
|
|
64
|
+
[key: string]: any;
|
|
65
|
+
}): Promise<void>;
|
|
66
|
+
register(user: {
|
|
67
|
+
[key: string]: any;
|
|
68
|
+
}, errors: {
|
|
69
|
+
[key: string]: any;
|
|
70
|
+
}): Promise<User | undefined>;
|
|
51
71
|
}
|
|
52
72
|
declare class Bagel {
|
|
53
73
|
host?: string;
|
|
54
74
|
onError?: (err: any) => void;
|
|
55
|
-
constructor({ host, onError }:
|
|
56
|
-
|
|
75
|
+
constructor({ host, onError }: {
|
|
76
|
+
[key: string]: any;
|
|
77
|
+
});
|
|
78
|
+
read_table: Tables | undefined;
|
|
57
79
|
data(table: Tables): DataRequest<Tables>;
|
|
58
80
|
auth: BagelAuth;
|
|
59
81
|
_endpointCleaner(endpoint: string): string;
|
|
60
|
-
api(endpoint: string, query?:
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
82
|
+
api(endpoint: string, query?: {
|
|
83
|
+
[key: string]: string;
|
|
84
|
+
}): Promise<{
|
|
85
|
+
[key: string]: any;
|
|
86
|
+
}>;
|
|
87
|
+
get<T = {
|
|
88
|
+
[key: string]: any;
|
|
89
|
+
}>(endpoint: string, query?: {
|
|
90
|
+
[key: string]: any;
|
|
91
|
+
}): Promise<T>;
|
|
92
|
+
delete(endpoint: string): Promise<{
|
|
93
|
+
[key: string]: any;
|
|
94
|
+
}>;
|
|
95
|
+
put(endpoint: string, payload: any): Promise<{
|
|
96
|
+
[key: string]: any;
|
|
97
|
+
}>;
|
|
98
|
+
patch(endpoint: string, payload?: any): Promise<{
|
|
99
|
+
[key: string]: any;
|
|
100
|
+
}>;
|
|
65
101
|
_setAuthorization(): void;
|
|
66
|
-
post(endpoint: string, payload?: any): Promise<
|
|
102
|
+
post(endpoint: string, payload?: any): Promise<{
|
|
103
|
+
[key: string]: any;
|
|
104
|
+
}>;
|
|
67
105
|
uploadFile<T = any>(file: File, options?: UploadOptions): Promise<T>;
|
|
68
106
|
}
|
|
69
107
|
|
package/dist/index.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import axios$1 from 'axios';
|
|
2
2
|
|
|
3
|
-
const toCamelCase = (str) => str?.
|
|
4
|
-
const toPascalCase = (str) => str?.
|
|
3
|
+
const toCamelCase = (str) => str?.replaceAll(/[-._\s]+(.)?/g, (_, c) => c?.toUpperCase() || "").replace(/^./, (str2) => str2.toLowerCase()) || str;
|
|
4
|
+
const toPascalCase = (str) => str?.replaceAll(/[-_\s]+(.)?/g, (_, c) => c?.toUpperCase() || "").replace(/^./, (str2) => str2.toUpperCase()) || str;
|
|
5
5
|
function formatType(typeName) {
|
|
6
|
-
typeName = typeName.
|
|
6
|
+
typeName = typeName.replaceAll("-", "").replaceAll(/(post|put)$/gi, "").replaceAll(/^body_/gi, "");
|
|
7
7
|
return toPascalCase(typeName);
|
|
8
8
|
}
|
|
9
9
|
function resolveReference(ref) {
|
|
@@ -23,7 +23,7 @@ function schemaToType(schema) {
|
|
|
23
23
|
return resolveReference(schema.$ref);
|
|
24
24
|
switch (schema.type) {
|
|
25
25
|
case "object":
|
|
26
|
-
return "
|
|
26
|
+
return "{ [key: string]: any }";
|
|
27
27
|
case "string":
|
|
28
28
|
return "string";
|
|
29
29
|
case "integer":
|
|
@@ -34,6 +34,8 @@ function schemaToType(schema) {
|
|
|
34
34
|
return "boolean";
|
|
35
35
|
case "array":
|
|
36
36
|
return `${schemaToType(schema.items)}[]`;
|
|
37
|
+
case "undefined":
|
|
38
|
+
return "undefined";
|
|
37
39
|
case "null":
|
|
38
40
|
return "null";
|
|
39
41
|
default:
|
|
@@ -42,12 +44,15 @@ function schemaToType(schema) {
|
|
|
42
44
|
}
|
|
43
45
|
function isOptional(schema) {
|
|
44
46
|
const type = schemaToType(schema);
|
|
45
|
-
|
|
47
|
+
const splitType = type.split(/\s+\|\s+/);
|
|
48
|
+
const includesNull = splitType.includes("null");
|
|
49
|
+
const includesUndefined = splitType.includes("undefined");
|
|
50
|
+
return includesNull || includesUndefined || schema.default !== void 0;
|
|
46
51
|
}
|
|
47
|
-
const
|
|
48
|
-
function formatVarType(varName, schema, required = false, defaultValue
|
|
52
|
+
const cleanOptionals = (str) => str.split(" | ").filter((t) => t !== "null" && t !== "undefined").join(" | ");
|
|
53
|
+
function formatVarType(varName, schema, required = false, defaultValue) {
|
|
49
54
|
let type = schemaToType(schema);
|
|
50
|
-
type =
|
|
55
|
+
type = cleanOptionals(type);
|
|
51
56
|
let defaultStr = defaultValue ? ` = ${defaultValue}` : "";
|
|
52
57
|
if (defaultStr && type === "string")
|
|
53
58
|
defaultStr = ` = '${defaultValue}'`;
|
|
@@ -59,10 +64,11 @@ function formatVarType(varName, schema, required = false, defaultValue = null) {
|
|
|
59
64
|
return `${varName}${optionalStr}: ${type}${defaultStr}`;
|
|
60
65
|
}
|
|
61
66
|
function cleanPath(path) {
|
|
62
|
-
return path.split("/").filter((p) => p &&
|
|
67
|
+
return path.split("/").filter((p) => p && !/\{|\}/.test(p)).join("/");
|
|
63
68
|
}
|
|
64
69
|
|
|
65
70
|
const allTypes = [];
|
|
71
|
+
const primitiveTypes = ["string", "number", "boolean", "null", "void", "any", "Record<string, any>", "undefined", "{ [key: string]: any }"];
|
|
66
72
|
function collectTypeForImportStatement(typeName) {
|
|
67
73
|
typeName = typeName.trim().replace("[]", "");
|
|
68
74
|
if (typeName.includes("|")) {
|
|
@@ -73,7 +79,6 @@ function collectTypeForImportStatement(typeName) {
|
|
|
73
79
|
);
|
|
74
80
|
return;
|
|
75
81
|
}
|
|
76
|
-
const primitiveTypes = ["string", "number", "boolean", "null", "void", "any", "Record<string, any>"];
|
|
77
82
|
const isPrimitive = primitiveTypes.includes(typeName);
|
|
78
83
|
typeName = formatType(typeName);
|
|
79
84
|
if (!typeName || isPrimitive)
|
|
@@ -84,7 +89,7 @@ function collectTypeForImportStatement(typeName) {
|
|
|
84
89
|
function getResponseType(response) {
|
|
85
90
|
const mediaTypeObject = response.content?.["application/json"];
|
|
86
91
|
if (!mediaTypeObject || !mediaTypeObject.schema)
|
|
87
|
-
return
|
|
92
|
+
return;
|
|
88
93
|
const responseType = schemaToType(mediaTypeObject.schema);
|
|
89
94
|
collectTypeForImportStatement(responseType);
|
|
90
95
|
return responseType;
|
|
@@ -184,7 +189,7 @@ function generateFunctionForOperation(method, path, operation) {
|
|
|
184
189
|
const responseTypeStr = responseType ? `: Promise<AxiosResponse<${responseType}>>` : "";
|
|
185
190
|
return generateAxiosFunction(method, formattedPath, allParams, responseTypeStr, parameters, requestBodyPayload);
|
|
186
191
|
}
|
|
187
|
-
const generateRandomString = () => Math.random().toString(36).
|
|
192
|
+
const generateRandomString = () => Math.random().toString(36).slice(7);
|
|
188
193
|
function fileTemplate(tsString, typeForImport, baseURL) {
|
|
189
194
|
const templateCode = `import ax from 'axios';
|
|
190
195
|
import type { AxiosResponse } from 'axios';
|
|
@@ -198,7 +203,7 @@ function fileTemplate(tsString, typeForImport, baseURL) {
|
|
|
198
203
|
const functionsInventory = {};
|
|
199
204
|
const pathOperations = [];
|
|
200
205
|
function hasConflict(path, method) {
|
|
201
|
-
const cleanPathName = path.split("/").filter((p) => p &&
|
|
206
|
+
const cleanPathName = path.split("/").filter((p) => p && !/\{|\}/.test(p)).join("/");
|
|
202
207
|
const matchingPaths = pathOperations.filter((p) => p.path === cleanPathName && p.method === method);
|
|
203
208
|
pathOperations.push({ path: cleanPathName, method });
|
|
204
209
|
return matchingPaths.length > 0;
|
|
@@ -208,7 +213,7 @@ function createFunctionPlaceholder(path, method, operation) {
|
|
|
208
213
|
functionsInventory[funcID] = generateFunctionForOperation(method, path, operation);
|
|
209
214
|
return funcID;
|
|
210
215
|
}
|
|
211
|
-
function handlePathSegment(path, operation, existingObj =
|
|
216
|
+
function handlePathSegment(path, operation, existingObj = {}) {
|
|
212
217
|
const methods = Object.keys(operation);
|
|
213
218
|
const obj = {};
|
|
214
219
|
for (const method of methods) {
|
|
@@ -226,7 +231,7 @@ function generateFunctions(paths, baseUrl) {
|
|
|
226
231
|
const body = {};
|
|
227
232
|
const allPathsClean = Object.keys(paths).map(cleanPath);
|
|
228
233
|
for (const [path, operation] of Object.entries(paths)) {
|
|
229
|
-
const splitPath = path.split("/").filter((p) => p &&
|
|
234
|
+
const splitPath = path.split("/").filter((p) => p && !/\{|\}/.test(p));
|
|
230
235
|
splitPath.reduce((acc, key, index, array) => {
|
|
231
236
|
const objFuncKey = toCamelCase(key);
|
|
232
237
|
if (!objFuncKey)
|
|
@@ -245,7 +250,7 @@ function generateFunctions(paths, baseUrl) {
|
|
|
245
250
|
}, body);
|
|
246
251
|
}
|
|
247
252
|
for (const [parent, object] of Object.entries(body)) {
|
|
248
|
-
tsString += `export const ${parent} = ${JSON.stringify(object,
|
|
253
|
+
tsString += `export const ${parent} = ${JSON.stringify(object, void 0, 2)};
|
|
249
254
|
`;
|
|
250
255
|
}
|
|
251
256
|
Object.entries(functionsInventory).forEach(([key, value]) => {
|
|
@@ -324,7 +329,7 @@ class DataRequest {
|
|
|
324
329
|
async get() {
|
|
325
330
|
if (!this.data_table)
|
|
326
331
|
throw new Error("Data table not set");
|
|
327
|
-
const filterStr = Object.keys(this._filter).length ? `?filter={${Object.entries(this._filter).map(([k, v]) => `${k}:${v}`).join(",")}}` : "";
|
|
332
|
+
const filterStr = Object.keys(this._filter).length > 0 ? `?filter={${Object.entries(this._filter).map(([k, v]) => `${k}:${v}`).join(",")}}` : "";
|
|
328
333
|
const url = `/data/${this.data_table}${this.itemID ? `/${this.itemID}` : ""}${filterStr}`;
|
|
329
334
|
try {
|
|
330
335
|
const { data } = await axios.get(url);
|
|
@@ -370,7 +375,7 @@ function responses(key) {
|
|
|
370
375
|
class BagelAuth {
|
|
371
376
|
constructor(bagel) {
|
|
372
377
|
this.bagel = bagel;
|
|
373
|
-
__publicField(this, "user"
|
|
378
|
+
__publicField(this, "user");
|
|
374
379
|
this.bagel = bagel;
|
|
375
380
|
}
|
|
376
381
|
async validateUser() {
|
|
@@ -380,8 +385,7 @@ class BagelAuth {
|
|
|
380
385
|
});
|
|
381
386
|
this.user = usr;
|
|
382
387
|
return usr;
|
|
383
|
-
} catch
|
|
384
|
-
return null;
|
|
388
|
+
} catch {
|
|
385
389
|
}
|
|
386
390
|
}
|
|
387
391
|
async resetPassword(ctx) {
|
|
@@ -421,7 +425,7 @@ class BagelAuth {
|
|
|
421
425
|
this.bagel.onError?.(err);
|
|
422
426
|
console.log(err);
|
|
423
427
|
}
|
|
424
|
-
this.user =
|
|
428
|
+
this.user = void 0;
|
|
425
429
|
}
|
|
426
430
|
async acceptInvite(token, user) {
|
|
427
431
|
await axios.post(`/auth/accept-invite/${token}`, user);
|
|
@@ -442,7 +446,7 @@ class Bagel {
|
|
|
442
446
|
constructor({ host, onError }) {
|
|
443
447
|
__publicField(this, "host");
|
|
444
448
|
__publicField(this, "onError");
|
|
445
|
-
__publicField(this, "read_table"
|
|
449
|
+
__publicField(this, "read_table");
|
|
446
450
|
__publicField(this, "auth", new BagelAuth(this));
|
|
447
451
|
this.host = host?.replace(/\/$/, "");
|
|
448
452
|
if (!this.host) {
|
|
@@ -457,7 +461,7 @@ class Bagel {
|
|
|
457
461
|
return new DataRequest(table, this);
|
|
458
462
|
}
|
|
459
463
|
_endpointCleaner(endpoint) {
|
|
460
|
-
const url = `${endpoint.replace(/^\//, "").
|
|
464
|
+
const url = `${endpoint.replace(/^\//, "").replaceAll(/\/$/g, "")}`;
|
|
461
465
|
return url;
|
|
462
466
|
}
|
|
463
467
|
async api(endpoint, query) {
|
|
@@ -470,7 +474,7 @@ class Bagel {
|
|
|
470
474
|
async get(endpoint, query) {
|
|
471
475
|
this._setAuthorization();
|
|
472
476
|
endpoint = this._endpointCleaner(endpoint);
|
|
473
|
-
if (
|
|
477
|
+
if (/undefined|null/.test(endpoint))
|
|
474
478
|
throw new Error(`Invalid endpoint: ${endpoint}`);
|
|
475
479
|
if (query) {
|
|
476
480
|
const queryParams = Object.entries(query).filter(([_, value]) => !!value).map(([key, value]) => `${key}=${value}`).join("&");
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -33,7 +33,7 @@ class DataRequest<T extends Tables = Tables> {
|
|
|
33
33
|
|
|
34
34
|
itemID: string
|
|
35
35
|
|
|
36
|
-
_filter:
|
|
36
|
+
_filter: { [key: string]: any } = {}
|
|
37
37
|
|
|
38
38
|
constructor(table: T, bagel: Bagel) {
|
|
39
39
|
this.data_table = table
|
|
@@ -41,13 +41,13 @@ class DataRequest<T extends Tables = Tables> {
|
|
|
41
41
|
this.itemID = ''
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
async post(item:
|
|
44
|
+
async post(item: { [key: string]: any }): Promise<{ [key: string]: any }> {
|
|
45
45
|
if (!this.data_table) throw new Error('Data table not set')
|
|
46
46
|
const { data } = await axios.post(`/data/${this.data_table}`, item)
|
|
47
47
|
return data
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
filter(filter:
|
|
50
|
+
filter(filter: { [key: string]: any }) {
|
|
51
51
|
this._filter = filter
|
|
52
52
|
return this
|
|
53
53
|
}
|
|
@@ -56,7 +56,7 @@ class DataRequest<T extends Tables = Tables> {
|
|
|
56
56
|
TableToTypeMapping[T] | TableToTypeMapping[T][] | undefined
|
|
57
57
|
> {
|
|
58
58
|
if (!this.data_table) throw new Error('Data table not set')
|
|
59
|
-
const filterStr = Object.keys(this._filter).length
|
|
59
|
+
const filterStr = Object.keys(this._filter).length > 0
|
|
60
60
|
? `?filter={${Object.entries(this._filter)
|
|
61
61
|
.map(([k, v]) => `${k}:${v}`)
|
|
62
62
|
.join(',')}}`
|
|
@@ -87,7 +87,7 @@ class DataRequest<T extends Tables = Tables> {
|
|
|
87
87
|
return data
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
async put(updatedItem:
|
|
90
|
+
async put(updatedItem: { [key: string]: any }): Promise<{ [key: string]: any }> {
|
|
91
91
|
const { data_table, itemID } = this
|
|
92
92
|
if (!data_table) throw new Error('Data table not set')
|
|
93
93
|
if (!itemID) throw new Error('Item ID not set')
|
|
@@ -100,7 +100,7 @@ class DataRequest<T extends Tables = Tables> {
|
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
function responses(key: string) {
|
|
103
|
-
const res:
|
|
103
|
+
const res: { [key: string]: string } = {
|
|
104
104
|
LOGIN_BAD_CREDENTIALS: 'Invalid username or password',
|
|
105
105
|
RESET_PASSWORD_BAD_TOKEN: 'This reset password link is invalid or expired.',
|
|
106
106
|
}
|
|
@@ -112,17 +112,17 @@ class BagelAuth {
|
|
|
112
112
|
this.bagel = bagel
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
user: User |
|
|
115
|
+
user: User | undefined = undefined
|
|
116
116
|
|
|
117
|
-
async validateUser(): Promise<User |
|
|
117
|
+
async validateUser(): Promise<User | undefined> {
|
|
118
118
|
try {
|
|
119
119
|
const { data: usr } = await axios.get('/users/me', {
|
|
120
120
|
withCredentials: true,
|
|
121
121
|
})
|
|
122
122
|
this.user = usr
|
|
123
123
|
return usr
|
|
124
|
-
} catch
|
|
125
|
-
|
|
124
|
+
} catch {
|
|
125
|
+
//
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
128
|
|
|
@@ -140,7 +140,7 @@ class BagelAuth {
|
|
|
140
140
|
}
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
-
async login(user: User): Promise<User |
|
|
143
|
+
async login(user: User): Promise<User | undefined> {
|
|
144
144
|
const formData = new FormData()
|
|
145
145
|
formData.append('username', user.email || '')
|
|
146
146
|
formData.append('password', user.password || '')
|
|
@@ -166,15 +166,15 @@ class BagelAuth {
|
|
|
166
166
|
this.bagel.onError?.(err)
|
|
167
167
|
console.log(err)
|
|
168
168
|
}
|
|
169
|
-
this.user =
|
|
169
|
+
this.user = undefined
|
|
170
170
|
}
|
|
171
171
|
|
|
172
|
-
async acceptInvite(token: string, user:
|
|
172
|
+
async acceptInvite(token: string, user: { [key: string]: any }) {
|
|
173
173
|
await axios.post(`/auth/accept-invite/${token}`, user)
|
|
174
174
|
await this.login(user as User)
|
|
175
175
|
}
|
|
176
176
|
|
|
177
|
-
async register(user:
|
|
177
|
+
async register(user: { [key: string]: any }, errors: { [key: string]: any }) {
|
|
178
178
|
try {
|
|
179
179
|
await axios.post<User>('/auth/register', user)
|
|
180
180
|
return this.login(user as User)
|
|
@@ -192,7 +192,7 @@ export class Bagel {
|
|
|
192
192
|
|
|
193
193
|
onError?: (err: any) => void
|
|
194
194
|
|
|
195
|
-
constructor({ host, onError }:
|
|
195
|
+
constructor({ host, onError }: { [key: string]: any }) {
|
|
196
196
|
this.host = host?.replace(/\/$/, '')
|
|
197
197
|
if (!this.host) {
|
|
198
198
|
throw new Error(
|
|
@@ -203,7 +203,7 @@ export class Bagel {
|
|
|
203
203
|
this.onError = onError
|
|
204
204
|
}
|
|
205
205
|
|
|
206
|
-
read_table: Tables |
|
|
206
|
+
read_table: Tables | undefined = undefined
|
|
207
207
|
|
|
208
208
|
data(table: Tables): DataRequest<Tables> {
|
|
209
209
|
return new DataRequest(table, this)
|
|
@@ -212,14 +212,14 @@ export class Bagel {
|
|
|
212
212
|
auth = new BagelAuth(this)
|
|
213
213
|
|
|
214
214
|
_endpointCleaner(endpoint: string) {
|
|
215
|
-
const url = `${endpoint.replace(/^\//, '').
|
|
215
|
+
const url = `${endpoint.replace(/^\//, '').replaceAll(/\/$/g, '')}`
|
|
216
216
|
return url
|
|
217
217
|
}
|
|
218
218
|
|
|
219
219
|
async api(
|
|
220
220
|
endpoint: string,
|
|
221
|
-
query?:
|
|
222
|
-
): Promise<
|
|
221
|
+
query?: { [key: string]: string },
|
|
222
|
+
): Promise<{ [key: string]: any }> {
|
|
223
223
|
if (query) {
|
|
224
224
|
const queryParams = Object.entries(query)
|
|
225
225
|
.map(([key, value]) => `${key}=${value}`)
|
|
@@ -231,13 +231,14 @@ export class Bagel {
|
|
|
231
231
|
.then(({ data }: { data: any }) => data)
|
|
232
232
|
}
|
|
233
233
|
|
|
234
|
-
async get<T =
|
|
234
|
+
async get<T = { [key: string]: any }>(
|
|
235
235
|
endpoint: string,
|
|
236
|
-
query?:
|
|
236
|
+
query?: { [key: string]: any },
|
|
237
237
|
): Promise<T> {
|
|
238
238
|
this._setAuthorization()
|
|
239
239
|
endpoint = this._endpointCleaner(endpoint)
|
|
240
|
-
if (
|
|
240
|
+
if ((/undefined|null/).test(endpoint)) throw new Error(`Invalid endpoint: ${endpoint}`)
|
|
241
|
+
|
|
241
242
|
if (query) {
|
|
242
243
|
const queryParams = Object.entries(query)
|
|
243
244
|
.filter(([_, value]) => !!value)
|
|
@@ -255,7 +256,7 @@ export class Bagel {
|
|
|
255
256
|
})
|
|
256
257
|
}
|
|
257
258
|
|
|
258
|
-
async delete(endpoint: string): Promise<
|
|
259
|
+
async delete(endpoint: string): Promise<{ [key: string]: any }> {
|
|
259
260
|
this._setAuthorization()
|
|
260
261
|
endpoint = this._endpointCleaner(endpoint)
|
|
261
262
|
return axios
|
|
@@ -267,7 +268,7 @@ export class Bagel {
|
|
|
267
268
|
})
|
|
268
269
|
}
|
|
269
270
|
|
|
270
|
-
async put(endpoint: string, payload: any): Promise<
|
|
271
|
+
async put(endpoint: string, payload: any): Promise<{ [key: string]: any }> {
|
|
271
272
|
endpoint = this._endpointCleaner(endpoint)
|
|
272
273
|
this._setAuthorization()
|
|
273
274
|
return axios
|
|
@@ -282,7 +283,7 @@ export class Bagel {
|
|
|
282
283
|
async patch(
|
|
283
284
|
endpoint: string,
|
|
284
285
|
payload: any = {},
|
|
285
|
-
): Promise<
|
|
286
|
+
): Promise<{ [key: string]: any }> {
|
|
286
287
|
endpoint = this._endpointCleaner(endpoint)
|
|
287
288
|
return axios
|
|
288
289
|
.patch(`/${endpoint}`, payload)
|
|
@@ -303,7 +304,7 @@ export class Bagel {
|
|
|
303
304
|
async post(
|
|
304
305
|
endpoint: string,
|
|
305
306
|
payload: any = {},
|
|
306
|
-
): Promise<
|
|
307
|
+
): Promise<{ [key: string]: any }> {
|
|
307
308
|
this._setAuthorization()
|
|
308
309
|
endpoint = this._endpointCleaner(endpoint)
|
|
309
310
|
return axios
|
|
@@ -18,6 +18,8 @@ import {
|
|
|
18
18
|
|
|
19
19
|
const allTypes: string[] = []
|
|
20
20
|
|
|
21
|
+
const primitiveTypes = ['string', 'number', 'boolean', 'null', 'void', 'any', 'Record<string, any>', 'undefined', '{ [key: string]: any }']
|
|
22
|
+
|
|
21
23
|
function collectTypeForImportStatement(typeName: string) {
|
|
22
24
|
typeName = typeName.trim().replace('[]', '')
|
|
23
25
|
if (typeName.includes('|')) {
|
|
@@ -26,16 +28,15 @@ function collectTypeForImportStatement(typeName: string) {
|
|
|
26
28
|
)
|
|
27
29
|
return
|
|
28
30
|
}
|
|
29
|
-
const primitiveTypes = ['string', 'number', 'boolean', 'null', 'void', 'any', 'Record<string, any>']
|
|
30
31
|
const isPrimitive = primitiveTypes.includes(typeName)
|
|
31
32
|
typeName = formatType(typeName)
|
|
32
33
|
if (!typeName || isPrimitive) return
|
|
33
34
|
if (!allTypes.includes(typeName)) allTypes.push(typeName)
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
function getResponseType(response: ResponseObject): string |
|
|
37
|
+
function getResponseType(response: ResponseObject): string | undefined {
|
|
37
38
|
const mediaTypeObject = response.content?.['application/json']
|
|
38
|
-
if (!mediaTypeObject || !mediaTypeObject.schema) return
|
|
39
|
+
if (!mediaTypeObject || !mediaTypeObject.schema) return
|
|
39
40
|
const responseType = schemaToType(mediaTypeObject.schema)
|
|
40
41
|
collectTypeForImportStatement(responseType)
|
|
41
42
|
return responseType
|
|
@@ -101,7 +102,7 @@ function formatPathWithParams(path: string) {
|
|
|
101
102
|
return formattedPath
|
|
102
103
|
}
|
|
103
104
|
|
|
104
|
-
function generateRequestBody(requestBody?: RequestBodyObject):
|
|
105
|
+
function generateRequestBody(requestBody?: RequestBodyObject): { [key: string]: string } {
|
|
105
106
|
const bodySchema = requestBody?.content['application/json']?.schema
|
|
106
107
|
if (!bodySchema) return { requestBodyParam: '', requestBodyPayload: '' }
|
|
107
108
|
const requestBodyType = schemaToType(bodySchema)
|
|
@@ -170,7 +171,7 @@ function generateFunctionForOperation(method: string, path: string, operation: O
|
|
|
170
171
|
return generateAxiosFunction(method, formattedPath, allParams, responseTypeStr, parameters, requestBodyPayload)
|
|
171
172
|
}
|
|
172
173
|
|
|
173
|
-
const generateRandomString = () => Math.random().toString(36).
|
|
174
|
+
const generateRandomString = () => Math.random().toString(36).slice(7)
|
|
174
175
|
|
|
175
176
|
function fileTemplate(tsString: string, typeForImport: string[], baseURL: string) {
|
|
176
177
|
const templateCode = (
|
|
@@ -185,11 +186,11 @@ function fileTemplate(tsString: string, typeForImport: string[], baseURL: string
|
|
|
185
186
|
return templateCode.replace(doubleQuoteRegex, '$1:')
|
|
186
187
|
}
|
|
187
188
|
|
|
188
|
-
const functionsInventory:
|
|
189
|
+
const functionsInventory: { [key: string]: any } = {}
|
|
189
190
|
const pathOperations: any[] = []
|
|
190
191
|
|
|
191
192
|
function hasConflict(path: string, method: string) {
|
|
192
|
-
const cleanPathName = path.split('/').filter(p => p && !
|
|
193
|
+
const cleanPathName = path.split('/').filter(p => p && !(/\{|\}/).test(p)).join('/')
|
|
193
194
|
const matchingPaths = pathOperations.filter(p => p.path === cleanPathName && p.method === method)
|
|
194
195
|
pathOperations.push({ path: cleanPathName, method })
|
|
195
196
|
return matchingPaths.length > 0
|
|
@@ -205,10 +206,10 @@ function createFunctionPlaceholder(path: string, method: string, operation: any)
|
|
|
205
206
|
function handlePathSegment(
|
|
206
207
|
path: string,
|
|
207
208
|
operation: any,
|
|
208
|
-
existingObj:
|
|
209
|
+
existingObj: { [key: string]: any } = {},
|
|
209
210
|
) {
|
|
210
211
|
const methods = Object.keys(operation)
|
|
211
|
-
const obj:
|
|
212
|
+
const obj: { [key: string]: any } = {}
|
|
212
213
|
for (const method of methods) {
|
|
213
214
|
let functionName = method.toLowerCase()
|
|
214
215
|
if (hasConflict(path, method)) {
|
|
@@ -222,10 +223,10 @@ function handlePathSegment(
|
|
|
222
223
|
|
|
223
224
|
export function generateFunctions(paths: PathsObject, baseUrl: string) {
|
|
224
225
|
let tsString = ''
|
|
225
|
-
const body:
|
|
226
|
+
const body: { [key: string]: any } = {}
|
|
226
227
|
const allPathsClean = Object.keys(paths).map(cleanPath)
|
|
227
228
|
for (const [path, operation] of Object.entries(paths)) {
|
|
228
|
-
const splitPath = path.split('/').filter(p => p && !
|
|
229
|
+
const splitPath = path.split('/').filter(p => p && !(/\{|\}/).test(p))
|
|
229
230
|
splitPath.reduce((acc, key: string, index: number, array: string[]) => {
|
|
230
231
|
const objFuncKey = toCamelCase(key)
|
|
231
232
|
if (!objFuncKey) return acc
|
|
@@ -248,7 +249,7 @@ export function generateFunctions(paths: PathsObject, baseUrl: string) {
|
|
|
248
249
|
}, body)
|
|
249
250
|
}
|
|
250
251
|
for (const [parent, object] of Object.entries(body)) {
|
|
251
|
-
tsString += `export const ${parent} = ${JSON.stringify(object,
|
|
252
|
+
tsString += `export const ${parent} = ${JSON.stringify(object, undefined, 2)};\n`
|
|
252
253
|
}
|
|
253
254
|
Object.entries(functionsInventory).forEach(([key, value]) => {
|
|
254
255
|
tsString = tsString.replace(`"${key}"`, value)
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { SchemaObject } from './openApiTypes'
|
|
2
2
|
|
|
3
|
-
export const toCamelCase = (str?: string) => str?.
|
|
4
|
-
export const toPascalCase = (str?: string) => str?.
|
|
3
|
+
export const toCamelCase = (str?: string) => str?.replaceAll(/[-._\s]+(.)?/g, (_, c) => c?.toUpperCase() || '').replace(/^./, str => str.toLowerCase()) || str
|
|
4
|
+
export const toPascalCase = (str?: string) => str?.replaceAll(/[-_\s]+(.)?/g, (_, c) => c?.toUpperCase() || '').replace(/^./, str => str.toUpperCase()) || str
|
|
5
5
|
|
|
6
6
|
export function formatType(typeName: string): string {
|
|
7
7
|
// eslint-disable-next-line regexp/no-unused-capturing-group
|
|
8
|
-
typeName = typeName.
|
|
8
|
+
typeName = typeName.replaceAll('-', '').replaceAll(/(post|put)$/gi, '').replaceAll(/^body_/gi, '')
|
|
9
9
|
return toPascalCase(typeName)!
|
|
10
10
|
}
|
|
11
11
|
|
|
@@ -22,7 +22,7 @@ export function schemaToType(schema?: SchemaObject): string {
|
|
|
22
22
|
if (schema.$ref) return resolveReference(schema.$ref)
|
|
23
23
|
switch (schema.type) {
|
|
24
24
|
case 'object':
|
|
25
|
-
return '
|
|
25
|
+
return '{ [key: string]: any }'
|
|
26
26
|
case 'string':
|
|
27
27
|
return 'string'
|
|
28
28
|
case 'integer':
|
|
@@ -33,6 +33,8 @@ export function schemaToType(schema?: SchemaObject): string {
|
|
|
33
33
|
return 'boolean'
|
|
34
34
|
case 'array':
|
|
35
35
|
return `${schemaToType(schema.items)}[]`
|
|
36
|
+
case 'undefined':
|
|
37
|
+
return 'undefined'
|
|
36
38
|
case 'null':
|
|
37
39
|
return 'null'
|
|
38
40
|
default:
|
|
@@ -43,14 +45,18 @@ export function schemaToType(schema?: SchemaObject): string {
|
|
|
43
45
|
export function isOptional(schema: SchemaObject) {
|
|
44
46
|
/// / !schema?.required?.includes(schema.title || '')
|
|
45
47
|
const type = schemaToType(schema)
|
|
46
|
-
|
|
48
|
+
const splitType = type.split(/\s+\|\s+/)
|
|
49
|
+
const includesNull = splitType.includes('null')
|
|
50
|
+
const includesUndefined = splitType.includes('undefined')
|
|
51
|
+
|
|
52
|
+
return includesNull || includesUndefined || schema.default !== undefined
|
|
47
53
|
}
|
|
48
54
|
|
|
49
|
-
export const
|
|
55
|
+
export const cleanOptionals = (str: string) => str.split(' | ').filter(t => t !== 'null' && t !== 'undefined').join(' | ')
|
|
50
56
|
|
|
51
|
-
export function formatVarType(varName: string, schema: any, required = false, defaultValue
|
|
57
|
+
export function formatVarType(varName: string, schema: any, required = false, defaultValue?: unknown) {
|
|
52
58
|
let type = schemaToType(schema)
|
|
53
|
-
type =
|
|
59
|
+
type = cleanOptionals(type)
|
|
54
60
|
|
|
55
61
|
let defaultStr = defaultValue ? ` = ${defaultValue}` : ''
|
|
56
62
|
|
|
@@ -64,5 +70,5 @@ export function formatVarType(varName: string, schema: any, required = false, de
|
|
|
64
70
|
}
|
|
65
71
|
|
|
66
72
|
export function cleanPath(path: string) {
|
|
67
|
-
return path.split('/').filter(p => p && !
|
|
73
|
+
return path.split('/').filter(p => p && !(/\{|\}/).test(p)).join('/')
|
|
68
74
|
}
|