@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
@@ -0,0 +1,53 @@
1
+ import type { WebsiteMarketingAttribution } from "./types";
2
+ export declare function refreshWebsiteMarketingMetaContext(websiteId: string): boolean;
3
+ export declare function storeWebsiteMarketingGa4ClientId(websiteId: string, clientId: unknown): boolean;
4
+ export declare function storeWebsiteMarketingGa4SessionId(websiteId: string, sessionId: unknown): boolean;
5
+ export declare function captureWebsiteMarketingAttribution(websiteId: string, windowDays: number): WebsiteMarketingAttribution | null;
6
+ export declare function getWebsiteMarketingAttribution(websiteId: string): WebsiteMarketingAttribution | null;
7
+ export declare function serializeWebsiteMarketingAttribution(attribution: WebsiteMarketingAttribution): {
8
+ schema_version: 1;
9
+ first_touch: {
10
+ captured_at: string;
11
+ landing_url: string;
12
+ referrer_host: string | undefined;
13
+ source: string | undefined;
14
+ medium: string | undefined;
15
+ campaign: string | undefined;
16
+ term: string | undefined;
17
+ content: string | undefined;
18
+ source_platform: string | undefined;
19
+ campaign_id: string | undefined;
20
+ sales_origin_key: string | undefined;
21
+ gclid: string | undefined;
22
+ gbraid: string | undefined;
23
+ wbraid: string | undefined;
24
+ fbclid: string | undefined;
25
+ ttclid: string | undefined;
26
+ msclkid: string | undefined;
27
+ };
28
+ last_non_direct_touch: {
29
+ captured_at: string;
30
+ landing_url: string;
31
+ referrer_host: string | undefined;
32
+ source: string | undefined;
33
+ medium: string | undefined;
34
+ campaign: string | undefined;
35
+ term: string | undefined;
36
+ content: string | undefined;
37
+ source_platform: string | undefined;
38
+ campaign_id: string | undefined;
39
+ sales_origin_key: string | undefined;
40
+ gclid: string | undefined;
41
+ gbraid: string | undefined;
42
+ wbraid: string | undefined;
43
+ fbclid: string | undefined;
44
+ ttclid: string | undefined;
45
+ msclkid: string | undefined;
46
+ } | null;
47
+ ga4_client_id: string | undefined;
48
+ ga4_session_id: string | undefined;
49
+ meta_fbp: string | undefined;
50
+ meta_fbc: string | undefined;
51
+ client_user_agent: string | undefined;
52
+ captured_at: string;
53
+ };
@@ -0,0 +1,3 @@
1
+ export declare function prepareClarity(projectId: string): void;
2
+ export declare function loadClarityScript(projectId: string): void;
3
+ export declare function sendClarityEvent(eventName: string): void;
@@ -0,0 +1 @@
1
+ export declare function matchesCanonicalMarketingHost(canonicalDomain: string | null | undefined, currentHostname: string): boolean;
@@ -0,0 +1,2 @@
1
+ import type { WebsiteMarketingItem } from "./types";
2
+ export declare function mapGa4Items(items: WebsiteMarketingItem[] | undefined): unknown[] | undefined;
@@ -0,0 +1,5 @@
1
+ export { captureWebsiteMarketingAttribution, getWebsiteMarketingAttribution, serializeWebsiteMarketingAttribution, } from "./attribution";
2
+ export { createWebsiteMarketingRuntime } from "./runtime";
3
+ export { getAllowedMarketingParameters, sanitizeMarketingUrl, } from "./sanitize";
4
+ export type { WebsiteAdvertisingConsent, WebsiteMarketingAttribution, WebsiteMarketingBrowserEvent, WebsiteMarketingBrowserEventName, WebsiteMarketingContactPlacement, WebsiteMarketingDiagnostic, WebsiteMarketingItem, WebsiteMarketingRuntime, WebsiteMarketingRuntimeOptions, WebsiteMarketingScriptLoadStrategy, WebsiteMarketingTouchpoint, } from "./types";
5
+ export { MARKETING_SCHEMA_VERSION, WEBSITE_MARKETING_CONTACT_PLACEMENTS, } from "./types";
@@ -0,0 +1,2 @@
1
+ import type { WebsiteMarketingRuntime, WebsiteMarketingRuntimeOptions } from "./types";
2
+ export declare function createWebsiteMarketingRuntime(options: WebsiteMarketingRuntimeOptions): WebsiteMarketingRuntime;
@@ -0,0 +1,2 @@
1
+ export declare function sanitizeMarketingUrl(input: string, baseUrl?: string): string;
2
+ export declare function getAllowedMarketingParameters(input: string, baseUrl?: string): Record<string, string>;
@@ -0,0 +1,111 @@
1
+ import type { WebsiteMarketingPublicConfig } from "../types";
2
+ export declare const MARKETING_SCHEMA_VERSION: 1;
3
+ export type WebsiteMarketingBrowserEventName = "page_view" | "search" | "view_item_list" | "select_item" | "view_item" | "add_to_cart" | "remove_from_cart" | "view_cart" | "begin_checkout" | "add_shipping_info" | "add_payment_info" | "contact";
4
+ export declare const WEBSITE_MARKETING_CONTACT_PLACEMENTS: readonly ["product_detail", "floating", "header", "footer", "contact_page"];
5
+ export type WebsiteMarketingContactPlacement = (typeof WEBSITE_MARKETING_CONTACT_PLACEMENTS)[number];
6
+ export interface WebsiteMarketingItem {
7
+ /** Stable advertising identifier. Always the Bacano product variant ID. */
8
+ itemId: string;
9
+ itemName: string;
10
+ sku?: string | null;
11
+ price?: number | null;
12
+ quantity?: number;
13
+ itemBrand?: string | null;
14
+ itemCategory?: string | null;
15
+ itemVariant?: string | null;
16
+ index?: number;
17
+ }
18
+ export interface WebsiteMarketingBrowserEvent {
19
+ schemaVersion: typeof MARKETING_SCHEMA_VERSION;
20
+ eventId: string;
21
+ eventName: WebsiteMarketingBrowserEventName;
22
+ occurredAt: string;
23
+ currency?: string;
24
+ value?: number;
25
+ searchTerm?: string;
26
+ itemListId?: string;
27
+ itemListName?: string;
28
+ shippingTier?: string;
29
+ paymentType?: string;
30
+ contactMethod?: "whatsapp" | "phone" | "email";
31
+ /**
32
+ * Stable storefront location where a `contact` action was offered.
33
+ * Ignored by the runtime for every other event.
34
+ */
35
+ contactPlacement?: WebsiteMarketingContactPlacement;
36
+ items?: WebsiteMarketingItem[];
37
+ pageLocation?: string;
38
+ pageTitle?: string;
39
+ }
40
+ export interface WebsiteMarketingTouchpoint {
41
+ capturedAt: string;
42
+ landingUrl: string;
43
+ referrerHost?: string;
44
+ source?: string;
45
+ medium?: string;
46
+ campaign?: string;
47
+ term?: string;
48
+ content?: string;
49
+ sourcePlatform?: string;
50
+ campaignId?: string;
51
+ /** Optional stable public key of a custom origin configured in Bacano. */
52
+ salesOriginKey?: string;
53
+ gclid?: string;
54
+ gbraid?: string;
55
+ wbraid?: string;
56
+ fbclid?: string;
57
+ ttclid?: string;
58
+ msclkid?: string;
59
+ }
60
+ export interface WebsiteMarketingAttribution {
61
+ schemaVersion: typeof MARKETING_SCHEMA_VERSION;
62
+ firstTouch: WebsiteMarketingTouchpoint;
63
+ lastNonDirectTouch: WebsiteMarketingTouchpoint | null;
64
+ /** GA4 browser identifier used to join authoritative server events. */
65
+ ga4ClientId?: string;
66
+ /** GA4 browser session used for Realtime and session attribution. */
67
+ ga4SessionId?: string;
68
+ /** Meta browser identifier created by the Pixel. */
69
+ metaFbp?: string;
70
+ /** Meta click identifier created by the Pixel or derived from fbclid. */
71
+ metaFbc?: string;
72
+ /** Browser user agent required to match Meta server events. */
73
+ clientUserAgent?: string;
74
+ capturedAt: string;
75
+ expiresAt: string;
76
+ }
77
+ export interface WebsiteAdvertisingConsent {
78
+ policyId: string;
79
+ policyVersion: number;
80
+ statementHash: string;
81
+ granted: boolean;
82
+ }
83
+ export type WebsiteMarketingDiagnostic = {
84
+ level: "debug" | "warning";
85
+ code: string;
86
+ message: string;
87
+ eventName?: WebsiteMarketingBrowserEventName;
88
+ };
89
+ export type WebsiteMarketingScriptLoadStrategy = "immediate" | "idle";
90
+ export interface WebsiteMarketingRuntimeOptions {
91
+ websiteId: string;
92
+ config: WebsiteMarketingPublicConfig;
93
+ /**
94
+ * Canonical storefront domain. When supplied, measurement remains a no-op
95
+ * on localhost, preview hosts and copied static artifacts.
96
+ */
97
+ canonicalDomain?: string | null;
98
+ /**
99
+ * `idle` prepares the provider queues immediately, then downloads vendor
100
+ * scripts after the first interaction or an idle timeout.
101
+ */
102
+ scriptLoadStrategy?: WebsiteMarketingScriptLoadStrategy;
103
+ diagnostic?: (diagnostic: WebsiteMarketingDiagnostic) => void;
104
+ }
105
+ export interface WebsiteMarketingRuntime {
106
+ readonly enabled: boolean;
107
+ track(event: Omit<WebsiteMarketingBrowserEvent, "schemaVersion" | "eventId" | "occurredAt" | "currency"> & Partial<Pick<WebsiteMarketingBrowserEvent, "eventId" | "occurredAt" | "currency">>): void;
108
+ captureAttribution(): WebsiteMarketingAttribution | null;
109
+ getAttribution(): WebsiteMarketingAttribution | null;
110
+ destroy(): void;
111
+ }
package/media.d.ts CHANGED
@@ -1,9 +1,52 @@
1
- export type MediaUrlVariant = 'original' | 'thumbnail' | 'card' | 'detail';
2
- export type MediaTransformFormat = 'auto' | 'same' | 'jpeg' | 'webp' | 'png' | 'avif';
1
+ export type MediaUrlVariant = "original" | "thumbnail" | "card" | "detail";
2
+ export type MediaTransformFormat = "auto" | "same" | "jpeg" | "webp" | "png" | "avif";
3
+ export type MediaTransformOptions = {
4
+ width?: number;
5
+ height?: number;
6
+ quality?: number;
7
+ format?: MediaTransformFormat;
8
+ };
9
+ export type MediaResponsiveSource = {
10
+ width: number;
11
+ url: string;
12
+ };
13
+ export type MediaResponsiveSourceOptions = {
14
+ widths?: number[];
15
+ quality?: number;
16
+ format?: MediaTransformFormat;
17
+ };
3
18
  export declare function buildStorageFileUrl(storageUrl: string | undefined, fileId: string, variant?: MediaUrlVariant): string;
