@scaleway/sdk-client 2.2.0 → 2.2.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.
Files changed (84) hide show
  1. package/dist/_virtual/_rolldown/runtime.js +2 -0
  2. package/dist/bridge.js +8 -0
  3. package/dist/helpers/__tests__/is-browser.browser.test.js +10 -0
  4. package/dist/helpers/__tests__/is-browser.node.test.js +10 -0
  5. package/dist/helpers/__tests__/json.test.js +48 -0
  6. package/dist/helpers/__tests__/marshalling.test.js +177 -0
  7. package/dist/helpers/is-browser.js +3 -1
  8. package/dist/helpers/is-response.js +3 -1
  9. package/dist/helpers/json.js +10 -4
  10. package/dist/helpers/marshalling.js +7 -5
  11. package/dist/index.js +4 -4
  12. package/dist/internal/async/__tests__/interval-retrier.test.js +121 -0
  13. package/dist/internal/async/__tests__/sleep.test.js +19 -0
  14. package/dist/internal/async/interval-retrier.d.ts +1 -1
  15. package/dist/internal/async/interval-retrier.js +33 -3
  16. package/dist/internal/async/sleep.js +3 -1
  17. package/dist/internal/interceptors/__tests__/composer.test.js +48 -0
  18. package/dist/internal/interceptors/__tests__/helpers.test.js +27 -0
  19. package/dist/internal/interceptors/composer.js +5 -3
  20. package/dist/internal/interceptors/helpers.js +4 -2
  21. package/dist/internal/interceptors/types.js +0 -0
  22. package/dist/internal/logger/__tests__/index.test.js +209 -0
  23. package/dist/internal/logger/console-logger.js +2 -0
  24. package/dist/internal/logger/index.js +5 -3
  25. package/dist/internal/logger/level-resolver.js +4 -2
  26. package/dist/internal/logger/logger.js +0 -0
  27. package/dist/internal/validations/__tests__/string-validation.test.js +98 -0
  28. package/dist/internal/validations/string-validation.js +14 -9
  29. package/dist/internals.js +9 -8
  30. package/dist/package.js +2 -1
  31. package/dist/scw/__tests__/api.test.js +19 -0
  32. package/dist/scw/__tests__/auth.test.js +57 -0
  33. package/dist/scw/__tests__/client-ini-factory.test.js +220 -0
  34. package/dist/scw/__tests__/client-ini-profile.test.js +70 -0
  35. package/dist/scw/__tests__/client-settings.test.js +51 -0
  36. package/dist/scw/__tests__/client.test.js +59 -0
  37. package/dist/scw/__tests__/custom-marshalling.test.js +168 -0
  38. package/dist/scw/api.js +2 -0
  39. package/dist/scw/auth.js +17 -6
  40. package/dist/scw/client-ini-factory.js +9 -7
  41. package/dist/scw/client-ini-profile.js +3 -1
  42. package/dist/scw/client-settings.js +3 -1
  43. package/dist/scw/client.js +4 -2
  44. package/dist/scw/constants.js +6 -4
  45. package/dist/scw/custom-marshalling.js +17 -15
  46. package/dist/scw/custom-types.js +2 -0
  47. package/dist/scw/errors/__tests__/scw-error.test.js +41 -0
  48. package/dist/scw/errors/__tests__/types.test.js +16 -0
  49. package/dist/scw/errors/error-parser.js +3 -1
  50. package/dist/scw/errors/non-standard/__tests__/index.test.js +123 -0
  51. package/dist/scw/errors/non-standard/invalid-request-mapper.js +3 -1
  52. package/dist/scw/errors/non-standard/unknown-resource-mapper.js +3 -1
  53. package/dist/scw/errors/scw-error-from-json.js +0 -0
  54. package/dist/scw/errors/scw-error.js +2 -0
  55. package/dist/scw/errors/standard/__tests__/index.test.js +329 -0
  56. package/dist/scw/errors/standard/already-exists-error.js +2 -0
  57. package/dist/scw/errors/standard/denied-authentication-error.js +2 -0
  58. package/dist/scw/errors/standard/index.js +3 -1
  59. package/dist/scw/errors/standard/invalid-arguments-error.js +2 -0
  60. package/dist/scw/errors/standard/out-of-stock-error.js +2 -0
  61. package/dist/scw/errors/standard/permissions-denied-error.js +2 -0
  62. package/dist/scw/errors/standard/precondition-failed-error.js +2 -0
  63. package/dist/scw/errors/standard/quotas-exceeded-error.js +2 -0
  64. package/dist/scw/errors/standard/resource-expired-error.js +2 -0
  65. package/dist/scw/errors/standard/resource-locked-error.js +2 -0
  66. package/dist/scw/errors/standard/resource-not-found-error.js +2 -0
  67. package/dist/scw/errors/standard/too-many-requests-error.js +2 -0
  68. package/dist/scw/errors/standard/transient-state-error.js +2 -0
  69. package/dist/scw/errors/types.js +3 -1
  70. package/dist/scw/fetch/__tests__/build-fetcher.test.js +114 -0
  71. package/dist/scw/fetch/__tests__/http-dumper.test.js +45 -0
  72. package/dist/scw/fetch/__tests__/http-interceptors.test.js +60 -0
  73. package/dist/scw/fetch/__tests__/resource-paginator.test.js +110 -0
  74. package/dist/scw/fetch/__tests__/response-parser.test.js +94 -0
  75. package/dist/scw/fetch/build-fetcher.js +6 -4
  76. package/dist/scw/fetch/http-dumper.js +4 -2
  77. package/dist/scw/fetch/http-interceptors.js +5 -3
  78. package/dist/scw/fetch/resource-paginator.js +6 -4
  79. package/dist/scw/fetch/response-parser.js +5 -3
  80. package/dist/scw/fetch/types.js +0 -0
  81. package/dist/scw/locality.js +2 -0
  82. package/dist/vendor/base64/index.d.js +0 -0
  83. package/dist/vendor/base64/index.js +2 -0
  84. package/package.json +1 -1
