@bacano/sdk 1.0.1 → 1.1.8

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 (72) hide show
  1. package/README.md +439 -18
  2. package/STOREFRONT_CLARITY.md +140 -0
  3. package/STOREFRONT_CONSTRUCTION.md +105 -0
  4. package/STOREFRONT_LEADS.md +130 -0
  5. package/STOREFRONT_LEGAL.md +66 -0
  6. package/STOREFRONT_MARKETING.md +291 -0
  7. package/STOREFRONT_PERFORMANCE.md +304 -0
  8. package/STOREFRONT_PREVIEW.md +499 -0
  9. package/STOREFRONT_PRODUCT_SPECIFICATIONS.md +127 -0
  10. package/STOREFRONT_VOLUME_PRICING.md +131 -0
  11. package/client.d.ts +8 -1
  12. package/errors.d.ts +9 -1
  13. package/graphql.cjs +266 -3
  14. package/graphql.d.ts +2 -2
  15. package/graphql.js +266 -3
  16. package/index.cjs +2035 -255
  17. package/index.d.ts +8 -6
  18. package/index.js +2035 -255
  19. package/marketing/attribution.d.ts +53 -0
  20. package/marketing/clarity.d.ts +3 -0
  21. package/marketing/domain.d.ts +1 -0
  22. package/marketing/ga4.d.ts +2 -0
  23. package/marketing/index.d.ts +5 -0
  24. package/marketing/runtime.d.ts +2 -0
  25. package/marketing/sanitize.d.ts +2 -0
  26. package/marketing/types.d.ts +111 -0
  27. package/media.d.ts +45 -2
  28. package/modules/auth.d.ts +3 -2
  29. package/modules/availability.d.ts +2 -2
  30. package/modules/cart-errors.d.ts +2 -0
  31. package/modules/cart-session.d.ts +2 -2
  32. package/modules/cart.d.ts +4 -3
  33. package/modules/catalog.d.ts +15 -3
  34. package/modules/content.d.ts +2 -2
  35. package/modules/marketing.d.ts +5 -0
  36. package/modules/orders.d.ts +2 -2
  37. package/modules/profile.d.ts +1 -1
  38. package/modules/static-catalog.d.ts +13 -0
  39. package/modules/website.d.ts +7 -1
  40. package/package.json +14 -3
  41. package/react/context-registry.d.ts +9 -0
  42. package/react/context.d.ts +1 -1
  43. package/react/hooks.d.ts +24 -2
  44. package/react/marketing-context.d.ts +3 -0
  45. package/react/marketing-provider.d.ts +10 -0
  46. package/react/preview/cache.d.ts +23 -0
  47. package/react/preview/context.d.ts +5 -0
  48. package/react/preview/navigation.d.ts +9 -0
  49. package/react/preview/provider.d.ts +3 -0
  50. package/react/preview/shell.d.ts +3 -0
  51. package/react/preview/toolbar.d.ts +3 -0
  52. package/react/preview/types.d.ts +60 -0
  53. package/react/preview.cjs +742 -0
  54. package/react/preview.d.ts +14 -0
  55. package/react/preview.js +730 -0
  56. package/react/website-gate.d.ts +22 -0
  57. package/react.cjs +3893 -1795
  58. package/react.d.ts +8 -4
  59. package/react.js +3891 -1789
  60. package/skills/bacano-web/SKILL.md +116 -0
  61. package/skills/bacano-web/agents/openai.yaml +4 -0
  62. package/skills/bacano-web/references/architecture-runtime.md +109 -0
  63. package/skills/bacano-web/references/common.md +92 -0
  64. package/skills/bacano-web/references/informational.md +39 -0
  65. package/skills/bacano-web/references/report.md +70 -0
  66. package/skills/bacano-web/references/storefront.md +116 -0
  67. package/skills/bacano-web/scripts/audit-http.mjs +284 -0
  68. package/skills/bacano-web/scripts/cli.mjs +222 -0
  69. package/skills/bacano-web/scripts/postinstall.mjs +8 -0
  70. package/transport/documents.d.ts +23 -18
  71. package/transport/graphql.d.ts +13 -1
  72. package/types.d.ts +338 -0
