@reactionary/source 0.0.52 → 0.2.15
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/.env-template +19 -0
- package/.github/workflows/pull-request.yml +3 -1
- package/.github/workflows/release.yml +9 -0
- package/.vscode/extensions.json +0 -2
- package/LICENSE +21 -0
- package/README.md +175 -23
- package/core/package.json +6 -3
- package/core/src/cache/cache.interface.ts +1 -0
- package/core/src/cache/index.ts +4 -0
- package/core/src/cache/memory-cache.ts +30 -2
- package/core/src/cache/noop-cache.ts +15 -1
- package/core/src/cache/redis-cache.ts +20 -0
- package/core/src/client/client-builder.ts +71 -54
- package/core/src/client/client.ts +9 -47
- package/core/src/client/index.ts +2 -0
- package/core/src/decorators/index.ts +1 -0
- package/core/src/decorators/reactionary.decorator.ts +203 -34
- package/core/src/index.ts +6 -19
- package/core/src/initialization.ts +1 -18
- package/core/src/metrics/metrics.ts +67 -0
- package/core/src/providers/analytics.provider.ts +1 -6
- package/core/src/providers/base.provider.ts +5 -69
- package/core/src/providers/cart.provider.ts +15 -55
- package/core/src/providers/category.provider.ts +7 -11
- package/core/src/providers/checkout.provider.ts +17 -15
- package/core/src/providers/identity.provider.ts +6 -8
- package/core/src/providers/index.ts +2 -1
- package/core/src/providers/inventory.provider.ts +15 -5
- package/core/src/providers/order-search.provider.ts +29 -0
- package/core/src/providers/order.provider.ts +47 -15
- package/core/src/providers/price.provider.ts +30 -36
- package/core/src/providers/product-search.provider.ts +61 -0
- package/core/src/providers/product.provider.ts +71 -12
- package/core/src/providers/profile.provider.ts +74 -14
- package/core/src/providers/store.provider.ts +3 -5
- package/core/src/schemas/capabilities.schema.ts +10 -3
- package/core/src/schemas/errors/generic.error.ts +9 -0
- package/core/src/schemas/errors/index.ts +4 -0
- package/core/src/schemas/errors/invalid-input.error.ts +9 -0
- package/core/src/schemas/errors/invalid-output.error.ts +9 -0
- package/core/src/schemas/errors/not-found.error.ts +9 -0
- package/core/src/schemas/index.ts +7 -0
- package/core/src/schemas/models/analytics.model.ts +2 -1
- package/core/src/schemas/models/base.model.ts +6 -24
- package/core/src/schemas/models/cart.model.ts +5 -8
- package/core/src/schemas/models/category.model.ts +4 -9
- package/core/src/schemas/models/checkout.model.ts +6 -7
- package/core/src/schemas/models/cost.model.ts +4 -3
- package/core/src/schemas/models/currency.model.ts +2 -1
- package/core/src/schemas/models/identifiers.model.ts +106 -62
- package/core/src/schemas/models/identity.model.ts +10 -19
- package/core/src/schemas/models/index.ts +2 -1
- package/core/src/schemas/models/inventory.model.ts +8 -5
- package/core/src/schemas/models/order-search.model.ts +28 -0
- package/core/src/schemas/models/order.model.ts +20 -26
- package/core/src/schemas/models/payment.model.ts +14 -17
- package/core/src/schemas/models/price.model.ts +11 -11
- package/core/src/schemas/models/product-search.model.ts +42 -0
- package/core/src/schemas/models/product.model.ts +64 -22
- package/core/src/schemas/models/profile.model.ts +19 -22
- package/core/src/schemas/models/shipping-method.model.ts +24 -29
- package/core/src/schemas/models/store.model.ts +9 -5
- package/core/src/schemas/mutations/analytics.mutation.ts +8 -7
- package/core/src/schemas/mutations/base.mutation.ts +2 -1
- package/core/src/schemas/mutations/cart.mutation.ts +33 -33
- package/core/src/schemas/mutations/checkout.mutation.ts +23 -30
- package/core/src/schemas/mutations/identity.mutation.ts +4 -3
- package/core/src/schemas/mutations/profile.mutation.ts +38 -3
- package/core/src/schemas/queries/base.query.ts +2 -1
- package/core/src/schemas/queries/cart.query.ts +3 -3
- package/core/src/schemas/queries/category.query.ts +18 -18
- package/core/src/schemas/queries/checkout.query.ts +7 -9
- package/core/src/schemas/queries/identity.query.ts +2 -1
- package/core/src/schemas/queries/index.ts +2 -1
- package/core/src/schemas/queries/inventory.query.ts +5 -5
- package/core/src/schemas/queries/order-search.query.ts +10 -0
- package/core/src/schemas/queries/order.query.ts +3 -2
- package/core/src/schemas/queries/price.query.ts +10 -4
- package/core/src/schemas/queries/product-search.query.ts +16 -0
- package/core/src/schemas/queries/product.query.ts +13 -6
- package/core/src/schemas/queries/profile.query.ts +5 -2
- package/core/src/schemas/queries/store.query.ts +6 -5
- package/core/src/schemas/result.ts +107 -0
- package/core/src/schemas/session.schema.ts +4 -4
- package/core/src/test/reactionary.decorator.spec.ts +249 -0
- package/core/src/zod-utils.ts +19 -0
- package/core/tsconfig.json +1 -1
- package/core/tsconfig.spec.json +2 -26
- package/core/vitest.config.ts +14 -0
- package/documentation/1-purpose.md +114 -0
- package/documentation/2-getting-started.md +229 -0
- package/documentation/3-querying-and-changing-data.md +74 -0
- package/documentation/4-product-data.md +107 -0
- package/documentation/5-cart-and-checkout.md +211 -0
- package/documentation/6-product-search.md +143 -0
- package/documentation/7-marketing.md +3 -0
- package/eslint.config.mjs +1 -0
- package/examples/node/eslint.config.mjs +1 -4
- package/examples/node/package.json +10 -3
- package/examples/node/project.json +4 -1
- package/examples/node/src/basic/basic-node-provider-model-extension.spec.ts +22 -23
- package/examples/node/src/basic/basic-node-provider-query-extension.spec.ts +15 -11
- package/examples/node/src/basic/basic-node-setup.spec.ts +44 -28
- package/examples/node/src/basic/client-creation.spec.ts +53 -0
- package/examples/node/src/capabilities/cart.spec.ts +255 -0
- package/examples/node/src/capabilities/category.spec.ts +193 -0
- package/examples/node/src/capabilities/checkout.spec.ts +341 -0
- package/examples/node/src/capabilities/identity.spec.ts +93 -0
- package/examples/node/src/capabilities/inventory.spec.ts +66 -0
- package/examples/node/src/capabilities/order-search.spec.ts +159 -0
- package/examples/node/src/capabilities/order.spec.ts +91 -0
- package/examples/node/src/capabilities/price.spec.ts +51 -0
- package/examples/node/src/capabilities/product-search.spec.ts +293 -0
- package/examples/node/src/capabilities/product.spec.ts +122 -0
- package/examples/node/src/capabilities/profile.spec.ts +316 -0
- package/examples/node/src/capabilities/store.spec.ts +26 -0
- package/examples/node/src/utils.ts +137 -0
- package/examples/node/tsconfig.json +9 -12
- package/examples/node/tsconfig.lib.json +1 -2
- package/examples/node/tsconfig.spec.json +2 -14
- package/examples/node/vitest.config.ts +14 -0
- package/migrations.json +22 -5
- package/nx.json +8 -47
- package/package.json +24 -96
- package/providers/algolia/README.md +39 -2
- package/providers/algolia/package.json +2 -1
- package/providers/algolia/src/core/initialize.ts +7 -14
- package/providers/algolia/src/index.ts +2 -4
- package/providers/algolia/src/providers/index.ts +1 -0
- package/providers/algolia/src/providers/product-search.provider.ts +241 -0
- package/providers/algolia/src/schema/capabilities.schema.ts +2 -3
- package/providers/algolia/src/schema/index.ts +3 -0
- package/providers/algolia/src/schema/search.schema.ts +8 -8
- package/providers/algolia/tsconfig.json +1 -1
- package/providers/algolia/tsconfig.lib.json +1 -1
- package/providers/algolia/tsconfig.spec.json +2 -14
- package/providers/algolia/vitest.config.ts +14 -0
- package/providers/commercetools/README.md +30 -3
- package/providers/commercetools/package.json +2 -1
- package/providers/commercetools/src/core/client.ts +178 -99
- package/providers/commercetools/src/core/initialize.ts +130 -74
- package/providers/commercetools/src/core/token-cache.ts +45 -0
- package/providers/commercetools/src/index.ts +3 -2
- package/providers/commercetools/src/providers/cart.provider.ts +281 -341
- package/providers/commercetools/src/providers/category.provider.ts +223 -138
- package/providers/commercetools/src/providers/checkout.provider.ts +631 -449
- package/providers/commercetools/src/providers/identity.provider.ts +50 -29
- package/providers/commercetools/src/providers/index.ts +2 -2
- package/providers/commercetools/src/providers/inventory.provider.ts +76 -74
- package/providers/commercetools/src/providers/order-search.provider.ts +220 -0
- package/providers/commercetools/src/providers/order.provider.ts +96 -61
- package/providers/commercetools/src/providers/price.provider.ts +147 -117
- package/providers/commercetools/src/providers/product-search.provider.ts +528 -0
- package/providers/commercetools/src/providers/product.provider.ts +249 -74
- package/providers/commercetools/src/providers/profile.provider.ts +445 -28
- package/providers/commercetools/src/providers/store.provider.ts +54 -40
- package/providers/commercetools/src/schema/capabilities.schema.ts +3 -1
- package/providers/commercetools/src/schema/commercetools.schema.ts +17 -3
- package/providers/commercetools/src/schema/configuration.schema.ts +1 -0
- package/providers/commercetools/src/schema/session.schema.ts +7 -0
- package/providers/commercetools/src/test/caching.spec.ts +82 -0
- package/providers/commercetools/src/test/identity.spec.ts +109 -0
- package/providers/commercetools/src/test/test-utils.ts +21 -19
- package/providers/commercetools/tsconfig.json +1 -1
- package/providers/commercetools/tsconfig.lib.json +1 -1
- package/providers/commercetools/tsconfig.spec.json +2 -14
- package/providers/commercetools/vitest.config.ts +15 -0
- package/providers/fake/README.md +20 -4
- package/providers/fake/package.json +2 -1
- package/providers/fake/src/core/initialize.ts +47 -49
- package/providers/fake/src/providers/analytics.provider.ts +5 -7
- package/providers/fake/src/providers/cart.provider.ts +163 -92
- package/providers/fake/src/providers/category.provider.ts +78 -50
- package/providers/fake/src/providers/checkout.provider.ts +254 -0
- package/providers/fake/src/providers/identity.provider.ts +57 -65
- package/providers/fake/src/providers/index.ts +6 -2
- package/providers/fake/src/providers/inventory.provider.ts +40 -36
- package/providers/fake/src/providers/order-search.provider.ts +78 -0
- package/providers/fake/src/providers/order.provider.ts +106 -0
- package/providers/fake/src/providers/price.provider.ts +93 -41
- package/providers/fake/src/providers/product-search.provider.ts +206 -0
- package/providers/fake/src/providers/product.provider.ts +56 -41
- package/providers/fake/src/providers/profile.provider.ts +147 -0
- package/providers/fake/src/providers/store.provider.ts +30 -20
- package/providers/fake/src/schema/capabilities.schema.ts +5 -1
- package/providers/fake/src/test/cart.provider.spec.ts +59 -80
- package/providers/fake/src/test/category.provider.spec.ts +145 -87
- package/providers/fake/src/test/checkout.provider.spec.ts +222 -0
- package/providers/fake/src/test/order-search.provider.spec.ts +50 -0
- package/providers/fake/src/test/order.provider.spec.ts +44 -0
- package/providers/fake/src/test/price.provider.spec.ts +50 -45
- package/providers/fake/src/test/product.provider.spec.ts +15 -7
- package/providers/fake/src/test/profile.provider.spec.ts +167 -0
- package/providers/fake/tsconfig.json +1 -1
- package/providers/fake/tsconfig.lib.json +1 -1
- package/providers/fake/tsconfig.spec.json +2 -12
- package/providers/fake/vitest.config.ts +14 -0
- package/providers/medusa/README.md +30 -0
- package/providers/medusa/TESTING.md +98 -0
- package/providers/medusa/eslint.config.mjs +19 -0
- package/providers/medusa/package.json +22 -0
- package/providers/medusa/project.json +34 -0
- package/providers/medusa/src/core/client.ts +370 -0
- package/providers/medusa/src/core/initialize.ts +78 -0
- package/providers/medusa/src/index.ts +13 -0
- package/providers/medusa/src/providers/cart.provider.ts +575 -0
- package/providers/medusa/src/providers/category.provider.ts +247 -0
- package/providers/medusa/src/providers/checkout.provider.ts +636 -0
- package/providers/medusa/src/providers/identity.provider.ts +137 -0
- package/providers/medusa/src/providers/inventory.provider.ts +173 -0
- package/providers/medusa/src/providers/order-search.provider.ts +201 -0
- package/providers/medusa/src/providers/order.provider.ts +226 -0
- package/providers/medusa/src/providers/price.provider.ts +140 -0
- package/providers/medusa/src/providers/product-search.provider.ts +243 -0
- package/providers/medusa/src/providers/product.provider.ts +261 -0
- package/providers/medusa/src/providers/profile.provider.ts +392 -0
- package/providers/medusa/src/schema/capabilities.schema.ts +18 -0
- package/providers/medusa/src/schema/configuration.schema.ts +11 -0
- package/providers/medusa/src/schema/medusa.schema.ts +31 -0
- package/providers/medusa/src/test/cart.provider.spec.ts +240 -0
- package/providers/medusa/src/test/category.provider.spec.ts +231 -0
- package/providers/medusa/src/test/checkout.spec.ts +349 -0
- package/providers/medusa/src/test/identity.provider.spec.ts +122 -0
- package/providers/medusa/src/test/inventory.provider.spec.ts +88 -0
- package/providers/medusa/src/test/large-cart.provider.spec.ts +103 -0
- package/providers/medusa/src/test/price.provider.spec.ts +104 -0
- package/providers/medusa/src/test/product.provider.spec.ts +146 -0
- package/providers/medusa/src/test/search.provider.spec.ts +203 -0
- package/providers/medusa/src/test/test-utils.ts +13 -0
- package/providers/medusa/src/utils/medusa-helpers.ts +89 -0
- package/providers/medusa/tsconfig.json +21 -0
- package/providers/medusa/tsconfig.lib.json +9 -0
- package/providers/medusa/tsconfig.spec.json +4 -0
- package/providers/medusa/vitest.config.ts +15 -0
- package/providers/meilisearch/README.md +48 -0
- package/providers/meilisearch/eslint.config.mjs +22 -0
- package/providers/meilisearch/package.json +13 -0
- package/providers/meilisearch/project.json +34 -0
- package/providers/meilisearch/src/core/initialize.ts +16 -0
- package/providers/meilisearch/src/index.ts +5 -0
- package/providers/meilisearch/src/providers/index.ts +1 -0
- package/providers/meilisearch/src/providers/product-search.provider.ts +251 -0
- package/providers/meilisearch/src/schema/capabilities.schema.ts +9 -0
- package/providers/meilisearch/src/schema/configuration.schema.ts +10 -0
- package/providers/meilisearch/src/schema/index.ts +3 -0
- package/providers/meilisearch/src/schema/search.schema.ts +14 -0
- package/providers/meilisearch/tsconfig.json +24 -0
- package/providers/meilisearch/tsconfig.lib.json +10 -0
- package/providers/meilisearch/tsconfig.spec.json +4 -0
- package/providers/meilisearch/vitest.config.ts +14 -0
- package/providers/posthog/package.json +2 -1
- package/providers/posthog/tsconfig.json +1 -1
- package/tsconfig.base.json +5 -0
- package/vitest.config.ts +10 -0
- package/core/src/providers/search.provider.ts +0 -18
- package/core/src/schemas/models/search.model.ts +0 -36
- package/core/src/schemas/queries/search.query.ts +0 -9
- package/examples/next/.swcrc +0 -30
- package/examples/next/eslint.config.mjs +0 -21
- package/examples/next/index.d.ts +0 -6
- package/examples/next/next-env.d.ts +0 -5
- package/examples/next/next.config.js +0 -31
- package/examples/next/project.json +0 -9
- package/examples/next/public/.gitkeep +0 -0
- package/examples/next/public/favicon.ico +0 -0
- package/examples/next/src/app/global.css +0 -0
- package/examples/next/src/app/layout.tsx +0 -18
- package/examples/next/src/app/page.module.scss +0 -2
- package/examples/next/src/app/page.tsx +0 -47
- package/examples/next/src/instrumentation.ts +0 -9
- package/examples/next/tsconfig.json +0 -44
- package/examples/node/jest.config.ts +0 -10
- package/jest.config.ts +0 -6
- package/jest.preset.js +0 -3
- package/providers/algolia/jest.config.ts +0 -10
- package/providers/algolia/src/providers/product.provider.ts +0 -66
- package/providers/algolia/src/providers/search.provider.ts +0 -106
- package/providers/algolia/src/test/search.provider.spec.ts +0 -91
- package/providers/commercetools/jest.config.cjs +0 -10
- package/providers/commercetools/src/providers/search.provider.ts +0 -96
- package/providers/commercetools/src/test/cart.provider.spec.ts +0 -199
- package/providers/commercetools/src/test/category.provider.spec.ts +0 -168
- package/providers/commercetools/src/test/checkout.provider.spec.ts +0 -312
- package/providers/commercetools/src/test/identity.provider.spec.ts +0 -88
- package/providers/commercetools/src/test/inventory.provider.spec.ts +0 -41
- package/providers/commercetools/src/test/price.provider.spec.ts +0 -81
- package/providers/commercetools/src/test/product.provider.spec.ts +0 -80
- package/providers/commercetools/src/test/profile.provider.spec.ts +0 -49
- package/providers/commercetools/src/test/search.provider.spec.ts +0 -61
- package/providers/commercetools/src/test/store.provider.spec.ts +0 -37
- package/providers/fake/jest.config.cjs +0 -10
- package/providers/fake/src/providers/search.provider.ts +0 -132
|
@@ -1,70 +1,92 @@
|
|
|
1
|
+
import { ClientBuilder } from '@commercetools/ts-client';
|
|
1
2
|
import {
|
|
2
|
-
|
|
3
|
-
type
|
|
4
|
-
|
|
5
|
-
type TokenStore,
|
|
6
|
-
} from '@commercetools/ts-client';
|
|
7
|
-
import { createApiBuilderFromCtpClient } from '@commercetools/platform-sdk';
|
|
3
|
+
createApiBuilderFromCtpClient,
|
|
4
|
+
type ApiRoot,
|
|
5
|
+
} from '@commercetools/platform-sdk';
|
|
8
6
|
import type { CommercetoolsConfiguration } from '../schema/configuration.schema.js';
|
|
9
7
|
import { randomUUID } from 'crypto';
|
|
10
8
|
import {
|
|
11
9
|
AnonymousIdentitySchema,
|
|
12
|
-
GuestIdentitySchema,
|
|
13
10
|
RegisteredIdentitySchema,
|
|
11
|
+
type AnonymousIdentity,
|
|
12
|
+
type GuestIdentity,
|
|
13
|
+
type RegisteredIdentity,
|
|
14
14
|
type RequestContext,
|
|
15
15
|
} from '@reactionary/core';
|
|
16
16
|
import * as crypto from 'crypto';
|
|
17
|
-
import createDebug from 'debug'
|
|
18
|
-
|
|
17
|
+
import createDebug from 'debug';
|
|
18
|
+
import { RequestContextTokenCache } from './token-cache.js';
|
|
19
|
+
const debug = createDebug('reactionary:commercetools');
|
|
19
20
|
|
|
21
|
+
export class CommercetoolsAPI {
|
|
22
|
+
protected config: CommercetoolsConfiguration;
|
|
23
|
+
protected context: RequestContext;
|
|
24
|
+
protected cache: RequestContextTokenCache;
|
|
25
|
+
protected client: Promise<ApiRoot> | undefined;
|
|
26
|
+
protected adminClient: Promise<ApiRoot> | undefined;
|
|
20
27
|
|
|
28
|
+
constructor(config: CommercetoolsConfiguration, context: RequestContext) {
|
|
29
|
+
this.config = config;
|
|
30
|
+
this.context = context;
|
|
31
|
+
this.cache = new RequestContextTokenCache(this.context);
|
|
32
|
+
}
|
|
21
33
|
|
|
34
|
+
public async getClient() {
|
|
35
|
+
if (!this.client) {
|
|
36
|
+
this.client = this.createClient();
|
|
37
|
+
}
|
|
22
38
|
|
|
23
|
-
|
|
24
|
-
|
|
39
|
+
return this.client;
|
|
40
|
+
}
|
|
25
41
|
|
|
26
|
-
public async
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
42
|
+
public async getAdminClient() {
|
|
43
|
+
if (!this.adminClient) {
|
|
44
|
+
this.adminClient = this.createAdminClient();
|
|
45
|
+
}
|
|
30
46
|
|
|
31
|
-
return
|
|
32
|
-
refreshToken: identity.refresh_token,
|
|
33
|
-
token: identity.token || '',
|
|
34
|
-
expirationTime: identity.expiry.getTime(),
|
|
35
|
-
};
|
|
47
|
+
return this.adminClient;
|
|
36
48
|
}
|
|
37
49
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
50
|
+
protected async createAdminClient() {
|
|
51
|
+
let builder = this.createBaseClientBuilder();
|
|
52
|
+
builder = builder.withAnonymousSessionFlow({
|
|
53
|
+
credentials: {
|
|
54
|
+
clientId: this.config.clientId,
|
|
55
|
+
clientSecret: this.config.clientSecret,
|
|
56
|
+
},
|
|
57
|
+
host: this.config.authUrl,
|
|
58
|
+
projectKey: this.config.projectKey,
|
|
59
|
+
});
|
|
43
60
|
|
|
44
|
-
|
|
45
|
-
identity.token = cache.token;
|
|
46
|
-
identity.expiry = new Date(cache.expirationTime);
|
|
61
|
+
return createApiBuilderFromCtpClient(builder.build());
|
|
47
62
|
}
|
|
48
|
-
}
|
|
49
63
|
|
|
64
|
+
protected async createClient() {
|
|
65
|
+
let session = await this.cache.get();
|
|
66
|
+
const isNewSession = !session || !session.refreshToken;
|
|
50
67
|
|
|
68
|
+
if (isNewSession) {
|
|
69
|
+
await this.becomeGuest();
|
|
51
70
|
|
|
52
|
-
|
|
53
|
-
|
|
71
|
+
session = await this.cache.get();
|
|
72
|
+
}
|
|
54
73
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
74
|
+
let builder = this.createBaseClientBuilder();
|
|
75
|
+
builder = builder.withRefreshTokenFlow({
|
|
76
|
+
credentials: {
|
|
77
|
+
clientId: this.config.clientId,
|
|
78
|
+
clientSecret: this.config.clientSecret,
|
|
79
|
+
},
|
|
80
|
+
host: this.config.authUrl,
|
|
81
|
+
projectKey: this.config.projectKey,
|
|
82
|
+
refreshToken: session?.refreshToken || '',
|
|
83
|
+
tokenCache: this.cache,
|
|
84
|
+
});
|
|
58
85
|
|
|
59
|
-
|
|
60
|
-
return this.createClient(reqCtx);
|
|
86
|
+
return createApiBuilderFromCtpClient(builder.build());
|
|
61
87
|
}
|
|
62
88
|
|
|
63
|
-
public async register(
|
|
64
|
-
username: string,
|
|
65
|
-
password: string,
|
|
66
|
-
reqCtx: RequestContext
|
|
67
|
-
) {
|
|
89
|
+
public async register(username: string, password: string) {
|
|
68
90
|
const registrationBuilder =
|
|
69
91
|
this.createBaseClientBuilder().withAnonymousSessionFlow({
|
|
70
92
|
host: this.config.authUrl,
|
|
@@ -92,19 +114,13 @@ export class CommercetoolsClient {
|
|
|
92
114
|
})
|
|
93
115
|
.execute();
|
|
94
116
|
|
|
95
|
-
const login = await this.login(username, password
|
|
117
|
+
const login = await this.login(username, password);
|
|
96
118
|
|
|
97
119
|
return login;
|
|
98
120
|
}
|
|
99
121
|
|
|
100
|
-
public async login(
|
|
101
|
-
|
|
102
|
-
password: string,
|
|
103
|
-
reqCtx: RequestContext
|
|
104
|
-
) {
|
|
105
|
-
const cache = new RequestContextTokenCache(reqCtx);
|
|
106
|
-
|
|
107
|
-
const loginBuilder = this.createBaseClientBuilder().withPasswordFlow({
|
|
122
|
+
public async login(username: string, password: string) {
|
|
123
|
+
const loginBuilder = this.createBaseClientBuilder().withPasswordFlow({
|
|
108
124
|
host: this.config.authUrl,
|
|
109
125
|
projectKey: this.config.projectKey,
|
|
110
126
|
credentials: {
|
|
@@ -112,7 +128,7 @@ export class CommercetoolsClient {
|
|
|
112
128
|
clientSecret: this.config.clientSecret,
|
|
113
129
|
user: { username, password },
|
|
114
130
|
},
|
|
115
|
-
tokenCache: cache,
|
|
131
|
+
tokenCache: this.cache,
|
|
116
132
|
scopes: this.config.scopes,
|
|
117
133
|
});
|
|
118
134
|
|
|
@@ -130,78 +146,136 @@ export class CommercetoolsClient {
|
|
|
130
146
|
})
|
|
131
147
|
.execute();
|
|
132
148
|
|
|
133
|
-
|
|
134
|
-
|
|
149
|
+
const self = await loginClient
|
|
150
|
+
.withProjectKey({ projectKey: this.config.projectKey })
|
|
151
|
+
.me()
|
|
152
|
+
.get({})
|
|
153
|
+
.execute();
|
|
154
|
+
|
|
155
|
+
return RegisteredIdentitySchema.parse({
|
|
135
156
|
type: 'Registered',
|
|
136
|
-
logonId: username,
|
|
137
157
|
id: {
|
|
138
|
-
userId:
|
|
158
|
+
userId: self.body.id,
|
|
139
159
|
},
|
|
140
160
|
});
|
|
161
|
+
}
|
|
141
162
|
|
|
142
|
-
|
|
163
|
+
public async logout() {
|
|
164
|
+
await this.cache.set({ token: '', refreshToken: '', expirationTime: 0 });
|
|
165
|
+
|
|
166
|
+
// TODO: We could do token revocation here, if we wanted to. The above simply whacks the session.
|
|
167
|
+
const identity = {
|
|
168
|
+
type: 'Anonymous'
|
|
169
|
+
} satisfies AnonymousIdentity;
|
|
170
|
+
return identity;
|
|
143
171
|
}
|
|
144
172
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
173
|
+
// FIXME: This can fail if the short-lived access token has expired. In other words, probably missing a token refresh.
|
|
174
|
+
public async introspect(): Promise<
|
|
175
|
+
AnonymousIdentity | GuestIdentity | RegisteredIdentity
|
|
176
|
+
> {
|
|
177
|
+
const session = await this.cache.get();
|
|
148
178
|
|
|
149
|
-
|
|
179
|
+
if (!session || !session.token) {
|
|
180
|
+
const identity = {
|
|
181
|
+
type: 'Anonymous'
|
|
182
|
+
} satisfies AnonymousIdentity;
|
|
150
183
|
|
|
151
|
-
|
|
184
|
+
return identity;
|
|
185
|
+
}
|
|
152
186
|
|
|
153
|
-
|
|
154
|
-
|
|
187
|
+
const authHeader =
|
|
188
|
+
'Basic ' +
|
|
189
|
+
Buffer.from(
|
|
190
|
+
`${this.config.clientId}:${this.config.clientSecret}`
|
|
191
|
+
).toString('base64');
|
|
192
|
+
const introspectionUrl = `${this.config.authUrl}/oauth/introspect`;
|
|
193
|
+
|
|
194
|
+
const response = await fetch(introspectionUrl, {
|
|
195
|
+
method: 'POST',
|
|
196
|
+
headers: {
|
|
197
|
+
Authorization: authHeader,
|
|
198
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
199
|
+
},
|
|
200
|
+
body: new URLSearchParams({
|
|
201
|
+
token: session.token,
|
|
202
|
+
}),
|
|
203
|
+
});
|
|
155
204
|
|
|
156
|
-
protected createClient(reqCtx: RequestContext) {
|
|
157
|
-
const cache = new RequestContextTokenCache(reqCtx);
|
|
158
205
|
|
|
159
|
-
|
|
160
|
-
|
|
206
|
+
const body = await response.json();
|
|
207
|
+
if (!body) {
|
|
208
|
+
return AnonymousIdentitySchema.parse({});
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const scopes: string = body.scope + '';
|
|
212
|
+
|
|
213
|
+
// FIXME: Map unmapped user_id...
|
|
214
|
+
if (scopes.indexOf('anonymous_id') > -1) {
|
|
215
|
+
const s = scopes.split(' ');
|
|
216
|
+
const idScope = s.find((x) => x.startsWith('anonymous_id'));
|
|
217
|
+
const id = idScope?.split(':')[1] || '';
|
|
218
|
+
const identity = {
|
|
161
219
|
id: {
|
|
162
|
-
userId:
|
|
220
|
+
userId: id,
|
|
163
221
|
},
|
|
164
222
|
type: 'Guest',
|
|
165
|
-
}
|
|
166
|
-
}
|
|
223
|
+
} satisfies GuestIdentity;
|
|
167
224
|
|
|
168
|
-
|
|
169
|
-
|
|
225
|
+
return identity;
|
|
226
|
+
}
|
|
170
227
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
},
|
|
180
|
-
tokenCache: cache,
|
|
181
|
-
});
|
|
182
|
-
} else {
|
|
183
|
-
builder = builder.withRefreshTokenFlow({
|
|
184
|
-
credentials: {
|
|
185
|
-
clientId: this.config.clientId,
|
|
186
|
-
clientSecret: this.config.clientSecret,
|
|
228
|
+
// FIXME: Map unmapped user_id...
|
|
229
|
+
if (scopes.indexOf('customer_id') > -1) {
|
|
230
|
+
const s = scopes.split(' ');
|
|
231
|
+
const idScope = s.find((x: any) => x.startsWith('customer_id'));
|
|
232
|
+
const id = idScope?.split(':')[1] || '';
|
|
233
|
+
const identity = {
|
|
234
|
+
id: {
|
|
235
|
+
userId: id,
|
|
187
236
|
},
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
});
|
|
237
|
+
type: 'Registered',
|
|
238
|
+
} satisfies RegisteredIdentity;
|
|
239
|
+
|
|
240
|
+
return identity;
|
|
193
241
|
}
|
|
194
242
|
|
|
195
|
-
return
|
|
243
|
+
return {
|
|
244
|
+
type: 'Anonymous',
|
|
245
|
+
} satisfies AnonymousIdentity;
|
|
196
246
|
}
|
|
197
247
|
|
|
248
|
+
protected async becomeGuest() {
|
|
249
|
+
const credentials = Buffer.from(
|
|
250
|
+
`${this.config.clientId}:${this.config.clientSecret}`
|
|
251
|
+
).toString('base64');
|
|
252
|
+
|
|
253
|
+
// FIXME: Missing scope-down from .env scopes list
|
|
254
|
+
const response = await fetch(
|
|
255
|
+
`${this.config.authUrl}/oauth/${this.config.projectKey}/anonymous/token?grant_type=client_credentials`,
|
|
256
|
+
{
|
|
257
|
+
method: 'POST',
|
|
258
|
+
headers: {
|
|
259
|
+
Authorization: `Basic ${credentials}`,
|
|
260
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
261
|
+
},
|
|
262
|
+
body: new URLSearchParams({
|
|
263
|
+
grant_type: 'client_credentials',
|
|
264
|
+
}),
|
|
265
|
+
}
|
|
266
|
+
);
|
|
198
267
|
|
|
268
|
+
const result = await response.json();
|
|
199
269
|
|
|
270
|
+
this.cache.set({
|
|
271
|
+
expirationTime:
|
|
272
|
+
Date.now() + Number(result.expires_in) * 1000 - 5 * 60 * 1000,
|
|
273
|
+
token: result.access_token,
|
|
274
|
+
refreshToken: result.refresh_token,
|
|
275
|
+
});
|
|
276
|
+
}
|
|
200
277
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
protected createBaseClientBuilder(reqCtx?: RequestContext) {
|
|
278
|
+
protected createBaseClientBuilder() {
|
|
205
279
|
let builder = new ClientBuilder()
|
|
206
280
|
.withProjectKey(this.config.projectKey)
|
|
207
281
|
.withQueueMiddleware({
|
|
@@ -237,7 +311,12 @@ export class CommercetoolsClient {
|
|
|
237
311
|
httpClient: fetch,
|
|
238
312
|
});
|
|
239
313
|
|
|
240
|
-
const correlationId =
|
|
314
|
+
const correlationId =
|
|
315
|
+
this.context.correlationId ||
|
|
316
|
+
'REACTIONARY-' +
|
|
317
|
+
(typeof crypto !== 'undefined' && 'randomUUID' in crypto
|
|
318
|
+
? crypto.randomUUID()
|
|
319
|
+
: randomUUID());
|
|
241
320
|
builder = builder.withCorrelationIdMiddleware({
|
|
242
321
|
generate: () => correlationId,
|
|
243
322
|
});
|
|
@@ -1,88 +1,144 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
Cache,
|
|
3
|
-
ProductProvider,
|
|
4
|
-
SearchProvider,
|
|
5
|
-
IdentityProvider,
|
|
6
|
-
CartProvider,
|
|
7
|
-
InventoryProvider,
|
|
8
|
-
PriceProvider,
|
|
9
|
-
CategoryProvider,
|
|
10
|
-
StoreProvider,
|
|
11
|
-
CheckoutProvider,
|
|
12
|
-
OrderProvider
|
|
13
|
-
} from "@reactionary/core";
|
|
1
|
+
import type { Cache, RequestContext, Client, ClientFromCapabilities } from '@reactionary/core';
|
|
14
2
|
import {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
ProductSchema,
|
|
20
|
-
SearchResultSchema,
|
|
21
|
-
CategorySchema,
|
|
22
|
-
CheckoutSchema
|
|
23
|
-
} from "@reactionary/core";
|
|
24
|
-
import type { CommercetoolsCapabilities } from "../schema/capabilities.schema.js";
|
|
25
|
-
import { CommercetoolsSearchProvider } from "../providers/search.provider.js";
|
|
3
|
+
CommercetoolsCapabilitiesSchema,
|
|
4
|
+
type CommercetoolsCapabilities,
|
|
5
|
+
} from '../schema/capabilities.schema.js';
|
|
6
|
+
import { CommercetoolsSearchProvider } from '../providers/product-search.provider.js';
|
|
26
7
|
import { CommercetoolsProductProvider } from '../providers/product.provider.js';
|
|
27
|
-
import
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
import {
|
|
32
|
-
import {
|
|
33
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
CommercetoolsConfigurationSchema,
|
|
10
|
+
type CommercetoolsConfiguration,
|
|
11
|
+
} from '../schema/configuration.schema.js';
|
|
12
|
+
import { CommercetoolsIdentityProvider } from '../providers/identity.provider.js';
|
|
13
|
+
import { CommercetoolsCartProvider } from '../providers/cart.provider.js';
|
|
14
|
+
import { CommercetoolsInventoryProvider } from '../providers/inventory.provider.js';
|
|
15
|
+
import { CommercetoolsPriceProvider } from '../providers/price.provider.js';
|
|
16
|
+
import { CommercetoolsCategoryProvider } from '../providers/category.provider.js';
|
|
17
|
+
import {
|
|
18
|
+
CommercetoolsCheckoutProvider,
|
|
19
|
+
CommercetoolsOrderProvider,
|
|
20
|
+
CommercetoolsOrderSearchProvider,
|
|
21
|
+
CommercetoolsProfileProvider,
|
|
22
|
+
CommercetoolsStoreProvider,
|
|
23
|
+
} from '../providers/index.js';
|
|
24
|
+
import { CommercetoolsAPI } from './client.js';
|
|
25
|
+
|
|
26
|
+
export function withCommercetoolsCapabilities<
|
|
27
|
+
T extends CommercetoolsCapabilities
|
|
28
|
+
>(configuration: CommercetoolsConfiguration, capabilities: T) {
|
|
29
|
+
return (cache: Cache, context: RequestContext): ClientFromCapabilities<T> => {
|
|
30
|
+
const client: any = {};
|
|
31
|
+
const config = CommercetoolsConfigurationSchema.parse(configuration);
|
|
32
|
+
const caps = CommercetoolsCapabilitiesSchema.parse(capabilities);
|
|
33
|
+
const commercetoolsApi = new CommercetoolsAPI(config, context);
|
|
34
|
+
|
|
35
|
+
if (caps.product) {
|
|
36
|
+
client.product = new CommercetoolsProductProvider(
|
|
37
|
+
config,
|
|
38
|
+
cache,
|
|
39
|
+
context,
|
|
40
|
+
commercetoolsApi
|
|
41
|
+
);
|
|
42
|
+
}
|
|
34
43
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
(T['store'] extends true ? { store: StoreProvider } : object) &
|
|
44
|
-
(T['order'] extends true ? { order: OrderProvider } : object) &
|
|
45
|
-
(T['checkout'] extends true ? { checkout: CheckoutProvider } : object) ;
|
|
46
|
-
export function withCommercetoolsCapabilities<T extends CommercetoolsCapabilities>(
|
|
47
|
-
configuration: CommercetoolsConfiguration,
|
|
48
|
-
capabilities: T
|
|
49
|
-
) {
|
|
50
|
-
return (cache: Cache): CommercetoolsClient<T> => {
|
|
51
|
-
const client: any = {};
|
|
44
|
+
if (caps.profile) {
|
|
45
|
+
client.profile = new CommercetoolsProfileProvider(
|
|
46
|
+
config,
|
|
47
|
+
cache,
|
|
48
|
+
context,
|
|
49
|
+
commercetoolsApi
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
if (caps.productSearch) {
|
|
54
|
+
client.productSearch = new CommercetoolsSearchProvider(
|
|
55
|
+
config,
|
|
56
|
+
cache,
|
|
57
|
+
context,
|
|
58
|
+
commercetoolsApi
|
|
59
|
+
);
|
|
60
|
+
}
|
|
56
61
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
62
|
+
if (caps.identity) {
|
|
63
|
+
client.identity = new CommercetoolsIdentityProvider(
|
|
64
|
+
config,
|
|
65
|
+
cache,
|
|
66
|
+
context,
|
|
67
|
+
commercetoolsApi
|
|
68
|
+
);
|
|
69
|
+
}
|
|
60
70
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
71
|
+
if (caps.cart) {
|
|
72
|
+
client.cart = new CommercetoolsCartProvider(
|
|
73
|
+
config,
|
|
74
|
+
cache,
|
|
75
|
+
context,
|
|
76
|
+
commercetoolsApi
|
|
77
|
+
);
|
|
78
|
+
}
|
|
64
79
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
80
|
+
if (caps.inventory) {
|
|
81
|
+
client.inventory = new CommercetoolsInventoryProvider(
|
|
82
|
+
config,
|
|
83
|
+
cache,
|
|
84
|
+
context,
|
|
85
|
+
commercetoolsApi
|
|
86
|
+
);
|
|
87
|
+
}
|
|
68
88
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
89
|
+
if (caps.price) {
|
|
90
|
+
client.price = new CommercetoolsPriceProvider(
|
|
91
|
+
config,
|
|
92
|
+
cache,
|
|
93
|
+
context,
|
|
94
|
+
commercetoolsApi
|
|
95
|
+
);
|
|
96
|
+
}
|
|
72
97
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
98
|
+
if (caps.category) {
|
|
99
|
+
client.category = new CommercetoolsCategoryProvider(
|
|
100
|
+
config,
|
|
101
|
+
cache,
|
|
102
|
+
context,
|
|
103
|
+
commercetoolsApi
|
|
104
|
+
);
|
|
105
|
+
}
|
|
76
106
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
107
|
+
if (caps.checkout) {
|
|
108
|
+
client.checkout = new CommercetoolsCheckoutProvider(
|
|
109
|
+
config,
|
|
110
|
+
cache,
|
|
111
|
+
context,
|
|
112
|
+
commercetoolsApi
|
|
113
|
+
);
|
|
114
|
+
}
|
|
80
115
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
116
|
+
if (caps.store) {
|
|
117
|
+
client.store = new CommercetoolsStoreProvider(
|
|
118
|
+
config,
|
|
119
|
+
cache,
|
|
120
|
+
context,
|
|
121
|
+
commercetoolsApi
|
|
122
|
+
);
|
|
123
|
+
}
|
|
84
124
|
|
|
125
|
+
if (caps.order) {
|
|
126
|
+
client.store = new CommercetoolsOrderProvider(
|
|
127
|
+
config,
|
|
128
|
+
cache,
|
|
129
|
+
context,
|
|
130
|
+
commercetoolsApi
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
if (caps.orderSearch) {
|
|
134
|
+
client.orderSearch = new CommercetoolsOrderSearchProvider(
|
|
135
|
+
config,
|
|
136
|
+
cache,
|
|
137
|
+
context,
|
|
138
|
+
commercetoolsApi
|
|
139
|
+
);
|
|
140
|
+
}
|
|
85
141
|
|
|
86
|
-
|
|
87
|
-
|
|
142
|
+
return client;
|
|
143
|
+
};
|
|
88
144
|
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { TokenCache, TokenCacheOptions, TokenStore } from "@commercetools/ts-client";
|
|
2
|
+
import type { RequestContext } from "@reactionary/core";
|
|
3
|
+
import { CommercetoolsSessionSchema } from "../schema/session.schema.js";
|
|
4
|
+
|
|
5
|
+
export const PROVIDER_COMMERCETOOLS_SESSION_KEY = 'PROVIDER_COMMERCETOOLS';
|
|
6
|
+
export class RequestContextTokenCache implements TokenCache {
|
|
7
|
+
constructor(protected context: RequestContext) {}
|
|
8
|
+
|
|
9
|
+
public async get(
|
|
10
|
+
tokenCacheOptions?: TokenCacheOptions
|
|
11
|
+
): Promise<TokenStore | undefined> {
|
|
12
|
+
const session = CommercetoolsSessionSchema.parse(
|
|
13
|
+
this.context.session[PROVIDER_COMMERCETOOLS_SESSION_KEY] || {}
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
if (!session) {
|
|
17
|
+
return {
|
|
18
|
+
refreshToken: undefined,
|
|
19
|
+
token: '',
|
|
20
|
+
expirationTime: new Date().getTime(),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
refreshToken: session.refreshToken,
|
|
26
|
+
token: session.token,
|
|
27
|
+
expirationTime: session.expirationTime,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
public async set(
|
|
32
|
+
cache: TokenStore,
|
|
33
|
+
tokenCacheOptions?: TokenCacheOptions
|
|
34
|
+
): Promise<void> {
|
|
35
|
+
const session = CommercetoolsSessionSchema.parse(
|
|
36
|
+
this.context.session[PROVIDER_COMMERCETOOLS_SESSION_KEY] || {}
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
this.context.session[PROVIDER_COMMERCETOOLS_SESSION_KEY] = session;
|
|
40
|
+
|
|
41
|
+
session.refreshToken = cache.refreshToken;
|
|
42
|
+
session.token = cache.token;
|
|
43
|
+
session.expirationTime = cache.expirationTime;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -4,9 +4,10 @@ export * from './core/initialize.js';
|
|
|
4
4
|
export * from './providers/cart.provider.js';
|
|
5
5
|
export * from './providers/identity.provider.js';
|
|
6
6
|
export * from './providers/inventory.provider.js';
|
|
7
|
+
export * from './providers/order-search.provider.js';
|
|
7
8
|
export * from './providers/price.provider.js';
|
|
8
9
|
export * from './providers/product.provider.js';
|
|
9
|
-
export * from './providers/search.provider.js';
|
|
10
|
+
export * from './providers/product-search.provider.js';
|
|
10
11
|
|
|
11
12
|
export * from './schema/capabilities.schema.js';
|
|
12
|
-
export * from './schema/configuration.schema.js';
|
|
13
|
+
export * from './schema/configuration.schema.js';
|