@scaleway/sdk-client 2.1.0 → 2.2.1
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,61 @@
|
|
|
1
|
+
import { LevelResolver, shouldLog } from "../../internal/logger/level-resolver.js";
|
|
1
2
|
import { getLogger } from "../../internal/logger/index.js";
|
|
2
|
-
import { shouldLog, LevelResolver } from "../../internal/logger/level-resolver.js";
|
|
3
3
|
import { dumpRequest, dumpResponse } from "./http-dumper.js";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
4
|
+
/**
|
|
5
|
+
* HTTP Request with obfuscated secrets.
|
|
6
|
+
*
|
|
7
|
+
* @internal
|
|
8
|
+
*/
|
|
9
|
+
var ObfuscatedRequest = class ObfuscatedRequest extends Request {
|
|
10
|
+
constructor(request, obfuscate) {
|
|
11
|
+
super(request);
|
|
12
|
+
this.request = request;
|
|
13
|
+
this.obfuscate = obfuscate;
|
|
14
|
+
}
|
|
15
|
+
get headers() {
|
|
16
|
+
return new Headers(Array.from(this.request.headers, this.obfuscate));
|
|
17
|
+
}
|
|
18
|
+
clone() {
|
|
19
|
+
return new ObfuscatedRequest(this.request, this.obfuscate);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Creates an interceptor to obfuscate the requests.
|
|
24
|
+
*
|
|
25
|
+
* @param obfuscate - The Header entries obfuscator mapper
|
|
26
|
+
* @returns The obfuscated Request
|
|
27
|
+
*
|
|
28
|
+
* @internal
|
|
29
|
+
*/
|
|
17
30
|
const obfuscateInterceptor = (obfuscate) => ({ request }) => new ObfuscatedRequest(request, obfuscate);
|
|
18
|
-
|
|
31
|
+
var identity = ({ request }) => request;
|
|
32
|
+
/**
|
|
33
|
+
* Creates an interceptor to log the requests.
|
|
34
|
+
*
|
|
35
|
+
* @param identifier - The request identifier
|
|
36
|
+
* @param obfuscate - The obfuscation interceptor
|
|
37
|
+
* @returns The interceptor
|
|
38
|
+
*
|
|
39
|
+
* @internal
|
|
40
|
+
*/
|
|
19
41
|
const logRequest = (identifier, obfuscate = identity) => async ({ request }) => {
|
|
20
|
-
|
|
21
|
-
getLogger().debug(
|
|
22
|
-
`--------------- Scaleway SDK REQUEST ${identifier} ---------------
|
|
42
|
+
if (shouldLog(LevelResolver[getLogger().logLevel], "debug")) getLogger().debug(`--------------- Scaleway SDK REQUEST ${identifier} ---------------
|
|
23
43
|
${await dumpRequest(await obfuscate({ request }))}
|
|
24
|
-
---------------------------------------------------------`
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
return request;
|
|
44
|
+
---------------------------------------------------------`);
|
|
45
|
+
return request;
|
|
28
46
|
};
|
|
47
|
+
/**
|
|
48
|
+
* Creates an interceptor to log the responses.
|
|
49
|
+
*
|
|
50
|
+
* @param identifier - The request identifier
|
|
51
|
+
* @returns The interceptor
|
|
52
|
+
*
|
|
53
|
+
* @internal
|
|
54
|
+
*/
|
|
29
55
|
const logResponse = (identifier) => async ({ response }) => {
|
|
30
|
-
|
|
31
|
-
getLogger().debug(
|
|
32
|
-
`--------------- Scaleway SDK RESPONSE ${identifier} ---------------
|
|
56
|
+
if (shouldLog(LevelResolver[getLogger().logLevel], "debug")) getLogger().debug(`--------------- Scaleway SDK RESPONSE ${identifier} ---------------
|
|
33
57
|
${await dumpResponse(response)}
|
|
34
|
-
---------------------------------------------------------`
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
return response;
|
|
38
|
-
};
|
|
39
|
-
export {
|
|
40
|
-
logRequest,
|
|
41
|
-
logResponse,
|
|
42
|
-
obfuscateInterceptor
|
|
58
|
+
---------------------------------------------------------`);
|
|
59
|
+
return response;
|
|
43
60
|
};
|
|
61
|
+
export { logRequest, logResponse, obfuscateInterceptor };
|
|
@@ -1,36 +1,60 @@
|
|
|
1
1
|
const extract = (key) => (result) => result[key];
|
|
2
2
|
function* pages(key, fetcher, request, firstPage) {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
3
|
+
if (!Array.isArray(firstPage[key])) throw new Error(`Property ${key} is not a list in paginated result`);
|
|
4
|
+
const getList = extract(key);
|
|
5
|
+
let page = request.page || 1;
|
|
6
|
+
if (page === 1) {
|
|
7
|
+
yield Promise.resolve(getList(firstPage));
|
|
8
|
+
page += 1;
|
|
9
|
+
}
|
|
10
|
+
const { length } = firstPage[key];
|
|
11
|
+
if (!length) return;
|
|
12
|
+
const { totalCount } = firstPage;
|
|
13
|
+
while (page <= Math.floor((totalCount + length - 1) / length)) {
|
|
14
|
+
yield fetcher({
|
|
15
|
+
...request,
|
|
16
|
+
page
|
|
17
|
+
}).then(getList);
|
|
18
|
+
page += 1;
|
|
19
|
+
}
|
|
19
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* Fetches a paginated resource.
|
|
23
|
+
*
|
|
24
|
+
* @param key - The resource key of values list
|
|
25
|
+
* @param fetcher - The method to retrieve paginated resources
|
|
26
|
+
* @param request - A request with pagination options
|
|
27
|
+
* @param initial - The first page
|
|
28
|
+
* @returns An async generator of resources arrays
|
|
29
|
+
*/
|
|
20
30
|
async function* fetchPaginated(key, fetcher, request, initial = fetcher(request)) {
|
|
21
|
-
|
|
31
|
+
yield* pages(key, fetcher, request, await initial);
|
|
22
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Fetches all paginated resource.
|
|
35
|
+
*
|
|
36
|
+
* @param key - The resource key of values list
|
|
37
|
+
* @param fetcher - The method to retrieve paginated resources
|
|
38
|
+
* @param request - A request with pagination options
|
|
39
|
+
* @param initial - The first page
|
|
40
|
+
* @returns A resources array Promise
|
|
41
|
+
*/
|
|
23
42
|
const fetchAll = async (key, fetcher, request, initial = fetcher(request)) => (await Promise.all(Array.from(pages(key, fetcher, request, await initial)))).flat();
|
|
43
|
+
/**
|
|
44
|
+
* Enriches a listing method with helpers.
|
|
45
|
+
*
|
|
46
|
+
* @param key - The resource key of values list
|
|
47
|
+
* @param fetcher - The method to retrieve paginated resources
|
|
48
|
+
* @param request - A request with pagination options
|
|
49
|
+
* @returns A resource Promise with the pagination helpers
|
|
50
|
+
*
|
|
51
|
+
* @internal
|
|
52
|
+
*/
|
|
24
53
|
const enrichForPagination = (key, fetcher, request) => {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
};
|
|
31
|
-
export {
|
|
32
|
-
enrichForPagination,
|
|
33
|
-
extract,
|
|
34
|
-
fetchAll,
|
|
35
|
-
fetchPaginated
|
|
54
|
+
const firstPage = fetcher(request);
|
|
55
|
+
return Object.assign(firstPage, {
|
|
56
|
+
all: () => fetchAll(key, fetcher, request, firstPage),
|
|
57
|
+
[Symbol.asyncIterator]: () => fetchPaginated(key, fetcher, request, firstPage)
|
|
58
|
+
});
|
|
36
59
|
};
|
|
60
|
+
export { enrichForPagination };
|
|
@@ -1,55 +1,54 @@
|
|
|
1
|
-
import { isResponse } from "../../helpers/is-response.js";
|
|
2
1
|
import { isJSONObject } from "../../helpers/json.js";
|
|
3
|
-
import {
|
|
2
|
+
import { isResponse } from "../../helpers/is-response.js";
|
|
4
3
|
import { ScalewayError } from "../errors/scw-error.js";
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
import { parseScalewayError } from "../errors/error-parser.js";
|
|
5
|
+
var X_TOTAL_COUNT_HEADER_KEY = "x-total-count";
|
|
6
|
+
var TOTAL_COUNT_RES_KEY = "total_count";
|
|
7
|
+
/**
|
|
8
|
+
* Fixes the totalCount property for old APIs.
|
|
9
|
+
*
|
|
10
|
+
* @internal
|
|
11
|
+
*/
|
|
7
12
|
const fixLegacyTotalCount = (obj, headers) => {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
return obj;
|
|
15
|
-
}
|
|
16
|
-
if (isJSONObject(obj) && !(TOTAL_COUNT_RES_KEY in obj)) {
|
|
17
|
-
return Object.assign(obj, { [TOTAL_COUNT_RES_KEY]: totalCount });
|
|
18
|
-
}
|
|
19
|
-
return obj;
|
|
13
|
+
const headerVal = headers.get(X_TOTAL_COUNT_HEADER_KEY);
|
|
14
|
+
if (!headerVal) return obj;
|
|
15
|
+
const totalCount = parseInt(headerVal, 10);
|
|
16
|
+
if (Number.isNaN(totalCount)) return obj;
|
|
17
|
+
if (isJSONObject(obj) && !(TOTAL_COUNT_RES_KEY in obj)) return Object.assign(obj, { [TOTAL_COUNT_RES_KEY]: totalCount });
|
|
18
|
+
return obj;
|
|
20
19
|
};
|
|
20
|
+
/**
|
|
21
|
+
* Makes response parser.
|
|
22
|
+
*
|
|
23
|
+
* @param unmarshaller - The response payload unmarshaller
|
|
24
|
+
* @returns An async converter of HTTP Response to desired result
|
|
25
|
+
*
|
|
26
|
+
* @throws {@link ScalewayError}
|
|
27
|
+
* Thrown by the API if the request couldn't be completed.
|
|
28
|
+
*
|
|
29
|
+
* @throws TypeError
|
|
30
|
+
* Thrown if the response parameter isn't of the expected type.
|
|
31
|
+
*
|
|
32
|
+
* @throws Error
|
|
33
|
+
* JSON parsing could trigger an error.
|
|
34
|
+
*
|
|
35
|
+
* @internal
|
|
36
|
+
*/
|
|
21
37
|
const responseParser = (unmarshaller, responseType) => async (response) => {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
return unmarshaller(await response.text());
|
|
38
|
-
} catch (err) {
|
|
39
|
-
throw new ScalewayError(
|
|
40
|
-
response.status,
|
|
41
|
-
`could not parse '${contentType ?? ""}' response${err instanceof Error ? `: ${err.message}` : ""}`
|
|
42
|
-
);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
const error = await response.clone().json().catch(() => response.text());
|
|
46
|
-
if (isJSONObject(error)) throw parseScalewayError(response.status, error);
|
|
47
|
-
throw new ScalewayError(
|
|
48
|
-
response.status,
|
|
49
|
-
typeof error === "string" ? error : "cannot read error response body"
|
|
50
|
-
);
|
|
51
|
-
};
|
|
52
|
-
export {
|
|
53
|
-
fixLegacyTotalCount,
|
|
54
|
-
responseParser
|
|
38
|
+
if (!isResponse(response)) throw new TypeError("Invalid response object");
|
|
39
|
+
if (response.ok) {
|
|
40
|
+
if (response.status === 204) return unmarshaller(void 0);
|
|
41
|
+
const contentType = response.headers.get("Content-Type");
|
|
42
|
+
try {
|
|
43
|
+
if (responseType === "json" && contentType === "application/json") return unmarshaller(fixLegacyTotalCount(await response.json(), response.headers));
|
|
44
|
+
if (responseType === "blob") return unmarshaller(await response.blob());
|
|
45
|
+
return unmarshaller(await response.text());
|
|
46
|
+
} catch (err) {
|
|
47
|
+
throw new ScalewayError(response.status, `could not parse '${contentType ?? ""}' response${err instanceof Error ? `: ${err.message}` : ""}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
const error = await response.clone().json().catch(() => response.text());
|
|
51
|
+
if (isJSONObject(error)) throw parseScalewayError(response.status, error);
|
|
52
|
+
throw new ScalewayError(response.status, typeof error === "string" ? error : "cannot read error response body");
|
|
55
53
|
};
|
|
54
|
+
export { responseParser };
|
package/dist/scw/locality.js
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
function toApiLocality(legacy) {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
2
|
+
if (!legacy) return { type: "unspecified" };
|
|
3
|
+
const { zones, regions } = legacy;
|
|
4
|
+
if (zones && zones.length > 0) return {
|
|
5
|
+
type: "zone",
|
|
6
|
+
zones
|
|
7
|
+
};
|
|
8
|
+
if (regions && regions.length > 0) return {
|
|
9
|
+
type: "region",
|
|
10
|
+
regions
|
|
11
|
+
};
|
|
12
|
+
return { type: "global" };
|
|
13
13
|
}
|
|
14
|
-
export {
|
|
15
|
-
toApiLocality
|
|
16
|
-
};
|
|
14
|
+
export { toApiLocality };
|
|
@@ -1,51 +1,43 @@
|
|
|
1
1
|
var lookup = [];
|
|
2
|
+
var revLookup = [];
|
|
2
3
|
var i;
|
|
3
4
|
var len;
|
|
4
5
|
var code = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
5
6
|
for (i = 0, len = code.length; i < len; ++i) {
|
|
6
|
-
|
|
7
|
+
lookup[i] = code[i];
|
|
8
|
+
revLookup[code.charCodeAt(i)] = i;
|
|
7
9
|
}
|
|
10
|
+
revLookup["-".charCodeAt(0)] = 62;
|
|
11
|
+
revLookup["_".charCodeAt(0)] = 63;
|
|
8
12
|
function tripletToBase64(num) {
|
|
9
|
-
|
|
13
|
+
return lookup[num >> 18 & 63] + lookup[num >> 12 & 63] + lookup[num >> 6 & 63] + lookup[num & 63];
|
|
10
14
|
}
|
|
11
15
|
function encodeChunk(uint8, start, end) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
var tmp;
|
|
17
|
+
var output = [];
|
|
18
|
+
var i;
|
|
19
|
+
for (i = start; i < end; i += 3) {
|
|
20
|
+
tmp = (uint8[i] << 16 & 16711680) + (uint8[i + 1] << 8 & 65280) + (uint8[i + 2] & 255);
|
|
21
|
+
output.push(tripletToBase64(tmp));
|
|
22
|
+
}
|
|
23
|
+
return output.join("");
|
|
20
24
|
}
|
|
21
25
|
function fromByteArray(uint8) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
if (extraBytes === 1) {
|
|
39
|
-
tmp = uint8[len2 - 1];
|
|
40
|
-
parts.push(`${lookup[tmp >> 2] + lookup[tmp << 4 & 63]}==`);
|
|
41
|
-
} else if (extraBytes === 2) {
|
|
42
|
-
tmp = (uint8[len2 - 2] << 8) + uint8[len2 - 1];
|
|
43
|
-
parts.push(
|
|
44
|
-
lookup[tmp >> 10] + lookup[tmp >> 4 & 63] + lookup[tmp << 2 & 63] + "="
|
|
45
|
-
);
|
|
46
|
-
}
|
|
47
|
-
return parts.join("");
|
|
26
|
+
var tmp;
|
|
27
|
+
var len = uint8.length;
|
|
28
|
+
var extraBytes = len % 3;
|
|
29
|
+
var parts = [];
|
|
30
|
+
var maxChunkLength = 16383;
|
|
31
|
+
var i;
|
|
32
|
+
var len2;
|
|
33
|
+
for (i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) parts.push(encodeChunk(uint8, i, i + maxChunkLength > len2 ? len2 : i + maxChunkLength));
|
|
34
|
+
if (extraBytes === 1) {
|
|
35
|
+
tmp = uint8[len - 1];
|
|
36
|
+
parts.push(`${lookup[tmp >> 2] + lookup[tmp << 4 & 63]}==`);
|
|
37
|
+
} else if (extraBytes === 2) {
|
|
38
|
+
tmp = (uint8[len - 2] << 8) + uint8[len - 1];
|
|
39
|
+
parts.push(lookup[tmp >> 10] + lookup[tmp >> 4 & 63] + lookup[tmp << 2 & 63] + "=");
|
|
40
|
+
}
|
|
41
|
+
return parts.join("");
|
|
48
42
|
}
|
|
49
|
-
export {
|
|
50
|
-
fromByteArray
|
|
51
|
-
};
|
|
43
|
+
export { fromByteArray };
|
package/package.json
CHANGED