@adobe/aio-commerce-lib-auth 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/es/index.js CHANGED
@@ -1,38 +1,39 @@
1
- import { err, map, ok } from "@adobe/aio-commerce-lib-core/result";
1
+ /**
2
+ * @license
3
+ *
4
+ * Copyright 2025 Adobe. All rights reserved.
5
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License. You may obtain a copy
7
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
8
+ *
9
+ * Unless required by applicable law or agreed to in writing, software distributed under
10
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
11
+ * OF ANY KIND, either express or implied. See the License for the specific language
12
+ * governing permissions and limitations under the License.
13
+ */
14
+ import { CommerceSdkValidationError } from "@adobe/aio-commerce-lib-core/error";
2
15
  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";
4
- import crypto from "node:crypto";
16
+ import { array, email, enum as enum$1, instance, minLength, nonEmpty, nonOptional, object, optional, pipe, safeParse, string, transform, union, url } from "valibot";
17
+ import crypto from "crypto";
5
18
  import OAuth1a from "oauth-1.0a";
6
-
7
- //#region source/lib/ims-auth/schema.ts
8
- 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}`));
12
- };
13
- /** The environments accepted by the IMS auth service. */
14
- const IMS_AUTH_ENV = {
19
+ 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}`)), stringArray = (name) => pipe(array(string(), `Expected a stringified JSON array value for the IMS auth parameter ${name}`)), IMS_AUTH_ENV = {
15
20
  PROD: "prod",
16
21
  STAGE: "stage"
17
- };
18
- const ImsAuthEnvSchema = enum$1(IMS_AUTH_ENV);
19
- /** Defines the schema to validate the necessary parameters for the IMS auth service. */
20
- 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")
22
+ }, ImsAuthEnvSchema = enum$1(IMS_AUTH_ENV), ImsAuthParamsSchema = object({
23
+ clientId: imsAuthParameter("clientId"),
24
+ clientSecrets: pipe(stringArray("clientSecrets"), minLength(1, "Expected at least one client secret for IMS auth")),
25
+ technicalAccountId: imsAuthParameter("technicalAccountId"),
26
+ technicalAccountEmail: pipe(string("Expected a string value for the IMS auth parameter technicalAccountEmail"), email("Expected a valid email format for technicalAccountEmail")),
27
+ imsOrgId: imsAuthParameter("imsOrgId"),
28
+ environment: pipe(optional(ImsAuthEnvSchema, IMS_AUTH_ENV.PROD)),
29
+ context: pipe(optional(string(), "aio-commerce-sdk-creds")),
30
+ scopes: pipe(stringArray("scopes"), minLength(1, "Expected at least one scope for IMS auth"))
29
31
  });
