@cimplify/sdk 0.44.12 → 0.44.16

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 (99) hide show
  1. package/dist/advanced.d.mts +1 -1
  2. package/dist/advanced.d.ts +1 -1
  3. package/dist/advanced.js +21 -21
  4. package/dist/advanced.mjs +2 -2
  5. package/dist/{chunk-6TVQQYQ5.mjs → chunk-6AZZ6AOF.mjs} +21 -1
  6. package/dist/{chunk-EZK2FXTM.mjs → chunk-7NML226B.mjs} +1 -1
  7. package/dist/{chunk-BAWKQRIB.js → chunk-CFD4J32N.js} +21 -21
  8. package/dist/{chunk-OMAP327U.js → chunk-MBGQP6FZ.js} +62 -61
  9. package/dist/{chunk-V2O5AO7I.js → chunk-MNIKXG7W.js} +26 -0
  10. package/dist/{chunk-3WD6U5RD.mjs → chunk-UXLQ7WXI.mjs} +4 -3
  11. package/dist/chunk-XL4CX75J.js +9370 -0
  12. package/dist/chunk-ZLEFMQC6.mjs +9318 -0
  13. package/dist/cli/commands/deploy.mjs +9 -1
  14. package/dist/{client-lvLvB1_K.d.ts → client-D6ZisKco.d.ts} +7 -0
  15. package/dist/{client-CkGlXZRd.d.mts → client-Dh-bHyhU.d.mts} +7 -0
  16. package/dist/index.d.mts +1 -1
  17. package/dist/index.d.ts +1 -1
  18. package/dist/index.js +106 -106
  19. package/dist/index.mjs +3 -3
  20. package/dist/mock/cli.mjs +172 -23
  21. package/dist/mock/library.d.mts +2 -2
  22. package/dist/mock/library.d.ts +2 -2
  23. package/dist/mock/library.js +172 -23
  24. package/dist/mock/library.mjs +172 -23
  25. package/dist/mock/msw.d.mts +1 -1
  26. package/dist/mock/msw.d.ts +1 -1
  27. package/dist/mock/msw.js +172 -23
  28. package/dist/mock/msw.mjs +172 -23
  29. package/dist/react.d.mts +1 -1
  30. package/dist/react.d.ts +1 -1
  31. package/dist/react.js +80 -80
  32. package/dist/react.mjs +3 -3
  33. package/dist/server-CWpUlLOQ.d.mts +1003 -0
  34. package/dist/server-CWpUlLOQ.d.ts +1003 -0
  35. package/dist/{server-CUbuQxOV.d.ts → server-CnECAQDQ.d.mts} +28 -6
  36. package/dist/{server-CUbuQxOV.d.mts → server-CnECAQDQ.d.ts} +28 -6
  37. package/dist/server.d.mts +2 -2
  38. package/dist/server.d.ts +2 -2
  39. package/dist/server.js +5 -5
  40. package/dist/server.mjs +3 -3
  41. package/dist/testing/suite.d.mts +60 -0
  42. package/dist/testing/suite.d.ts +60 -0
  43. package/dist/testing/suite.js +169 -0
  44. package/dist/testing/suite.mjs +165 -0
  45. package/dist/testing.d.mts +1359 -0
  46. package/dist/testing.d.ts +1359 -0
  47. package/dist/testing.js +213 -0
  48. package/dist/testing.mjs +4 -0
  49. package/dist/utils.js +28 -28
  50. package/dist/utils.mjs +1 -1
  51. package/package.json +18 -3
  52. package/registry/account.json +15 -0
  53. package/registry/billing-plan-selector.json +16 -0
  54. package/registry/cart-drawer.json +17 -0
  55. package/registry/currency-selector.json +15 -0
  56. package/registry/customer-input-fields.json +15 -0
  57. package/registry/delivery-estimate.json +16 -0
  58. package/registry/index.json +105 -0
  59. package/registry/location-picker.json +15 -0
  60. package/registry/recently-viewed.json +16 -0
  61. package/registry/recommendation-carousel.json +16 -0
  62. package/registry/resource-picker.json +15 -0
  63. package/registry/session-message-banner.json +15 -0
  64. package/templates/storefront-bakery/AGENTS.md +12 -0
  65. package/templates/storefront-bakery/__tests__/brand.test.ts +4 -0
  66. package/templates/storefront-bakery/__tests__/cart-flow.test.ts +4 -0
  67. package/templates/storefront-bakery/__tests__/contract.test.ts +4 -0
  68. package/templates/storefront-bakery/package.json +11 -3
  69. package/templates/storefront-bakery/vitest.config.ts +9 -0
  70. package/templates/storefront-fashion/AGENTS.md +21 -1
  71. package/templates/storefront-fashion/__tests__/brand.test.ts +4 -0
  72. package/templates/storefront-fashion/__tests__/cart-flow.test.ts +4 -0
  73. package/templates/storefront-fashion/__tests__/contract.test.ts +4 -0
  74. package/templates/storefront-fashion/package.json +11 -3
  75. package/templates/storefront-fashion/vitest.config.ts +9 -0
  76. package/templates/storefront-grocery/AGENTS.md +12 -0
  77. package/templates/storefront-grocery/__tests__/brand.test.ts +4 -0
  78. package/templates/storefront-grocery/__tests__/cart-flow.test.ts +4 -0
  79. package/templates/storefront-grocery/__tests__/contract.test.ts +4 -0
  80. package/templates/storefront-grocery/package.json +11 -3
  81. package/templates/storefront-grocery/vitest.config.ts +9 -0
  82. package/templates/storefront-restaurant/AGENTS.md +12 -0
  83. package/templates/storefront-restaurant/__tests__/brand.test.ts +4 -0
  84. package/templates/storefront-restaurant/__tests__/cart-flow.test.ts +4 -0
  85. package/templates/storefront-restaurant/__tests__/contract.test.ts +4 -0
  86. package/templates/storefront-restaurant/package.json +11 -3
  87. package/templates/storefront-restaurant/vitest.config.ts +9 -0
  88. package/templates/storefront-retail/AGENTS.md +12 -0
  89. package/templates/storefront-retail/__tests__/brand.test.ts +4 -0
  90. package/templates/storefront-retail/__tests__/cart-flow.test.ts +4 -0
  91. package/templates/storefront-retail/__tests__/contract.test.ts +4 -0
  92. package/templates/storefront-retail/package.json +11 -3
  93. package/templates/storefront-retail/vitest.config.ts +9 -0
  94. package/templates/storefront-services/AGENTS.md +12 -0
  95. package/templates/storefront-services/__tests__/brand.test.ts +4 -0
  96. package/templates/storefront-services/__tests__/cart-flow.test.ts +4 -0
  97. package/templates/storefront-services/__tests__/contract.test.ts +4 -0
  98. package/templates/storefront-services/package.json +11 -3
  99. package/templates/storefront-services/vitest.config.ts +9 -0
