@cimplify/sdk 0.82.0 → 0.83.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/dist/mock/msw.mjs CHANGED
@@ -5897,6 +5897,14 @@ function createLinkService({ clock, ids }) {
5897
5897
  };
5898
5898
  }
5899
5899
 
5900
+ // src/mock/state/snapshot.ts
5901
+ function applySnapshot(reg, data) {
5902
+ for (const [k, v] of Object.entries(data)) {
5903
+ const store = reg[k];
5904
+ if (store) store.loadJSON(v);
5905
+ }
5906
+ }
5907
+
5900
5908
  // src/mock/seeds/image.ts
5901
5909
  var CDN_BASE_URL = "https://static-tmp.cimplify.io";
5902
5910
  function seedImage(industry, slug) {
@@ -10264,15 +10272,214 @@ function applySeed(registry, name) {
10264
10272
  return fn(registry);
10265
10273
  }
10266
10274
 
10275
+ // src/mock/seeds/context.ts
10276
+ var SEED_ISO = "2026-01-01T00:00:00.000Z";
10277
+ var ID_PREFIX = {
10278
+ business: "bus_",
10279
+ category: "cat_",
10280
+ collection: "col_",
10281
+ product: "prod_",
10282
+ service: "svc_"
10283
+ };
10284
+ var DEFAULT_CURRENCY = "GHS";
10285
+ function slugify(value) {
10286
+ return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
10287
+ }
10288
+ function makeSeedContext(registry) {
10289
+ let current;
10290
+ const requireBusiness = () => {
10291
+ if (current) return current;
10292
+ const sole = registry.businesses.list();
10293
+ if (sole.length === 1) {
10294
+ current = sole[0];
10295
+ return current;
10296
+ }
10297
+ throw new Error("Seed must create a business (ctx.business) before adding child records.");
10298
+ };
10299
+ const resolveCategoryId = (cat) => {
10300
+ if (!cat) return void 0;
10301
+ if (typeof cat !== "string") return cat.id;
10302
+ if (registry.categories.get(cat)) return cat;
10303
+ return registry.categories.list().find((c) => c.slug === cat)?.id;
10304
+ };
10305
+ const resolveCollectionId = (col) => {
10306
+ if (!col) return void 0;
10307
+ if (typeof col !== "string") return col.id;
10308
+ if (registry.collections.get(col)) return col;
10309
+ return registry.collections.list().find((c) => c.slug === col)?.id;
10310
+ };
10311
+ return {
10312
+ registry,
10313
+ business(input) {
10314
+ const handle = input.handle ?? slugify(input.name);
10315
+ const id = `${ID_PREFIX.business}${slugify(handle)}`;
10316
+ const business = {
10317
+ business_type: "other",
10318
+ email: `hello@${handle}.test`,
10319
+ default_currency: DEFAULT_CURRENCY,
10320
+ default_offers_table_service: false,
10321
+ default_accepts_online_orders: true,
10322
+ status: "active",
10323
+ created_by: "seed",
10324
+ preferences: {},
10325
+ is_online_only: true,
10326
+ enabled_payment_types: ["mobile_money"],
10327
+ default_location_settings: {},
10328
+ country_code: "GH",
10329
+ timezone: "Africa/Accra",
10330
+ ...input,
10331
+ id,
10332
+ handle,
10333
+ created_at: input.created_at ?? SEED_ISO,
10334
+ updated_at: input.updated_at ?? SEED_ISO
10335
+ };
10336
+ registry.businesses.put(id, business);
10337
+ current = business;
10338
+ return business;
10339
+ },
10340
+ category(input) {
10341
+ const business = requireBusiness();
10342
+ const slug = input.slug ?? slugify(input.name);
10343
+ const id = `${ID_PREFIX.category}${slug}`;
10344
+ const category = {
10345
+ id,
10346
+ business_id: business.id,
10347
+ name: input.name,
10348
+ slug,
10349
+ description: input.description,
10350
+ image: input.image,
10351
+ product_ids: [],
10352
+ display_order: input.displayOrder ?? 0,
10353
+ is_active: true,
10354
+ created_at: SEED_ISO,
10355
+ updated_at: SEED_ISO
10356
+ };
10357
+ registry.categories.put(id, category);
10358
+ return category;
10359
+ },
10360
+ collection(input) {
10361
+ const business = requireBusiness();
10362
+ const slug = input.slug ?? slugify(input.name);
10363
+ const id = `${ID_PREFIX.collection}${slug}`;
10364
+ const collection = {
10365
+ id,
10366
+ business_id: business.id,
10367
+ name: input.name,
10368
+ slug,
10369
+ description: input.description,
10370
+ product_ids: [],
10371
+ is_active: true,
10372
+ created_at: SEED_ISO,
10373
+ updated_at: SEED_ISO
10374
+ };
10375
+ registry.collections.put(id, collection);
10376
+ return collection;
10377
+ },
10378
+ product(input) {
10379
+ const business = requireBusiness();
10380
+ const slug = input.slug ?? slugify(input.name);
10381
+ const id = `${ID_PREFIX.product}${slug}`;
10382
+ const categoryId = resolveCategoryId(input.category);
10383
+ const collectionId = resolveCollectionId(input.collection);
10384
+ const product = {
10385
+ id,
10386
+ business_id: business.id,
10387
+ name: input.name,
10388
+ slug,
10389
+ description: input.description,
10390
+ product_type: input.productType ?? "product",
10391
+ base_price: input.price,
10392
+ currency: input.currency ?? business.default_currency,
10393
+ image: input.image,
10394
+ images: input.images ?? (input.image ? [input.image] : []),
10395
+ is_available: true,
10396
+ category_ids: categoryId ? [categoryId] : [],
10397
+ collection_ids: collectionId ? [collectionId] : [],
10398
+ add_on_ids: [],
10399
+ variant_ids: [],
10400
+ tags: input.tags ?? [],
10401
+ calories: input.calories,
10402
+ allergies: input.allergies ?? [],
10403
+ ingredients: input.ingredients ?? [],
10404
+ pairings: [],
10405
+ is_signature: input.isSignature ?? false,
10406
+ is_new: input.isNew ?? false,
10407
+ duration_minutes: input.durationMinutes,
10408
+ metadata: input.metadata,
10409
+ created_at: SEED_ISO,
10410
+ updated_at: SEED_ISO
10411
+ };
10412
+ registry.products.put(id, product);
10413
+ if (categoryId) {
10414
+ const cat = registry.categories.get(categoryId);
10415
+ if (cat && !cat.product_ids.includes(id)) cat.product_ids.push(id);
10416
+ }
10417
+ if (collectionId) {
10418
+ const col = registry.collections.get(collectionId);
10419
+ if (col && !col.product_ids.includes(id)) col.product_ids.push(id);
10420
+ }
10421
+ return product;
10422
+ },
10423
+ service(input) {
10424
+ const business = requireBusiness();
10425
+ const id = `${ID_PREFIX.service}${slugify(input.name)}`;
10426
+ const service = {
10427
+ id,
10428
+ business_id: business.id,
10429
+ name: input.name,
10430
+ description: input.description,
10431
+ duration_minutes: input.durationMinutes,
10432
+ price: input.price,
10433
+ is_available: true
10434
+ };
10435
+ registry.services.put(id, service);
10436
+ return service;
10437
+ },
10438
+ image: seedImage,
10439
+ extend(name) {
10440
+ const result = applySeed(registry, name);
10441
+ current = registry.businesses.get(result.businessId) ?? current;
10442
+ return result;
10443
+ }
10444
+ };
10445
+ }
10446
+
10447
+ // src/mock/seeds/source.ts
10448
+ var SNAPSHOT_META_KEY = "__meta";
10449
+ function loadSnapshot(registry, data, businessId) {
10450
+ applySnapshot(registry, data);
10451
+ if (businessId) return { businessId };
10452
+ const meta = data[SNAPSHOT_META_KEY];
10453
+ if (meta?.defaultBusinessId) return { businessId: meta.defaultBusinessId };
10454
+ const businesses = registry.businesses.list();
10455
+ if (businesses.length === 1) return { businessId: businesses[0].id };
10456
+ if (businesses.length === 0) {
10457
+ throw new Error("Seed snapshot has no business. Add one, or set __meta.defaultBusinessId.");
10458
+ }
10459
+ throw new Error(
10460
+ `Seed snapshot has ${businesses.length} businesses; set __meta.defaultBusinessId to pick one.`
10461
+ );
10462
+ }
10463
+ function resolveSeed(registry, source) {
10464
+ if (typeof source === "string") return applySeed(registry, source);
10465
+ switch (source.kind) {
10466
+ case "builtin":
10467
+ return applySeed(registry, source.name);
10468
+ case "json":
10469
+ return loadSnapshot(registry, source.data, source.businessId);
10470
+ case "fn":
10471
+ return source.seed(makeSeedContext(registry));
10472
+ }
10473
+ }
10474
+
10267
10475
  // src/mock/deps.ts
10268
10476
  function createDeps(options = {}) {
10269
10477
  const clock = createClock({ frozenAt: options.frozenAt });
10270
10478
  const ids = createIdGen(options.rngSeed);
10271
10479
  const bus = createBus({ idGen: () => ids.raw("evt"), clock: () => clock.now() });
10272
10480
  const registry = createStateRegistry();
10273
- const seedName = options.seed ?? "default";
10274
- const seedResult = applySeed(registry, seedName);
10275
- let defaultBusinessId = seedResult.businessId;
10481
+ const seedSource = options.seed ?? "default";
10482
+ let defaultBusinessId = resolveSeed(registry, seedSource).businessId;
10276
10483
  const auth = createAuthService({
10277
10484
  registry,
10278
10485
  clock,
@@ -10326,11 +10533,10 @@ function createDeps(options = {}) {
10326
10533
  return defaultBusinessId;
10327
10534
  },
10328
10535
  chaos,
10329
- resetAll(newSeed) {
10536
+ resetAll(next) {
10330
10537
  for (const store of Object.values(registry)) store.reset();
10331
10538
  bus.clear();
10332
- const r = applySeed(registry, newSeed ?? seedName);
10333
- defaultBusinessId = r.businessId;
10539
+ defaultBusinessId = resolveSeed(registry, next ?? seedSource).businessId;
10334
10540
  return defaultBusinessId;
10335
10541
  }
10336
10542
  };
@@ -1096,10 +1096,94 @@ interface LinkService {
1096
1096
  revokeAllSessions(customerId: string): number;
1097
1097
  }
1098
1098
 
1099
+ /** A whole-registry JSON snapshot: `storeName -> id -> row`. */
1100
+ type RegistrySnapshot = Record<string, Record<string, unknown>>;
1101
+
1099
1102
  type SeedName = "default" | "empty" | "reesa-storefront" | "restaurant" | "retail" | "services" | "grocery" | "fashion" | "pharmacy" | "auto";
1100
1103
 
1104
+ interface SeedBusinessInput extends Partial<Omit<MockBusiness, "id" | "name">> {
1105
+ name: string;
1106
+ }
1107
+ interface SeedCategoryInput {
1108
+ name: string;
1109
+ slug?: string;
1110
+ description?: string;
1111
+ image?: string;
1112
+ displayOrder?: number;
1113
+ }
1114
+ interface SeedCollectionInput {
1115
+ name: string;
1116
+ slug?: string;
1117
+ description?: string;
1118
+ }
1119
+ interface SeedProductInput {
1120
+ name: string;
1121
+ price: string;
1122
+ slug?: string;
1123
+ description?: string;
1124
+ productType?: string;
1125
+ currency?: string;
1126
+ image?: string;
1127
+ images?: string[];
1128
+ category?: MockCategory | string;
1129
+ collection?: MockCollection | string;
1130
+ tags?: string[];
1131
+ isSignature?: boolean;
1132
+ isNew?: boolean;
1133
+ ingredients?: string[];
1134
+ allergies?: string[];
1135
+ calories?: number;
1136
+ durationMinutes?: number;
1137
+ metadata?: Record<string, unknown>;
1138
+ }
1139
+ interface SeedServiceInput {
1140
+ name: string;
1141
+ price: string;
1142
+ durationMinutes: number;
1143
+ description?: string;
1144
+ }
1145
+ /**
1146
+ * Ergonomic builder over the mock state registry. Hands seed authors the same
1147
+ * id-minting, defaulting, and back-reference wiring the built-in seeds do by
1148
+ * hand, while keeping a stable surface even if the underlying store shapes
1149
+ * change. `registry` is the escape hatch for anything not modeled here.
1150
+ */
1151
+ interface SeedContext {
1152
+ readonly registry: StateRegistry;
1153
+ business(input: SeedBusinessInput): MockBusiness;
1154
+ category(input: SeedCategoryInput): MockCategory;
1155
+ collection(input: SeedCollectionInput): MockCollection;
1156
+ product(input: SeedProductInput): MockProduct;
1157
+ service(input: SeedServiceInput): MockService;
1158
+ image(industry: string, slug: string): string;
1159
+ /** Apply a built-in seed first, then keep mutating from there. */
1160
+ extend(name: SeedName): {
1161
+ businessId: string;
1162
+ };
1163
+ }
1164
+ type SeedFn = (ctx: SeedContext) => {
1165
+ businessId: string;
1166
+ };
1167
+
1168
+ /**
1169
+ * Where the mock's initial state comes from. A bare string is a built-in seed
1170
+ * name (back-compat); the object forms open the door to user-supplied data
1171
+ * (`json`) and logic (`fn`).
1172
+ */
1173
+ type SeedSource = SeedName | {
1174
+ kind: "builtin";
1175
+ name: SeedName;
1176
+ } | {
1177
+ kind: "json";
1178
+ data: RegistrySnapshot;
1179
+ businessId?: string;
1180
+ } | {
1181
+ kind: "fn";
1182
+ seed: SeedFn;
1183
+ };
1184
+
1101
1185
  interface MockOptions {
1102
- seed?: SeedName;
1186
+ seed?: SeedSource;
1103
1187
  authMode?: "permissive" | "strict";
1104
1188
  defaultOtp?: string;
1105
1189
  rngSeed?: number;
@@ -1143,7 +1227,7 @@ interface Deps {
1143
1227
  link: LinkService;
1144
1228
  defaultBusinessId: string;
1145
1229
  chaos: ChaosState;
1146
- resetAll: (seed?: SeedName) => string;
1230
+ resetAll: (seed?: SeedSource) => string;
1147
1231
  }
1148
1232
 
1149
1233
  interface CreateAppOptions extends MockOptions {
@@ -1096,10 +1096,94 @@ interface LinkService {
1096
1096
  revokeAllSessions(customerId: string): number;
1097
1097
  }
1098
1098
 
1099
+ /** A whole-registry JSON snapshot: `storeName -> id -> row`. */
1100
+ type RegistrySnapshot = Record<string, Record<string, unknown>>;
1101
+
1099
1102
  type SeedName = "default" | "empty" | "reesa-storefront" | "restaurant" | "retail" | "services" | "grocery" | "fashion" | "pharmacy" | "auto";
1100
1103
 
1104
+ interface SeedBusinessInput extends Partial<Omit<MockBusiness, "id" | "name">> {
1105
+ name: string;
1106
+ }
1107
+ interface SeedCategoryInput {
1108
+ name: string;
1109
+ slug?: string;
1110
+ description?: string;
1111
+ image?: string;
1112
+ displayOrder?: number;
1113
+ }
1114
+ interface SeedCollectionInput {
1115
+ name: string;
1116
+ slug?: string;
1117
+ description?: string;
1118
+ }
1119
+ interface SeedProductInput {
1120
+ name: string;
1121
+ price: string;
1122
+ slug?: string;
1123
+ description?: string;
1124
+ productType?: string;
1125
+ currency?: string;
1126
+ image?: string;
1127
+ images?: string[];
1128
+ category?: MockCategory | string;
1129
+ collection?: MockCollection | string;
1130
+ tags?: string[];
1131
+ isSignature?: boolean;
1132
+ isNew?: boolean;
1133
+ ingredients?: string[];
1134
+ allergies?: string[];
1135
+ calories?: number;
1136
+ durationMinutes?: number;
1137
+ metadata?: Record<string, unknown>;
1138
+ }
1139
+ interface SeedServiceInput {
1140
+ name: string;
1141
+ price: string;
1142
+ durationMinutes: number;
1143
+ description?: string;
1144
+ }
1145
+ /**
1146
+ * Ergonomic builder over the mock state registry. Hands seed authors the same
1147
+ * id-minting, defaulting, and back-reference wiring the built-in seeds do by
1148
+ * hand, while keeping a stable surface even if the underlying store shapes
1149
+ * change. `registry` is the escape hatch for anything not modeled here.
1150
+ */
1151
+ interface SeedContext {
1152
+ readonly registry: StateRegistry;
1153
+ business(input: SeedBusinessInput): MockBusiness;
1154
+ category(input: SeedCategoryInput): MockCategory;
1155
+ collection(input: SeedCollectionInput): MockCollection;
1156
+ product(input: SeedProductInput): MockProduct;
1157
+ service(input: SeedServiceInput): MockService;
1158
+ image(industry: string, slug: string): string;
1159
+ /** Apply a built-in seed first, then keep mutating from there. */
1160
+ extend(name: SeedName): {
1161
+ businessId: string;
1162
+ };
1163
+ }
1164
+ type SeedFn = (ctx: SeedContext) => {
1165
+ businessId: string;
1166
+ };
1167
+
1168
+ /**
1169
+ * Where the mock's initial state comes from. A bare string is a built-in seed
1170
+ * name (back-compat); the object forms open the door to user-supplied data
1171
+ * (`json`) and logic (`fn`).
1172
+ */
1173
+ type SeedSource = SeedName | {
1174
+ kind: "builtin";
1175
+ name: SeedName;
1176
+ } | {
1177
+ kind: "json";
1178
+ data: RegistrySnapshot;
1179
+ businessId?: string;
1180
+ } | {
1181
+ kind: "fn";
1182
+ seed: SeedFn;
1183
+ };
1184
+
1101
1185
  interface MockOptions {
1102
- seed?: SeedName;
1186
+ seed?: SeedSource;
1103
1187
  authMode?: "permissive" | "strict";
1104
1188
  defaultOtp?: string;
1105
1189
  rngSeed?: number;
@@ -1143,7 +1227,7 @@ interface Deps {
1143
1227
  link: LinkService;
1144
1228
  defaultBusinessId: string;
1145
1229
  chaos: ChaosState;
1146
- resetAll: (seed?: SeedName) => string;
1230
+ resetAll: (seed?: SeedSource) => string;
1147
1231
  }
1148
1232
 
1149
1233
  interface CreateAppOptions extends MockOptions {
@@ -1,4 +1,4 @@
1
- import { A as AppHandle, C as CreateAppOptions } from '../server-tr993CPj.mjs';
1
+ import { A as AppHandle, C as CreateAppOptions } from '../server-DaovvB9J.mjs';
2
2
  import 'hono';
3
3
  import '../product-DXhjLQ_w.mjs';
4
4
 
@@ -1,4 +1,4 @@
1
- import { A as AppHandle, C as CreateAppOptions } from '../server-wAB-qfyZ.js';
1
+ import { A as AppHandle, C as CreateAppOptions } from '../server-ZGCyuz4V.js';
2
2
  import 'hono';
3
3
  import '../product-DXhjLQ_w.js';
4
4
 
@@ -1,13 +1,13 @@
1
1
  'use strict';
2
2
 
3
- var chunkSRJEMEVZ_js = require('../chunk-SRJEMEVZ.js');
3
+ var chunkFKBXZ2A6_js = require('../chunk-FKBXZ2A6.js');
4
4
  require('../chunk-XA3ZNR75.js');
5
5
  require('../chunk-OWW5GUSB.js');
6
6
 
7
7
  // src/mock/msw.ts
8
8
  async function createMswHandlers(options = {}) {
9
9
  const baseUrl = options.baseUrl ?? "http://localhost:8787";
10
- const handle = chunkSRJEMEVZ_js.createMockApp(options);
10
+ const handle = chunkFKBXZ2A6_js.createMockApp(options);
11
11
  const msw = await import('msw').catch(() => {
12
12
  throw new Error("msw is required to use @cimplify/sdk/mock/msw \u2014 install it as a peer dependency");
13
13
  });
@@ -1,4 +1,4 @@
1
- import { createMockApp } from '../chunk-BRVIXGUW.mjs';
1
+ import { createMockApp } from '../chunk-PLTP6HWW.mjs';
2
2
  import '../chunk-AMZXALF6.mjs';
3
3
  import '../chunk-3G6RQLXK.mjs';
4
4
 
@@ -1,7 +1,7 @@
1
1
  import { TestAPI } from 'vitest';
2
- import { T as TestClientHandle } from '../client-BSpVgule.mjs';
3
- import { C as CreateAppOptions } from '../server-tr993CPj.mjs';
4
- export { S as SeedName } from '../server-tr993CPj.mjs';
2
+ import { T as TestClientHandle } from '../client-Cogz7C1t.mjs';
3
+ import { C as CreateAppOptions } from '../server-DaovvB9J.mjs';
4
+ export { S as SeedName } from '../server-DaovvB9J.mjs';
5
5
  import '../client-DnHP_2Jw.mjs';
6
6
  import '../product-DXhjLQ_w.mjs';
7
7
  import '../payment-T_0MUE9o.mjs';
@@ -1,7 +1,7 @@
1
1
  import { TestAPI } from 'vitest';
2
- import { T as TestClientHandle } from '../client-Dh-KIIX8.js';
3
- import { C as CreateAppOptions } from '../server-wAB-qfyZ.js';
4
- export { S as SeedName } from '../server-wAB-qfyZ.js';
2
+ import { T as TestClientHandle } from '../client-Cq3B-WXv.js';
3
+ import { C as CreateAppOptions } from '../server-ZGCyuz4V.js';
4
+ export { S as SeedName } from '../server-ZGCyuz4V.js';
5
5
  import '../client-xc2aQSB4.js';
6
6
  import '../product-DXhjLQ_w.js';
7
7
  import '../payment-nH9OCUg2.js';
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunkIZDJEDR4_js = require('../chunk-IZDJEDR4.js');
4
- require('../chunk-SRJEMEVZ.js');
3
+ var chunkODEPW244_js = require('../chunk-ODEPW244.js');
4
+ require('../chunk-FKBXZ2A6.js');
5
5
  require('../chunk-GFM5JW45.js');
6
6
  require('../chunk-HPN5R3K2.js');
7
7
  require('../chunk-7Y2O3E4D.js');
@@ -20,11 +20,11 @@ var PLACEHOLDER_PHRASES = [
20
20
  function createBrandSuite(opts) {
21
21
  vitest.describe(opts.label ?? "brand schema", () => {
22
22
  vitest.it("conforms to the Cimplify brand contract", () => {
23
- vitest.expect(() => chunkIZDJEDR4_js.assertBrand(opts.brand)).not.toThrow();
23
+ vitest.expect(() => chunkODEPW244_js.assertBrand(opts.brand)).not.toThrow();
24
24
  });
25
25
  vitest.it("declares a known mock seed", () => {
26
26
  const b = opts.brand;
27
- vitest.expect(chunkIZDJEDR4_js.SeedNameSchema.safeParse(b.mock?.seed).success).toBe(true);
27
+ vitest.expect(chunkODEPW244_js.SeedNameSchema.safeParse(b.mock?.seed).success).toBe(true);
28
28
  });
29
29
  vitest.it("has no placeholder copy left in", () => {
30
30
  const offenders = [];
@@ -56,7 +56,7 @@ ${msg}`);
56
56
  vitest.expect(b.mock?.businessId).toMatch(/^bus_/);
57
57
  });
58
58
  vitest.it("zod-parses cleanly", () => {
59
- const result = chunkIZDJEDR4_js.BrandSchema.safeParse(opts.brand);
59
+ const result = chunkODEPW244_js.BrandSchema.safeParse(opts.brand);
60
60
  if (!result.success) {
61
61
  throw new Error(
62
62
  "Brand schema violations:\n" + result.error.issues.map((i) => ` \u2022 brand.${i.path.join(".")}: ${i.message}`).join("\n")
@@ -71,23 +71,23 @@ function createCartFlowSuite(opts = {}) {
71
71
  vitest.describe(opts.label ?? "cart flow against in-process mock", () => {
72
72
  let h;
73
73
  vitest.beforeEach(() => {
74
- h = chunkIZDJEDR4_js.createTestClient(opts);
74
+ h = chunkODEPW244_js.createTestClient(opts);
75
75
  });
76
76
  vitest.afterEach(() => h.dispose());
77
77
  vitest.it("starts with an empty cart matching the canonical shape", async () => {
78
78
  const res = await h.client.cart.get();
79
79
  vitest.expect(res.ok).toBe(true);
80
80
  if (!res.ok) return;
81
- vitest.expect(() => chunkIZDJEDR4_js.assertCart(res.value)).not.toThrow();
81
+ vitest.expect(() => chunkODEPW244_js.assertCart(res.value)).not.toThrow();
82
82
  vitest.expect(res.value.items).toHaveLength(0);
83
83
  });
84
84
  vitest.it("adds the first product, persists it, and returns a shape-valid cart", async () => {
85
- const { product, variantId } = await chunkIZDJEDR4_js.fixtures.addFirstProduct(h.client);
85
+ const { product, variantId } = await chunkODEPW244_js.fixtures.addFirstProduct(h.client);
86
86
  vitest.expect(product.id).toBeTruthy();
87
87
  const get = await h.client.cart.get();
88
88
  vitest.expect(get.ok).toBe(true);
89
89
  if (!get.ok) return;
90
- vitest.expect(() => chunkIZDJEDR4_js.assertCart(get.value)).not.toThrow();
90
+ vitest.expect(() => chunkODEPW244_js.assertCart(get.value)).not.toThrow();
91
91
  vitest.expect(get.value.items).toHaveLength(1);
92
92
  vitest.expect(get.value.items[0]?.item_id).toBe(product.id);
93
93
  if (variantId) {
@@ -98,8 +98,8 @@ function createCartFlowSuite(opts = {}) {
98
98
  vitest.expect(parseFloat(String(get.value.pricing.subtotal))).toBeGreaterThan(0);
99
99
  });
100
100
  vitest.it("dedupes by line_key when adding the same product twice", async () => {
101
- await chunkIZDJEDR4_js.fixtures.addFirstProduct(h.client);
102
- await chunkIZDJEDR4_js.fixtures.addFirstProduct(h.client);
101
+ await chunkODEPW244_js.fixtures.addFirstProduct(h.client);
102
+ await chunkODEPW244_js.fixtures.addFirstProduct(h.client);
103
103
  const res = await h.client.cart.get();
104
104
  vitest.expect(res.ok).toBe(true);
105
105
  if (!res.ok) return;
@@ -107,7 +107,7 @@ function createCartFlowSuite(opts = {}) {
107
107
  vitest.expect(res.value.items[0]?.quantity).toBe(2);
108
108
  });
109
109
  vitest.it("removes items and zeroes the subtotal", async () => {
110
- await chunkIZDJEDR4_js.fixtures.addFirstProduct(h.client);
110
+ await chunkODEPW244_js.fixtures.addFirstProduct(h.client);
111
111
  const before = await h.client.cart.get();
112
112
  if (!before.ok) throw before.error;
113
113
  const itemId = before.value.items[0]?.id;
@@ -133,28 +133,28 @@ function createContractSuite(opts = {}) {
133
133
  vitest.describe(opts.label ?? "SDK \u2194 mock contract", () => {
134
134
  let h;
135
135
  vitest.beforeEach(() => {
136
- h = chunkIZDJEDR4_js.createTestClient(opts);
136
+ h = chunkODEPW244_js.createTestClient(opts);
137
137
  });
138
138
  vitest.afterEach(() => h.dispose());
139
139
  vitest.it("AddItemPayload schema accepts a minimal valid body", () => {
140
- const result = chunkIZDJEDR4_js.AddItemPayloadSchema.safeParse({ item_id: "prod_x", quantity: 1 });
140
+ const result = chunkODEPW244_js.AddItemPayloadSchema.safeParse({ item_id: "prod_x", quantity: 1 });
141
141
  vitest.expect(result.success).toBe(true);
142
142
  });
143
143
  vitest.it("AddItemPayload schema rejects negative quantity", () => {
144
- const result = chunkIZDJEDR4_js.AddItemPayloadSchema.safeParse({ item_id: "prod_x", quantity: -1 });
144
+ const result = chunkODEPW244_js.AddItemPayloadSchema.safeParse({ item_id: "prod_x", quantity: -1 });
145
145
  vitest.expect(result.success).toBe(false);
146
146
  });
147
147
  vitest.it("AddItemPayload schema rejects empty item_id", () => {
148
- const result = chunkIZDJEDR4_js.AddItemPayloadSchema.safeParse({ item_id: "", quantity: 1 });
148
+ const result = chunkODEPW244_js.AddItemPayloadSchema.safeParse({ item_id: "", quantity: 1 });
149
149
  vitest.expect(result.success).toBe(false);
150
150
  });
151
151
  vitest.it("Cart line items returned by the mock match CartItemSchema", async () => {
152
- const { product } = await chunkIZDJEDR4_js.fixtures.addFirstProduct(h.client);
152
+ const { product } = await chunkODEPW244_js.fixtures.addFirstProduct(h.client);
153
153
  const get = await h.client.cart.get();
154
154
  if (!get.ok) throw get.error;
155
155
  vitest.expect(get.value.items.length).toBeGreaterThan(0);
156
156
  for (const item of get.value.items) {
157
- const result = chunkIZDJEDR4_js.CartItemSchema.safeParse(item);
157
+ const result = chunkODEPW244_js.CartItemSchema.safeParse(item);
158
158
  if (!result.success) {
159
159
  const issues = result.error.issues.map((i) => ` \u2022 ${i.path.join(".")}: ${i.message}`).join("\n");
160
160
  throw new Error(`Cart item shape mismatch for ${product.name}:
@@ -164,19 +164,19 @@ ${issues}`);
164
164
  }
165
165
  });
166
166
  vitest.it("CheckoutResponse from the mock includes bill_token", async () => {
167
- await chunkIZDJEDR4_js.fixtures.addFirstProduct(h.client);
167
+ await chunkODEPW244_js.fixtures.addFirstProduct(h.client);
168
168
  const cartRes = await h.client.cart.get();
169
169
  if (!cartRes.ok) throw cartRes.error;
170
170
  const checkout = await h.client.checkout.process({
171
171
  cart_id: cartRes.value.id,
172
- customer: chunkIZDJEDR4_js.fixtures.customer(),
172
+ customer: chunkODEPW244_js.fixtures.customer(),
173
173
  order_type: "delivery",
174
174
  payment_method: "mobile_money",
175
175
  mobile_money_details: { phone_number: "+233244000000", provider: "mtn" }
176
176
  });
177
177
  vitest.expect(checkout.ok).toBe(true);
178
178
  if (!checkout.ok) return;
179
- const result = chunkIZDJEDR4_js.CheckoutResponseSchema.safeParse(checkout.value);
179
+ const result = chunkODEPW244_js.CheckoutResponseSchema.safeParse(checkout.value);
180
180
  if (!result.success) {
181
181
  const issues = result.error.issues.map((i) => ` \u2022 ${i.path.join(".")}: ${i.message}`).join("\n");
182
182
  throw new Error(`CheckoutResponse shape mismatch:
@@ -1,5 +1,5 @@
1
- import { assertBrand, SeedNameSchema, BrandSchema, createTestClient, assertCart, fixtures, AddItemPayloadSchema, CartItemSchema, CheckoutResponseSchema } from '../chunk-7PAQR3VC.mjs';
2
- import '../chunk-BRVIXGUW.mjs';
1
+ import { assertBrand, SeedNameSchema, BrandSchema, createTestClient, assertCart, fixtures, AddItemPayloadSchema, CartItemSchema, CheckoutResponseSchema } from '../chunk-I6RE4BKH.mjs';
2
+ import '../chunk-PLTP6HWW.mjs';
3
3
  import '../chunk-NWUEWUX2.mjs';
4
4
  import '../chunk-7BM56JET.mjs';
5
5
  import '../chunk-TD3AY34U.mjs';