package/types.d.ts CHANGED
@@ -1,8 +1,14 @@
1
+ import type { WebsiteAdvertisingConsent, WebsiteMarketingAttribution } from "./marketing/types";
1
2
  export interface BacanoClientConfig {
2
3
  /** Bacano public API URL (e.g., https://api.bacanoerp.com) */
3
4
  apiUrl: string;
4
5
  /** Website slug — required tenant context for every storefront request. */
5
6
  websiteSlug: string;
7
+ /**
8
+ * Browser-safe website context already returned by `public-config`.
9
+ * Passing it avoids resolving the same website again through GraphQL.
10
+ */
11
+ initialContext?: BacanoClientContext;
6
12
  /** Cart session storage strategy (default: 'localStorage') */
7
13
  tokenStorage?: "localStorage" | "cookie" | "memory";
8
14
  /**
@@ -18,12 +24,163 @@ export type AccessTokenProvider = () => string | null | Promise<string | null>;
18
24
  export interface WebsitePublicConfig {
19
25
  websiteId: string;
20
26
  companyId: string;
27
+ /** Versioned marker for the website context embedded in public-config. */
28
+ contextSchemaVersion?: 1 | null;
29
+ chainId?: string | null;
21
30
  slug: string;
22
31
  name: string;
23
32
  domain: string | null;
33
+ config?: Record<string, unknown> | null;
24
34
  buyerAccountsEnabled: boolean;
25
35
  clerkPublishableKey: string | null;
26
36
  customerIdentification: WebsiteCustomerIdentificationPolicy;
37
+ marketing: WebsiteMarketingPublicConfig;
38
+ /**
39
+ * Optional on caller-constructed configs. `getWebsitePublicConfig()` always
40
+ * resolves this block, including a safe empty fallback.
41
+ */
42
+ branding?: WebsiteBrandingPublicConfig;
43
+ /**
44
+ * Optional on caller-constructed configs for compatibility with SDK 1.0.10.
45
+ * `getWebsitePublicConfig()` always returns this block.
46
+ */
47
+ legal?: WebsiteLegalPublicConfig;
48
+ /**
49
+ * Optional on caller-constructed configs. `getWebsitePublicConfig()` always
50
+ * resolves this block, including a safe disabled fallback.
51
+ */
52
+ construction?: WebsiteConstructionPublicConfig;
53
+ /** Public thresholds for displaying quantity-pricing guidance. */
54
+ volumePricing?: WebsiteVolumePricingPublicConfig;
55
+ }
56
+ export interface WebsiteVolumePricingPublicConfig {
57
+ schemaVersion: 1;
58
+ enabled: boolean;
59
+ tiers: Array<{
60
+ priceType: "WHOLESALE" | "WHOLESALE_2";
61
+ minQuantity: number;
62
+ }>;
63
+ }
64
+ export interface WebsiteBrandingMedia {
65
+ fileId: string;
66
+ name: string | null;
67
+ altText: string | null;
68
+ width: number | null;
69
+ height: number | null;
70
+ originalUrl: string;
71
+ }
72
+ export interface WebsiteBrandingPublicConfig {
73
+ schemaVersion: 1;
74
+ favicon: WebsiteBrandingMedia | null;
75
+ }
76
+ export interface WebsiteConstructionMedia {
77
+ fileId: string;
78
+ name: string | null;
79
+ altText: string | null;
80
+ width: number | null;
81
+ height: number | null;
82
+ originalUrl: string;
83
+ heroUrl: string;
84
+ responsiveSources: Array<{
85
+ width: number;
86
+ url: string;
87
+ }>;
88
+ }
89
+ export interface WebsiteConstructionPublicConfig {
90
+ schemaVersion: 1;
91
+ enabled: boolean;
92
+ /** True only on the canonical production domain without a valid preview. */
93
+ enforced: boolean;
94
+ previewAccessGranted: boolean;
95
+ title: string | null;
96
+ message: string | null;
97
+ desktopImage: WebsiteConstructionMedia | null;
98
+ mobileImage: WebsiteConstructionMedia | null;
99
+ }
100
+ export interface WebsiteLegalPublicConfig {
101
+ schemaVersion: 1;
102
+ version: number;
103
+ contentHash: string | null;
104
+ documents: {
105
+ terms: Record<string, unknown> | null;
106
+ /** Present in public-config from SDK 1.0.12; optional for older fixtures. */
107
+ shipping?: Record<string, unknown> | null;
108
+ /** Present in public-config from SDK 1.0.12; optional for older fixtures. */
109
+ returns?: Record<string, unknown> | null;
110
+ privacy: Record<string, unknown> | null;
111
+ cookies: Record<string, unknown> | null;
112
+ };
113
+ inquiriesChannel: string | null;
114
+ directMarketingConsent: {
115
+ version: number;
116
+ statement: string;
117
+ statementHash: string;
118
+ } | null;
119
+ cookieNotice: {
120
+ enabled: boolean;
121
+ message: string;
122
+ buttonLabel: string;
123
+ };
124
+ }
125
+ export type WebsiteCampaignCaptureSource = "WEBSITE" | "QR";
126
+ export interface WebsiteCampaignCaptureContact {
127
+ partyKind?: "PERSON" | "COMPANY";
128
+ firstName?: string | null;
129
+ lastName?: string | null;
130
+ legalName?: string | null;
131
+ commercialName?: string | null;
132
+ email?: string | null;
133
+ phone?: string | null;
134
+ }
135
+ export interface WebsiteCampaignCaptureInput {
136
+ /** Stable public key configured for the campaign in Bacano. */
137
+ campaignKey: string;
138
+ /** Stable per-submission key. Reusing it is safe and does not duplicate data. */
139
+ idempotencyKey: string;
140
+ /** Use QR only when the current form was reached through a QR entry point. */
141
+ source?: WebsiteCampaignCaptureSource;
142
+ /** Must reflect an explicit acceptance of the website's current statement. */
143
+ commercialConsent: true;
144
+ contact: WebsiteCampaignCaptureContact;
145
+ /** Storefront-defined answers. Bacano stores these as an immutable snapshot. */
146
+ answers?: Record<string, unknown>;
147
+ }
148
+ export interface WebsiteCampaignCaptureResult {
149
+ accepted: boolean;
150
+ message: string;
151
+ }
152
+ export type ResolvedWebsitePublicConfig = WebsitePublicConfig & {
153
+ branding: WebsiteBrandingPublicConfig;
154
+ legal: WebsiteLegalPublicConfig;
155
+ construction: WebsiteConstructionPublicConfig;
156
+ volumePricing: WebsiteVolumePricingPublicConfig;
157
+ };
158
+ export interface WebsiteMarketingPublicConfig {
159
+ schemaVersion: 1;
160
+ enabled: boolean;
161
+ currencyCode: string;
162
+ timeZone: string;
163
+ attributionWindowDays: number;
164
+ consentPolicy: {
165
+ id: string;
166
+ version: number;
167
+ statement: string;
168
+ statementHash: string;
169
+ } | null;
170
+ destinations: {
171
+ ga4: {
172
+ measurementId: string;
173
+ diagnosticMode: boolean;
174
+ } | null;
175
+ meta: {
176
+ pixelId: string;
177
+ diagnosticMode: boolean;
178
+ } | null;
179
+ /** Browser-only Microsoft Clarity destination; absent in SDK <= 1.0.14. */
180
+ clarity?: {
181
+ projectId: string;
182
+ } | null;
183
+ };
27
184
  }
