@viu/emporix-sdk 2.29.0 → 2.30.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.
Files changed (47) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/dist/availability.d.cts +1 -1
  3. package/dist/availability.d.ts +1 -1
  4. package/dist/cart.d.cts +1 -1
  5. package/dist/cart.d.ts +1 -1
  6. package/dist/category.d.cts +1 -1
  7. package/dist/category.d.ts +1 -1
  8. package/dist/checkout.d.cts +1 -1
  9. package/dist/checkout.d.ts +1 -1
  10. package/dist/{chunk-6PJFOX3A.js → chunk-4VRUMCS2.js} +8 -5
  11. package/dist/chunk-4VRUMCS2.js.map +1 -0
  12. package/dist/companies.d.cts +1 -1
  13. package/dist/companies.d.ts +1 -1
  14. package/dist/contacts.d.cts +1 -1
  15. package/dist/contacts.d.ts +1 -1
  16. package/dist/{context-B5rWL6QD.d.cts → context-CpLIDl0P.d.cts} +24 -9
  17. package/dist/{context-B5rWL6QD.d.ts → context-CpLIDl0P.d.ts} +24 -9
  18. package/dist/{customer-groups-_czUdHab.d.cts → customer-groups-DJVbdrEP.d.cts} +1 -1
  19. package/dist/{customer-groups-BRN6I23C.d.ts → customer-groups-DhpCTCTg.d.ts} +1 -1
  20. package/dist/customer-groups.d.cts +2 -2
  21. package/dist/customer-groups.d.ts +2 -2
  22. package/dist/customer.d.cts +1 -1
  23. package/dist/customer.d.ts +1 -1
  24. package/dist/index.cjs +7 -4
  25. package/dist/index.cjs.map +1 -1
  26. package/dist/index.d.cts +14 -3
  27. package/dist/index.d.ts +14 -3
  28. package/dist/index.js +3 -3
  29. package/dist/index.js.map +1 -1
  30. package/dist/locations.d.cts +1 -1
  31. package/dist/locations.d.ts +1 -1
  32. package/dist/media.d.cts +1 -1
  33. package/dist/media.d.ts +1 -1
  34. package/dist/orders.d.cts +1 -1
  35. package/dist/orders.d.ts +1 -1
  36. package/dist/payment.cjs.map +1 -1
  37. package/dist/payment.d.cts +1 -1
  38. package/dist/payment.d.ts +1 -1
  39. package/dist/payment.js +1 -1
  40. package/dist/price.d.cts +1 -1
  41. package/dist/price.d.ts +1 -1
  42. package/dist/product.d.cts +1 -1
  43. package/dist/product.d.ts +1 -1
  44. package/dist/segment.d.cts +1 -1
  45. package/dist/segment.d.ts +1 -1
  46. package/package.json +1 -1
  47. package/dist/chunk-6PJFOX3A.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,51 @@
1
1
  # @viu/emporix-sdk
2
2
 
