@adobe/aio-commerce-lib-auth 0.2.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/dist/es/index.js CHANGED
@@ -1,38 +1,55 @@
1
- import { err, map, ok } from "@adobe/aio-commerce-lib-core/result";
1
+ import { CommerceSdkValidationError } from "@adobe/aio-commerce-lib-core/error";
2
2
  import { context, getToken } from "@adobe/aio-lib-ims";
3
- import { array, enum as enum$1, instance, message, nonEmpty, nonOptional, object, optional, parseJson, picklist, pipe, safeParse, string, transform, union, url } from "valibot";
3
+ import { array, email, enum as enum$1, instance, minLength, nonEmpty, nonOptional, object, optional, pipe, safeParse, string, transform, union, url } from "valibot";
4
4
  import crypto from "node:crypto";
5
5
  import OAuth1a from "oauth-1.0a";
6
6
 
7
7
  //#region source/lib/ims-auth/schema.ts
8
+ /**
9
+ * Creates a validation schema for a required IMS auth string parameter.
10
+ * @param name The name of the parameter for error messages.
11
+ * @returns A validation pipeline that ensures the parameter is a non-empty string.
12
+ */
8
13
  const imsAuthParameter = (name) => pipe(string(`Expected a string value for the IMS auth parameter ${name}`), nonEmpty(`Expected a non-empty string value for the IMS auth parameter ${name}`));