19
+ /**
20
+ * Build an explicitly transformed public storage URL.
21
+ *
22
+ * Storefronts should use this helper instead of manually appending storage
23
+ * query parameters. The gateway remains responsible for validating and
24
+ * bounding every transform.
25
+ */
26
+ export declare function buildStorageTransformedFileUrl(storageUrl: string | undefined, fileId: string, options: MediaTransformOptions): string;
27
+ /** Build width-labelled candidates suitable for an HTML `srcset`. */
28
+ export declare function buildStorageResponsiveSources(storageUrl: string | undefined, fileId: string, options?: MediaResponsiveSourceOptions): MediaResponsiveSource[];
29
+ export declare function formatMediaSrcSet(sources: MediaResponsiveSource[]): string;
4
30
  export declare function buildStorageMediaUrls(storageUrl: string | undefined, fileId: string): {
5
31
  originalUrl: string;
6
32
  thumbnailUrl: string;
7
33
  cardUrl: string;
8
34
  detailUrl: string;
35
+ responsiveSources: MediaResponsiveSource[];
36
+ };
37
+ /**
38
+ * Build the semantic URLs used by editorial full-width images.
39
+ *
40
+ * Candidates are capped at the original pixel width and always include the
41
+ * original width as the final candidate. When dimensions are unavailable the
42
+ * optimized srcset is intentionally empty and `heroUrl` falls back to the
43
+ * original file, preventing accidental enlargement by the storage service.
44
+ */
45
+ export declare function buildStorageContentMediaUrls(storageUrl: string | undefined, fileId: string, originalWidth?: number | null): {
46
+ heroUrl: string;
47
+ responsiveSources: MediaResponsiveSource[];
48
+ originalUrl: string;
49
+ thumbnailUrl: string;
50
+ cardUrl: string;
51
+ detailUrl: string;
9
52
  };
