@viu/emporix-sdk 2.5.0 → 2.7.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 +40 -0
- package/dist/availability.d.cts +1 -1
- package/dist/availability.d.ts +1 -1
- package/dist/cart.d.cts +1 -1
- package/dist/cart.d.ts +1 -1
- package/dist/category.cjs +49 -8
- package/dist/category.cjs.map +1 -1
- package/dist/category.d.cts +25 -4
- package/dist/category.d.ts +25 -4
- package/dist/category.js +1 -1
- package/dist/checkout.d.cts +1 -1
- package/dist/checkout.d.ts +1 -1
- package/dist/{chunk-4BJUCCKJ.js → chunk-AUVJ5V47.js} +51 -10
- package/dist/chunk-AUVJ5V47.js.map +1 -0
- package/dist/companies.d.cts +1 -1
- package/dist/companies.d.ts +1 -1
- package/dist/contacts.d.cts +1 -1
- package/dist/contacts.d.ts +1 -1
- package/dist/{context-CgUWXqEt.d.cts → context-DJDTlhLW.d.cts} +30 -1
- package/dist/{context-CgUWXqEt.d.ts → context-DJDTlhLW.d.ts} +30 -1
- package/dist/customer-groups.d.cts +1 -1
- package/dist/customer-groups.d.ts +1 -1
- package/dist/customer.d.cts +1 -1
- package/dist/customer.d.ts +1 -1
- package/dist/index.cjs +97 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -3
- package/dist/index.d.ts +11 -3
- package/dist/index.js +50 -6
- package/dist/index.js.map +1 -1
- package/dist/locations.d.cts +1 -1
- package/dist/locations.d.ts +1 -1
- package/dist/media.d.cts +1 -1
- package/dist/media.d.ts +1 -1
- package/dist/orders.d.cts +1 -1
- package/dist/orders.d.ts +1 -1
- package/dist/payment.d.cts +1 -1
- package/dist/payment.d.ts +1 -1
- package/dist/price.d.cts +1 -1
- package/dist/price.d.ts +1 -1
- package/dist/product.d.cts +1 -1
- package/dist/product.d.ts +1 -1
- package/dist/segment.d.cts +1 -1
- package/dist/segment.d.ts +1 -1
- package/package.json +1 -1
- package/dist/chunk-4BJUCCKJ.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,45 @@
|
|
|
1
1
|
# @viu/emporix-sdk
|
|
2
2
|
|
|
3
|
+
## 2.7.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#96](https://github.com/viuteam/emporix-sdk/pull/96) [`da1113a`](https://github.com/viuteam/emporix-sdk/commit/da1113a07f70dceb9f1cb732b28462ccb3671f4a) Thanks [@amnael1](https://github.com/amnael1)! - Fix and extend the Category service for catalogue + hierarchy browsing. Several
|
|
8
|
+
methods targeted routes that don't exist on the deployed category service
|
|
9
|
+
(verified against a live tenant):
|
|
10
|
+
- **`categories.productsIn(...)`** requested a non-existent
|
|
11
|
+
`/categories/{id}/products` route (always 404). It now resolves products via
|
|
12
|
+
category **assignments** (`/categories/{id}/assignments` → keep `PRODUCT`
|
|
13
|
+
refs → `/products/search`), preserving its `PaginatedItems<Product>` contract;
|
|
14
|
+
categories with no products return an empty page instead of throwing.
|
|
15
|
+
- **`categories.tree()`** pointed at a non-existent `/categories/{...}Tree`
|
|
16
|
+
route. It now reads `/category-trees` and returns the catalogue's **root
|
|
17
|
+
categories** (`Promise<Category[]>`) for top-level navigation. (Return type
|
|
18
|
+
changed from the previous nested-node shape; the `rootId` argument is removed.)
|
|
19
|
+
- **New `categories.subcategories(categoryId)`** (+ React `useSubcategories`):
|
|
20
|
+
a category's direct child categories, resolved from `CATEGORY` assignment refs
|
|
21
|
+
(mirrors `productsIn`). Returns `[]` when there are none.
|
|
22
|
+
|
|
23
|
+
React `useCategoryTree()` now returns `Category[]` (root categories) and takes no
|
|
24
|
+
`rootId`.
|
|
25
|
+
|
|
26
|
+
## 2.6.0
|
|
27
|
+
|
|
28
|
+
### Minor Changes
|
|
29
|
+
|
|
30
|
+
- [#92](https://github.com/viuteam/emporix-sdk/pull/92) [`45a2bd8`](https://github.com/viuteam/emporix-sdk/commit/45a2bd8d83cb46d775301790cb2efc60805efc90) Thanks [@amnael1](https://github.com/amnael1)! - Add opt-in reactive customer-token auto-refresh.
|
|
31
|
+
|
|
32
|
+
Core: `EmporixClient.setCustomerTokenRefresher(refresher)` registers a
|
|
33
|
+
single-flight `CustomerTokenRefresher`; on a `customer`-kind 401 the HTTP layer
|
|
34
|
+
refreshes once and retries. Off by default — the customer token stays
|
|
35
|
+
caller-owned.
|
|
36
|
+
|
|
37
|
+
React: `EmporixProvider` gains `autoRefreshCustomerToken` and
|
|
38
|
+
`onCustomerSessionExpired`. When enabled, a customer 401 is transparently
|
|
39
|
+
refreshed via the stored refresh token (anonymous-authorized
|
|
40
|
+
`GET /refreshauthtoken`) and the request is retried; B2B `legalEntityId` is
|
|
41
|
+
preserved.
|
|
42
|
+
|
|
3
43
|
## 2.5.0
|
|
4
44
|
|
|
5
45
|
### Minor Changes
|
package/dist/availability.d.cts
CHANGED
package/dist/availability.d.ts
CHANGED
package/dist/cart.d.cts
CHANGED
package/dist/cart.d.ts
CHANGED
package/dist/category.cjs
CHANGED
|
@@ -43,26 +43,67 @@ var CategoryService = class {
|
|
|
43
43
|
const pageSize = params.pageSize ?? 50;
|
|
44
44
|
return iterateAll((pageNumber) => this.list({ pageNumber, pageSize }, auth));
|
|
45
45
|
}
|
|
46
|
-
/**
|
|
47
|
-
|
|
46
|
+
/**
|
|
47
|
+
* The catalogue's **root categories** — the published category trees
|
|
48
|
+
* (`GET /category-trees`). Use these for top-level storefront navigation;
|
|
49
|
+
* drill into a node's children with {@link subcategories}.
|
|
50
|
+
*/
|
|
51
|
+
async tree(auth = ANON) {
|
|
48
52
|
return this.ctx.http.request({
|
|
49
53
|
method: "GET",
|
|
50
|
-
path: `/category/${this.ctx.tenant}/
|
|
51
|
-
|
|
54
|
+
path: `/category/${this.ctx.tenant}/category-trees`,
|
|
55
|
+
auth
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Direct child categories of a category (for hierarchy drill-down). Mirrors
|
|
60
|
+
* {@link productsIn}: reads the category's **assignments** and keeps the
|
|
61
|
+
* `CATEGORY` references, resolving them to full categories. Returns an empty
|
|
62
|
+
* array when the category has no child categories.
|
|
63
|
+
*/
|
|
64
|
+
async subcategories(categoryId, params = {}, auth = ANON) {
|
|
65
|
+
const pageNumber = params.pageNumber ?? 1;
|
|
66
|
+
const pageSize = params.pageSize ?? 50;
|
|
67
|
+
const assignments = await this.ctx.http.request({
|
|
68
|
+
method: "GET",
|
|
69
|
+
path: `/category/${this.ctx.tenant}/categories/${categoryId}/assignments`,
|
|
70
|
+
query: { pageNumber, pageSize },
|
|
52
71
|
auth
|
|
53
72
|
});
|
|
73
|
+
const categoryIds = assignments.map((a) => a.ref?.type?.toUpperCase() === "CATEGORY" ? a.ref.id : void 0).filter((id) => Boolean(id));
|
|
74
|
+
if (categoryIds.length === 0) return [];
|
|
75
|
+
return this.searchByIds(categoryIds, {}, auth);
|
|
54
76
|
}
|
|
55
|
-
/**
|
|
77
|
+
/**
|
|
78
|
+
* One page of products in a category. The category service exposes products
|
|
79
|
+
* as **assignments** (`/categories/{id}/assignments`) — references, not full
|
|
80
|
+
* products — so this fetches a page of assignments, keeps the `PRODUCT`
|
|
81
|
+
* references, and resolves them to full products via `/products/search`.
|
|
82
|
+
* `hasNextPage` reflects the assignments page (the source of truth for
|
|
83
|
+
* pagination).
|
|
84
|
+
*/
|
|
56
85
|
async productsIn(categoryId, params = {}, auth = ANON) {
|
|
57
86
|
const pageNumber = params.pageNumber ?? 1;
|
|
58
87
|
const pageSize = params.pageSize ?? 50;
|
|
59
|
-
const
|
|
88
|
+
const assignments = await this.ctx.http.request({
|
|
60
89
|
method: "GET",
|
|
61
|
-
path: `/category/${this.ctx.tenant}/categories/${categoryId}/
|
|
90
|
+
path: `/category/${this.ctx.tenant}/categories/${categoryId}/assignments`,
|
|
62
91
|
query: { pageNumber, pageSize },
|
|
63
92
|
auth
|
|
64
93
|
});
|
|
65
|
-
|
|
94
|
+
const hasNextPage = assignments.length === pageSize;
|
|
95
|
+
const productIds = assignments.map((a) => a.ref?.type?.toUpperCase() === "PRODUCT" ? a.ref.id : void 0).filter((id) => Boolean(id));
|
|
96
|
+
if (productIds.length === 0) {
|
|
97
|
+
return { items: [], pageNumber, pageSize, hasNextPage };
|
|
98
|
+
}
|
|
99
|
+
const items = await this.ctx.http.request({
|
|
100
|
+
method: "POST",
|
|
101
|
+
path: `/product/${this.ctx.tenant}/products/search`,
|
|
102
|
+
query: { pageSize: productIds.length },
|
|
103
|
+
auth,
|
|
104
|
+
body: { q: `id:(${productIds.join(",")})` }
|
|
105
|
+
});
|
|
106
|
+
return { items, pageNumber, pageSize, hasNextPage };
|
|
66
107
|
}
|
|
67
108
|
/**
|
|
68
109
|
* Bulk fetch by id. POSTs `/categories/search` with `q="id:(id1,id2,…)"`,
|
package/dist/category.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/context.ts","../src/services/category.ts"],"names":[],"mappings":"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","file":"category.cjs","sourcesContent":["import type { HttpClient } from \"./http\";\nimport type { TokenProvider, AuthContext } from \"./auth\";\nimport type { Logger } from \"./logger\";\n\n/** Shared dependencies every service facade receives. */\nexport interface ClientContext {\n tenant: string;\n http: HttpClient;\n tokenProvider: TokenProvider;\n logger: Logger;\n}\n\n/**\n * A cursor-paged collection — `pageNumber`/`pageSize` indexing with a\n * `hasNextPage` signal driven by the source page being full. Used by all\n * paginated services and hooks across the SDK.\n */\nexport interface PaginatedItems<T> {\n items: T[];\n pageNumber: number;\n pageSize: number;\n hasNextPage: boolean;\n}\n\n/** Default `AuthContext` applied by a service when the caller passes none. */\nexport type DefaultAuth = AuthContext | undefined;\n\n/**\n * Async-iterates every item across pages of a `PaginatedItems<T>` source.\n * Stops when the source reports `hasNextPage: false`.\n *\n * @param fetchPage - given a 1-based page number, returns the page.\n * @param start - first page to fetch (default `1`).\n */\nexport async function* iterateAll<T>(\n fetchPage: (pageNumber: number) => Promise<PaginatedItems<T>>,\n start = 1,\n): AsyncIterable<T> {\n let p = start;\n for (;;) {\n const page = await fetchPage(p);\n for (const it of page.items) yield it;\n if (!page.hasNextPage) return;\n p += 1;\n }\n}\n\n","import type { ClientContext, PaginatedItems } from \"../core/context\";\nimport { iterateAll } from \"../core/context\";\nimport type { AuthContext } from \"../core/auth\";\nimport type { Product } from \"./product\";\nimport type { Category as GeneratedCategory, CategoryTree } from \"../generated/category\";\n\nconst ANON: AuthContext = { kind: \"anonymous\" };\n\n/** A category as returned by the Category service (all generated fields). */\nexport type Category = GeneratedCategory;\n\n/** The category tree as returned by the Category service. */\nexport type CategoryNode = CategoryTree;\n\n/** Category reads. Default auth: anonymous. */\nexport class CategoryService {\n constructor(private readonly ctx: ClientContext) {}\n\n /** Fetches one category by id. */\n async get(categoryId: string, auth: AuthContext = ANON): Promise<Category> {\n return this.ctx.http.request<Category>({\n method: \"GET\",\n path: `/category/${this.ctx.tenant}/categories/${categoryId}`,\n auth,\n });\n }\n\n /** One page of categories. */\n async list(\n params: { pageNumber?: number; pageSize?: number } = {},\n auth: AuthContext = ANON,\n ): Promise<PaginatedItems<Category>> {\n const pageNumber = params.pageNumber ?? 1;\n const pageSize = params.pageSize ?? 50;\n const items = await this.ctx.http.request<Category[]>({\n method: \"GET\",\n path: `/category/${this.ctx.tenant}/categories`,\n query: { pageNumber, pageSize },\n auth,\n });\n return { items, pageNumber, pageSize, hasNextPage: items.length === pageSize };\n }\n\n /** Async-iterates every category across pages. */\n listAll(params: { pageSize?: number } = {}, auth: AuthContext = ANON): AsyncIterable<Category> {\n const pageSize = params.pageSize ?? 50;\n return iterateAll<Category>((pageNumber) => this.list({ pageNumber, pageSize }, auth));\n }\n\n /** Fetches the category tree, optionally rooted at `rootId`. */\n async tree(rootId?: string, auth: AuthContext = ANON): Promise<CategoryNode> {\n return this.ctx.http.request<CategoryNode>({\n method: \"GET\",\n path: `/category/${this.ctx.tenant}/categories/tree`,\n query: rootId ? { rootId } : {},\n auth,\n });\n }\n\n /** One page of products in a category. */\n async productsIn(\n categoryId: string,\n params: { pageNumber?: number; pageSize?: number } = {},\n auth: AuthContext = ANON,\n ): Promise<PaginatedItems<Product>> {\n const pageNumber = params.pageNumber ?? 1;\n const pageSize = params.pageSize ?? 50;\n const items = await this.ctx.http.request<Product[]>({\n method: \"GET\",\n path: `/category/${this.ctx.tenant}/categories/${categoryId}/products`,\n query: { pageNumber, pageSize },\n auth,\n });\n return { items, pageNumber, pageSize, hasNextPage: items.length === pageSize };\n }\n\n /**\n * Bulk fetch by id. POSTs `/categories/search` with `q=\"id:(id1,id2,…)\"`,\n * chunking when the list is larger than `options.chunkSize` (default\n * 100). An empty list short-circuits with no HTTP call. **Order is not\n * guaranteed** across chunks — re-index by `id` if order matters.\n */\n async searchByIds(\n ids: string[],\n options: { chunkSize?: number } = {},\n auth: AuthContext = ANON,\n ): Promise<Category[]> {\n if (ids.length === 0) return [];\n const chunkSize = options.chunkSize ?? 100;\n const chunks: string[][] = [];\n for (let i = 0; i < ids.length; i += chunkSize) {\n chunks.push(ids.slice(i, i + chunkSize));\n }\n const pages = await Promise.all(\n chunks.map((chunk) =>\n this.ctx.http.request<Category[]>({\n method: \"POST\",\n path: `/category/${this.ctx.tenant}/categories/search`,\n query: { pageSize: chunk.length },\n auth,\n body: { q: `id:(${chunk.join(\",\")})` },\n }),\n ),\n );\n return pages.flat();\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/context.ts","../src/services/category.ts"],"names":[],"mappings":"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","file":"category.cjs","sourcesContent":["import type { HttpClient } from \"./http\";\nimport type { TokenProvider, AuthContext } from \"./auth\";\nimport type { Logger } from \"./logger\";\n\n/** Shared dependencies every service facade receives. */\nexport interface ClientContext {\n tenant: string;\n http: HttpClient;\n tokenProvider: TokenProvider;\n logger: Logger;\n}\n\n/**\n * A cursor-paged collection — `pageNumber`/`pageSize` indexing with a\n * `hasNextPage` signal driven by the source page being full. Used by all\n * paginated services and hooks across the SDK.\n */\nexport interface PaginatedItems<T> {\n items: T[];\n pageNumber: number;\n pageSize: number;\n hasNextPage: boolean;\n}\n\n/** Default `AuthContext` applied by a service when the caller passes none. */\nexport type DefaultAuth = AuthContext | undefined;\n\n/**\n * Async-iterates every item across pages of a `PaginatedItems<T>` source.\n * Stops when the source reports `hasNextPage: false`.\n *\n * @param fetchPage - given a 1-based page number, returns the page.\n * @param start - first page to fetch (default `1`).\n */\nexport async function* iterateAll<T>(\n fetchPage: (pageNumber: number) => Promise<PaginatedItems<T>>,\n start = 1,\n): AsyncIterable<T> {\n let p = start;\n for (;;) {\n const page = await fetchPage(p);\n for (const it of page.items) yield it;\n if (!page.hasNextPage) return;\n p += 1;\n }\n}\n\n","import type { ClientContext, PaginatedItems } from \"../core/context\";\nimport { iterateAll } from \"../core/context\";\nimport type { AuthContext } from \"../core/auth\";\nimport type { Product } from \"./product\";\nimport type { Category as GeneratedCategory, CategoryTree } from \"../generated/category\";\n\nconst ANON: AuthContext = { kind: \"anonymous\" };\n\n/** A category as returned by the Category service (all generated fields). */\nexport type Category = GeneratedCategory;\n\n/** The category tree as returned by the Category service. */\nexport type CategoryNode = CategoryTree;\n\n/** Category reads. Default auth: anonymous. */\nexport class CategoryService {\n constructor(private readonly ctx: ClientContext) {}\n\n /** Fetches one category by id. */\n async get(categoryId: string, auth: AuthContext = ANON): Promise<Category> {\n return this.ctx.http.request<Category>({\n method: \"GET\",\n path: `/category/${this.ctx.tenant}/categories/${categoryId}`,\n auth,\n });\n }\n\n /** One page of categories. */\n async list(\n params: { pageNumber?: number; pageSize?: number } = {},\n auth: AuthContext = ANON,\n ): Promise<PaginatedItems<Category>> {\n const pageNumber = params.pageNumber ?? 1;\n const pageSize = params.pageSize ?? 50;\n const items = await this.ctx.http.request<Category[]>({\n method: \"GET\",\n path: `/category/${this.ctx.tenant}/categories`,\n query: { pageNumber, pageSize },\n auth,\n });\n return { items, pageNumber, pageSize, hasNextPage: items.length === pageSize };\n }\n\n /** Async-iterates every category across pages. */\n listAll(params: { pageSize?: number } = {}, auth: AuthContext = ANON): AsyncIterable<Category> {\n const pageSize = params.pageSize ?? 50;\n return iterateAll<Category>((pageNumber) => this.list({ pageNumber, pageSize }, auth));\n }\n\n /**\n * The catalogue's **root categories** — the published category trees\n * (`GET /category-trees`). Use these for top-level storefront navigation;\n * drill into a node's children with {@link subcategories}.\n */\n async tree(auth: AuthContext = ANON): Promise<Category[]> {\n return this.ctx.http.request<Category[]>({\n method: \"GET\",\n path: `/category/${this.ctx.tenant}/category-trees`,\n auth,\n });\n }\n\n /**\n * Direct child categories of a category (for hierarchy drill-down). Mirrors\n * {@link productsIn}: reads the category's **assignments** and keeps the\n * `CATEGORY` references, resolving them to full categories. Returns an empty\n * array when the category has no child categories.\n */\n async subcategories(\n categoryId: string,\n params: { pageNumber?: number; pageSize?: number } = {},\n auth: AuthContext = ANON,\n ): Promise<Category[]> {\n const pageNumber = params.pageNumber ?? 1;\n const pageSize = params.pageSize ?? 50;\n const assignments = await this.ctx.http.request<Array<{ ref?: { id?: string; type?: string } }>>({\n method: \"GET\",\n path: `/category/${this.ctx.tenant}/categories/${categoryId}/assignments`,\n query: { pageNumber, pageSize },\n auth,\n });\n const categoryIds = assignments\n .map((a) => (a.ref?.type?.toUpperCase() === \"CATEGORY\" ? a.ref.id : undefined))\n .filter((id): id is string => Boolean(id));\n if (categoryIds.length === 0) return [];\n return this.searchByIds(categoryIds, {}, auth);\n }\n\n /**\n * One page of products in a category. The category service exposes products\n * as **assignments** (`/categories/{id}/assignments`) — references, not full\n * products — so this fetches a page of assignments, keeps the `PRODUCT`\n * references, and resolves them to full products via `/products/search`.\n * `hasNextPage` reflects the assignments page (the source of truth for\n * pagination).\n */\n async productsIn(\n categoryId: string,\n params: { pageNumber?: number; pageSize?: number } = {},\n auth: AuthContext = ANON,\n ): Promise<PaginatedItems<Product>> {\n const pageNumber = params.pageNumber ?? 1;\n const pageSize = params.pageSize ?? 50;\n const assignments = await this.ctx.http.request<Array<{ ref?: { id?: string; type?: string } }>>({\n method: \"GET\",\n path: `/category/${this.ctx.tenant}/categories/${categoryId}/assignments`,\n query: { pageNumber, pageSize },\n auth,\n });\n const hasNextPage = assignments.length === pageSize;\n const productIds = assignments\n .map((a) => (a.ref?.type?.toUpperCase() === \"PRODUCT\" ? a.ref.id : undefined))\n .filter((id): id is string => Boolean(id));\n if (productIds.length === 0) {\n return { items: [], pageNumber, pageSize, hasNextPage };\n }\n const items = await this.ctx.http.request<Product[]>({\n method: \"POST\",\n path: `/product/${this.ctx.tenant}/products/search`,\n query: { pageSize: productIds.length },\n auth,\n body: { q: `id:(${productIds.join(\",\")})` },\n });\n return { items, pageNumber, pageSize, hasNextPage };\n }\n\n /**\n * Bulk fetch by id. POSTs `/categories/search` with `q=\"id:(id1,id2,…)\"`,\n * chunking when the list is larger than `options.chunkSize` (default\n * 100). An empty list short-circuits with no HTTP call. **Order is not\n * guaranteed** across chunks — re-index by `id` if order matters.\n */\n async searchByIds(\n ids: string[],\n options: { chunkSize?: number } = {},\n auth: AuthContext = ANON,\n ): Promise<Category[]> {\n if (ids.length === 0) return [];\n const chunkSize = options.chunkSize ?? 100;\n const chunks: string[][] = [];\n for (let i = 0; i < ids.length; i += chunkSize) {\n chunks.push(ids.slice(i, i + chunkSize));\n }\n const pages = await Promise.all(\n chunks.map((chunk) =>\n this.ctx.http.request<Category[]>({\n method: \"POST\",\n path: `/category/${this.ctx.tenant}/categories/search`,\n query: { pageSize: chunk.length },\n auth,\n body: { q: `id:(${chunk.join(\",\")})` },\n }),\n ),\n );\n return pages.flat();\n }\n}\n"]}
|
package/dist/category.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as ClientContext, b as AuthContext, P as PaginatedItems } from './context-
|
|
1
|
+
import { C as ClientContext, b as AuthContext, P as PaginatedItems } from './context-DJDTlhLW.cjs';
|
|
2
2
|
import { Product } from './product.cjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -292,9 +292,30 @@ declare class CategoryService {
|
|
|
292
292
|
listAll(params?: {
|
|
293
293
|
pageSize?: number;
|
|
294
294
|
}, auth?: AuthContext): AsyncIterable<Category>;
|
|
295
|
-
/**
|
|
296
|
-
|
|
297
|
-
|
|
295
|
+
/**
|
|
296
|
+
* The catalogue's **root categories** — the published category trees
|
|
297
|
+
* (`GET /category-trees`). Use these for top-level storefront navigation;
|
|
298
|
+
* drill into a node's children with {@link subcategories}.
|
|
299
|
+
*/
|
|
300
|
+
tree(auth?: AuthContext): Promise<Category[]>;
|
|
301
|
+
/**
|
|
302
|
+
* Direct child categories of a category (for hierarchy drill-down). Mirrors
|
|
303
|
+
* {@link productsIn}: reads the category's **assignments** and keeps the
|
|
304
|
+
* `CATEGORY` references, resolving them to full categories. Returns an empty
|
|
305
|
+
* array when the category has no child categories.
|
|
306
|
+
*/
|
|
307
|
+
subcategories(categoryId: string, params?: {
|
|
308
|
+
pageNumber?: number;
|
|
309
|
+
pageSize?: number;
|
|
310
|
+
}, auth?: AuthContext): Promise<Category[]>;
|
|
311
|
+
/**
|
|
312
|
+
* One page of products in a category. The category service exposes products
|
|
313
|
+
* as **assignments** (`/categories/{id}/assignments`) — references, not full
|
|
314
|
+
* products — so this fetches a page of assignments, keeps the `PRODUCT`
|
|
315
|
+
* references, and resolves them to full products via `/products/search`.
|
|
316
|
+
* `hasNextPage` reflects the assignments page (the source of truth for
|
|
317
|
+
* pagination).
|
|
318
|
+
*/
|
|
298
319
|
productsIn(categoryId: string, params?: {
|
|
299
320
|
pageNumber?: number;
|
|
300
321
|
pageSize?: number;
|
package/dist/category.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as ClientContext, b as AuthContext, P as PaginatedItems } from './context-
|
|
1
|
+
import { C as ClientContext, b as AuthContext, P as PaginatedItems } from './context-DJDTlhLW.js';
|
|
2
2
|
import { Product } from './product.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -292,9 +292,30 @@ declare class CategoryService {
|
|
|
292
292
|
listAll(params?: {
|
|
293
293
|
pageSize?: number;
|
|
294
294
|
}, auth?: AuthContext): AsyncIterable<Category>;
|
|
295
|
-
/**
|
|
296
|
-
|
|
297
|
-
|
|
295
|
+
/**
|
|
296
|
+
* The catalogue's **root categories** — the published category trees
|
|
297
|
+
* (`GET /category-trees`). Use these for top-level storefront navigation;
|
|
298
|
+
* drill into a node's children with {@link subcategories}.
|
|
299
|
+
*/
|
|
300
|
+
tree(auth?: AuthContext): Promise<Category[]>;
|
|
301
|
+
/**
|
|
302
|
+
* Direct child categories of a category (for hierarchy drill-down). Mirrors
|
|
303
|
+
* {@link productsIn}: reads the category's **assignments** and keeps the
|
|
304
|
+
* `CATEGORY` references, resolving them to full categories. Returns an empty
|
|
305
|
+
* array when the category has no child categories.
|
|
306
|
+
*/
|
|
307
|
+
subcategories(categoryId: string, params?: {
|
|
308
|
+
pageNumber?: number;
|
|
309
|
+
pageSize?: number;
|
|
310
|
+
}, auth?: AuthContext): Promise<Category[]>;
|
|
311
|
+
/**
|
|
312
|
+
* One page of products in a category. The category service exposes products
|
|
313
|
+
* as **assignments** (`/categories/{id}/assignments`) — references, not full
|
|
314
|
+
* products — so this fetches a page of assignments, keeps the `PRODUCT`
|
|
315
|
+
* references, and resolves them to full products via `/products/search`.
|
|
316
|
+
* `hasNextPage` reflects the assignments page (the source of truth for
|
|
317
|
+
* pagination).
|
|
318
|
+
*/
|
|
298
319
|
productsIn(categoryId: string, params?: {
|
|
299
320
|
pageNumber?: number;
|
|
300
321
|
pageSize?: number;
|
package/dist/category.js
CHANGED
package/dist/checkout.d.cts
CHANGED
package/dist/checkout.d.ts
CHANGED
|
@@ -32,26 +32,67 @@ var CategoryService = class {
|
|
|
32
32
|
const pageSize = params.pageSize ?? 50;
|
|
33
33
|
return iterateAll((pageNumber) => this.list({ pageNumber, pageSize }, auth));
|
|
34
34
|
}
|
|
35
|
-
/**
|
|
36
|
-
|
|
35
|
+
/**
|
|
36
|
+
* The catalogue's **root categories** — the published category trees
|
|
37
|
+
* (`GET /category-trees`). Use these for top-level storefront navigation;
|
|
38
|
+
* drill into a node's children with {@link subcategories}.
|
|
39
|
+
*/
|
|
40
|
+
async tree(auth = ANON) {
|
|
37
41
|
return this.ctx.http.request({
|
|
38
42
|
method: "GET",
|
|
39
|
-
path: `/category/${this.ctx.tenant}/
|
|
40
|
-
|
|
43
|
+
path: `/category/${this.ctx.tenant}/category-trees`,
|
|
44
|
+
auth
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Direct child categories of a category (for hierarchy drill-down). Mirrors
|
|
49
|
+
* {@link productsIn}: reads the category's **assignments** and keeps the
|
|
50
|
+
* `CATEGORY` references, resolving them to full categories. Returns an empty
|
|
51
|
+
* array when the category has no child categories.
|
|
52
|
+
*/
|
|
53
|
+
async subcategories(categoryId, params = {}, auth = ANON) {
|
|
54
|
+
const pageNumber = params.pageNumber ?? 1;
|
|
55
|
+
const pageSize = params.pageSize ?? 50;
|
|
56
|
+
const assignments = await this.ctx.http.request({
|
|
57
|
+
method: "GET",
|
|
58
|
+
path: `/category/${this.ctx.tenant}/categories/${categoryId}/assignments`,
|
|
59
|
+
query: { pageNumber, pageSize },
|
|
41
60
|
auth
|
|
42
61
|
});
|
|
62
|
+
const categoryIds = assignments.map((a) => a.ref?.type?.toUpperCase() === "CATEGORY" ? a.ref.id : void 0).filter((id) => Boolean(id));
|
|
63
|
+
if (categoryIds.length === 0) return [];
|
|
64
|
+
return this.searchByIds(categoryIds, {}, auth);
|
|
43
65
|
}
|
|
44
|
-
/**
|
|
66
|
+
/**
|
|
67
|
+
* One page of products in a category. The category service exposes products
|
|
68
|
+
* as **assignments** (`/categories/{id}/assignments`) — references, not full
|
|
69
|
+
* products — so this fetches a page of assignments, keeps the `PRODUCT`
|
|
70
|
+
* references, and resolves them to full products via `/products/search`.
|
|
71
|
+
* `hasNextPage` reflects the assignments page (the source of truth for
|
|
72
|
+
* pagination).
|
|
73
|
+
*/
|
|
45
74
|
async productsIn(categoryId, params = {}, auth = ANON) {
|
|
46
75
|
const pageNumber = params.pageNumber ?? 1;
|
|
47
76
|
const pageSize = params.pageSize ?? 50;
|
|
48
|
-
const
|
|
77
|
+
const assignments = await this.ctx.http.request({
|
|
49
78
|
method: "GET",
|
|
50
|
-
path: `/category/${this.ctx.tenant}/categories/${categoryId}/
|
|
79
|
+
path: `/category/${this.ctx.tenant}/categories/${categoryId}/assignments`,
|
|
51
80
|
query: { pageNumber, pageSize },
|
|
52
81
|
auth
|
|
53
82
|
});
|
|
54
|
-
|
|
83
|
+
const hasNextPage = assignments.length === pageSize;
|
|
84
|
+
const productIds = assignments.map((a) => a.ref?.type?.toUpperCase() === "PRODUCT" ? a.ref.id : void 0).filter((id) => Boolean(id));
|
|
85
|
+
if (productIds.length === 0) {
|
|
86
|
+
return { items: [], pageNumber, pageSize, hasNextPage };
|
|
87
|
+
}
|
|
88
|
+
const items = await this.ctx.http.request({
|
|
89
|
+
method: "POST",
|
|
90
|
+
path: `/product/${this.ctx.tenant}/products/search`,
|
|
91
|
+
query: { pageSize: productIds.length },
|
|
92
|
+
auth,
|
|
93
|
+
body: { q: `id:(${productIds.join(",")})` }
|
|
94
|
+
});
|
|
95
|
+
return { items, pageNumber, pageSize, hasNextPage };
|
|
55
96
|
}
|
|
56
97
|
/**
|
|
57
98
|
* Bulk fetch by id. POSTs `/categories/search` with `q="id:(id1,id2,…)"`,
|
|
@@ -82,5 +123,5 @@ var CategoryService = class {
|
|
|
82
123
|
};
|
|
83
124
|
|
|
84
125
|
export { CategoryService };
|
|
85
|
-
//# sourceMappingURL=chunk-
|
|
86
|
-
//# sourceMappingURL=chunk-
|
|
126
|
+
//# sourceMappingURL=chunk-AUVJ5V47.js.map
|
|
127
|
+
//# sourceMappingURL=chunk-AUVJ5V47.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/services/category.ts"],"names":[],"mappings":"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","file":"chunk-AUVJ5V47.js","sourcesContent":["import type { ClientContext, PaginatedItems } from \"../core/context\";\nimport { iterateAll } from \"../core/context\";\nimport type { AuthContext } from \"../core/auth\";\nimport type { Product } from \"./product\";\nimport type { Category as GeneratedCategory, CategoryTree } from \"../generated/category\";\n\nconst ANON: AuthContext = { kind: \"anonymous\" };\n\n/** A category as returned by the Category service (all generated fields). */\nexport type Category = GeneratedCategory;\n\n/** The category tree as returned by the Category service. */\nexport type CategoryNode = CategoryTree;\n\n/** Category reads. Default auth: anonymous. */\nexport class CategoryService {\n constructor(private readonly ctx: ClientContext) {}\n\n /** Fetches one category by id. */\n async get(categoryId: string, auth: AuthContext = ANON): Promise<Category> {\n return this.ctx.http.request<Category>({\n method: \"GET\",\n path: `/category/${this.ctx.tenant}/categories/${categoryId}`,\n auth,\n });\n }\n\n /** One page of categories. */\n async list(\n params: { pageNumber?: number; pageSize?: number } = {},\n auth: AuthContext = ANON,\n ): Promise<PaginatedItems<Category>> {\n const pageNumber = params.pageNumber ?? 1;\n const pageSize = params.pageSize ?? 50;\n const items = await this.ctx.http.request<Category[]>({\n method: \"GET\",\n path: `/category/${this.ctx.tenant}/categories`,\n query: { pageNumber, pageSize },\n auth,\n });\n return { items, pageNumber, pageSize, hasNextPage: items.length === pageSize };\n }\n\n /** Async-iterates every category across pages. */\n listAll(params: { pageSize?: number } = {}, auth: AuthContext = ANON): AsyncIterable<Category> {\n const pageSize = params.pageSize ?? 50;\n return iterateAll<Category>((pageNumber) => this.list({ pageNumber, pageSize }, auth));\n }\n\n /**\n * The catalogue's **root categories** — the published category trees\n * (`GET /category-trees`). Use these for top-level storefront navigation;\n * drill into a node's children with {@link subcategories}.\n */\n async tree(auth: AuthContext = ANON): Promise<Category[]> {\n return this.ctx.http.request<Category[]>({\n method: \"GET\",\n path: `/category/${this.ctx.tenant}/category-trees`,\n auth,\n });\n }\n\n /**\n * Direct child categories of a category (for hierarchy drill-down). Mirrors\n * {@link productsIn}: reads the category's **assignments** and keeps the\n * `CATEGORY` references, resolving them to full categories. Returns an empty\n * array when the category has no child categories.\n */\n async subcategories(\n categoryId: string,\n params: { pageNumber?: number; pageSize?: number } = {},\n auth: AuthContext = ANON,\n ): Promise<Category[]> {\n const pageNumber = params.pageNumber ?? 1;\n const pageSize = params.pageSize ?? 50;\n const assignments = await this.ctx.http.request<Array<{ ref?: { id?: string; type?: string } }>>({\n method: \"GET\",\n path: `/category/${this.ctx.tenant}/categories/${categoryId}/assignments`,\n query: { pageNumber, pageSize },\n auth,\n });\n const categoryIds = assignments\n .map((a) => (a.ref?.type?.toUpperCase() === \"CATEGORY\" ? a.ref.id : undefined))\n .filter((id): id is string => Boolean(id));\n if (categoryIds.length === 0) return [];\n return this.searchByIds(categoryIds, {}, auth);\n }\n\n /**\n * One page of products in a category. The category service exposes products\n * as **assignments** (`/categories/{id}/assignments`) — references, not full\n * products — so this fetches a page of assignments, keeps the `PRODUCT`\n * references, and resolves them to full products via `/products/search`.\n * `hasNextPage` reflects the assignments page (the source of truth for\n * pagination).\n */\n async productsIn(\n categoryId: string,\n params: { pageNumber?: number; pageSize?: number } = {},\n auth: AuthContext = ANON,\n ): Promise<PaginatedItems<Product>> {\n const pageNumber = params.pageNumber ?? 1;\n const pageSize = params.pageSize ?? 50;\n const assignments = await this.ctx.http.request<Array<{ ref?: { id?: string; type?: string } }>>({\n method: \"GET\",\n path: `/category/${this.ctx.tenant}/categories/${categoryId}/assignments`,\n query: { pageNumber, pageSize },\n auth,\n });\n const hasNextPage = assignments.length === pageSize;\n const productIds = assignments\n .map((a) => (a.ref?.type?.toUpperCase() === \"PRODUCT\" ? a.ref.id : undefined))\n .filter((id): id is string => Boolean(id));\n if (productIds.length === 0) {\n return { items: [], pageNumber, pageSize, hasNextPage };\n }\n const items = await this.ctx.http.request<Product[]>({\n method: \"POST\",\n path: `/product/${this.ctx.tenant}/products/search`,\n query: { pageSize: productIds.length },\n auth,\n body: { q: `id:(${productIds.join(\",\")})` },\n });\n return { items, pageNumber, pageSize, hasNextPage };\n }\n\n /**\n * Bulk fetch by id. POSTs `/categories/search` with `q=\"id:(id1,id2,…)\"`,\n * chunking when the list is larger than `options.chunkSize` (default\n * 100). An empty list short-circuits with no HTTP call. **Order is not\n * guaranteed** across chunks — re-index by `id` if order matters.\n */\n async searchByIds(\n ids: string[],\n options: { chunkSize?: number } = {},\n auth: AuthContext = ANON,\n ): Promise<Category[]> {\n if (ids.length === 0) return [];\n const chunkSize = options.chunkSize ?? 100;\n const chunks: string[][] = [];\n for (let i = 0; i < ids.length; i += chunkSize) {\n chunks.push(ids.slice(i, i + chunkSize));\n }\n const pages = await Promise.all(\n chunks.map((chunk) =>\n this.ctx.http.request<Category[]>({\n method: \"POST\",\n path: `/category/${this.ctx.tenant}/categories/search`,\n query: { pageSize: chunk.length },\n auth,\n body: { q: `id:(${chunk.join(\",\")})` },\n }),\n ),\n );\n return pages.flat();\n }\n}\n"]}
|
package/dist/companies.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as ClientContext, b as AuthContext } from './context-
|
|
1
|
+
import { C as ClientContext, b as AuthContext } from './context-DJDTlhLW.cjs';
|
|
2
2
|
import { L as LegalEntity, f as LegalEntityCreate, h as LegalEntityUpdate } from './types.gen-D1QuqPLs.cjs';
|
|
3
3
|
export { A as AccountLimit, e as CustomerGroupRef, g as LegalEntityType, i as LegalInfo } from './types.gen-D1QuqPLs.cjs';
|
|
4
4
|
|
package/dist/companies.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as ClientContext, b as AuthContext } from './context-
|
|
1
|
+
import { C as ClientContext, b as AuthContext } from './context-DJDTlhLW.js';
|
|
2
2
|
import { L as LegalEntity, f as LegalEntityCreate, h as LegalEntityUpdate } from './types.gen-D1QuqPLs.js';
|
|
3
3
|
export { A as AccountLimit, e as CustomerGroupRef, g as LegalEntityType, i as LegalInfo } from './types.gen-D1QuqPLs.js';
|
|
4
4
|
|
package/dist/contacts.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as ClientContext, b as AuthContext } from './context-
|
|
1
|
+
import { C as ClientContext, b as AuthContext } from './context-DJDTlhLW.cjs';
|
|
2
2
|
import { C as ContactAssignment, a as ContactAssignmentCreate, c as ContactAssignmentUpdate } from './types.gen-D1QuqPLs.cjs';
|
|
3
3
|
export { b as ContactAssignmentType } from './types.gen-D1QuqPLs.cjs';
|
|
4
4
|
|
package/dist/contacts.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as ClientContext, b as AuthContext } from './context-
|
|
1
|
+
import { C as ClientContext, b as AuthContext } from './context-DJDTlhLW.js';
|
|
2
2
|
import { C as ContactAssignment, a as ContactAssignmentCreate, c as ContactAssignmentUpdate } from './types.gen-D1QuqPLs.js';
|
|
3
3
|
export { b as ContactAssignmentType } from './types.gen-D1QuqPLs.js';
|
|
4
4
|
|
|
@@ -161,6 +161,19 @@ type AuthContext = {
|
|
|
161
161
|
kind: "raw";
|
|
162
162
|
token: string;
|
|
163
163
|
};
|
|
164
|
+
/**
|
|
165
|
+
* Supplies a fresh customer token when a `customer`-kind request 401s. The host
|
|
166
|
+
* (e.g. EmporixProvider) implements this; the SDK never refreshes the
|
|
167
|
+
* caller-owned customer token unless a refresher is registered.
|
|
168
|
+
*/
|
|
169
|
+
interface CustomerTokenRefresher {
|
|
170
|
+
/**
|
|
171
|
+
* Called on a `customer`-kind 401. Receives the token that just failed;
|
|
172
|
+
* returns a fresh customer token to retry with, or `null` to give up (the
|
|
173
|
+
* 401 then propagates as EmporixAuthError).
|
|
174
|
+
*/
|
|
175
|
+
refresh(expiredToken: string): Promise<string | null>;
|
|
176
|
+
}
|
|
164
177
|
/** An obtained anonymous storefront session. */
|
|
165
178
|
interface AnonymousSession {
|
|
166
179
|
accessToken: string;
|
|
@@ -232,6 +245,20 @@ declare const auth: {
|
|
|
232
245
|
};
|
|
233
246
|
/** Resolves an {@link AuthContext} to a concrete bearer token. */
|
|
234
247
|
declare function resolveToken(ctx: AuthContext, provider: TokenProvider): Promise<string>;
|
|
248
|
+
/**
|
|
249
|
+
* Late-bindable, single-flight holder for an optional
|
|
250
|
+
* {@link CustomerTokenRefresher}. Single-flight is required because Emporix
|
|
251
|
+
* rotates the refresh token on each refresh — concurrent refreshes would
|
|
252
|
+
* invalidate each other. Off (returns `null`) until a refresher is set.
|
|
253
|
+
*/
|
|
254
|
+
declare class CustomerRefreshRegistry {
|
|
255
|
+
private refresher;
|
|
256
|
+
private inflight;
|
|
257
|
+
set(refresher: CustomerTokenRefresher | null): void;
|
|
258
|
+
get enabled(): boolean;
|
|
259
|
+
/** Concurrent callers share one in-flight refresh. */
|
|
260
|
+
refresh(expiredToken: string): Promise<string | null>;
|
|
261
|
+
}
|
|
235
262
|
/** SDK-owned token provider: client-credentials service tokens + anonymous session. */
|
|
236
263
|
declare class DefaultTokenProvider implements TokenProvider {
|
|
237
264
|
private readonly cfg;
|
|
@@ -290,6 +317,8 @@ interface HttpClientOptions {
|
|
|
290
317
|
};
|
|
291
318
|
/** Override the retry backoff delay (ms → Promise). Defaults to a real timer. */
|
|
292
319
|
sleep?: (ms: number) => Promise<void>;
|
|
320
|
+
/** Opt-in customer-token refresher registry (off unless a refresher is set). */
|
|
321
|
+
customerRefresh?: CustomerRefreshRegistry;
|
|
293
322
|
}
|
|
294
323
|
/** Fetch wrapper: auth resolution, JSON parsing, typed error mapping, logging. */
|
|
295
324
|
declare class HttpClient {
|
|
@@ -341,4 +370,4 @@ interface PaginatedItems<T> {
|
|
|
341
370
|
*/
|
|
342
371
|
declare function iterateAll<T>(fetchPage: (pageNumber: number) => Promise<PaginatedItems<T>>, start?: number): AsyncIterable<T>;
|
|
343
372
|
|
|
344
|
-
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,
|
|
373
|
+
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 };
|
|
@@ -161,6 +161,19 @@ type AuthContext = {
|
|
|
161
161
|
kind: "raw";
|
|
162
162
|
token: string;
|
|
163
163
|
};
|
|
164
|
+
/**
|
|
165
|
+
* Supplies a fresh customer token when a `customer`-kind request 401s. The host
|
|
166
|
+
* (e.g. EmporixProvider) implements this; the SDK never refreshes the
|
|
167
|
+
* caller-owned customer token unless a refresher is registered.
|
|
168
|
+
*/
|
|
169
|
+
interface CustomerTokenRefresher {
|
|
170
|
+
/**
|
|
171
|
+
* Called on a `customer`-kind 401. Receives the token that just failed;
|
|
172
|
+
* returns a fresh customer token to retry with, or `null` to give up (the
|
|
173
|
+
* 401 then propagates as EmporixAuthError).
|
|
174
|
+
*/
|
|
175
|
+
refresh(expiredToken: string): Promise<string | null>;
|
|
176
|
+
}
|
|
164
177
|
/** An obtained anonymous storefront session. */
|
|
165
178
|
interface AnonymousSession {
|
|
166
179
|
accessToken: string;
|
|
@@ -232,6 +245,20 @@ declare const auth: {
|
|
|
232
245
|
};
|
|
233
246
|
/** Resolves an {@link AuthContext} to a concrete bearer token. */
|
|
234
247
|
declare function resolveToken(ctx: AuthContext, provider: TokenProvider): Promise<string>;
|
|
248
|
+
/**
|
|
249
|
+
* Late-bindable, single-flight holder for an optional
|
|
250
|
+
* {@link CustomerTokenRefresher}. Single-flight is required because Emporix
|
|
251
|
+
* rotates the refresh token on each refresh — concurrent refreshes would
|
|
252
|
+
* invalidate each other. Off (returns `null`) until a refresher is set.
|
|
253
|
+
*/
|
|
254
|
+
declare class CustomerRefreshRegistry {
|
|
255
|
+
private refresher;
|
|
256
|
+
private inflight;
|
|
257
|
+
set(refresher: CustomerTokenRefresher | null): void;
|
|
258
|
+
get enabled(): boolean;
|
|
259
|
+
/** Concurrent callers share one in-flight refresh. */
|
|
260
|
+
refresh(expiredToken: string): Promise<string | null>;
|
|
261
|
+
}
|
|
235
262
|
/** SDK-owned token provider: client-credentials service tokens + anonymous session. */
|
|
236
263
|
declare class DefaultTokenProvider implements TokenProvider {
|
|
237
264
|
private readonly cfg;
|
|
@@ -290,6 +317,8 @@ interface HttpClientOptions {
|
|
|
290
317
|
};
|
|
291
318
|
/** Override the retry backoff delay (ms → Promise). Defaults to a real timer. */
|
|
292
319
|
sleep?: (ms: number) => Promise<void>;
|
|
320
|
+
/** Opt-in customer-token refresher registry (off unless a refresher is set). */
|
|
321
|
+
customerRefresh?: CustomerRefreshRegistry;
|
|
293
322
|
}
|
|
294
323
|
/** Fetch wrapper: auth resolution, JSON parsing, typed error mapping, logging. */
|
|
295
324
|
declare class HttpClient {
|
|
@@ -341,4 +370,4 @@ interface PaginatedItems<T> {
|
|
|
341
370
|
*/
|
|
342
371
|
declare function iterateAll<T>(fetchPage: (pageNumber: number) => Promise<PaginatedItems<T>>, start?: number): AsyncIterable<T>;
|
|
343
372
|
|
|
344
|
-
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,
|
|
373
|
+
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 };
|
package/dist/customer.d.cts
CHANGED
package/dist/customer.d.ts
CHANGED