@scaleway/sdk-client 2.1.0 → 2.2.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/dist/_virtual/_rolldown/runtime.js +11 -0
- package/dist/helpers/is-browser.js +1 -3
- package/dist/helpers/is-response.js +8 -3
- package/dist/helpers/json.js +47 -40
- package/dist/helpers/marshalling.js +88 -59
- package/dist/index.js +6 -47
- package/dist/internal/async/interval-retrier.js +64 -49
- package/dist/internal/async/sleep.js +10 -4
- package/dist/internal/interceptors/composer.js +34 -23
- package/dist/internal/interceptors/helpers.js +22 -9
- package/dist/internal/logger/console-logger.js +27 -22
- package/dist/internal/logger/index.js +23 -7
- package/dist/internal/logger/level-resolver.js +9 -12
- package/dist/internal/validations/string-validation.js +20 -21
- package/dist/internals.js +8 -0
- package/dist/package.js +32 -0
- package/dist/scw/api.js +10 -7
- package/dist/scw/auth.js +60 -17
- package/dist/scw/client-ini-factory.js +127 -57
- package/dist/scw/client-ini-profile.js +23 -19
- package/dist/scw/client-settings.js +25 -49
- package/dist/scw/client.js +76 -25
- package/dist/scw/constants.js +3 -8
- package/dist/scw/custom-marshalling.js +147 -121
- package/dist/scw/custom-types.js +11 -10
- package/dist/scw/errors/error-parser.js +83 -61
- package/dist/scw/errors/non-standard/invalid-request-mapper.js +20 -29
- package/dist/scw/errors/non-standard/unknown-resource-mapper.js +9 -16
- package/dist/scw/errors/scw-error.js +42 -39
- package/dist/scw/errors/standard/already-exists-error.js +20 -29
- package/dist/scw/errors/standard/denied-authentication-error.js +43 -34
- package/dist/scw/errors/standard/index.js +20 -18
- package/dist/scw/errors/standard/invalid-arguments-error.js +51 -50
- package/dist/scw/errors/standard/out-of-stock-error.js +18 -15
- package/dist/scw/errors/standard/permissions-denied-error.js +30 -26
- package/dist/scw/errors/standard/precondition-failed-error.js +32 -29
- package/dist/scw/errors/standard/quotas-exceeded-error.js +43 -38
- package/dist/scw/errors/standard/resource-expired-error.js +20 -29
- package/dist/scw/errors/standard/resource-locked-error.js +19 -18
- package/dist/scw/errors/standard/resource-not-found-error.js +19 -22
- package/dist/scw/errors/standard/too-many-requests-error.js +41 -54
- package/dist/scw/errors/standard/transient-state-error.js +20 -29
- package/dist/scw/errors/types.js +12 -12
- package/dist/scw/fetch/build-fetcher.js +49 -54
- package/dist/scw/fetch/http-dumper.js +50 -16
- package/dist/scw/fetch/http-interceptors.d.ts +1 -3
- package/dist/scw/fetch/http-interceptors.js +52 -34
- package/dist/scw/fetch/resource-paginator.js +52 -28
- package/dist/scw/fetch/response-parser.js +48 -49
- package/dist/scw/locality.js +12 -14
- package/dist/vendor/base64/index.js +31 -39
- package/package.json +1 -1
- package/dist/package.json.js +0 -8
|
@@ -1,43 +1,48 @@
|
|
|
1
1
|
import { isJSONObject } from "../../../helpers/json.js";
|
|
2
2
|
import { ScalewayError } from "../scw-error.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Build the default message for {@link QuotasExceededError}.
|
|
5
|
+
*
|
|
6
|
+
* @param list - The list of {@link QuotasExceededErrorDetails}
|
|
7
|
+
* @returns The error message
|
|
8
|
+
*
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
11
|
+
var buildMessage = (list) => `quota(s) exceeded: ${list.map((details) => {
|
|
12
|
+
const message = `Quotas reached: You have reached the maximum number of ${details.resource} authorized by your Organization. Access the quotas page from your Organization dashboard to manage quotas.`;
|
|
13
|
+
return details.scope ? `${message} for ${details.scope.kind} '${details.scope.id}'` : message;
|
|
6
14
|
}).join("; ")}`;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
var buildScope = (detail) => {
|
|
16
|
+
if (typeof detail.organization_id === "string" && detail.organization_id.length) return {
|
|
17
|
+
id: detail.organization_id,
|
|
18
|
+
kind: "organization"
|
|
19
|
+
};
|
|
20
|
+
if (typeof detail.project_id === "string" && detail.project_id.length) return {
|
|
21
|
+
id: detail.project_id,
|
|
22
|
+
kind: "project"
|
|
23
|
+
};
|
|
15
24
|
};
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
export {
|
|
42
|
-
QuotasExceededError
|
|
25
|
+
/**
|
|
26
|
+
* QuotasExceeded error happens when one or many resource exceed quotas during the creation of a resource.
|
|
27
|
+
*
|
|
28
|
+
* @public
|
|
29
|
+
*/
|
|
30
|
+
var QuotasExceededError = class QuotasExceededError extends ScalewayError {
|
|
31
|
+
constructor(status, body, list) {
|
|
32
|
+
super(status, body, buildMessage(list));
|
|
33
|
+
this.status = status;
|
|
34
|
+
this.body = body;
|
|
35
|
+
this.list = list;
|
|
36
|
+
this.name = "QuotasExceededError";
|
|
37
|
+
}
|
|
38
|
+
static fromJSON(status, obj) {
|
|
39
|
+
if (!Array.isArray(obj.details)) return null;
|
|
40
|
+
return new QuotasExceededError(status, obj, obj.details.reduce((list, detail) => isJSONObject(detail) && typeof detail.resource === "string" && typeof detail.quota === "number" && typeof detail.current === "number" ? list.concat({
|
|
41
|
+
current: detail.current,
|
|
42
|
+
quota: detail.quota,
|
|
43
|
+
resource: detail.resource,
|
|
44
|
+
scope: buildScope(detail)
|
|
45
|
+
}) : list, []));
|
|
46
|
+
}
|
|
43
47
|
};
|
|
48
|
+
export { QuotasExceededError };
|
|
@@ -1,31 +1,22 @@
|
|
|
1
1
|
import { ScalewayError } from "../scw-error.js";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
status,
|
|
22
|
-
obj,
|
|
23
|
-
obj.resource,
|
|
24
|
-
obj.resource_id,
|
|
25
|
-
new Date(obj.expired_since)
|
|
26
|
-
);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
export {
|
|
30
|
-
ResourceExpiredError
|
|
2
|
+
/**
|
|
3
|
+
* ResourceExpired error happens when trying to access a resource that has expired.
|
|
4
|
+
*
|
|
5
|
+
* @public
|
|
6
|
+
*/
|
|
7
|
+
var ResourceExpiredError = class ResourceExpiredError extends ScalewayError {
|
|
8
|
+
constructor(status, body, resource, resourceId, expiredSince) {
|
|
9
|
+
super(status, body, `resource ${resource} with ID ${resourceId} expired since ${expiredSince.toISOString()}`);
|
|
10
|
+
this.status = status;
|
|
11
|
+
this.body = body;
|
|
12
|
+
this.resource = resource;
|
|
13
|
+
this.resourceId = resourceId;
|
|
14
|
+
this.expiredSince = expiredSince;
|
|
15
|
+
this.name = "ResourceExpiredError";
|
|
16
|
+
}
|
|
17
|
+
static fromJSON(status, obj) {
|
|
18
|
+
if (typeof obj.resource !== "string" || typeof obj.resource_id !== "string" || typeof obj.expired_since !== "string") return null;
|
|
19
|
+
return new ResourceExpiredError(status, obj, obj.resource, obj.resource_id, new Date(obj.expired_since));
|
|
20
|
+
}
|
|
31
21
|
};
|
|
22
|
+
export { ResourceExpiredError };
|
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
import { ScalewayError } from "../scw-error.js";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
2
|
+
/**
|
|
3
|
+
* ResourceLocked error happens when a resource is locked by trust and safety.
|
|
4
|
+
*
|
|
5
|
+
* @public
|
|
6
|
+
*/
|
|
7
|
+
var ResourceLockedError = class ResourceLockedError extends ScalewayError {
|
|
8
|
+
constructor(status, body, resource, resourceId) {
|
|
9
|
+
super(status, body, `resource ${resource} with ID ${resourceId} is locked`);
|
|
10
|
+
this.status = status;
|
|
11
|
+
this.body = body;
|
|
12
|
+
this.resource = resource;
|
|
13
|
+
this.resourceId = resourceId;
|
|
14
|
+
this.name = "ResourceLockedError";
|
|
15
|
+
}
|
|
16
|
+
static fromJSON(status, obj) {
|
|
17
|
+
if (typeof obj.resource !== "string" || typeof obj.resource_id !== "string") return null;
|
|
18
|
+
return new ResourceLockedError(status, obj, obj.resource, obj.resource_id);
|
|
19
|
+
}
|
|
20
20
|
};
|
|
21
|
+
export { ResourceLockedError };
|
|
@@ -1,24 +1,21 @@
|
|
|
1
1
|
import { ScalewayError } from "../scw-error.js";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
export {
|
|
23
|
-
ResourceNotFoundError
|
|
2
|
+
/**
|
|
3
|
+
* ResourceNotFound error happens when getting a resource that does not exist anymore.
|
|
4
|
+
*
|
|
5
|
+
* @public
|
|
6
|
+
*/
|
|
7
|
+
var ResourceNotFoundError = class ResourceNotFoundError extends ScalewayError {
|
|
8
|
+
constructor(status, body, resource, resourceId) {
|
|
9
|
+
super(status, body, `resource ${resource} with ID ${resourceId} is not found`);
|
|
10
|
+
this.status = status;
|
|
11
|
+
this.body = body;
|
|
12
|
+
this.resource = resource;
|
|
13
|
+
this.resourceId = resourceId;
|
|
14
|
+
this.name = "ResourceNotFoundError";
|
|
15
|
+
}
|
|
16
|
+
static fromJSON(status, obj) {
|
|
17
|
+
if (typeof obj.resource !== "string" || typeof obj.resource_id !== "string") return null;
|
|
18
|
+
return new ResourceNotFoundError(status, obj, obj.resource, obj.resource_id);
|
|
19
|
+
}
|
|
24
20
|
};
|
|
21
|
+
export { ResourceNotFoundError };
|
|
@@ -1,58 +1,45 @@
|
|
|
1
1
|
import { isJSONObject } from "../../../helpers/json.js";
|
|
2
2
|
import { ScalewayError } from "../scw-error.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
if (details.length > 0) {
|
|
19
|
-
output += ` (${details.join(", ")})`;
|
|
20
|
-
}
|
|
21
|
-
if (helpMessage.length > 0) {
|
|
22
|
-
output += `: ${helpMessage}`;
|
|
23
|
-
}
|
|
24
|
-
return output;
|
|
3
|
+
/**
|
|
4
|
+
* Build the default message for {@link TooManyRequestsError}.
|
|
5
|
+
*
|
|
6
|
+
* @internal
|
|
7
|
+
*/
|
|
8
|
+
var buildMessage = (helpMessage, limit, resetSeconds, resetAt) => {
|
|
9
|
+
const details = [];
|
|
10
|
+
if (limit) if (limit.windowSeconds) details.push(`quota is ${limit.quota} for ${limit.windowSeconds}s`);
|
|
11
|
+
else details.push(`quota is ${limit.quota}`);
|
|
12
|
+
if (resetSeconds) details.push(`resets in ${resetSeconds}s`);
|
|
13
|
+
else if (resetAt) details.push(`resets at ${resetAt.toISOString()}`);
|
|
14
|
+
let output = `too many requests`;
|
|
15
|
+
if (details.length > 0) output += ` (${details.join(", ")})`;
|
|
16
|
+
if (helpMessage.length > 0) output += `: ${helpMessage}`;
|
|
17
|
+
return output;
|
|
25
18
|
};
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
typeof obj.reset_seconds === "number" ? obj.reset_seconds : void 0,
|
|
52
|
-
typeof obj.reset_at === "string" ? new Date(obj.reset_at) : void 0
|
|
53
|
-
);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
export {
|
|
57
|
-
TooManyRequestsError
|
|
19
|
+
/**
|
|
20
|
+
* TooManyRequestsError error happens when fetching too many times a resource.
|
|
21
|
+
*
|
|
22
|
+
* @public
|
|
23
|
+
*/
|
|
24
|
+
var TooManyRequestsError = class TooManyRequestsError extends ScalewayError {
|
|
25
|
+
constructor(status, body, helpMessage, limit, resetSeconds, resetAt) {
|
|
26
|
+
super(status, body, buildMessage(helpMessage, limit, resetSeconds, resetAt));
|
|
27
|
+
this.status = status;
|
|
28
|
+
this.body = body;
|
|
29
|
+
this.helpMessage = helpMessage;
|
|
30
|
+
this.limit = limit;
|
|
31
|
+
this.resetSeconds = resetSeconds;
|
|
32
|
+
this.resetAt = resetAt;
|
|
33
|
+
this.name = "TooManyRequestsError";
|
|
34
|
+
}
|
|
35
|
+
static fromJSON(status, obj) {
|
|
36
|
+
if (typeof obj.help_message !== "string") return null;
|
|
37
|
+
let limit;
|
|
38
|
+
if (isJSONObject(obj.limit) && typeof obj.limit.quota === "number") limit = {
|
|
39
|
+
quota: obj.limit.quota,
|
|
40
|
+
windowSeconds: typeof obj.limit.window_seconds === "number" ? obj.limit.window_seconds : void 0
|
|
41
|
+
};
|
|
42
|
+
return new TooManyRequestsError(status, obj, obj.help_message, limit, typeof obj.reset_seconds === "number" ? obj.reset_seconds : void 0, typeof obj.reset_at === "string" ? new Date(obj.reset_at) : void 0);
|
|
43
|
+
}
|
|
58
44
|
};
|
|
45
|
+
export { TooManyRequestsError };
|
|
@@ -1,31 +1,22 @@
|
|
|
1
1
|
import { ScalewayError } from "../scw-error.js";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
status,
|
|
22
|
-
obj,
|
|
23
|
-
obj.resource,
|
|
24
|
-
obj.resource_id,
|
|
25
|
-
obj.current_state
|
|
26
|
-
);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
export {
|
|
30
|
-
TransientStateError
|
|
2
|
+
/**
|
|
3
|
+
* TransientState error happens when trying to perform an action on a resource in a transient state.
|
|
4
|
+
*
|
|
5
|
+
* @public
|
|
6
|
+
*/
|
|
7
|
+
var TransientStateError = class TransientStateError extends ScalewayError {
|
|
8
|
+
constructor(status, body, resource, resourceId, currentState) {
|
|
9
|
+
super(status, body, `resource ${resource} with ID ${resourceId} is in a transient state: ${currentState}`);
|
|
10
|
+
this.status = status;
|
|
11
|
+
this.body = body;
|
|
12
|
+
this.resource = resource;
|
|
13
|
+
this.resourceId = resourceId;
|
|
14
|
+
this.currentState = currentState;
|
|
15
|
+
this.name = "TransientStateError";
|
|
16
|
+
}
|
|
17
|
+
static fromJSON(status, obj) {
|
|
18
|
+
if (typeof obj.resource !== "string" || typeof obj.resource_id !== "string" || typeof obj.current_state !== "string") return null;
|
|
19
|
+
return new TransientStateError(status, obj, obj.resource, obj.resource_id, obj.current_state);
|
|
20
|
+
}
|
|
31
21
|
};
|
|
22
|
+
export { TransientStateError };
|
package/dist/scw/errors/types.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { isJSONObject } from "../../helpers/json.js";
|
|
2
|
+
/**
|
|
3
|
+
* Verifies the object is a record of string to string[].
|
|
4
|
+
*
|
|
5
|
+
* @param obj - The object
|
|
6
|
+
* @returns Whether the object is of the expected type
|
|
7
|
+
*
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
2
10
|
const isRecordOfStringArray = (obj) => {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
for (const elt of Object.values(obj)) {
|
|
7
|
-
if (!Array.isArray(elt) || Object.values(elt).find((x) => typeof x !== "string") !== void 0) {
|
|
8
|
-
return false;
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
return true;
|
|
12
|
-
};
|
|
13
|
-
export {
|
|
14
|
-
isRecordOfStringArray
|
|
11
|
+
if (!isJSONObject(obj)) return false;
|
|
12
|
+
for (const elt of Object.values(obj)) if (!Array.isArray(elt) || Object.values(elt).find((x) => typeof x !== "string") !== void 0) return false;
|
|
13
|
+
return true;
|
|
15
14
|
};
|
|
15
|
+
export { isRecordOfStringArray };
|
|
@@ -1,61 +1,56 @@
|
|
|
1
|
-
import { isBrowser } from "../../helpers/is-browser.js";
|
|
2
|
-
import { composeRequestInterceptors, composeResponseInterceptors, composeResponseErrorInterceptors } from "../../internal/interceptors/composer.js";
|
|
3
1
|
import { obfuscateAuthHeadersEntry } from "../auth.js";
|
|
2
|
+
import { isBrowser } from "../../helpers/is-browser.js";
|
|
3
|
+
import { composeRequestInterceptors, composeResponseErrorInterceptors, composeResponseInterceptors } from "../../internal/interceptors/composer.js";
|
|
4
4
|
import { logRequest, logResponse, obfuscateInterceptor } from "./http-interceptors.js";
|
|
5
5
|
import { responseParser } from "./response-parser.js";
|
|
6
|
+
/**
|
|
7
|
+
* Builds Request from {@link ScwRequest} & {@link Settings}.
|
|
8
|
+
*
|
|
9
|
+
* @param request - A scaleway request
|
|
10
|
+
* @param settings - The settings
|
|
11
|
+
* @returns A fetch Request
|
|
12
|
+
*
|
|
13
|
+
* @internal
|
|
14
|
+
*/
|
|
6
15
|
const buildRequest = (request, settings) => {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
},
|
|
19
|
-
method: request.method
|
|
20
|
-
});
|
|
16
|
+
let { path } = request;
|
|
17
|
+
if (request.urlParams instanceof URLSearchParams) path = path.concat(`?${request.urlParams.toString()}`);
|
|
18
|
+
return new Request(`${settings.apiURL}${path}`, {
|
|
19
|
+
body: request.body,
|
|
20
|
+
headers: {
|
|
21
|
+
Accept: "application/json",
|
|
22
|
+
...!isBrowser() ? { "User-Agent": settings.userAgent } : {},
|
|
23
|
+
...request.headers
|
|
24
|
+
},
|
|
25
|
+
method: request.method
|
|
26
|
+
});
|
|
21
27
|
};
|
|
22
|
-
|
|
28
|
+
var asIs = (response) => response;
|
|
29
|
+
/**
|
|
30
|
+
* Builds a resource fetcher.
|
|
31
|
+
*
|
|
32
|
+
* @param settings - The {@link Settings} object
|
|
33
|
+
* @param httpClient - The HTTP client that should be used to call the API
|
|
34
|
+
* @returns The fetcher
|
|
35
|
+
*
|
|
36
|
+
* @internal
|
|
37
|
+
*/
|
|
23
38
|
const buildFetcher = (settings, httpClient) => {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const finalRequest = await reqInterceptors(buildRequest(request, settings));
|
|
41
|
-
try {
|
|
42
|
-
const response = await httpClient(finalRequest);
|
|
43
|
-
const resInterceptors = prepareResponse(requestId);
|
|
44
|
-
const finalResponse = await resInterceptors(response);
|
|
45
|
-
const resUnmarshaller = responseParser(
|
|
46
|
-
unwrapper,
|
|
47
|
-
request.responseType ?? "json"
|
|
48
|
-
);
|
|
49
|
-
const unmarshaledResponse = await resUnmarshaller(finalResponse);
|
|
50
|
-
return unmarshaledResponse;
|
|
51
|
-
} catch (err) {
|
|
52
|
-
const resErrorInterceptors = prepareResponseErrors();
|
|
53
|
-
const handledError = await resErrorInterceptors(finalRequest, err);
|
|
54
|
-
return unwrapper(handledError);
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
};
|
|
58
|
-
export {
|
|
59
|
-
buildFetcher,
|
|
60
|
-
buildRequest
|
|
39
|
+
let requestNumber = 0;
|
|
40
|
+
const prepareRequest = (requestId) => composeRequestInterceptors([...settings.interceptors.map((obj) => obj.request).filter((obj) => obj), logRequest(requestId, obfuscateInterceptor(obfuscateAuthHeadersEntry))]);
|
|
41
|
+
const prepareResponse = (requestId) => composeResponseInterceptors([...settings.interceptors.map((obj) => obj.response).filter((obj) => obj), logResponse(requestId)]);
|
|
42
|
+
const prepareResponseErrors = () => composeResponseErrorInterceptors(settings.interceptors.map((obj) => obj.responseError).filter((obj) => obj));
|
|
43
|
+
return async (request, unwrapper = asIs) => {
|
|
44
|
+
requestNumber += 1;
|
|
45
|
+
const requestId = `${requestNumber}`;
|
|
46
|
+
const finalRequest = await prepareRequest(requestId)(buildRequest(request, settings));
|
|
47
|
+
try {
|
|
48
|
+
const response = await httpClient(finalRequest);
|
|
49
|
+
const finalResponse = await prepareResponse(requestId)(response);
|
|
50
|
+
return await responseParser(unwrapper, request.responseType ?? "json")(finalResponse);
|
|
51
|
+
} catch (err) {
|
|
52
|
+
return unwrapper(await prepareResponseErrors()(finalRequest, err));
|
|
53
|
+
}
|
|
54
|
+
};
|
|
61
55
|
};
|
|
56
|
+
export { buildFetcher };
|
|
@@ -1,20 +1,54 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Converts a string to PascalCase.
|
|
3
|
+
*
|
|
4
|
+
* @param str - The input string
|
|
5
|
+
* @returns The string in PascalCase
|
|
6
|
+
*
|
|
7
|
+
* @internal
|
|
8
|
+
*/
|
|
9
|
+
var toPascalCase = (str) => str.replace(/\w+/g, (word) => `${word[0].toUpperCase()}${word.slice(1).toLowerCase()}`);
|
|
10
|
+
/**
|
|
11
|
+
* Converts a Headers entry to string.
|
|
12
|
+
*
|
|
13
|
+
* @param entry - The header entry as a string tuple
|
|
14
|
+
* @returns A serialized string
|
|
15
|
+
*
|
|
16
|
+
* @internal
|
|
17
|
+
*/
|
|
18
|
+
var serializeHeadersEntry = ([name, value]) => `${toPascalCase(name)}: ${value}`;
|
|
19
|
+
/**
|
|
20
|
+
* Converts Headers to safe to log strings (with obfuscated auth secrets).
|
|
21
|
+
*
|
|
22
|
+
* @param headers - The Headers
|
|
23
|
+
* @returns Serialized headers strings
|
|
24
|
+
*
|
|
25
|
+
* @internal
|
|
26
|
+
*/
|
|
27
|
+
var serializeHeaders = (headers) => Array.from(headers.entries(), serializeHeadersEntry);
|
|
28
|
+
/**
|
|
29
|
+
* Dumps a Request into a readable string.
|
|
30
|
+
*
|
|
31
|
+
* @param request - The request
|
|
32
|
+
* @returns The readable string
|
|
33
|
+
*
|
|
34
|
+
* @internal
|
|
35
|
+
*/
|
|
7
36
|
const dumpRequest = async (request) => [
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
37
|
+
`${request.method.toUpperCase()}: ${request.url}`,
|
|
38
|
+
...serializeHeaders(request.headers),
|
|
39
|
+
await request.clone().text()
|
|
11
40
|
].join("\r\n");
|
|
41
|
+
/**
|
|
42
|
+
* Dumps a Response into a readable string.
|
|
43
|
+
*
|
|
44
|
+
* @param response - The response
|
|
45
|
+
* @returns The readable string
|
|
46
|
+
*
|
|
47
|
+
* @internal
|
|
48
|
+
*/
|
|
12
49
|
const dumpResponse = async (response) => [
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
50
|
+
`HTTP ${response.status} ${response.ok ? "OK" : "NOK"}`,
|
|
51
|
+
...serializeHeaders(response.headers),
|
|
52
|
+
await response.clone().text()
|
|
16
53
|
].join("\r\n");
|
|
17
|
-
export {
|
|
18
|
-
dumpRequest,
|
|
19
|
-
dumpResponse
|
|
20
|
-
};
|
|
54
|
+
export { dumpRequest, dumpResponse };
|
|
@@ -11,9 +11,7 @@ import type { RequestInterceptor, ResponseInterceptor } from '../../internal/int
|
|
|
11
11
|
*
|
|
12
12
|
* @internal
|
|
13
13
|
*/
|
|
14
|
-
|
|
15
|
-
(entry: [string, string]): [string, string];
|
|
16
|
-
}
|
|
14
|
+
type HeaderEntryMapper = (entry: [string, string]) => [string, string];
|
|
17
15
|
/**
|
|
18
16
|
* Creates an interceptor to obfuscate the requests.
|
|
19
17
|
*
|