@cimplify/sdk 0.48.2 → 0.49.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/react.mjs CHANGED
@@ -6975,6 +6975,289 @@ function ProductImageGallery({
6975
6975
  )
6976
6976
  ] });
6977
6977
  }
6978
+ var ASPECT_STYLES2 = {
6979
+ square: { aspectRatio: "1/1" },
6980
+ "4/3": { aspectRatio: "4/3" },
6981
+ "16/9": { aspectRatio: "16/9" },
6982
+ "16/10": { aspectRatio: "16/10" },
6983
+ "3/4": { aspectRatio: "3/4" }
6984
+ };
6985
+ function StoreVideo({
6986
+ src,
6987
+ poster,
6988
+ alt,
6989
+ aspectRatio = "16/9",
6990
+ controls = false,
6991
+ autoplay = true,
6992
+ loop = true,
6993
+ muted = true,
6994
+ lazy = true,
6995
+ className
6996
+ }) {
6997
+ const ref = useRef(null);
6998
+ const [inView, setInView] = useState(!lazy);
6999
+ useEffect(() => {
7000
+ if (!lazy || inView) return;
7001
+ const node = ref.current;
7002
+ if (!node || typeof IntersectionObserver === "undefined") {
7003
+ setInView(true);
7004
+ return;
7005
+ }
7006
+ const observer = new IntersectionObserver(
7007
+ (entries) => {
7008
+ if (entries.some((e) => e.isIntersecting)) {
7009
+ setInView(true);
7010
+ observer.disconnect();
7011
+ }
7012
+ },
7013
+ { rootMargin: "200px" }
7014
+ );
7015
+ observer.observe(node);
7016
+ return () => observer.disconnect();
7017
+ }, [lazy, inView]);
7018
+ return /* @__PURE__ */ jsx(
7019
+ "div",
7020
+ {
7021
+ "data-cimplify-store-video": true,
7022
+ className,
7023
+ style: { position: "relative", overflow: "hidden", ...ASPECT_STYLES2[aspectRatio] },
7024
+ children: /* @__PURE__ */ jsx(
7025
+ "video",
7026
+ {
7027
+ ref,
7028
+ src: inView ? src : void 0,
7029
+ poster,
7030
+ autoPlay: autoplay,
7031
+ loop,
7032
+ muted,
7033
+ playsInline: true,
7034
+ controls,
7035
+ preload: lazy ? "metadata" : "auto",
7036
+ "aria-label": alt,
7037
+ style: { width: "100%", height: "100%", objectFit: "cover", display: "block" },
7038
+ children: poster ? /* @__PURE__ */ jsx(
7039
+ "img",
7040
+ {
7041
+ src: poster,
7042
+ alt: alt ?? "",
7043
+ style: { width: "100%", height: "100%", objectFit: "cover" }
7044
+ }
7045
+ ) : null
7046
+ }
7047
+ )
7048
+ }
7049
+ );
7050
+ }
7051
+ var ASPECT_STYLES3 = {
7052
+ square: { aspectRatio: "1/1" },
7053
+ "4/3": { aspectRatio: "4/3" },
7054
+ "16/9": { aspectRatio: "16/9" },
7055
+ "3/4": { aspectRatio: "3/4" }
7056
+ };
7057
+ var MODEL_VIEWER_CDN = "https://unpkg.com/@google/model-viewer@4.0.0/dist/model-viewer.min.js";
7058
+ var modelViewerLoadPromise = null;
7059
+ function ensureModelViewer() {
7060
+ if (typeof window === "undefined") return Promise.resolve();
7061
+ if (modelViewerLoadPromise) return modelViewerLoadPromise;
7062
+ if (window.customElements?.get("model-viewer")) {
7063
+ modelViewerLoadPromise = Promise.resolve();
7064
+ return modelViewerLoadPromise;
7065
+ }
7066
+ modelViewerLoadPromise = new Promise((resolve, reject) => {
7067
+ const script = document.createElement("script");
7068
+ script.type = "module";
7069
+ script.src = MODEL_VIEWER_CDN;
7070
+ script.onload = () => resolve();
7071
+ script.onerror = () => reject(new Error("Failed to load model-viewer"));
7072
+ document.head.appendChild(script);
7073
+ });
7074
+ return modelViewerLoadPromise;
7075
+ }
7076
+ function ProductModel3D({
7077
+ src,
7078
+ iosSrc,
7079
+ poster,
7080
+ alt,
7081
+ aspectRatio = "square",
7082
+ ar = true,
7083
+ autoRotate = true,
7084
+ cameraControls = true,
7085
+ className
7086
+ }) {
7087
+ const [ready, setReady] = useState(false);
7088
+ useEffect(() => {
7089
+ let cancelled = false;
7090
+ ensureModelViewer().then(
7091
+ () => {
7092
+ if (!cancelled) setReady(true);
7093
+ },
7094
+ () => {
7095
+ }
7096
+ );
7097
+ return () => {
7098
+ cancelled = true;
7099
+ };
7100
+ }, []);
7101
+ return /* @__PURE__ */ jsx(
7102
+ "div",
7103
+ {
7104
+ "data-cimplify-product-model-3d": true,
7105
+ className,
7106
+ style: { position: "relative", overflow: "hidden", ...ASPECT_STYLES3[aspectRatio] },
7107
+ children: ready ? React10.createElement("model-viewer", {
7108
+ src,
7109
+ "ios-src": iosSrc,
7110
+ alt,
7111
+ poster,
7112
+ ar: ar || void 0,
7113
+ "ar-modes": ar ? "webxr scene-viewer quick-look" : void 0,
7114
+ "camera-controls": cameraControls || void 0,
7115
+ "auto-rotate": autoRotate || void 0,
7116
+ "shadow-intensity": "1",
7117
+ style: { width: "100%", height: "100%", backgroundColor: "transparent" }
7118
+ }) : poster ? React10.createElement("img", {
7119
+ src: poster,
7120
+ alt: alt ?? "",
7121
+ "data-cimplify-product-model-3d-loading": true,
7122
+ style: { width: "100%", height: "100%", objectFit: "cover" }
7123
+ }) : React10.createElement("div", {
7124
+ "data-cimplify-product-model-3d-loading": true,
7125
+ style: { width: "100%", height: "100%", backgroundColor: "var(--muted, #f3f4f6)" }
7126
+ })
7127
+ }
7128
+ );
7129
+ }
7130
+ var ASPECT_STYLES4 = {
7131
+ square: { aspectRatio: "1/1" },
7132
+ "4/3": { aspectRatio: "4/3" },
7133
+ "16/10": { aspectRatio: "16/10" },
7134
+ "3/4": { aspectRatio: "3/4" }
7135
+ };
7136
+ function thumbnailFor(item) {
7137
+ if (item.type === "image") return item.src;
7138
+ return item.poster ?? null;
7139
+ }
7140
+ function thumbIcon(item) {
7141
+ if (item.type === "video") return "\u25B6";
7142
+ if (item.type === "model") return "\u25C6";
7143
+ return null;
7144
+ }
7145
+ function MediaGallery({
7146
+ items,
7147
+ productName,
7148
+ aspectRatio = "4/3",
7149
+ className
7150
+ }) {
7151
+ const validItems = useMemo(
7152
+ () => items.filter((i) => typeof i.src === "string" && i.src.trim().length > 0),
7153
+ [items]
7154
+ );
7155
+ const [selected, setSelected] = useState(0);
7156
+ useEffect(() => {
7157
+ setSelected(0);
7158
+ }, [validItems.length, productName]);
7159
+ if (validItems.length === 0) return null;
7160
+ const active = validItems[selected] ?? validItems[0];
7161
+ return /* @__PURE__ */ jsxs("div", { "data-cimplify-media-gallery": true, className, children: [
7162
+ /* @__PURE__ */ jsx(
7163
+ "div",
7164
+ {
7165
+ "data-cimplify-media-gallery-main": true,
7166
+ style: { position: "relative", overflow: "hidden", ...ASPECT_STYLES4[aspectRatio] },
7167
+ children: active.type === "image" ? /* @__PURE__ */ jsx(
7168
+ "img",
7169
+ {
7170
+ src: active.src,
7171
+ alt: active.alt ?? productName,
7172
+ style: { width: "100%", height: "100%", objectFit: "cover" },
7173
+ "data-cimplify-media-gallery-active": true
7174
+ }
7175
+ ) : active.type === "video" ? /* @__PURE__ */ jsx(
7176
+ StoreVideo,
7177
+ {
7178
+ src: active.src,
7179
+ poster: active.poster,
7180
+ alt: active.alt ?? productName,
7181
+ aspectRatio: "square",
7182
+ lazy: false
7183
+ }
7184
+ ) : /* @__PURE__ */ jsx(
7185
+ ProductModel3D,
7186
+ {
7187
+ src: active.src,
7188
+ iosSrc: active.iosSrc,
7189
+ poster: active.poster,
7190
+ alt: active.alt ?? productName,
7191
+ aspectRatio: "square"
7192
+ }
7193
+ )
7194
+ }
7195
+ ),
7196
+ validItems.length > 1 && /* @__PURE__ */ jsx(
7197
+ RadioGroup,
7198
+ {
7199
+ "aria-label": `${productName} media thumbnails`,
7200
+ value: String(selected),
7201
+ onValueChange: (v) => setSelected(Number(v)),
7202
+ "data-cimplify-media-gallery-thumbnails": true,
7203
+ style: { display: "flex", gap: "0.5rem", marginTop: "0.75rem" },
7204
+ children: validItems.map((item, index) => {
7205
+ const thumb = thumbnailFor(item);
7206
+ const icon = thumbIcon(item);
7207
+ const isSelected = selected === index;
7208
+ return /* @__PURE__ */ jsxs(
7209
+ Radio.Root,
7210
+ {
7211
+ value: String(index),
7212
+ "data-cimplify-media-gallery-thumb": true,
7213
+ "data-selected": isSelected || void 0,
7214
+ "data-type": item.type,
7215
+ style: {
7216
+ position: "relative",
7217
+ width: "4rem",
7218
+ height: "4rem",
7219
+ overflow: "hidden",
7220
+ padding: 0,
7221
+ border: "none",
7222
+ cursor: "pointer",
7223
+ backgroundColor: "var(--muted, #f3f4f6)"
7224
+ },
7225
+ children: [
7226
+ thumb ? /* @__PURE__ */ jsx(
7227
+ "img",
7228
+ {
7229
+ src: thumb,
7230
+ alt: "",
7231
+ style: { width: "100%", height: "100%", objectFit: "cover" }
7232
+ }
7233
+ ) : null,
7234
+ icon ? /* @__PURE__ */ jsx(
7235
+ "span",
7236
+ {
7237
+ "aria-hidden": true,
7238
+ style: {
7239
+ position: "absolute",
7240
+ inset: 0,
7241
+ display: "flex",
7242
+ alignItems: "center",
7243
+ justifyContent: "center",
7244
+ color: "white",
7245
+ fontSize: "0.875rem",
7246
+ textShadow: "0 1px 2px rgba(0,0,0,0.6)",
7247
+ pointerEvents: "none"
7248
+ },
7249
+ children: icon
7250
+ }
7251
+ ) : null
7252
+ ]
7253
+ },
7254
+ `${item.src}-${index}`
7255
+ );
7256
+ })
7257
+ }
7258
+ )
7259
+ ] });
7260
+ }
6978
7261
  function CartLineItemRow({
6979
7262
  item,
6980
7263
  onRemove,
@@ -8381,7 +8664,7 @@ var CardVariant = /* @__PURE__ */ ((CardVariant2) => {
8381
8664
  CardVariant2["Subscription"] = "subscription";
8382
8665
  return CardVariant2;
8383
8666
  })(CardVariant || {});
8384
- var ASPECT_STYLES2 = {
8667
+ var ASPECT_STYLES5 = {
8385
8668
  square: { aspectRatio: "1/1" },
8386
8669
  "4/3": { aspectRatio: "4/3" },
8387
8670
  "16/10": { aspectRatio: "16/10" },
@@ -8490,7 +8773,7 @@ function ProductCard({
8490
8773
  {
8491
8774
  "data-cimplify-product-card-image-container": true,
8492
8775
  className: cn("overflow-hidden rounded-t-xl", classNames?.imageContainer),
8493
- style: ASPECT_STYLES2[aspectRatio],
8776
+ style: ASPECT_STYLES5[aspectRatio],
8494
8777
  children: renderImage ? renderImage({ src: imageUrl, alt: product.name, className: classNames?.image }) : /* @__PURE__ */ jsx(
8495
8778
  "img",
8496
8779
  {
@@ -13615,4 +13898,4 @@ function SparkleIcon({ className }) {
13615
13898
  );
13616
13899
  }
13617
13900
 
13618
- export { AccommodationCard, Ad, AdProvider, AddOnSelector, AddressElement, AuthElement, AvailabilityBadge, BillingPlanSelector, BookingCard, BookingList, BookingPage, BookingsPage, BundleProductCard, BundleProductLayout, BundleSelector, CardImage, CardShell, CardVariant, CartDrawer, CartDrawerProvider, CartPage, CartSummary, CartTemplate, CatalogueCollectionLayout, CataloguePage, CatalogueTemplate, CategoryFilter, CategoryGrid, ChatWidget, CheckoutPage, CimplifyAccount, CimplifyCheckout, CimplifyProvider, CollectionPage, CollectionTemplate, CompactCartLayout, CompactCatalogueLayout, CompactSearchLayout, CompactServiceCard, CompositeProductCard, CompositeProductLayout, CompositeSelector, CurrencySelector, CustomAttributesTable, CustomerInputFields, DatePicker, DateSlotPicker, DealBanner, DealsPage, DefaultCartLayout, DefaultCatalogueLayout, DefaultCollectionLayout, DefaultProductLayout, DefaultSearchLayout, DeliveryEstimate, DigitalProductCard, DigitalProductLayout, DiscountInput, ElementsProvider, FeaturedCollectionLayout, FoodProductCard, FoodProductLayout, InventoryBadge, LeaseServiceCard, LocationPicker, MetadataStringList, OrderDetailPage, OrderHistory, OrderHistoryPage, OrderSummary, PaymentElement, Price, PriceRange, ProductCard, ProductCustomizer, ProductGrid, ProductImageGallery, ProductPage, ProductSheet, ProductTemplate, PropertiesTable, QuantitySelector, QuickAddButton, RecentlyViewed, RecommendationCarousel, RelatedProductsSection, RentalServiceCard, ResourcePicker, RetailProductCard, SaleBadge, ScheduleServiceCard, SearchInput, SearchPage, SearchTemplate, ServiceProductLayout, SessionMessageBanner, SlotPicker, SoldOutOverlay, StaffPicker, StandardServiceCard, StoreNav, SubscriptionCard, TagPills, TimePicker, TwoColumnGrid, VariantSelector, VolumePricing, WholesaleProductCard, WholesaleProductLayout, WishlistButton, cn, roomToResource, useActivityState, useAds, useAttributeDefinitions, useAvailableSlots, useBillingPlans, useBookings, useBootstrap, useBundles, useCart, useCartDrawer, useCategories, useChat, useCheckout, useCimplify, useCimplifyClient, useCollection, useCollections, useDeals, useDeliveryFee, useElements, useElementsReady, useFxRate, useLocations, useOptionalCimplify, useOrder, useOrders, useProduct, useProductAvailability, useProductDeals, useProductPrice, useProductSchedules, useProducts, useProductsOnSale, usePropertyFacets, useQuote, useRecommendations, useSearch, useServiceAvailability, useServices, useSubscription, useSubscriptions, useTaxonomies, useTaxonomy, useTaxonomyPath, useValidateDiscount, useVariantSelector };
13901
+ export { AccommodationCard, Ad, AdProvider, AddOnSelector, AddressElement, AuthElement, AvailabilityBadge, BillingPlanSelector, BookingCard, BookingList, BookingPage, BookingsPage, BundleProductCard, BundleProductLayout, BundleSelector, CardImage, CardShell, CardVariant, CartDrawer, CartDrawerProvider, CartPage, CartSummary, CartTemplate, CatalogueCollectionLayout, CataloguePage, CatalogueTemplate, CategoryFilter, CategoryGrid, ChatWidget, CheckoutPage, CimplifyAccount, CimplifyCheckout, CimplifyProvider, CollectionPage, CollectionTemplate, CompactCartLayout, CompactCatalogueLayout, CompactSearchLayout, CompactServiceCard, CompositeProductCard, CompositeProductLayout, CompositeSelector, CurrencySelector, CustomAttributesTable, CustomerInputFields, DatePicker, DateSlotPicker, DealBanner, DealsPage, DefaultCartLayout, DefaultCatalogueLayout, DefaultCollectionLayout, DefaultProductLayout, DefaultSearchLayout, DeliveryEstimate, DigitalProductCard, DigitalProductLayout, DiscountInput, ElementsProvider, FeaturedCollectionLayout, FoodProductCard, FoodProductLayout, InventoryBadge, LeaseServiceCard, LocationPicker, MediaGallery, MetadataStringList, OrderDetailPage, OrderHistory, OrderHistoryPage, OrderSummary, PaymentElement, Price, PriceRange, ProductCard, ProductCustomizer, ProductGrid, ProductImageGallery, ProductModel3D, ProductPage, ProductSheet, ProductTemplate, PropertiesTable, QuantitySelector, QuickAddButton, RecentlyViewed, RecommendationCarousel, RelatedProductsSection, RentalServiceCard, ResourcePicker, RetailProductCard, SaleBadge, ScheduleServiceCard, SearchInput, SearchPage, SearchTemplate, ServiceProductLayout, SessionMessageBanner, SlotPicker, SoldOutOverlay, StaffPicker, StandardServiceCard, StoreNav, StoreVideo, SubscriptionCard, TagPills, TimePicker, TwoColumnGrid, VariantSelector, VolumePricing, WholesaleProductCard, WholesaleProductLayout, WishlistButton, cn, roomToResource, useActivityState, useAds, useAttributeDefinitions, useAvailableSlots, useBillingPlans, useBookings, useBootstrap, useBundles, useCart, useCartDrawer, useCategories, useChat, useCheckout, useCimplify, useCimplifyClient, useCollection, useCollections, useDeals, useDeliveryFee, useElements, useElementsReady, useFxRate, useLocations, useOptionalCimplify, useOrder, useOrders, useProduct, useProductAvailability, useProductDeals, useProductPrice, useProductSchedules, useProducts, useProductsOnSale, usePropertyFacets, useQuote, useRecommendations, useSearch, useServiceAvailability, useServices, useSubscription, useSubscriptions, useTaxonomies, useTaxonomy, useTaxonomyPath, useValidateDiscount, useVariantSelector };
package/dist/server.d.mts CHANGED
@@ -68,7 +68,18 @@ declare const tags: {
68
68
  readonly collection: (id: string) => string;
69
69
  readonly collectionProducts: (id: string) => string;
70
70
  readonly business: () => string;
71
+ readonly brand: () => string;
71
72
  readonly locations: () => string;
73
+ readonly location: (id: string) => string;
74
+ readonly locale: () => string;
75
+ readonly pricing: () => string;
76
+ readonly tag: (name: string) => string;
77
+ readonly addons: () => string;
78
+ readonly addon: (id: string) => string;
79
+ readonly subscriptions: () => string;
80
+ readonly subscription: (id: string) => string;
81
+ readonly stock: () => string;
82
+ readonly stockFor: (productId: string) => string;
72
83
  readonly orders: (customerId: string) => string;
73
84
  readonly order: (id: string) => string;
74
85
  };
@@ -89,10 +100,26 @@ declare function revalidateCategory(id: string): Promise<void>;
89
100
  declare function revalidateCollections(): Promise<void>;
90
101
  declare function revalidateCollection(id: string): Promise<void>;
91
102
  declare function revalidateBusiness(): Promise<void>;
103
+ declare function revalidateBrand(): Promise<void>;
104
+ declare function revalidateLocations(): Promise<void>;
105
+ declare function revalidateLocation(id: string): Promise<void>;
106
+ declare function revalidatePricing(): Promise<void>;
107
+ declare function revalidateAddOns(): Promise<void>;
108
+ declare function revalidateAddOn(id: string): Promise<void>;
109
+ declare function revalidateSubscriptions(): Promise<void>;
110
+ declare function revalidateSubscription(id: string): Promise<void>;
111
+ declare function revalidateStock(productId?: string): Promise<void>;
92
112
  /**
93
113
  * Escape hatch: invalidate by raw tag string. Prefer the typed helpers
94
114
  * above where possible — they keep the tag scheme in one place.
95
115
  */
96
116
  declare function revalidateByTag(tag: string): Promise<void>;
97
117
 
98
- export { CimplifyClient, type ServerClientOptions, getServerClient, revalidateBusiness, revalidateByTag, revalidateCategories, revalidateCategory, revalidateCollection, revalidateCollections, revalidateProduct, revalidateProducts, tags };
118
+ interface RevalidateRouteOptions {
119
+ secret?: string;
120
+ revalidateTag?: (tag: string) => void;
121
+ now?: () => number;
122
+ }
123
+ declare function revalidateRouteHandler(req: Request, options?: RevalidateRouteOptions): Promise<Response>;
124
+
125
+ export { CimplifyClient, type RevalidateRouteOptions, type ServerClientOptions, getServerClient, revalidateAddOn, revalidateAddOns, revalidateBrand, revalidateBusiness, revalidateByTag, revalidateCategories, revalidateCategory, revalidateCollection, revalidateCollections, revalidateLocation, revalidateLocations, revalidatePricing, revalidateProduct, revalidateProducts, revalidateRouteHandler, revalidateStock, revalidateSubscription, revalidateSubscriptions, tags };
package/dist/server.d.ts CHANGED
@@ -68,7 +68,18 @@ declare const tags: {
68
68
  readonly collection: (id: string) => string;
69
69
  readonly collectionProducts: (id: string) => string;
70
70
  readonly business: () => string;
71
+ readonly brand: () => string;
71
72
  readonly locations: () => string;
73
+ readonly location: (id: string) => string;
74
+ readonly locale: () => string;
75
+ readonly pricing: () => string;
76
+ readonly tag: (name: string) => string;
77
+ readonly addons: () => string;
78
+ readonly addon: (id: string) => string;
79
+ readonly subscriptions: () => string;
80
+ readonly subscription: (id: string) => string;
81
+ readonly stock: () => string;
82
+ readonly stockFor: (productId: string) => string;
72
83
  readonly orders: (customerId: string) => string;
73
84
  readonly order: (id: string) => string;
74
85
  };
@@ -89,10 +100,26 @@ declare function revalidateCategory(id: string): Promise<void>;
89
100
  declare function revalidateCollections(): Promise<void>;
90
101
  declare function revalidateCollection(id: string): Promise<void>;
91
102
  declare function revalidateBusiness(): Promise<void>;
103
+ declare function revalidateBrand(): Promise<void>;
104
+ declare function revalidateLocations(): Promise<void>;
105
+ declare function revalidateLocation(id: string): Promise<void>;
106
+ declare function revalidatePricing(): Promise<void>;
107
+ declare function revalidateAddOns(): Promise<void>;
108
+ declare function revalidateAddOn(id: string): Promise<void>;
109
+ declare function revalidateSubscriptions(): Promise<void>;
110
+ declare function revalidateSubscription(id: string): Promise<void>;
111
+ declare function revalidateStock(productId?: string): Promise<void>;
92
112
  /**
93
113
  * Escape hatch: invalidate by raw tag string. Prefer the typed helpers
94
114
  * above where possible — they keep the tag scheme in one place.
95
115
  */
96
116
  declare function revalidateByTag(tag: string): Promise<void>;
97
117
 
98
- export { CimplifyClient, type ServerClientOptions, getServerClient, revalidateBusiness, revalidateByTag, revalidateCategories, revalidateCategory, revalidateCollection, revalidateCollections, revalidateProduct, revalidateProducts, tags };
118
+ interface RevalidateRouteOptions {
119
+ secret?: string;
120
+ revalidateTag?: (tag: string) => void;
121
+ now?: () => number;
122
+ }
123
+ declare function revalidateRouteHandler(req: Request, options?: RevalidateRouteOptions): Promise<Response>;
124
+
125
+ export { CimplifyClient, type RevalidateRouteOptions, type ServerClientOptions, getServerClient, revalidateAddOn, revalidateAddOns, revalidateBrand, revalidateBusiness, revalidateByTag, revalidateCategories, revalidateCategory, revalidateCollection, revalidateCollections, revalidateLocation, revalidateLocations, revalidatePricing, revalidateProduct, revalidateProducts, revalidateRouteHandler, revalidateStock, revalidateSubscription, revalidateSubscriptions, tags };
package/dist/server.js CHANGED
@@ -41,7 +41,19 @@ var tags = {
41
41
  collection: (id) => `cimplify:collection:${id}`,
42
42
  collectionProducts: (id) => `cimplify:collection:${id}:products`,
43
43
  business: () => "cimplify:business",
44
+ brand: () => "cimplify:brand",
44
45
  locations: () => "cimplify:locations",
46
+ location: (id) => `cimplify:location:${id}`,
47
+ locale: () => "cimplify:locale",
48
+ pricing: () => "cimplify:pricing",
49
+ // Product-level tag (e.g. "vegan", "bestseller"), not "cache tag".
50
+ tag: (name) => `cimplify:tag:${name}`,
51
+ addons: () => "cimplify:addons",
52
+ addon: (id) => `cimplify:addon:${id}`,
53
+ subscriptions: () => "cimplify:subscriptions",
54
+ subscription: (id) => `cimplify:subscription:${id}`,
55
+ stock: () => "cimplify:stock",
56
+ stockFor: (productId) => `cimplify:stock:${productId}`,
45
57
  orders: (customerId) => `cimplify:orders:${customerId}`,
46
58
  order: (id) => `cimplify:order:${id}`
47
59
  };
@@ -88,21 +100,134 @@ async function revalidateCollection(id) {
88
100
  async function revalidateBusiness() {
89
101
  return revalidate(tags.business());
90
102
  }
103
+ async function revalidateBrand() {
104
+ return revalidate(tags.brand());
105
+ }
106
+ async function revalidateLocations() {
107
+ return revalidate(tags.locations());
108
+ }
109
+ async function revalidateLocation(id) {
110
+ return revalidate(tags.location(id), tags.locations());
111
+ }
112
+ async function revalidatePricing() {
113
+ return revalidate(tags.pricing(), tags.products());
114
+ }
115
+ async function revalidateAddOns() {
116
+ return revalidate(tags.addons());
117
+ }
118
+ async function revalidateAddOn(id) {
119
+ return revalidate(tags.addon(id), tags.addons());
120
+ }
121
+ async function revalidateSubscriptions() {
122
+ return revalidate(tags.subscriptions());
123
+ }
124
+ async function revalidateSubscription(id) {
125
+ return revalidate(tags.subscription(id), tags.subscriptions());
126
+ }
127
+ async function revalidateStock(productId) {
128
+ return productId ? revalidate(tags.stockFor(productId), tags.stock()) : revalidate(tags.stock());
129
+ }
91
130
  async function revalidateByTag(tag) {
92
131
  return revalidate(tag);
93
132
  }
94
133
 
134
+ // src/server/revalidate-route.ts
135
+ var TIMESTAMP_HEADER = "x-cimplify-timestamp";
136
+ var SIGNATURE_HEADER = "x-cimplify-signature";
137
+ var SIGNATURE_PREFIX = "sha256=";
138
+ var MAX_SKEW_MS = 5 * 60 * 1e3;
139
+ var SECRET_ENV = "CIMPLIFY_REVALIDATE_SECRET";
140
+ async function revalidateRouteHandler(req, options = {}) {
141
+ const secret = options.secret ?? envSecret();
142
+ if (!secret) return text(`revalidate disabled: ${SECRET_ENV} not set`, 500);
143
+ const timestamp = req.headers.get(TIMESTAMP_HEADER);
144
+ const signature = req.headers.get(SIGNATURE_HEADER);
145
+ if (!timestamp || !signature) return text("missing auth headers", 401);
146
+ const ts = Number.parseInt(timestamp, 10);
147
+ const now = options.now ?? Date.now;
148
+ if (!Number.isFinite(ts) || Math.abs(now() - ts) > MAX_SKEW_MS) {
149
+ return text("stale or invalid timestamp", 401);
150
+ }
151
+ const body = await req.text();
152
+ if (!await verifyHmac(secret, `${timestamp}.${body}`, signature)) {
153
+ return text("invalid signature", 401);
154
+ }
155
+ let parsed;
156
+ try {
157
+ parsed = JSON.parse(body);
158
+ } catch {
159
+ return text("invalid json", 400);
160
+ }
161
+ const tags2 = Array.isArray(parsed.tags) ? parsed.tags.filter((t) => typeof t === "string" && t.length > 0) : [];
162
+ if (tags2.length === 0) return text("no tags", 400);
163
+ const revalidate2 = options.revalidateTag ?? await loadRevalidateTag();
164
+ for (const tag of tags2) revalidate2(tag);
165
+ return Response.json({ ok: true, revalidated: tags2.length });
166
+ }
167
+ var cachedRevalidateTag = null;
168
+ async function loadRevalidateTag() {
169
+ if (cachedRevalidateTag) return cachedRevalidateTag;
170
+ const specifier = "next/cache";
171
+ const mod = await import(
172
+ /* webpackIgnore: true */
173
+ /* @vite-ignore */
174
+ specifier
175
+ );
176
+ cachedRevalidateTag = mod.revalidateTag;
177
+ return cachedRevalidateTag;
178
+ }
179
+ async function verifyHmac(secret, payload, signatureHeader) {
180
+ if (!signatureHeader.startsWith(SIGNATURE_PREFIX)) return false;
181
+ const providedBytes = hexToBytes(signatureHeader.slice(SIGNATURE_PREFIX.length));
182
+ if (!providedBytes) return false;
183
+ const enc = new TextEncoder();
184
+ const key = await crypto.subtle.importKey(
185
+ "raw",
186
+ enc.encode(secret),
187
+ { name: "HMAC", hash: "SHA-256" },
188
+ false,
189
+ ["verify"]
190
+ );
191
+ return crypto.subtle.verify("HMAC", key, providedBytes, enc.encode(payload));
192
+ }
193
+ function hexToBytes(hex) {
194
+ if (hex.length % 2 !== 0 || !/^[0-9a-f]+$/i.test(hex)) return null;
195
+ const buf = new ArrayBuffer(hex.length / 2);
196
+ const out = new Uint8Array(buf);
197
+ for (let i = 0; i < hex.length; i += 2) {
198
+ out[i / 2] = Number.parseInt(hex.slice(i, i + 2), 16);
199
+ }
200
+ return out;
201
+ }
202
+ function envSecret() {
203
+ const proc = globalThis.process;
204
+ return proc?.env?.[SECRET_ENV];
205
+ }
206
+ function text(message, status) {
207
+ return new Response(message, { status, headers: { "content-type": "text/plain" } });
208
+ }
209
+
95
210
  Object.defineProperty(exports, "CimplifyError", {
96
211
  enumerable: true,
97
212
  get: function () { return chunkTKOTACKZ_js.CimplifyError; }
98
213
  });
99
214
  exports.getServerClient = getServerClient;
215
+ exports.revalidateAddOn = revalidateAddOn;
216
+ exports.revalidateAddOns = revalidateAddOns;
217
+ exports.revalidateBrand = revalidateBrand;
100
218
  exports.revalidateBusiness = revalidateBusiness;
101
219
  exports.revalidateByTag = revalidateByTag;
102
220
  exports.revalidateCategories = revalidateCategories;
103
221
  exports.revalidateCategory = revalidateCategory;
104
222
  exports.revalidateCollection = revalidateCollection;
105
223
  exports.revalidateCollections = revalidateCollections;
224
+ exports.revalidateLocation = revalidateLocation;
225
+ exports.revalidateLocations = revalidateLocations;
226
+ exports.revalidatePricing = revalidatePricing;
106
227
  exports.revalidateProduct = revalidateProduct;
107
228
  exports.revalidateProducts = revalidateProducts;
229
+ exports.revalidateRouteHandler = revalidateRouteHandler;
230
+ exports.revalidateStock = revalidateStock;
231
+ exports.revalidateSubscription = revalidateSubscription;
232
+ exports.revalidateSubscriptions = revalidateSubscriptions;
108
233
  exports.tags = tags;