package/modules/auth.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- import type { AccessTokenProvider, GetWebsitePublicConfigOptions, WebsitePublicConfig } from "../types";
1
+ import type { AccessTokenProvider, BacanoClientContext, GetWebsitePublicConfigOptions, ResolvedWebsitePublicConfig, WebsitePublicConfig } from "../types";
2
+ export declare function getWebsiteContextFromPublicConfig(config: WebsitePublicConfig): BacanoClientContext | undefined;
2
3
  /** Build a bearer header from a token without inspecting or storing it. */
3
4
  export declare function createAuthHeaders(accessToken: string | null | undefined): Record<string, string>;
4
5
  export declare function createRequestHeadersProvider(websiteSlug: string, getAccessToken?: AccessTokenProvider): () => Promise<Record<string, string>>;
@@ -6,4 +7,4 @@ export declare function createRequestHeadersProvider(websiteSlug: string, getAcc
6
7
  * Load the browser-safe buyer-auth bootstrap for the current storefront.
7
8
  * Clerk secrets are intentionally never part of this response.
8
9
  */
9
- export declare function getWebsitePublicConfig(options: GetWebsitePublicConfigOptions): Promise<WebsitePublicConfig>;
10
+ export declare function getWebsitePublicConfig(options: GetWebsitePublicConfigOptions): Promise<ResolvedWebsitePublicConfig>;
@@ -1,5 +1,5 @@
1
- import type { ProductAvailability, BacanoClientContext } from '../types';
2
- import { type RequestHeadersProvider } from '../transport/graphql';
1
+ import { type RequestHeadersProvider } from "../transport/graphql";
2
+ import type { BacanoClientContext, ProductAvailability } from "../types";
3
3
  export interface AvailabilityModule {
4
4
  checkAvailability(productVariantIds: string[]): Promise<ProductAvailability[]>;
5
5
  }
@@ -0,0 +1,2 @@
1
+ export declare function getStableCartActionErrorCode(errors: string[] | null | undefined, fallbackCode: string): string;
2
+ export declare function hasRecoverableCartSessionError(errors: string[] | null | undefined): boolean;
@@ -1,4 +1,4 @@
1
- import type { BacanoClientConfig } from '../types';
1
+ import type { BacanoClientConfig } from "../types";
2
2
  export interface CartSession {
3
3
  orderId: string;
4
4
  cartToken: string;
@@ -8,6 +8,6 @@ export interface CartSessionStorage {
8
8
  set(session: CartSession): void;
9
9
  clear(): void;
10
10
  }
11
- type StorageKind = NonNullable<BacanoClientConfig['tokenStorage']>;
11
+ type StorageKind = NonNullable<BacanoClientConfig["tokenStorage"]>;
12
12
  export declare function createCartSessionStorage(kind: StorageKind, getSlug: () => string): CartSessionStorage;
13
13
  export {};
package/modules/cart.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import type { Cart, CartItem, StartGuestCheckoutInput, BacanoClientContext, WebsiteFulfillmentFamily, WebsiteGuestContact } from '../types';
2
- import { type RequestHeadersProvider } from '../transport/graphql';
3
- import type { CartSessionStorage } from './cart-session';
1
+ import { type RequestHeadersProvider } from "../transport/graphql";
2
+ import type { BacanoClientContext, Cart, CartItem, StartGuestCheckoutInput, WebsiteFulfillmentFamily, WebsiteGuestContact } from "../types";
3
+ import type { CartSessionStorage } from "./cart-session";
4
4
  export interface CartModule {
5
5
  getOrCreate(contact?: WebsiteGuestContact, fulfillmentFamily?: WebsiteFulfillmentFamily): Promise<Cart>;
6
6
  startCheckout(input: StartGuestCheckoutInput): Promise<Cart>;
@@ -12,5 +12,6 @@ export interface CartModule {
12
12
  quantity: number;
13
13
  }>;
14
14
  removeItem(cartItemId: string): Promise<Cart>;
15
+ clear(): Promise<void>;
15
16
  }
16
17
  export declare function createCartModule(graphqlUrl: string, getHeaders: RequestHeadersProvider, getContext: () => BacanoClientContext, cartSessionStorage: CartSessionStorage): CartModule;
@@ -1,14 +1,26 @@
1
- import type { Product, ProductPrice, ProductVariantPricing, ProductMedia, ProductMediaKind, ProductCategory, CatalogCategoryList, CatalogAttributeList, Brand, GetProductsOptions, GetCategoryListOptions, GetAttributeListOptions, GetCatalogPageOptions, CatalogPageResult, GetProductRecommendationsOptions, ProductRecommendationsResult, GetProductSeoEntriesOptions, ProductSeoEntriesResult, GetProductFiltersOptions, ProductFilters, SearchSuggestion, GetSearchSuggestionsOptions, BacanoClientContext } from '../types';
2
- import { type RequestHeadersProvider } from '../transport/graphql';
1
+ import { type RequestHeadersProvider } from "../transport/graphql";
2
+ import type { BacanoClientContext, Brand, CatalogAttributeList, CatalogCategoryList, CatalogPageResult, GetAttributeListOptions, GetCatalogPageOptions, GetCategoryListOptions, GetProductFiltersOptions, GetProductRecommendationsOptions, GetProductSeoEntriesOptions, GetProductsOptions, GetSearchSuggestionsOptions, GetStaticCatalogBootstrapOptions, GetStaticCatalogSnapshotOptions, Product, ProductCategory, ProductFilters, ProductMedia, ProductMediaKind, ProductPrice, ProductRecommendationsResult, ProductSeoEntriesResult, ProductVariant, ProductVariantLiveState, ProductVariantPricing, SearchSuggestion, StaticCatalogBootstrap, StaticCatalogSnapshot } from "../types";
3
3
  export declare function getProductMediaKind(mimeType?: string | null): ProductMediaKind;
4
4
  export declare function getProductMediaByKind(media: ProductMedia[] | null | undefined, kind: ProductMediaKind): ProductMedia[];
5
5
  export declare function getProductImages(media: ProductMedia[] | null | undefined): ProductMedia[];
6
6
  export declare function getProductVideos(media: ProductMedia[] | null | undefined): ProductMedia[];
7
+ /**
8
+ * Returns the variants that belong in a product detail selector.
9
+ *
10
+ * Static catalog snapshots expose saleable variants in `variants` so cards,
11
+ * filters and prices remain stable, while `detailVariants` also preserves
12
+ * enabled public-price variants that are currently sold out. The fallback
13
+ * keeps cached snapshots produced by older SDK versions compatible.
14
+ */
15
+ export declare function getProductDetailVariants(product: Product): ProductVariant[];
7
16
  export declare function getPrimaryProductImage(media: ProductMedia[] | null | undefined): ProductMedia | null;
8
17
  export declare function resolveProductPricing(prices: ProductPrice[]): ProductVariantPricing;
9
18
  export interface CatalogModule {
10
19
  getCatalogPage(opts: GetCatalogPageOptions): Promise<CatalogPageResult>;
20
+ getStaticCatalogSnapshot(opts: GetStaticCatalogSnapshotOptions): Promise<StaticCatalogSnapshot>;
21
+ getStaticCatalogBootstrap(opts: GetStaticCatalogBootstrapOptions): Promise<StaticCatalogBootstrap>;
11
22
  getProductRecommendations(opts: GetProductRecommendationsOptions): Promise<ProductRecommendationsResult>;
23
+ getProductLiveState(productVariantIds: string[]): Promise<ProductVariantLiveState[]>;
12
24
  getProductSeoEntries(opts?: GetProductSeoEntriesOptions): Promise<ProductSeoEntriesResult>;
13
25
  getProducts(opts?: GetProductsOptions): Promise<Product[]>;
14
26
  getProduct(productId: string): Promise<Product | null>;
@@ -21,4 +33,4 @@ export interface CatalogModule {
21
33
  getSearchSuggestions(opts: GetSearchSuggestionsOptions): Promise<SearchSuggestion[]>;
22
34
  checkAvailability: never;
23
35
  }
24
- export declare function createCatalogModule(graphqlUrl: string, getHeaders: RequestHeadersProvider, getContext: () => BacanoClientContext, storageUrl?: string): Omit<CatalogModule, 'checkAvailability'>;
36
+ export declare function createCatalogModule(graphqlUrl: string, getHeaders: RequestHeadersProvider, getContext: () => BacanoClientContext, storageUrl?: string): Omit<CatalogModule, "checkAvailability">;
@@ -1,5 +1,5 @@
1
- import type { GetContentOptions, ContentEntry, ProductContentBlock, BacanoClientContext } from '../types';
2
- import { type RequestHeadersProvider } from '../transport/graphql';
1
+ import { type RequestHeadersProvider } from "../transport/graphql";
2
+ import type { BacanoClientContext, ContentEntry, GetContentOptions, ProductContentBlock } from "../types";
3
3
  export interface ContentModule {
4
4
  getByKey(key: string, opts?: GetContentOptions): Promise<ContentEntry | null>;
5
5
  getByCategory(categoryKey: string, opts?: GetContentOptions): Promise<ContentEntry[]>;
@@ -0,0 +1,5 @@
1
+ import type { BacanoClientContext, WebsiteCampaignCaptureInput, WebsiteCampaignCaptureResult } from "../types";
2
+ export interface MarketingModule {
3
+ captureLead(input: WebsiteCampaignCaptureInput): Promise<WebsiteCampaignCaptureResult>;
4
+ }
5
+ export declare function createMarketingModule(apiUrl: string, websiteSlug: string, getContext: () => BacanoClientContext): MarketingModule;
@@ -1,5 +1,5 @@
1
- import type { BacanoClientContext, GetOrdersOptions, Order, PublicOrder, PublicOrderLookupInput, WaitForPublicOrderPaymentInput } from '../types';
2
- import { type RequestHeadersProvider } from '../transport/graphql';
1
+ import { type RequestHeadersProvider } from "../transport/graphql";
2
+ import type { BacanoClientContext, GetOrdersOptions, Order, PublicOrder, PublicOrderLookupInput, WaitForPublicOrderPaymentInput } from "../types";
3
3
  export interface OrdersModule {
4
4
  list(opts?: GetOrdersOptions): Promise<Order[]>;
5
5
  get(orderId: string): Promise<Order | null>;
@@ -1,5 +1,5 @@
1
- import type { CustomerAddress, CustomerProfile, CustomerProfileUpdate } from "../types";
2
1
  import { type RequestHeadersProvider } from "../transport/graphql";
2
+ import type { CustomerAddress, CustomerProfile, CustomerProfileUpdate } from "../types";
3
3
  export interface ProfileModule {
4
4
  get(): Promise<CustomerProfile>;
5
5
  getAddresses(): Promise<CustomerAddress[]>;
@@ -0,0 +1,13 @@
1
+ import type { CatalogPageResult, GetCatalogPageOptions, GetStaticCatalogBootstrapOptions, GetStaticCatalogSnapshotOptions, StaticCatalogSnapshot } from "../types";
2
+ type StaticCatalogCollectorOptions = {
3
+ websiteId: string;
4
+ snapshot: GetStaticCatalogSnapshotOptions;
5
+ bootstrap?: Pick<GetStaticCatalogBootstrapOptions, "initialPageSize" | "sortBy">;
6
+ loadPage: (options: GetCatalogPageOptions) => Promise<CatalogPageResult>;
7
+ };
8
+ export type StaticCatalogCollection = {
9
+ snapshot: StaticCatalogSnapshot;
10
+ initialPage: CatalogPageResult | null;
11
+ };
12
+ export declare function collectStaticCatalog({ websiteId, snapshot: options, bootstrap, loadPage, }: StaticCatalogCollectorOptions): Promise<StaticCatalogCollection>;
13
+ export {};
@@ -1,3 +1,9 @@
1
- import type { BacanoClientContext } from "../types";
2
1
  import { type RequestHeadersProvider } from "../transport/graphql";
2
+ import type { BacanoClientContext } from "../types";
3
3
  export declare function resolveWebsite(graphqlUrl: string, slug: string, headers?: RequestHeadersProvider): Promise<BacanoClientContext>;
4
+ /**
5
+ * Share the immutable public website bootstrap between SDK clients created by
6
+ * different React integrations in the same runtime.
7
+ */
8
+ export declare function resolveWebsiteCached(graphqlUrl: string, slug: string, headers?: RequestHeadersProvider): Promise<BacanoClientContext>;
9
+ export declare function clearWebsiteContextCache(): void;
package/package.json CHANGED
@@ -1,10 +1,16 @@
1
1
  {
2
2
  "name": "@bacano/sdk",
3
- "version": "1.0.1",
3
+ "version": "1.1.8",
4
4
  "description": "TypeScript SDK for building websites on the Bacano ERP",
5
5
  "main": "./index.cjs",
6
6
  "module": "./index.js",
7
7
  "types": "./index.d.ts",
8
+ "bin": {
9
+ "bacano-web": "./skills/bacano-web/scripts/cli.mjs"
10
+ },
11
+ "scripts": {
12
+ "postinstall": "node ./skills/bacano-web/scripts/postinstall.mjs"
13
+ },
8
14
  "exports": {
9
15
  ".": {
10
16
  "types": "./index.d.ts",
@@ -20,6 +26,11 @@
20
26
  "types": "./react.d.ts",
21
27
  "import": "./react.js",
22
28
  "require": "./react.cjs"
29
+ },
30
+ "./react/preview": {
31
+ "types": "./react/preview.d.ts",
32
+ "import": "./react/preview.js",
33
+ "require": "./react/preview.cjs"
23
34
  }
24
35
  },
25
36
  "sideEffects": false,
@@ -28,10 +39,10 @@
28
39
  },
29
40
  "repository": {
30
41
  "type": "git",
31
- "url": "git+https://github.com/pulpo-labs/erp.git",
42
+ "url": "git+https://github.com/bacano-erp/erp.git",
32
43
  "directory": "libs/sdk"
33
44
  },
34
- "homepage": "https://github.com/pulpo-labs/erp/tree/main/libs/sdk#readme",
45
+ "homepage": "https://github.com/bacano-erp/erp/tree/main/libs/sdk#readme",
35
46
  "peerDependencies": {
36
47
  "react": ">=18.0.0"
37
48
  },
@@ -0,0 +1,9 @@
1
+ import { type Context } from "react";
2
+ /**
3
+ * Returns one React context per key in the current JavaScript realm.
4
+ *
5
+ * The SDK publishes independently bundled React entrypoints. A global symbol
6
+ * prevents those bundles from creating private context instances while still
7
+ * keeping provider values isolated by each React tree.
8
+ */
9
+ export declare function getOrCreateReactContext<T>(key: string, defaultValue: T): Context<T>;
@@ -1,4 +1,4 @@
1
- import type { BacanoClient } from '../client';
1
+ import type { BacanoClient } from "../client";
2
2
  export interface BacanoClientContextValue {
3
3
  client: BacanoClient | null;
4
4
  loading: boolean;
package/react/hooks.d.ts CHANGED
@@ -1,9 +1,11 @@
1
- import type { BacanoClient } from '../client';
2
- import type { Product, ProductCategory, CatalogCategoryList, CatalogAttributeList, Brand, ProductAvailability, ProductFilters, GetProductsOptions, GetCategoryListOptions, GetAttributeListOptions, GetProductFiltersOptions, SearchSuggestion, GetSearchSuggestionsOptions, ContentEntry, GetContentOptions, Cart, CartItem, StartGuestCheckoutInput, WebsiteFulfillmentFamily, WebsiteGuestContact, CheckoutSubmission, CheckoutResult, Order, GetOrdersOptions, CustomerProfile, CustomerProfileUpdate, AsyncState } from '../types';
1
+ import type { BacanoClient } from "../client";
2
+ import type { AsyncState, Brand, Cart, CartItem, CatalogAttributeList, CatalogCategoryList, CheckoutResult, CheckoutSubmission, ContentEntry, CustomerProfile, CustomerProfileUpdate, GetAttributeListOptions, GetCategoryListOptions, GetContentOptions, GetOrdersOptions, GetProductFiltersOptions, GetProductsOptions, GetSearchSuggestionsOptions, Order, Product, ProductAvailability, ProductCategory, ProductFilters, ProductVariantLiveState, SearchSuggestion, StartGuestCheckoutInput, WebsiteFulfillmentFamily, WebsiteGuestContact } from "../types";
3
3
  /** Returns the initialized BacanoClient instance */
4
4
  export declare function useBacano(): BacanoClient;
5
5
  /** Returns the initialization state (for loading/error handling) */
6
6
  export declare function useBacanoState(): import("./context").BacanoClientContextValue;
7
+ /** Returns the storefront marketing runtime. It is a safe no-op when disabled. */
8
+ export declare function useMarketing(): import("..").WebsiteMarketingRuntime;
7
9
  export declare function useProducts(opts?: GetProductsOptions): AsyncState<Product[]> & {
8
10
  refetch: () => void;
9
11
  };
@@ -31,6 +33,25 @@ export declare function useSearchSuggestions(opts?: GetSearchSuggestionsOptions)
31
33
  export declare function useAvailability(productVariantIds: string[]): AsyncState<ProductAvailability[]> & {
32
34
  refetch: () => void;
33
35
  };
36
+ /**
37
+ * Stock *and* price, live, in one request.
38
+ *
39
+ * `useAvailability` answers only "can this be bought". That is half the
40
+ * question a storefront needs, because price and discount are baked into the
41
+ * static export at build time and the cart charges whatever is true now — so a
42
+ * page can advertise a sale that ended and a price nobody will honour.
43
+ *
44
+ * Worse, a promotion ends because *time passed*. No row changes, so no rebuild
45
+ * is ever triggered, and the stale offer survives until something unrelated
46
+ * causes a publish. Reading price live is the only thing that fixes that.
47
+ *
48
+ * Costs no extra round trip on a product page that already checks stock:
49
+ * `getProductLiveState` returns both. Prefer it over `useAvailability`
50
+ * anywhere a price is displayed.
51
+ */
52
+ export declare function useProductLiveState(productVariantIds: string[]): AsyncState<ProductVariantLiveState[]> & {
53
+ refetch: () => void;
54
+ };
34
55
  export declare function useContentByKey(key: string | null, opts?: GetContentOptions): AsyncState<ContentEntry | null> & {
35
56
  refetch: () => void;
36
57
  };
@@ -52,6 +73,7 @@ export declare function useCart(): {
52
73
  quantity: number;
53
74
  }>;
54
75
  removeItem: (cartItemId: string) => Promise<void>;
76
+ clear: () => Promise<void>;
55
77
  refresh: () => Promise<void>;
56
78
  };
57
79
  export declare function useCheckout(): {
@@ -0,0 +1,3 @@
1
+ import type { WebsiteMarketingRuntime } from "../marketing";
2
+ export declare const NOOP_MARKETING_RUNTIME: WebsiteMarketingRuntime;
3
+ export declare const BacanoMarketingContext: import("react").Context<WebsiteMarketingRuntime>;
@@ -0,0 +1,10 @@
1
+ import { type JSX, type ReactNode } from "react";
2
+ import type { WebsiteMarketingDiagnostic, WebsiteMarketingScriptLoadStrategy } from "../marketing";
3
+ import type { WebsitePublicConfig } from "../types";
4
+ export interface BacanoMarketingProviderProps {
5
+ publicConfig: WebsitePublicConfig | null;
6
+ children: ReactNode;
7
+ scriptLoadStrategy?: WebsiteMarketingScriptLoadStrategy;
8
+ diagnostic?: (diagnostic: WebsiteMarketingDiagnostic) => void;
9
+ }
10
+ export declare function BacanoMarketingProvider({ publicConfig, children, scriptLoadStrategy, diagnostic, }: BacanoMarketingProviderProps): JSX.Element;
@@ -0,0 +1,23 @@
1
+ import type { BacanoClient } from "../../client";
2
+ import type { PreviewRouteLoader } from "./types";
3
+ export interface PreviewCacheValue<TDocument> {
4
+ document: TDocument;
5
+ refreshedAt: Date;
6
+ }
7
+ export declare class PreviewRouteCache<TDocument> {
8
+ private readonly maxEntries;
9
+ private readonly values;
10
+ private readonly inFlight;
11
+ constructor(maxEntries: number);
12
+ load(input: {
13
+ route: string;
14
+ force: boolean;
15
+ client: BacanoClient;
16
+ loader: PreviewRouteLoader<TDocument>;
17
+ }): Promise<PreviewCacheValue<TDocument>>;
18
+ clear(): void;
19
+ private trim;
20
+ }
21
+ export declare class EmptyPreviewDocumentError extends Error {
22
+ constructor();
23
+ }
@@ -0,0 +1,5 @@
1
+ import type { BacanoPreviewContextValue } from "./types";
2
+ export declare const BacanoPreviewModeContext: import("react").Context<boolean>;
3
+ export declare const BacanoPreviewContext: import("react").Context<BacanoPreviewContextValue<unknown> | null>;
4
+ export declare function useBacanoPreview<TDocument = unknown>(): BacanoPreviewContextValue<TDocument>;
5
+ export declare function useBacanoPreviewMode(): boolean;
@@ -0,0 +1,9 @@
1
+ import type { MouseEvent as ReactMouseEvent } from "react";
2
+ export declare function normalizePreviewRoute(value: string | null | undefined): string;
3
+ export interface PreviewLinkInterceptorOptions {
4
+ navigate: (route: string) => void;
5
+ normalizeRoute?: (route: string) => string;
6
+ isPreviewableRoute?: (route: string) => boolean;
7
+ origin?: string;
8
+ }
9
+ export declare function interceptPreviewLink(event: Pick<ReactMouseEvent<HTMLElement>, "altKey" | "button" | "ctrlKey" | "defaultPrevented" | "metaKey" | "preventDefault" | "shiftKey" | "target">, options: PreviewLinkInterceptorOptions): boolean;
@@ -0,0 +1,3 @@
1
+ import { type JSX } from "react";
2
+ import type { BacanoPreviewProviderProps } from "./types";
3
+ export declare function BacanoPreviewProvider<TDocument>({ websiteSlug, route: requestedRoute, loadRoute, navigate: navigateStorefront, normalizeRoute, isPreviewableRoute, initialExpanded, initialPosition, cacheMaxEntries, children, }: BacanoPreviewProviderProps<TDocument>): JSX.Element;
@@ -0,0 +1,3 @@
1
+ import type { JSX } from "react";
2
+ import type { BacanoPreviewShellProps } from "./types";
3
+ export declare function BacanoPreviewShell<TDocument>({ toolbar, children, ...providerProps }: BacanoPreviewShellProps<TDocument>): JSX.Element;
@@ -0,0 +1,3 @@
1
+ import { type JSX } from "react";
2
+ import type { BacanoPreviewToolbarProps } from "./types";
3
+ export declare function BacanoPreviewToolbar({ websiteName, logo, primaryColor, accentColor, backgroundColor, locale, zIndex, suggestedRoutes, }: BacanoPreviewToolbarProps): JSX.Element;