28
185
  export type WebsiteCustomerIdentifierType = "AUTO" | "EMAIL" | "PHONE" | "DOCUMENT";
29
186
  export interface WebsiteCustomerDocumentType {
@@ -49,6 +206,11 @@ export interface GetWebsitePublicConfigOptions {
49
206
  * header automatically and should omit this option.
50
207
  */
51
208
  origin?: string;
209
+ /**
210
+ * Short-lived signed token generated by Bacano. Storefronts should normally
211
+ * let `BacanoWebsiteGate` discover and manage it automatically.
212
+ */
213
+ previewToken?: string;
52
214
  }
53
215
  export interface BacanoClientContext {
54
216
  websiteId: string;
@@ -79,11 +241,68 @@ export interface Product {
79
241
  createdAt: string;
80
242
  updatedAt: string;
81
243
  variants: ProductVariant[];
244
+ /**
245
+ * Variants visible on a product detail page. Unlike `variants`, this list
246
+ * also preserves enabled public-price variants that are currently sold out.
247
+ */
248
+ detailVariants?: ProductVariant[];
82
249
  media: ProductMedia[];
83
250
  attributes: ProductAttribute[];
84
251
  relatedProducts: ProductRelatedProduct[];
252
+ optionGroup: ProductOptionGroup | null;
253
+ /** Public, non-empty technical specification resolved by Bacano. */
254
+ specification: ProductSpecification | null;
255
+ }
256
+ export interface ProductSpecification {
257
+ contentTypeId: string;
258
+ key: string;
259
+ name: string;
260
+ sections: ProductSpecificationSection[];
261
+ }
262
+ export interface ProductSpecificationSection {
263
+ id: string | null;
264
+ key: string;
265
+ title: string;
266
+ description: string | null;
267
+ sortOrder: number;
268
+ fields: ProductSpecificationField[];
269
+ }
270
+ export interface ProductSpecificationField {
271
+ id: string;
272
+ key: string;
273
+ label: string;
274
+ type: "text" | "number" | "measure" | "boolean" | "date" | "select" | "component";
275
+ sortOrder: number;
276
+ value: string | number | boolean | ProductSpecificationOption | ProductSpecificationOption[] | ProductSpecificationMeasure | ProductSpecificationField[];
277
+ }
278
+ export interface ProductSpecificationOption {
279
+ id: string;
280
+ key: string;
281
+ label: string;
282
+ }
283
+ export interface ProductSpecificationMeasure {
284
+ value: number;
285
+ unit: {
286
+ code: string;
287
+ symbol: string;
288
+ name: string;
289
+ };
85
290
  }
86
291
  export interface ProductRelatedProduct {
292
+ id: string;
293
+ productId: string;
294
+ slug: string | null;
295
+ name: string;
296
+ sku: string | null;
297
+ sortOrder: number;
298
+ media: ProductMedia[];
299
+ }
300
+ export interface ProductOptionGroup {
301
+ id: string;
302
+ title: string | null;
303
+ members: ProductOptionGroupMember[];
304
+ }
305
+ export interface ProductOptionGroupMember {
87
306
  id: string;
88
307
  productId: string;
89
308
  slug: string | null;
@@ -138,6 +357,11 @@ export interface ProductMedia {
138
357
  thumbnailUrl: string;
139
358
  cardUrl: string;
140
359
  detailUrl: string;
360
+ /** Width-labelled WebP candidates for responsive storefront images. */
361
+ responsiveSources?: Array<{
362
+ width: number;
363
+ url: string;
364
+ }>;
141
365
  mediaKind: ProductMediaKind;
142
366
  mimeType: string | null;
143
367
  fileName: string | null;
@@ -300,6 +524,16 @@ export interface ProductAvailability {
300
524
  productVariantId: string;
301
525
  inStock: boolean;
302
526
  label: string;
527
+ /** Current public purchase limit, net of active stock reservations. */
528
+ maxPurchasableQuantity: number;
529
+ }
530
+ export interface ProductVariantLiveState {
531
+ productVariantId: string;
532
+ inStock: boolean;
533
+ availabilityLabel: string;
534
+ /** Current public purchase limit, net of active stock reservations. */
535
+ maxPurchasableQuantity: number;
536
+ pricing: ProductVariantPricing;
303
537
  }
304
538
  export type ProductSortBy = "name_asc" | "name_desc" | "price_asc" | "price_desc" | "newest";
305
539
  export interface GetProductsOptions {
@@ -356,6 +590,40 @@ export interface ProductFilters {
356
590
  };
357
591
  /** Category-specific dynamic attributes — populated when categoryName is provided */
358
592
  attributes: AttributeFilter[];
593
+ /** Public technical facets derived from Bacano's typed index. */
594
+ technical: ProductSpecificationFacet[];
595
+ }
596
+ export interface ProductSpecificationFacet {
597
+ fieldId: string;
598
+ fieldPath: string;
599
+ key: string;
600
+ label: string;
601
+ type: "number" | "measure" | "boolean" | "date" | "select";
602
+ sectionKey: string | null;
603
+ unitCode: string | null;
604
+ min: number | null;
605
+ max: number | null;
606
+ dateFrom: string | null;
607
+ dateTo: string | null;
608
+ booleanValues: Array<{
609
+ value: boolean;
610
+ count: number;
611
+ }>;
612
+ options: Array<{
613
+ id: string;
614
+ key: string;
615
+ label: string;
616
+ count: number;
617
+ sortOrder: number;
618
+ }>;
619
+ }
620
+ export interface ProductSpecificationFilterSelection {
621
+ optionIds?: string[];
622
+ booleanValues?: boolean[];
623
+ min?: number;
624
+ max?: number;
625
+ dateFrom?: string;
626
+ dateTo?: string;
359
627
  }
360
628
  export interface GetProductFiltersOptions {
361
629
  /** When set, includes category-specific attribute facets */
@@ -370,6 +638,8 @@ export interface GetProductFiltersOptions {
370
638
  }
371
639
  export interface CatalogPageIncludeOptions {
372
640
  products?: boolean;
641
+ /** Include sold-out public variants for statically generated detail pages. */
642
+ detailVariants?: boolean;
373
643
  categories?: boolean;
374
644
  attributes?: boolean;
375
645
  filters?: boolean;
@@ -387,6 +657,8 @@ export interface GetCatalogPageOptions {
387
657
  minPrice?: number;
388
658
  maxPrice?: number;
389
659
  attributesBySlug?: Record<string, string[]>;
660
+ /** Technical filters keyed by the stable field ID exposed in facets. */
661
+ technicalByField?: Record<string, ProductSpecificationFilterSelection>;
390
662
  sortBy?: ProductSortBy;
391
663
  limit?: number;
392
664
  offset?: number;
@@ -443,6 +715,38 @@ export interface CatalogPageResult {
443
715
  appliedFilters: Record<string, unknown>;
444
716
  debug: CatalogPageDebug | null;
445
717
  }
718
+ export interface GetStaticCatalogSnapshotOptions {
719
+ categoryListKey: string;
720
+ attributeListKey: string;
721
+ /** Products fetched per gateway request. Defaults to the server maximum. */
722
+ pageSize?: number;
723
+ /** Safety ceiling for a single build. Defaults to 10,000 products. */
724
+ maxProducts?: number;
725
+ }
726
+ export interface GetStaticCatalogBootstrapOptions extends GetStaticCatalogSnapshotOptions {
727
+ /** Products exposed in the initial static catalog page. Defaults to 24. */
728
+ initialPageSize?: number;
729
+ /** Stable order used by both the snapshot and its initial page. */
730
+ sortBy?: ProductSortBy;
731
+ }
732
+ export interface StaticCatalogSnapshot {
733
+ schemaVersion: 1;
734
+ snapshotId: string;
735
+ generatedAt: string;
736
+ websiteId: string;
737
+ products: Product[];
738
+ total: number;
739
+ pageSize: number;
740
+ pageCount: number;
741
+ }
742
+ /**
743
+ * Complete build snapshot plus the first renderable catalog page and facets.
744
+ * This avoids a second catalog request while statically generating a store.
745
+ */
746
+ export interface StaticCatalogBootstrap extends StaticCatalogSnapshot {
747
+ bootstrapSchemaVersion: 1;
748
+ initialPage: CatalogPageResult;
749
+ }
446
750
  export type ProductRecommendationSource = "manual" | "subcategory" | "category" | "attributes" | "fallback";
447
751
  export interface ProductRecommendationPricing {
448
752
  currentPriceMin: number;
@@ -482,6 +786,18 @@ export interface ContentMedia {
482
786
  thumbnailUrl?: string | null;
483
787
  cardUrl?: string | null;
484
788
  detailUrl?: string | null;
789
+ /** Optimized full-width editorial source, capped at the original width. */
790
+ heroUrl?: string | null;
791
+ /** Width-labelled WebP candidates for responsive storefront images. */
792
+ responsiveSources?: Array<{
793
+ width: number;
794
+ url: string;
795
+ }>;
796
+ /** Intrinsic dimensions of the original image when available. */
797
+ originalWidth?: number | null;
798
+ originalHeight?: number | null;
799
+ /** @deprecated Use originalUrl/cardUrl/detailUrl/heroUrl for the rendering context. */
800
+ src?: string | null;
485
801
  /** @deprecated Use originalUrl/cardUrl/detailUrl based on the rendering context. */
486
802
  url?: string | null;
487
803
  }
@@ -594,11 +910,30 @@ export interface Cart {
594
910
  status: string;
595
911
  createdAt: string;
596
912
  updatedAt: string;
913
+ volumePricing: CartVolumePricing;
914
+ }
915
+ export interface CartVolumePricing {
916
+ enabled: boolean;
917
+ eligibleQuantity: number;
918
+ appliedPriceType: "WHOLESALE" | "WHOLESALE_2" | null;
919
+ appliedMinQuantity: number | null;
920
+ nextPriceType: "WHOLESALE" | "WHOLESALE_2" | null;
921
+ nextMinQuantity: number | null;
922
+ remainingQuantity: number | null;
923
+ totalSavings?: number;
597
924
  }
598
925
  export interface CartItem {
599
926
  id: string;
600
927
  productVariantId: string;
601
928
  quantity: number;
929
+ unitPrice: number | null;
930
+ lineTotal: number | null;
931
+ baseUnitPrice?: number | null;
932
+ unitSavings?: number;
933
+ lineSavings?: number;
934
+ volumePricingEligible?: boolean;
935
+ resolvedPriceType: ProductPriceType | null;
936
+ volumePricingMinQuantity: number | null;
602
937
  productVariant: {
603
938
  sku: string;
604
939
  product: {
@@ -628,6 +963,7 @@ export interface StartGuestCheckoutInput {
628
963
  contact: WebsiteGuestContact;
629
964
  items: WebsiteCheckoutItem[];
630
965
  fulfillmentFamily?: WebsiteFulfillmentFamily;
966
+ marketingAttribution?: WebsiteMarketingAttribution;
631
967
  }
632
968
  export interface CheckoutSubmission {
633
969
  contact: WebsiteGuestContact;
@@ -636,6 +972,8 @@ export interface CheckoutSubmission {
636
972
  shippingQuoteId?: string;
637
973
  paymentMode?: WebsitePaymentMode;
638
974
  paymentMethodId?: string;
975
+ marketingAttribution?: WebsiteMarketingAttribution;
976
+ advertisingConsent?: WebsiteAdvertisingConsent;
639
977
  /**
640
978
  * Request an account activation email after Bacano creates a valid guest order.
641
979
  * Delivery does not depend on the order being paid.