@randajan/api-kit 2.0.0 → 3.0.0
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/README.md +332 -72
- package/dist/cjs/client/index.cjs +236 -199
- package/dist/cjs/client/index.cjs.map +4 -4
- package/dist/cjs/index.cjs +263 -208
- package/dist/cjs/index.cjs.map +4 -4
- package/dist/cjs/server/index.cjs +102 -56
- package/dist/cjs/server/index.cjs.map +4 -4
- package/dist/esm/chunk-4NYBELZF.js +309 -0
- package/dist/esm/chunk-4NYBELZF.js.map +7 -0
- package/dist/esm/{chunk-72RXZFQZ.js → chunk-IUVT7Q4N.js} +24 -6
- package/dist/esm/chunk-IUVT7Q4N.js.map +7 -0
- package/dist/esm/{chunk-7K2N7A5V.js → chunk-K7ZQO3VB.js} +97 -87
- package/dist/esm/chunk-K7ZQO3VB.js.map +7 -0
- package/dist/esm/client/index.mjs +4 -4
- package/dist/esm/index.mjs +7 -5
- package/dist/esm/server/index.mjs +4 -4
- package/package.json +1 -1
- package/dist/esm/chunk-72RXZFQZ.js.map +0 -7
- package/dist/esm/chunk-7K2N7A5V.js.map +0 -7
- package/dist/esm/chunk-CYUBH2V3.js +0 -280
- package/dist/esm/chunk-CYUBH2V3.js.map +0 -7
package/dist/cjs/index.cjs
CHANGED
|
@@ -20,17 +20,18 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
var index_exports = {};
|
|
21
21
|
__export(index_exports, {
|
|
22
22
|
Api: () => Api,
|
|
23
|
-
ApiError: () => ApiError,
|
|
24
23
|
Fetch: () => Fetch,
|
|
24
|
+
FetchError: () => FetchError,
|
|
25
|
+
HttpError: () => HttpError,
|
|
25
26
|
createApi: () => server_default,
|
|
26
27
|
createFetch: () => client_default
|
|
27
28
|
});
|
|
28
29
|
module.exports = __toCommonJS(index_exports);
|
|
29
30
|
|
|
30
31
|
// <define:__slib_info>
|
|
31
|
-
var define_slib_info_default = { isBuild: true, name: "@randajan/api-kit", description: "A lightweight wrapper around fetch that always returns a structured JSON response, handling errors and network issues gracefully", version: "
|
|
32
|
+
var define_slib_info_default = { isBuild: true, name: "@randajan/api-kit", description: "A lightweight wrapper around fetch that always returns a structured JSON response, handling errors and network issues gracefully", version: "2.0.0", author: { name: "Jan Randa", email: "jnranda@gmail.com", url: "https://www.linkedin.com/in/randajan/" }, env: "development", mode: "web", port: 3e3, dir: { root: "C:\\dev\\lib\\api-kit", dist: "dist" } };
|
|
32
33
|
|
|
33
|
-
// src/arc/class/
|
|
34
|
+
// src/arc/class/FetchError.js
|
|
34
35
|
var import_props = require("@randajan/props");
|
|
35
36
|
|
|
36
37
|
// src/arc/tool.js
|
|
@@ -57,44 +58,34 @@ var doFn = (any) => isFn(any) ? any() : any;
|
|
|
57
58
|
var isProm = (any) => any instanceof Promise;
|
|
58
59
|
var isErr = (any) => any instanceof Error;
|
|
59
60
|
|
|
60
|
-
// src/arc/class/
|
|
61
|
-
var
|
|
62
|
-
static create(code, message, httpStatusCode = 400, remoteStack = void 0) {
|
|
63
|
-
return new _ApiError(code, message, httpStatusCode, remoteStack);
|
|
64
|
-
}
|
|
61
|
+
// src/arc/class/FetchError.js
|
|
62
|
+
var FetchError = class _FetchError extends Error {
|
|
65
63
|
static is(any) {
|
|
66
|
-
return any instanceof
|
|
64
|
+
return any && any instanceof _FetchError;
|
|
67
65
|
}
|
|
68
|
-
static
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
const msg = toStr(any?.message || any) || "Unknown";
|
|
73
|
-
const apierr = _ApiError.create(code, msg, httpStatusCode);
|
|
74
|
-
return (0, import_props.solid)(apierr, "stack", any?.stack);
|
|
66
|
+
static code(code, message, opt = {}) {
|
|
67
|
+
opt.code = code;
|
|
68
|
+
return new _FetchError(message, opt);
|
|
75
69
|
}
|
|
76
|
-
constructor(
|
|
77
|
-
|
|
70
|
+
constructor(message, options = {}) {
|
|
71
|
+
const { code, ...opt } = options || {};
|
|
72
|
+
super(message, opt);
|
|
78
73
|
(0, import_props.safe)(this, {}, "code", (t, f) => mrgStr(t, f, "."));
|
|
79
|
-
(0, import_props.solid)(this, "httpStatusCode", httpStatusCode ?? 400, true);
|
|
80
|
-
(0, import_props.solid)(this, "remoteStack", remoteStack);
|
|
81
74
|
this.rise(code);
|
|
82
75
|
}
|
|
83
|
-
rise(code
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
(0, import_props.solid)(this, "_exposeStack", !!exposeStack, false, true);
|
|
76
|
+
rise(code) {
|
|
77
|
+
if (code == null) {
|
|
78
|
+
return this;
|
|
79
|
+
}
|
|
80
|
+
this.code = code;
|
|
89
81
|
return this;
|
|
90
82
|
}
|
|
91
83
|
toJSON() {
|
|
92
|
-
const { message,
|
|
84
|
+
const { message, cause } = this;
|
|
93
85
|
const body = { message, ...this };
|
|
94
|
-
if (
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
delete body.stack;
|
|
86
|
+
if (cause) {
|
|
87
|
+
const { message: message2, stack } = cause;
|
|
88
|
+
body.cause = { message: message2, stack };
|
|
98
89
|
}
|
|
99
90
|
return body;
|
|
100
91
|
}
|
|
@@ -104,8 +95,47 @@ var ApiError = class _ApiError extends Error {
|
|
|
104
95
|
}
|
|
105
96
|
};
|
|
106
97
|
|
|
98
|
+
// src/arc/class/HttpError.js
|
|
99
|
+
var import_props2 = require("@randajan/props");
|
|
100
|
+
var HttpError = class _HttpError extends FetchError {
|
|
101
|
+
static is(any) {
|
|
102
|
+
return any && any instanceof _HttpError;
|
|
103
|
+
}
|
|
104
|
+
static code(code, message, httpStatusCode = 400, opt = {}) {
|
|
105
|
+
opt.code = code;
|
|
106
|
+
return new _HttpError(message, httpStatusCode, opt);
|
|
107
|
+
}
|
|
108
|
+
constructor(message, httpStatusCode = 400, options = {}) {
|
|
109
|
+
const { detail, exposeCause, ...opt } = options || {};
|
|
110
|
+
const http = httpStatusCode ?? 400;
|
|
111
|
+
const msg = message || `HTTP:${http}`;
|
|
112
|
+
super(msg, opt);
|
|
113
|
+
(0, import_props2.safe)(this, {}, "_exposeCause", (t) => !!t, void 0, false);
|
|
114
|
+
this.detail = detail;
|
|
115
|
+
this.httpStatusCode = http;
|
|
116
|
+
this._exposeCause = exposeCause;
|
|
117
|
+
}
|
|
118
|
+
exposeCause(exposeCause = true) {
|
|
119
|
+
this._exposeCause = exposeCause;
|
|
120
|
+
return this;
|
|
121
|
+
}
|
|
122
|
+
toJSON() {
|
|
123
|
+
const { message, cause, _exposeCause } = this;
|
|
124
|
+
const body = { message, ...this };
|
|
125
|
+
if (_exposeCause && cause) {
|
|
126
|
+
const { message: message2, stack } = cause;
|
|
127
|
+
body.cause = { message: message2, stack, ...cause };
|
|
128
|
+
}
|
|
129
|
+
return body;
|
|
130
|
+
}
|
|
131
|
+
toString() {
|
|
132
|
+
const { httpStatusCode } = this;
|
|
133
|
+
return super.toString() + ` [${httpStatusCode}]`;
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
|
|
107
137
|
// src/server/class/Api.js
|
|
108
|
-
var
|
|
138
|
+
var import_props4 = require("@randajan/props");
|
|
109
139
|
|
|
110
140
|
// src/arc/class/Functionable.js
|
|
111
141
|
var Functionable = class extends Function {
|
|
@@ -137,10 +167,10 @@ var lockObject = (o) => {
|
|
|
137
167
|
var info = lockObject(define_slib_info_default);
|
|
138
168
|
var info_default = info;
|
|
139
169
|
|
|
140
|
-
// src/arc/
|
|
141
|
-
var
|
|
170
|
+
// src/arc/opt.js
|
|
171
|
+
var import_props3 = require("@randajan/props");
|
|
142
172
|
var start = (opt) => {
|
|
143
|
-
if (opt.
|
|
173
|
+
if (opt.timetrack) {
|
|
144
174
|
return opt.startAt = Date.now();
|
|
145
175
|
}
|
|
146
176
|
};
|
|
@@ -159,7 +189,7 @@ var endTime = (body, startAt) => {
|
|
|
159
189
|
time.netIn = body.time.startAt - startAt;
|
|
160
190
|
time.netOut = endAt - body.time.endAt;
|
|
161
191
|
}
|
|
162
|
-
body.time = (0,
|
|
192
|
+
body.time = (0, import_props3.solids)({}, time);
|
|
163
193
|
};
|
|
164
194
|
var end = (body, opt) => {
|
|
165
195
|
const hasError = !!body.error;
|
|
@@ -172,29 +202,23 @@ var end = (body, opt) => {
|
|
|
172
202
|
if (isFn(opt.onError)) {
|
|
173
203
|
opt.onError(body, opt);
|
|
174
204
|
}
|
|
175
|
-
if (opt.throwError
|
|
205
|
+
if (opt.throwError) {
|
|
176
206
|
throw body.error;
|
|
177
207
|
}
|
|
178
208
|
}
|
|
179
|
-
return
|
|
209
|
+
return Object.freeze(body);
|
|
180
210
|
};
|
|
181
|
-
var
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
if (v1 === v2) {
|
|
185
|
-
return;
|
|
186
|
-
}
|
|
187
|
-
const f1 = v1.split(".");
|
|
188
|
-
const f2 = v2.split(".");
|
|
189
|
-
if (f1[0] !== f2[0]) {
|
|
190
|
-
return "major";
|
|
191
|
-
}
|
|
192
|
-
if (f1[1] !== f2[1]) {
|
|
193
|
-
return "minor";
|
|
211
|
+
var createTrait = (trait) => {
|
|
212
|
+
if (!trait) {
|
|
213
|
+
return (opt) => opt;
|
|
194
214
|
}
|
|
195
|
-
if (
|
|
196
|
-
return
|
|
215
|
+
if (isFn(trait)) {
|
|
216
|
+
return trait;
|
|
197
217
|
}
|
|
218
|
+
throw new Error("config.trait should be a function");
|
|
219
|
+
};
|
|
220
|
+
var configTrait = (config) => {
|
|
221
|
+
config.trait = createTrait(config.trait);
|
|
198
222
|
};
|
|
199
223
|
|
|
200
224
|
// src/server/tool.js
|
|
@@ -221,15 +245,32 @@ var tryFn = (any) => {
|
|
|
221
245
|
}
|
|
222
246
|
return r.result.then(wrapResult).catch(wrapError);
|
|
223
247
|
};
|
|
248
|
+
var normalizeServerError = (any, opt) => {
|
|
249
|
+
let err = any;
|
|
250
|
+
if (!HttpError.is(err)) {
|
|
251
|
+
let custom = isFn(opt.normalizeError);
|
|
252
|
+
if (custom) {
|
|
253
|
+
try {
|
|
254
|
+
err = opt.normalizeError(err, opt);
|
|
255
|
+
} catch {
|
|
256
|
+
custom = false;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
if (!custom || !HttpError.is(err)) {
|
|
260
|
+
err = HttpError.code(0, "Unknown", 500, { cause: any });
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
return err.rise(1).rise(opt.code);
|
|
264
|
+
};
|
|
224
265
|
|
|
225
266
|
// src/server/class/static.js
|
|
226
267
|
var apiExit = (resp, opt) => {
|
|
227
|
-
const {
|
|
268
|
+
const { exposeCause } = opt;
|
|
228
269
|
resp.statusCode = 200;
|
|
229
270
|
if (resp.error) {
|
|
230
|
-
resp.error =
|
|
271
|
+
resp.error = normalizeServerError(resp.error, opt);
|
|
231
272
|
resp.statusCode = resp.error.httpStatusCode;
|
|
232
|
-
resp.error.
|
|
273
|
+
resp.error.exposeCause(!!exposeCause);
|
|
233
274
|
}
|
|
234
275
|
resp[info_default.name] = info_default.version;
|
|
235
276
|
return end(resp, opt);
|
|
@@ -248,20 +289,6 @@ var apiResolve = (exe, opt) => {
|
|
|
248
289
|
return resp.then((resp2) => apiExit(resp2, opt));
|
|
249
290
|
};
|
|
250
291
|
|
|
251
|
-
// src/arc/opt.js
|
|
252
|
-
var createTrait = (trait) => {
|
|
253
|
-
if (!trait) {
|
|
254
|
-
return (opt) => opt;
|
|
255
|
-
}
|
|
256
|
-
if (isFn(trait)) {
|
|
257
|
-
return trait;
|
|
258
|
-
}
|
|
259
|
-
throw new Error("config.trait should be a function");
|
|
260
|
-
};
|
|
261
|
-
var configTrait = (config) => {
|
|
262
|
-
config.trait = createTrait(config.trait);
|
|
263
|
-
};
|
|
264
|
-
|
|
265
292
|
// src/server/class/Api.js
|
|
266
293
|
var Api = class _Api extends Functionable {
|
|
267
294
|
static create(config = {}) {
|
|
@@ -271,7 +298,7 @@ var Api = class _Api extends Functionable {
|
|
|
271
298
|
configTrait(config);
|
|
272
299
|
super((exe, opt) => apiResolve(exe, mrgObj(config, opt)));
|
|
273
300
|
Object.freeze(config);
|
|
274
|
-
(0,
|
|
301
|
+
(0, import_props4.solid)(this, "config", config);
|
|
275
302
|
}
|
|
276
303
|
code(code, exe, opt = {}) {
|
|
277
304
|
opt.code = code;
|
|
@@ -287,25 +314,7 @@ var createApi = Api.create;
|
|
|
287
314
|
var server_default = createApi;
|
|
288
315
|
|
|
289
316
|
// src/client/class/static.js
|
|
290
|
-
var
|
|
291
|
-
|
|
292
|
-
// src/arc/url.js
|
|
293
|
-
var _regexp = /^https?:\/\//i;
|
|
294
|
-
var buildUrl = (inputUrl, params) => {
|
|
295
|
-
if (!params) {
|
|
296
|
-
return inputUrl;
|
|
297
|
-
}
|
|
298
|
-
const hasHost = _regexp.test(inputUrl);
|
|
299
|
-
const url = new URL(inputUrl, hasHost ? void 0 : "http://thisisonlyplaceholder.xyz");
|
|
300
|
-
url.hash = "";
|
|
301
|
-
for (const [key, value] of Object.entries(params)) {
|
|
302
|
-
if (value != null) {
|
|
303
|
-
url.searchParams.append(key, value);
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
;
|
|
307
|
-
return hasHost ? url.toString() : url.pathname + url.search;
|
|
308
|
-
};
|
|
317
|
+
var import_props5 = require("@randajan/props");
|
|
309
318
|
|
|
310
319
|
// src/arc/types/kinds/json.js
|
|
311
320
|
var json_exports = {};
|
|
@@ -330,175 +339,222 @@ var decode2 = (body) => Object.fromEntries(new URLSearchParams(body));
|
|
|
330
339
|
var encode2 = (body) => new URLSearchParams(body);
|
|
331
340
|
|
|
332
341
|
// src/arc/types/index.js
|
|
333
|
-
var
|
|
334
|
-
var
|
|
335
|
-
|
|
342
|
+
var _types = { json: json_exports, form: form_exports };
|
|
343
|
+
var joinTypeNames = (types = {}) => {
|
|
344
|
+
const native = Object.keys(_types);
|
|
345
|
+
const custom = typeof types === "object" ? Object.keys(types) : [];
|
|
346
|
+
return `'${[.../* @__PURE__ */ new Set([...native, ...custom])].join("', '")}'`;
|
|
347
|
+
};
|
|
348
|
+
var getType = (propertyName, reqFnName, opt) => {
|
|
349
|
+
const tn = opt[propertyName] || opt.type;
|
|
350
|
+
if (!tn) {
|
|
336
351
|
return json_exports;
|
|
337
352
|
}
|
|
338
|
-
const
|
|
339
|
-
|
|
353
|
+
const customType = opt.types?.[tn];
|
|
354
|
+
const type = customType || _types[tn];
|
|
355
|
+
if (!type) {
|
|
356
|
+
throw new Error(`Unknown config.${propertyName} '${tn}'. Must be one of: ${joinTypeNames(opt.types)}`);
|
|
357
|
+
}
|
|
358
|
+
if (!customType) {
|
|
340
359
|
return type;
|
|
341
360
|
}
|
|
342
|
-
|
|
361
|
+
if (!type.mime || typeof type.mime !== "string") {
|
|
362
|
+
throw new Error(`Type definition '${tn}' requires 'mime' to be a string`);
|
|
363
|
+
}
|
|
364
|
+
if (!isFn(type[reqFnName])) {
|
|
365
|
+
throw new Error(`Type definition '${tn}' requires '${reqFnName}' to be a function`);
|
|
366
|
+
}
|
|
367
|
+
return type;
|
|
343
368
|
};
|
|
344
369
|
var encodeBody = (opt) => {
|
|
345
|
-
const type = getType(
|
|
370
|
+
const type = getType("requestType", "encode", opt);
|
|
346
371
|
opt.headers["Content-Type"] = type.mime;
|
|
347
372
|
opt.body = type.encode(opt.body);
|
|
348
373
|
};
|
|
349
374
|
var attachBodyDecoder = (opt) => {
|
|
350
|
-
const type = getType(
|
|
375
|
+
const type = getType("responseType", "decode", opt);
|
|
351
376
|
opt.headers["Accept"] = type.mime;
|
|
352
377
|
opt.decodeBody = type.decode;
|
|
353
378
|
};
|
|
354
379
|
|
|
355
|
-
// src/client/
|
|
356
|
-
var
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
opt.method = method;
|
|
380
|
+
// src/client/url.js
|
|
381
|
+
var _regexp = /^https?:\/\//i;
|
|
382
|
+
var buildUrl = (inputUrl, params) => {
|
|
383
|
+
if (!params) {
|
|
384
|
+
return inputUrl;
|
|
361
385
|
}
|
|
362
|
-
|
|
363
|
-
|
|
386
|
+
const hasHost = _regexp.test(inputUrl);
|
|
387
|
+
const url = new URL(inputUrl, hasHost ? void 0 : "http://thisisonlyplaceholder.xyz");
|
|
388
|
+
url.hash = "";
|
|
389
|
+
for (const [key, value] of Object.entries(params)) {
|
|
390
|
+
if (value != null) {
|
|
391
|
+
url.searchParams.append(key, value);
|
|
392
|
+
}
|
|
364
393
|
}
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
394
|
+
;
|
|
395
|
+
return hasHost ? url.toString() : url.pathname + url.search;
|
|
396
|
+
};
|
|
397
|
+
|
|
398
|
+
// src/client/tool.js
|
|
399
|
+
var diffVersion = (version) => {
|
|
400
|
+
const v1 = toStr(info.version);
|
|
401
|
+
const v2 = toStr(version);
|
|
402
|
+
if (v1 === v2) {
|
|
403
|
+
return;
|
|
370
404
|
}
|
|
371
|
-
|
|
372
|
-
|
|
405
|
+
const f1 = v1.split(".");
|
|
406
|
+
const f2 = v2.split(".");
|
|
407
|
+
if (f1[0] !== f2[0]) {
|
|
408
|
+
return "major";
|
|
373
409
|
}
|
|
374
|
-
if (
|
|
375
|
-
|
|
410
|
+
if (f1[1] !== f2[1]) {
|
|
411
|
+
return "minor";
|
|
412
|
+
}
|
|
413
|
+
if (f1[2] !== f2[2]) {
|
|
414
|
+
return "patch";
|
|
376
415
|
}
|
|
377
|
-
return opt;
|
|
378
416
|
};
|
|
379
|
-
var
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
417
|
+
var failedError = (cause) => FetchError.code(1, "Failed", { cause });
|
|
418
|
+
var timeoutError = (_) => FetchError.code(2, "Timeout");
|
|
419
|
+
var abortError = (_) => FetchError.code(3, "Aborted");
|
|
420
|
+
var statusError = (resp) => HttpError.code(4, resp.statusText, resp.status, { exposeCause: true });
|
|
421
|
+
var unreadableError = (resp, cause) => resp.ok ? FetchError.code(5, "Unreadable", { cause }) : statusError(resp);
|
|
422
|
+
var undecodableError = (resp, cause, detail) => resp.ok ? FetchError.code(6, "Undecodable", { cause, detail }) : statusError(resp);
|
|
423
|
+
var parseHeaders = (resp, opt) => {
|
|
424
|
+
if (!resp || !opt.parseHeaders) {
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
return Object.freeze(Object.fromEntries(resp.headers.entries()));
|
|
383
428
|
};
|
|
384
|
-
var statusError = ({ status, statusText }) => ApiError.create(4, statusText || status, status);
|
|
385
|
-
var unreadableError = (resp) => resp.ok ? ApiError.create(3, "Unreadable", 415) : statusError(resp);
|
|
386
|
-
var foreignError = (resp) => ({ isApiKit: false, error: statusError(resp) });
|
|
387
429
|
var readText = async (resp) => {
|
|
388
430
|
try {
|
|
389
431
|
return await resp.text();
|
|
390
|
-
} catch {
|
|
391
|
-
throw unreadableError(resp);
|
|
432
|
+
} catch (err) {
|
|
433
|
+
throw unreadableError(resp, err);
|
|
392
434
|
}
|
|
393
435
|
};
|
|
394
|
-
var decodeText = (
|
|
436
|
+
var decodeText = (resp, opt, text) => {
|
|
395
437
|
try {
|
|
396
438
|
return opt.decodeBody(text);
|
|
397
|
-
} catch {
|
|
398
|
-
throw
|
|
439
|
+
} catch (err) {
|
|
440
|
+
throw undecodableError(resp, err, text);
|
|
441
|
+
}
|
|
442
|
+
};
|
|
443
|
+
var normalizeClientError = (any, opt) => {
|
|
444
|
+
let err = any;
|
|
445
|
+
if (!FetchError.is(err)) {
|
|
446
|
+
let custom = isFn(opt.normalizeError);
|
|
447
|
+
if (custom) {
|
|
448
|
+
try {
|
|
449
|
+
err = opt.normalizeError(err, opt);
|
|
450
|
+
} catch {
|
|
451
|
+
custom = false;
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
if (!custom || !FetchError.is(err)) {
|
|
455
|
+
err = FetchError.code(0, "Unknown", { cause: any });
|
|
456
|
+
}
|
|
399
457
|
}
|
|
458
|
+
return err.rise(0).rise(0);
|
|
400
459
|
};
|
|
401
|
-
var
|
|
402
|
-
if (!
|
|
403
|
-
return
|
|
460
|
+
var reconstructApiError = (remoteErr) => {
|
|
461
|
+
if (!remoteErr) {
|
|
462
|
+
return;
|
|
404
463
|
}
|
|
405
|
-
|
|
464
|
+
const { message, code, httpStatusCode, cause, detail } = remoteErr;
|
|
465
|
+
return HttpError.code(code, message, httpStatusCode, { cause, detail, exposeCause: true });
|
|
466
|
+
};
|
|
467
|
+
var mrgOpt = (a, b) => {
|
|
468
|
+
const opt = mrgObj(a, b);
|
|
469
|
+
opt.body = mrgObj(a?.body, b?.body);
|
|
470
|
+
opt.params = mrgObj(a?.params, b?.params);
|
|
471
|
+
opt.headers = mrgObj(a?.headers, b?.headers, {});
|
|
472
|
+
return opt;
|
|
406
473
|
};
|
|
407
|
-
var
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
console.error(msg);
|
|
474
|
+
var prepareOpt = (url, opt, method) => {
|
|
475
|
+
start(opt);
|
|
476
|
+
opt.url = buildUrl(mrgStr(opt.url, url), opt.params);
|
|
477
|
+
if (method) {
|
|
478
|
+
opt.method = method;
|
|
413
479
|
}
|
|
414
|
-
if (
|
|
415
|
-
|
|
480
|
+
if (opt.body) {
|
|
481
|
+
encodeBody(opt);
|
|
416
482
|
}
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
return foreignError(resp);
|
|
483
|
+
attachBodyDecoder(opt);
|
|
484
|
+
const hasTimeout = opt.timeout > 0;
|
|
485
|
+
if (opt.isAbortable || hasTimeout) {
|
|
486
|
+
opt.abortController = new AbortController();
|
|
487
|
+
opt.signal = opt.abortController.signal;
|
|
423
488
|
}
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
body.result = opt.parseBody(raw);
|
|
427
|
-
} catch (err) {
|
|
428
|
-
body.error = err.message || err;
|
|
489
|
+
if (hasTimeout) {
|
|
490
|
+
opt.timeoutId = setTimeout(() => opt.abortController?.abort(timeoutError()), opt.timeout);
|
|
429
491
|
}
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
var resolveDecoded = (raw, opt, resp) => {
|
|
433
|
-
if (raw?.[info_default.name]) {
|
|
434
|
-
return resolveApiKit(raw, opt);
|
|
492
|
+
if (isFn(opt.trait)) {
|
|
493
|
+
opt = opt.trait(opt) || opt;
|
|
435
494
|
}
|
|
436
|
-
return
|
|
495
|
+
return opt;
|
|
437
496
|
};
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
497
|
+
|
|
498
|
+
// src/client/class/static.js
|
|
499
|
+
var localReject = (err, opt) => ({ error: normalizeClientError(FetchError.is(err) ? err : failedError(err), opt) });
|
|
500
|
+
var remoteReject = (err, opt) => ({ isRemote: true, error: normalizeClientError(err, opt) });
|
|
501
|
+
var remoteResolve = async (resp, opt) => {
|
|
502
|
+
const text = await readText(resp);
|
|
503
|
+
if (!text) {
|
|
504
|
+
if (resp.ok || resp.status === 304) {
|
|
505
|
+
return { isRemote: true };
|
|
506
|
+
}
|
|
507
|
+
throw statusError(resp);
|
|
441
508
|
}
|
|
442
|
-
const
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
};
|
|
450
|
-
var remoteResolve = (body, opt, resp) => {
|
|
451
|
-
normalizeError(body, opt, resp);
|
|
452
|
-
body.isOk = !body.error;
|
|
453
|
-
body.isRemote = true;
|
|
454
|
-
body.isApiKit = !!body.isApiKit;
|
|
455
|
-
body.statusCode = body.statusCode ?? body.error?.httpStatusCode ?? resp.status;
|
|
456
|
-
if (opt.parseHeaders) {
|
|
457
|
-
body.headers = Object.freeze(Object.fromEntries(resp.headers.entries()));
|
|
509
|
+
const body = decodeText(resp, opt, text);
|
|
510
|
+
const ver = body?.[info_default.name];
|
|
511
|
+
if (!ver) {
|
|
512
|
+
if (resp.ok) {
|
|
513
|
+
return { isRemote: true, result: body };
|
|
514
|
+
}
|
|
515
|
+
throw statusError(resp);
|
|
458
516
|
}
|
|
459
|
-
|
|
517
|
+
body.isRemote = true;
|
|
518
|
+
body.isApiKit = true;
|
|
519
|
+
body.apiKitDiff = diffVersion(ver);
|
|
520
|
+
body.error = reconstructApiError(body.error);
|
|
521
|
+
return body;
|
|
460
522
|
};
|
|
461
|
-
var
|
|
462
|
-
var fetchExe = async (_fetch, opt) => {
|
|
523
|
+
var fetchBody = async (_fetch, opt) => {
|
|
463
524
|
let resp, body;
|
|
464
525
|
try {
|
|
465
526
|
resp = await _fetch(opt.url, opt);
|
|
466
|
-
} catch (
|
|
467
|
-
|
|
527
|
+
} catch (err2) {
|
|
528
|
+
body = localReject(err2, opt);
|
|
468
529
|
}
|
|
469
530
|
try {
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
return remoteReject(opt, resp, ApiError.is(err) ? err : ApiError.to(0, err, 500));
|
|
531
|
+
body = body || await remoteResolve(resp, opt);
|
|
532
|
+
} catch (err2) {
|
|
533
|
+
body = remoteReject(err2, opt);
|
|
474
534
|
}
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
535
|
+
const err = body.error;
|
|
536
|
+
body.isOk = !err;
|
|
537
|
+
body.isRemote = !!body.isRemote;
|
|
538
|
+
body.isApiKit = !!body.isApiKit;
|
|
539
|
+
body.statusCode = err?.httpStatusCode || resp?.status;
|
|
540
|
+
body.headers = parseHeaders(resp, opt);
|
|
541
|
+
body = end(body, opt);
|
|
542
|
+
return opt.resultOnly ? body.result : body;
|
|
543
|
+
};
|
|
544
|
+
var executeFetch = (_fetch, url, opt, method) => {
|
|
545
|
+
opt = prepareOpt(url, opt, method);
|
|
546
|
+
const prom = fetchBody(_fetch, opt);
|
|
479
547
|
if (opt.timeoutId) {
|
|
480
548
|
prom.finally((_) => clearTimeout(opt.timeoutId));
|
|
481
549
|
}
|
|
482
|
-
if (!opt.
|
|
550
|
+
if (!opt.isAbortable) {
|
|
483
551
|
return prom;
|
|
484
552
|
}
|
|
485
|
-
return (0,
|
|
486
|
-
};
|
|
487
|
-
|
|
488
|
-
// src/client/class/Fetch.js
|
|
489
|
-
var import_props5 = require("@randajan/props");
|
|
490
|
-
|
|
491
|
-
// src/client/tool.js
|
|
492
|
-
var mrgQuery = (opt) => mrgObj(opt?.params, opt?.query);
|
|
493
|
-
var mrgOpt = (a, b) => {
|
|
494
|
-
const opt = mrgObj(a, b);
|
|
495
|
-
opt.body = mrgObj(a?.body, b?.body);
|
|
496
|
-
opt.query = mrgObj(mrgQuery(a), mrgQuery(b));
|
|
497
|
-
opt.headers = mrgObj(a?.headers, b?.headers, {});
|
|
498
|
-
return opt;
|
|
553
|
+
return (0, import_props5.solid)(prom, "abort", (_) => opt.abortController?.abort(abortError()));
|
|
499
554
|
};
|
|
500
555
|
|
|
501
556
|
// src/client/class/Fetch.js
|
|
557
|
+
var import_props6 = require("@randajan/props");
|
|
502
558
|
var Fetch = class _Fetch extends Functionable {
|
|
503
559
|
static create(config = {}) {
|
|
504
560
|
return new _Fetch(config);
|
|
@@ -506,14 +562,13 @@ var Fetch = class _Fetch extends Functionable {
|
|
|
506
562
|
constructor(config = {}) {
|
|
507
563
|
const _fetch = config.fetch || globalThis.fetch;
|
|
508
564
|
if (!_fetch) {
|
|
509
|
-
throw new Error("Missing fetch function. Please provide it
|
|
565
|
+
throw new Error("Missing fetch function. Please provide it in config");
|
|
510
566
|
}
|
|
511
567
|
configTrait(config);
|
|
512
|
-
config.parseBody = createTrait(config.parseBody);
|
|
513
568
|
delete config.fetch;
|
|
514
|
-
super((url, opt, method) =>
|
|
569
|
+
super((url, opt, method) => executeFetch(_fetch, url, mrgOpt(config, opt), method));
|
|
515
570
|
Object.freeze(config);
|
|
516
|
-
(0,
|
|
571
|
+
(0, import_props6.solid)(this, "config", config);
|
|
517
572
|
}
|
|
518
573
|
extend(config) {
|
|
519
574
|
return new _Fetch(mrgOpt(this.config, config));
|