@@ -0,0 +1,220 @@
1
+ import { withAdditionalInterceptors, withDefaultPageSize, withHTTPClient, withLegacyInterceptors, withProfile, withUserAgent, withUserAgentSuffix } from "../client-ini-factory.js";
2
+ import { describe, expect, it } from "vitest";
3
+ //#region src/scw/__tests__/client-ini-factory.test.ts
4
+ var EMPTY_PROFILE = {};
5
+ var FILLED_PROFILE = {
6
+ accessKey: "SCW1234567890ABCDEFG",
7
+ apiURL: "https://api.example.com",
8
+ defaultOrganizationId: "a8f9d4ab-dda4-4b9d-ab77-0a8c59a246e9",
9
+ defaultProjectId: "d67e2125-a1ee-4056-9f7a-ab855be03d07",
10
+ defaultRegion: "fr-par",
11
+ defaultZone: "fr-par-3",
12
+ secretKey: "3aef5281-13eb-4705-b858-eb64dd5da24c"
13
+ };
14
+ var DEFAULT_SETTINGS = {
15
+ apiURL: "https://api.scaleway.com",
16
+ defaultOrganizationId: "bd61983a-e4b5-4c6b-a841-07bc44037b5a",
17
+ defaultPageSize: 10,
18
+ defaultProjectId: "43f42be7-ea3d-4148-889c-3ad4b53bddcb",
19
+ defaultRegion: "nl-ams",
20
+ defaultZone: "fr-par-1",
21
+ httpClient: fetch,
22
+ interceptors: [],
23
+ userAgent: "scaleway-sdk-js/v1.0.0-beta"
24
+ };
25
+ describe("withProfile", () => {
26
+ it(`doesn't modify Settings object with empty Profile object`, () => {
27
+ expect(withProfile(EMPTY_PROFILE)(DEFAULT_SETTINGS)).toStrictEqual(DEFAULT_SETTINGS);
28
+ expect(withProfile({ WTF: "malicious content" })(DEFAULT_SETTINGS)).toStrictEqual(DEFAULT_SETTINGS);
29
+ expect(withProfile({
30
+ apiURL: void 0,
31
+ defaultOrganizationId: void 0,
32
+ defaultPageSize: void 0,
33
+ defaultProjectId: void 0,
34
+ defaultRegion: void 0,
35
+ defaultZone: void 0,
36
+ httpClient: void 0,
37
+ interceptors: void 0,
38
+ requestInterceptors: void 0,
39
+ responseInterceptors: void 0,
40
+ userAgent: void 0
41
+ })(DEFAULT_SETTINGS)).toStrictEqual(DEFAULT_SETTINGS);
42
+ expect(withProfile({
43
+ apiURL: null,
44
+ defaultOrganizationId: null,
45
+ defaultPageSize: null,
46
+ defaultProjectId: null,
47
+ defaultRegion: null,
48
+ defaultZone: null,
49
+ httpClient: null,
50
+ interceptors: null,
51
+ requestInterceptors: null,
52
+ responseInterceptors: null,
53
+ userAgent: null
54
+ })(DEFAULT_SETTINGS)).toStrictEqual(DEFAULT_SETTINGS);
55
+ expect(withProfile({
56
+ apiURL: "",
57
+ defaultOrganizationId: "",
58
+ defaultPageSize: "",
59
+ defaultProjectId: "",
60
+ defaultRegion: "",
61
+ defaultZone: "",
62
+ httpClient: "",
63
+ interceptors: "",
64
+ requestInterceptors: "",
65
+ responseInterceptors: "",
66
+ userAgent: ""
67
+ })(DEFAULT_SETTINGS)).toStrictEqual(DEFAULT_SETTINGS);
68
+ expect(withProfile({
69
+ apiURL: 0,
70
+ defaultOrganizationId: 0,
71
+ defaultPageSize: 0,
72
+ defaultProjectId: 0,
73
+ defaultRegion: 0,
74
+ defaultZone: 0,
75
+ httpClient: 0,
76
+ interceptors: 0,
77
+ requestInterceptors: 0,
78
+ responseInterceptors: 0,
79
+ userAgent: 0
80
+ })(DEFAULT_SETTINGS)).toStrictEqual(DEFAULT_SETTINGS);
81
+ });
82
+ it("only modifies apiURL", () => {
83
+ const expectedSettings = {
84
+ ...DEFAULT_SETTINGS,
85
+ apiURL: FILLED_PROFILE.apiURL
86
+ };
87
+ expect(withProfile({ apiURL: FILLED_PROFILE.apiURL })(DEFAULT_SETTINGS)).toStrictEqual(expectedSettings);
88
+ });
89
+ it("only modifies default organization ID", () => {
90
+ const expectedSettings = {
91
+ ...DEFAULT_SETTINGS,
92
+ defaultOrganizationId: FILLED_PROFILE.defaultOrganizationId
93
+ };
94
+ expect(withProfile({ defaultOrganizationId: FILLED_PROFILE.defaultOrganizationId })(DEFAULT_SETTINGS)).toStrictEqual(expectedSettings);
95
+ });
96
+ it("only modifies default project ID", () => {
97
+ const expectedSettings = {
98
+ ...DEFAULT_SETTINGS,
99
+ defaultProjectId: FILLED_PROFILE.defaultProjectId
100
+ };
101
+ expect(withProfile({ defaultProjectId: FILLED_PROFILE.defaultProjectId })(DEFAULT_SETTINGS)).toStrictEqual(expectedSettings);
102
+ });
103
+ it("only modifies default region", () => {
104
+ const expectedSettings = {
105
+ ...DEFAULT_SETTINGS,
106
+ defaultRegion: FILLED_PROFILE.defaultRegion
107
+ };
108
+ expect(withProfile({ defaultRegion: FILLED_PROFILE.defaultRegion })(DEFAULT_SETTINGS)).toStrictEqual(expectedSettings);
109
+ });
110
+ it("only modifies default zone", () => {
111
+ const expectedSettings = {
112
+ ...DEFAULT_SETTINGS,
113
+ defaultZone: FILLED_PROFILE.defaultZone
114
+ };
115
+ expect(withProfile({ defaultZone: FILLED_PROFILE.defaultZone })(DEFAULT_SETTINGS)).toStrictEqual(expectedSettings);
116
+ });
117
+ it("modifies authentication", async () => {
118
+ if (!DEFAULT_SETTINGS.apiURL) throw new Error("API URL is missing");
119
+ const request = new Request(DEFAULT_SETTINGS.apiURL);
120
+ const reqInterceptor = withProfile({
121
+ accessKey: FILLED_PROFILE.accessKey,
122
+ secretKey: FILLED_PROFILE.secretKey
123
+ })(DEFAULT_SETTINGS).interceptors[0].request;
124
+ expect(reqInterceptor).toBeDefined();
125
+ if (reqInterceptor) {
126
+ const { headers } = await reqInterceptor({ request });
127
+ expect(headers.get("x-auth-token")).toStrictEqual(FILLED_PROFILE.secretKey);
128
+ }
129
+ });
130
+ });
131
+ describe("withDefaultPageSize", () => {
132
+ it("only modifies the default page size", () => {
133
+ const newDefaultPageSize = 42;
134
+ const expectedSettings = {
135
+ ...DEFAULT_SETTINGS,
136
+ defaultPageSize: newDefaultPageSize
137
+ };
138
+ expect(JSON.stringify(withDefaultPageSize(newDefaultPageSize)(DEFAULT_SETTINGS))).toStrictEqual(JSON.stringify(expectedSettings));
139
+ });
140
+ });
141
+ describe("withHTTPClient", () => {
142
+ it("only modifies the http client", () => {
143
+ const newHTTPClient = () => Promise.resolve(new Response());
144
+ const expectedSettings = {
145
+ ...DEFAULT_SETTINGS,
146
+ httpClient: newHTTPClient
147
+ };
148
+ expect(JSON.stringify(withHTTPClient(newHTTPClient)(DEFAULT_SETTINGS))).toStrictEqual(JSON.stringify(expectedSettings));
149
+ });
150
+ });
151
+ describe("withUserAgent", () => {
152
+ const defaultUserAgent = "my-source/v0.1.0";
153
+ it("only modifies the user agent", () => {
154
+ const expectedSettings = {
155
+ ...DEFAULT_SETTINGS,
156
+ userAgent: defaultUserAgent
157
+ };
158
+ expect(JSON.stringify(withUserAgent(defaultUserAgent)(DEFAULT_SETTINGS))).toStrictEqual(JSON.stringify(expectedSettings));
159
+ });
160
+ });
161
+ describe("withUserAgentSuffix", () => {
162
+ it("appends to the original user agent", () => {
163
+ const defaultUserAgent = DEFAULT_SETTINGS.userAgent;
164
+ const addUserAgent = "additional-source/v1.0.0";
165
+ const expectedSettings = {
166
+ ...DEFAULT_SETTINGS,
167
+ userAgent: `${defaultUserAgent} ${addUserAgent}`
168
+ };
169
+ expect(JSON.stringify(withUserAgentSuffix(addUserAgent)(DEFAULT_SETTINGS))).toStrictEqual(JSON.stringify(expectedSettings));
170
+ });
171
+ it("replaces the default user agent if the original one is empty", () => {
172
+ const newSettings = {
173
+ ...DEFAULT_SETTINGS,
174
+ userAgent: ""
175
+ };
176
+ const addUserAgent = "additional-source/v1.0.0";
177
+ const expectedSettings = {
178
+ ...newSettings,
179
+ userAgent: addUserAgent
180
+ };
181
+ expect(JSON.stringify(withUserAgentSuffix(addUserAgent)(newSettings))).toStrictEqual(JSON.stringify(expectedSettings));
182
+ });
183
+ });
184
+ describe("withAdditionalInterceptors", () => {
185
+ it("appends interceptors to existing ones", () => {
186
+ const oneInterProfile = withAdditionalInterceptors([{ request: ({ request }) => request }])(DEFAULT_SETTINGS);
187
+ const twoInterProfile = withAdditionalInterceptors([{
188
+ response: ({ response }) => response,
189
+ responseError: (err) => err
190
+ }])(oneInterProfile);
191
+ expect(twoInterProfile.interceptors.length).toEqual(2);
192
+ expect(twoInterProfile.interceptors[1].response).toBeDefined();
193
+ expect(twoInterProfile.interceptors[1].responseError).toBeDefined();
194
+ expect(twoInterProfile.interceptors[1].request).toBeUndefined();
195
+ });
196
+ });
197
+ describe("withLegacyInterceptors", () => {
198
+ it("changes nothing if no legacy interceptor", () => {
199
+ expect(JSON.stringify(withLegacyInterceptors()(DEFAULT_SETTINGS))).toStrictEqual(JSON.stringify(DEFAULT_SETTINGS));
200
+ });
201
+ it("appends the legacy request and response interceptors", () => {
202
+ const legacyInterceptors = (obj) => ({
203
+ ...obj,
204
+ requestInterceptors: [({ request }) => request, ({ request }) => request],
205
+ responseInterceptors: [({ response }) => response]
206
+ });
207
+ expect(withLegacyInterceptors()(legacyInterceptors(DEFAULT_SETTINGS)).interceptors.length).toBe(3);
208
+ const legacyReqInterceptors = (obj) => ({
209
+ ...obj,
210
+ requestInterceptors: [({ request }) => request, ({ request }) => request]
211
+ });
212
+ expect(withLegacyInterceptors()(legacyReqInterceptors(DEFAULT_SETTINGS)).interceptors.length).toBe(2);
213
+ const legacyResInterceptors = (obj) => ({
214
+ ...obj,
215
+ responseInterceptors: [({ response }) => response]
216
+ });
217
+ expect(withLegacyInterceptors()(legacyResInterceptors(DEFAULT_SETTINGS)).interceptors.length).toBe(1);
218
+ });
219
+ });
220
+ //#endregion
@@ -0,0 +1,70 @@
1
+ import { assertValidAuthenticationSecrets, hasAuthenticationSecrets } from "../client-ini-profile.js";
2
+ import { describe, expect, it, test } from "vitest";
3
+ //#region src/scw/__tests__/client-ini-profile.test.ts
4
+ describe("hasAuthenticationSecrets", () => {
5
+ it("confirms a non-empty payload", () => {
6
+ expect(hasAuthenticationSecrets({
7
+ accessKey: "any-string",
8
+ secretKey: "any-string"
9
+ })).toBeTruthy();
10
+ });
11
+ it("rejects payload with empty access or secret", () => {
12
+ expect(hasAuthenticationSecrets({
13
+ accessKey: "",
14
+ secretKey: ""
15
+ })).toBeFalsy();
16
+ expect(hasAuthenticationSecrets({
17
+ accessKey: "",
18
+ secretKey: "any-string"
19
+ })).toBeFalsy();
20
+ expect(hasAuthenticationSecrets({
21
+ accessKey: "any-string",
22
+ secretKey: ""
23
+ })).toBeFalsy();
24
+ });
25
+ });
26
+ describe("assertValidAuthenticationSecrets", () => {
27
+ it(`doesn't throw for valid secrets`, () => {
28
+ expect(() => {
29
+ assertValidAuthenticationSecrets({
30
+ accessKey: "SCW01234567890123456",
31
+ secretKey: "e4b83996-4c60-449a-98d2-38f5de7b4e6b"
32
+ });
33
+ }).not.toThrow();
34
+ });
35
+ test.each([
36
+ {
37
+ accessKey: "",
38
+ secretKey: ""
39
+ },
40
+ {
41
+ accessKey: "SCW01234567890123456",
42
+ secretKey: ""
43
+ },
44
+ {
45
+ accessKey: "",
46
+ secretKey: "e4b83996-4c60-449a-98d2-38f5de7b4e6b"
47
+ }
48
+ ])("%s throws for empty keys", (value) => {
49
+ expect(() => {
50
+ assertValidAuthenticationSecrets(value);
51
+ }).toThrow(/* @__PURE__ */ new Error(`Invalid secrets, accessKey & secretKey must be defined. See https://www.scaleway.com/en/docs/identity-and-access-management/iam/how-to/create-api-keys/`));
52
+ });
53
+ it(`throws for invalid accessKey`, () => {
54
+ expect(() => {
55
+ assertValidAuthenticationSecrets({
56
+ accessKey: "SCW0123",
57
+ secretKey: "e4b83996-4c60-449a-98d2-38f5de7b4e6b"
58
+ });
59
+ }).toThrow(/* @__PURE__ */ new Error(`Invalid access key format 'SCW0123', expected SCWXXXXXXXXXXXXXXXXX format. See https://www.scaleway.com/en/docs/identity-and-access-management/iam/how-to/create-api-keys/`));
60
+ });
61
+ it(`throws for invalid secretKey`, () => {
62
+ expect(() => {
63
+ assertValidAuthenticationSecrets({
64
+ accessKey: "SCW01234567890123456",
65
+ secretKey: "e4b83996-4c60-449a-98d2"
66
+ });
67
+ }).toThrow(/* @__PURE__ */ new Error(`Invalid secret key format 'e4b83996-4c60-449a-98d2', expected a UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. See https://www.scaleway.com/en/docs/identity-and-access-management/iam/how-to/create-api-keys/`));
68
+ });
69
+ });
70
+ //#endregion
@@ -0,0 +1,51 @@
1
+ import { assertValidSettings } from "../client-settings.js";
2
+ import { describe, expect, it } from "vitest";
3
+ //#region src/scw/__tests__/client-settings.test.ts
4
+ var VALID_SETTINGS = {
5
+ apiURL: "https://api.scaleway.com",
6
+ defaultOrganizationId: "1f1ca70e-a7d4-4061-8495-09e17e69a0dc",
7
+ defaultPageSize: 10,
8
+ defaultProjectId: "ca69720b-8a3d-4295-8f6d-87257f0474b4",
9
+ defaultRegion: "fr-par",
10
+ defaultZone: "fr-par-1",
11
+ httpClient: fetch,
12
+ interceptors: [],
13
+ requestInterceptors: [],
14
+ responseInterceptors: [],
15
+ userAgent: "scaleway-sdk-js/v1.0.0-beta"
16
+ };
17
+ var INVALID_SETTINGS_LIST = [
18
+ { apiURL: "https://api.scaleway.com/" },
19
+ { apiURL: "ftp://api.scaleway.com" },
20
+ { defaultZone: "fr-par-0" },
21
+ { defaultZone: "fr-par" },
22
+ { defaultRegion: "fr-par-1" },
23
+ { httpClient: "str-client" },
24
+ { defaultOrganizationId: "" },
25
+ { defaultOrganizationId: "not-a-uuid-v4" },
26
+ { defaultProjectId: "" },
27
+ { defaultProjectId: "not-a-uuid-v4" },
28
+ { defaultPageSize: 0 },
29
+ { defaultPageSize: -1 },
30
+ { defaultPageSize: "42" },
31
+ { userAgent: null }
32
+ ];
33
+ describe("assertValidSettings", () => {
34
+ it("accepts valid Settings object", () => {
35
+ expect(() => {
36
+ assertValidSettings(VALID_SETTINGS);
37
+ }).not.toThrow();
38
+ });
39
+ for (const obj of INVALID_SETTINGS_LIST) {
40
+ const newProfile = {
41
+ ...VALID_SETTINGS,
42
+ ...obj
43
+ };
44
+ it(`rejects invalid Settings object ${JSON.stringify(obj)}`, () => {
45
+ expect(() => {
46
+ assertValidSettings(newProfile);
47
+ }).toThrow();
48
+ });
49
+ }
50
+ });
51
+ //#endregion
@@ -0,0 +1,59 @@
1
+ import { withProfile } from "../client-ini-factory.js";
2
+ import { createAdvancedClient, createClient } from "../client.js";
3
+ import { describe, expect, it } from "vitest";
4
+ //#region src/scw/__tests__/client.test.ts
5
+ var withApiURL = (apiURL) => (obj) => ({
6
+ ...obj,
7
+ apiURL
8
+ });
9
+ var withPassthroughFetch = (res) => (obj) => ({
10
+ ...obj,
11
+ httpClient: () => Promise.resolve(new Response(res))
12
+ });
13
+ describe("createAdvancedClient", () => {
14
+ it("initializes without throwing", () => {
15
+ expect(() => {
16
+ createAdvancedClient();
17
+ }).not.toThrow();
18
+ });
19
+ it("contains override from withProfile", () => {
20
+ expect(createAdvancedClient(withProfile({ defaultRegion: "nl-ams" })).settings.defaultRegion).toBe("nl-ams");
21
+ });
22
+ it("contains override from withProfile with authentication", () => {
23
+ expect(createAdvancedClient(withProfile({
24
+ accessKey: "SCW1234567890ABCDEFG",
25
+ secretKey: "3aef5281-13eb-4705-b858-eb64dd5da24c"
26
+ })).settings.interceptors.length).toBe(1);
27
+ });
28
+ it("does not mutate default requestInterceptors", () => {
29
+ let client = createAdvancedClient(withProfile({
30
+ accessKey: "SCW1234567890ABCDEFG",
31
+ secretKey: "3aef5281-13eb-4705-b858-eb64dd5da24c"
32
+ }));
33
+ client = createAdvancedClient(withProfile({
34
+ accessKey: "SCW1234567890ABCDEFG",
35
+ secretKey: "3aef5281-13eb-4705-b858-eb64dd5da24c"
36
+ }));
37
+ expect(client.settings.interceptors.length).toBe(1);
38
+ });
39
+ it("contains override from custom option", () => {
40
+ const betaApiRoot = "https://api-beta.scaleway.com";
41
+ expect(createAdvancedClient(withApiURL(betaApiRoot)).settings.apiURL).toBe(betaApiRoot);
42
+ });
43
+ it("contains override of httpClient", () => {
44
+ return expect(createAdvancedClient(withPassthroughFetch("hello world")).settings.httpClient("any-url").then((obj) => obj.text())).resolves.toBe("hello world");
45
+ });
46
+ });
47
+ describe("createClient", () => {
48
+ it("initializes without throwing", () => {
49
+ expect(() => {
50
+ createClient();
51
+ }).not.toThrow();
52
+ });
53
+ it("contains proper default values", () => {
54
+ const client = createAdvancedClient();
55
+ expect(client.settings.apiURL).toBe("https://api.scaleway.com");
56
+ expect(client.settings.userAgent.startsWith("scaleway-sdk-js/")).toBe(true);
57
+ });
58
+ });
59
+ //#endregion
@@ -0,0 +1,168 @@
1
+ import { Decimal } from "../custom-types.js";
2
+ import { marshalMoney, marshalScwFile, marshalTimeSeries, marshalTimeSeriesPoint, unmarshalDecimal, unmarshalMoney, unmarshalScwFile, unmarshalServiceInfo, unmarshalTimeSeries, unmarshalTimeSeriesPoint } from "../custom-marshalling.js";
3
+ import { describe, expect, it } from "vitest";
4
+ //#region src/scw/__tests__/custom-marshalling.test.ts
5
+ describe("unmarshalMoney", () => {
6
+ it("returns the proper object", () => {
7
+ expect(unmarshalMoney({
8
+ currency_code: "EUR",
9
+ nanos: 0,
10
+ units: 42
11
+ })).toStrictEqual({
12
+ currencyCode: "EUR",
13
+ nanos: 0,
14
+ units: 42
15
+ });
16
+ });
17
+ it("throws for invalid input", () => {
18
+ expect(() => {
19
+ unmarshalMoney(null);
20
+ }).toThrow();
21
+ });
22
+ });
23
+ describe("unmarshalServiceInfo", () => {
24
+ it("returns the proper object", () => {
25
+ expect(unmarshalServiceInfo({
26
+ description: "Service description",
27
+ documentation_url: "https://",
28
+ name: "TheService",
29
+ version: "v1"
30
+ })).toStrictEqual({
31
+ description: "Service description",
32
+ documentationUrl: "https://",
33
+ name: "TheService",
34
+ version: "v1"
35
+ });
36
+ });
37
+ it("throws for invalid input", () => {
38
+ expect(() => {
39
+ unmarshalServiceInfo(null);
40
+ }).toThrow();
41
+ });
42
+ });
43
+ describe("unmarshalScwFile", () => {
44
+ it("returns the proper object", () => {
45
+ expect(unmarshalScwFile({
46
+ content: "eyJoZWxsbyI6IndvcmxkIn0=",
47
+ content_type: "text/plain",
48
+ name: "filename"
49
+ })).toStrictEqual({
50
+ content: "eyJoZWxsbyI6IndvcmxkIn0=",
51
+ contentType: "text/plain",
52
+ name: "filename"
53
+ });
54
+ });
55
+ it("throws for invalid input", () => {
56
+ expect(() => {
57
+ unmarshalScwFile(null);
58
+ }).toThrow();
59
+ });
60
+ });
61
+ describe("unmarshalTimeSeriesPoint", () => {
62
+ it("returns the proper object", () => {
63
+ expect(unmarshalTimeSeriesPoint(["2019-08-08T15:00:00.000Z", 42])).toStrictEqual({
64
+ timestamp: /* @__PURE__ */ new Date("2019-08-08T15:00:00.000Z"),
65
+ value: 42
66
+ });
67
+ });
68
+ it("throws for invalid input", () => {
69
+ expect(() => {
70
+ unmarshalTimeSeriesPoint(null);
71
+ }).toThrow();
72
+ });
73
+ });
74
+ describe("unmarshalTimeSeries", () => {
75
+ it("returns the proper object", () => {
76
+ expect(unmarshalTimeSeries({
77
+ metadata: { mattress: "cloud" },
78
+ name: "sleep",
79
+ points: [["2019-08-08T15:00:00.000Z", 8]]
80
+ })).toStrictEqual({
81
+ metadata: { mattress: "cloud" },
82
+ name: "sleep",
83
+ points: [{
84
+ timestamp: /* @__PURE__ */ new Date("2019-08-08T15:00:00.000Z"),
85
+ value: 8
86
+ }]
87
+ });
88
+ });
89
+ it("throws for invalid input", () => {
90
+ expect(() => {
91
+ unmarshalTimeSeries(null);
92
+ }).toThrow();
93
+ });
94
+ });
95
+ describe("unmarshalDecimal", () => {
96
+ it("returns the proper object", () => {
97
+ const decimal = unmarshalDecimal({ value: "0.01" });
98
+ expect(decimal).toBeInstanceOf(Decimal);
99
+ expect(decimal?.toString()).toStrictEqual("0.01");
100
+ });
101
+ it("throws for invalid input", () => {
102
+ expect(unmarshalDecimal(null)).toBeNull();
103
+ expect(() => {
104
+ unmarshalDecimal({});
105
+ }).toThrow();
106
+ expect(() => {
107
+ unmarshalDecimal({ value: null });
108
+ }).toThrow();
109
+ expect(() => {
110
+ unmarshalDecimal({ value: .02 });
111
+ }).toThrow();
112
+ });
113
+ });
114
+ describe("marshalScwFile", () => {
115
+ it("returns a the proper object", () => expect(marshalScwFile({
116
+ content: "eyJoZWxsbyI6IndvcmxkIn0=",
117
+ contentType: "text/plain",
118
+ name: "filename"
119
+ })).toStrictEqual({
120
+ content: "eyJoZWxsbyI6IndvcmxkIn0=",
121
+ content_type: "text/plain",
122
+ name: "filename"
123
+ }));
124
+ });
125
+ describe("marshalMoney", () => {
126
+ it("returns the proper object", () => {
127
+ expect(marshalMoney({
128
+ currencyCode: "EUR",
129
+ nanos: 0,
130
+ units: 42
131
+ })).toStrictEqual({
132
+ currency_code: "EUR",
133
+ nanos: 0,
134
+ units: 42
135
+ });
136
+ });
137
+ });
138
+ describe("marshalTimeSeriesPoint", () => {
139
+ it("returns the proper object", () => {
140
+ expect(marshalTimeSeriesPoint({
141
+ timestamp: /* @__PURE__ */ new Date("2019-08-08T15:00:00.000Z"),
142
+ value: 42
143
+ })).toStrictEqual({
144
+ timestamp: "2019-08-08T15:00:00.000Z",
145
+ value: 42
146
+ });
147
+ });
148
+ });
149
+ describe("marshalTimeSeries", () => {
150
+ it("returns the proper object", () => {
151
+ expect(marshalTimeSeries({
152
+ metadata: { mattress: "cloud" },
153
+ name: "sleep",
154
+ points: [{
155
+ timestamp: /* @__PURE__ */ new Date("2019-08-08T15:00:00.000Z"),
156
+ value: 8
157
+ }]
158
+ })).toStrictEqual({
159
+ metadata: { mattress: "cloud" },
160
+ name: "sleep",
161
+ points: [{
162
+ timestamp: "2019-08-08T15:00:00.000Z",
163
+ value: 8
164
+ }]
165
+ });
166
+ });
167
+ });
168
+ //#endregion
package/dist/scw/api.js CHANGED
@@ -1,3 +1,4 @@
1
+ //#region src/scw/api.ts
1
2
  /**
2
3
  * Abstract class to instantiate API from a {@link Client}.
3
4
  *
@@ -8,4 +9,5 @@ var API = class {
8
9
  this.client = client;
9
10
  }
10
11
  };
12
+ //#endregion
11
13
  export { API };
package/dist/scw/auth.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { addAsyncHeaderInterceptor, addHeaderInterceptor } from "../internal/interceptors/helpers.js";
2
2
  import { assertValidAuthenticationSecrets } from "./client-ini-profile.js";
3
3
  import { AUTH_HEADER_KEY, SESSION_HEADER_KEY } from "./constants.js";
4
+ //#region src/scw/auth.ts
4
5
  /**
5
6
  * Authentication utilities for Scaleway SDK.
6
7
  *
@@ -9,6 +10,15 @@ import { AUTH_HEADER_KEY, SESSION_HEADER_KEY } from "./constants.js";
9
10
  * tooltips and generated documentation.
10
11
  */