9
- const jsonStringArray = (name) => {
10
- const jsonStringArraySchema = message(pipe(string(`Expected a string value for the IMS auth parameter ${name}`), nonEmpty(`Expected a non-empty string value for the IMS auth parameter ${name}`), parseJson()), `An error occurred while parsing the JSON string array parameter ${name}`);
11
- return pipe(jsonStringArraySchema, array(string(), `Expected a stringified JSON array value for the IMS auth parameter ${name}`));
14
+ /**
15
+ * Creates a validation schema for an IMS auth string array parameter.
16
+ * @param name The name of the parameter for error messages.
17
+ * @returns A validation pipeline that ensures the parameter is an array of strings.
18
+ */
19
+ const stringArray = (name) => {
20
+ return pipe(array(string(), `Expected a stringified JSON array value for the IMS auth parameter ${name}`));
12
21
  };
13
22
  /** The environments accepted by the IMS auth service. */
14
23
  const IMS_AUTH_ENV = {
15
24
  PROD: "prod",
16
25
  STAGE: "stage"
17
26
  };
27
+ /** Validation schema for IMS auth environment values. */
18
28
  const ImsAuthEnvSchema = enum$1(IMS_AUTH_ENV);
19
29
  /** Defines the schema to validate the necessary parameters for the IMS auth service. */
20
30
  const ImsAuthParamsSchema = object({
21
- AIO_COMMERCE_IMS_CLIENT_ID: imsAuthParameter("AIO_COMMERCE_IMS_CLIENT_ID"),
22
- AIO_COMMERCE_IMS_CLIENT_SECRETS: jsonStringArray("AIO_COMMERCE_IMS_CLIENT_SECRETS"),
23
- AIO_COMMERCE_IMS_TECHNICAL_ACCOUNT_ID: imsAuthParameter("AIO_COMMERCE_IMS_TECHNICAL_ACCOUNT_ID"),
24
- AIO_COMMERCE_IMS_TECHNICAL_ACCOUNT_EMAIL: imsAuthParameter("AIO_COMMERCE_IMS_TECHNICAL_ACCOUNT_EMAIL"),
25
- AIO_COMMERCE_IMS_IMS_ORG_ID: imsAuthParameter("AIO_COMMERCE_IMS_IMS_ORG_ID"),
26
- AIO_COMMERCE_IMS_ENV: pipe(optional(ImsAuthEnvSchema, IMS_AUTH_ENV.PROD)),
27
- AIO_COMMERCE_IMS_CTX: pipe(optional(string(), "aio-commerce-sdk-creds")),
28
- AIO_COMMERCE_IMS_SCOPES: jsonStringArray("AIO_COMMERCE_IMS_SCOPES")
31
+ clientId: imsAuthParameter("clientId"),
32
+ clientSecrets: pipe(stringArray("clientSecrets"), minLength(1, "Expected at least one client secret for IMS auth")),
33
+ technicalAccountId: imsAuthParameter("technicalAccountId"),
34
+ technicalAccountEmail: pipe(string("Expected a string value for the IMS auth parameter technicalAccountEmail"), email("Expected a valid email format for technicalAccountEmail")),
35
+ imsOrgId: imsAuthParameter("imsOrgId"),
36
+ environment: pipe(optional(ImsAuthEnvSchema, IMS_AUTH_ENV.PROD)),
37
+ context: pipe(optional(string(), "aio-commerce-sdk-creds")),
38
+ scopes: pipe(stringArray("scopes"), minLength(1, "Expected at least one scope for IMS auth"))
29
39
  });
30
40
 
31
41
  //#endregion
32
42
  //#region source/lib/ims-auth/provider.ts
33
- function snakeCaseImsAuthConfig(config) {
43
+ /**
44
+ * Converts IMS auth configuration properties to snake_case format.
45
+ * @param config The IMS auth configuration with camelCase properties.
46
+ * @returns The configuration with snake_case properties.
47
+ */
48
+ function toImsAuthConfig(config) {
34
49
  return {
35
- ...config,
50
+ scopes: config.scopes,
51
+ env: config?.environment ?? "prod",
52
+ context: config.context,
36
53
  client_id: config.clientId,
37
54
  client_secrets: config.clientSecrets,
38
55
  technical_account_id: config.technicalAccountId,
@@ -40,90 +57,112 @@ function snakeCaseImsAuthConfig(config) {
40
57
  ims_org_id: config.imsOrgId
41
58
  };
42
59
  }
43
- function makeImsAuthValidationError(message$1, issues) {
44
- return {
45
- _tag: "ImsAuthValidationError",
46
- message: message$1,
47
- issues
48
- };
49
- }
50
- function makeImsAuthError(message$1, error) {
51
- return {
52
- _tag: "ImsAuthError",
53
- message: message$1,
54
- error
55
- };
56
- }
57
- function fromParams$1(params) {
58
- return {
59
- clientId: params.AIO_COMMERCE_IMS_CLIENT_ID,
60
- clientSecrets: params.AIO_COMMERCE_IMS_CLIENT_SECRETS,
61
- technicalAccountId: params.AIO_COMMERCE_IMS_TECHNICAL_ACCOUNT_ID,
62
- technicalAccountEmail: params.AIO_COMMERCE_IMS_TECHNICAL_ACCOUNT_EMAIL,
63
- imsOrgId: params.AIO_COMMERCE_IMS_IMS_ORG_ID,
64
- scopes: params.AIO_COMMERCE_IMS_SCOPES,
65
- environment: params.AIO_COMMERCE_IMS_ENV,
66
- context: params.AIO_COMMERCE_IMS_CTX
67
- };
68
- }
69
- async function tryGetAccessToken(contextName) {
70
- try {
71
- const accessToken = await getToken(contextName, {});
72
- return ok(accessToken);
73
- } catch (error) {
74
- return err(makeImsAuthError("Failed to retrieve IMS access token", error));
75
- }
60
+ /**
61
+ * Asserts the provided configuration for an Adobe IMS authentication provider. {@link ImsAuthParams}
62
+ * {@link ImsAuthProvider}
63
+ * @param config {Record<PropertyKey, unknown>} The configuration to validate.
64
+ * @throws {CommerceSdkValidationError} If the configuration is invalid.
65
+ * @example
66
+ * ```typescript
67
+ * const config = {
68
+ * clientId: "your-client-id",
69
+ * clientSecrets: ["your-client-secret"],
70
+ * technicalAccountId: "your-technical-account-id",
71
+ * technicalAccountEmail: "your-account@example.com",
72
+ * imsOrgId: "your-ims-org-id@AdobeOrg",
73
+ * scopes: ["AdobeID", "openid"],
74
+ * environment: "prod", // or "stage"
75
+ * context: "my-app-context"
76
+ * };
77
+ *
78
+ * // This will validate the config and throw if invalid
79
+ * assertImsAuthParams(config);
80
+ *```
81
+ * @example
82
+ * ```typescript
83
+ * // Example of a failing assert:
84
+ * try {
85
+ * assertImsAuthParams({
86
+ * clientId: "valid-client-id",
87
+ * // Missing required fields like clientSecrets, technicalAccountId, etc.
88
+ * });
89
+ * } catch (error) {
90
+ * console.error(error.message); // "Invalid ImsAuthProvider configuration"
91
+ * console.error(error.issues); // Array of validation issues
92
+ * }
93
+ * ```
94
+ */
95
+ function assertImsAuthParams(config) {
96
+ const result = safeParse(ImsAuthParamsSchema, config);
97
+ if (!result.success) throw new CommerceSdkValidationError("Invalid ImsAuthProvider configuration", { issues: result.issues });
76
98
  }
77
99
  /**
78
100
  * Creates an {@link ImsAuthProvider} based on the provided configuration.
79
- * @param config The configuration for the IMS Auth Provider.
101
+ * @param config An {@link ImsAuthParams} parameter that contains the configuration for the IMS auth provider.
80
102
  * @returns An {@link ImsAuthProvider} instance that can be used to get access token and auth headers.
103
+ * @example
104
+ * ```typescript
105
+ * const config = {
106
+ * clientId: "your-client-id",
107
+ * clientSecrets: ["your-client-secret"],
108
+ * technicalAccountId: "your-technical-account-id",
109
+ * technicalAccountEmail: "your-account@example.com",
110
+ * imsOrgId: "your-ims-org-id@AdobeOrg",
111
+ * scopes: ["AdobeID", "openid"],
112
+ * environment: "prod",
113
+ * context: "my-app-context"
114
+ * };
115
+ *
116
+ * const authProvider = getImsAuthProvider(config);
117
+ *
118
+ * // Get access token
119
+ * const token = await authProvider.getAccessToken();
120
+ * console.log(token); // "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9..."
121
+ *
122
+ * // Get headers for API requests
123
+ * const headers = await authProvider.getHeaders();
124
+ * console.log(headers);
125
+ * // {
126
+ * // Authorization: "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...",
127
+ * // "x-api-key": "your-client-id"
128
+ * // }
129
+ *
130
+ * // Use headers in API calls
131
+ * const response = await fetch('https://api.adobe.io/some-endpoint', {
132
+ * headers: await authProvider.getHeaders()
133
+ * });
134
+ * ```
81
135
  */
82
- function getImsAuthProvider(config) {
136
+ function getImsAuthProvider(authParams) {
83
137
  const getAccessToken = async () => {
84
- const snakeCasedConfig = snakeCaseImsAuthConfig(config);
85
- await context.set(config.context, snakeCasedConfig);
86
- return tryGetAccessToken(config.context);
138
+ const imsAuthConfig = toImsAuthConfig(authParams);
139
+ await context.set(authParams.context, imsAuthConfig);
140
+ return getToken(authParams.context, {});
87
141
  };
88
142
  const getHeaders = async () => {
89
- const result = await getAccessToken();
90
- return map(result, (accessToken) => ({
143
+ const accessToken = await getAccessToken();
144
+ return {
91
145
  Authorization: `Bearer ${accessToken}`,
92
- "x-api-key": config.clientId
93
- }));
146
+ "x-api-key": authParams.clientId
147
+ };
94
148
  };
95
149
  return {
96
150
  getAccessToken,
97
151
  getHeaders
98
152
  };
99
153
  }
100
- /**
101
- * Tries to create an {@link ImsAuthProvider} based on the provided parameters.
102
- * @param params The parameters required to create the IMS Auth Provider.
103
- * @returns An {@link ImsAuthProvider} instance that can be used to get access token and auth headers.
104
- */
105
- function tryGetImsAuthProvider(params) {
106
- const validation = safeParse(ImsAuthParamsSchema, params);
107
- if (!validation.success) return err(makeImsAuthValidationError("Failed to validate the provided IMS parameters", validation.issues));
108
- return ok(getImsAuthProvider(fromParams$1(validation.output)));
109
- }
110
154
 
111
155
  //#endregion
112
156
  //#region source/lib/integration-auth/schema.ts
113
157
  /**
114
- * The HTTP methods supported by Commerce.
115
- * This is used to determine which headers to include in the signing of the authorization header.
158
+ * Creates a validation schema for a required Commerce Integration string parameter.
159
+ * @param name The name of the parameter for error messages.
160
+ * @returns A validation pipeline that ensures the parameter is a non-empty string.
116
161
  */
117
- const AllowedHttpMethod = [
118
- "GET",
119
- "POST",
120
- "PUT",
121
- "PATCH",
122
- "DELETE"
123
- ];
124
- const HttpMethodSchema = picklist(AllowedHttpMethod);
125
162
  const integrationAuthParameter = (name) => pipe(string(`Expected a string value for the Commerce Integration parameter ${name}`), nonEmpty(`Expected a non-empty string value for the Commerce Integration parameter ${name}`));
163
+ /** Validation schema for the Adobe Commerce endpoint base URL. */
126
164
  const BaseUrlSchema = pipe(string("Expected a string for the Adobe Commerce endpoint"), nonEmpty("Expected a non-empty string for the Adobe Commerce endpoint"), url("Expected a valid url for the Adobe Commerce endpoint"));
165
+ /** Validation schema that accepts either a URL string or URL instance and normalizes to string. */
127
166
  const UrlSchema = pipe(union([BaseUrlSchema, instance(URL)]), transform((url$1) => {
128
167
  if (url$1 instanceof URL) return url$1.toString();
129
168
  return url$1;
@@ -133,69 +172,94 @@ const UrlSchema = pipe(union([BaseUrlSchema, instance(URL)]), transform((url$1)
133
172
  * This is used to validate the parameters passed to the Commerce Integration provider.
134
173
  */
135
174
  const IntegrationAuthParamsSchema = nonOptional(object({
136
- AIO_COMMERCE_INTEGRATIONS_CONSUMER_KEY: integrationAuthParameter("AIO_COMMERCE_INTEGRATIONS_CONSUMER_KEY"),
137
- AIO_COMMERCE_INTEGRATIONS_CONSUMER_SECRET: integrationAuthParameter("AIO_COMMERCE_INTEGRATIONS_CONSUMER_SECRET"),
138
- AIO_COMMERCE_INTEGRATIONS_ACCESS_TOKEN: integrationAuthParameter("AIO_COMMERCE_INTEGRATIONS_ACCESS_TOKEN"),
139
- AIO_COMMERCE_INTEGRATIONS_ACCESS_TOKEN_SECRET: integrationAuthParameter("AIO_COMMERCE_INTEGRATIONS_ACCESS_TOKEN_SECRET")
175
+ consumerKey: integrationAuthParameter("consumerKey"),
176
+ consumerSecret: integrationAuthParameter("consumerSecret"),
177
+ accessToken: integrationAuthParameter("accessToken"),
178
+ accessTokenSecret: integrationAuthParameter("accessTokenSecret")
140
179
  }));
141
180
 
142
181
  //#endregion
143
182
  //#region source/lib/integration-auth/provider.ts
144
- function makeIntegrationAuthValidationError(message$1, issues) {
145
- return {
146
- _tag: "IntegrationAuthValidationError",
147
- message: message$1,
148
- issues
149
- };
150
- }
151
- function fromParams(params) {
152
- return {
153
- consumerKey: params.AIO_COMMERCE_INTEGRATIONS_CONSUMER_KEY,
154
- consumerSecret: params.AIO_COMMERCE_INTEGRATIONS_CONSUMER_SECRET,
155
- accessToken: params.AIO_COMMERCE_INTEGRATIONS_ACCESS_TOKEN,
156
- accessTokenSecret: params.AIO_COMMERCE_INTEGRATIONS_ACCESS_TOKEN_SECRET
157
- };
183
+ /**
184
+ * Asserts the provided configuration for an Adobe Commerce integration authentication provider. {@link IntegrationAuthParams}
185
+ * {@link IntegrationAuthProvider}
186
+ * @param config {Record<PropertyKey, unknown>} The configuration to validate.
187
+ * @throws {CommerceSdkValidationError} If the configuration is invalid.
188
+ * @example
189
+ * ```typescript
190
+ * const config = {
191
+ * consumerKey: "your-consumer-key",
192
+ * consumerSecret: "your-consumer-secret",
193
+ * accessToken: "your-access-token",
194
+ * accessTokenSecret: "your-access-token-secret"
195
+ * };
196
+ *
197
+ * // This will validate the config and throw if invalid
198
+ * assertIntegrationAuthParams(config);
199
+ * ```
200
+ * @example
201
+ * ```typescript
202
+ * // Example of a failing assert:
203
+ * try {
204
+ * assertIntegrationAuthParams({
205
+ * consumerKey: "valid-consumer-key",
206
+ * // Missing required fields like consumerSecret, accessToken, accessTokenSecret
207
+ * });
208
+ * } catch (error) {
209
+ * console.error(error.message); // "Invalid IntegrationAuthProvider configuration"
210
+ * console.error(error.issues); // Array of validation issues
211
+ * }
212
+ * ```
213
+ */
214
+ function assertIntegrationAuthParams(config) {
215
+ const result = safeParse(IntegrationAuthParamsSchema, config);
216
+ if (!result.success) throw new CommerceSdkValidationError("Invalid IntegrationAuthProvider configuration", { issues: result.issues });
158
217
  }
159
218
  /**
160
219
  * Creates an {@link IntegrationAuthProvider} based on the provided configuration.
161
- * @param config The configuration for the integration.
220
+ * @param config {IntegrationAuthParams} The configuration for the integration.
162
221
  * @returns An {@link IntegrationAuthProvider} instance that can be used to get auth headers.
222
+ * @example
223
+ * ```typescript
224
+ * const config = {
225
+ * consumerKey: "your-consumer-key",
226
+ * consumerSecret: "your-consumer-secret",
227
+ * accessToken: "your-access-token",
228
+ * accessTokenSecret: "your-access-token-secret"
229
+ * };
230
+ *
231
+ * const authProvider = getIntegrationAuthProvider(config);
232
+ *
233
+ * // Get OAuth headers for a REST API call
234
+ * const headers = authProvider.getHeaders("GET", "https://your-store.com/rest/V1/products");
235
+ * console.log(headers); // { Authorization: "OAuth oauth_consumer_key=..., oauth_signature=..." }
236
+ *
237
+ * // Can also be used with URL objects
238
+ * const url = new URL("https://your-store.com/rest/V1/customers");
239
+ * const postHeaders = authProvider.getHeaders("POST", url);
240
+ * ```
163
241
  */
164
- function getIntegrationAuthProvider(config) {
242
+ function getIntegrationAuthProvider(authParams) {
165
243
  const oauth = new OAuth1a({
166
244
  consumer: {
167
- key: config.consumerKey,
168
- secret: config.consumerSecret
245
+ key: authParams.consumerKey,
246
+ secret: authParams.consumerSecret
169
247
  },
170
248
  signature_method: "HMAC-SHA256",
171
249
  hash_function: (baseString, key) => crypto.createHmac("sha256", key).update(baseString).digest("base64")
172
250
  });
173
251
  const oauthToken = {
174
- key: config.accessToken,
175
- secret: config.accessTokenSecret
252
+ key: authParams.accessToken,
253
+ secret: authParams.accessTokenSecret
176
254
  };
177
- const getHeaders = (method, url$1) => {
178
- const uriValidation = safeParse(UrlSchema, url$1);
179
- if (!uriValidation.success) return err(makeIntegrationAuthValidationError("Failed to validate the provided Adobe Commerce URL", uriValidation.issues));
180
- const finalUrl = uriValidation.output;
181
- const headers = oauth.toHeader(oauth.authorize({
182
- url: finalUrl,
255
+ return { getHeaders: (method, url$1) => {
256
+ const urlString = url$1 instanceof URL ? url$1.toString() : url$1;
257
+ return oauth.toHeader(oauth.authorize({
258
+ url: urlString,
183
259
  method
184
260
  }, oauthToken));
185
- return ok(headers);
186
- };
187
- return { getHeaders };
188
- }
189
- /**
190
- * Tries to create an {@link IntegrationAuthProvider} based on the provided parameters.
191
- * @param params The parameters required for integration authentication.
192
- * @returns An {@link IntegrationAuthProvider} instance that can be used to get auth headers.
193
- */
194
- function tryGetIntegrationAuthProvider(params) {
195
- const validation = safeParse(IntegrationAuthParamsSchema, params);
196
- if (!validation.success) return err(makeIntegrationAuthValidationError("Failed to validate the provided integration parameters", validation.issues));
197
- return ok(getIntegrationAuthProvider(fromParams(validation.output)));
261
+ } };
198
262
  }
199
263
 
200
264
  //#endregion
201
- export { IMS_AUTH_ENV, getImsAuthProvider, getIntegrationAuthProvider, tryGetImsAuthProvider, tryGetIntegrationAuthProvider };
265
+ export { IMS_AUTH_ENV, assertImsAuthParams, assertIntegrationAuthParams, getImsAuthProvider, getIntegrationAuthProvider };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@adobe/aio-commerce-lib-auth",
3
3
  "type": "module",
4
- "version": "0.2.0",
4
+ "version": "0.3.0",
5
5
  "private": false,
6
6
  "author": "Adobe Inc.",
7
7
  "engines": {
@@ -26,7 +26,7 @@
26
26
  },
27
27
  "main": "./dist/cjs/index.cjs",
28
28
  "module": "./dist/es/index.js",
29
- "types": "./dist/es/index.d.ts",
29
+ "types": "./dist/cjs/index.d.cts",
30
30
  "exports": {
31
31
  ".": {
32
32
  "import": {
@@ -40,12 +40,18 @@
40
40
  },
41
41
  "./package.json": "./package.json"
42
42
  },
43
+ "files": [
44
+ "dist",
45
+ "package.json",
46
+ "CHANGELOG.md",
47
+ "README.md"
48
+ ],
43
49
  "dependencies": {
44
50
  "@adobe/aio-lib-ims": "^8.1.0",
45
51
  "ansis": "^4.1.0",
46
52
  "oauth-1.0a": "^2.2.6",
47
53
  "valibot": "^1.1.0",
48
- "@adobe/aio-commerce-lib-core": "0.2.0"
54
+ "@adobe/aio-commerce-lib-core": "0.3.0"
49
55
  },
50
56
  "devDependencies": {
51
57
  "vitest": "^3.2.4",
@@ -1,18 +0,0 @@
1
-
2
- > @adobe/aio-commerce-lib-auth@0.2.0 build /home/runner/work/aio-commerce-sdk/aio-commerce-sdk/packages/aio-commerce-lib-auth
3
- > tsdown
4
-
5
- ℹ tsdown v0.12.9 powered by rolldown v1.0.0-beta.24
6
- ℹ Using tsdown config: /home/runner/work/aio-commerce-sdk/aio-commerce-sdk/packages/aio-commerce-lib-auth/tsdown.config.ts
7
- ℹ entry: source/index.ts
8
- ℹ target: node22.0.0
9
- ℹ tsconfig: tsconfig.json
10
- ℹ Build start
11
- ℹ [CJS] dist/cjs/index.cjs 10.48 kB │ gzip: 2.73 kB
12
- ℹ [CJS] 1 files, total: 10.48 kB
13
- ℹ [CJS] dist/index.d.cts 7.68 kB │ gzip: 1.41 kB
14
- ℹ [CJS] 1 files, total: 7.68 kB
15
- ℹ [ESM] dist/es/index.js 8.55 kB │ gzip: 2.28 kB
16
- ℹ [ESM] dist/es/index.d.ts 7.63 kB │ gzip: 1.41 kB
17
- ℹ [ESM] 2 files, total: 16.18 kB
18
- ✔ Build complete in 2646ms
package/source/index.ts DELETED
@@ -1,35 +0,0 @@
1
- /*
2
- * Copyright 2025 Adobe. All rights reserved.
3
- * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
- * you may not use this file except in compliance with the License. You may obtain a copy
5
- * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
- *
7
- * Unless required by applicable law or agreed to in writing, software distributed under
8
- * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
- * OF ANY KIND, either express or implied. See the License for the specific language
10
- * governing permissions and limitations under the License.
11
- */
12
-
13
- export {
14
- getImsAuthProvider,
15
- type ImsAuthConfig,
16
- type ImsAuthError,
17
- type ImsAuthProvider,
18
- tryGetImsAuthProvider,
19
- } from "./lib/ims-auth/provider";
20
-
21
- export {
22
- IMS_AUTH_ENV,
23
- type ImsAuthEnv,
24
- type ImsAuthParams,
25
- } from "./lib/ims-auth/schema";
26
-
27
- export {
28
- getIntegrationAuthProvider,
29
- type IntegrationAuthError,
30
- type IntegrationAuthProvider,
31
- type IntegrationConfig,
32
- tryGetIntegrationAuthProvider,
33
- } from "./lib/integration-auth/provider";
34
-
35
- export type { IntegrationAuthParams } from "./lib/integration-auth/schema";
@@ -1,160 +0,0 @@
1
- import {
2
- type ErrorType,
3
- err,
4
- map,
5
- ok,
6
- type Result,
7
- } from "@adobe/aio-commerce-lib-core/result";
8
-
9
- import type { ValidationErrorType } from "@adobe/aio-commerce-lib-core/validation";
10
- import { context, getToken } from "@adobe/aio-lib-ims";
11
- import type { SnakeCasedProperties } from "type-fest";
12
- import { type InferInput, type InferIssue, safeParse } from "valibot";
13
-
14
- import {
15
- type ImsAuthEnv,
16
- type ImsAuthParams,
17
- ImsAuthParamsSchema,
18
- } from "./schema";
19
-
20
- type ImsAccessToken = string;
21
- type ImsAuthHeader = "Authorization" | "x-api-key";
22
- type ImsAuthHeaders = Record<ImsAuthHeader, string>;
23
-
24
- /** Defines a validation error type for the IMS auth service. */
25
- export type ImsAuthValidationError = ValidationErrorType<
26
- "ImsAuthValidationError",
27
- InferIssue<typeof ImsAuthParamsSchema>[]
28
- >;
29
-
30
- /** Defines an error type for the IMS auth service. */
31
- export type ImsAuthError<TError = unknown> = ErrorType<
32
- "ImsAuthError",
33
- {
34
- message: string;
35
- error: TError;
36
- }
37
- >;
38
-
39
- /** Defines the configuration options to create an {@link ImsAuthProvider}. */
40
- export interface ImsAuthConfig {
41
- clientId: string;
42
- clientSecrets: string[];
43
- technicalAccountId: string;
44
- technicalAccountEmail: string;
45
- imsOrgId: string;
46
- scopes: string[];
47
- environment: ImsAuthEnv;
48
- context: string;
49
- }
50
-
51
- /** Defines an authentication provider for Adobe IMS. */
52
- export interface ImsAuthProvider {
53
- getAccessToken: () => Promise<Result<ImsAccessToken, ImsAuthError>>;
54
- getHeaders: () => Promise<Result<ImsAuthHeaders, ImsAuthError>>;
55
- }
56
-
57
- function snakeCaseImsAuthConfig(
58
- config: ImsAuthConfig,
59
- ): SnakeCasedProperties<ImsAuthConfig> {
60
- return {
61
- ...config,
62
- client_id: config.clientId,
63
- client_secrets: config.clientSecrets,
64
- technical_account_id: config.technicalAccountId,
65
- technical_account_email: config.technicalAccountEmail,
66
- ims_org_id: config.imsOrgId,
67
- };
68
- }
69
-
70
- function makeImsAuthValidationError(
71
- message: string,
72
- issues: InferIssue<typeof ImsAuthParamsSchema>[],
73
- ) {
74
- return {
75
- _tag: "ImsAuthValidationError",
76
- message,
77
- issues,
78
- } satisfies ImsAuthValidationError;
79
- }
80
-
81
- function makeImsAuthError(message: string, error: unknown) {
82
- return {
83
- _tag: "ImsAuthError",
84
- message,
85
- error,
86
- } satisfies ImsAuthError;
87
- }
88
-
89
- function fromParams(params: ImsAuthParams) {
90
- return {
91
- clientId: params.AIO_COMMERCE_IMS_CLIENT_ID,
92
- clientSecrets: params.AIO_COMMERCE_IMS_CLIENT_SECRETS,
93
- technicalAccountId: params.AIO_COMMERCE_IMS_TECHNICAL_ACCOUNT_ID,
94
- technicalAccountEmail: params.AIO_COMMERCE_IMS_TECHNICAL_ACCOUNT_EMAIL,
95
- imsOrgId: params.AIO_COMMERCE_IMS_IMS_ORG_ID,
96
- scopes: params.AIO_COMMERCE_IMS_SCOPES,
97
- environment: params.AIO_COMMERCE_IMS_ENV,
98
- context: params.AIO_COMMERCE_IMS_CTX,
99
- } satisfies ImsAuthConfig;
100
- }
101
-
102
- async function tryGetAccessToken(
103
- contextName: string,
104
- ): Promise<Result<ImsAccessToken, ImsAuthError>> {
105
- try {
106
- const accessToken = await getToken(contextName, {});
107
- return ok(accessToken);
108
- } catch (error) {
109
- return err(makeImsAuthError("Failed to retrieve IMS access token", error));
110
- }
111
- }
112
-
113
- /**
114
- * Creates an {@link ImsAuthProvider} based on the provided configuration.
115
- * @param config The configuration for the IMS Auth Provider.
116
- * @returns An {@link ImsAuthProvider} instance that can be used to get access token and auth headers.
117
- */
118
- export function getImsAuthProvider(config: ImsAuthConfig): ImsAuthProvider {
119
- const getAccessToken = async () => {
120
- const snakeCasedConfig = snakeCaseImsAuthConfig(config);
121
-
122
- await context.set(config.context, snakeCasedConfig);
123
- return tryGetAccessToken(config.context);
124
- };
125
-
126
- const getHeaders = async () => {
127
- const result = await getAccessToken();
128
- return map(result, (accessToken) => ({
129
- Authorization: `Bearer ${accessToken}`,
130
- "x-api-key": config.clientId,
131
- }));
132
- };
133
-
134
- return {
135
- getAccessToken,
136
- getHeaders,
137
- };
138
- }
139
-
140
- /**
141
- * Tries to create an {@link ImsAuthProvider} based on the provided parameters.
142
- * @param params The parameters required to create the IMS Auth Provider.
143
- * @returns An {@link ImsAuthProvider} instance that can be used to get access token and auth headers.
144
- */
145
- export function tryGetImsAuthProvider(
146
- params: InferInput<typeof ImsAuthParamsSchema>,
147
- ): Result<ImsAuthProvider, ImsAuthValidationError> {
148
- const validation = safeParse(ImsAuthParamsSchema, params);
149
-
150
- if (!validation.success) {
151
- return err(
152
- makeImsAuthValidationError(
153
- "Failed to validate the provided IMS parameters",
154
- validation.issues,
155
- ),
156
- );
157
- }
158
-
159
- return ok(getImsAuthProvider(fromParams(validation.output)));
160
- }