30
-
31
- //#endregion
32
- //#region source/lib/ims-auth/provider.ts
33
- function snakeCaseImsAuthConfig(config) {
32
+ function toImsAuthConfig(config) {
34
33
  return {
35
- ...config,
34
+ scopes: config.scopes,
35
+ env: config?.environment ?? "prod",
36
+ context: config.context,
36
37
  client_id: config.clientId,
37
38
  client_secrets: config.clientSecrets,
38
39
  technical_account_id: config.technicalAccountId,
@@ -40,162 +41,56 @@ function snakeCaseImsAuthConfig(config) {
40
41
  ims_org_id: config.imsOrgId
41
42
  };
42
43
  }
43
- function makeImsAuthValidationError(message$1, issues) {
44
- return {
45
- _tag: "ImsAuthValidationError",
46
- message: message$1,
47
- issues
48
- };
44
+ function assertImsAuthParams(config) {
45
+ let result = safeParse(ImsAuthParamsSchema, config);
46
+ if (!result.success) throw new CommerceSdkValidationError("Invalid ImsAuthProvider configuration", { issues: result.issues });
49
47
  }
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
- }
76
- }
77
- /**
78
- * Creates an {@link ImsAuthProvider} based on the provided configuration.
79
- * @param config The configuration for the IMS Auth Provider.
80
- * @returns An {@link ImsAuthProvider} instance that can be used to get access token and auth headers.
81
- */
82
- function getImsAuthProvider(config) {
83
- const getAccessToken = async () => {
84
- const snakeCasedConfig = snakeCaseImsAuthConfig(config);
85
- await context.set(config.context, snakeCasedConfig);
86
- return tryGetAccessToken(config.context);
87
- };
88
- const getHeaders = async () => {
89
- const result = await getAccessToken();
90
- return map(result, (accessToken) => ({
48
+ function getImsAuthProvider(authParams) {
49
+ let getAccessToken = async () => {
50
+ let imsAuthConfig = toImsAuthConfig(authParams);
51
+ return await context.set(authParams.context, imsAuthConfig), getToken(authParams.context, {});
52
+ }, getHeaders = async () => {
53
+ let accessToken = await getAccessToken();
54
+ return {
91
55
  Authorization: `Bearer ${accessToken}`,
92
- "x-api-key": config.clientId
93
- }));
56
+ "x-api-key": authParams.clientId
57
+ };
94
58
  };
95
59
  return {
96
60
  getAccessToken,
97
61
  getHeaders
98
62
  };
99
63
  }
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
-
111
- //#endregion
112
- //#region source/lib/integration-auth/schema.ts
113
- /**
114
- * The HTTP methods supported by Commerce.
115
- * This is used to determine which headers to include in the signing of the authorization header.
116
- */
117
- const AllowedHttpMethod = [
118
- "GET",
119
- "POST",
120
- "PUT",
121
- "PATCH",
122
- "DELETE"
123
- ];
124
- const HttpMethodSchema = picklist(AllowedHttpMethod);
125
- 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}`));
126
- 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"));
127
- const UrlSchema = pipe(union([BaseUrlSchema, instance(URL)]), transform((url$1) => {
128
- if (url$1 instanceof URL) return url$1.toString();
129
- return url$1;
130
- }));
131
- /**
132
- * The schema for the Commerce Integration parameters.
133
- * This is used to validate the parameters passed to the Commerce Integration provider.
134
- */
64
+ 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}`)), 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"));
65
+ pipe(union([BaseUrlSchema, instance(URL)]), transform((url$1) => url$1 instanceof URL ? url$1.toString() : url$1));
135
66
  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")
67
+ consumerKey: integrationAuthParameter("consumerKey"),
68
+ consumerSecret: integrationAuthParameter("consumerSecret"),
69
+ accessToken: integrationAuthParameter("accessToken"),
70
+ accessTokenSecret: integrationAuthParameter("accessTokenSecret")
140
71
  }));
141
-
142
- //#endregion
143
- //#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
- };
72
+ function assertIntegrationAuthParams(config) {
73
+ let result = safeParse(IntegrationAuthParamsSchema, config);
74
+ if (!result.success) throw new CommerceSdkValidationError("Invalid IntegrationAuthProvider configuration", { issues: result.issues });
158
75
  }
