@terreno/api 0.13.1 → 0.13.2
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/api.js +9 -0
- package/dist/api.test.js +2 -2
- package/dist/models/versionConfig.d.ts +1 -1
- package/dist/transformers.d.ts +5 -5
- package/dist/transformers.js +38 -37
- package/package.json +1 -1
- package/src/api.test.ts +2 -2
- package/src/api.ts +9 -0
- package/src/models/versionConfig.ts +1 -1
- package/src/openApiEtag.ts +1 -1
- package/src/transformers.ts +32 -30
package/dist/api.js
CHANGED
|
@@ -335,6 +335,9 @@ function _buildModelRouter(model, options) {
|
|
|
335
335
|
body = (0, transformers_1.transform)(options, req.body, "create", req.user);
|
|
336
336
|
}
|
|
337
337
|
catch (error) {
|
|
338
|
+
if ((0, errors_1.isAPIError)(error)) {
|
|
339
|
+
throw error;
|
|
340
|
+
}
|
|
338
341
|
throw new errors_1.APIError({
|
|
339
342
|
disableExternalErrorTracking: (0, errors_1.getDisableExternalErrorTracking)(error),
|
|
340
343
|
error: error,
|
|
@@ -687,6 +690,9 @@ function _buildModelRouter(model, options) {
|
|
|
687
690
|
body = (0, transformers_1.transform)(options, req.body, "update", req.user);
|
|
688
691
|
}
|
|
689
692
|
catch (error) {
|
|
693
|
+
if ((0, errors_1.isAPIError)(error)) {
|
|
694
|
+
throw error;
|
|
695
|
+
}
|
|
690
696
|
throw new errors_1.APIError({
|
|
691
697
|
disableExternalErrorTracking: (0, errors_1.getDisableExternalErrorTracking)(error),
|
|
692
698
|
error: error,
|
|
@@ -968,6 +974,9 @@ function _buildModelRouter(model, options) {
|
|
|
968
974
|
body = (0, transformers_1.transform)(options, body, "update", req.user);
|
|
969
975
|
}
|
|
970
976
|
catch (error) {
|
|
977
|
+
if ((0, errors_1.isAPIError)(error)) {
|
|
978
|
+
throw error;
|
|
979
|
+
}
|
|
971
980
|
throw new errors_1.APIError({
|
|
972
981
|
disableExternalErrorTracking: (0, errors_1.getDisableExternalErrorTracking)(error),
|
|
973
982
|
error: error,
|
package/dist/api.test.js
CHANGED
|
@@ -774,7 +774,7 @@ var transformers_1 = require("./transformers");
|
|
|
774
774
|
}),
|
|
775
775
|
}));
|
|
776
776
|
server = (0, supertest_1.default)(app);
|
|
777
|
-
return [4 /*yield*/, server.post("/food").send({ calories: 15, name: "Broccoli" }).expect(
|
|
777
|
+
return [4 /*yield*/, server.post("/food").send({ calories: 15, name: "Broccoli" }).expect(403)];
|
|
778
778
|
case 1:
|
|
779
779
|
res = _a.sent();
|
|
780
780
|
(0, bun_test_1.expect)(res.body.title).toContain("cannot write fields");
|
|
@@ -1699,7 +1699,7 @@ var transformers_1 = require("./transformers");
|
|
|
1699
1699
|
}),
|
|
1700
1700
|
}));
|
|
1701
1701
|
server = (0, supertest_1.default)(app);
|
|
1702
|
-
return [4 /*yield*/, server.post("/food").send({ calories: 15, name: "Broccoli" }).expect(
|
|
1702
|
+
return [4 /*yield*/, server.post("/food").send({ calories: 15, name: "Broccoli" }).expect(403)];
|
|
1703
1703
|
case 1:
|
|
1704
1704
|
res = _a.sent();
|
|
1705
1705
|
(0, bun_test_1.expect)(res.body.title).toContain("cannot write fields");
|
|
@@ -12,6 +12,6 @@ export interface VersionConfigDocument extends mongoose.Document {
|
|
|
12
12
|
updated?: Date;
|
|
13
13
|
}
|
|
14
14
|
export interface VersionConfigModel extends mongoose.Model<VersionConfigDocument> {
|
|
15
|
-
findOneOrNone(query: Record<string,
|
|
15
|
+
findOneOrNone(query: Record<string, unknown>, errorArgs?: Partial<APIErrorConstructor>): Promise<(Document & VersionConfigDocument) | null>;
|
|
16
16
|
}
|
|
17
17
|
export declare const VersionConfig: VersionConfigModel;
|
package/dist/transformers.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export interface TerrenoTransformer<T> {
|
|
|
6
6
|
transform?: (obj: Partial<T>, method: "create" | "update", user?: User) => Partial<T> | undefined;
|
|
7
7
|
serialize?: (obj: T, user?: User) => Partial<T> | undefined;
|
|
8
8
|
}
|
|
9
|
-
export declare
|
|
9
|
+
export declare const AdminOwnerTransformer: <T>(options: {
|
|
10
10
|
anonReadFields?: string[];
|
|
11
11
|
authReadFields?: string[];
|
|
12
12
|
ownerReadFields?: string[];
|
|
@@ -15,11 +15,11 @@ export declare function AdminOwnerTransformer<T>(options: {
|
|
|
15
15
|
authWriteFields?: string[];
|
|
16
16
|
ownerWriteFields?: string[];
|
|
17
17
|
adminWriteFields?: string[];
|
|
18
|
-
})
|
|
19
|
-
export declare
|
|
20
|
-
export declare
|
|
18
|
+
}) => TerrenoTransformer<T>;
|
|
19
|
+
export declare const transform: <T>(options: ModelRouterOptions<T>, data: Partial<T> | Partial<T>[], method: "create" | "update", user?: User) => Partial<T> | (Partial<T> | undefined)[] | undefined;
|
|
20
|
+
export declare const serialize: <T>(req: express.Request, options: ModelRouterOptions<T>, data: (Document & T) | (Document & T)[]) => Partial<T> | (Partial<T> | undefined)[] | undefined;
|
|
21
21
|
/**
|
|
22
22
|
* Default response handler for modelRouter. Calls toObject on each doc and returns the result,
|
|
23
23
|
* using transformers.serializer if provided.
|
|
24
24
|
*/
|
|
25
|
-
export declare
|
|
25
|
+
export declare const defaultResponseHandler: <T>(doc: (Document & T) | (Document & T)[] | null, method: "list" | "create" | "read" | "update", request: express.Request, options: ModelRouterOptions<T>) => Promise<Partial<T> | (Partial<T> | undefined)[] | null | undefined>;
|
package/dist/transformers.js
CHANGED
|
@@ -72,13 +72,10 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
|
72
72
|
return to.concat(ar || Array.prototype.slice.call(from));
|
|
73
73
|
};
|
|
74
74
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
75
|
-
exports.AdminOwnerTransformer =
|
|
76
|
-
exports.transform = transform;
|
|
77
|
-
exports.serialize = serialize;
|
|
78
|
-
exports.defaultResponseHandler = defaultResponseHandler;
|
|
75
|
+
exports.defaultResponseHandler = exports.serialize = exports.transform = exports.AdminOwnerTransformer = void 0;
|
|
79
76
|
var errors_1 = require("./errors");
|
|
80
77
|
var logger_1 = require("./logger");
|
|
81
|
-
function
|
|
78
|
+
var getUserType = function (user, obj) {
|
|
82
79
|
if (user === null || user === void 0 ? void 0 : user.admin) {
|
|
83
80
|
return "admin";
|
|
84
81
|
}
|
|
@@ -89,9 +86,9 @@ function getUserType(user, obj) {
|
|
|
89
86
|
return "auth";
|
|
90
87
|
}
|
|
91
88
|
return "anon";
|
|
92
|
-
}
|
|
93
|
-
function
|
|
94
|
-
function
|
|
89
|
+
};
|
|
90
|
+
var AdminOwnerTransformer = function (options) {
|
|
91
|
+
var pickFields = function (obj, fields) {
|
|
95
92
|
var e_1, _a;
|
|
96
93
|
var newData = {};
|
|
97
94
|
try {
|
|
@@ -110,7 +107,7 @@ function AdminOwnerTransformer(options) {
|
|
|
110
107
|
finally { if (e_1) throw e_1.error; }
|
|
111
108
|
}
|
|
112
109
|
return newData;
|
|
113
|
-
}
|
|
110
|
+
};
|
|
114
111
|
return {
|
|
115
112
|
serialize: function (obj, user) {
|
|
116
113
|
var _a, _b, _c, _d;
|
|
@@ -126,7 +123,6 @@ function AdminOwnerTransformer(options) {
|
|
|
126
123
|
}
|
|
127
124
|
return pickFields(obj, __spreadArray(__spreadArray([], __read(((_d = options.anonReadFields) !== null && _d !== void 0 ? _d : [])), false), ["id"], false));
|
|
128
125
|
},
|
|
129
|
-
// TODO: Migrate AdminOwnerTransform to use pre-hooks.
|
|
130
126
|
transform: function (obj, _method, user) {
|
|
131
127
|
var _a, _b, _c, _d;
|
|
132
128
|
var userType = getUserType(user, obj);
|
|
@@ -145,13 +141,17 @@ function AdminOwnerTransformer(options) {
|
|
|
145
141
|
}
|
|
146
142
|
var unallowedFields = Object.keys(obj).filter(function (k) { return !allowedFields.includes(k); });
|
|
147
143
|
if (unallowedFields.length) {
|
|
148
|
-
throw new
|
|
144
|
+
throw new errors_1.APIError({
|
|
145
|
+
status: 403,
|
|
146
|
+
title: "User of type ".concat(userType, " cannot write fields: ").concat(unallowedFields.join(", ")),
|
|
147
|
+
});
|
|
149
148
|
}
|
|
150
149
|
return obj;
|
|
151
150
|
},
|
|
152
151
|
};
|
|
153
|
-
}
|
|
154
|
-
|
|
152
|
+
};
|
|
153
|
+
exports.AdminOwnerTransformer = AdminOwnerTransformer;
|
|
154
|
+
var transform = function (options, data, method, user) {
|
|
155
155
|
var _a, _b;
|
|
156
156
|
if (!((_a = options.transformer) === null || _a === void 0 ? void 0 : _a.transform)) {
|
|
157
157
|
return data;
|
|
@@ -163,8 +163,9 @@ function transform(options, data, method, user) {
|
|
|
163
163
|
return transformFn(data, method, user);
|
|
164
164
|
}
|
|
165
165
|
return data.map(function (d) { return transformFn(d, method, user); });
|
|
166
|
-
}
|
|
167
|
-
|
|
166
|
+
};
|
|
167
|
+
exports.transform = transform;
|
|
168
|
+
var serialize = function (req, options, data) {
|
|
168
169
|
var _a;
|
|
169
170
|
var serializeFn = function (serializeData, serializeUser) {
|
|
170
171
|
var _a, _b;
|
|
@@ -190,30 +191,30 @@ function serialize(req, options, data) {
|
|
|
190
191
|
return serializeFn(data, req.user);
|
|
191
192
|
}
|
|
192
193
|
return data.map(function (d) { return serializeFn(d, req.user); });
|
|
193
|
-
}
|
|
194
|
+
};
|
|
195
|
+
exports.serialize = serialize;
|
|
194
196
|
/**
|
|
195
197
|
* Default response handler for modelRouter. Calls toObject on each doc and returns the result,
|
|
196
198
|
* using transformers.serializer if provided.
|
|
197
199
|
*/
|
|
198
|
-
function
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
return [2 /*return*/];
|
|
217
|
-
});
|
|
200
|
+
var defaultResponseHandler = function (doc, method, request, options) { return __awaiter(void 0, void 0, void 0, function () {
|
|
201
|
+
var errorObj;
|
|
202
|
+
return __generator(this, function (_a) {
|
|
203
|
+
if (!doc) {
|
|
204
|
+
return [2 /*return*/, null];
|
|
205
|
+
}
|
|
206
|
+
try {
|
|
207
|
+
return [2 /*return*/, (0, exports.serialize)(request, options, doc)];
|
|
208
|
+
}
|
|
209
|
+
catch (error) {
|
|
210
|
+
errorObj = error;
|
|
211
|
+
throw new errors_1.APIError({
|
|
212
|
+
error: errorObj,
|
|
213
|
+
status: 400,
|
|
214
|
+
title: "Error serializing ".concat(method, " response: ").concat(errorObj.message),
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
return [2 /*return*/];
|
|
218
218
|
});
|
|
219
|
-
}
|
|
219
|
+
}); };
|
|
220
|
+
exports.defaultResponseHandler = defaultResponseHandler;
|
package/package.json
CHANGED
package/src/api.test.ts
CHANGED
|
@@ -576,7 +576,7 @@ describe("@terreno/api", () => {
|
|
|
576
576
|
);
|
|
577
577
|
server = supertest(app);
|
|
578
578
|
|
|
579
|
-
const res = await server.post("/food").send({calories: 15, name: "Broccoli"}).expect(
|
|
579
|
+
const res = await server.post("/food").send({calories: 15, name: "Broccoli"}).expect(403);
|
|
580
580
|
expect(res.body.title).toContain("cannot write fields");
|
|
581
581
|
});
|
|
582
582
|
|
|
@@ -1324,7 +1324,7 @@ describe("@terreno/api", () => {
|
|
|
1324
1324
|
);
|
|
1325
1325
|
server = supertest(app);
|
|
1326
1326
|
|
|
1327
|
-
const res = await server.post("/food").send({calories: 15, name: "Broccoli"}).expect(
|
|
1327
|
+
const res = await server.post("/food").send({calories: 15, name: "Broccoli"}).expect(403);
|
|
1328
1328
|
expect(res.body.title).toContain("cannot write fields");
|
|
1329
1329
|
});
|
|
1330
1330
|
|
package/src/api.ts
CHANGED
|
@@ -528,6 +528,9 @@ function _buildModelRouter<T>(model: Model<T>, options: ModelRouterOptions<T>):
|
|
|
528
528
|
try {
|
|
529
529
|
body = transform<T>(options, req.body, "create", req.user);
|
|
530
530
|
} catch (error: any) {
|
|
531
|
+
if (isAPIError(error)) {
|
|
532
|
+
throw error;
|
|
533
|
+
}
|
|
531
534
|
throw new APIError({
|
|
532
535
|
disableExternalErrorTracking: getDisableExternalErrorTracking(error),
|
|
533
536
|
error,
|
|
@@ -827,6 +830,9 @@ function _buildModelRouter<T>(model: Model<T>, options: ModelRouterOptions<T>):
|
|
|
827
830
|
try {
|
|
828
831
|
body = transform<T>(options, req.body, "update", req.user);
|
|
829
832
|
} catch (error: any) {
|
|
833
|
+
if (isAPIError(error)) {
|
|
834
|
+
throw error;
|
|
835
|
+
}
|
|
830
836
|
throw new APIError({
|
|
831
837
|
disableExternalErrorTracking: getDisableExternalErrorTracking(error),
|
|
832
838
|
error,
|
|
@@ -1080,6 +1086,9 @@ function _buildModelRouter<T>(model: Model<T>, options: ModelRouterOptions<T>):
|
|
|
1080
1086
|
try {
|
|
1081
1087
|
body = transform<T>(options, body, "update", req.user) as Partial<T>;
|
|
1082
1088
|
} catch (error: any) {
|
|
1089
|
+
if (isAPIError(error)) {
|
|
1090
|
+
throw error;
|
|
1091
|
+
}
|
|
1083
1092
|
throw new APIError({
|
|
1084
1093
|
disableExternalErrorTracking: getDisableExternalErrorTracking(error),
|
|
1085
1094
|
error,
|
|
@@ -17,7 +17,7 @@ export interface VersionConfigDocument extends mongoose.Document {
|
|
|
17
17
|
|
|
18
18
|
export interface VersionConfigModel extends mongoose.Model<VersionConfigDocument> {
|
|
19
19
|
findOneOrNone(
|
|
20
|
-
query: Record<string,
|
|
20
|
+
query: Record<string, unknown>,
|
|
21
21
|
errorArgs?: Partial<APIErrorConstructor>
|
|
22
22
|
): Promise<(Document & VersionConfigDocument) | null>;
|
|
23
23
|
}
|
package/src/openApiEtag.ts
CHANGED
|
@@ -14,7 +14,7 @@ export const openApiEtagMiddleware = (req: Request, res: Response, next: NextFun
|
|
|
14
14
|
|
|
15
15
|
const originalJson = res.json.bind(res);
|
|
16
16
|
|
|
17
|
-
res.json = (body:
|
|
17
|
+
res.json = (body: unknown) => {
|
|
18
18
|
const jsonString = JSON.stringify(body);
|
|
19
19
|
const etag = `"${crypto.createHash("sha256").update(jsonString).digest("hex").substring(0, 16)}"`;
|
|
20
20
|
|
package/src/transformers.ts
CHANGED
|
@@ -15,7 +15,10 @@ export interface TerrenoTransformer<T> {
|
|
|
15
15
|
serialize?: (obj: T, user?: User) => Partial<T> | undefined;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
const getUserType = (
|
|
19
|
+
user?: User,
|
|
20
|
+
obj?: Record<string, unknown>
|
|
21
|
+
): "anon" | "auth" | "owner" | "admin" => {
|
|
19
22
|
if (user?.admin) {
|
|
20
23
|
return "admin";
|
|
21
24
|
}
|
|
@@ -26,10 +29,9 @@ function getUserType(user?: User, obj?: any): "anon" | "auth" | "owner" | "admin
|
|
|
26
29
|
return "auth";
|
|
27
30
|
}
|
|
28
31
|
return "anon";
|
|
29
|
-
}
|
|
32
|
+
};
|
|
30
33
|
|
|
31
|
-
export
|
|
32
|
-
// TODO: do something with KeyOf here.
|
|
34
|
+
export const AdminOwnerTransformer = <T>(options: {
|
|
33
35
|
anonReadFields?: string[];
|
|
34
36
|
authReadFields?: string[];
|
|
35
37
|
ownerReadFields?: string[];
|
|
@@ -38,20 +40,20 @@ export function AdminOwnerTransformer<T>(options: {
|
|
|
38
40
|
authWriteFields?: string[];
|
|
39
41
|
ownerWriteFields?: string[];
|
|
40
42
|
adminWriteFields?: string[];
|
|
41
|
-
}): TerrenoTransformer<T> {
|
|
42
|
-
|
|
43
|
+
}): TerrenoTransformer<T> => {
|
|
44
|
+
const pickFields = (obj: Partial<T>, fields: string[]): Partial<T> => {
|
|
43
45
|
const newData: Partial<T> = {};
|
|
44
46
|
for (const field of fields) {
|
|
45
|
-
if (obj[field] !== undefined) {
|
|
46
|
-
newData[field] = obj[field];
|
|
47
|
+
if ((obj as Record<string, unknown>)[field] !== undefined) {
|
|
48
|
+
(newData as Record<string, unknown>)[field] = (obj as Record<string, unknown>)[field];
|
|
47
49
|
}
|
|
48
50
|
}
|
|
49
51
|
return newData;
|
|
50
|
-
}
|
|
52
|
+
};
|
|
51
53
|
|
|
52
54
|
return {
|
|
53
55
|
serialize: (obj: T, user?: User) => {
|
|
54
|
-
const userType = getUserType(user, obj);
|
|
56
|
+
const userType = getUserType(user, obj as Record<string, unknown>);
|
|
55
57
|
if (userType === "admin") {
|
|
56
58
|
return pickFields(obj, [...(options.adminReadFields ?? []), "id"]);
|
|
57
59
|
}
|
|
@@ -63,10 +65,9 @@ export function AdminOwnerTransformer<T>(options: {
|
|
|
63
65
|
}
|
|
64
66
|
return pickFields(obj, [...(options.anonReadFields ?? []), "id"]);
|
|
65
67
|
},
|
|
66
|
-
// TODO: Migrate AdminOwnerTransform to use pre-hooks.
|
|
67
68
|
transform: (obj: Partial<T>, _method: "create" | "update", user?: User) => {
|
|
68
|
-
const userType = getUserType(user, obj);
|
|
69
|
-
let allowedFields:
|
|
69
|
+
const userType = getUserType(user, obj as Record<string, unknown>);
|
|
70
|
+
let allowedFields: string[];
|
|
70
71
|
if (userType === "admin") {
|
|
71
72
|
allowedFields = options.adminWriteFields ?? [];
|
|
72
73
|
} else if (userType === "owner") {
|
|
@@ -78,21 +79,22 @@ export function AdminOwnerTransformer<T>(options: {
|
|
|
78
79
|
}
|
|
79
80
|
const unallowedFields = Object.keys(obj).filter((k) => !allowedFields.includes(k));
|
|
80
81
|
if (unallowedFields.length) {
|
|
81
|
-
throw new
|
|
82
|
-
|
|
83
|
-
|
|
82
|
+
throw new APIError({
|
|
83
|
+
status: 403,
|
|
84
|
+
title: `User of type ${userType} cannot write fields: ${unallowedFields.join(", ")}`,
|
|
85
|
+
});
|
|
84
86
|
}
|
|
85
87
|
return obj;
|
|
86
88
|
},
|
|
87
89
|
};
|
|
88
|
-
}
|
|
90
|
+
};
|
|
89
91
|
|
|
90
|
-
export
|
|
92
|
+
export const transform = <T>(
|
|
91
93
|
options: ModelRouterOptions<T>,
|
|
92
94
|
data: Partial<T> | Partial<T>[],
|
|
93
95
|
method: "create" | "update",
|
|
94
96
|
user?: User
|
|
95
|
-
) {
|
|
97
|
+
) => {
|
|
96
98
|
if (!options.transformer?.transform) {
|
|
97
99
|
return data;
|
|
98
100
|
}
|
|
@@ -108,16 +110,16 @@ export function transform<T>(
|
|
|
108
110
|
return transformFn(data, method, user);
|
|
109
111
|
}
|
|
110
112
|
return data.map((d) => transformFn(d, method, user));
|
|
111
|
-
}
|
|
113
|
+
};
|
|
112
114
|
|
|
113
|
-
export
|
|
115
|
+
export const serialize = <T>(
|
|
114
116
|
req: express.Request,
|
|
115
117
|
options: ModelRouterOptions<T>,
|
|
116
|
-
data: (Document
|
|
117
|
-
) {
|
|
118
|
-
const serializeFn = (serializeData: Document
|
|
118
|
+
data: (Document & T) | (Document & T)[]
|
|
119
|
+
) => {
|
|
120
|
+
const serializeFn = (serializeData: Document & T, serializeUser?: User) => {
|
|
119
121
|
const dataObject = serializeData.toObject() as T;
|
|
120
|
-
(dataObject as
|
|
122
|
+
(dataObject as Record<string, unknown>).id = serializeData._id;
|
|
121
123
|
|
|
122
124
|
// Search for any value that is a Map and transform it to a plain object.
|
|
123
125
|
// Otherwise Express drops the contents.
|
|
@@ -143,18 +145,18 @@ export function serialize<T>(
|
|
|
143
145
|
return serializeFn(data, req.user);
|
|
144
146
|
}
|
|
145
147
|
return data.map((d) => serializeFn(d, req.user));
|
|
146
|
-
}
|
|
148
|
+
};
|
|
147
149
|
|
|
148
150
|
/**
|
|
149
151
|
* Default response handler for modelRouter. Calls toObject on each doc and returns the result,
|
|
150
152
|
* using transformers.serializer if provided.
|
|
151
153
|
*/
|
|
152
|
-
export async
|
|
153
|
-
doc: (Document
|
|
154
|
+
export const defaultResponseHandler = async <T>(
|
|
155
|
+
doc: (Document & T) | (Document & T)[] | null,
|
|
154
156
|
method: "list" | "create" | "read" | "update",
|
|
155
157
|
request: express.Request,
|
|
156
158
|
options: ModelRouterOptions<T>
|
|
157
|
-
) {
|
|
159
|
+
) => {
|
|
158
160
|
if (!doc) {
|
|
159
161
|
return null;
|
|
160
162
|
}
|
|
@@ -168,4 +170,4 @@ export async function defaultResponseHandler<T>(
|
|
|
168
170
|
title: `Error serializing ${method} response: ${errorObj.message}`,
|
|
169
171
|
});
|
|
170
172
|
}
|
|
171
|
-
}
|
|
173
|
+
};
|