11
12
  /**
13
+ * Add an JWT Session Header to a request through an interceptor.
14
+ *
15
+ * @param request - The request to modify
16
+ * @param getJwt - The session value
17
+ * @returns The Request interceptor
18
+ *
19
+ */
20
+ var addSessionHeader = async ({ request, getAsyncToken }) => addAsyncHeaderInterceptor(SESSION_HEADER_KEY, getAsyncToken)({ request });
21
+ /**
12
22
  * Authenticates with a session token.
13
23
  *
14
24
  * @param getToken - The token accessor
@@ -18,7 +28,7 @@ import { AUTH_HEADER_KEY, SESSION_HEADER_KEY } from "./constants.js";
18
28
  *
19
29
  * @internal
20
30
  */
21
- const authenticateWithSessionToken = (getToken) => addAsyncHeaderInterceptor(SESSION_HEADER_KEY, getToken);
31
+ var authenticateWithSessionToken = (getToken) => addAsyncHeaderInterceptor(SESSION_HEADER_KEY, getToken);
22
32
  /**
23
33
  * Authenticates with a secrets.
24
34
  *
@@ -30,7 +40,7 @@ const authenticateWithSessionToken = (getToken) => addAsyncHeaderInterceptor(SES
30
40
  *
31
41
  * @internal
32
42
  */