159
- /**
160
- * Creates an {@link IntegrationAuthProvider} based on the provided configuration.
161
- * @param config The configuration for the integration.
162
- * @returns An {@link IntegrationAuthProvider} instance that can be used to get auth headers.
163
- */
164
- function getIntegrationAuthProvider(config) {
165
- const oauth = new OAuth1a({
76
+ function getIntegrationAuthProvider(authParams) {
77
+ let oauth = new OAuth1a({
166
78
  consumer: {
167
- key: config.consumerKey,
168
- secret: config.consumerSecret
79
+ key: authParams.consumerKey,
80
+ secret: authParams.consumerSecret
169
81
  },
170
82
  signature_method: "HMAC-SHA256",
171
83
  hash_function: (baseString, key) => crypto.createHmac("sha256", key).update(baseString).digest("base64")
172
- });
173
- const oauthToken = {
174
- key: config.accessToken,
175
- secret: config.accessTokenSecret
84
+ }), oauthToken = {
85
+ key: authParams.accessToken,
86
+ secret: authParams.accessTokenSecret
176
87
  };
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,
88
+ return { getHeaders: (method, url$1) => {
89
+ let urlString = url$1 instanceof URL ? url$1.toString() : url$1;
90
+ return oauth.toHeader(oauth.authorize({
91
+ url: urlString,
183
92
  method
184
93
  }, 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)));
94
+ } };
198
95
  }
199
-
200
- //#endregion
201
- export { IMS_AUTH_ENV, getImsAuthProvider, getIntegrationAuthProvider, tryGetImsAuthProvider, tryGetIntegrationAuthProvider };
96
+ export { IMS_AUTH_ENV, assertImsAuthParams, assertIntegrationAuthParams, getImsAuthProvider, getIntegrationAuthProvider };
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@adobe/aio-commerce-lib-auth",
3
3
  "type": "module",
4
- "version": "0.2.0",
5
- "private": false,
6
4
  "author": "Adobe Inc.",
5
+ "version": "0.3.1",
6
+ "private": false,
7
7
  "engines": {
8
- "node": ">=22"
8
+ "node": ">=20 <=24"
9
9
  },
10
10
  "license": "Apache-2.0",
11
11
  "description": "Authentication utilities for Adobe Commerce apps deployed in Adobe App Builder.",
@@ -21,12 +21,12 @@
21
21
  },
22
22
  "repository": {
23
23
  "type": "git",
24
- "url": "https://github.com/adobe/aio-commerce-sdk.git",
24
+ "url": "git+https://github.com/adobe/aio-commerce-sdk.git",
25
25
  "directory": "packages/aio-commerce-lib-auth"
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,30 +40,40 @@
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.4.0"
49
55
  },
50
56
  "devDependencies": {
51
- "vitest": "^3.2.4",
57
+ "@aio-commerce-sdk/config-tsdown": "1.0.0",
58
+ "@aio-commerce-sdk/config-typedoc": "1.0.0",
52
59
  "@aio-commerce-sdk/config-typescript": "1.0.0",
53
- "@aio-commerce-sdk/config-tsdown": "1.0.0"
60
+ "@aio-commerce-sdk/config-vitest": "1.0.0"
54
61
  },
55
62
  "sideEffects": false,
56
63
  "scripts": {
57
64
  "build": "tsdown",
58
- "assist": "pnpm -w assist .",
59
- "assist:apply": "pnpm -w assist:apply .",
60
- "check:ci": "pnpm -w check:ci .",
61
- "format": "pnpm -w format .",
62
- "format:check": "pnpm -w format:check .",
63
- "lint": "pnpm -w lint .",
64
- "lint:fix": "pnpm -w lint:fix .",
65
+ "docs": "typedoc && prettier --write '**/*.md'",
66
+ "assist": "biome check --formatter-enabled=false --linter-enabled=false --assist-enabled=true --no-errors-on-unmatched",
67
+ "assist:apply": "biome check --write --formatter-enabled=false --linter-enabled=false --assist-enabled=true --no-errors-on-unmatched",
68
+ "check:ci": "biome ci --formatter-enabled=true --linter-enabled=true --assist-enabled=true --no-errors-on-unmatched",
69
+ "format": "biome format --write --no-errors-on-unmatched",
70
+ "format:markdown": "prettier --no-error-on-unmatched-pattern --write '**/*.md' \"!**/{CODE_OF_CONDUCT.md,COPYRIGHT,LICENSE,SECURITY.md,CONTRIBUTING.md}\"",
71
+ "format:check": "biome format --no-errors-on-unmatched",
72
+ "lint": "biome lint --no-errors-on-unmatched",
73
+ "lint:fix": "biome lint --write --no-errors-on-unmatched",
65
74
  "typecheck": "tsc --noEmit && echo '✅ No type errors found.'",
66
- "test": "vitest run",
67
- "test:watch": "vitest"
75
+ "test": "vitest run --coverage",
76
+ "test:watch": "vitest --coverage",
77
+ "test:ui": "vitest --ui"
68
78
  }
