@reactionary/provider-commercetools 0.0.62 → 0.0.64

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/core/client.js CHANGED
@@ -1,6 +1,4 @@
1
- import {
2
- ClientBuilder
3
- } from "@commercetools/ts-client";
1
+ import { ClientBuilder } from "@commercetools/ts-client";
4
2
  import { createApiBuilderFromCtpClient } from "@commercetools/platform-sdk";
5
3
  import { randomUUID } from "crypto";
6
4
  import {
@@ -10,34 +8,41 @@ import {
10
8
  } from "@reactionary/core";
11
9
  import * as crypto from "crypto";
12
10
  import createDebug from "debug";
11
+ import { RequestContextTokenCache } from "./token-cache.js";
13
12
  const debug = createDebug("reactionary:commercetools");
14
- class RequestContextTokenCache {
15
- constructor(context) {
16
- this.context = context;
17
- }
18
- async get(tokenCacheOptions) {
19
- const identity = this.context.identity;
20
- return {
21
- refreshToken: identity.refresh_token,
22
- token: identity.token || "",
23
- expirationTime: identity.expiry.getTime()
24
- };
25
- }
26
- async set(cache, tokenCacheOptions) {
27
- const identity = this.context.identity;
28
- identity.refresh_token = cache.refreshToken;
29
- identity.token = cache.token;
30
- identity.expiry = new Date(cache.expirationTime);
31
- }
32
- }
33
13
  class CommercetoolsClient {
34
- constructor(config) {
14
+ constructor(config, context) {
35
15
  this.config = config;
16
+ this.context = context;
17
+ this.cache = new RequestContextTokenCache(this.context);
36
18
  }
37
- async getClient(reqCtx) {
38
- return this.createClient(reqCtx);
19
+ async getClient() {
20
+ if (!this.client) {
21
+ this.client = this.createClient();
22
+ }
23
+ return this.client;
24
+ }
25
+ async createClient() {
26
+ let session = await this.cache.get();
27
+ const isNewSession = !session || session.token.length === 0;
28
+ if (isNewSession) {
29
+ await this.becomeGuest();
30
+ session = await this.cache.get();
31
+ }
32
+ let builder = this.createBaseClientBuilder();
33
+ builder = builder.withRefreshTokenFlow({
34
+ credentials: {
35
+ clientId: this.config.clientId,
36
+ clientSecret: this.config.clientSecret
37
+ },
38
+ host: this.config.authUrl,
39
+ projectKey: this.config.projectKey,
40
+ refreshToken: session.refreshToken || "",
41
+ tokenCache: this.cache
42
+ });
43
+ return createApiBuilderFromCtpClient(builder.build());
39
44
  }
40
- async register(username, password, reqCtx) {
45
+ async register(username, password) {
41
46
  const registrationBuilder = this.createBaseClientBuilder().withAnonymousSessionFlow({
42
47
  host: this.config.authUrl,
43
48
  projectKey: this.config.projectKey,
@@ -56,11 +61,10 @@ class CommercetoolsClient {
56
61
  password
57
62
  }
58
63
  }).execute();
59
- const login = await this.login(username, password, reqCtx);
64
+ const login = await this.login(username, password);
60
65
  return login;
61
66
  }
62
- async login(username, password, reqCtx) {
63
- const cache = new RequestContextTokenCache(reqCtx);
67
+ async login(username, password) {
64
68
  const loginBuilder = this.createBaseClientBuilder().withPasswordFlow({
65
69
  host: this.config.authUrl,
66
70
  projectKey: this.config.projectKey,
@@ -69,7 +73,7 @@ class CommercetoolsClient {
69
73
  clientSecret: this.config.clientSecret,
70
74
  user: { username, password }
71
75
  },
72
- tokenCache: cache,
76
+ tokenCache: this.cache,
73
77
  scopes: this.config.scopes
74
78
  });
75
79
  const loginClient = createApiBuilderFromCtpClient(loginBuilder.build());
@@ -79,60 +83,71 @@ class CommercetoolsClient {
79
83
  password
80
84
  }
81
85
  }).execute();
82
- reqCtx.identity = RegisteredIdentitySchema.parse({
83
- ...reqCtx.identity,
86
+ return RegisteredIdentitySchema.parse({
84
87
  type: "Registered",
85
- logonId: username,
86
88
  id: {
87
89
  userId: login.body.customer.id
88
90
  }
89
91
  });
90
- return reqCtx.identity;
91
92
  }
92
- async logout(reqCtx) {
93
- const cache = new RequestContextTokenCache(reqCtx);
94
- await cache.set({ token: "", refreshToken: "", expirationTime: 0 });
95
- reqCtx.identity = AnonymousIdentitySchema.parse({});
96
- return reqCtx.identity;
93
+ async logout() {
94
+ await this.cache.set({ token: "", refreshToken: "", expirationTime: 0 });
95
+ return AnonymousIdentitySchema.parse({});
97
96
  }
98
- createClient(reqCtx) {
99
- const cache = new RequestContextTokenCache(reqCtx);
100
- if (reqCtx.identity.type === "Anonymous") {
101
- reqCtx.identity = GuestIdentitySchema.parse({
102
- id: {
103
- userId: crypto.randomUUID().toString()
104
- },
105
- type: "Guest"
106
- });
97
+ async introspect() {
98
+ const session = await this.cache.get();
99
+ if (!session || !session.token) {
100
+ return AnonymousIdentitySchema.parse({});
107
101
  }
108
- const identity = reqCtx.identity;
109
- let builder = this.createBaseClientBuilder(reqCtx);
110
- if (!identity.token || !identity.refresh_token) {
111
- builder = builder.withAnonymousSessionFlow({
112
- host: this.config.authUrl,
113
- projectKey: this.config.projectKey,
114
- credentials: {
115
- clientId: this.config.clientId,
116
- clientSecret: this.config.clientSecret,
117
- anonymousId: identity.id.userId
118
- },
119
- tokenCache: cache
120
- });
121
- } else {
122
- builder = builder.withRefreshTokenFlow({
123
- credentials: {
124
- clientId: this.config.clientId,
125
- clientSecret: this.config.clientSecret
126
- },
127
- host: this.config.authUrl,
128
- projectKey: this.config.projectKey,
129
- refreshToken: identity.refresh_token || "",
130
- tokenCache: cache
131
- });
102
+ const authHeader = "Basic " + Buffer.from(
103
+ `${this.config.clientId}:${this.config.clientSecret}`
104
+ ).toString("base64");
105
+ const introspectionUrl = `${this.config.authUrl}/oauth/introspect`;
106
+ const response = await fetch(introspectionUrl, {
107
+ method: "POST",
108
+ headers: {
109
+ Authorization: authHeader,
110
+ "Content-Type": "application/x-www-form-urlencoded"
111
+ },
112
+ body: new URLSearchParams({
113
+ token: session.token
114
+ })
115
+ });
116
+ const body = await response.json();
117
+ const scopes = body.scope;
118
+ if (scopes.indexOf("anonymous_id") > -1) {
119
+ return GuestIdentitySchema.parse({});
132
120
  }
133
- return createApiBuilderFromCtpClient(builder.build());
121
+ if (scopes.indexOf("customer_id") > -1) {
122
+ return RegisteredIdentitySchema.parse({});
123
+ }
124
+ return AnonymousIdentitySchema.parse({});
125
+ }
126
+ async becomeGuest() {
127
+ const credentials = Buffer.from(
128
+ `${this.config.clientId}:${this.config.clientSecret}`
129
+ ).toString("base64");
130
+ const response = await fetch(
131
+ `${this.config.authUrl}/oauth/${this.config.projectKey}/anonymous/token?grant_type=client_credentials`,
132
+ {
133
+ method: "POST",
134
+ headers: {
135
+ Authorization: `Basic ${credentials}`,
136
+ "Content-Type": "application/x-www-form-urlencoded"
137
+ },
138
+ body: new URLSearchParams({
139
+ grant_type: "client_credentials"
140
+ })
141
+ }
142
+ );
143
+ const result = await response.json();
144
+ this.cache.set({
145
+ expirationTime: (/* @__PURE__ */ new Date()).getTime() + Number(result.expires_in),
146
+ token: result.access_token,
147
+ refreshToken: result.refresh_token
148
+ });
134
149
  }
135
- createBaseClientBuilder(reqCtx) {
150
+ createBaseClientBuilder() {
136
151
  let builder = new ClientBuilder().withProjectKey(this.config.projectKey).withQueueMiddleware({
137
152
  concurrency: 20
138
153
  }).withConcurrentModificationMiddleware({
@@ -159,7 +174,7 @@ class CommercetoolsClient {
159
174
  host: this.config.apiUrl,
160
175
  httpClient: fetch
161
176
  });
162
- const correlationId = reqCtx?.correlationId || "REACTIONARY-" + (typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : randomUUID());
177
+ const correlationId = this.context.correlationId || "REACTIONARY-" + (typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : randomUUID());
163
178
  builder = builder.withCorrelationIdMiddleware({
164
179
  generate: () => correlationId
165
180
  });
@@ -170,6 +185,5 @@ class CommercetoolsClient {
170
185
  }
171
186
  }
172
187
  export {
173
- CommercetoolsClient,
174
- RequestContextTokenCache
188
+ CommercetoolsClient
175
189
  };
@@ -4,7 +4,6 @@ import {
4
4
  InventorySchema,
5
5
  PriceSchema,
6
6
  ProductSchema,
7
- ProductSearchResultSchema,
8
7
  CategorySchema,
9
8
  CheckoutSchema,
10
9
  ProductSearchResultItemSchema
@@ -17,32 +16,34 @@ import { CommercetoolsInventoryProvider } from "../providers/inventory.provider.
17
16
  import { CommercetoolsPriceProvider } from "../providers/price.provider.js";
18
17
  import { CommercetoolsCategoryProvider } from "../providers/category.provider.js";
19
18
  import { CommercetoolsCheckoutProvider } from "../providers/index.js";
19
+ import { CommercetoolsClient, CommercetoolsClient as CTCustomerClient } from "./client.js";
20
20
  function withCommercetoolsCapabilities(configuration, capabilities) {
21
- return (cache) => {
21
+ return (cache, context) => {
22
22
  const client = {};
23
+ const commercetoolsClient = new CommercetoolsClient(configuration, context);
23
24
  if (capabilities.product) {
24
- client.product = new CommercetoolsProductProvider(configuration, ProductSchema, cache);
25
+ client.product = new CommercetoolsProductProvider(configuration, ProductSchema, cache, context, commercetoolsClient);
25
26
  }
26
27
  if (capabilities.productSearch) {
27
- client.productSearch = new CommercetoolsSearchProvider(configuration, ProductSearchResultItemSchema, cache);
28
+ client.productSearch = new CommercetoolsSearchProvider(configuration, ProductSearchResultItemSchema, cache, context, commercetoolsClient);
28
29
  }
29
30
  if (capabilities.identity) {
30
- client.identity = new CommercetoolsIdentityProvider(configuration, IdentitySchema, cache);
31
+ client.identity = new CommercetoolsIdentityProvider(configuration, IdentitySchema, cache, context, commercetoolsClient);
31
32
  }
32
33
  if (capabilities.cart) {
33
- client.cart = new CommercetoolsCartProvider(configuration, CartSchema, cache);
34
+ client.cart = new CommercetoolsCartProvider(configuration, CartSchema, cache, context, commercetoolsClient);
34
35
  }
35
36
  if (capabilities.inventory) {
36
- client.inventory = new CommercetoolsInventoryProvider(configuration, InventorySchema, cache);
37
+ client.inventory = new CommercetoolsInventoryProvider(configuration, InventorySchema, cache, context, commercetoolsClient);
37
38
  }
38
39
  if (capabilities.price) {
39
- client.price = new CommercetoolsPriceProvider(configuration, PriceSchema, cache);
40
+ client.price = new CommercetoolsPriceProvider(configuration, PriceSchema, cache, context, commercetoolsClient);
40
41
  }
41
42
  if (capabilities.category) {
42
- client.category = new CommercetoolsCategoryProvider(configuration, CategorySchema, cache);
43
+ client.category = new CommercetoolsCategoryProvider(configuration, CategorySchema, cache, context, commercetoolsClient);
43
44
  }
44
45
  if (capabilities.checkout) {
45
- client.checkout = new CommercetoolsCheckoutProvider(configuration, CheckoutSchema, cache);
46
+ client.checkout = new CommercetoolsCheckoutProvider(configuration, CheckoutSchema, cache, context, commercetoolsClient);
46
47
  }
47
48
  return client;
48
49
  };
@@ -0,0 +1,35 @@
1
+ import { CommercetoolsSessionSchema } from "../schema/session.schema.js";
2
+ class RequestContextTokenCache {
3
+ constructor(context) {
4
+ this.context = context;
5
+ }
6
+ async get(tokenCacheOptions) {
7
+ const session = CommercetoolsSessionSchema.parse(
8
+ this.context.session["PROVIDER_COMMERCETOOLS"] || {}
9
+ );
10
+ if (!session) {
11
+ return {
12
+ refreshToken: void 0,
13
+ token: "",
14
+ expirationTime: (/* @__PURE__ */ new Date()).getTime()
15
+ };
16
+ }
17
+ return {
18
+ refreshToken: session.refreshToken,
19
+ token: session.token,
20
+ expirationTime: session.expirationTime
21
+ };
22
+ }
23
+ async set(cache, tokenCacheOptions) {
24
+ const session = CommercetoolsSessionSchema.parse(
25
+ this.context.session["PROVIDER_COMMERCETOOLS"] || {}
26
+ );
27
+ this.context.session["PROVIDER_COMMERCETOOLS"] = session;
28
+ session.refreshToken = cache.refreshToken;
29
+ session.token = cache.token;
30
+ session.expirationTime = cache.expirationTime;
31
+ }
32
+ }
33
+ export {
34
+ RequestContextTokenCache
35
+ };
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@reactionary/provider-commercetools",
3
- "version": "0.0.62",
3
+ "version": "0.0.64",
4
4
  "main": "index.js",
5
5
  "types": "src/index.d.ts",
6
6
  "dependencies": {
7
- "@reactionary/core": "0.0.62",
7
+ "@reactionary/core": "0.0.64",
8
8
  "debug": "^4.4.3",
9
9
  "zod": "4.1.9",
10
10
  "@commercetools/ts-client": "^4.2.1",