@viu/emporix-sdk 2.9.0 → 2.11.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 CHANGED
@@ -1,5 +1,37 @@
1
1
  # @viu/emporix-sdk
2
2
 
3
+ ## 2.11.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#114](https://github.com/viuteam/emporix-sdk/pull/114) [`ac2b2c8`](https://github.com/viuteam/emporix-sdk/commit/ac2b2c890521da017b3ef44ff15bdf6b16d69bb9) Thanks [@amnael1](https://github.com/amnael1)! - feat: invoke Emporix cloud functions
8
+
9
+ Adds `client.cloudFunctions.invoke<TRes, TReq>(functionId, { method?, path?,
10
+ body?, query?, headers? }, auth)` — a generic call to tenant cloud functions
11
+ (`/cloud-functions/{tenant}/functions/{id}[/sub]`), with GET/POST/PUT/DELETE and
12
+ service / customer / anonymous / raw auth (default anonymous). Adds the React
13
+ hooks `useInvokeCloudFunction` (mutation, any method) and `useCloudFunction`
14
+ (GET-style query with caching), both with auto-auth (customer-if-token-else-
15
+ anonymous) and an optional override.
16
+
17
+ ## 2.10.0
18
+
19
+ ### Minor Changes
20
+
21
+ - [#112](https://github.com/viuteam/emporix-sdk/pull/112) [`1f87a9b`](https://github.com/viuteam/emporix-sdk/commit/1f87a9b54ddde591716eba7427e04573113b17f9) Thanks [@amnael1](https://github.com/amnael1)! - feat: runtime currency switching
22
+
23
+ Adds `EmporixClient.setStorefrontContext({ currency, siteCode, targetLocation })`
24
+ to re-bind the anonymous price context at runtime (invalidating the anon session
25
+ so the next login re-mints with the new currency — covers the pre-cart guest
26
+ case `sessionContext.patch` cannot). Adds `useSiteContext().setCurrency(code)`,
27
+ which re-binds the context, clears the currency-bound guest cart, and PATCHes an
28
+ existing server session context. The storefront-demo gains a currency dropdown
29
+ populated from the active site's `availableCurrencies`.
30
+
31
+ On reload, the site-context `currency` now seeds from the client's configured
32
+ `context.currency` (instead of always deriving from the site default), so a
33
+ persisted currency choice is respected.
34
+
3
35
  ## 2.9.0
4
36
 
5
37
  ### Minor Changes
@@ -1,4 +1,4 @@
1
- import { C as ClientContext, b as AuthContext } from './context-DJDTlhLW.cjs';
1
+ import { C as ClientContext, b as AuthContext } from './context-CmShWI_R.cjs';
2
2
 
3
3
  type DistributionChannel = 'ASSORTMENT' | 'HOME_DELIVERY' | 'PICKUP';
4
4
  type Availability$1 = {
@@ -1,4 +1,4 @@
1
- import { C as ClientContext, b as AuthContext } from './context-DJDTlhLW.js';
1
+ import { C as ClientContext, b as AuthContext } from './context-CmShWI_R.js';
2
2
 
3
3
  type DistributionChannel = 'ASSORTMENT' | 'HOME_DELIVERY' | 'PICKUP';
4
4
  type Availability$1 = {
package/dist/cart.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { C as ClientContext, b as AuthContext } from './context-DJDTlhLW.cjs';
1
+ import { C as ClientContext, b as AuthContext } from './context-CmShWI_R.cjs';
2
2
 
3
3
  /**
4
4
  * Access control identifier that determines who can view or manage the cart.
package/dist/cart.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { C as ClientContext, b as AuthContext } from './context-DJDTlhLW.js';
1
+ import { C as ClientContext, b as AuthContext } from './context-CmShWI_R.js';
2
2
 
3
3
  /**
4
4
  * Access control identifier that determines who can view or manage the cart.
@@ -1,4 +1,4 @@
1
- import { C as ClientContext, b as AuthContext, P as PaginatedItems } from './context-DJDTlhLW.cjs';
1
+ import { C as ClientContext, b as AuthContext, P as PaginatedItems } from './context-CmShWI_R.cjs';
2
2
  import { Product } from './product.cjs';
3
3
 
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { C as ClientContext, b as AuthContext, P as PaginatedItems } from './context-DJDTlhLW.js';
1
+ import { C as ClientContext, b as AuthContext, P as PaginatedItems } from './context-CmShWI_R.js';
2
2
  import { Product } from './product.js';
3
3
 
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { C as ClientContext, b as AuthContext } from './context-DJDTlhLW.cjs';
1
+ import { C as ClientContext, b as AuthContext } from './context-CmShWI_R.cjs';
2
2
 
3
3
  /**
4
4
  * Information about the customer's address.
@@ -1,4 +1,4 @@
1
- import { C as ClientContext, b as AuthContext } from './context-DJDTlhLW.js';
1
+ import { C as ClientContext, b as AuthContext } from './context-CmShWI_R.js';
2
2
 
3
3
  /**
4
4
  * Information about the customer's address.
@@ -1,4 +1,4 @@
1
- import { C as ClientContext, b as AuthContext } from './context-DJDTlhLW.cjs';
1
+ import { C as ClientContext, b as AuthContext } from './context-CmShWI_R.cjs';
2
2
  import { L as LegalEntity, e as LegalEntityCreate, f as LegalEntityUpdate } from './types.gen-C_wOXYZB.cjs';
3
3
  export { A as AccountLimit, d as CustomerGroup, g as LegalInfo } from './types.gen-C_wOXYZB.cjs';
4
4
 
@@ -1,4 +1,4 @@
1
- import { C as ClientContext, b as AuthContext } from './context-DJDTlhLW.js';
1
+ import { C as ClientContext, b as AuthContext } from './context-CmShWI_R.js';
2
2
  import { L as LegalEntity, e as LegalEntityCreate, f as LegalEntityUpdate } from './types.gen-C_wOXYZB.js';
3
3
  export { A as AccountLimit, d as CustomerGroup, g as LegalInfo } from './types.gen-C_wOXYZB.js';
4
4
 
@@ -1,4 +1,4 @@
1
- import { C as ClientContext, b as AuthContext } from './context-DJDTlhLW.cjs';
1
+ import { C as ClientContext, b as AuthContext } from './context-CmShWI_R.cjs';
2
2
  import { C as ContactAssignment, a as ContactAssignmentCreate, b as ContactAssignmentUpdate } from './types.gen-C_wOXYZB.cjs';
3
3
 
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { C as ClientContext, b as AuthContext } from './context-DJDTlhLW.js';
1
+ import { C as ClientContext, b as AuthContext } from './context-CmShWI_R.js';
2
2
  import { C as ContactAssignment, a as ContactAssignmentCreate, b as ContactAssignmentUpdate } from './types.gen-C_wOXYZB.js';
3
3
 
4
4
  /**
@@ -3,7 +3,7 @@ type LogLevel = "trace" | "debug" | "info" | "warn" | "error" | "silent";
3
3
  /** Numeric ordering used for fast comparison. */
4
4
  declare const LEVEL: Record<LogLevel, number>;
5
5
  /** Services that bind their own logger and are independently level-controllable. */
6
- type ServiceName = "customer" | "product" | "category" | "cart" | "checkout" | "payment" | "price" | "media" | "segment" | "site" | "session-context" | "customer-management" | "iam" | "orders" | "sales-orders" | "availability" | "configuration" | "shopping-list" | "ai-rag-indexer" | "sequential-id" | "fee" | "webhook" | "schema" | "ai" | "tax" | "coupon" | "reward-points" | "brand" | "label" | "country" | "currency" | "shipping" | "returns" | "sepa-export" | "indexing" | "unit-handling" | "catalog" | "vendor" | "pick-pack" | "customer-admin" | "approval" | "http" | "auth";
6
+ type ServiceName = "customer" | "product" | "category" | "cart" | "checkout" | "payment" | "price" | "media" | "segment" | "site" | "session-context" | "customer-management" | "iam" | "orders" | "sales-orders" | "availability" | "configuration" | "shopping-list" | "ai-rag-indexer" | "sequential-id" | "fee" | "webhook" | "schema" | "ai" | "tax" | "coupon" | "reward-points" | "brand" | "label" | "country" | "currency" | "shipping" | "returns" | "sepa-export" | "indexing" | "unit-handling" | "catalog" | "vendor" | "pick-pack" | "customer-admin" | "approval" | "cloud-functions" | "http" | "auth";
7
7
  /** Arbitrary structured fields attached to a log line. */
8
8
  interface LogFields {
9
9
  [key: string]: unknown;
@@ -222,6 +222,16 @@ interface TokenProvider {
222
222
  * replaces the previous adapter.
223
223
  */
224
224
  attachAnonymousStore?(store: AnonymousSessionStore): void;
225
+ /**
226
+ * Override the storefront context (currency/site/country) used for the next
227
+ * anonymous login, then invalidate the current anonymous session so it
228
+ * re-mints with the new context. No-op for providers without anon support.
229
+ */
230
+ setAnonymousContext?(ctx: {
231
+ currency?: string;
232
+ siteCode?: string;
233
+ targetLocation?: string;
234
+ }): void;
225
235
  /**
226
236
  * Subscribe to token-refresh events. Optional — implementations may no-op.
227
237
  * Returns an unsubscribe function. `DefaultTokenProvider` emits for the
@@ -267,6 +277,7 @@ declare class DefaultTokenProvider implements TokenProvider {
267
277
  private anon;
268
278
  private anonLock;
269
279
  private anonStore?;
280
+ private contextOverride;
270
281
  private readonly refreshListeners;
271
282
  constructor(cfg: ResolvedConfig);
272
283
  onRefresh(listener: (event: {
@@ -285,6 +296,11 @@ declare class DefaultTokenProvider implements TokenProvider {
285
296
  /** Refreshes the anonymous session, preserving its sessionId. */
286
297
  refreshAnonymous(): Promise<AnonymousSession>;
287
298
  invalidateAnonymous(): void;
299
+ setAnonymousContext(ctx: {
300
+ currency?: string;
301
+ siteCode?: string;
302
+ targetLocation?: string;
303
+ }): void;
288
304
  /** Force a stale access token while keeping the refresh token + sessionId. */
289
305
  expireAnonymous(): void;
290
306
  private stripExpiry;
@@ -3,7 +3,7 @@ type LogLevel = "trace" | "debug" | "info" | "warn" | "error" | "silent";
3
3
  /** Numeric ordering used for fast comparison. */
4
4
  declare const LEVEL: Record<LogLevel, number>;
5
5
  /** Services that bind their own logger and are independently level-controllable. */
6
- type ServiceName = "customer" | "product" | "category" | "cart" | "checkout" | "payment" | "price" | "media" | "segment" | "site" | "session-context" | "customer-management" | "iam" | "orders" | "sales-orders" | "availability" | "configuration" | "shopping-list" | "ai-rag-indexer" | "sequential-id" | "fee" | "webhook" | "schema" | "ai" | "tax" | "coupon" | "reward-points" | "brand" | "label" | "country" | "currency" | "shipping" | "returns" | "sepa-export" | "indexing" | "unit-handling" | "catalog" | "vendor" | "pick-pack" | "customer-admin" | "approval" | "http" | "auth";
6
+ type ServiceName = "customer" | "product" | "category" | "cart" | "checkout" | "payment" | "price" | "media" | "segment" | "site" | "session-context" | "customer-management" | "iam" | "orders" | "sales-orders" | "availability" | "configuration" | "shopping-list" | "ai-rag-indexer" | "sequential-id" | "fee" | "webhook" | "schema" | "ai" | "tax" | "coupon" | "reward-points" | "brand" | "label" | "country" | "currency" | "shipping" | "returns" | "sepa-export" | "indexing" | "unit-handling" | "catalog" | "vendor" | "pick-pack" | "customer-admin" | "approval" | "cloud-functions" | "http" | "auth";
7
7
  /** Arbitrary structured fields attached to a log line. */
8
8
  interface LogFields {
9
9
  [key: string]: unknown;
@@ -222,6 +222,16 @@ interface TokenProvider {
222
222
  * replaces the previous adapter.
223
223
  */
224
224
  attachAnonymousStore?(store: AnonymousSessionStore): void;
225
+ /**
226
+ * Override the storefront context (currency/site/country) used for the next
227
+ * anonymous login, then invalidate the current anonymous session so it
228
+ * re-mints with the new context. No-op for providers without anon support.
229
+ */
230
+ setAnonymousContext?(ctx: {
231
+ currency?: string;
232
+ siteCode?: string;
233
+ targetLocation?: string;
234
+ }): void;
225
235
  /**
226
236
  * Subscribe to token-refresh events. Optional — implementations may no-op.
227
237
  * Returns an unsubscribe function. `DefaultTokenProvider` emits for the
@@ -267,6 +277,7 @@ declare class DefaultTokenProvider implements TokenProvider {
267
277
  private anon;
268
278
  private anonLock;
269
279
  private anonStore?;
280
+ private contextOverride;
270
281
  private readonly refreshListeners;
271
282
  constructor(cfg: ResolvedConfig);
272
283
  onRefresh(listener: (event: {
@@ -285,6 +296,11 @@ declare class DefaultTokenProvider implements TokenProvider {
285
296
  /** Refreshes the anonymous session, preserving its sessionId. */
286
297
  refreshAnonymous(): Promise<AnonymousSession>;
287
298
  invalidateAnonymous(): void;
299
+ setAnonymousContext(ctx: {
300
+ currency?: string;
301
+ siteCode?: string;
302
+ targetLocation?: string;
303
+ }): void;
288
304
  /** Force a stale access token while keeping the refresh token + sessionId. */
289
305
  expireAnonymous(): void;
290
306
  private stripExpiry;
@@ -1,4 +1,4 @@
1
- import { C as ClientContext, b as AuthContext } from './context-DJDTlhLW.cjs';
1
+ import { C as ClientContext, b as AuthContext } from './context-CmShWI_R.cjs';
2
2
 
3
3
  type AssignmentCreateRequest = {
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { C as ClientContext, b as AuthContext } from './context-DJDTlhLW.js';
1
+ import { C as ClientContext, b as AuthContext } from './context-CmShWI_R.js';
2
2
 
3
3
  type AssignmentCreateRequest = {
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { C as ClientContext, A as AnonymousSession, b as AuthContext } from './context-DJDTlhLW.cjs';
1
+ import { C as ClientContext, A as AnonymousSession, b as AuthContext } from './context-CmShWI_R.cjs';
2
2
 
3
3
  type AccountId = {
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { C as ClientContext, A as AnonymousSession, b as AuthContext } from './context-DJDTlhLW.js';
1
+ import { C as ClientContext, A as AnonymousSession, b as AuthContext } from './context-CmShWI_R.js';
2
2
 
3
3
  type AccountId = {
4
4
  /**
package/dist/index.cjs CHANGED
@@ -396,6 +396,7 @@ var DefaultTokenProvider = class {
396
396
  anon;
397
397
  anonLock;
398
398
  anonStore;
399
+ contextOverride;
399
400
  refreshListeners = /* @__PURE__ */ new Set();
400
401
  onRefresh(listener) {
401
402
  this.refreshListeners.add(listener);
@@ -508,6 +509,11 @@ var DefaultTokenProvider = class {
508
509
  this.anon = void 0;
509
510
  this.anonStore?.write(null);
510
511
  }
512
+ setAnonymousContext(ctx) {
513
+ const base = this.contextOverride ?? this.cfg.credentials.storefront?.context ?? {};
514
+ this.contextOverride = { ...base, ...ctx };
515
+ this.invalidateAnonymous();
516
+ }
511
517
  /** Force a stale access token while keeping the refresh token + sessionId. */
512
518
  expireAnonymous() {
513
519
  if (this.anon) this.anon = { ...this.anon, expiresAt: 0 };
@@ -524,7 +530,7 @@ var DefaultTokenProvider = class {
524
530
  const url = new URL(`${this.cfg.host}/customerlogin/auth/anonymous/${mode}`);
525
531
  url.searchParams.set("tenant", this.cfg.tenant);
526
532
  url.searchParams.set("client_id", sf.clientId);
527
- const c = sf.context;
533
+ const c = this.contextOverride ?? sf.context;
528
534
  if (c?.currency) url.searchParams.set("currency", c.currency);
529
535
  if (c?.siteCode) url.searchParams.set("siteCode", c.siteCode);
530
536
  if (c?.targetLocation) url.searchParams.set("targetLocation", c.targetLocation);
@@ -2896,6 +2902,28 @@ var FeeService = class {
2896
2902
  }
2897
2903
  };
2898
2904
 
2905
+ // src/services/cloud-functions.ts
2906
+ var CloudFunctionsService = class {
2907
+ constructor(ctx) {
2908
+ this.ctx = ctx;
2909
+ }
2910
+ ctx;
2911
+ base() {
2912
+ return `/cloud-functions/${this.ctx.tenant}/functions`;
2913
+ }
2914
+ async invoke(functionId, options = {}, authCtx = auth.anonymous()) {
2915
+ const sub = options.path ? `/${options.path.replace(/^\//, "")}` : "";
2916
+ return this.ctx.http.request({
2917
+ method: options.method ?? "POST",
2918
+ path: `${this.base()}/${functionId}${sub}`,
2919
+ auth: authCtx,
2920
+ ...options.body !== void 0 ? { body: options.body } : {},
2921
+ ...options.query ? { query: options.query } : {},
2922
+ ...options.headers ? { headers: options.headers } : {}
2923
+ });
2924
+ }
2925
+ };
2926
+
2899
2927
  // src/services/webhook.ts
2900
2928
  var SERVICE8 = { kind: "service" };
2901
2929
  var WebhookService = class {
@@ -5068,7 +5096,7 @@ var ApprovalService = class {
5068
5096
  };
5069
5097
 
5070
5098
  // package.json
5071
- var version = "2.9.0";
5099
+ var version = "2.11.0";
5072
5100
 
5073
5101
  // src/version.ts
5074
5102
  var SDK_VERSION = version;
@@ -5099,6 +5127,7 @@ var EmporixClient = class {
5099
5127
  ragIndexer;
5100
5128
  sequentialIds;
5101
5129
  fees;
5130
+ cloudFunctions;
5102
5131
  webhooks;
5103
5132
  schemas;
5104
5133
  ai;
@@ -5199,6 +5228,7 @@ var EmporixClient = class {
5199
5228
  this.ragIndexer = new RagIndexerService(mk("ai-rag-indexer"));
5200
5229
  this.sequentialIds = new SequentialIdService(mk("sequential-id"));
5201
5230
  this.fees = new FeeService(mk("fee"));
5231
+ this.cloudFunctions = new CloudFunctionsService(mk("cloud-functions"));
5202
5232
  this.webhooks = new WebhookService(mk("webhook"));
5203
5233
  this.schemas = new SchemaService(mk("schema"));
5204
5234
  this.ai = new AiService(mk("ai"));
@@ -5220,6 +5250,16 @@ var EmporixClient = class {
5220
5250
  this.customerAdmin = new CustomerAdminService(mk("customer-admin"));
5221
5251
  this.approvals = new ApprovalService(mk("approval"));
5222
5252
  }
5253
+ /**
5254
+ * Re-binds the storefront price context (currency / siteCode / targetLocation)
5255
+ * for anonymous pricing and invalidates the current anonymous session, so the
5256
+ * next request re-mints a token bound to the new context. Use this to switch
5257
+ * currency at runtime. Carts are currency-bound — clear the cart after a
5258
+ * currency change (the React `setCurrency` does this for you).
5259
+ */
5260
+ setStorefrontContext(ctx) {
5261
+ this.tokenProvider.setAnonymousContext?.(ctx);
5262
+ }
5223
5263
  /** Sets the runtime log level globally or for one service. */
5224
5264
  setLogLevel(level, opts = {}) {
5225
5265
  this.resolver.set(level, opts.service, opts.force ?? false);
@@ -5255,6 +5295,7 @@ exports.CatalogService = CatalogService;
5255
5295
  exports.CategoryService = CategoryService;
5256
5296
  exports.CheckoutService = CheckoutService;
5257
5297
  exports.ClientConfigService = ClientConfigService;
5298
+ exports.CloudFunctionsService = CloudFunctionsService;
5258
5299
  exports.CompaniesService = CompaniesService;
5259
5300
  exports.ContactsService = ContactsService;
5260
5301
  exports.CountryService = CountryService;