69
79
  }
@@ -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
- }
@@ -1,87 +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
- import {
14
- type InferOutput,
15
- nonEmpty,
16
- object,
17
- optional,
18
- parseJson,
19
- pipe,
20
- string,
21
- array as vArray,
22
- enum as vEnum,
23
- message as vMessage,
24
- } from "valibot";
25
-
26
- const imsAuthParameter = (name: string) =>
27
- pipe(
28
- string(`Expected a string value for the IMS auth parameter ${name}`),
29
- nonEmpty(
30
- `Expected a non-empty string value for the IMS auth parameter ${name}`,
31
- ),
32
- );
33
-
34
- const jsonStringArray = (name: string) => {
35
- const jsonStringArraySchema = vMessage(
36
- pipe(
37
- string(`Expected a string value for the IMS auth parameter ${name}`),
38
- nonEmpty(
39
- `Expected a non-empty string value for the IMS auth parameter ${name}`,
40
- ),
41
- parseJson(),
42
- ),
43
- `An error occurred while parsing the JSON string array parameter ${name}`,
44
- );
45
-
46
- return pipe(
47
- jsonStringArraySchema,
48
- vArray(
49
- string(),
50
- `Expected a stringified JSON array value for the IMS auth parameter ${name}`,
51
- ),
52
- );
53
- };
54
-
55
- /** The environments accepted by the IMS auth service. */
56
- export const IMS_AUTH_ENV = {
57
- PROD: "prod",
58
- STAGE: "stage",
59
- } as const;
60
-
61
- const ImsAuthEnvSchema = vEnum(IMS_AUTH_ENV);
62
-
63
- /** Defines the schema to validate the necessary parameters for the IMS auth service. */
64
- export const ImsAuthParamsSchema = object({
65
- AIO_COMMERCE_IMS_CLIENT_ID: imsAuthParameter("AIO_COMMERCE_IMS_CLIENT_ID"),
66
- AIO_COMMERCE_IMS_CLIENT_SECRETS: jsonStringArray(
67
- "AIO_COMMERCE_IMS_CLIENT_SECRETS",
68
- ),
69
- AIO_COMMERCE_IMS_TECHNICAL_ACCOUNT_ID: imsAuthParameter(
70
- "AIO_COMMERCE_IMS_TECHNICAL_ACCOUNT_ID",
71
- ),
72
-
73
- AIO_COMMERCE_IMS_TECHNICAL_ACCOUNT_EMAIL: imsAuthParameter(
74
- "AIO_COMMERCE_IMS_TECHNICAL_ACCOUNT_EMAIL",
75
- ),
76
- AIO_COMMERCE_IMS_IMS_ORG_ID: imsAuthParameter("AIO_COMMERCE_IMS_IMS_ORG_ID"),
77
-
78
- AIO_COMMERCE_IMS_ENV: pipe(optional(ImsAuthEnvSchema, IMS_AUTH_ENV.PROD)),
79
- AIO_COMMERCE_IMS_CTX: pipe(optional(string(), "aio-commerce-sdk-creds")),
80
- AIO_COMMERCE_IMS_SCOPES: jsonStringArray("AIO_COMMERCE_IMS_SCOPES"),
81
- });
82
-
83
- /** Defines the parameters for the IMS auth service. */
84
- export type ImsAuthParams = InferOutput<typeof ImsAuthParamsSchema>;
85
-
86
- /** Defines the environments accepted by the IMS auth service. */
87
- export type ImsAuthEnv = InferOutput<typeof ImsAuthEnvSchema>;