@@ -575,6 +575,10 @@ interface AuthService {
575
575
  }): Session;
576
576
  status(token: string | null): {
577
577
  is_authenticated: boolean;
578
+ account_id?: string;
579
+ user_type: "customer" | "guest";
580
+ session_expires_at?: number;
581
+ /** @deprecated Kept for SDK back-compat; production lens does not return this. */
578
582
  session?: Session;
579
583
  };
580
584
  }
@@ -736,6 +740,7 @@ interface CheckoutResult {
736
740
  payment_status: string;
737
741
  payment_reference?: string;
738
742
  requires_authorization: boolean;
743
+ authorization_type?: "otp" | "pin" | "phone" | "birthday" | "address";
739
744
  next_action: {
740
745
  type: "none";
741
746
  } | {
@@ -749,6 +754,12 @@ interface CheckoutResult {
749
754
  provider?: string;
750
755
  authorization_url?: string;
751
756
  display_text?: string;
757
+ /** Bearer token used for guest order access (lookup `/orders/{id}?token=...`). */
758
+ bill_token?: string;
759
+ /** Stripe-style client secret for direct PaymentIntent confirmation. */
760
+ client_secret?: string;
761
+ /** Stripe publishable key (mock value in dev). */
762
+ public_key?: string;
752
763
  }
753
764
 
754
765
  interface OrderService {
@@ -811,22 +822,33 @@ interface SchedulingService {
811
822
  interface InventoryService {
812
823
  productStock(productId: string): {
813
824
  product_id: string;
814
- quantity: number;
815
- available: boolean;
825
+ location_id?: string;
826
+ stock_level: number;
827
+ in_stock: boolean;
816
828
  };
817
829
  variantStock(variantId: string): {
818
830
  variant_id: string;
819
- quantity: number;
820
- available: boolean;
831
+ location_id?: string;
832
+ stock_level: number;
833
+ in_stock: boolean;
821
834
  };
822
- productAvailability(productId: string): {
835
+ productAvailability(productId: string, quantity?: number): {
823
836
  product_id: string;
837
+ quantity: number;
824
838
  is_available: boolean;
825
839
  };
826
- variantAvailability(variantId: string): {
840
+ variantAvailability(variantId: string, quantity?: number): {
827
841
  variant_id: string;
842
+ quantity: number;
828
843
  is_available: boolean;
829
844
  };
845
+ /**
846
+ * Reserve stock for a cart item. No-op for product types that don't track
847
+ * inventory (services, digital). Throws on insufficient stock.
848
+ */
849
+ reserve(productId: string, variantId: string | undefined, quantity: number): void;
850
+ /** Release a previously-reserved quantity (e.g. when a line is removed). */
851
+ release(productId: string, variantId: string | undefined, quantity: number): void;
830
852
  }
831
853
 
832
854
  interface FxService {
@@ -575,6 +575,10 @@ interface AuthService {
575
575
  }): Session;
576
576
  status(token: string | null): {
577
577
  is_authenticated: boolean;
578
+ account_id?: string;
579
+ user_type: "customer" | "guest";
580
+ session_expires_at?: number;
581
+ /** @deprecated Kept for SDK back-compat; production lens does not return this. */
578
582
  session?: Session;
579
583
  };
580
584
  }
@@ -736,6 +740,7 @@ interface CheckoutResult {
736
740
  payment_status: string;
737
741
  payment_reference?: string;
738
742
  requires_authorization: boolean;
743
+ authorization_type?: "otp" | "pin" | "phone" | "birthday" | "address";
739
744
  next_action: {
740
745
  type: "none";
741
746
  } | {
@@ -749,6 +754,12 @@ interface CheckoutResult {
749
754
  provider?: string;
750
755
  authorization_url?: string;
751
756
  display_text?: string;
757
+ /** Bearer token used for guest order access (lookup `/orders/{id}?token=...`). */
758
+ bill_token?: string;
759
+ /** Stripe-style client secret for direct PaymentIntent confirmation. */
760
+ client_secret?: string;
761
+ /** Stripe publishable key (mock value in dev). */
762
+ public_key?: string;
752
763
  }
753
764
 
754
765
  interface OrderService {
@@ -811,22 +822,33 @@ interface SchedulingService {
811
822
  interface InventoryService {
812
823
  productStock(productId: string): {
813
824
  product_id: string;
814
- quantity: number;
815
- available: boolean;
825
+ location_id?: string;
826
+ stock_level: number;
827
+ in_stock: boolean;
816
828
  };
817
829
  variantStock(variantId: string): {
818
830
  variant_id: string;
819
- quantity: number;
820
- available: boolean;
831
+ location_id?: string;
832
+ stock_level: number;
833
+ in_stock: boolean;
821
834
  };
822
- productAvailability(productId: string): {
835
+ productAvailability(productId: string, quantity?: number): {
823
836
  product_id: string;
837
+ quantity: number;
824
838
  is_available: boolean;
825
839
  };
826
- variantAvailability(variantId: string): {
840
+ variantAvailability(variantId: string, quantity?: number): {
827
841
  variant_id: string;
842
+ quantity: number;
828
843
  is_available: boolean;
829
844
  };
845
+ /**
846
+ * Reserve stock for a cart item. No-op for product types that don't track
847
+ * inventory (services, digital). Throws on insufficient stock.
848
+ */
849
+ reserve(productId: string, variantId: string | undefined, quantity: number): void;
850
+ /** Release a previously-reserved quantity (e.g. when a line is removed). */
851
+ release(productId: string, variantId: string | undefined, quantity: number): void;
830
852
  }
831
853
 
832
854
  interface FxService {
package/dist/server.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { C as CimplifyClient } from './client-CkGlXZRd.mjs';
2
- export { aN as Result } from './client-CkGlXZRd.mjs';
1
+ import { C as CimplifyClient } from './client-Dh-bHyhU.mjs';
2
+ export { aN as Result } from './client-Dh-bHyhU.mjs';
3
3
  export { am as Category, h as CimplifyError, ao as Collection, U as Product, a7 as ProductWithDetails } from './payment-DA1i5hhk.mjs';
4
4
 
5
5
  interface ServerClientOptions {
package/dist/server.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { C as CimplifyClient } from './client-lvLvB1_K.js';
2
- export { aN as Result } from './client-lvLvB1_K.js';
1
+ import { C as CimplifyClient } from './client-D6ZisKco.js';
2
+ export { aN as Result } from './client-D6ZisKco.js';
3
3
  export { am as Category, h as CimplifyError, ao as Collection, U as Product, a7 as ProductWithDetails } from './payment-DA1i5hhk.js';
4
4
 
5
5
  interface ServerClientOptions {
package/dist/server.js CHANGED
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
- var chunkOMAP327U_js = require('./chunk-OMAP327U.js');
4
- require('./chunk-BAWKQRIB.js');
5
- var chunkV2O5AO7I_js = require('./chunk-V2O5AO7I.js');
3
+ var chunkMBGQP6FZ_js = require('./chunk-MBGQP6FZ.js');
4
+ require('./chunk-CFD4J32N.js');
5
+ var chunkMNIKXG7W_js = require('./chunk-MNIKXG7W.js');
6
6
  var react = require('react');
7
7
 
8
8
  var DEFAULT_DEV_URL = "http://127.0.0.1:8787";
@@ -18,7 +18,7 @@ function readEnv(...keys) {
18
18
  var getServerClient = react.cache((opts = {}) => {
19
19
  const baseUrl = opts.apiUrl ?? readEnv("CIMPLIFY_API_URL", "NEXT_PUBLIC_CIMPLIFY_API_URL") ?? DEFAULT_DEV_URL;
20
20
  const publicKey = opts.secretKey ?? readEnv("CIMPLIFY_SECRET_KEY", "NEXT_PUBLIC_CIMPLIFY_PUBLIC_KEY") ?? "mock-dev";
21
- const client = chunkOMAP327U_js.createCimplifyClient({
21
+ const client = chunkMBGQP6FZ_js.createCimplifyClient({
22
22
  baseUrl,
23
23
  publicKey,
24
24
  suppressPublicKeyWarning: true
@@ -93,7 +93,7 @@ async function revalidateByTag(tag) {
93
93
 
94
94
  Object.defineProperty(exports, "CimplifyError", {
95
95
  enumerable: true,
96
- get: function () { return chunkV2O5AO7I_js.CimplifyError; }
96
+ get: function () { return chunkMNIKXG7W_js.CimplifyError; }
97
97
  });
98
98
  exports.getServerClient = getServerClient;
99
99
  exports.revalidateBusiness = revalidateBusiness;
package/dist/server.mjs CHANGED
@@ -1,6 +1,6 @@
1
- import { createCimplifyClient } from './chunk-3WD6U5RD.mjs';
2
- import './chunk-EZK2FXTM.mjs';
3
- export { CimplifyError } from './chunk-6TVQQYQ5.mjs';
1
+ import { createCimplifyClient } from './chunk-UXLQ7WXI.mjs';
2
+ import './chunk-7NML226B.mjs';
3
+ export { CimplifyError } from './chunk-6AZZ6AOF.mjs';
4
4
  import { cache } from 'react';
5
5
 
6
6
  var DEFAULT_DEV_URL = "http://127.0.0.1:8787";
@@ -0,0 +1,60 @@
1
+ import { C as CreateAppOptions } from '../server-CWpUlLOQ.mjs';
2
+ import 'hono';
3
+
4
+ /**
5
+ * Pre-baked test suites for scaffolded storefronts.
6
+ *
7
+ * Templates' `__tests__/*.test.ts` files are now ~5 lines each — they
8
+ * import their `brand` and call `createBrandSuite` / `createCartFlowSuite`
9
+ * / `createContractSuite`. One bug fix in this file → every template
10
+ * picks it up on `bun update @cimplify/sdk`.
11
+ *
12
+ * // __tests__/brand.test.ts in any template:
13
+ * import { createBrandSuite } from "@cimplify/sdk/testing/suite";
14
+ * import { brand } from "../lib/brand";
15
+ * createBrandSuite({ brand });
16
+ *
17
+ * // __tests__/cart-flow.test.ts:
18
+ * import { createCartFlowSuite } from "@cimplify/sdk/testing/suite";
19
+ * import { brand } from "../lib/brand";
20
+ * createCartFlowSuite({ seed: brand.mock.seed, businessId: brand.mock.businessId });
21
+ *
22
+ * // __tests__/contract.test.ts:
23
+ * import { createContractSuite } from "@cimplify/sdk/testing/suite";
24
+ * import { brand } from "../lib/brand";
25
+ * createContractSuite({ seed: brand.mock.seed });
26
+ */
27
+
28
+ /**
29
+ * Brand sanity suite. Catches: missing required fields, placeholder
30
+ * strings shipped to prod, invalid email/url/locale/currency formats,
31
+ * mismatched seed/businessId pairing.
32
+ */
33
+ declare function createBrandSuite(opts: {
34
+ brand: unknown;
35
+ label?: string;
36
+ }): void;
37
+ interface CartFlowOptions extends CreateAppOptions {
38
+ /** Expected business ID — asserts cart responses match the merchant. */
39
+ businessId?: string;
40
+ /** Override the describe() label. */
41
+ label?: string;
42
+ }
43
+ /**
44
+ * Cart flow suite. Boots the in-process mock, exercises add/dedupe/remove
45
+ * with shape assertions on every response. Catches: SDK ↔ mock contract
46
+ * drift, missing fields on cart items, add-to-cart not persisting,
47
+ * variant/payload silently dropped.
48
+ */
49
+ declare function createCartFlowSuite(opts?: CartFlowOptions): void;
50
+ interface ContractOptions extends CreateAppOptions {
51
+ label?: string;
52
+ }
53
+ /**
54
+ * Shape contract suite. Exercises the schemas against actual mock
55
+ * traffic. Catches: outbound payloads dropping required fields,
56
+ * inbound responses missing fields the storefront depends on.
57
+ */
58
+ declare function createContractSuite(opts?: ContractOptions): void;
59
+
60
+ export { createBrandSuite, createCartFlowSuite, createContractSuite };
@@ -0,0 +1,60 @@
1
+ import { C as CreateAppOptions } from '../server-CWpUlLOQ.js';
2
+ import 'hono';
3
+
4
+ /**
5
+ * Pre-baked test suites for scaffolded storefronts.
6
+ *
7
+ * Templates' `__tests__/*.test.ts` files are now ~5 lines each — they
8
+ * import their `brand` and call `createBrandSuite` / `createCartFlowSuite`
9
+ * / `createContractSuite`. One bug fix in this file → every template
10
+ * picks it up on `bun update @cimplify/sdk`.
11
+ *
12
+ * // __tests__/brand.test.ts in any template:
13
+ * import { createBrandSuite } from "@cimplify/sdk/testing/suite";
14
+ * import { brand } from "../lib/brand";
15
+ * createBrandSuite({ brand });
16
+ *
17
+ * // __tests__/cart-flow.test.ts:
18
+ * import { createCartFlowSuite } from "@cimplify/sdk/testing/suite";
19
+ * import { brand } from "../lib/brand";
20
+ * createCartFlowSuite({ seed: brand.mock.seed, businessId: brand.mock.businessId });
21
+ *
22
+ * // __tests__/contract.test.ts:
23
+ * import { createContractSuite } from "@cimplify/sdk/testing/suite";
24
+ * import { brand } from "../lib/brand";
25
+ * createContractSuite({ seed: brand.mock.seed });
26
+ */
27
+
28
+ /**
29
+ * Brand sanity suite. Catches: missing required fields, placeholder
30
+ * strings shipped to prod, invalid email/url/locale/currency formats,
31
+ * mismatched seed/businessId pairing.
32
+ */
33
+ declare function createBrandSuite(opts: {
34
+ brand: unknown;
35
+ label?: string;
36
+ }): void;
37
+ interface CartFlowOptions extends CreateAppOptions {
38
+ /** Expected business ID — asserts cart responses match the merchant. */
39
+ businessId?: string;
40
+ /** Override the describe() label. */
41
+ label?: string;
42
+ }
43
+ /**
44
+ * Cart flow suite. Boots the in-process mock, exercises add/dedupe/remove
45
+ * with shape assertions on every response. Catches: SDK ↔ mock contract
46
+ * drift, missing fields on cart items, add-to-cart not persisting,
47
+ * variant/payload silently dropped.
48
+ */
49
+ declare function createCartFlowSuite(opts?: CartFlowOptions): void;
50
+ interface ContractOptions extends CreateAppOptions {
51
+ label?: string;
52
+ }
53
+ /**
54
+ * Shape contract suite. Exercises the schemas against actual mock
55
+ * traffic. Catches: outbound payloads dropping required fields,
56
+ * inbound responses missing fields the storefront depends on.
57
+ */
58
+ declare function createContractSuite(opts?: ContractOptions): void;
59
+
60
+ export { createBrandSuite, createCartFlowSuite, createContractSuite };
@@ -0,0 +1,169 @@
1
+ 'use strict';
2
+
3
+ var chunkXL4CX75J_js = require('../chunk-XL4CX75J.js');
4
+ require('../chunk-MBGQP6FZ.js');
5
+ require('../chunk-CFD4J32N.js');
6
+ require('../chunk-MNIKXG7W.js');
7
+ var vitest = require('vitest');
8
+
9
+ var PLACEHOLDER_PHRASES = [
10
+ "lorem ipsum",
11
+ "todo",
12
+ "fixme",
13
+ "placeholder",
14
+ "your business name",
15
+ "your store"
16
+ ];
17
+ function createBrandSuite(opts) {
18
+ vitest.describe(opts.label ?? "brand schema", () => {
19
+ vitest.it("conforms to the Cimplify brand contract", () => {
20
+ vitest.expect(() => chunkXL4CX75J_js.assertBrand(opts.brand)).not.toThrow();
21
+ });
22
+ vitest.it("declares a known mock seed", () => {
23
+ const b = opts.brand;
24
+ vitest.expect(chunkXL4CX75J_js.SeedNameSchema.safeParse(b.mock?.seed).success).toBe(true);
25
+ });
26
+ vitest.it("has no placeholder copy left in", () => {
27
+ const flat = JSON.stringify(opts.brand).toLowerCase();
28
+ for (const phrase of PLACEHOLDER_PHRASES) {
29
+ vitest.expect(flat, `brand contains placeholder phrase "${phrase}"`).not.toContain(phrase);
30
+ }
31
+ });
32
+ vitest.it("uses the bus_ businessId convention", () => {
33
+ const b = opts.brand;
34
+ vitest.expect(b.mock?.businessId).toMatch(/^bus_/);
35
+ });
36
+ vitest.it("zod-parses cleanly", () => {
37
+ const result = chunkXL4CX75J_js.BrandSchema.safeParse(opts.brand);
38
+ if (!result.success) {
39
+ throw new Error(
40
+ "Brand schema violations:\n" + result.error.issues.map((i) => ` \u2022 brand.${i.path.join(".")}: ${i.message}`).join("\n")
41
+ );
42
+ }
43
+ vitest.expect(result.success).toBe(true);
44
+ });
45
+ });
46
+ }
47
+ function createCartFlowSuite(opts = {}) {
48
+ vitest.describe(opts.label ?? "cart flow against in-process mock", () => {
49
+ let h;
50
+ vitest.beforeEach(() => {
51
+ h = chunkXL4CX75J_js.createTestClient(opts);
52
+ });
53
+ vitest.afterEach(() => h.dispose());
54
+ vitest.it("starts with an empty cart matching the canonical shape", async () => {
55
+ const res = await h.client.cart.get();
56
+ vitest.expect(res.ok).toBe(true);
57
+ if (!res.ok) return;
58
+ vitest.expect(() => chunkXL4CX75J_js.assertCart(res.value)).not.toThrow();
59
+ vitest.expect(res.value.items).toHaveLength(0);
60
+ });
61
+ vitest.it("adds the first product, persists it, and returns a shape-valid cart", async () => {
62
+ const { product, variantId } = await chunkXL4CX75J_js.fixtures.addFirstProduct(h.client);
63
+ vitest.expect(product.id).toBeTruthy();
64
+ const get = await h.client.cart.get();
65
+ vitest.expect(get.ok).toBe(true);
66
+ if (!get.ok) return;
67
+ vitest.expect(() => chunkXL4CX75J_js.assertCart(get.value)).not.toThrow();
68
+ vitest.expect(get.value.items).toHaveLength(1);
69
+ vitest.expect(get.value.items[0]?.item_id).toBe(product.id);
70
+ if (variantId) {
71
+ vitest.expect(get.value.items[0]?.variant_id).toBe(variantId);
72
+ const variantInfo = get.value.items[0]?.variant_info;
73
+ vitest.expect(variantInfo?.display_attributes).toBeDefined();
74
+ }
75
+ vitest.expect(parseFloat(String(get.value.pricing.subtotal))).toBeGreaterThan(0);
76
+ });
77
+ vitest.it("dedupes by line_key when adding the same product twice", async () => {
78
+ await chunkXL4CX75J_js.fixtures.addFirstProduct(h.client);
79
+ await chunkXL4CX75J_js.fixtures.addFirstProduct(h.client);
80
+ const res = await h.client.cart.get();
81
+ vitest.expect(res.ok).toBe(true);
82
+ if (!res.ok) return;
83
+ vitest.expect(res.value.items).toHaveLength(1);
84
+ vitest.expect(res.value.items[0]?.quantity).toBe(2);
85
+ });
86
+ vitest.it("removes items and zeroes the subtotal", async () => {
87
+ await chunkXL4CX75J_js.fixtures.addFirstProduct(h.client);
88
+ const before = await h.client.cart.get();
89
+ if (!before.ok) throw before.error;
90
+ const itemId = before.value.items[0]?.id;
91
+ vitest.expect(itemId).toBeTruthy();
92
+ const removed = await h.client.cart.removeItem(itemId);
93
+ vitest.expect(removed.ok).toBe(true);
94
+ const after = await h.client.cart.get();
95
+ if (!after.ok) throw after.error;
96
+ vitest.expect(after.value.items).toHaveLength(0);
97
+ vitest.expect(parseFloat(String(after.value.pricing.subtotal))).toBe(0);
98
+ });
99
+ if (opts.businessId) {
100
+ vitest.it("returns the brand's businessId on cart responses", async () => {
101
+ const res = await h.client.cart.get();
102
+ if (!res.ok) throw res.error;
103
+ vitest.expect(res.value.business_id).toBe(opts.businessId);
104
+ });
105
+ }
106
+ });
107
+ }
108
+ function createContractSuite(opts = {}) {
109
+ vitest.describe(opts.label ?? "SDK \u2194 mock contract", () => {
110
+ let h;
111
+ vitest.beforeEach(() => {
112
+ h = chunkXL4CX75J_js.createTestClient(opts);
113
+ });
114
+ vitest.afterEach(() => h.dispose());
115
+ vitest.it("AddItemPayload schema accepts a minimal valid body", () => {
116
+ const result = chunkXL4CX75J_js.AddItemPayloadSchema.safeParse({ item_id: "prod_x", quantity: 1 });
117
+ vitest.expect(result.success).toBe(true);
118
+ });
119
+ vitest.it("AddItemPayload schema rejects negative quantity", () => {
120
+ const result = chunkXL4CX75J_js.AddItemPayloadSchema.safeParse({ item_id: "prod_x", quantity: -1 });
121
+ vitest.expect(result.success).toBe(false);
122
+ });
123
+ vitest.it("AddItemPayload schema rejects empty item_id", () => {
124
+ const result = chunkXL4CX75J_js.AddItemPayloadSchema.safeParse({ item_id: "", quantity: 1 });
125
+ vitest.expect(result.success).toBe(false);
126
+ });
127
+ vitest.it("Cart line items returned by the mock match CartItemSchema", async () => {
128
+ const { product } = await chunkXL4CX75J_js.fixtures.addFirstProduct(h.client);
129
+ const get = await h.client.cart.get();
130
+ if (!get.ok) throw get.error;
131
+ vitest.expect(get.value.items.length).toBeGreaterThan(0);
132
+ for (const item of get.value.items) {
133
+ const result = chunkXL4CX75J_js.CartItemSchema.safeParse(item);
134
+ if (!result.success) {
135
+ const issues = result.error.issues.map((i) => ` \u2022 ${i.path.join(".")}: ${i.message}`).join("\n");
136
+ throw new Error(`Cart item shape mismatch for ${product.name}:
137
+ ${issues}`);
138
+ }
139
+ vitest.expect(result.success).toBe(true);
140
+ }
141
+ });
142
+ vitest.it("CheckoutResponse from the mock includes bill_token", async () => {
143
+ await chunkXL4CX75J_js.fixtures.addFirstProduct(h.client);
144
+ const cartRes = await h.client.cart.get();
145
+ if (!cartRes.ok) throw cartRes.error;
146
+ const checkout = await h.client.checkout.process({
147
+ cart_id: cartRes.value.id,
148
+ customer: chunkXL4CX75J_js.fixtures.customer(),
149
+ order_type: "delivery",
150
+ payment_method: "mobile_money",
151
+ mobile_money_details: { phone_number: "+233244000000", provider: "mtn" }
152
+ });
153
+ vitest.expect(checkout.ok).toBe(true);
154
+ if (!checkout.ok) return;
155
+ const result = chunkXL4CX75J_js.CheckoutResponseSchema.safeParse(checkout.value);
156
+ if (!result.success) {
157
+ const issues = result.error.issues.map((i) => ` \u2022 ${i.path.join(".")}: ${i.message}`).join("\n");
158
+ throw new Error(`CheckoutResponse shape mismatch:
159
+ ${issues}`);
160
+ }
161
+ vitest.expect(checkout.value.bill_token).toBeTruthy();
162
+ vitest.expect(checkout.value.order_id).toBeTruthy();
163
+ });
164
+ });
165
+ }
166
+
167
+ exports.createBrandSuite = createBrandSuite;
168
+ exports.createCartFlowSuite = createCartFlowSuite;
169
+ exports.createContractSuite = createContractSuite;
@@ -0,0 +1,165 @@
1
+ import { assertBrand, SeedNameSchema, BrandSchema, createTestClient, assertCart, fixtures, AddItemPayloadSchema, CartItemSchema, CheckoutResponseSchema } from '../chunk-ZLEFMQC6.mjs';
2
+ import '../chunk-UXLQ7WXI.mjs';
3
+ import '../chunk-7NML226B.mjs';
4
+ import '../chunk-6AZZ6AOF.mjs';
5
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
6
+
7
+ var PLACEHOLDER_PHRASES = [
8
+ "lorem ipsum",
9
+ "todo",
10
+ "fixme",
11
+ "placeholder",
12
+ "your business name",
13
+ "your store"
14
+ ];
15
+ function createBrandSuite(opts) {
16
+ describe(opts.label ?? "brand schema", () => {
17
+ it("conforms to the Cimplify brand contract", () => {
18
+ expect(() => assertBrand(opts.brand)).not.toThrow();
19
+ });
20
+ it("declares a known mock seed", () => {
21
+ const b = opts.brand;
22
+ expect(SeedNameSchema.safeParse(b.mock?.seed).success).toBe(true);
23
+ });
24
+ it("has no placeholder copy left in", () => {
25
+ const flat = JSON.stringify(opts.brand).toLowerCase();
26
+ for (const phrase of PLACEHOLDER_PHRASES) {
27
+ expect(flat, `brand contains placeholder phrase "${phrase}"`).not.toContain(phrase);
28
+ }
29
+ });
30
+ it("uses the bus_ businessId convention", () => {
31
+ const b = opts.brand;
32
+ expect(b.mock?.businessId).toMatch(/^bus_/);
33
+ });
34
+ it("zod-parses cleanly", () => {
35
+ const result = BrandSchema.safeParse(opts.brand);
36
+ if (!result.success) {
37
+ throw new Error(
38
+ "Brand schema violations:\n" + result.error.issues.map((i) => ` \u2022 brand.${i.path.join(".")}: ${i.message}`).join("\n")
39
+ );
40
+ }
41
+ expect(result.success).toBe(true);
42
+ });
43
+ });
44
+ }
45
+ function createCartFlowSuite(opts = {}) {
46
+ describe(opts.label ?? "cart flow against in-process mock", () => {
47
+ let h;
48
+ beforeEach(() => {
49
+ h = createTestClient(opts);
50
+ });
51
+ afterEach(() => h.dispose());
52
+ it("starts with an empty cart matching the canonical shape", async () => {
53
+ const res = await h.client.cart.get();
54
+ expect(res.ok).toBe(true);
55
+ if (!res.ok) return;
56
+ expect(() => assertCart(res.value)).not.toThrow();
57
+ expect(res.value.items).toHaveLength(0);
58
+ });
59
+ it("adds the first product, persists it, and returns a shape-valid cart", async () => {
60
+ const { product, variantId } = await fixtures.addFirstProduct(h.client);
61
+ expect(product.id).toBeTruthy();
62
+ const get = await h.client.cart.get();
63
+ expect(get.ok).toBe(true);
64
+ if (!get.ok) return;
65
+ expect(() => assertCart(get.value)).not.toThrow();
66
+ expect(get.value.items).toHaveLength(1);
67
+ expect(get.value.items[0]?.item_id).toBe(product.id);
68
+ if (variantId) {
69
+ expect(get.value.items[0]?.variant_id).toBe(variantId);
70
+ const variantInfo = get.value.items[0]?.variant_info;
71
+ expect(variantInfo?.display_attributes).toBeDefined();
72
+ }
73
+ expect(parseFloat(String(get.value.pricing.subtotal))).toBeGreaterThan(0);
74
+ });
75
+ it("dedupes by line_key when adding the same product twice", async () => {
76
+ await fixtures.addFirstProduct(h.client);
77
+ await fixtures.addFirstProduct(h.client);
78
+ const res = await h.client.cart.get();
79
+ expect(res.ok).toBe(true);
80
+ if (!res.ok) return;
81
+ expect(res.value.items).toHaveLength(1);
82
+ expect(res.value.items[0]?.quantity).toBe(2);
83
+ });
84
+ it("removes items and zeroes the subtotal", async () => {
85
+ await fixtures.addFirstProduct(h.client);
86
+ const before = await h.client.cart.get();
87
+ if (!before.ok) throw before.error;
88
+ const itemId = before.value.items[0]?.id;
89
+ expect(itemId).toBeTruthy();
90
+ const removed = await h.client.cart.removeItem(itemId);
91
+ expect(removed.ok).toBe(true);
92
+ const after = await h.client.cart.get();
93
+ if (!after.ok) throw after.error;
94
+ expect(after.value.items).toHaveLength(0);
95
+ expect(parseFloat(String(after.value.pricing.subtotal))).toBe(0);
96
+ });
97
+ if (opts.businessId) {
98
+ it("returns the brand's businessId on cart responses", async () => {
99
+ const res = await h.client.cart.get();
100
+ if (!res.ok) throw res.error;
101
+ expect(res.value.business_id).toBe(opts.businessId);
102
+ });
103
+ }
104
+ });
105
+ }
106
+ function createContractSuite(opts = {}) {
107
+ describe(opts.label ?? "SDK \u2194 mock contract", () => {
108
+ let h;
109
+ beforeEach(() => {
110
+ h = createTestClient(opts);
111
+ });
112
+ afterEach(() => h.dispose());
113
+ it("AddItemPayload schema accepts a minimal valid body", () => {
114
+ const result = AddItemPayloadSchema.safeParse({ item_id: "prod_x", quantity: 1 });
115
+ expect(result.success).toBe(true);
116
+ });
117
+ it("AddItemPayload schema rejects negative quantity", () => {
118
+ const result = AddItemPayloadSchema.safeParse({ item_id: "prod_x", quantity: -1 });
119
+ expect(result.success).toBe(false);
120
+ });
121
+ it("AddItemPayload schema rejects empty item_id", () => {
122
+ const result = AddItemPayloadSchema.safeParse({ item_id: "", quantity: 1 });
123
+ expect(result.success).toBe(false);
124
+ });
125
+ it("Cart line items returned by the mock match CartItemSchema", async () => {
126
+ const { product } = await fixtures.addFirstProduct(h.client);
127
+ const get = await h.client.cart.get();
128
+ if (!get.ok) throw get.error;
129
+ expect(get.value.items.length).toBeGreaterThan(0);
130
+ for (const item of get.value.items) {
131
+ const result = CartItemSchema.safeParse(item);
132
+ if (!result.success) {
133
+ const issues = result.error.issues.map((i) => ` \u2022 ${i.path.join(".")}: ${i.message}`).join("\n");
134
+ throw new Error(`Cart item shape mismatch for ${product.name}:
135
+ ${issues}`);
136
+ }
137
+ expect(result.success).toBe(true);
138
+ }
139
+ });
140
+ it("CheckoutResponse from the mock includes bill_token", async () => {
141
+ await fixtures.addFirstProduct(h.client);
142
+ const cartRes = await h.client.cart.get();
143
+ if (!cartRes.ok) throw cartRes.error;
144
+ const checkout = await h.client.checkout.process({
145
+ cart_id: cartRes.value.id,
146
+ customer: fixtures.customer(),
147
+ order_type: "delivery",
148
+ payment_method: "mobile_money",
149
+ mobile_money_details: { phone_number: "+233244000000", provider: "mtn" }
150
+ });
151
+ expect(checkout.ok).toBe(true);
152
+ if (!checkout.ok) return;
153
+ const result = CheckoutResponseSchema.safeParse(checkout.value);
154
+ if (!result.success) {
155
+ const issues = result.error.issues.map((i) => ` \u2022 ${i.path.join(".")}: ${i.message}`).join("\n");
156
+ throw new Error(`CheckoutResponse shape mismatch:
157
+ ${issues}`);
158
+ }
159
+ expect(checkout.value.bill_token).toBeTruthy();
160
+ expect(checkout.value.order_id).toBeTruthy();
161
+ });
162
+ });
163
+ }
164
+
165
+ export { createBrandSuite, createCartFlowSuite, createContractSuite };