@adobe/aio-commerce-lib-auth 0.1.0 → 0.3.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/CHANGELOG.md CHANGED
@@ -1,5 +1,35 @@
1
1
  # @adobe/aio-commerce-lib-auth
2
2
 
3
+ ## 0.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#22](https://github.com/adobe/aio-commerce-sdk/pull/22) [`9885eee`](https://github.com/adobe/aio-commerce-sdk/commit/9885eee5849ba7939b2067d3357e677beced3774) Thanks [@iivvaannxx](https://github.com/iivvaannxx)! - Changes include:
8
+ - Removed `try*` methods from public interface
9
+ - Added `assert` methods that throw if required configuration is not provided
10
+ - Cleaned up unused types to reduce bundle size
11
+
12
+ ### Patch Changes
13
+
14
+ - Updated dependencies [[`9885eee`](https://github.com/adobe/aio-commerce-sdk/commit/9885eee5849ba7939b2067d3357e677beced3774)]:
15
+ - @adobe/aio-commerce-lib-core@0.3.0
16
+
17
+ ## 0.2.0
18
+
19
+ ### Minor Changes
20
+
21
+ - [#18](https://github.com/adobe/aio-commerce-sdk/pull/18) [`aadbff1`](https://github.com/adobe/aio-commerce-sdk/commit/aadbff1acd08120f9d5cb8db4e3c849f552d8c79) Thanks [@jnatherley](https://github.com/jnatherley)! - Introduces the `aio-commerce-lib-core` package, which contains core utilities for the AIO Commerce SDK. It includes:
22
+ - A `Result` type based on Rust's `Result` type, to do better error handling.
23
+ - A set of validation utilities, including pretty printing of validation errors, and custom validation error types.
24
+ - Refactor aio-commerce-lib-auth to use aio-commerce-lib-core
25
+
26
+ Implements validation for the `aio-commerce-lib-auth` operations via `valibot`.
27
+
28
+ ### Patch Changes
29
+
30
+ - Updated dependencies [[`aadbff1`](https://github.com/adobe/aio-commerce-sdk/commit/aadbff1acd08120f9d5cb8db4e3c849f552d8c79)]:
31
+ - @adobe/aio-commerce-lib-core@0.2.0
32
+
3
33
  ## 0.1.0
4
34
 
5
35
  ### Minor Changes
package/README.md CHANGED
@@ -28,39 +28,111 @@ In your App Builder application, you can use the library to authenticate users o
28
28
 
29
29
  ### IMS Provider
30
30
 
31
- In the runtime action you can generate an access token using the IMS Provider:
32
-
33
31
  ```typescript
34
- import { getImsAuthProvider } from "@adobe/aio-commerce-lib-auth";
32
+ import {
33
+ assertImsAuthParams,
34
+ getImsAuthProvider,
35
+ } from "@adobe/aio-commerce-lib-auth";
35
36
 
36
- export const main = async function (params: Record<string, unknown>) {
37
- // Generate the needed headers for API requests
38
- const imsAuth = getImsAuthProvider(params);
39
- const headers = await imsAuth.getHeaders();
37
+ import { CommerceSdkValidationError } from "@adobe/aio-commerce-lib-core";
40
38
 
41
- return { statusCode: 200 };
39
+ export const main = async function (params: Record<string, unknown>) {
40
+ try {
41
+ // Validate parameters and get the IMS auth provider
42
+ assertImsAuthParams(params);
43
+ const imsAuthProvider = getImsAuthProvider(params);
44
+
45
+ const token = await imsAuthProvider.getAccessToken();
46
+ const headers = await imsAuthProvider.getHeaders();
47
+
48
+ // Use headers in your API calls
49
+ // business logic e.g requesting orders
50
+ return { statusCode: 200 };
51
+ } catch (error) {
52
+ if (error instanceof CommerceSdkValidationError) {
53
+ return {
54
+ statusCode: 400,
55
+ body: {
56
+ error: `Invalid IMS configuration: ${error.message}`,
57
+ },
58
+ };
59
+ }
60
+ throw error;
61
+ }
42
62
  };
43
63
  ```
44
64
 
45
65
  ### Integrations Provider
46
66
 
47
- In the runtime action you can generate an access token using the Integrations Provider:
48
-
49
67
  ```typescript
50
- import { getIntegrationsAuthProvider } from "@adobe/aio-commerce-lib-auth";
68
+ import {
69
+ assertIntegrationAuthParams,
70
+ getIntegrationAuthProvider,
71
+ } from "@adobe/aio-commerce-lib-auth";
72
+
73
+ import { CommerceSdkValidationError } from "@adobe/aio-commerce-lib-core";
51
74
 
52
75
  export const main = async function (params: Record<string, unknown>) {
53
- // Generate the needed headers for API requests
54
- const integrationsAuth = getIntegrationsAuthProvider(params);
55
- const headers = integrationsAuth.getHeaders(
56
- "GET",
57
- "http://localhost/rest/V1/orders",
58
- );
59
-
60
- return { statusCode: 200 };
76
+ try {
77
+ // Validate parameters and get the integration auth provider
78
+ assertIntegrationAuthParams(params);
79
+ const integrationsAuth = getIntegrationAuthProvider(params);
80
+
81
+ // Get OAuth headers for API requests
82
+ const headers = integrationsAuth.getHeaders(
83
+ "GET",
84
+ "http://localhost/rest/V1/orders",
85
+ );
86
+
87
+ // Use headers in your API calls
88
+ // business logic e.g requesting orders
89
+ return { statusCode: 200 };
90
+ } catch (error) {
91
+ if (error instanceof CommerceSdkValidationError) {
92
+ return {
93
+ statusCode: 400,
94
+ body: {
95
+ error: `Invalid Integration configuration: ${error.message}`,
96
+ },
97
+ };
98
+ }
99
+ throw error;
100
+ }
61
101
  };
62
102
  ```
63
103
 
104
+ ## Error Handling
105
+
106
+ The library uses validation to ensure all required parameters are provided and correctly formatted. When validation fails, a `CommerceSdkValidationError` is thrown with detailed information about what went wrong.
107
+
108
+ ```typescript
109
+ import { CommerceSdkValidationError } from "@adobe/aio-commerce-lib-core/error";
110
+
111
+ try {
112
+ assertImsAuthParams({
113
+ clientId: "valid-id",
114
+ // Missing required fields
115
+ });
116
+ } catch (error) {
117
+ if (error instanceof CommerceSdkValidationError) {
118
+ console.error(error.display());
119
+ // Output:
120
+ // Invalid ImsAuthProvider configuration
121
+ // ├── Schema validation error at clientSecrets → Expected at least one client secret for IMS auth
122
+ // ├── Schema validation error at technicalAccountId → Expected a non-empty string value for the IMS auth parameter technicalAccountId
123
+ // └── Schema validation error at technicalAccountEmail → Expected a valid email format for technicalAccountEmail
124
+ }
125
+ }
126
+ ```
127
+
128
+ ## Best Practices
129
+
130
+ 1. **Always validate parameters** - Use the `assert*` functions before creating providers
131
+ 2. **Handle errors gracefully** - Catch and properly handle validation and authentication errors
132
+ 3. **Store credentials securely** - Use environment variables or secure configuration management
133
+ 4. **Cache tokens when possible** - The IMS provider handles token lifecycle internally
134
+ 5. **Use TypeScript** - Leverage the full type safety provided by the library
135
+
64
136
  ## Contributing
65
137
 
66
- This package is part of the Adobe Commerce SDK monorepo. See the [Contributing Guide](../../.github/CONTRIBUTING.md) and [Development Guide](../../.github/DEVELOPMENT.md) for development setup and guidelines.
138
+ This package is part of the Adobe Commerce SDK monorepo. See the [Contributing Guide](https://github.com/adobe/aio-commerce-sdk/blob/main/.github/CONTRIBUTING.md) and [Development Guide](https://github.com/adobe/aio-commerce-sdk/blob/main/.github/DEVELOPMENT.md) for development setup and guidelines.
@@ -21,115 +21,272 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
21
21
  }) : target, mod));
22
22
 
23
23
  //#endregion
24
+ const __adobe_aio_commerce_lib_core_error = __toESM(require("@adobe/aio-commerce-lib-core/error"));
24
25
  const __adobe_aio_lib_ims = __toESM(require("@adobe/aio-lib-ims"));
26
+ const valibot = __toESM(require("valibot"));
25
27
  const node_crypto = __toESM(require("node:crypto"));
26
28
  const oauth_1_0a = __toESM(require("oauth-1.0a"));
27
29
 
28
- //#region source/lib/params.ts
30
+ //#region source/lib/ims-auth/schema.ts
29
31
  /**
30
- * Checks if the given value is non-empty.
31
- *
32
- * @param name of the parameter. Required because of `aio app dev` compatibility: inputs mapped to undefined env vars come as $<input_name> in dev mode, but as '' in prod mode.
33
- * @param value of the parameter.
32
+ * Creates a validation schema for a required IMS auth string parameter.
33
+ * @param name The name of the parameter for error messages.
34
+ * @returns A validation pipeline that ensures the parameter is a non-empty string.
34
35
  */
35
- function nonEmpty(name, value) {
36
- const v = value?.trim();
37
- return v !== void 0 && v !== `$${name}`;
38
- }
36
+ const imsAuthParameter = (name) => (0, valibot.pipe)((0, valibot.string)(`Expected a string value for the IMS auth parameter ${name}`), (0, valibot.nonEmpty)(`Expected a non-empty string value for the IMS auth parameter ${name}`));
39
37
  /**
40
- * Checks if all required parameters are non-empty.
41
- * @param params action input parameters.
42
- * @param required list of required parameter names.
38
+ * Creates a validation schema for an IMS auth string array parameter.
39
+ * @param name The name of the parameter for error messages.
40
+ * @returns A validation pipeline that ensures the parameter is an array of strings.
43
41
  */
44
- function allNonEmpty(params, required) {
45
- return required.every((name) => nonEmpty(name, params[name]));
46
- }
42
+ const stringArray = (name) => {
43
+ return (0, valibot.pipe)((0, valibot.array)((0, valibot.string)(), `Expected a stringified JSON array value for the IMS auth parameter ${name}`));
44
+ };
45
+ /** The environments accepted by the IMS auth service. */
46
+ const IMS_AUTH_ENV = {
47
+ PROD: "prod",
48
+ STAGE: "stage"
49
+ };
50
+ /** Validation schema for IMS auth environment values. */
51
+ const ImsAuthEnvSchema = (0, valibot.enum)(IMS_AUTH_ENV);
52
+ /** Defines the schema to validate the necessary parameters for the IMS auth service. */
53
+ const ImsAuthParamsSchema = (0, valibot.object)({
54
+ clientId: imsAuthParameter("clientId"),
55
+ clientSecrets: (0, valibot.pipe)(stringArray("clientSecrets"), (0, valibot.minLength)(1, "Expected at least one client secret for IMS auth")),
56
+ technicalAccountId: imsAuthParameter("technicalAccountId"),
57
+ technicalAccountEmail: (0, valibot.pipe)((0, valibot.string)("Expected a string value for the IMS auth parameter technicalAccountEmail"), (0, valibot.email)("Expected a valid email format for technicalAccountEmail")),
58
+ imsOrgId: imsAuthParameter("imsOrgId"),
59
+ environment: (0, valibot.pipe)((0, valibot.optional)(ImsAuthEnvSchema, IMS_AUTH_ENV.PROD)),
60
+ context: (0, valibot.pipe)((0, valibot.optional)((0, valibot.string)(), "aio-commerce-sdk-creds")),
61
+ scopes: (0, valibot.pipe)(stringArray("scopes"), (0, valibot.minLength)(1, "Expected at least one scope for IMS auth"))
62
+ });
47
63
 
48
64
  //#endregion
49
- //#region source/lib/ims-auth.ts
65
+ //#region source/lib/ims-auth/provider.ts
66
+ /**
67
+ * Converts IMS auth configuration properties to snake_case format.
68
+ * @param config The IMS auth configuration with camelCase properties.
69
+ * @returns The configuration with snake_case properties.
70
+ */
71
+ function toImsAuthConfig(config) {
72
+ return {
73
+ scopes: config.scopes,
74
+ env: config?.environment ?? "prod",
75
+ context: config.context,
76
+ client_id: config.clientId,
77
+ client_secrets: config.clientSecrets,
78
+ technical_account_id: config.technicalAccountId,
79
+ technical_account_email: config.technicalAccountEmail,
80
+ ims_org_id: config.imsOrgId
81
+ };
82
+ }
50
83
  /**
51
- * If the required IMS parameters are present, this function returns an {@link ImsAuthProvider}.
52
- * @param params includes IMS parameters
84
+ * Asserts the provided configuration for an Adobe IMS authentication provider. {@link ImsAuthParams}
85
+ * {@link ImsAuthProvider}
86
+ * @param config {Record<PropertyKey, unknown>} The configuration to validate.
87
+ * @throws {CommerceSdkValidationError} If the configuration is invalid.
88
+ * @example
89
+ * ```typescript
90
+ * const config = {
91
+ * clientId: "your-client-id",
92
+ * clientSecrets: ["your-client-secret"],
93
+ * technicalAccountId: "your-technical-account-id",
94
+ * technicalAccountEmail: "your-account@example.com",
95
+ * imsOrgId: "your-ims-org-id@AdobeOrg",
96
+ * scopes: ["AdobeID", "openid"],
97
+ * environment: "prod", // or "stage"
98
+ * context: "my-app-context"
99
+ * };
100
+ *
101
+ * // This will validate the config and throw if invalid
102
+ * assertImsAuthParams(config);
103
+ *```
104
+ * @example
105
+ * ```typescript
106
+ * // Example of a failing assert:
107
+ * try {
108
+ * assertImsAuthParams({
109
+ * clientId: "valid-client-id",
110
+ * // Missing required fields like clientSecrets, technicalAccountId, etc.
111
+ * });
112
+ * } catch (error) {
113
+ * console.error(error.message); // "Invalid ImsAuthProvider configuration"
114
+ * console.error(error.issues); // Array of validation issues
115
+ * }
116
+ * ```
53
117
  */
54
- async function getImsAuthProvider(params) {
55
- const config = resolveImsConfig(params);
56
- if (config) {
57
- const contextName = params.AIO_COMMERCE_IMS_CTX ?? "aio-commerce-sdk-creds";
58
- await __adobe_aio_lib_ims.context.set(contextName, config);
118
+ function assertImsAuthParams(config) {
119
+ const result = (0, valibot.safeParse)(ImsAuthParamsSchema, config);
120
+ if (!result.success) throw new __adobe_aio_commerce_lib_core_error.CommerceSdkValidationError("Invalid ImsAuthProvider configuration", { issues: result.issues });
121
+ }
122
+ /**
123
+ * Creates an {@link ImsAuthProvider} based on the provided configuration.
124
+ * @param config An {@link ImsAuthParams} parameter that contains the configuration for the IMS auth provider.
125
+ * @returns An {@link ImsAuthProvider} instance that can be used to get access token and auth headers.
126
+ * @example
127
+ * ```typescript
128
+ * const config = {
129
+ * clientId: "your-client-id",
130
+ * clientSecrets: ["your-client-secret"],
131
+ * technicalAccountId: "your-technical-account-id",
132
+ * technicalAccountEmail: "your-account@example.com",
133
+ * imsOrgId: "your-ims-org-id@AdobeOrg",
134
+ * scopes: ["AdobeID", "openid"],
135
+ * environment: "prod",
136
+ * context: "my-app-context"
137
+ * };
138
+ *
139
+ * const authProvider = getImsAuthProvider(config);
140
+ *
141
+ * // Get access token
142
+ * const token = await authProvider.getAccessToken();
143
+ * console.log(token); // "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9..."
144
+ *
145
+ * // Get headers for API requests
146
+ * const headers = await authProvider.getHeaders();
147
+ * console.log(headers);
148
+ * // {
149
+ * // Authorization: "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...",
150
+ * // "x-api-key": "your-client-id"
151
+ * // }
152
+ *
153
+ * // Use headers in API calls
154
+ * const response = await fetch('https://api.adobe.io/some-endpoint', {
155
+ * headers: await authProvider.getHeaders()
156
+ * });
157
+ * ```
158
+ */
159
+ function getImsAuthProvider(authParams) {
160
+ const getAccessToken = async () => {
161
+ const imsAuthConfig = toImsAuthConfig(authParams);
162
+ await __adobe_aio_lib_ims.context.set(authParams.context, imsAuthConfig);
163
+ return (0, __adobe_aio_lib_ims.getToken)(authParams.context, {});
164
+ };
165
+ const getHeaders = async () => {
166
+ const accessToken = await getAccessToken();
59
167
  return {
60
- getAccessToken: async () => (0, __adobe_aio_lib_ims.getToken)(contextName, {}),
61
- getHeaders: async () => {
62
- const accessToken = await (0, __adobe_aio_lib_ims.getToken)(contextName, {});
63
- return {
64
- Authorization: `Bearer ${accessToken}`,
65
- "x-api-key": config.client_id
66
- };
67
- }
168
+ Authorization: `Bearer ${accessToken}`,
169
+ "x-api-key": authParams.clientId
68
170
  };
69
- }
70
- }
71
- function resolveImsConfig(params) {
72
- if (allNonEmpty(params, [
73
- "AIO_COMMERCE_IMS_CLIENT_ID",
74
- "AIO_COMMERCE_IMS_CLIENT_SECRETS",
75
- "AIO_COMMERCE_IMS_TECHNICAL_ACCOUNT_ID",
76
- "AIO_COMMERCE_IMS_TECHNICAL_ACCOUNT_EMAIL",
77
- "AIO_COMMERCE_IMS_IMS_ORG_ID",
78
- "AIO_COMMERCE_IMS_SCOPES"
79
- ])) return {
80
- client_id: params.AIO_COMMERCE_IMS_CLIENT_ID,
81
- client_secrets: JSON.parse(params.AIO_COMMERCE_IMS_CLIENT_SECRETS ?? "[]"),
82
- technical_account_id: params.AIO_COMMERCE_IMS_TECHNICAL_ACCOUNT_ID,
83
- technical_account_email: params.AIO_COMMERCE_IMS_TECHNICAL_ACCOUNT_EMAIL,
84
- ims_org_id: params.AIO_COMMERCE_IMS_IMS_ORG_ID,
85
- scopes: JSON.parse(params.AIO_COMMERCE_IMS_SCOPES ?? "[]"),
86
- environment: params.AIO_COMMERCE_IMS_ENV ?? "prod"
171
+ };
172
+ return {
173
+ getAccessToken,
174
+ getHeaders
87
175
  };
88
176
  }
89
177
 
90
178
  //#endregion
91
- //#region source/lib/integration-auth.ts
179
+ //#region source/lib/integration-auth/schema.ts
92
180
  /**
93
- * If the required integration parameters are present, this function returns an {@link IntegrationAuthProvider}.
94
- * @param params includes integration parameters
181
+ * Creates a validation schema for a required Commerce Integration string parameter.
182
+ * @param name The name of the parameter for error messages.
183
+ * @returns A validation pipeline that ensures the parameter is a non-empty string.
95
184
  */
96
- function getIntegrationAuthProvider(params) {
97
- const config = resolveIntegrationConfig(params);
98
- if (config) {
99
- const oauth = new oauth_1_0a.default({
100
- consumer: {
101
- key: config.consumerKey,
102
- secret: config.consumerSecret
103
- },
104
- signature_method: "HMAC-SHA256",
105
- hash_function: (baseString, key) => node_crypto.default.createHmac("sha256", key).update(baseString).digest("base64")
106
- });
107
- const oauthToken = {
108
- key: config.accessToken,
109
- secret: config.accessTokenSecret
110
- };
111
- return { getHeaders(method, url) {
112
- return oauth.toHeader(oauth.authorize({
113
- url,
114
- method
115
- }, oauthToken));
116
- } };
117
- }
185
+ const integrationAuthParameter = (name) => (0, valibot.pipe)((0, valibot.string)(`Expected a string value for the Commerce Integration parameter ${name}`), (0, valibot.nonEmpty)(`Expected a non-empty string value for the Commerce Integration parameter ${name}`));
186
+ /** Validation schema for the Adobe Commerce endpoint base URL. */
187
+ const BaseUrlSchema = (0, valibot.pipe)((0, valibot.string)("Expected a string for the Adobe Commerce endpoint"), (0, valibot.nonEmpty)("Expected a non-empty string for the Adobe Commerce endpoint"), (0, valibot.url)("Expected a valid url for the Adobe Commerce endpoint"));
188
+ /** Validation schema that accepts either a URL string or URL instance and normalizes to string. */
189
+ const UrlSchema = (0, valibot.pipe)((0, valibot.union)([BaseUrlSchema, (0, valibot.instance)(URL)]), (0, valibot.transform)((url) => {
190
+ if (url instanceof URL) return url.toString();
191
+ return url;
192
+ }));
193
+ /**
194
+ * The schema for the Commerce Integration parameters.
195
+ * This is used to validate the parameters passed to the Commerce Integration provider.
196
+ */
197
+ const IntegrationAuthParamsSchema = (0, valibot.nonOptional)((0, valibot.object)({
198
+ consumerKey: integrationAuthParameter("consumerKey"),
199
+ consumerSecret: integrationAuthParameter("consumerSecret"),
200
+ accessToken: integrationAuthParameter("accessToken"),
201
+ accessTokenSecret: integrationAuthParameter("accessTokenSecret")
202
+ }));
203
+
204
+ //#endregion
205
+ //#region source/lib/integration-auth/provider.ts
206
+ /**
207
+ * Asserts the provided configuration for an Adobe Commerce integration authentication provider. {@link IntegrationAuthParams}
208
+ * {@link IntegrationAuthProvider}
209
+ * @param config {Record<PropertyKey, unknown>} The configuration to validate.
210
+ * @throws {CommerceSdkValidationError} If the configuration is invalid.
211
+ * @example
212
+ * ```typescript
213
+ * const config = {
214
+ * consumerKey: "your-consumer-key",
215
+ * consumerSecret: "your-consumer-secret",
216
+ * accessToken: "your-access-token",
217
+ * accessTokenSecret: "your-access-token-secret"
218
+ * };
219
+ *
220
+ * // This will validate the config and throw if invalid
221
+ * assertIntegrationAuthParams(config);
222
+ * ```
223
+ * @example
224
+ * ```typescript
225
+ * // Example of a failing assert:
226
+ * try {
227
+ * assertIntegrationAuthParams({
228
+ * consumerKey: "valid-consumer-key",
229
+ * // Missing required fields like consumerSecret, accessToken, accessTokenSecret
230
+ * });
231
+ * } catch (error) {
232
+ * console.error(error.message); // "Invalid IntegrationAuthProvider configuration"
233
+ * console.error(error.issues); // Array of validation issues
234
+ * }
235
+ * ```
236
+ */
237
+ function assertIntegrationAuthParams(config) {
238
+ const result = (0, valibot.safeParse)(IntegrationAuthParamsSchema, config);
239
+ if (!result.success) throw new __adobe_aio_commerce_lib_core_error.CommerceSdkValidationError("Invalid IntegrationAuthProvider configuration", { issues: result.issues });
118
240
  }
119
- function resolveIntegrationConfig(params) {
120
- if (allNonEmpty(params, [
121
- "AIO_COMMERCE_INTEGRATIONS_CONSUMER_KEY",
122
- "AIO_COMMERCE_INTEGRATIONS_CONSUMER_SECRET",
123
- "AIO_COMMERCE_INTEGRATIONS_ACCESS_TOKEN",
124
- "AIO_COMMERCE_INTEGRATIONS_ACCESS_TOKEN_SECRET"
125
- ])) return {
126
- consumerKey: params.AIO_COMMERCE_INTEGRATIONS_CONSUMER_KEY,
127
- consumerSecret: params.AIO_COMMERCE_INTEGRATIONS_CONSUMER_SECRET,
128
- accessToken: params.AIO_COMMERCE_INTEGRATIONS_ACCESS_TOKEN,
129
- accessTokenSecret: params.AIO_COMMERCE_INTEGRATIONS_ACCESS_TOKEN_SECRET
241
+ /**
242
+ * Creates an {@link IntegrationAuthProvider} based on the provided configuration.
243
+ * @param config {IntegrationAuthParams} The configuration for the integration.
244
+ * @returns An {@link IntegrationAuthProvider} instance that can be used to get auth headers.
245
+ * @example
246
+ * ```typescript
247
+ * const config = {
248
+ * consumerKey: "your-consumer-key",
249
+ * consumerSecret: "your-consumer-secret",
250
+ * accessToken: "your-access-token",
251
+ * accessTokenSecret: "your-access-token-secret"
252
+ * };
253
+ *
254
+ * const authProvider = getIntegrationAuthProvider(config);
255
+ *
256
+ * // Get OAuth headers for a REST API call
257
+ * const headers = authProvider.getHeaders("GET", "https://your-store.com/rest/V1/products");
258
+ * console.log(headers); // { Authorization: "OAuth oauth_consumer_key=..., oauth_signature=..." }
259
+ *
260
+ * // Can also be used with URL objects
261
+ * const url = new URL("https://your-store.com/rest/V1/customers");
262
+ * const postHeaders = authProvider.getHeaders("POST", url);
263
+ * ```
264
+ */
265
+ function getIntegrationAuthProvider(authParams) {
266
+ const oauth = new oauth_1_0a.default({
267
+ consumer: {
268
+ key: authParams.consumerKey,
269
+ secret: authParams.consumerSecret
270
+ },
271
+ signature_method: "HMAC-SHA256",
272
+ hash_function: (baseString, key) => node_crypto.default.createHmac("sha256", key).update(baseString).digest("base64")
273
+ });
274
+ const oauthToken = {
275
+ key: authParams.accessToken,
276
+ secret: authParams.accessTokenSecret
130
277
  };
278
+ return { getHeaders: (method, url) => {
279
+ const urlString = url instanceof URL ? url.toString() : url;
280
+ return oauth.toHeader(oauth.authorize({
281
+ url: urlString,
282
+ method
283
+ }, oauthToken));
284
+ } };
131
285
  }
132
286
 
133
287
  //#endregion
288
+ exports.IMS_AUTH_ENV = IMS_AUTH_ENV;
289
+ exports.assertImsAuthParams = assertImsAuthParams;
290
+ exports.assertIntegrationAuthParams = assertIntegrationAuthParams;
134
291
  exports.getImsAuthProvider = getImsAuthProvider;
135
292
  exports.getIntegrationAuthProvider = getIntegrationAuthProvider;
@@ -1,39 +1,65 @@
1
- import OAuth1a from "oauth-1.0a";
1
+ import * as valibot24 from "valibot";
2
+ import { InferOutput } from "valibot";
2
3
 
3
- //#region source/lib/ims-auth.d.ts
4
- declare const IMS_AUTH_HEADERS: readonly ["Authorization", "x-api-key"];
5
- declare const IMS_AUTH_PARAMS: readonly ["AIO_COMMERCE_IMS_CLIENT_ID", "AIO_COMMERCE_IMS_CLIENT_SECRETS", "AIO_COMMERCE_IMS_TECHNICAL_ACCOUNT_ID", "AIO_COMMERCE_IMS_TECHNICAL_ACCOUNT_EMAIL", "AIO_COMMERCE_IMS_IMS_ORG_ID", "AIO_COMMERCE_IMS_SCOPES", "AIO_COMMERCE_IMS_ENV", "AIO_COMMERCE_IMS_CTX"];
6
- type ImsAuthParam = (typeof IMS_AUTH_PARAMS)[number];
7
- type ImsAuthParams = Partial<Record<ImsAuthParam, string>>;
8
- type ImsAuthHeader = (typeof IMS_AUTH_HEADERS)[number];
4
+ //#region source/lib/ims-auth/schema.d.ts
5
+ declare const IMS_AUTH_ENV: {
6
+ readonly PROD: "prod";
7
+ readonly STAGE: "stage";
8
+ };
9
+ declare const ImsAuthEnvSchema: valibot24.EnumSchema<{
10
+ readonly PROD: "prod";
11
+ readonly STAGE: "stage";
12
+ }, undefined>;
13
+ declare const ImsAuthParamsSchema: valibot24.ObjectSchema<{
14
+ readonly clientId: valibot24.SchemaWithPipe<readonly [valibot24.StringSchema<`Expected a string value for the IMS auth parameter ${string}`>, valibot24.NonEmptyAction<string, `Expected a non-empty string value for the IMS auth parameter ${string}`>]>;
15
+ readonly clientSecrets: valibot24.SchemaWithPipe<readonly [valibot24.SchemaWithPipe<readonly [valibot24.ArraySchema<valibot24.StringSchema<undefined>, `Expected a stringified JSON array value for the IMS auth parameter ${string}`>]>, valibot24.MinLengthAction<string[], 1, "Expected at least one client secret for IMS auth">]>;
16
+ readonly technicalAccountId: valibot24.SchemaWithPipe<readonly [valibot24.StringSchema<`Expected a string value for the IMS auth parameter ${string}`>, valibot24.NonEmptyAction<string, `Expected a non-empty string value for the IMS auth parameter ${string}`>]>;
17
+ readonly technicalAccountEmail: valibot24.SchemaWithPipe<readonly [valibot24.StringSchema<"Expected a string value for the IMS auth parameter technicalAccountEmail">, valibot24.EmailAction<string, "Expected a valid email format for technicalAccountEmail">]>;
18
+ readonly imsOrgId: valibot24.SchemaWithPipe<readonly [valibot24.StringSchema<`Expected a string value for the IMS auth parameter ${string}`>, valibot24.NonEmptyAction<string, `Expected a non-empty string value for the IMS auth parameter ${string}`>]>;
19
+ readonly environment: valibot24.SchemaWithPipe<readonly [valibot24.OptionalSchema<valibot24.EnumSchema<{
20
+ readonly PROD: "prod";
21
+ readonly STAGE: "stage";
22
+ }, undefined>, "prod">]>;
23
+ readonly context: valibot24.SchemaWithPipe<readonly [valibot24.OptionalSchema<valibot24.StringSchema<undefined>, "aio-commerce-sdk-creds">]>;
24
+ readonly scopes: valibot24.SchemaWithPipe<readonly [valibot24.SchemaWithPipe<readonly [valibot24.ArraySchema<valibot24.StringSchema<undefined>, `Expected a stringified JSON array value for the IMS auth parameter ${string}`>]>, valibot24.MinLengthAction<string[], 1, "Expected at least one scope for IMS auth">]>;
25
+ }, undefined>;
26
+ type ImsAuthParams = InferOutput<typeof ImsAuthParamsSchema>;
27
+ type ImsAuthEnv = InferOutput<typeof ImsAuthEnvSchema>;
28
+ //#endregion
29
+ //#region source/lib/ims-auth/provider.d.ts
30
+ type ImsAuthHeader = "Authorization" | "x-api-key";
9
31
  type ImsAuthHeaders = Record<ImsAuthHeader, string>;
10
- type ImsAccessToken = string;
11
32
  interface ImsAuthProvider {
33
+ getAccessToken: () => Promise<string>;
12
34
  getHeaders: () => Promise<ImsAuthHeaders>;
13
- getAccessToken: () => Promise<ImsAccessToken>;
14
35
  }
15
- declare function getImsAuthProvider(params: ImsAuthParams): Promise<{
36
+ declare function assertImsAuthParams(config: Record<PropertyKey, unknown>): asserts config is ImsAuthParams;
37
+ declare function getImsAuthProvider(authParams: ImsAuthParams): {
16
38
  getAccessToken: () => Promise<string>;
17
39
  getHeaders: () => Promise<{
18
40
  Authorization: string;
19
41
  "x-api-key": string;
20
42
  }>;
21
- } | undefined>;
43
+ };
44
+ //#endregion
45
+ //#region source/lib/integration-auth/schema.d.ts
46
+ type HttpMethodInput = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
47
+ declare const IntegrationAuthParamsSchema: valibot24.NonOptionalSchema<valibot24.ObjectSchema<{
48
+ readonly consumerKey: valibot24.SchemaWithPipe<readonly [valibot24.StringSchema<`Expected a string value for the Commerce Integration parameter ${string}`>, valibot24.NonEmptyAction<string, `Expected a non-empty string value for the Commerce Integration parameter ${string}`>]>;
49
+ readonly consumerSecret: valibot24.SchemaWithPipe<readonly [valibot24.StringSchema<`Expected a string value for the Commerce Integration parameter ${string}`>, valibot24.NonEmptyAction<string, `Expected a non-empty string value for the Commerce Integration parameter ${string}`>]>;
50
+ readonly accessToken: valibot24.SchemaWithPipe<readonly [valibot24.StringSchema<`Expected a string value for the Commerce Integration parameter ${string}`>, valibot24.NonEmptyAction<string, `Expected a non-empty string value for the Commerce Integration parameter ${string}`>]>;
51
+ readonly accessTokenSecret: valibot24.SchemaWithPipe<readonly [valibot24.StringSchema<`Expected a string value for the Commerce Integration parameter ${string}`>, valibot24.NonEmptyAction<string, `Expected a non-empty string value for the Commerce Integration parameter ${string}`>]>;
52
+ }, undefined>, undefined>;
53
+ type IntegrationAuthParams = InferOutput<typeof IntegrationAuthParamsSchema>;
22
54
  //#endregion
23
- //#region source/lib/integration-auth.d.ts
24
- declare const HTTP_METHODS: readonly ["GET", "POST", "PUT", "PATCH", "DELETE"];
25
- declare const INTEGRATION_AUTH_HEADERS: readonly ["Authorization"];
26
- declare const INTEGRATION_AUTH_PARAMS: readonly ["AIO_COMMERCE_INTEGRATIONS_CONSUMER_KEY", "AIO_COMMERCE_INTEGRATIONS_CONSUMER_SECRET", "AIO_COMMERCE_INTEGRATIONS_ACCESS_TOKEN", "AIO_COMMERCE_INTEGRATIONS_ACCESS_TOKEN_SECRET"];
27
- type IntegrationAuthParam = (typeof INTEGRATION_AUTH_PARAMS)[number];
28
- type IntegrationAuthParams = Partial<Record<IntegrationAuthParam, string>>;
29
- type IntegrationAuthHeader = (typeof INTEGRATION_AUTH_HEADERS)[number];
55
+ //#region source/lib/integration-auth/provider.d.ts
56
+ type IntegrationAuthHeader = "Authorization";
30
57
  type IntegrationAuthHeaders = Record<IntegrationAuthHeader, string>;
31
- type HttpMethod = (typeof HTTP_METHODS)[number];
58
+ type AdobeCommerceUrl = string | URL;
32
59
  interface IntegrationAuthProvider {
33
- getHeaders: (method: HttpMethod, url: string) => IntegrationAuthHeaders;
60
+ getHeaders: (method: HttpMethodInput, url: AdobeCommerceUrl) => IntegrationAuthHeaders;
34
61
  }
35
- declare function getIntegrationAuthProvider(params: IntegrationAuthParams): {
36
- getHeaders(method: HttpMethod, url: string): OAuth1a.Header;
37
- } | undefined;
62
+ declare function assertIntegrationAuthParams(config: Record<PropertyKey, unknown>): asserts config is IntegrationAuthParams;
63
+ declare function getIntegrationAuthProvider(authParams: IntegrationAuthParams): IntegrationAuthProvider;
38
64
  //#endregion
39
- export { ImsAuthHeader, ImsAuthHeaders, ImsAuthParam, ImsAuthParams, ImsAuthProvider, IntegrationAuthHeader, IntegrationAuthHeaders, IntegrationAuthParam, IntegrationAuthParams, IntegrationAuthProvider, getImsAuthProvider, getIntegrationAuthProvider };
65
+ export { IMS_AUTH_ENV, ImsAuthEnv, ImsAuthParams, ImsAuthProvider, IntegrationAuthParams, IntegrationAuthProvider, assertImsAuthParams, assertIntegrationAuthParams, getImsAuthProvider, getIntegrationAuthProvider };