@revenexx/cover 0.1.0 → 0.1.2

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 (42) hide show
  1. package/app/app.config.ts +1 -1
  2. package/app/components/account/AccountSidebar.vue +10 -1
  3. package/app/components/account/address/AccountAddressCard.vue +69 -88
  4. package/app/components/auth/AuthRegisterPanel.vue +122 -194
  5. package/app/formkit.config.ts +21 -0
  6. package/app/interfaces/auth.ts +0 -2
  7. package/app/interfaces/validation.ts +1 -1
  8. package/app/validations/formValidationConfig.ts +0 -30
  9. package/nuxt.config.ts +7 -3
  10. package/package.json +2 -2
  11. package/server/api/account/orders.get.ts +6 -5
  12. package/server/api/account/profile.get.ts +3 -3
  13. package/server/api/account/profile.put.ts +6 -4
  14. package/server/api/auth/login.post.ts +2 -5
  15. package/server/api/auth/recovery.post.ts +5 -13
  16. package/server/api/auth/recovery.put.ts +5 -14
  17. package/server/api/auth/register.post.ts +21 -44
  18. package/server/api/orders/index.post.ts +28 -24
  19. package/server/api/payment/methods.post.ts +5 -4
  20. package/server/api/shipping/rates.post.ts +6 -4
  21. package/server/interfaces/auth.ts +1 -1
  22. package/server/services/ApiAccountService.ts +44 -0
  23. package/server/services/ApiAuthService.ts +15 -14
  24. package/server/services/ApiCartService.ts +45 -27
  25. package/server/services/ApiMarketService.ts +11 -9
  26. package/server/utils/accountService.ts +4 -5
  27. package/server/utils/authService.ts +0 -3
  28. package/server/utils/liveCatalog.ts +30 -17
  29. package/server/utils/liveInventories.ts +4 -4
  30. package/server/utils/liveOrders.ts +5 -3
  31. package/server/utils/livePrices.ts +10 -9
  32. package/server/utils/revenexxSdk.ts +213 -0
  33. package/app/validations/companyName.ts +0 -18
  34. package/app/validations/maxLength.ts +0 -12
  35. package/app/validations/optionalCompanyName.ts +0 -23
  36. package/app/validations/phoneNumber.ts +0 -19
  37. package/app/validations/termsRequired.ts +0 -4
  38. package/app/validations/zipCode.ts +0 -15
  39. package/server/services/SdkAccountService.ts +0 -56
  40. package/server/services/SdkAuthService.ts +0 -83
  41. package/server/utils/revenexxApi.ts +0 -136
  42. package/server/utils/shopSdk.ts +0 -88