33
- const authenticateWithSecrets = (secrets) => {
43
+ var authenticateWithSecrets = (secrets) => {
34
44
  assertValidAuthenticationSecrets(secrets);
35
45
  return addHeaderInterceptor(AUTH_HEADER_KEY, secrets.secretKey);
36
46
  };
@@ -42,7 +52,7 @@ const authenticateWithSecrets = (secrets) => {
42
52
  *
43
53
  * @internal
44
54
  */
45
- const obfuscateToken = (key) => `${key.substring(0, 5)}xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`;
55
+ var obfuscateToken = (key) => `${key.substring(0, 5)}xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`;
46
56
  /**
47
57
  * Obfuscates an UUID.
48
58
  *
@@ -51,7 +61,7 @@ const obfuscateToken = (key) => `${key.substring(0, 5)}xxxxxxxxxxxxxxxxxxxxxxxxx
51
61
  *
52
62
  * @internal
53
63
  */
54
- const obfuscateUUID = (key) => `${key.substring(0, 8)}-xxxx-xxxx-xxxx-xxxxxxxxxxxx`;
64
+ var obfuscateUUID = (key) => `${key.substring(0, 8)}-xxxx-xxxx-xxxx-xxxxxxxxxxxx`;
55
65
  /**
56
66
  * Obfuscates headers entry.
57
67
  *
@@ -60,9 +70,10 @@ const obfuscateUUID = (key) => `${key.substring(0, 8)}-xxxx-xxxx-xxxx-xxxxxxxxxx
60
70
  *
61
71
  * @internal
62
72
  */
63
- const obfuscateAuthHeadersEntry = ([name, value]) => {
73
+ var obfuscateAuthHeadersEntry = ([name, value]) => {
64
74
  if (name === "x-session-token") return [name, obfuscateToken(value)];
65
75
  if (name === "x-auth-token") return [name, obfuscateUUID(value)];
66
76
  return [name, value];
67
77
  };
68
- export { authenticateWithSecrets, authenticateWithSessionToken, obfuscateAuthHeadersEntry };
78
+ //#endregion
79
+ export { addSessionHeader, authenticateWithSecrets, authenticateWithSessionToken, obfuscateAuthHeadersEntry, obfuscateToken, obfuscateUUID };