@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 +30 -0
- package/README.md +92 -20
- package/dist/cjs/index.cjs +242 -85
- package/dist/cjs/index.d.cts +50 -24
- package/dist/es/index.d.ts +50 -24
- package/dist/es/index.js +240 -86
- package/package.json +12 -3
- package/.turbo/turbo-build.log +0 -18
- package/source/index.ts +0 -14
- package/source/lib/ims-auth.ts +0 -95
- package/source/lib/integration-auth.ts +0 -95
- package/source/lib/params.ts +0 -34
- package/test/ims-auth.test.ts +0 -69
- package/test/integration-auth.test.ts +0 -61
- package/tsconfig.json +0 -15
- package/tsdown.config.ts +0 -7
- package/vitest.config.ts +0 -16
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 {
|
|
32
|
+
import {
|
|
33
|
+
assertImsAuthParams,
|
|
34
|
+
getImsAuthProvider,
|
|
35
|
+
} from "@adobe/aio-commerce-lib-auth";
|
|
35
36
|
|
|
36
|
-
|
|
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
|
-
|
|
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 {
|
|
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
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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](
|
|
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.
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -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/
|
|
30
|
+
//#region source/lib/ims-auth/schema.ts
|
|
29
31
|
/**
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* @
|
|
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
|
-
|
|
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
|
-
*
|
|
41
|
-
* @param
|
|
42
|
-
* @
|
|
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
|
-
|
|
45
|
-
return
|
|
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
|
-
*
|
|
52
|
-
* @
|
|
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
|
-
|
|
55
|
-
const
|
|
56
|
-
if (
|
|
57
|
-
|
|
58
|
-
|
|
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
|
-
|
|
61
|
-
|
|
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
|
-
|
|
72
|
-
|
|
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
|
-
*
|
|
94
|
-
* @param
|
|
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
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
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;
|
package/dist/cjs/index.d.cts
CHANGED
|
@@ -1,39 +1,65 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as valibot24 from "valibot";
|
|
2
|
+
import { InferOutput } from "valibot";
|
|
2
3
|
|
|
3
|
-
//#region source/lib/ims-auth.d.ts
|
|
4
|
-
declare const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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
|
|
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
|
-
}
|
|
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
|
-
|
|
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
|
|
58
|
+
type AdobeCommerceUrl = string | URL;
|
|
32
59
|
interface IntegrationAuthProvider {
|
|
33
|
-
getHeaders: (method:
|
|
60
|
+
getHeaders: (method: HttpMethodInput, url: AdobeCommerceUrl) => IntegrationAuthHeaders;
|
|
34
61
|
}
|
|
35
|
-
declare function
|
|
36
|
-
|
|
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 {
|
|
65
|
+
export { IMS_AUTH_ENV, ImsAuthEnv, ImsAuthParams, ImsAuthProvider, IntegrationAuthParams, IntegrationAuthProvider, assertImsAuthParams, assertIntegrationAuthParams, getImsAuthProvider, getIntegrationAuthProvider };
|