@@ -34,9 +34,9 @@ function contactName(contact: ApiContact | null, fallback: string): string {
34
34
 
35
35
  /**
36
36
  * Live authentication via the public revenexx API (customers app):
37
- * POST /v1/customers/auth/login → platform session (incl. secret) + contact
38
- * POST /v1/customers/auth/me → platform user + contact
39
- * POST /v1/customers/auth/logout → revokes the platform session
37
+ * customersAuthLogin → platform session (incl. secret) + contact
38
+ * auth/me (raw call) → platform user + contact
39
+ * customersAuthLogout → revokes the platform session
40
40
  *
41
41
  * Session state lives in the same cookie as the other implementations, so
42
42
  * the client-side auth flow (store, guards, middleware) is identical. The
@@ -44,11 +44,10 @@ function contactName(contact: ApiContact | null, fallback: string): string {
44
44
  */
45
45
  export class ApiAuthService implements IAuthService {
46
46
  async login(event: H3Event, email: string, password: string): Promise<AuthLoginResult> {
47
- const api = useRevenexxApi();
48
- const { session, contact } = await api.post<{ session: ApiSession; contact: ApiContact | null }>(
49
- "/v1/customers/auth/login",
50
- { email, password },
51
- );
47
+ const { session, contact } = await useRevenexxSdk().customers.customersAuthLogin({ email, password }) as unknown as {
48
+ session: ApiSession;
49
+ contact: ApiContact | null;
50
+ };
52
51
 
53
52
  const storedSession: StoredSession = {
54
53
  id: session.$id,
@@ -94,11 +93,13 @@ export class ApiAuthService implements IAuthService {
94
93
 
95
94
  try {
96
95
  // session_id makes the customers app validate the session is still
97
- // alive — a logged-out/revoked session answers 401 here.
98
- const { user, contact } = await useRevenexxApi().post<{
96
+ // alive — a logged-out/revoked session answers 401 here. Raw call:
97
+ // the AuthMeRequest contract does not declare session_id yet, so
98
+ // the generated customersAuthMe() would drop the session check.
99
+ const { user, contact } = await useRevenexxSdk().call<{
99
100
  user: { $id: string; name?: string; email: string };
100
101
  contact: ApiContact | null;
101
- }>("/v1/customers/auth/me", { user_id: parsed.userId, session_id: parsed.id });
102
+ }>("POST", "/v1/customers/auth/me", { body: { user_id: parsed.userId, session_id: parsed.id } });
102
103
 
103
104
  return {
104
105
  $id: user.$id,
@@ -122,9 +123,9 @@ export class ApiAuthService implements IAuthService {
122
123
  try {
123
124
  const parsed = JSON.parse(raw) as StoredSession;
124
125
  if (parsed.userId && parsed.id) {
125
- await useRevenexxApi().post("/v1/customers/auth/logout", {
126
- user_id: parsed.userId,
127
- session_id: parsed.id,
126
+ await useRevenexxSdk().customers.customersAuthLogout({
127
+ userId: parsed.userId,
128
+ sessionId: parsed.id,
128
129
  });
129
130
  }
130
131
  }
@@ -1,4 +1,5 @@
1
1
  import type { H3Event } from "h3";
2
+ import type { Models } from "@revenexx/sdk";
2
3
 
3
4
  import type { CartItem } from "../../app/interfaces/cart-item";
4
5
  import type { StoredSession } from "../../app/interfaces/auth";
@@ -137,11 +138,15 @@ function toSummary(cart: ApiCart): CartSummaryRow {
137
138
  */
138
139
  export class ApiCartService implements ICartService, ICartManager {
139
140
  private async listActive(owner: CartOwner): Promise<ApiCart[]> {
140
- const { items } = await useRevenexxApi().get<{ items: ApiCart[] }>("/v1/carts", {
141
- ...ownerQuery(owner),
142
- status: "active",
143
- limit: 100,
144
- order: "updated_at.desc",
141
+ // Raw call: carts.list does not declare its query parameters in the
142
+ // contract yet, so the generated cartsList() cannot filter by owner.
143
+ const { items } = await useRevenexxSdk().call<{ items: ApiCart[] }>("GET", "/v1/carts", {
144
+ query: {
145
+ ...ownerQuery(owner),
146
+ status: "active",
147
+ limit: 100,
148
+ order: "updated_at.desc",
149
+ },
145
150
  });
146
151
  return items;
147
152
  }
@@ -152,11 +157,11 @@ export class ApiCartService implements ICartService, ICartManager {
152
157
  if (current) {
153
158
  return current;
154
159
  }
155
- return useRevenexxApi().post<ApiCart>("/v1/carts", {
160
+ return await useRevenexxSdk().carts.cartsCreate({
156
161
  name: DEFAULT_CART_NAME,
157
- ...(owner.contactId ? { contact_id: owner.contactId } : { session_key: owner.sessionKey }),
158
- is_current: true,
159
- });
162
+ ...(owner.contactId ? { contactId: owner.contactId } : { sessionKey: owner.sessionKey }),
163
+ isCurrent: true,
164
+ }) as unknown as ApiCart;
160
165
  }
161
166
 
162
167
  // ---- ICartService (the active cart) --------------------------------
@@ -168,16 +173,16 @@ export class ApiCartService implements ICartService, ICartManager {
168
173
  if (!current) {
169
174
  return [];
170
175
  }
171
- const { items } = await useRevenexxApi().get<{ items: ApiCartLine[] }>(`/v1/carts/${current.id}/items`);
176
+ const { items } = await useRevenexxSdk().carts.cartsItemsList({ cartId: current.id }) as unknown as { items: ApiCartLine[] };
172
177
  return items.map(toCartItem);
173
178
  }
174
179
 
175
180
  async saveItems(event: H3Event, items: CartItem[]): Promise<void> {
176
181
  const owner = resolveOwner(event);
177
182
  const cart = await this.ensureActiveCart(owner);
178
- await useRevenexxApi().request(`/v1/carts/${cart.id}/items`, {
179
- method: "PUT",
180
- body: { items: items.map((item, index) => toApiLine(item, index)) },
183
+ await useRevenexxSdk().carts.cartsItemsReplace({
184
+ cartId: cart.id,
185
+ items: items.map((item, index) => toApiLine(item, index)) as unknown as Models.CartItemCreateRequest[],
181
186
  });
182
187
  }
183
188
 
@@ -199,30 +204,43 @@ export class ApiCartService implements ICartService, ICartManager {
199
204
 
200
205
  async createCart(event: H3Event, name: string, activate: boolean): Promise<CartSummaryRow> {
201
206
  const owner = resolveOwner(event);
202
- const cart = await useRevenexxApi().post<ApiCart>("/v1/carts", {
207
+ const cart = await useRevenexxSdk().carts.cartsCreate({
203
208
  name: name.trim() || DEFAULT_CART_NAME,
204
- ...(owner.contactId ? { contact_id: owner.contactId } : { session_key: owner.sessionKey }),
205
- is_current: activate,
206
- });
209
+ ...(owner.contactId ? { contactId: owner.contactId } : { sessionKey: owner.sessionKey }),
210
+ isCurrent: activate,
211
+ }) as unknown as ApiCart;
207
212
  return { ...toSummary(cart), active: activate };
208
213
  }
209
214
 
210
215
  async renameCart(event: H3Event, id: string, name: string): Promise<void> {
211
- await useRevenexxApi().put(`/v1/carts/${id}`, { name: name.trim() });
216
+ await useRevenexxSdk().carts.cartsUpdate({ id, name: name.trim() });
212
217
  }
213
218
 
214
219
  async deleteCart(event: H3Event, id: string): Promise<void> {
215
- await useRevenexxApi().request(`/v1/carts/${id}`, { method: "DELETE" });
220
+ await useRevenexxSdk().carts.cartsDelete({ id });
216
221
  }
217
222
 
218
223
  async activateCart(event: H3Event, id: string): Promise<CartItem[]> {
219
- await useRevenexxApi().post(`/v1/carts/${id}/activate`, {});
220
- const { items } = await useRevenexxApi().get<{ items: ApiCartLine[] }>(`/v1/carts/${id}/items`);
224
+ await useRevenexxSdk().carts.cartsActivate({ id });
225
+ const { items } = await useRevenexxSdk().carts.cartsItemsList({ cartId: id }) as unknown as { items: ApiCartLine[] };
221
226
  return items.map(toCartItem);
222
227
  }
223
228
 
224
229
  async addItemToCart(event: H3Event, id: string, item: CartItem): Promise<void> {
225
- await useRevenexxApi().post(`/v1/carts/${id}/items`, toApiLine(item, 0));
230
+ const line = toApiLine(item, 0);
231
+ await useRevenexxSdk().carts.cartsItemsCreate({
232
+ cartId: id,
233
+ ...(line.product_id ? { productId: String(line.product_id) } : {}),
234
+ ...(line.sku ? { sku: String(line.sku) } : {}),
235
+ name: String(line.name),
236
+ quantity: Number(line.quantity),
237
+ ...(line.unit ? { unit: String(line.unit) } : {}),
238
+ unitPrice: Number(line.unit_price),
239
+ taxRate: Number(line.tax_rate),
240
+ position: Number(line.position),
241
+ snapshot: line.snapshot as object,
242
+ metadata: line.metadata as object,
243
+ });
226
244
  }
227
245
 
228
246
  async orderActiveCart(event: H3Event, orderRef: string): Promise<string | null> {
@@ -232,7 +250,7 @@ export class ApiCartService implements ICartService, ICartManager {
232
250
  if (!current) {
233
251
  return null;
234
252
  }
235
- await useRevenexxApi().post(`/v1/carts/${current.id}/order`, { order_ref: orderRef });
253
+ await useRevenexxSdk().carts.cartsOrder({ id: current.id, orderRef });
236
254
  return current.id;
237
255
  }
238
256
 
@@ -245,10 +263,10 @@ export class ApiCartService implements ICartService, ICartManager {
245
263
  // the session cart is adopted as the customer's cart.
246
264
  const customerCarts = await this.listActive({ contactId, sessionKey: "" });
247
265
  const target = customerCarts.find(c => c.is_current) ?? customerCarts[0];
248
- await useRevenexxApi().post("/v1/carts/claim", {
249
- session_key: sessionKey,
250
- contact_id: contactId,
251
- ...(target ? { target_cart_id: target.id } : {}),
266
+ await useRevenexxSdk().carts.cartsClaim({
267
+ sessionKey,
268
+ contactId,
269
+ ...(target ? { targetCartId: target.id } : {}),
252
270
  });
253
271
  }
254
272
  }
@@ -25,7 +25,9 @@ interface ApiListPage<T> {
25
25
 
26
26
  const MARKET_CACHE_TTL_MS = 5 * 60 * 1000;
27
27
 
28
- let cache: { markets: ShopMarket[]; loadedAt: number } | null = null;
28
+ // Partitioned by tenant a multi-tenant theme must never serve one
29
+ // tenant's markets to another (see revenexxTenantKey()).
30
+ const cache = new Map<string, { markets: ShopMarket[]; loadedAt: number }>();
29
31
 
30
32
  /**
31
33
  * Live markets via the public revenexx API (markets app):
@@ -34,20 +36,20 @@ let cache: { markets: ShopMarket[]; loadedAt: number } | null = null;
34
36
  */
35
37
  export class ApiMarketService implements IMarketService {
36
38
  async listMarkets(): Promise<ShopMarket[]> {
37
- if (cache && Date.now() - cache.loadedAt < MARKET_CACHE_TTL_MS) {
38
- return cache.markets;
39
+ const tenantKey = revenexxTenantKey();
40
+ const cached = cache.get(tenantKey);
41
+ if (cached && Date.now() - cached.loadedAt < MARKET_CACHE_TTL_MS) {
42
+ return cached.markets;
39
43
  }
40
44
 
41
- const api = useRevenexxApi();
42
- const { items } = await api.get<ApiListPage<ApiMarketRow>>("/v1/markets");
45
+ const sdk = useRevenexxSdk();
46
+ const { items } = await sdk.markets.marketsList() as unknown as ApiListPage<ApiMarketRow>;
43
47
  const active = items
44
48
  .filter(m => m.status === "active")
45
49
  .sort((a, b) => a.position - b.position || a.code.localeCompare(b.code));
46
50
 
47
51
  const markets = await Promise.all(active.map(async (market): Promise<ShopMarket> => {
48
- const { items: locales } = await api.get<ApiListPage<ApiLocaleRow>>(
49
- `/v1/markets/${encodeURIComponent(market.id)}/locales`,
50
- );
52
+ const { items: locales } = await sdk.markets.marketsLocalesList({ marketId: market.id }) as unknown as ApiListPage<ApiLocaleRow>;
51
53
  return {
52
54
  id: market.id,
53
55
  code: market.code,
@@ -65,7 +67,7 @@ export class ApiMarketService implements IMarketService {
65
67
  };
66
68
  }));
67
69
 
68
- cache = { markets, loadedAt: Date.now() };
70
+ cache.set(tenantKey, { markets, loadedAt: Date.now() });
69
71
  return markets;
70
72
  }
71
73
  }
@@ -1,19 +1,18 @@
1
1
  import type { H3Event } from "h3";
2
2
 
3
3
  import type { IAccountService } from "../interfaces/account";
4
+ import { ApiAccountService } from "../services/ApiAccountService";
4
5
  import { MockAccountService } from "../services/MockAccountService";
5
- import { SdkAccountService } from "../services/SdkAccountService";
6
6
 
7
7
  /**
8
8
  * Registry of available account service implementations.
9
9
  * The active implementation is selected by the `accountService` key in app.config.ts:
10
10
  * - "mock" — demo identity from the bundled config asset
11
- * - "sdk" — live identity via the revenexx web SDK (requires NUXT_WEB_SDK_*
12
- * runtime config and an authenticated session)
11
+ * - "api" — live identity via the public revenexx API (customers app)
13
12
  */
14
13
  const serviceRegistry: Record<string, IAccountService> = {
15
14
  mock: new MockAccountService("account/user.json"),
16
- sdk: new SdkAccountService(),
15
+ api: new ApiAccountService(),
17
16
  };
18
17
 
19
18
  /**
@@ -24,7 +23,7 @@ export function getAccountService(event?: H3Event): IAccountService {
24
23
  const key = resolveServiceKey(event, {
25
24
  domain: "accountService",
26
25
  mockKey: "mock",
27
- liveKey: "sdk",
26
+ liveKey: "api",
28
27
  });
29
28
  return serviceRegistry[key] ?? serviceRegistry["mock"]!;
30
29
  }
@@ -3,20 +3,17 @@ import type { H3Event } from "h3";
3
3
  import type { IAuthService } from "../interfaces/auth";
4
4
  import { ApiAuthService } from "../services/ApiAuthService";
5
5
  import { MockAuthService } from "../services/MockAuthService";
6
- import { SdkAuthService } from "../services/SdkAuthService";
7
6
 
8
7
  /**
9
8
  * Registry of available auth implementations:
10
9
  * - "mock" — offline login as bundled B2B demo personas (buyer/approver/admin)
11
10
  * - "api" — live authentication via the public revenexx API (customers app)
12
- * - "sdk" — live authentication via the revenexx web SDK (direct platform)
13
11
  */
14
12
  const mockAuthService = new MockAuthService("account/personas.json");
15
13
 
16
14
  const serviceRegistry: Record<string, IAuthService> = {
17
15
  mock: mockAuthService,
18
16
  api: new ApiAuthService(),
19
- sdk: new SdkAuthService(),
20
17
  };
21
18
 
22
19
  export function getAuthService(event?: H3Event): IAuthService {
@@ -1,3 +1,5 @@
1
+ import { Collection } from "@revenexx/sdk";
2
+
1
3
  import type { ProductCategory, ProductSubcategory } from "../../app/config/navigation";
2
4
  import type { Product } from "../../app/composables/useProducts";
3
5
  import type { ProductDetail } from "../../app/interfaces/product-detail";
@@ -58,16 +60,22 @@ const LIVE_DEFAULT_TAX_RATE = 19;
58
60
  const LIVE_DEFAULT_STOCK = { quantity: 9999, maxOrderQuantity: 999999 };
59
61
 
60
62
  export async function searchLiveProducts(params: LiveSearchParams): Promise<LiveSearchResponse> {
61
- return useRevenexxApi().get<LiveSearchResponse>(
62
- "/v1/search/collections/products/documents/search",
63
+ // Raw call (GET form): the gateway currently 404s the POST search route
64
+ // its spec declares, and the GET contract does not declare facet_by —
65
+ // the generated search methods can't cover this call yet.
66
+ return useRevenexxSdk().call<LiveSearchResponse>(
67
+ "GET",
68
+ `/v1/search/collections/${Collection.Products}/documents/search`,
63
69
  {
64
- q: params.q,
65
- query_by: params.queryBy ?? "name,sku,description,manufacturer",
66
- filter_by: params.filterBy,
67
- facet_by: params.facetBy,
68
- sort_by: params.sortBy,
69
- page: params.page ?? 1,
70
- per_page: params.perPage ?? 24,
70
+ query: {
71
+ q: params.q,
72
+ query_by: params.queryBy ?? "name,sku,description,manufacturer",
73
+ filter_by: params.filterBy,
74
+ facet_by: params.facetBy,
75
+ sort_by: params.sortBy,
76
+ page: params.page ?? 1,
77
+ per_page: params.perPage ?? 24,
78
+ },
71
79
  },
72
80
  );
73
81
  }
@@ -167,21 +175,26 @@ interface LiveCategoryPage {
167
175
  const CATEGORY_CACHE_TTL_MS = 5 * 60 * 1000;
168
176
  const CATEGORY_PAGE_LIMIT = 200;
169
177
 
170
- let categoryCache: { rows: LiveCategoryRow[]; loadedAt: number } | null = null;
178
+ // Partitioned by tenant a multi-tenant theme must never serve one
179
+ // tenant's category tree to another (see revenexxTenantKey()).
180
+ const categoryCache = new Map<string, { rows: LiveCategoryRow[]; loadedAt: number }>();
171
181
 
172
182
  async function loadLiveCategoryRows(): Promise<LiveCategoryRow[]> {
173
- if (categoryCache && Date.now() - categoryCache.loadedAt < CATEGORY_CACHE_TTL_MS) {
174
- return categoryCache.rows;
183
+ const tenantKey = revenexxTenantKey();
184
+ const cached = categoryCache.get(tenantKey);
185
+ if (cached && Date.now() - cached.loadedAt < CATEGORY_CACHE_TTL_MS) {
186
+ return cached.rows;
175
187
  }
176
188
 
177
- const api = useRevenexxApi();
189
+ const sdk = useRevenexxSdk();
178
190
  const rows: LiveCategoryRow[] = [];
179
191
  let offset = 0;
180
192
  // Paginate defensively — the demo tenant has a few hundred categories.
193
+ // Raw call: the categories list contract does not declare limit/offset
194
+ // yet, so the generated productsCategoriesList() cannot paginate.
181
195
  for (let pageIndex = 0; pageIndex < 25; pageIndex++) {
182
- const page = await api.get<LiveCategoryPage>("/v1/products/categories", {
183
- limit: CATEGORY_PAGE_LIMIT,
184
- offset,
196
+ const page = await sdk.call<LiveCategoryPage>("GET", "/v1/products/categories", {
197
+ query: { limit: CATEGORY_PAGE_LIMIT, offset },
185
198
  });
186
199
  rows.push(...page.items);
187
200
  if (!page.page.hasMore) {
@@ -190,7 +203,7 @@ async function loadLiveCategoryRows(): Promise<LiveCategoryRow[]> {
190
203
  offset += page.page.returned;
191
204
  }
192
205
 
193
- categoryCache = { rows, loadedAt: Date.now() };
206
+ categoryCache.set(tenantKey, { rows, loadedAt: Date.now() });
194
207
  return rows;
195
208
  }
196
209
 
@@ -1,4 +1,5 @@
1
1
  import type { H3Event } from "h3";
2
+ import type { Models } from "@revenexx/sdk";
2
3
 
3
4
  import type { Product } from "../../app/composables/useProducts";
4
5
  import type { ProductDetail } from "../../app/interfaces/product-detail";
@@ -30,10 +31,9 @@ function toStock(entry: ItemAvailability): { quantity: number; maxOrderQuantity:
30
31
  }
31
32
 
32
33
  async function fetchAvailability(items: Array<{ product_id?: string; sku?: string }>): Promise<Map<string, ItemAvailability>> {
33
- const { availability } = await useRevenexxApi().post<{ availability: ItemAvailability[] }>(
34
- "/v1/inventories/availability",
35
- { items },
36
- );
34
+ const { availability } = await useRevenexxSdk().inventories.inventoriesAvailability({
35
+ items: items as Models.InventoryAvailabilityItem[],
36
+ }) as unknown as { availability: ItemAvailability[] };
37
37
  const byKey = new Map<string, ItemAvailability>();
38
38
  for (const entry of availability) {
39
39
  if (entry.product_id) byKey.set(entry.product_id, entry);
@@ -129,11 +129,13 @@ export function mapLiveOrderToAccount(order: LiveOrder): AccountOrder {
129
129
 
130
130
  /** Fetch one live order by its display number (the account history id). */
131
131
  export async function getLiveOrderByNumber(number: string): Promise<LiveOrder | null> {
132
- const api = useRevenexxApi();
133
- const { items } = await api.get<{ items: LiveOrder[] }>("/v1/orders", { number, limit: 1 });
132
+ const sdk = useRevenexxSdk();
133
+ // Raw call: orders.list does not declare its query parameters in the
134
+ // contract yet, so the generated ordersList() cannot filter by number.
135
+ const { items } = await sdk.call<{ items: LiveOrder[] }>("GET", "/v1/orders", { query: { number, limit: 1 } });
134
136
  const row = items[0];
135
137
  if (!row) {
136
138
  return null;
137
139
  }
138
- return api.get<LiveOrder>(`/v1/orders/${row.id}`);
140
+ return await sdk.orders.ordersGet({ id: row.id }) as unknown as LiveOrder;
139
141
  }
@@ -1,4 +1,5 @@
1
1
  import type { H3Event } from "h3";
2
+ import type { Models } from "@revenexx/sdk";
2
3
 
3
4
  import type { StoredSession } from "../../app/interfaces/auth";
4
5
  import type { Product } from "../../app/composables/useProducts";
@@ -21,7 +22,7 @@ interface ResolvedPrice {
21
22
  }
22
23
 
23
24
  /** The buyer's price scope from the session (guests resolve openly). */
24
- function priceContext(event: H3Event): { contact_id?: string; organization_id?: string } {
25
+ function priceContext(event: H3Event): { contactId?: string; organizationId?: string } {
25
26
  const raw = getCookie(event, SESSION_COOKIE_NAME);
26
27
  if (!raw) {
27
28
  return {};
@@ -29,8 +30,8 @@ function priceContext(event: H3Event): { contact_id?: string; organization_id?:
29
30
  try {
30
31
  const parsed = JSON.parse(raw) as StoredSession;
31
32
  return {
32
- ...(parsed.contactId ? { contact_id: parsed.contactId } : {}),
33
- ...(parsed.organizationId ? { organization_id: parsed.organizationId } : {}),
33
+ ...(parsed.contactId ? { contactId: parsed.contactId } : {}),
34
+ ...(parsed.organizationId ? { organizationId: parsed.organizationId } : {}),
34
35
  };
35
36
  }
36
37
  catch {
@@ -61,10 +62,10 @@ export async function enrichProductsWithLivePrices(event: H3Event, products: Pro
61
62
  if (products.length === 0) {
62
63
  return products;
63
64
  }
64
- const { prices } = await useRevenexxApi().post<{ prices: ResolvedPrice[] }>("/v1/prices/resolve", {
65
- items: products.map(p => ({ product_id: p.id, sku: p.sku, quantity: 1 })),
65
+ const { prices } = await useRevenexxSdk().prices.pricesResolve({
66
+ items: products.map(p => ({ product_id: p.id, sku: p.sku, quantity: 1 })) as Models.PriceResolveItem[],
66
67
  ...priceContext(event),
67
- });
68
+ }) as unknown as { prices: ResolvedPrice[] };
68
69
 
69
70
  const byKey = new Map<string, ResolvedPrice>();
70
71
  for (const price of prices) {
@@ -84,10 +85,10 @@ export async function enrichDetailWithLivePrices(event: H3Event, detail: Product
84
85
  if (!product) {
85
86
  return detail;
86
87
  }
87
- const { prices } = await useRevenexxApi().post<{ prices: ResolvedPrice[] }>("/v1/prices/resolve", {
88
- items: [{ product_id: product.id, sku: product.sku, quantity: 1 }],
88
+ const { prices } = await useRevenexxSdk().prices.pricesResolve({
89
+ items: [{ product_id: product.id, sku: product.sku, quantity: 1 }] as Models.PriceResolveItem[],
89
90
  ...priceContext(event),
90
- });
91
+ }) as unknown as { prices: ResolvedPrice[] };
91
92
  const resolved = prices[0];
92
93
  return { ...detail, prices: resolved ? toPriceMap(resolved) : [] };
93
94
  }