3
+ ## 2.30.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#211](https://github.com/viuteam/emporix-sdk/pull/211) [`9c87fa4`](https://github.com/viuteam/emporix-sdk/commit/9c87fa478368c74503f0f0b2f61b8a7b8e4a7631) Thanks [@amnael1](https://github.com/amnael1)! - Stop spending one Emporix token call per guest request.
8
+
9
+ `AnonymousSessionStore` may now carry the anonymous **access** token and its
10
+ expiry (`StoredAnonymousSession`: `{ refreshToken, sessionId, accessToken?,
11
+ expiresAt? }`), and `@viu/emporix-sdk-next` persists both in its httpOnly
12
+ session cookie. A server-side guest client lives for exactly one request, so its
13
+ in-memory token cache is always empty — before this, every single request redeemed
14
+ the refresh token for a token the guest already held. Emporix bills per API call,
15
+ and an anonymous token is valid for 3599 seconds on the `viu` tenant.
16
+
17
+ Measured with a request-counting stub, guest path, one business call per request:
18
+
19
+ | | before | after |
20
+ | ---------------------------------------- | ----------- | ------- |
21
+ | first request of a session | 1 login | 1 login |
22
+ | every later request | 1 refresh | **0** |
23
+ | four `withEmporixSession` in one request | 4 refreshes | **0** |
24
+
25
+ A logged-in customer already cost zero token calls and still does —
26
+ `auth.customer(token)` is passed straight through and no anonymous token is ever
27
+ minted for them.
28
+
29
+ Both fields are optional and the two hosts choose oppositely on purpose: the
30
+ React storage adapters keep persisting **only** `{ refreshToken, sessionId }`,
31
+ because a browser client is long-lived and holds the token in memory anyway, so
32
+ writing it to `localStorage` would only expose a bearer token to JavaScript. A
33
+ test pins that.
34
+
35
+ `accessToken` counts only together with a future `expiresAt` — either alone is
36
+ treated as «no token», so a truncated or hand-edited record cannot make the SDK
37
+ send an empty bearer token. A stored token that the tenant revoked early, or one
38
+ an out-of-sync clock made look valid, comes back as a 401 that `HttpClient`
39
+ answers with `expireAnonymous()` plus one retry; the `sessionId` survives, so the
40
+ guest keeps their cart. Existing sessions keep working: a cookie written before
41
+ this release simply has neither field and refreshes exactly as it did.
42
+
43
+ ### Patch Changes
44
+
45
+ - [#210](https://github.com/viuteam/emporix-sdk/pull/210) [`f0592aa`](https://github.com/viuteam/emporix-sdk/commit/f0592aa34ea639cd9a273f60c4e20d03aa70a306) Thanks [@viu-release-bot](https://github.com/apps/viu-release-bot)! - chore(sdk): sync generated types with upstream Emporix API specs
46
+
47
+ Updated services: ai-service,schema
48
+
3
49
  ## 2.29.0
4
50
 
5
51
  ### Minor Changes
@@ -1,4 +1,4 @@
1
- import { C as ClientContext, b as AuthContext, P as PaginatedItems } from './context-B5rWL6QD.cjs';
1
+ import { C as ClientContext, b as AuthContext, P as PaginatedItems } from './context-CpLIDl0P.cjs';
2
2
 
3
3
  type AvailabilityDto = {
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { C as ClientContext, b as AuthContext, P as PaginatedItems } from './context-B5rWL6QD.js';
1
+ import { C as ClientContext, b as AuthContext, P as PaginatedItems } from './context-CpLIDl0P.js';
2
2
 
3
3
  type AvailabilityDto = {
4
4
  /**
package/dist/cart.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { C as ClientContext, b as AuthContext } from './context-B5rWL6QD.cjs';
1
+ import { C as ClientContext, b as AuthContext } from './context-CpLIDl0P.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-B5rWL6QD.js';
1
+ import { C as ClientContext, b as AuthContext } from './context-CpLIDl0P.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-B5rWL6QD.cjs';
1
+ import { C as ClientContext, b as AuthContext, P as PaginatedItems } from './context-CpLIDl0P.cjs';
2
2
  import { a as QueryFor } from './query-mLQs2WFr.cjs';
3
3
  import { Product } from './product.cjs';
4
4
 
@@ -1,4 +1,4 @@
1
- import { C as ClientContext, b as AuthContext, P as PaginatedItems } from './context-B5rWL6QD.js';
1
+ import { C as ClientContext, b as AuthContext, P as PaginatedItems } from './context-CpLIDl0P.js';
2
2
  import { a as QueryFor } from './query-mLQs2WFr.js';
3
3
  import { Product } from './product.js';
4
4
 
@@ -1,4 +1,4 @@
1
- import { C as ClientContext, b as AuthContext } from './context-B5rWL6QD.cjs';
1
+ import { C as ClientContext, b as AuthContext } from './context-CpLIDl0P.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-B5rWL6QD.js';
1
+ import { C as ClientContext, b as AuthContext } from './context-CpLIDl0P.js';
2
2
 
3
3
  /**
4
4
  * Information about the customer's address.
@@ -74,12 +74,13 @@ var DefaultTokenProvider = class {
74
74
  if (!this.anon) {
75
75
  const persisted = store.read();
76
76
  if (persisted) {
77
+ const token = persisted.accessToken ?? "";
77
78
  this.anon = {
78
- accessToken: "",
79
+ accessToken: token,
79
80
  refreshToken: persisted.refreshToken,
80
81
  sessionId: persisted.sessionId,
81
82
  expiresIn: 0,
82
- expiresAt: 0
83
+ expiresAt: token === "" ? 0 : persisted.expiresAt ?? 0
83
84
  };
84
85
  }
85
86
  }
@@ -231,7 +232,9 @@ var DefaultTokenProvider = class {
231
232
  };
232
233
  this.anonStore?.write({
233
234
  refreshToken: this.anon.refreshToken,
234
- sessionId: this.anon.sessionId
235
+ sessionId: this.anon.sessionId,
236
+ accessToken: this.anon.accessToken,
237
+ expiresAt: this.anon.expiresAt
235
238
  });
236
239
  this.notifyRefresh("anonymous", true);
237
240
  return this.stripExpiry(this.anon);
@@ -400,5 +403,5 @@ var PaymentGatewayService = class {
400
403
  };
401
404
 
402
405
  export { CustomerRefreshRegistry, DefaultTokenProvider, PaymentGatewayService, auth, resolveToken };
403
- //# sourceMappingURL=chunk-6PJFOX3A.js.map
404
- //# sourceMappingURL=chunk-6PJFOX3A.js.map
406
+ //# sourceMappingURL=chunk-4VRUMCS2.js.map
407
+ //# sourceMappingURL=chunk-4VRUMCS2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/auth.ts","../src/services/payment.ts"],"names":[],"mappings":"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","file":"chunk-4VRUMCS2.js","sourcesContent":["import type { ResolvedConfig, ServiceCredentials } from \"./config\";\nimport { EmporixAuthError, EmporixTimeoutError, EmporixNetworkError } from \"./errors\";\n\n/** Which token a call should use. */\nexport type AuthKind = \"service\" | \"customer\" | \"anonymous\" | \"raw\";\n\n/** Caller-supplied, per-call auth selector. Never stored on the client. */\nexport type AuthContext =\n | { kind: \"service\"; credentials?: string }\n | { kind: \"anonymous\" }\n | { kind: \"customer\"; token: string }\n | { kind: \"raw\"; token: string };\n\n/**\n * Supplies a fresh customer token when a `customer`-kind request 401s. The host\n * (e.g. EmporixProvider) implements this; the SDK never refreshes the\n * caller-owned customer token unless a refresher is registered.\n */\nexport interface CustomerTokenRefresher {\n /**\n * Called on a `customer`-kind 401. Receives the token that just failed;\n * returns a fresh customer token to retry with, or `null` to give up (the\n * 401 then propagates as EmporixAuthError).\n */\n refresh(expiredToken: string): Promise<string | null>;\n}\n\n/** An obtained anonymous storefront session. */\nexport interface AnonymousSession {\n accessToken: string;\n refreshToken: string;\n sessionId: string;\n expiresIn: number;\n}\n\n/**\n * An anonymous session as it survives outside the client instance.\n *\n * `accessToken` and `expiresAt` are optional, and a store is free to drop them:\n * they turn a *server* round trip into zero token calls, because a server client\n * lives for one request and would otherwise refresh on every single one. A\n * long-lived browser client keeps the token in memory anyway, so the React\n * storage adapters deliberately persist only the two required fields — a token\n * readable by JavaScript buys nothing there.\n *\n * A store that returns `accessToken` without a future `expiresAt` gets treated as\n * having no token at all; see {@link DefaultTokenProvider.attachAnonymousStore}.\n */\nexport interface StoredAnonymousSession {\n refreshToken: string;\n sessionId: string;\n /** The access token itself, so a fresh client need not spend a refresh call for it. */\n accessToken?: string;\n /** Epoch ms after which `accessToken` is stale. The expiry buffer is already applied. */\n expiresAt?: number;\n}\n\n/**\n * Persistence callback for anonymous sessions. `read` is called once on the\n * first need for an anonymous token to bootstrap a possibly-existing session;\n * `write` is called after every successful login or refresh. `write(null)`\n * means the SDK is invalidating the stored session.\n */\nexport interface AnonymousSessionStore {\n read(): StoredAnonymousSession | null;\n write(session: StoredAnonymousSession | null): void;\n}\n\n/** Supplies SDK-managed tokens (service/custom + anonymous). May be user-injected. */\nexport interface TokenProvider {\n /** Service/custom client-credentials token for the named credential set. */\n getToken(credentialSet: string): Promise<string>;\n /** Cached anonymous storefront session (preserves sessionId across refreshes). */\n getAnonymousToken(): Promise<AnonymousSession>;\n /** Refresh the anonymous session, preserving sessionId. */\n refreshAnonymous?(): Promise<AnonymousSession>;\n /** Invalidate a cached SDK-managed token so the next call re-auths. */\n invalidate?(credentialSet: string): void;\n /** Invalidate the cached anonymous session entirely (next call re-logs in). */\n invalidateAnonymous?(): void;\n /**\n * Mark the anonymous access token stale but keep the refresh token, so the\n * next {@link getAnonymousToken} refreshes (preserving sessionId) rather\n * than starting a brand-new session.\n */\n expireAnonymous?(): void;\n /**\n * Install a persistence adapter for the anonymous session. The host (e.g.\n * `EmporixProvider`) calls this at construction so the SDK can bootstrap\n * an existing session and persist refreshes. Idempotent: a later call\n * replaces the previous adapter.\n */\n attachAnonymousStore?(store: AnonymousSessionStore): void;\n /**\n * Override the storefront context (currency/site/country) used for the next\n * anonymous login, then invalidate the current anonymous session so it\n * re-mints with the new context. No-op for providers without anon support.\n */\n setAnonymousContext?(ctx: {\n currency?: string;\n siteCode?: string;\n targetLocation?: string;\n }): void;\n /**\n * Subscribe to token-refresh events. Optional — implementations may no-op.\n * Returns an unsubscribe function. `DefaultTokenProvider` emits for the\n * anonymous-login / anonymous-refresh paths.\n */\n onRefresh?(\n listener: (event: { kind: \"anonymous\" | \"customer\"; success: boolean }) => void,\n ): () => void;\n}\n\n/** Tiny constructors for {@link AuthContext}. */\nexport const auth = {\n /** Service/custom credential set (default `backend`). */\n service: (credentials?: string): AuthContext =>\n credentials === undefined ? { kind: \"service\" } : { kind: \"service\", credentials },\n /** Cached anonymous storefront token. */\n anonymous: (): AuthContext => ({ kind: \"anonymous\" }),\n /** Caller-owned customer bearer token. */\n customer: (token: string): AuthContext => ({ kind: \"customer\", token }),\n /** Exact token, no transformation (SSO / token-exchange). */\n raw: (token: string): AuthContext => ({ kind: \"raw\", token }),\n};\n\n/** Resolves an {@link AuthContext} to a concrete bearer token. */\nexport async function resolveToken(ctx: AuthContext, provider: TokenProvider): Promise<string> {\n switch (ctx.kind) {\n case \"service\":\n return provider.getToken(ctx.credentials ?? \"backend\");\n case \"anonymous\":\n return (await provider.getAnonymousToken()).accessToken;\n case \"customer\":\n case \"raw\":\n return ctx.token;\n }\n}\n\n/**\n * Late-bindable, single-flight holder for an optional\n * {@link CustomerTokenRefresher}. Single-flight is required because Emporix\n * rotates the refresh token on each refresh — concurrent refreshes would\n * invalidate each other. Off (returns `null`) until a refresher is set.\n */\nexport class CustomerRefreshRegistry {\n private refresher: CustomerTokenRefresher | null = null;\n private inflight: Promise<string | null> | null = null;\n\n set(refresher: CustomerTokenRefresher | null): void {\n this.refresher = refresher;\n }\n\n get enabled(): boolean {\n return this.refresher !== null;\n }\n\n /** Concurrent callers share one in-flight refresh. */\n refresh(expiredToken: string): Promise<string | null> {\n if (!this.refresher) return Promise.resolve(null);\n if (this.inflight) return this.inflight;\n const p = Promise.resolve(this.refresher.refresh(expiredToken)).finally(() => {\n this.inflight = null;\n });\n this.inflight = p;\n return p;\n }\n}\n\ninterface CacheEntry {\n token: string;\n expiresAt: number;\n obtainedAt: number;\n}\n\n/** SDK-owned token provider: client-credentials service tokens + anonymous session. */\nexport class DefaultTokenProvider implements TokenProvider {\n private readonly serviceCache = new Map<string, CacheEntry>();\n private readonly serviceLocks = new Map<string, Promise<string>>();\n private anon: (AnonymousSession & { expiresAt: number }) | undefined;\n private anonLock: Promise<AnonymousSession> | undefined;\n private anonStore?: AnonymousSessionStore;\n private contextOverride:\n | { currency?: string; siteCode?: string; targetLocation?: string }\n | undefined;\n private readonly refreshListeners = new Set<\n (event: { kind: \"anonymous\" | \"customer\"; success: boolean }) => void\n >();\n\n constructor(private readonly cfg: ResolvedConfig) {}\n\n onRefresh(\n listener: (event: { kind: \"anonymous\" | \"customer\"; success: boolean }) => void,\n ): () => void {\n this.refreshListeners.add(listener);\n return () => {\n this.refreshListeners.delete(listener);\n };\n }\n\n private notifyRefresh(kind: \"anonymous\" | \"customer\", success: boolean): void {\n for (const l of this.refreshListeners) {\n try {\n l({ kind, success });\n } catch {\n // Never let a telemetry listener break the auth path.\n }\n }\n }\n\n attachAnonymousStore(store: AnonymousSessionStore): void {\n this.anonStore = store;\n // Bootstrap `this.anon` from the store if we don't have it yet.\n //\n // A persisted access token that is still inside its lifetime is adopted as\n // is, and that is the point on a server: a client that lives for one request\n // would otherwise spend one `/anonymous/refresh` per request for a token it\n // already holds. Without a token — or past its expiry — `expiresAt` stays 0\n // and the next getAnonymousToken refreshes, which preserves the sessionId,\n // so the guest's cart survives either way.\n //\n // `expiresAt` counts only when there is a token to go with it. A store that\n // returns one without the other would otherwise make `anonFresh()` true and\n // hand out an empty bearer token.\n //\n // Trusting a stored expiry means trusting the writer's clock. A token\n // revoked early, or an expiry that a skewed clock made look valid, comes\n // back as a 401 — which `HttpClient` answers with `expireAnonymous()` plus\n // one retry, so the failure mode is a refresh, not an error.\n if (!this.anon) {\n const persisted = store.read();\n if (persisted) {\n const token = persisted.accessToken ?? \"\";\n this.anon = {\n accessToken: token,\n refreshToken: persisted.refreshToken,\n sessionId: persisted.sessionId,\n expiresIn: 0,\n expiresAt: token === \"\" ? 0 : (persisted.expiresAt ?? 0),\n };\n }\n }\n }\n\n private creds(set: string): ServiceCredentials {\n if (set === \"backend\") {\n const b = this.cfg.credentials.backend;\n if (!b?.clientId || !b.secret) {\n throw new EmporixAuthError(\n \"A 'service' AuthContext was used but credentials.backend is not configured\",\n );\n }\n return b;\n }\n const c = this.cfg.credentials.custom?.[set];\n if (!c) throw new Error(`Unknown credential set \"${set}\"`);\n return c;\n }\n\n private fresh(e: CacheEntry | undefined): boolean {\n if (!e) return false;\n const now = Date.now();\n if (now - e.obtainedAt >= this.cfg.cache.maxLifetimeSeconds * 1000) return false;\n return now < e.expiresAt;\n }\n\n async getToken(set: string): Promise<string> {\n // Surface an unknown credential set before entering the cache/lock path.\n this.creds(set);\n const cached = this.serviceCache.get(set);\n if (this.fresh(cached)) return cached!.token;\n const inflight = this.serviceLocks.get(set);\n if (inflight) return inflight;\n const p = this.requestServiceToken(set).finally(() => this.serviceLocks.delete(set));\n this.serviceLocks.set(set, p);\n return p;\n }\n\n /**\n * fetch with the configured read timeout. Token endpoints sit in front of\n * single-flight locks — one hung call would otherwise block every request\n * on this credential set forever.\n */\n private async boundedFetch(url: string | URL, init: RequestInit = {}): Promise<Response> {\n const ms = this.cfg.timeouts?.readMs ?? 60_000;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), ms);\n try {\n return await fetch(url, { ...init, signal: controller.signal });\n } catch (err) {\n if ((err as Error).name === \"AbortError\") {\n throw new EmporixTimeoutError(`token request timed out after ${ms}ms`);\n }\n throw new EmporixNetworkError(`token request network failure: ${(err as Error).message}`);\n } finally {\n clearTimeout(timer);\n }\n }\n\n private async requestServiceToken(set: string): Promise<string> {\n const c = this.creds(set);\n const body = new URLSearchParams({\n grant_type: \"client_credentials\",\n client_id: c.clientId,\n client_secret: c.secret,\n });\n if (c.scope) body.set(\"scope\", c.scope);\n const res = await this.boundedFetch(`${this.cfg.host}/oauth/token`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body,\n });\n const json = (await res.json().catch(() => ({}))) as Record<string, unknown>;\n if (!res.ok) {\n throw new EmporixAuthError(`Token request failed for \"${set}\"`, res.status, json);\n }\n const obtainedAt = Date.now();\n const ttl = Number((json.expires_in as number | undefined) ?? 3600);\n this.serviceCache.set(set, {\n token: json.access_token as string,\n obtainedAt,\n expiresAt: obtainedAt + (ttl - this.cfg.cache.expirationBufferSeconds) * 1000,\n });\n return this.serviceCache.get(set)!.token;\n }\n\n invalidate(set: string): void {\n this.serviceCache.delete(set);\n }\n\n private anonFresh(): boolean {\n return !!this.anon && Date.now() < this.anon.expiresAt;\n }\n\n async getAnonymousToken(): Promise<AnonymousSession> {\n if (this.anonFresh()) return this.stripExpiry(this.anon!);\n if (this.anonLock) return this.anonLock;\n // Token expired but a refresh token survives → refresh to keep the same\n // sessionId; only fall back to a brand-new login if the refresh fails.\n const canRefresh = !!this.anon?.refreshToken;\n const obtain = canRefresh\n ? this.fetchAnonymous(\"refresh\").catch(() => this.fetchAnonymous(\"login\"))\n : this.fetchAnonymous(\"login\");\n const p = obtain.finally(() => {\n this.anonLock = undefined;\n });\n this.anonLock = p;\n return p;\n }\n\n /** Refreshes the anonymous session, preserving its sessionId. */\n async refreshAnonymous(): Promise<AnonymousSession> {\n if (!this.anon) return this.getAnonymousToken();\n return this.fetchAnonymous(\"refresh\");\n }\n\n invalidateAnonymous(): void {\n this.anon = undefined;\n this.anonStore?.write(null);\n }\n\n setAnonymousContext(ctx: {\n currency?: string;\n siteCode?: string;\n targetLocation?: string;\n }): void {\n const base = this.contextOverride ?? this.cfg.credentials.storefront?.context ?? {};\n this.contextOverride = { ...base, ...ctx };\n this.invalidateAnonymous();\n }\n\n /** Force a stale access token while keeping the refresh token + sessionId. */\n expireAnonymous(): void {\n if (this.anon) this.anon = { ...this.anon, expiresAt: 0 };\n }\n\n private stripExpiry(s: AnonymousSession & { expiresAt: number }): AnonymousSession {\n const { expiresAt: _expiresAt, ...rest } = s;\n return rest;\n }\n\n private async fetchAnonymous(mode: \"login\" | \"refresh\"): Promise<AnonymousSession> {\n const sf = this.cfg.credentials.storefront;\n if (!sf?.clientId) {\n throw new Error(\"credentials.storefront.clientId is required for anonymous tokens\");\n }\n const url = new URL(`${this.cfg.host}/customerlogin/auth/anonymous/${mode}`);\n url.searchParams.set(\"tenant\", this.cfg.tenant);\n url.searchParams.set(\"client_id\", sf.clientId);\n // Context is the runtime override (set via setAnonymousContext) if present,\n // else the config-fixed context.\n const c = this.contextOverride ?? sf.context;\n if (c?.currency) url.searchParams.set(\"currency\", c.currency);\n if (c?.siteCode) url.searchParams.set(\"siteCode\", c.siteCode);\n if (c?.targetLocation) url.searchParams.set(\"targetLocation\", c.targetLocation);\n if (mode === \"refresh\" && this.anon) {\n url.searchParams.set(\"refresh_token\", this.anon.refreshToken);\n }\n try {\n const res = await this.boundedFetch(url, { method: \"GET\" });\n const json = (await res.json().catch(() => ({}))) as Record<string, unknown>;\n if (!res.ok) {\n this.notifyRefresh(\"anonymous\", false);\n throw new EmporixAuthError(`Anonymous token ${mode} failed`, res.status, json);\n }\n const obtainedAt = Date.now();\n this.anon = {\n accessToken: json.access_token as string,\n refreshToken: json.refresh_token as string,\n sessionId: json.sessionId as string,\n expiresIn: json.expires_in as number,\n expiresAt:\n obtainedAt +\n ((json.expires_in as number) - this.cfg.cache.expirationBufferSeconds) * 1000,\n };\n // The access token and its expiry go out too, so a store that keeps them\n // (a server one) can hand the next request a usable token instead of\n // another refresh. A store that only wants the refresh token drops them.\n this.anonStore?.write({\n refreshToken: this.anon.refreshToken,\n sessionId: this.anon.sessionId,\n accessToken: this.anon.accessToken,\n expiresAt: this.anon.expiresAt,\n });\n this.notifyRefresh(\"anonymous\", true);\n return this.stripExpiry(this.anon);\n } catch (err) {\n // Re-throw EmporixAuthError as-is; for non-Emporix errors (network), also notify.\n if (!(err instanceof EmporixAuthError)) {\n this.notifyRefresh(\"anonymous\", false);\n }\n throw err;\n }\n }\n}\n// Customer-token refreshes happen via client.customers.refresh() and don't\n// route through this TokenProvider — only the anonymous flow notifies.\n// React-side useCustomerSession.refresh emits its own telemetry event in a\n// follow-up if needed.\n","import type { ClientContext } from \"../core/context\";\nimport { auth, type AuthContext } from \"../core/auth\";\nimport { requireCustomer } from \"../core/require-customer\";\nimport type {\n PaymentModeFrontendResponse,\n AuthorizePaymentRequest,\n InitializePaymentRequest,\n InitializePaymentResponse,\n PaymentModeResponse,\n PaymentModeRequest,\n PaymentMethodUpdateRequest,\n PaymentTransactionResponse,\n AuthorizePaymentResponse,\n CaptureRequest,\n RefundRequest,\n CommonPaymentResponse,\n} from \"../generated/payment\";\n\nconst ANON: AuthContext = auth.anonymous();\nconst SERVICE: AuthContext = auth.service();\n\n/** A frontend payment mode (generated). */\nexport type PaymentMode = PaymentModeFrontendResponse;\n\n/** Post-checkout authorize request (generated; caller sends the exact wire shape). */\nexport type AuthorizePaymentInput = AuthorizePaymentRequest;\n\n/** Frontend payment-initialize request (generated). */\nexport type InitializePaymentInput = InitializePaymentRequest;\n\n/** Frontend payment-initialize response (generated). */\nexport type InitializePaymentResult = InitializePaymentResponse;\n\n/** Post-checkout authorize result. */\nexport interface AuthorizePaymentResult {\n successful: boolean;\n paymentTransactionId?: string;\n authorizationToken?: string;\n requiresExternalPayment?: boolean;\n externalPaymentRedirectURL?: string;\n externalPaymentHttpMethod?: string;\n [k: string]: unknown;\n}\n\n/** A configured payment mode (admin view, `/paymentmodes/config`). */\nexport type PaymentModeConfig = PaymentModeResponse;\n\n/** Body for creating a payment-mode configuration. */\nexport type PaymentModeCreateInput = PaymentModeRequest;\n\n/** Body for updating a payment-mode configuration. */\nexport type PaymentModeUpdateInput = PaymentMethodUpdateRequest;\n\n/** A payment transaction (generated). */\nexport type PaymentTransaction = PaymentTransactionResponse;\n\n/** Result of a backend payment authorization. */\nexport type PaymentAuthorizeResult = AuthorizePaymentResponse;\n\n/** Body for capturing an authorized payment. */\nexport type PaymentCaptureInput = CaptureRequest;\n\n/** Body for refunding a captured payment. */\nexport type PaymentRefundInput = RefundRequest;\n\n/**\n * Result of a refund/cancel operation. Business failures are reported in the\n * body (`successful: false` + `message`), not via HTTP status.\n */\nexport type PaymentActionResult = CommonPaymentResponse;\n\n/** Result of a capture — like {@link PaymentActionResult} plus the provider's capture id. */\nexport type PaymentCaptureResult = {\n successful?: boolean;\n message?: string;\n captureId?: string;\n};\n\n/** Payment-Gateway: list frontend payment modes, authorize deferred payments. */\nexport class PaymentGatewayService {\n static readonly channel = \"payment\" as const;\n constructor(private readonly ctx: ClientContext) {}\n\n /**\n * Lists configured frontend payment modes. The endpoint requires a bearer\n * token but no customer scope (\"No scope required\"), so it defaults to an\n * anonymous context and works for guests and logged-in customers alike.\n */\n async listPaymentModes(authCtx: AuthContext = ANON): Promise<PaymentMode[]> {\n return this.ctx.http.request<PaymentMode[]>({\n method: \"GET\",\n path: `/payment-gateway/${this.ctx.tenant}/paymentmodes/frontend`,\n auth: authCtx,\n });\n }\n\n /** Authorizes a post-checkout (deferred) payment for an existing order. */\n async authorize(\n input: AuthorizePaymentInput,\n authCtx?: AuthContext,\n ): Promise<AuthorizePaymentResult> {\n return this.ctx.http.request<AuthorizePaymentResult>({\n method: \"POST\",\n path: `/payment-gateway/${this.ctx.tenant}/payment/frontend/authorize`,\n auth: requireCustomer(authCtx),\n body: input,\n });\n }\n\n /** Retrieves a single frontend payment mode by id. Defaults to anonymous (no scope required). */\n async getMode(id: string, authCtx: AuthContext = ANON): Promise<PaymentMode> {\n return this.ctx.http.request<PaymentMode>({\n method: \"GET\",\n path: `/payment-gateway/${this.ctx.tenant}/paymentmodes/frontend/${id}`,\n auth: authCtx,\n });\n }\n\n /** Initializes a payment from the frontend. Defaults to anonymous (no scope required). */\n async initialize(\n input: InitializePaymentInput,\n authCtx: AuthContext = ANON,\n ): Promise<InitializePaymentResult> {\n return this.ctx.http.request<InitializePaymentResult>({\n method: \"POST\",\n path: `/payment-gateway/${this.ctx.tenant}/payment/frontend/initialize`,\n auth: authCtx,\n body: input,\n });\n }\n\n /**\n * Payment-mode **configuration** (`/paymentmodes/config`) — the admin view.\n * For the storefront view use {@link listPaymentModes} / {@link getMode}.\n * Defaults to service auth.\n */\n readonly modes = {\n /** Lists all configured payment modes. The endpoint takes no query parameters. */\n list: async (authCtx: AuthContext = SERVICE): Promise<PaymentModeConfig[]> =>\n this.ctx.http.request<PaymentModeConfig[]>({\n method: \"GET\",\n path: `/payment-gateway/${this.ctx.tenant}/paymentmodes/config`,\n auth: authCtx,\n }),\n\n /** Retrieves one payment-mode configuration by id. */\n get: async (id: string, authCtx: AuthContext = SERVICE): Promise<PaymentModeConfig> =>\n this.ctx.http.request<PaymentModeConfig>({\n method: \"GET\",\n path: `/payment-gateway/${this.ctx.tenant}/paymentmodes/config/${id}`,\n auth: authCtx,\n }),\n\n /** Creates a payment-mode configuration. Responds 200 with the created mode. */\n create: async (\n input: PaymentModeCreateInput,\n authCtx: AuthContext = SERVICE,\n ): Promise<PaymentModeConfig> =>\n this.ctx.http.request<PaymentModeConfig>({\n method: \"POST\",\n path: `/payment-gateway/${this.ctx.tenant}/paymentmodes/config`,\n body: input,\n auth: authCtx,\n }),\n\n /** Updates a payment-mode configuration (PUT). Responds 200 with the updated mode. */\n update: async (\n id: string,\n input: PaymentModeUpdateInput,\n authCtx: AuthContext = SERVICE,\n ): Promise<PaymentModeConfig> =>\n this.ctx.http.request<PaymentModeConfig>({\n method: \"PUT\",\n path: `/payment-gateway/${this.ctx.tenant}/paymentmodes/config/${id}`,\n body: input,\n auth: authCtx,\n }),\n\n /** Deletes a payment-mode configuration. */\n delete: async (id: string, authCtx: AuthContext = SERVICE): Promise<void> => {\n await this.ctx.http.request<void>({\n method: \"DELETE\",\n path: `/payment-gateway/${this.ctx.tenant}/paymentmodes/config/${id}`,\n auth: authCtx,\n });\n },\n };\n\n /**\n * Backend transaction lifecycle and reads. `authorize` creates the transaction\n * that `capture`/`refund`/`cancel` then act on. Business failures are reported\n * in the response body (`successful: false`), not as HTTP errors — always check\n * `successful`. Defaults to service auth.\n */\n readonly transactions = {\n /** One page of payment transactions. */\n list: async (\n params: { pageNumber?: number; pageSize?: number; sort?: string } = {},\n authCtx: AuthContext = SERVICE,\n ): Promise<PaymentTransaction[]> => {\n const query = {\n ...(params.pageNumber === undefined ? {} : { pageNumber: params.pageNumber }),\n ...(params.pageSize === undefined ? {} : { pageSize: params.pageSize }),\n ...(params.sort === undefined ? {} : { sort: params.sort }),\n };\n return this.ctx.http.request<PaymentTransaction[]>({\n method: \"GET\",\n path: `/payment-gateway/${this.ctx.tenant}/transactions`,\n ...(Object.keys(query).length > 0 ? { query } : {}),\n auth: authCtx,\n });\n },\n\n /** Retrieves one payment transaction by id. */\n get: async (transactionId: string, authCtx: AuthContext = SERVICE): Promise<PaymentTransaction> =>\n this.ctx.http.request<PaymentTransaction>({\n method: \"GET\",\n path: `/payment-gateway/${this.ctx.tenant}/transactions/${transactionId}`,\n auth: authCtx,\n }),\n\n /**\n * Authorizes a payment as a backend caller (`POST /payment/authorize`). The\n * storefront equivalent is {@link PaymentGatewayService.authorize}, which\n * targets `/payment/frontend/authorize` with a customer token.\n */\n authorize: async (\n input: AuthorizePaymentInput,\n authCtx: AuthContext = SERVICE,\n ): Promise<PaymentAuthorizeResult> =>\n this.ctx.http.request<PaymentAuthorizeResult>({\n method: \"POST\",\n path: `/payment-gateway/${this.ctx.tenant}/payment/authorize`,\n body: input,\n auth: authCtx,\n }),\n\n /**\n * Captures an authorized payment. Omit `input` to capture the full\n * authorized amount. Returns the provider's `captureId` on success.\n */\n capture: async (\n transactionId: string,\n input?: PaymentCaptureInput,\n authCtx: AuthContext = SERVICE,\n ): Promise<PaymentCaptureResult> =>\n this.ctx.http.request<PaymentCaptureResult>({\n method: \"POST\",\n path: `/payment-gateway/${this.ctx.tenant}/payment/${transactionId}/capture`,\n ...(input === undefined ? {} : { body: input }),\n auth: authCtx,\n }),\n\n /**\n * Refunds a captured payment. Omit `input` to refund the full captured\n * amount; pass `captureId` when several captures exist for the payment.\n */\n refund: async (\n transactionId: string,\n input?: PaymentRefundInput,\n authCtx: AuthContext = SERVICE,\n ): Promise<PaymentActionResult> =>\n this.ctx.http.request<PaymentActionResult>({\n method: \"POST\",\n path: `/payment-gateway/${this.ctx.tenant}/payment/${transactionId}/refund`,\n ...(input === undefined ? {} : { body: input }),\n auth: authCtx,\n }),\n\n /** Cancels an authorized payment. Takes no body. */\n cancel: async (transactionId: string, authCtx: AuthContext = SERVICE): Promise<PaymentActionResult> =>\n this.ctx.http.request<PaymentActionResult>({\n method: \"POST\",\n path: `/payment-gateway/${this.ctx.tenant}/payment/${transactionId}/cancel`,\n auth: authCtx,\n }),\n };\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { C as ClientContext, b as AuthContext } from './context-B5rWL6QD.cjs';
1
+ import { C as ClientContext, b as AuthContext } from './context-CpLIDl0P.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-B5rWL6QD.js';
1
+ import { C as ClientContext, b as AuthContext } from './context-CpLIDl0P.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-B5rWL6QD.cjs';
1
+ import { C as ClientContext, b as AuthContext } from './context-CpLIDl0P.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-B5rWL6QD.js';
1
+ import { C as ClientContext, b as AuthContext } from './context-CpLIDl0P.js';
2
2
  import { C as ContactAssignment, a as ContactAssignmentCreate, b as ContactAssignmentUpdate } from './types.gen-C_wOXYZB.js';
3
3
 
4
4
  /**
@@ -193,6 +193,27 @@ interface AnonymousSession {
193
193
  sessionId: string;
194
194
  expiresIn: number;
195
195
  }
196
+ /**
197
+ * An anonymous session as it survives outside the client instance.
198
+ *
199
+ * `accessToken` and `expiresAt` are optional, and a store is free to drop them:
200
+ * they turn a *server* round trip into zero token calls, because a server client
201
+ * lives for one request and would otherwise refresh on every single one. A
202
+ * long-lived browser client keeps the token in memory anyway, so the React
203
+ * storage adapters deliberately persist only the two required fields — a token
204
+ * readable by JavaScript buys nothing there.
205
+ *
206
+ * A store that returns `accessToken` without a future `expiresAt` gets treated as
207
+ * having no token at all; see {@link DefaultTokenProvider.attachAnonymousStore}.
208
+ */
209
+ interface StoredAnonymousSession {
210
+ refreshToken: string;
211
+ sessionId: string;
212
+ /** The access token itself, so a fresh client need not spend a refresh call for it. */
213
+ accessToken?: string;
214
+ /** Epoch ms after which `accessToken` is stale. The expiry buffer is already applied. */
215
+ expiresAt?: number;
216
+ }
196
217
  /**
197
218
  * Persistence callback for anonymous sessions. `read` is called once on the
198
219
  * first need for an anonymous token to bootstrap a possibly-existing session;
@@ -200,14 +221,8 @@ interface AnonymousSession {
200
221
  * means the SDK is invalidating the stored session.
201
222
  */
202
223
  interface AnonymousSessionStore {
203
- read(): {
204
- refreshToken: string;
205
- sessionId: string;
206
- } | null;
207
- write(session: {
208
- refreshToken: string;
209
- sessionId: string;
210
- } | null): void;
224
+ read(): StoredAnonymousSession | null;
225
+ write(session: StoredAnonymousSession | null): void;
211
226
  }
212
227
  /** Supplies SDK-managed tokens (service/custom + anonymous). May be user-injected. */
213
228
  interface TokenProvider {
@@ -443,4 +458,4 @@ interface PaginatedItems<T> {
443
458
  */
444
459
  declare function iterateAll<T>(fetchPage: (pageNumber: number) => Promise<PaginatedItems<T>>, start?: number): AsyncIterable<T>;
445
460
 
446
- export { type AnonymousSession as A, type ClientContext as C, DEFAULT_HOST as D, type EmporixConfig as E, HttpClient as H, LEVEL as L, type PaginatedItems as P, type RequestOptions as R, type ServiceCredentials as S, type TokenProvider as T, type AnonymousSessionStore as a, type AuthContext as b, type AuthKind as c, CustomerRefreshRegistry as d, type CustomerTokenRefresher as e, DefaultTokenProvider as f, type HttpClientOptions as g, LevelResolver as h, type LogFields as i, type LogLevel as j, type Logger as k, type LoggerConfig as l, type LoggerObjectConfig as m, type ResolvedConfig as n, type ServiceName as o, type StorefrontCredentials as p, auth as q, createConsoleLogger as r, createNoopLogger as s, iterateAll as t, redact as u, resolveToken as v, validateConfig as w };
461
+ export { type AnonymousSession as A, type ClientContext as C, DEFAULT_HOST as D, type EmporixConfig as E, HttpClient as H, LEVEL as L, type PaginatedItems as P, type RequestOptions as R, type ServiceCredentials as S, type TokenProvider as T, type AnonymousSessionStore as a, type AuthContext as b, type AuthKind as c, CustomerRefreshRegistry as d, type CustomerTokenRefresher as e, DefaultTokenProvider as f, type HttpClientOptions as g, LevelResolver as h, type LogFields as i, type LogLevel as j, type Logger as k, type LoggerConfig as l, type LoggerObjectConfig as m, type ResolvedConfig as n, type ServiceName as o, type StoredAnonymousSession as p, type StorefrontCredentials as q, auth as r, createConsoleLogger as s, createNoopLogger as t, iterateAll as u, redact as v, resolveToken as w, validateConfig as x };
@@ -193,6 +193,27 @@ interface AnonymousSession {
193
193
  sessionId: string;
194
194
  expiresIn: number;
195
195
  }
196
+ /**
197
+ * An anonymous session as it survives outside the client instance.
198
+ *
199
+ * `accessToken` and `expiresAt` are optional, and a store is free to drop them:
200
+ * they turn a *server* round trip into zero token calls, because a server client
201
+ * lives for one request and would otherwise refresh on every single one. A
202
+ * long-lived browser client keeps the token in memory anyway, so the React
203
+ * storage adapters deliberately persist only the two required fields — a token
204
+ * readable by JavaScript buys nothing there.
205
+ *
206
+ * A store that returns `accessToken` without a future `expiresAt` gets treated as
207
+ * having no token at all; see {@link DefaultTokenProvider.attachAnonymousStore}.
208
+ */
209
+ interface StoredAnonymousSession {
210
+ refreshToken: string;
211
+ sessionId: string;
212
+ /** The access token itself, so a fresh client need not spend a refresh call for it. */
213
+ accessToken?: string;
214
+ /** Epoch ms after which `accessToken` is stale. The expiry buffer is already applied. */
215
+ expiresAt?: number;
216
+ }
196
217
  /**
197
218
  * Persistence callback for anonymous sessions. `read` is called once on the
198
219
  * first need for an anonymous token to bootstrap a possibly-existing session;
@@ -200,14 +221,8 @@ interface AnonymousSession {
200
221
  * means the SDK is invalidating the stored session.
201
222
  */
202
223
  interface AnonymousSessionStore {
203
- read(): {
204
- refreshToken: string;
205
- sessionId: string;
206
- } | null;
207
- write(session: {
208
- refreshToken: string;
209
- sessionId: string;
210
- } | null): void;
224
+ read(): StoredAnonymousSession | null;
225
+ write(session: StoredAnonymousSession | null): void;
211
226
  }
212
227
  /** Supplies SDK-managed tokens (service/custom + anonymous). May be user-injected. */
213
228
  interface TokenProvider {
@@ -443,4 +458,4 @@ interface PaginatedItems<T> {
443
458
  */
444
459
  declare function iterateAll<T>(fetchPage: (pageNumber: number) => Promise<PaginatedItems<T>>, start?: number): AsyncIterable<T>;
445
460
 
446
- export { type AnonymousSession as A, type ClientContext as C, DEFAULT_HOST as D, type EmporixConfig as E, HttpClient as H, LEVEL as L, type PaginatedItems as P, type RequestOptions as R, type ServiceCredentials as S, type TokenProvider as T, type AnonymousSessionStore as a, type AuthContext as b, type AuthKind as c, CustomerRefreshRegistry as d, type CustomerTokenRefresher as e, DefaultTokenProvider as f, type HttpClientOptions as g, LevelResolver as h, type LogFields as i, type LogLevel as j, type Logger as k, type LoggerConfig as l, type LoggerObjectConfig as m, type ResolvedConfig as n, type ServiceName as o, type StorefrontCredentials as p, auth as q, createConsoleLogger as r, createNoopLogger as s, iterateAll as t, redact as u, resolveToken as v, validateConfig as w };
461
+ export { type AnonymousSession as A, type ClientContext as C, DEFAULT_HOST as D, type EmporixConfig as E, HttpClient as H, LEVEL as L, type PaginatedItems as P, type RequestOptions as R, type ServiceCredentials as S, type TokenProvider as T, type AnonymousSessionStore as a, type AuthContext as b, type AuthKind as c, CustomerRefreshRegistry as d, type CustomerTokenRefresher as e, DefaultTokenProvider as f, type HttpClientOptions as g, LevelResolver as h, type LogFields as i, type LogLevel as j, type Logger as k, type LoggerConfig as l, type LoggerObjectConfig as m, type ResolvedConfig as n, type ServiceName as o, type StoredAnonymousSession as p, type StorefrontCredentials as q, auth as r, createConsoleLogger as s, createNoopLogger as t, iterateAll as u, redact as v, resolveToken as w, validateConfig as x };
@@ -1,4 +1,4 @@
1
- import { C as ClientContext, b as AuthContext } from './context-B5rWL6QD.cjs';
1
+ import { C as ClientContext, b as AuthContext } from './context-CpLIDl0P.cjs';
2
2
 
3
3
  /**
4
4
  * Access control metadata.
@@ -1,4 +1,4 @@
1
- import { C as ClientContext, b as AuthContext } from './context-B5rWL6QD.js';
1
+ import { C as ClientContext, b as AuthContext } from './context-CpLIDl0P.js';
2
2
 
3
3
  /**
4
4
  * Access control metadata.
@@ -1,2 +1,2 @@
1
- export { g as CustomerGroupsService, j as IamGroup, c as IamGroupMemberAssignment } from './customer-groups-_czUdHab.cjs';
2
- import './context-B5rWL6QD.cjs';
1
+ export { g as CustomerGroupsService, j as IamGroup, c as IamGroupMemberAssignment } from './customer-groups-DJVbdrEP.cjs';
2
+ import './context-CpLIDl0P.cjs';
@@ -1,2 +1,2 @@
1
- export { g as CustomerGroupsService, j as IamGroup, c as IamGroupMemberAssignment } from './customer-groups-BRN6I23C.js';
2
- import './context-B5rWL6QD.js';
1
+ export { g as CustomerGroupsService, j as IamGroup, c as IamGroupMemberAssignment } from './customer-groups-DhpCTCTg.js';
2
+ import './context-CpLIDl0P.js';
@@ -1,4 +1,4 @@
1
- import { C as ClientContext, A as AnonymousSession, b as AuthContext } from './context-B5rWL6QD.cjs';
1
+ import { C as ClientContext, A as AnonymousSession, b as AuthContext } from './context-CpLIDl0P.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-B5rWL6QD.js';
1
+ import { C as ClientContext, A as AnonymousSession, b as AuthContext } from './context-CpLIDl0P.js';
2
2
 
3
3
  type AccountId = {
4
4
  /**
package/dist/index.cjs CHANGED
@@ -422,12 +422,13 @@ var DefaultTokenProvider = class {
422
422
  if (!this.anon) {
423
423
  const persisted = store.read();
424
424
  if (persisted) {
425
+ const token = persisted.accessToken ?? "";
425
426
  this.anon = {
426
- accessToken: "",
427
+ accessToken: token,
427
428
  refreshToken: persisted.refreshToken,
428
429
  sessionId: persisted.sessionId,
429
430
  expiresIn: 0,
430
- expiresAt: 0
431
+ expiresAt: token === "" ? 0 : persisted.expiresAt ?? 0
431
432
  };
432
433
  }
433
434
  }
@@ -579,7 +580,9 @@ var DefaultTokenProvider = class {
579
580
  };
580
581
  this.anonStore?.write({
581
582
  refreshToken: this.anon.refreshToken,
582
- sessionId: this.anon.sessionId
583
+ sessionId: this.anon.sessionId,
584
+ accessToken: this.anon.accessToken,
585
+ expiresAt: this.anon.expiresAt
583
586
  });
584
587
  this.notifyRefresh("anonymous", true);
585
588
  return this.stripExpiry(this.anon);
@@ -890,7 +893,7 @@ var HttpClient = class {
890
893
  };
891
894
 
892
895
  // package.json
893
- var version = "2.29.0";
896
+ var version = "2.30.0";
894
897
 
895
898
  // src/version.ts
896
899
  var SDK_VERSION = version;