@scaleway/sdk 0.0.2-alpha.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/LICENSE +191 -0
- package/README.md +28 -0
- package/dist/api/function/manual/FunctionAPI.js +436 -0
- package/dist/api/function/manual/WaitForFunctionAPI.js +27 -0
- package/dist/api/function/manual/types.js +1 -0
- package/dist/api/registry/manual/RegistryAPI.js +260 -0
- package/dist/api/registry/manual/WaitForRegistryAPI.js +27 -0
- package/dist/api/registry/manual/types.js +1 -0
- package/dist/helpers/API.js +12 -0
- package/dist/helpers/camelize.js +36 -0
- package/dist/helpers/forRegions.js +15 -0
- package/dist/helpers/is-browser.js +3 -0
- package/dist/helpers/json.js +6 -0
- package/dist/index.cjs +9449 -0
- package/dist/index.d.ts +1126 -0
- package/dist/index.js +13 -0
- package/dist/internal/async/interval-retrier.js +89 -0
- package/dist/internal/async/sleep.js +13 -0
- package/dist/internal/auth.js +68 -0
- package/dist/internal/interceptors/interceptor.js +11 -0
- package/dist/internal/interceptors/request.js +29 -0
- package/dist/internal/logger/console-logger.js +31 -0
- package/dist/internal/logger/index.js +38 -0
- package/dist/internal/logger/level-resolver.js +16 -0
- package/dist/internal/tools/string-validation.js +39 -0
- package/dist/internals.js +4 -0
- package/dist/node_modules/@scaleway/random-name/dist/index.js +254 -0
- package/dist/scw/client-ini-factory.js +24 -0
- package/dist/scw/client-ini-profile.js +30 -0
- package/dist/scw/client-settings.js +49 -0
- package/dist/scw/client.js +96 -0
- package/dist/scw/constants.js +4 -0
- package/dist/scw/errors/error-parser.js +121 -0
- package/dist/scw/errors/non-standard/invalid-request-mapper.js +34 -0
- package/dist/scw/errors/non-standard/unknown-resource-mapper.js +26 -0
- package/dist/scw/errors/scw-error.js +64 -0
- package/dist/scw/errors/standard/already-exists-error.js +26 -0
- package/dist/scw/errors/standard/denied-authentication-error.js +58 -0
- package/dist/scw/errors/standard/index.js +12 -0
- package/dist/scw/errors/standard/invalid-arguments-error.js +75 -0
- package/dist/scw/errors/standard/out-of-stock-error.js +24 -0
- package/dist/scw/errors/standard/permissions-denied-error.js +50 -0
- package/dist/scw/errors/standard/precondition-failed-error.js +62 -0
- package/dist/scw/errors/standard/quotas-exceeded-error.js +61 -0
- package/dist/scw/errors/standard/resource-expired-error.js +26 -0
- package/dist/scw/errors/standard/resource-locked-error.js +25 -0
- package/dist/scw/errors/standard/resource-not-found-error.js +25 -0
- package/dist/scw/errors/standard/transient-state-error.js +26 -0
- package/dist/scw/errors/types.js +26 -0
- package/dist/scw/fetch/build-fetcher.js +66 -0
- package/dist/scw/fetch/http-dumper.js +57 -0
- package/dist/scw/fetch/http-interceptors.js +80 -0
- package/dist/scw/fetch/resource-paginator.js +41 -0
- package/dist/scw/fetch/response-parser.js +46 -0
- package/dist/scw/marshalling.js +103 -0
- package/package.json +27 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ScalewayError } from '../scw-error.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* ResourceNotFound error happens when getting a resource that does not exist anymore.
|
|
5
|
+
*
|
|
6
|
+
* @public
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
class ResourceNotFoundError extends ScalewayError {
|
|
10
|
+
constructor(status, body, resource, resourceId) {
|
|
11
|
+
super(status, body, `scaleway-sdk-js: resource ${resource} with ID ${resourceId} is not found`);
|
|
12
|
+
this.status = status;
|
|
13
|
+
this.body = body;
|
|
14
|
+
this.resource = resource;
|
|
15
|
+
this.resourceId = resourceId;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
static fromJSON(status, obj) {
|
|
19
|
+
if (typeof obj.resource !== 'string' || typeof obj.resource_id !== 'string') return null;
|
|
20
|
+
return new ResourceNotFoundError(status, obj, obj.resource, obj.resource_id);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export { ResourceNotFoundError };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ScalewayError } from '../scw-error.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* TransientState error happens when trying to perform an action on a resource in a transient state.
|
|
5
|
+
*
|
|
6
|
+
* @public
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
class TransientStateError extends ScalewayError {
|
|
10
|
+
constructor(status, body, resource, resourceId, currentState) {
|
|
11
|
+
super(status, body, `scaleway-sdk-js: resource ${resource} with ID ${resourceId} is in a transient state: ${currentState}`);
|
|
12
|
+
this.status = status;
|
|
13
|
+
this.body = body;
|
|
14
|
+
this.resource = resource;
|
|
15
|
+
this.resourceId = resourceId;
|
|
16
|
+
this.currentState = currentState;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
static fromJSON(status, obj) {
|
|
20
|
+
if (typeof obj.resource !== 'string' || typeof obj.resource_id !== 'string' || typeof obj.current_state !== 'string') return null;
|
|
21
|
+
return new TransientStateError(status, obj, obj.resource, obj.resource_id, obj.current_state);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export { TransientStateError };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { isJSONObject } from '../../helpers/json.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Verifies the object is a record of string to string[].
|
|
5
|
+
*
|
|
6
|
+
* @param obj - The object
|
|
7
|
+
* @returns Whether the object is of the expected type
|
|
8
|
+
*
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const isRecordOfStringArray = obj => {
|
|
13
|
+
if (!isJSONObject(obj)) {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
for (const elt of Object.values(obj)) {
|
|
18
|
+
if (!Array.isArray(elt) || Object.values(elt).find(x => typeof x !== 'string') !== undefined) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return true;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export { isRecordOfStringArray };
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { isBrowser } from '../../helpers/is-browser.js';
|
|
2
|
+
import { obfuscateAuthHeadersEntry } from '../../internal/auth.js';
|
|
3
|
+
import { composeInterceptors } from '../../internal/interceptors/interceptor.js';
|
|
4
|
+
import { logRequest, logResponse, obfuscateInterceptor } from './http-interceptors.js';
|
|
5
|
+
import { responseParser } from './response-parser.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Builds Request from {@link ScwRequest} & {@link Settings}.
|
|
9
|
+
*
|
|
10
|
+
* @param request - A scaleway request
|
|
11
|
+
* @param settings - The settings
|
|
12
|
+
* @returns A fetch Request
|
|
13
|
+
*
|
|
14
|
+
* @internal
|
|
15
|
+
*/
|
|
16
|
+
const buildRequest = (request, settings) => {
|
|
17
|
+
let {
|
|
18
|
+
path
|
|
19
|
+
} = request;
|
|
20
|
+
|
|
21
|
+
if (request.urlParams instanceof URLSearchParams) {
|
|
22
|
+
path = path.concat(`?${request.urlParams.toString()}`);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return new Request(`${settings.apiURL}${path}`, {
|
|
26
|
+
body: request.body,
|
|
27
|
+
headers: {
|
|
28
|
+
Accept: 'application/json',
|
|
29
|
+
...(!isBrowser() ? {
|
|
30
|
+
'User-Agent': settings.userAgent
|
|
31
|
+
} : {}),
|
|
32
|
+
...request.headers
|
|
33
|
+
},
|
|
34
|
+
method: request.method
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const asIs = response => response;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Builds a resource fetcher.
|
|
42
|
+
*
|
|
43
|
+
* @param settings - The {@link Settings} object
|
|
44
|
+
* @param httpClient - The HTTP client that should be used to call the API
|
|
45
|
+
* @returns The fetcher
|
|
46
|
+
*
|
|
47
|
+
* @internal
|
|
48
|
+
*/
|
|
49
|
+
const buildFetcher = (settings, httpClient) => {
|
|
50
|
+
let requestNumber = 0;
|
|
51
|
+
|
|
52
|
+
const prepareRequest = requestId => composeInterceptors([...settings.requestInterceptors, logRequest(requestId, obfuscateInterceptor(obfuscateAuthHeadersEntry))]);
|
|
53
|
+
|
|
54
|
+
const prepareResponse = requestId => composeInterceptors([...settings.responseInterceptors, logResponse(requestId)]);
|
|
55
|
+
|
|
56
|
+
return async function (request, unwrapper) {
|
|
57
|
+
if (unwrapper === void 0) {
|
|
58
|
+
unwrapper = asIs;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const requestId = `${requestNumber += 1}`;
|
|
62
|
+
return Promise.resolve(buildRequest(request, settings)).then(prepareRequest(requestId)).then(httpClient).then(prepareResponse(requestId)).then(responseParser(unwrapper));
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export { buildFetcher, buildRequest };
|
|
@@ -0,0 +1,57 @@
|
|
|
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
|
+
const 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
|
+
|
|
19
|
+
|
|
20
|
+
const serializeHeadersEntry = _ref => {
|
|
21
|
+
let [name, value] = _ref;
|
|
22
|
+
return `${toPascalCase(name)}: ${value}`;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Converts Headers to safe to log strings (with obfuscated auth secrets).
|
|
26
|
+
*
|
|
27
|
+
* @param headers - The Headers
|
|
28
|
+
* @returns Serialized headers strings
|
|
29
|
+
*
|
|
30
|
+
* @internal
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
const serializeHeaders = headers => Array.from(headers.entries(), serializeHeadersEntry);
|
|
35
|
+
/**
|
|
36
|
+
* Dumps a Request into a readable string.
|
|
37
|
+
*
|
|
38
|
+
* @param request - The request
|
|
39
|
+
* @returns The readable string
|
|
40
|
+
*
|
|
41
|
+
* @internal
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
const dumpRequest = async request => [`${request.method.toUpperCase()}: ${request.url}`, ...serializeHeaders(request.headers), await request.clone().text()].join('\r\n');
|
|
46
|
+
/**
|
|
47
|
+
* Dumps a Response into a readable string.
|
|
48
|
+
*
|
|
49
|
+
* @param response - The response
|
|
50
|
+
* @returns The readable string
|
|
51
|
+
*
|
|
52
|
+
* @internal
|
|
53
|
+
*/
|
|
54
|
+
|
|
55
|
+
const dumpResponse = async response => [`HTTP ${response.status} ${response.ok ? 'OK' : 'NOK'}`, ...serializeHeaders(response.headers), await response.clone().text()].join('\r\n');
|
|
56
|
+
|
|
57
|
+
export { dumpRequest, dumpResponse };
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { getLogger } from '../../internal/logger/index.js';
|
|
2
|
+
import { shouldLog, LevelResolver } from '../../internal/logger/level-resolver.js';
|
|
3
|
+
import { dumpRequest, dumpResponse } from './http-dumper.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Mapper of an header entry.
|
|
7
|
+
*
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* HTTP Request with obfuscated secrets.
|
|
13
|
+
*
|
|
14
|
+
* @internal
|
|
15
|
+
*/
|
|
16
|
+
class ObfuscatedRequest extends Request {
|
|
17
|
+
constructor(request, obfuscate) {
|
|
18
|
+
super(request);
|
|
19
|
+
this.request = request;
|
|
20
|
+
this.obfuscate = obfuscate;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
get headers() {
|
|
24
|
+
return new Headers(Array.from(this.request.headers, this.obfuscate));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Creates an interceptor to obfuscate the requests.
|
|
30
|
+
*
|
|
31
|
+
* @param obfuscate - The Header entries obfuscator mapper
|
|
32
|
+
* @returns The obfuscated Request
|
|
33
|
+
*
|
|
34
|
+
* @internal
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
const obfuscateInterceptor = obfuscate => request => new ObfuscatedRequest(request, obfuscate);
|
|
39
|
+
|
|
40
|
+
const identity = instance => instance;
|
|
41
|
+
/**
|
|
42
|
+
* Creates an interceptor to log the requests.
|
|
43
|
+
*
|
|
44
|
+
* @param identifier - The request identifier
|
|
45
|
+
* @param obfuscate - The obfuscation interceptor
|
|
46
|
+
* @returns The interceptor
|
|
47
|
+
*
|
|
48
|
+
* @internal
|
|
49
|
+
*/
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
const logRequest = function (identifier, obfuscate) {
|
|
53
|
+
if (obfuscate === void 0) {
|
|
54
|
+
obfuscate = identity;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return async request => {
|
|
58
|
+
if (shouldLog(LevelResolver[getLogger().logLevel], 'debug')) getLogger().debug(`--------------- Scaleway SDK REQUEST ${identifier} ---------------
|
|
59
|
+
${await dumpRequest(await obfuscate(request))}
|
|
60
|
+
---------------------------------------------------------`);
|
|
61
|
+
return request;
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Creates an interceptor to log the responses.
|
|
66
|
+
*
|
|
67
|
+
* @param identifier - The request identifier
|
|
68
|
+
* @returns The interceptor
|
|
69
|
+
*
|
|
70
|
+
* @internal
|
|
71
|
+
*/
|
|
72
|
+
|
|
73
|
+
const logResponse = identifier => async response => {
|
|
74
|
+
if (shouldLog(LevelResolver[getLogger().logLevel], 'debug')) getLogger().debug(`--------------- Scaleway SDK RESPONSE ${identifier} ---------------
|
|
75
|
+
${await dumpResponse(response)}
|
|
76
|
+
---------------------------------------------------------`);
|
|
77
|
+
return response;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
export { logRequest, logResponse, obfuscateInterceptor };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const extract = key => result => result[key];
|
|
2
|
+
|
|
3
|
+
function* pages(key, fetcher, request, firstPage) {
|
|
4
|
+
if (!Array.isArray(firstPage[key])) throw new Error(`Property ${key} is not a list in paginated result`);
|
|
5
|
+
const getList = extract(key);
|
|
6
|
+
yield Promise.resolve(getList(firstPage));
|
|
7
|
+
const {
|
|
8
|
+
totalCount,
|
|
9
|
+
[key]: {
|
|
10
|
+
length
|
|
11
|
+
}
|
|
12
|
+
} = firstPage;
|
|
13
|
+
let page = (request.page || 1) + 1;
|
|
14
|
+
|
|
15
|
+
while (length && page <= Math.floor((totalCount + length - 1) / length)) page = (yield fetcher({ ...request,
|
|
16
|
+
page
|
|
17
|
+
}).then(getList)) || page + 1;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Fetches a paginated resource.
|
|
21
|
+
* @param key - The resource key of values list
|
|
22
|
+
* @param fetcher - The method to retrieve paginated resources
|
|
23
|
+
* @param request - A request with pagination options
|
|
24
|
+
* @returns An async generator of resources arrays
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
async function* fetchPaginated(key, fetcher, request) {
|
|
29
|
+
yield* pages(key, fetcher, request, await fetcher(request));
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Fetches all paginated resource.
|
|
33
|
+
* @param key - The resource key of values list
|
|
34
|
+
* @param fetcher - The method to retrieve paginated resources
|
|
35
|
+
* @param request - A request with pagination options
|
|
36
|
+
* @returns A resources array Promise
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
const fetchAll = async (key, fetcher, request) => (await Promise.all(Array.from(pages(key, fetcher, request, await fetcher(request))))).flat();
|
|
40
|
+
|
|
41
|
+
export { extract, fetchAll, fetchPaginated };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { isJSONObject } from '../../helpers/json.js';
|
|
2
|
+
import { parseScalewayError } from '../errors/error-parser.js';
|
|
3
|
+
import { ScalewayError } from '../errors/scw-error.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Makes response parser.
|
|
7
|
+
*
|
|
8
|
+
* @param unmarshaller - The response payload unmarshaller
|
|
9
|
+
* @returns An async converter of HTTP Response to desired result
|
|
10
|
+
*
|
|
11
|
+
* @throws {@link ScalewayError}
|
|
12
|
+
* Thrown by the API if the request couldn't be completed.
|
|
13
|
+
*
|
|
14
|
+
* @throws TypeError
|
|
15
|
+
* Thrown if the response parameter isn't of the expected type.
|
|
16
|
+
*
|
|
17
|
+
* @throws Error
|
|
18
|
+
* JSON parsing could trigger an error.
|
|
19
|
+
*
|
|
20
|
+
* @internal
|
|
21
|
+
*/
|
|
22
|
+
const responseParser = unmarshaller => async response => {
|
|
23
|
+
if (!(response instanceof Response)) throw new TypeError('Invalid response object');
|
|
24
|
+
|
|
25
|
+
if (response.ok) {
|
|
26
|
+
const contentType = response.headers.get('Content-Type');
|
|
27
|
+
|
|
28
|
+
switch (contentType) {
|
|
29
|
+
case 'application/json':
|
|
30
|
+
try {
|
|
31
|
+
return unmarshaller(await response.json());
|
|
32
|
+
} catch (err) {
|
|
33
|
+
throw new ScalewayError(response.status, `could not parse ${contentType} response`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
default:
|
|
37
|
+
throw new ScalewayError(response.status, `invalid content type ${contentType ?? ''}`.trim());
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const error = await response.clone().json().catch(() => response.text());
|
|
42
|
+
if (isJSONObject(error)) throw parseScalewayError(response.status, error);
|
|
43
|
+
throw new ScalewayError(response.status, typeof error === 'string' ? error : 'cannot read error response body');
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export { responseParser };
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { camelizeKeys } from '../helpers/camelize.js';
|
|
2
|
+
import { isJSONObject } from '../helpers/json.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Unmarshals record to convert iso dates from string to Dates.
|
|
6
|
+
*
|
|
7
|
+
* @param obj - The input
|
|
8
|
+
* @param keys - The keys requiring a conversion
|
|
9
|
+
* @returns The updated input
|
|
10
|
+
*
|
|
11
|
+
* @internal
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const unmarshalDates = (obj, keys) => {
|
|
15
|
+
if (Array.isArray(obj)) return obj.map(v => unmarshalDates(v, keys));
|
|
16
|
+
if (obj && typeof obj === 'object') return Object.entries(obj).reduce((acc, _ref) => {
|
|
17
|
+
let [key, value] = _ref;
|
|
18
|
+
return { ...acc,
|
|
19
|
+
[key]: typeof value === 'string' && keys.includes(key) ? new Date(value) : unmarshalDates(value, keys)
|
|
20
|
+
};
|
|
21
|
+
}, {});
|
|
22
|
+
return obj;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Unmarshals input to a record with camilized keys and instanciated Date.
|
|
26
|
+
*
|
|
27
|
+
* @param obj - The input
|
|
28
|
+
* @param ignoreKeys - The keys which should be not be transformed
|
|
29
|
+
* @param dateKeys - The keys which should be transformed to Date
|
|
30
|
+
* @returns The record
|
|
31
|
+
*
|
|
32
|
+
* @throws TypeError
|
|
33
|
+
* Thrown if the input isn't {@link JSONObject}.
|
|
34
|
+
*
|
|
35
|
+
* @internal
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
const unmarshalAnyRes = function (obj, ignoreKeys, dateKeys) {
|
|
39
|
+
if (ignoreKeys === void 0) {
|
|
40
|
+
ignoreKeys = [];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (!isJSONObject(obj)) throw new TypeError(`Data isn't a dictionary.`);
|
|
44
|
+
return camelizeKeys(dateKeys && dateKeys.length > 0 ? unmarshalDates(obj, dateKeys) : obj, ignoreKeys);
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Throws an exception if the parameter is neither a string or defined.
|
|
48
|
+
*
|
|
49
|
+
* @param name - The parameter name
|
|
50
|
+
* @param param - The parameter value
|
|
51
|
+
*
|
|
52
|
+
* @throws ReferenceError
|
|
53
|
+
* Thrown if the parameter is invalid.
|
|
54
|
+
*
|
|
55
|
+
* @internal
|
|
56
|
+
*/
|
|
57
|
+
|
|
58
|
+
function assertNotEmptyParam(name, param) {
|
|
59
|
+
if (typeof param !== 'string' || param.length === 0) throw new ReferenceError(`param ${name} cannot be empty in request`);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Resolves the ideal parameter and value amongst an optional list.
|
|
63
|
+
*
|
|
64
|
+
* @param list - The list to be looking into
|
|
65
|
+
* @returns The parameter and value
|
|
66
|
+
*
|
|
67
|
+
* @throws ReferenceError
|
|
68
|
+
* Thrown if no value or default value is specified.
|
|
69
|
+
*
|
|
70
|
+
* @internal
|
|
71
|
+
*/
|
|
72
|
+
|
|
73
|
+
const resolveOneOf = list => {
|
|
74
|
+
const elt = list.find(obj => obj.value) || list.find(obj => obj.default);
|
|
75
|
+
const value = (elt == null ? void 0 : elt.value) || (elt == null ? void 0 : elt.default);
|
|
76
|
+
if (value) return {
|
|
77
|
+
param: elt.param,
|
|
78
|
+
value
|
|
79
|
+
};
|
|
80
|
+
const keyList = list.map(obj => obj.param).join(' or ');
|
|
81
|
+
throw new ReferenceError(`one of ${keyList} must be indicated in the request`);
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Filters defined parameters tuples and converts them to URLSearchParams.
|
|
85
|
+
*
|
|
86
|
+
* @param paramTuples - The key/value pairs
|
|
87
|
+
* @returns URLSearchParams
|
|
88
|
+
*
|
|
89
|
+
* @internal
|
|
90
|
+
*/
|
|
91
|
+
|
|
92
|
+
const urlParams = function () {
|
|
93
|
+
for (var _len = arguments.length, paramTuples = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
94
|
+
paramTuples[_key] = arguments[_key];
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return new URLSearchParams(paramTuples.reduce((params, _ref2) => {
|
|
98
|
+
let [key, value] = _ref2;
|
|
99
|
+
return typeof key === 'string' && value != null ? [...params, [key, value.toString()]] : params;
|
|
100
|
+
}, []));
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
export { assertNotEmptyParam, resolveOneOf, unmarshalAnyRes, unmarshalDates, urlParams };
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@scaleway/sdk",
|
|
3
|
+
"version": "0.0.2-alpha.0",
|
|
4
|
+
"license": "Apache-2.0",
|
|
5
|
+
"description": "Scaleway SDK.",
|
|
6
|
+
"main": "dist/index.cjs",
|
|
7
|
+
"module": "dist/index.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"files": [
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
12
|
+
"publishConfig": {
|
|
13
|
+
"access": "public"
|
|
14
|
+
},
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"directory": "packages/clients"
|
|
18
|
+
},
|
|
19
|
+
"engines": {
|
|
20
|
+
"node": ">=14.x"
|
|
21
|
+
},
|
|
22
|
+
"type": "module",
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@scaleway/random-name": "^3.0.0"
|
|
25
|
+
},
|
|
26
|
+
"gitHead": "348ef780f8af12baa19e8c5b3c02f3087bcf0964"
|
|
27
|
+
}
|