brainerce 1.48.0 → 1.48.1

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/README.md CHANGED
@@ -1696,6 +1696,9 @@ fields.forEach((field) => {
1696
1696
  // field.required: whether customer must fill this in
1697
1697
  // field.minLength, field.maxLength: validation for text fields
1698
1698
  // field.minValue, field.maxValue: validation for number fields
1699
+ // field.dateAvailability: constraints for DATE/DATETIME fields (blocked
1700
+ // weekdays/dates, min/max date, business hours + slots) — see
1701
+ // computeAvailableSlots()/isDateValueAllowed() below
1699
1702
  // field.enumValues: CustomizationFieldOption[] for SELECT/MULTI_SELECT
1700
1703
  // each option: { label: string, value: string, swatchColor?: string, swatchImageUrl?: string }
1701
1704
  // use option.value for metadata submission, option.label for display
@@ -2380,7 +2383,7 @@ const fields = await client.getCheckoutCustomFields(checkoutId);
2380
2383
 
2381
2384
  // 2. Render fields dynamically based on field.type:
2382
2385
  // TEXT → text input, NUMBER → number input, BOOLEAN → checkbox,
2383
- // SELECT → dropdown (field.options), DATE → date picker
2386
+ // SELECT → dropdown (field.options), DATE/DATETIME → date/time picker
2384
2387
  // Show pricing info from field.pricing (e.g., "+25₪ when checked")
2385
2388
 
2386
2389
  // 3. Set customer values → recalculates surcharges and total
@@ -2395,6 +2398,35 @@ const updatedCheckout = await client.setCheckoutCustomFields(checkoutId, {
2395
2398
  // updatedCheckout.total is recalculated with surcharges included
2396
2399
  ```
2397
2400
 
2401
+ **DATE / DATETIME fields with availability constraints**
2402
+
2403
+ A `DATE`/`DATETIME` field's `dateAvailability` (blocked weekdays, blocked specific
2404
+ dates, min/max date range, and — for `DATETIME` — business hours + time
2405
+ slots) is a merchant-configured restriction on which values the customer may
2406
+ pick. Use `computeAvailableSlots()` / `isDateValueAllowed()` to drive your own
2407
+ date-picker/slot-picker UI — the SDK ships no calendar component, only the
2408
+ math (evaluated in the **store's** timezone, never the browser's):
2409
+
2410
+ ```typescript
2411
+ import { computeAvailableSlots, isDateValueAllowed } from 'brainerce';
2412
+
2413
+ const { timezone } = await client.getStoreInfo(); // IANA string, e.g. "Asia/Jerusalem"
2414
+ const deliveryField = fields.find((f) => f.key === 'delivery_slot');
2415
+
2416
+ // Disable dates on your calendar of choice:
2417
+ const isDateDisabled = (candidate: Date) => {
2418
+ const result = isDateValueAllowed(candidate, deliveryField?.dateAvailability, deliveryField!.type, timezone);
2419
+ return !result.allowed;
2420
+ };
2421
+
2422
+ // Once the customer picks a date, list its bookable time slots (DATETIME only):
2423
+ const slots = computeAvailableSlots(deliveryField?.dateAvailability, '2026-08-15'); // ["09:00", "09:30", ...]
2424
+ ```
2425
+
2426
+ The backend independently re-validates every submitted value against the same
2427
+ constraints at write time — this is a client-side UX aid, not the source of
2428
+ enforcement.
2429
+
2398
2430
  **Pricing types:**
2399
2431
 
2400
2432
  - `none` → no surcharge
package/dist/index.d.mts CHANGED
@@ -169,6 +169,15 @@ interface StoreInfo {
169
169
  name: string;
170
170
  currency: string;
171
171
  language: string;
172
+ /**
173
+ * IANA timezone (e.g. "Asia/Jerusalem") the store operates in. Use this —
174
+ * never the shopper's browser timezone — to evaluate any DATE/DATETIME
175
+ * custom field's `dateAvailability` constraints (blocked weekdays, business
176
+ * hours, time slots) client-side via `computeAvailableSlots()`. Optional
177
+ * for backward compatibility with existing `StoreInfo` construction; the
178
+ * backend always populates it.
179
+ */
180
+ timezone?: string;
172
181
  /**
173
182
  * SEO snippet for the storefront homepage. Used for `<meta name="description">`,
174
183
  * `og:description`, and `twitter:description`. 50-160 chars recommended.
@@ -4472,6 +4481,45 @@ interface CreateRegionDto {
4472
4481
  interface UpdateRegionDto extends Partial<CreateRegionDto> {
4473
4482
  isActive?: boolean;
4474
4483
  }
4484
+ /**
4485
+ * A single per-weekday open/close window, store-local time. Only meaningful
4486
+ * on DATETIME fields — ignored for plain DATE fields.
4487
+ */
4488
+ interface BusinessHoursWindow {
4489
+ /** 0 = Sunday .. 6 = Saturday. */
4490
+ weekday: number;
4491
+ /** "HH:mm", 24h, store-local. */
4492
+ open: string;
4493
+ /** "HH:mm", 24h, store-local. */
4494
+ close: string;
4495
+ }
4496
+ /**
4497
+ * Date/time availability constraints for a DATE/DATETIME custom field
4498
+ * definition (checkout custom field or metafield). Null/absent = no
4499
+ * restrictions. Pass this — together with a candidate date and the store's
4500
+ * `timezone` (from `getStoreInfo()`) — into `computeAvailableSlots()` to
4501
+ * render a disabled-dates list or time-slot picker; the backend independently
4502
+ * re-validates every submitted value against these same constraints, so this
4503
+ * is purely a client-side UX aid, not the source of enforcement.
4504
+ *
4505
+ * This type intentionally mirrors (but does not import)
4506
+ * `DateAvailabilityConstraints` from `@brainerce/types` — the SDK has no
4507
+ * runtime dependency on that package. Keep the two in sync by hand.
4508
+ */
4509
+ interface DateAvailabilityConstraints {
4510
+ /** "YYYY-MM-DD", inclusive. */
4511
+ minDate?: string;
4512
+ /** "YYYY-MM-DD", inclusive. */
4513
+ maxDate?: string;
4514
+ /** Subset of 0-6; any weekday(s) fully blocked regardless of date. */
4515
+ blockedWeekdays?: number[];
4516
+ /** Specific blocked calendar dates, e.g. holidays: ["2026-12-25"]. */
4517
+ blockedDates?: string[];
4518
+ /** Per-weekday open/close windows. Omitted weekday = closed all day. Only meaningful on DATETIME fields. */
4519
+ businessHours?: BusinessHoursWindow[];
4520
+ /** Minutes per bookable slot within businessHours. Requires businessHours. Only meaningful on DATETIME fields. */
4521
+ slotDurationMinutes?: number;
4522
+ }
4475
4523
  /**
4476
4524
  * Metafield type for defining value structure
4477
4525
  */
@@ -4514,6 +4562,8 @@ interface MetafieldDefinition {
4514
4562
  maxLength?: number | null;
4515
4563
  minValue?: number | null;
4516
4564
  maxValue?: number | null;
4565
+ /** Date/time constraints for DATE/DATETIME fields — see `computeAvailableSlots()`. */
4566
+ dateAvailability?: DateAvailabilityConstraints | null;
4517
4567
  /** Allowed values for SELECT / MULTI_SELECT fields, with optional swatch metadata. */
4518
4568
  enumValues?: CustomizationFieldOption[] | null;
4519
4569
  defaultValue?: string | null;
@@ -4605,6 +4655,8 @@ interface PublicMetafieldDefinition {
4605
4655
  maxLength?: number | null;
4606
4656
  minValue?: number | null;
4607
4657
  maxValue?: number | null;
4658
+ /** Date/time constraints for DATE/DATETIME fields — see `computeAvailableSlots()`. */
4659
+ dateAvailability?: DateAvailabilityConstraints | null;
4608
4660
  defaultValue?: string | null;
4609
4661
  position: number;
4610
4662
  }
@@ -5398,7 +5450,7 @@ interface CheckoutCustomFieldDefinition {
5398
5450
  * `MULTI_SELECT` are NOT supported for checkout fields — those are
5399
5451
  * product-metafield-only (`ProductCustomizationField` / `MetafieldType`).
5400
5452
  */
5401
- type: 'TEXT' | 'TEXTAREA' | 'NUMBER' | 'BOOLEAN' | 'SELECT' | 'DATE' | 'IMAGE';
5453
+ type: 'TEXT' | 'TEXTAREA' | 'NUMBER' | 'BOOLEAN' | 'SELECT' | 'DATE' | 'DATETIME' | 'IMAGE';
5402
5454
  required: boolean;
5403
5455
  position: number;
5404
5456
  visibility: CheckoutFieldVisibility;
@@ -5411,6 +5463,8 @@ interface CheckoutCustomFieldDefinition {
5411
5463
  maxLength?: number | null;
5412
5464
  minValue?: number | null;
5413
5465
  maxValue?: number | null;
5466
+ /** Date/time constraints for DATE/DATETIME fields — see `computeAvailableSlots()`. */
5467
+ dateAvailability?: DateAvailabilityConstraints | null;
5414
5468
  translations?: Record<string, Record<string, string>> | null;
5415
5469
  }
5416
5470
  interface CheckoutFieldVisibility {
@@ -5943,6 +5997,7 @@ interface BlogPost {
5943
5997
  seoTitle?: string;
5944
5998
  seoDescription?: string;
5945
5999
  ogImageUrl?: string;
6000
+ translations?: Record<string, Record<string, string>> | null;
5946
6001
  createdAt: string;
5947
6002
  updatedAt: string;
5948
6003
  }
@@ -10736,6 +10791,59 @@ declare function formatVariantPrice(variant: Pick<ProductVariant, 'price' | 'sal
10736
10791
  /** Format any numeric amount as currency. Useful for cart totals, fees, etc. */
10737
10792
  declare function formatMoney(amount: number, currency: string, locale?: string): string;
10738
10793
 
10794
+ /**
10795
+ * Config well-formedness — mirrors the backend's own check. Returns
10796
+ * human-readable error strings; empty array = valid. Storefronts don't
10797
+ * generally need this (only admins author the config), but it's exposed for
10798
+ * any storefront building its own admin-like UI on top of the SDK.
10799
+ */
10800
+ declare function validateDateAvailabilityConfig(config: DateAvailabilityConstraints | null | undefined, fieldType: 'DATE' | 'DATETIME'): string[];
10801
+ interface StoreLocalParts {
10802
+ /** "YYYY-MM-DD" in the given timezone. */
10803
+ dateYYYYMMDD: string;
10804
+ /** "HH:mm" in the given timezone. */
10805
+ hhmm: string;
10806
+ /** 0 = Sunday .. 6 = Saturday. */
10807
+ weekday: number;
10808
+ }
10809
+ /**
10810
+ * Resolves an absolute instant to the store-local calendar date, "HH:mm",
10811
+ * and weekday. Use `getStoreInfo().timezone` as the `timezone` argument —
10812
+ * never the shopper's browser timezone, or "is Friday blocked" will
10813
+ * disagree with the backend's own answer for shoppers in a different zone.
10814
+ * Falls back to UTC parts on an invalid IANA timezone string — never throws.
10815
+ */
10816
+ declare function resolveStoreLocalParts(instant: Date, timezone: string): StoreLocalParts;
10817
+ /** Day-level gate: minDate/maxDate/blockedWeekdays/blockedDates only (no time-of-day). */
10818
+ declare function isCalendarDateAllowed(dateYYYYMMDD: string, config: DateAvailabilityConstraints | null | undefined): boolean;
10819
+ /**
10820
+ * Discrete slot starts ("HH:mm", store-local) for one calendar date. Empty
10821
+ * array if: the date fails `isCalendarDateAllowed`, no `businessHours` window
10822
+ * covers that weekday, or `slotDurationMinutes` is unset. A trailing slot
10823
+ * whose end would exceed `close` is dropped, not clamped. No
10824
+ * capacity/overbooking accounting — purely "which slots exist".
10825
+ *
10826
+ * Feed this into your own date-picker/slot-picker UI, e.g.:
10827
+ * ```ts
10828
+ * const { timezone } = await client.getStoreInfo();
10829
+ * const fields = await client.getCheckoutCustomFields(checkoutId);
10830
+ * const deliveryField = fields.find((f) => f.key === 'delivery_slot');
10831
+ * const local = resolveStoreLocalParts(candidateDate, timezone);
10832
+ * const slots = computeAvailableSlots(deliveryField?.dateAvailability, local.dateYYYYMMDD);
10833
+ * ```
10834
+ */
10835
+ declare function computeAvailableSlots(config: DateAvailabilityConstraints | null | undefined, dateYYYYMMDD: string): string[];
10836
+ /**
10837
+ * Full value validation for a candidate date/datetime a shopper is about to
10838
+ * submit — use this to disable a "Continue" button client-side before the
10839
+ * backend's own (authoritative) rejection would otherwise surface as an
10840
+ * error after a round trip.
10841
+ */
10842
+ declare function isDateValueAllowed(instant: Date, config: DateAvailabilityConstraints | null | undefined, fieldType: 'DATE' | 'DATETIME', timezone: string): {
10843
+ allowed: boolean;
10844
+ reason?: string;
10845
+ };
10846
+
10739
10847
  /**
10740
10848
  * JSON-LD (schema.org) builders for storefronts.
10741
10849
  *
@@ -10881,4 +10989,4 @@ interface CategorySitemapOptions {
10881
10989
  */
10882
10990
  declare function getCategorySitemapEntries(client: BrainerceClient, opts: CategorySitemapOptions): Promise<SitemapEntry[]>;
10883
10991
 
10884
- export { type AddToCartDto, type AddressDetailsResult, type AddressSuggestion, type AnnouncementContent, type AnnouncementSeverity, type AppliedDiscount, type ApplyCouponDto, type AttachModifierGroupInput, type Attribute, type AttributeOption, type AttributeSource, type BlogSitemapOptions, type BrainerceApiError, BrainerceClient, type BrainerceClientOptions, BrainerceError, type Brand, type BulkInventoryResponse, type BulkSaveVariantsDto, type BulkSaveVariantsResponse, type BulkVariantInput, type Cart, type CartAppliedDiscount, type CartBundleOffer, type CartBundlesResponse, type CartIncludeOption, type CartIncludeOptions, type CartItem, type CartItemModifierLine, type CartNudge, type CartRecommendationsResponse, type CartStatus, type CartUpgradeSuggestion, type CartUpgradesResponse, type CartWithIncludes, type Category, type CategoryDetail, type CategoryNode, type CategorySitemapOptions, type CategorySuggestion, type Checkout, type CheckoutAddress, type CheckoutBumpsResponse, type CheckoutCustomFieldDefinition, type CheckoutFieldPricing, type CheckoutFieldVisibility, type CheckoutLineItem, type CheckoutPrefillData, type CheckoutStatus, type CompleteCheckoutResponse, type CompleteDraftDto, type ConfigureOAuthProviderDto as ConfigureOAuthProviderInput, type ConflictStatus, type ConnectorPlatform, type ContactFormFieldType, type ContactFormFieldValidation, type ContactFormPublic, type ContactFormPublicField, type ContactFormSummary, type Content, type ContentDataMap, type ContentStatus, type ContentSummary, type ContentType, type Coupon, type CouponCreateResponse, type CouponQueryParams, type CouponStatus, type CouponType, type CouponValidationWarning, type CreateAddressDto, type CreateAttributeDto as CreateAttributeInput, type CreateAttributeOptionDto as CreateAttributeOptionInput, type CreateBrandDto as CreateBrandInput, type CreateCategoryDto as CreateCategoryInput, type CreateCheckoutDto, type CreateContentInput, type CreateCouponDto, type CreateCustomApiDto, type CreateCustomerDto, type CreateEmailTemplateDto as CreateEmailTemplateInput, type CreateGuestOrderDto, type CreateInquiryInput, type CreateInquiryResponse, type CreateMetafieldDefinitionDto as CreateMetafieldDefinitionInput, type CreateModifierGroupInput, type CreateModifierInput, type CreateOrderDto, type CreateProductDto, type CreateRefundDto, type CreateShippingRateDto as CreateShippingRateInput, type CreateShippingZoneDto as CreateShippingZoneInput, type CreateTagDto as CreateTagInput, type CreateTaxRateDto as CreateTaxRateInput, type CreateVariantDto, type CustomApiAuthType, type CustomApiConnectionStatus, type CustomApiCredentials, type CustomApiIntegration, type CustomApiSyncConfig, type CustomApiSyncDirection, type CustomApiTestResult, type Customer, type CustomerAddress, type CustomerAuthResponse, type CustomerOAuthProvider, type CustomerProfile, type CustomerQueryParams, type DeleteProductResponse, type DiscountBanner, type DiscountRuleType, type DownloadFile, type DraftLineItem, type EditInventoryDto, type EmailDomain, type EmailEventSettings, type EmailEventType, type EmailSettings, type EmailTemplate, type EmailTemplatePreview, type EmailTemplatesResponse, type EmailVerificationResponse, type ExtendReservationResponse, type FaqContent, type FaqItem, type FooterColumn, type FooterContent, type FooterLink, type FooterSocialLink, type FormatPriceOptions, type FormatProductPriceOptions, type FreeAllocationPolicy, type FulfillOrderDto, type GuestCheckoutStartResponse, type GuestOrderResponse, type HeaderContent, type HeaderCta, type HeaderLogo, type HeaderNavItem, type InsufficientStockError, type InventoryInfo, type InventoryReservationStrategy, type InventorySyncStatus, type InventoryTrackingMode, type InvitationStatus, type InviteMemberDto as InviteMemberInput, type InviteStoreMemberDto as InviteStoreMemberInput, type JsonLdOptions, type ListModifierGroupsParams, type LocalCart, type LocalCartItem, type LockedVariant, type LoyaltyNextTierSummary, type LoyaltyReward, type LoyaltyStatus, type LoyaltyTierSummary, type MergeCartsDto, type MetafieldConflict, type MetafieldConflictResolution, type MetafieldDefinition, type MetafieldType, type Modifier, type ModifierGroup, type ModifierSelection, type ModifierSelectionType, type ModifierValidationCode, type ModifierValidationError, type MyProductReview, type OAuthAuthorizeResponse, type OAuthCallbackResponse, type OAuthConnection, type OAuthConnectionsResponse, type OAuthProviderConfig, type OAuthProviderType, type OAuthProvidersResponse, type Order, type OrderAddress, type OrderBump, type OrderCustomer, type OrderDownloadLink, type OrderItem, type OrderQueryParams, type OrderStatus, type OrderStatusChange, type PageContent, type PageSeo, type PaginatedResponse, type PaymentClientSdk, type PaymentConfig, type PaymentIntent, type PaymentProvider, type PaymentProviderConfig, type PaymentProvidersConfig, type PaymentStatus, type PaymentUrlOptions, type PickupLocation, type PlatformCouponCapabilities, type PlatformMetafieldMetadata, type PreviewEmailTemplateDto as PreviewEmailTemplateInput, type Product, type ProductAttributeInput, type ProductAvailability, type ProductCustomizationField, type ProductDiscount, type ProductDiscountBadge, type ProductImage, type ProductMetafield, type ProductMetafieldValue, type ProductModifierGroupAttachment, type ProductQueryParams, type ProductRecommendation, type ProductRecommendationsResponse, type ProductRelationType, type ProductReview, type ProductReviewAdmin, type ProductSuggestion, type ProductVariant, type PublicMetafieldDefinition, type PublishProductResponse, RTL_LOCALES, type RecommendationVariant, type ReconcileInventoryResponse, type RedeemRewardResult, type ReferralInfo, type Refund, type RefundLineItem, type RefundLineItemResponse, type RefundType, type RegisterCustomerDto, type ReservationInfo, type ResolveMetafieldConflictDto as ResolveMetafieldConflictInput, type ResolveSyncConflictDto as ResolveSyncConflictInput, type RichTextContent, SDK_VERSION, type SearchSuggestions, type SelectPickupLocationDto, type SelectShippingMethodDto, type SendInvoiceDto, type SessionCartRef, type SetBillingAddressDto, type SetCheckoutCustomFieldsDto, type SetCheckoutCustomerDto, type SetDefinitionProductsDto as SetDefinitionProductsInput, type SetMetafieldPlatformsDto as SetMetafieldPlatformsInput, type SetShippingAddressDto, type SetShippingAddressResponse, type ShippingDestinations, type ShippingLine, type ShippingRate, type ShippingRateConfig, type ShippingRateType, type ShippingSummaryEntry, type ShippingZone, type ShippingZoneQueryParams, type SitemapEntry, type StockAvailabilityRequest, type StockAvailabilityResponse, type StockAvailabilityResult, type StoreInfo, type StoreInvitation, type StoreInvitationDetails, type StoreMember, type StorePermission, type StoreRole, type StoreTeamResponse, type SubmitProductReviewInput, type SupportedLocaleObject, type SyncConflict, type SyncConflictResolution, type SyncJob, type Tag, type TaxBreakdown, type TaxBreakdownItem, type TaxRate, type TaxonomyQueryParams, type TeamInvitation, type TeamInvitationsResponse, type TeamMember, type TeamMembersResponse, type TeamRole, type UpdateAddressDto, type UpdateAttachmentInput, type UpdateAttributeDto as UpdateAttributeInput, type UpdateAttributeOptionDto as UpdateAttributeOptionInput, type UpdateBrandDto as UpdateBrandInput, type UpdateCartItemDto, type UpdateCategoryDto as UpdateCategoryInput, type UpdateContentInput, type UpdateCouponDto, type UpdateCustomApiDto, type UpdateCustomerDto, type UpdateDraftDto, type UpdateEmailSettingsDto as UpdateEmailSettingsInput, type UpdateEmailTemplateDto as UpdateEmailTemplateInput, type UpdateInventoryDto, type UpdateMemberRoleDto as UpdateMemberRoleInput, type UpdateMetafieldDefinitionDto as UpdateMetafieldDefinitionInput, type UpdateModifierGroupInput, type UpdateModifierInput, type UpdateOAuthProviderDto as UpdateOAuthProviderInput, type UpdateOrderDto, type UpdateOrderShippingDto, type UpdateProductDto, type UpdateShippingRateDto as UpdateShippingRateInput, type UpdateShippingZoneDto as UpdateShippingZoneInput, type UpdateStoreMemberDto as UpdateStoreMemberInput, type UpdateTagDto as UpdateTagInput, type UpdateTaxRateDto as UpdateTaxRateInput, type UpdateVariantDto, type UpdateVariantInventoryDto, type UpsertProductMetafieldDto as UpsertProductMetafieldInput, type UserStore, type UserStorePermissions, type VariantInventoryResponse, type VariantPlatformOverlay, type VariantStatus, type WaitForOrderOptions, type WaitForOrderResult, type WebhookEvent, type WebhookEventType, type WriteProductReviewInput, buildArticleJsonLd, buildBreadcrumbJsonLd, buildCollectionPageJsonLd, buildOrganizationJsonLd, buildProductJsonLd, buildWebsiteJsonLd, createWebhookHandler, deriveSeoDescription, enableDevGuards, formatMoney, formatPrice, formatProductPrice, formatVariantPrice, getBlogSitemapEntries, getCartItemImage, getCartItemName, getCartTotals, getCategorySitemapEntries, getDescriptionContent, getDirectionForLocale, formatPrice as getPriceDisplay, getProductCustomizationFields, getProductMetafield, getProductMetafieldValue, getProductMetafieldsByType, getProductPrice, getProductPriceInfo, getProductSwatches, getStockStatus, getVariantOptions, getVariantPrice, isAllowedPaymentUrl, isCouponApplicableToProduct, isHtmlDescription, isWebhookEventType, jsonLdScriptProps, parseWebhookEvent, safePaymentRedirect, stripHtml, verifyWebhook };
10992
+ export { type AddToCartDto, type AddressDetailsResult, type AddressSuggestion, type AnnouncementContent, type AnnouncementSeverity, type AppliedDiscount, type ApplyCouponDto, type AttachModifierGroupInput, type Attribute, type AttributeOption, type AttributeSource, type BlogSitemapOptions, type BrainerceApiError, BrainerceClient, type BrainerceClientOptions, BrainerceError, type Brand, type BulkInventoryResponse, type BulkSaveVariantsDto, type BulkSaveVariantsResponse, type BulkVariantInput, type BusinessHoursWindow, type Cart, type CartAppliedDiscount, type CartBundleOffer, type CartBundlesResponse, type CartIncludeOption, type CartIncludeOptions, type CartItem, type CartItemModifierLine, type CartNudge, type CartRecommendationsResponse, type CartStatus, type CartUpgradeSuggestion, type CartUpgradesResponse, type CartWithIncludes, type Category, type CategoryDetail, type CategoryNode, type CategorySitemapOptions, type CategorySuggestion, type Checkout, type CheckoutAddress, type CheckoutBumpsResponse, type CheckoutCustomFieldDefinition, type CheckoutFieldPricing, type CheckoutFieldVisibility, type CheckoutLineItem, type CheckoutPrefillData, type CheckoutStatus, type CompleteCheckoutResponse, type CompleteDraftDto, type ConfigureOAuthProviderDto as ConfigureOAuthProviderInput, type ConflictStatus, type ConnectorPlatform, type ContactFormFieldType, type ContactFormFieldValidation, type ContactFormPublic, type ContactFormPublicField, type ContactFormSummary, type Content, type ContentDataMap, type ContentStatus, type ContentSummary, type ContentType, type Coupon, type CouponCreateResponse, type CouponQueryParams, type CouponStatus, type CouponType, type CouponValidationWarning, type CreateAddressDto, type CreateAttributeDto as CreateAttributeInput, type CreateAttributeOptionDto as CreateAttributeOptionInput, type CreateBrandDto as CreateBrandInput, type CreateCategoryDto as CreateCategoryInput, type CreateCheckoutDto, type CreateContentInput, type CreateCouponDto, type CreateCustomApiDto, type CreateCustomerDto, type CreateEmailTemplateDto as CreateEmailTemplateInput, type CreateGuestOrderDto, type CreateInquiryInput, type CreateInquiryResponse, type CreateMetafieldDefinitionDto as CreateMetafieldDefinitionInput, type CreateModifierGroupInput, type CreateModifierInput, type CreateOrderDto, type CreateProductDto, type CreateRefundDto, type CreateShippingRateDto as CreateShippingRateInput, type CreateShippingZoneDto as CreateShippingZoneInput, type CreateTagDto as CreateTagInput, type CreateTaxRateDto as CreateTaxRateInput, type CreateVariantDto, type CustomApiAuthType, type CustomApiConnectionStatus, type CustomApiCredentials, type CustomApiIntegration, type CustomApiSyncConfig, type CustomApiSyncDirection, type CustomApiTestResult, type Customer, type CustomerAddress, type CustomerAuthResponse, type CustomerOAuthProvider, type CustomerProfile, type CustomerQueryParams, type DateAvailabilityConstraints, type DeleteProductResponse, type DiscountBanner, type DiscountRuleType, type DownloadFile, type DraftLineItem, type EditInventoryDto, type EmailDomain, type EmailEventSettings, type EmailEventType, type EmailSettings, type EmailTemplate, type EmailTemplatePreview, type EmailTemplatesResponse, type EmailVerificationResponse, type ExtendReservationResponse, type FaqContent, type FaqItem, type FooterColumn, type FooterContent, type FooterLink, type FooterSocialLink, type FormatPriceOptions, type FormatProductPriceOptions, type FreeAllocationPolicy, type FulfillOrderDto, type GuestCheckoutStartResponse, type GuestOrderResponse, type HeaderContent, type HeaderCta, type HeaderLogo, type HeaderNavItem, type InsufficientStockError, type InventoryInfo, type InventoryReservationStrategy, type InventorySyncStatus, type InventoryTrackingMode, type InvitationStatus, type InviteMemberDto as InviteMemberInput, type InviteStoreMemberDto as InviteStoreMemberInput, type JsonLdOptions, type ListModifierGroupsParams, type LocalCart, type LocalCartItem, type LockedVariant, type LoyaltyNextTierSummary, type LoyaltyReward, type LoyaltyStatus, type LoyaltyTierSummary, type MergeCartsDto, type MetafieldConflict, type MetafieldConflictResolution, type MetafieldDefinition, type MetafieldType, type Modifier, type ModifierGroup, type ModifierSelection, type ModifierSelectionType, type ModifierValidationCode, type ModifierValidationError, type MyProductReview, type OAuthAuthorizeResponse, type OAuthCallbackResponse, type OAuthConnection, type OAuthConnectionsResponse, type OAuthProviderConfig, type OAuthProviderType, type OAuthProvidersResponse, type Order, type OrderAddress, type OrderBump, type OrderCustomer, type OrderDownloadLink, type OrderItem, type OrderQueryParams, type OrderStatus, type OrderStatusChange, type PageContent, type PageSeo, type PaginatedResponse, type PaymentClientSdk, type PaymentConfig, type PaymentIntent, type PaymentProvider, type PaymentProviderConfig, type PaymentProvidersConfig, type PaymentStatus, type PaymentUrlOptions, type PickupLocation, type PlatformCouponCapabilities, type PlatformMetafieldMetadata, type PreviewEmailTemplateDto as PreviewEmailTemplateInput, type Product, type ProductAttributeInput, type ProductAvailability, type ProductCustomizationField, type ProductDiscount, type ProductDiscountBadge, type ProductImage, type ProductMetafield, type ProductMetafieldValue, type ProductModifierGroupAttachment, type ProductQueryParams, type ProductRecommendation, type ProductRecommendationsResponse, type ProductRelationType, type ProductReview, type ProductReviewAdmin, type ProductSuggestion, type ProductVariant, type PublicMetafieldDefinition, type PublishProductResponse, RTL_LOCALES, type RecommendationVariant, type ReconcileInventoryResponse, type RedeemRewardResult, type ReferralInfo, type Refund, type RefundLineItem, type RefundLineItemResponse, type RefundType, type RegisterCustomerDto, type ReservationInfo, type ResolveMetafieldConflictDto as ResolveMetafieldConflictInput, type ResolveSyncConflictDto as ResolveSyncConflictInput, type RichTextContent, SDK_VERSION, type SearchSuggestions, type SelectPickupLocationDto, type SelectShippingMethodDto, type SendInvoiceDto, type SessionCartRef, type SetBillingAddressDto, type SetCheckoutCustomFieldsDto, type SetCheckoutCustomerDto, type SetDefinitionProductsDto as SetDefinitionProductsInput, type SetMetafieldPlatformsDto as SetMetafieldPlatformsInput, type SetShippingAddressDto, type SetShippingAddressResponse, type ShippingDestinations, type ShippingLine, type ShippingRate, type ShippingRateConfig, type ShippingRateType, type ShippingSummaryEntry, type ShippingZone, type ShippingZoneQueryParams, type SitemapEntry, type StockAvailabilityRequest, type StockAvailabilityResponse, type StockAvailabilityResult, type StoreInfo, type StoreInvitation, type StoreInvitationDetails, type StoreMember, type StorePermission, type StoreRole, type StoreTeamResponse, type SubmitProductReviewInput, type SupportedLocaleObject, type SyncConflict, type SyncConflictResolution, type SyncJob, type Tag, type TaxBreakdown, type TaxBreakdownItem, type TaxRate, type TaxonomyQueryParams, type TeamInvitation, type TeamInvitationsResponse, type TeamMember, type TeamMembersResponse, type TeamRole, type UpdateAddressDto, type UpdateAttachmentInput, type UpdateAttributeDto as UpdateAttributeInput, type UpdateAttributeOptionDto as UpdateAttributeOptionInput, type UpdateBrandDto as UpdateBrandInput, type UpdateCartItemDto, type UpdateCategoryDto as UpdateCategoryInput, type UpdateContentInput, type UpdateCouponDto, type UpdateCustomApiDto, type UpdateCustomerDto, type UpdateDraftDto, type UpdateEmailSettingsDto as UpdateEmailSettingsInput, type UpdateEmailTemplateDto as UpdateEmailTemplateInput, type UpdateInventoryDto, type UpdateMemberRoleDto as UpdateMemberRoleInput, type UpdateMetafieldDefinitionDto as UpdateMetafieldDefinitionInput, type UpdateModifierGroupInput, type UpdateModifierInput, type UpdateOAuthProviderDto as UpdateOAuthProviderInput, type UpdateOrderDto, type UpdateOrderShippingDto, type UpdateProductDto, type UpdateShippingRateDto as UpdateShippingRateInput, type UpdateShippingZoneDto as UpdateShippingZoneInput, type UpdateStoreMemberDto as UpdateStoreMemberInput, type UpdateTagDto as UpdateTagInput, type UpdateTaxRateDto as UpdateTaxRateInput, type UpdateVariantDto, type UpdateVariantInventoryDto, type UpsertProductMetafieldDto as UpsertProductMetafieldInput, type UserStore, type UserStorePermissions, type VariantInventoryResponse, type VariantPlatformOverlay, type VariantStatus, type WaitForOrderOptions, type WaitForOrderResult, type WebhookEvent, type WebhookEventType, type WriteProductReviewInput, buildArticleJsonLd, buildBreadcrumbJsonLd, buildCollectionPageJsonLd, buildOrganizationJsonLd, buildProductJsonLd, buildWebsiteJsonLd, computeAvailableSlots, createWebhookHandler, deriveSeoDescription, enableDevGuards, formatMoney, formatPrice, formatProductPrice, formatVariantPrice, getBlogSitemapEntries, getCartItemImage, getCartItemName, getCartTotals, getCategorySitemapEntries, getDescriptionContent, getDirectionForLocale, formatPrice as getPriceDisplay, getProductCustomizationFields, getProductMetafield, getProductMetafieldValue, getProductMetafieldsByType, getProductPrice, getProductPriceInfo, getProductSwatches, getStockStatus, getVariantOptions, getVariantPrice, isAllowedPaymentUrl, isCalendarDateAllowed, isCouponApplicableToProduct, isDateValueAllowed, isHtmlDescription, isWebhookEventType, jsonLdScriptProps, parseWebhookEvent, resolveStoreLocalParts, safePaymentRedirect, stripHtml, validateDateAvailabilityConfig, verifyWebhook };
package/dist/index.d.ts CHANGED
@@ -169,6 +169,15 @@ interface StoreInfo {
169
169
  name: string;
170
170
  currency: string;
171
171
  language: string;
172
+ /**
173
+ * IANA timezone (e.g. "Asia/Jerusalem") the store operates in. Use this —
174
+ * never the shopper's browser timezone — to evaluate any DATE/DATETIME
175
+ * custom field's `dateAvailability` constraints (blocked weekdays, business
176
+ * hours, time slots) client-side via `computeAvailableSlots()`. Optional
177
+ * for backward compatibility with existing `StoreInfo` construction; the
178
+ * backend always populates it.
179
+ */
180
+ timezone?: string;
172
181
  /**
173
182
  * SEO snippet for the storefront homepage. Used for `<meta name="description">`,
174
183
  * `og:description`, and `twitter:description`. 50-160 chars recommended.
@@ -4472,6 +4481,45 @@ interface CreateRegionDto {
4472
4481
  interface UpdateRegionDto extends Partial<CreateRegionDto> {
4473
4482
  isActive?: boolean;
4474
4483
  }
4484
+ /**
4485
+ * A single per-weekday open/close window, store-local time. Only meaningful
4486
+ * on DATETIME fields — ignored for plain DATE fields.
4487
+ */
4488
+ interface BusinessHoursWindow {
4489
+ /** 0 = Sunday .. 6 = Saturday. */
4490
+ weekday: number;
4491
+ /** "HH:mm", 24h, store-local. */
4492
+ open: string;
4493
+ /** "HH:mm", 24h, store-local. */
4494
+ close: string;
4495
+ }
4496
+ /**
4497
+ * Date/time availability constraints for a DATE/DATETIME custom field
4498
+ * definition (checkout custom field or metafield). Null/absent = no
4499
+ * restrictions. Pass this — together with a candidate date and the store's
4500
+ * `timezone` (from `getStoreInfo()`) — into `computeAvailableSlots()` to
4501
+ * render a disabled-dates list or time-slot picker; the backend independently
4502
+ * re-validates every submitted value against these same constraints, so this
4503
+ * is purely a client-side UX aid, not the source of enforcement.
4504
+ *
4505
+ * This type intentionally mirrors (but does not import)
4506
+ * `DateAvailabilityConstraints` from `@brainerce/types` — the SDK has no
4507
+ * runtime dependency on that package. Keep the two in sync by hand.
4508
+ */
4509
+ interface DateAvailabilityConstraints {
4510
+ /** "YYYY-MM-DD", inclusive. */
4511
+ minDate?: string;
4512
+ /** "YYYY-MM-DD", inclusive. */
4513
+ maxDate?: string;
4514
+ /** Subset of 0-6; any weekday(s) fully blocked regardless of date. */
4515
+ blockedWeekdays?: number[];
4516
+ /** Specific blocked calendar dates, e.g. holidays: ["2026-12-25"]. */
4517
+ blockedDates?: string[];
4518
+ /** Per-weekday open/close windows. Omitted weekday = closed all day. Only meaningful on DATETIME fields. */
4519
+ businessHours?: BusinessHoursWindow[];
4520
+ /** Minutes per bookable slot within businessHours. Requires businessHours. Only meaningful on DATETIME fields. */
4521
+ slotDurationMinutes?: number;
4522
+ }
4475
4523
  /**
4476
4524
  * Metafield type for defining value structure
4477
4525
  */
@@ -4514,6 +4562,8 @@ interface MetafieldDefinition {
4514
4562
  maxLength?: number | null;
4515
4563
  minValue?: number | null;
4516
4564
  maxValue?: number | null;
4565
+ /** Date/time constraints for DATE/DATETIME fields — see `computeAvailableSlots()`. */
4566
+ dateAvailability?: DateAvailabilityConstraints | null;
4517
4567
  /** Allowed values for SELECT / MULTI_SELECT fields, with optional swatch metadata. */
4518
4568
  enumValues?: CustomizationFieldOption[] | null;
4519
4569
  defaultValue?: string | null;
@@ -4605,6 +4655,8 @@ interface PublicMetafieldDefinition {
4605
4655
  maxLength?: number | null;
4606
4656
  minValue?: number | null;
4607
4657
  maxValue?: number | null;
4658
+ /** Date/time constraints for DATE/DATETIME fields — see `computeAvailableSlots()`. */
4659
+ dateAvailability?: DateAvailabilityConstraints | null;
4608
4660
  defaultValue?: string | null;
4609
4661
  position: number;
4610
4662
  }
@@ -5398,7 +5450,7 @@ interface CheckoutCustomFieldDefinition {
5398
5450
  * `MULTI_SELECT` are NOT supported for checkout fields — those are
5399
5451
  * product-metafield-only (`ProductCustomizationField` / `MetafieldType`).
5400
5452
  */
5401
- type: 'TEXT' | 'TEXTAREA' | 'NUMBER' | 'BOOLEAN' | 'SELECT' | 'DATE' | 'IMAGE';
5453
+ type: 'TEXT' | 'TEXTAREA' | 'NUMBER' | 'BOOLEAN' | 'SELECT' | 'DATE' | 'DATETIME' | 'IMAGE';
5402
5454
  required: boolean;
5403
5455
  position: number;
5404
5456
  visibility: CheckoutFieldVisibility;
@@ -5411,6 +5463,8 @@ interface CheckoutCustomFieldDefinition {
5411
5463
  maxLength?: number | null;
5412
5464
  minValue?: number | null;
5413
5465
  maxValue?: number | null;
5466
+ /** Date/time constraints for DATE/DATETIME fields — see `computeAvailableSlots()`. */
5467
+ dateAvailability?: DateAvailabilityConstraints | null;
5414
5468
  translations?: Record<string, Record<string, string>> | null;
5415
5469
  }
5416
5470
  interface CheckoutFieldVisibility {
@@ -5943,6 +5997,7 @@ interface BlogPost {
5943
5997
  seoTitle?: string;
5944
5998
  seoDescription?: string;
5945
5999
  ogImageUrl?: string;
6000
+ translations?: Record<string, Record<string, string>> | null;
5946
6001
  createdAt: string;
5947
6002
  updatedAt: string;
5948
6003
  }
@@ -10736,6 +10791,59 @@ declare function formatVariantPrice(variant: Pick<ProductVariant, 'price' | 'sal
10736
10791
  /** Format any numeric amount as currency. Useful for cart totals, fees, etc. */
10737
10792
  declare function formatMoney(amount: number, currency: string, locale?: string): string;
10738
10793
 
10794
+ /**
10795
+ * Config well-formedness — mirrors the backend's own check. Returns
10796
+ * human-readable error strings; empty array = valid. Storefronts don't
10797
+ * generally need this (only admins author the config), but it's exposed for
10798
+ * any storefront building its own admin-like UI on top of the SDK.
10799
+ */
10800
+ declare function validateDateAvailabilityConfig(config: DateAvailabilityConstraints | null | undefined, fieldType: 'DATE' | 'DATETIME'): string[];
10801
+ interface StoreLocalParts {
10802
+ /** "YYYY-MM-DD" in the given timezone. */
10803
+ dateYYYYMMDD: string;
10804
+ /** "HH:mm" in the given timezone. */
10805
+ hhmm: string;
10806
+ /** 0 = Sunday .. 6 = Saturday. */
10807
+ weekday: number;
10808
+ }
10809
+ /**
10810
+ * Resolves an absolute instant to the store-local calendar date, "HH:mm",
10811
+ * and weekday. Use `getStoreInfo().timezone` as the `timezone` argument —
10812
+ * never the shopper's browser timezone, or "is Friday blocked" will
10813
+ * disagree with the backend's own answer for shoppers in a different zone.
10814
+ * Falls back to UTC parts on an invalid IANA timezone string — never throws.
10815
+ */
10816
+ declare function resolveStoreLocalParts(instant: Date, timezone: string): StoreLocalParts;
10817
+ /** Day-level gate: minDate/maxDate/blockedWeekdays/blockedDates only (no time-of-day). */
10818
+ declare function isCalendarDateAllowed(dateYYYYMMDD: string, config: DateAvailabilityConstraints | null | undefined): boolean;
10819
+ /**
10820
+ * Discrete slot starts ("HH:mm", store-local) for one calendar date. Empty
10821
+ * array if: the date fails `isCalendarDateAllowed`, no `businessHours` window
10822
+ * covers that weekday, or `slotDurationMinutes` is unset. A trailing slot
10823
+ * whose end would exceed `close` is dropped, not clamped. No
10824
+ * capacity/overbooking accounting — purely "which slots exist".
10825
+ *
10826
+ * Feed this into your own date-picker/slot-picker UI, e.g.:
10827
+ * ```ts
10828
+ * const { timezone } = await client.getStoreInfo();
10829
+ * const fields = await client.getCheckoutCustomFields(checkoutId);
10830
+ * const deliveryField = fields.find((f) => f.key === 'delivery_slot');
10831
+ * const local = resolveStoreLocalParts(candidateDate, timezone);
10832
+ * const slots = computeAvailableSlots(deliveryField?.dateAvailability, local.dateYYYYMMDD);
10833
+ * ```
10834
+ */
10835
+ declare function computeAvailableSlots(config: DateAvailabilityConstraints | null | undefined, dateYYYYMMDD: string): string[];
10836
+ /**
10837
+ * Full value validation for a candidate date/datetime a shopper is about to
10838
+ * submit — use this to disable a "Continue" button client-side before the
10839
+ * backend's own (authoritative) rejection would otherwise surface as an
10840
+ * error after a round trip.
10841
+ */
10842
+ declare function isDateValueAllowed(instant: Date, config: DateAvailabilityConstraints | null | undefined, fieldType: 'DATE' | 'DATETIME', timezone: string): {
10843
+ allowed: boolean;
10844
+ reason?: string;
10845
+ };
10846
+
10739
10847
  /**
10740
10848
  * JSON-LD (schema.org) builders for storefronts.
10741
10849
  *
@@ -10881,4 +10989,4 @@ interface CategorySitemapOptions {
10881
10989
  */
10882
10990
  declare function getCategorySitemapEntries(client: BrainerceClient, opts: CategorySitemapOptions): Promise<SitemapEntry[]>;
10883
10991
 
10884
- export { type AddToCartDto, type AddressDetailsResult, type AddressSuggestion, type AnnouncementContent, type AnnouncementSeverity, type AppliedDiscount, type ApplyCouponDto, type AttachModifierGroupInput, type Attribute, type AttributeOption, type AttributeSource, type BlogSitemapOptions, type BrainerceApiError, BrainerceClient, type BrainerceClientOptions, BrainerceError, type Brand, type BulkInventoryResponse, type BulkSaveVariantsDto, type BulkSaveVariantsResponse, type BulkVariantInput, type Cart, type CartAppliedDiscount, type CartBundleOffer, type CartBundlesResponse, type CartIncludeOption, type CartIncludeOptions, type CartItem, type CartItemModifierLine, type CartNudge, type CartRecommendationsResponse, type CartStatus, type CartUpgradeSuggestion, type CartUpgradesResponse, type CartWithIncludes, type Category, type CategoryDetail, type CategoryNode, type CategorySitemapOptions, type CategorySuggestion, type Checkout, type CheckoutAddress, type CheckoutBumpsResponse, type CheckoutCustomFieldDefinition, type CheckoutFieldPricing, type CheckoutFieldVisibility, type CheckoutLineItem, type CheckoutPrefillData, type CheckoutStatus, type CompleteCheckoutResponse, type CompleteDraftDto, type ConfigureOAuthProviderDto as ConfigureOAuthProviderInput, type ConflictStatus, type ConnectorPlatform, type ContactFormFieldType, type ContactFormFieldValidation, type ContactFormPublic, type ContactFormPublicField, type ContactFormSummary, type Content, type ContentDataMap, type ContentStatus, type ContentSummary, type ContentType, type Coupon, type CouponCreateResponse, type CouponQueryParams, type CouponStatus, type CouponType, type CouponValidationWarning, type CreateAddressDto, type CreateAttributeDto as CreateAttributeInput, type CreateAttributeOptionDto as CreateAttributeOptionInput, type CreateBrandDto as CreateBrandInput, type CreateCategoryDto as CreateCategoryInput, type CreateCheckoutDto, type CreateContentInput, type CreateCouponDto, type CreateCustomApiDto, type CreateCustomerDto, type CreateEmailTemplateDto as CreateEmailTemplateInput, type CreateGuestOrderDto, type CreateInquiryInput, type CreateInquiryResponse, type CreateMetafieldDefinitionDto as CreateMetafieldDefinitionInput, type CreateModifierGroupInput, type CreateModifierInput, type CreateOrderDto, type CreateProductDto, type CreateRefundDto, type CreateShippingRateDto as CreateShippingRateInput, type CreateShippingZoneDto as CreateShippingZoneInput, type CreateTagDto as CreateTagInput, type CreateTaxRateDto as CreateTaxRateInput, type CreateVariantDto, type CustomApiAuthType, type CustomApiConnectionStatus, type CustomApiCredentials, type CustomApiIntegration, type CustomApiSyncConfig, type CustomApiSyncDirection, type CustomApiTestResult, type Customer, type CustomerAddress, type CustomerAuthResponse, type CustomerOAuthProvider, type CustomerProfile, type CustomerQueryParams, type DeleteProductResponse, type DiscountBanner, type DiscountRuleType, type DownloadFile, type DraftLineItem, type EditInventoryDto, type EmailDomain, type EmailEventSettings, type EmailEventType, type EmailSettings, type EmailTemplate, type EmailTemplatePreview, type EmailTemplatesResponse, type EmailVerificationResponse, type ExtendReservationResponse, type FaqContent, type FaqItem, type FooterColumn, type FooterContent, type FooterLink, type FooterSocialLink, type FormatPriceOptions, type FormatProductPriceOptions, type FreeAllocationPolicy, type FulfillOrderDto, type GuestCheckoutStartResponse, type GuestOrderResponse, type HeaderContent, type HeaderCta, type HeaderLogo, type HeaderNavItem, type InsufficientStockError, type InventoryInfo, type InventoryReservationStrategy, type InventorySyncStatus, type InventoryTrackingMode, type InvitationStatus, type InviteMemberDto as InviteMemberInput, type InviteStoreMemberDto as InviteStoreMemberInput, type JsonLdOptions, type ListModifierGroupsParams, type LocalCart, type LocalCartItem, type LockedVariant, type LoyaltyNextTierSummary, type LoyaltyReward, type LoyaltyStatus, type LoyaltyTierSummary, type MergeCartsDto, type MetafieldConflict, type MetafieldConflictResolution, type MetafieldDefinition, type MetafieldType, type Modifier, type ModifierGroup, type ModifierSelection, type ModifierSelectionType, type ModifierValidationCode, type ModifierValidationError, type MyProductReview, type OAuthAuthorizeResponse, type OAuthCallbackResponse, type OAuthConnection, type OAuthConnectionsResponse, type OAuthProviderConfig, type OAuthProviderType, type OAuthProvidersResponse, type Order, type OrderAddress, type OrderBump, type OrderCustomer, type OrderDownloadLink, type OrderItem, type OrderQueryParams, type OrderStatus, type OrderStatusChange, type PageContent, type PageSeo, type PaginatedResponse, type PaymentClientSdk, type PaymentConfig, type PaymentIntent, type PaymentProvider, type PaymentProviderConfig, type PaymentProvidersConfig, type PaymentStatus, type PaymentUrlOptions, type PickupLocation, type PlatformCouponCapabilities, type PlatformMetafieldMetadata, type PreviewEmailTemplateDto as PreviewEmailTemplateInput, type Product, type ProductAttributeInput, type ProductAvailability, type ProductCustomizationField, type ProductDiscount, type ProductDiscountBadge, type ProductImage, type ProductMetafield, type ProductMetafieldValue, type ProductModifierGroupAttachment, type ProductQueryParams, type ProductRecommendation, type ProductRecommendationsResponse, type ProductRelationType, type ProductReview, type ProductReviewAdmin, type ProductSuggestion, type ProductVariant, type PublicMetafieldDefinition, type PublishProductResponse, RTL_LOCALES, type RecommendationVariant, type ReconcileInventoryResponse, type RedeemRewardResult, type ReferralInfo, type Refund, type RefundLineItem, type RefundLineItemResponse, type RefundType, type RegisterCustomerDto, type ReservationInfo, type ResolveMetafieldConflictDto as ResolveMetafieldConflictInput, type ResolveSyncConflictDto as ResolveSyncConflictInput, type RichTextContent, SDK_VERSION, type SearchSuggestions, type SelectPickupLocationDto, type SelectShippingMethodDto, type SendInvoiceDto, type SessionCartRef, type SetBillingAddressDto, type SetCheckoutCustomFieldsDto, type SetCheckoutCustomerDto, type SetDefinitionProductsDto as SetDefinitionProductsInput, type SetMetafieldPlatformsDto as SetMetafieldPlatformsInput, type SetShippingAddressDto, type SetShippingAddressResponse, type ShippingDestinations, type ShippingLine, type ShippingRate, type ShippingRateConfig, type ShippingRateType, type ShippingSummaryEntry, type ShippingZone, type ShippingZoneQueryParams, type SitemapEntry, type StockAvailabilityRequest, type StockAvailabilityResponse, type StockAvailabilityResult, type StoreInfo, type StoreInvitation, type StoreInvitationDetails, type StoreMember, type StorePermission, type StoreRole, type StoreTeamResponse, type SubmitProductReviewInput, type SupportedLocaleObject, type SyncConflict, type SyncConflictResolution, type SyncJob, type Tag, type TaxBreakdown, type TaxBreakdownItem, type TaxRate, type TaxonomyQueryParams, type TeamInvitation, type TeamInvitationsResponse, type TeamMember, type TeamMembersResponse, type TeamRole, type UpdateAddressDto, type UpdateAttachmentInput, type UpdateAttributeDto as UpdateAttributeInput, type UpdateAttributeOptionDto as UpdateAttributeOptionInput, type UpdateBrandDto as UpdateBrandInput, type UpdateCartItemDto, type UpdateCategoryDto as UpdateCategoryInput, type UpdateContentInput, type UpdateCouponDto, type UpdateCustomApiDto, type UpdateCustomerDto, type UpdateDraftDto, type UpdateEmailSettingsDto as UpdateEmailSettingsInput, type UpdateEmailTemplateDto as UpdateEmailTemplateInput, type UpdateInventoryDto, type UpdateMemberRoleDto as UpdateMemberRoleInput, type UpdateMetafieldDefinitionDto as UpdateMetafieldDefinitionInput, type UpdateModifierGroupInput, type UpdateModifierInput, type UpdateOAuthProviderDto as UpdateOAuthProviderInput, type UpdateOrderDto, type UpdateOrderShippingDto, type UpdateProductDto, type UpdateShippingRateDto as UpdateShippingRateInput, type UpdateShippingZoneDto as UpdateShippingZoneInput, type UpdateStoreMemberDto as UpdateStoreMemberInput, type UpdateTagDto as UpdateTagInput, type UpdateTaxRateDto as UpdateTaxRateInput, type UpdateVariantDto, type UpdateVariantInventoryDto, type UpsertProductMetafieldDto as UpsertProductMetafieldInput, type UserStore, type UserStorePermissions, type VariantInventoryResponse, type VariantPlatformOverlay, type VariantStatus, type WaitForOrderOptions, type WaitForOrderResult, type WebhookEvent, type WebhookEventType, type WriteProductReviewInput, buildArticleJsonLd, buildBreadcrumbJsonLd, buildCollectionPageJsonLd, buildOrganizationJsonLd, buildProductJsonLd, buildWebsiteJsonLd, createWebhookHandler, deriveSeoDescription, enableDevGuards, formatMoney, formatPrice, formatProductPrice, formatVariantPrice, getBlogSitemapEntries, getCartItemImage, getCartItemName, getCartTotals, getCategorySitemapEntries, getDescriptionContent, getDirectionForLocale, formatPrice as getPriceDisplay, getProductCustomizationFields, getProductMetafield, getProductMetafieldValue, getProductMetafieldsByType, getProductPrice, getProductPriceInfo, getProductSwatches, getStockStatus, getVariantOptions, getVariantPrice, isAllowedPaymentUrl, isCouponApplicableToProduct, isHtmlDescription, isWebhookEventType, jsonLdScriptProps, parseWebhookEvent, safePaymentRedirect, stripHtml, verifyWebhook };
10992
+ export { type AddToCartDto, type AddressDetailsResult, type AddressSuggestion, type AnnouncementContent, type AnnouncementSeverity, type AppliedDiscount, type ApplyCouponDto, type AttachModifierGroupInput, type Attribute, type AttributeOption, type AttributeSource, type BlogSitemapOptions, type BrainerceApiError, BrainerceClient, type BrainerceClientOptions, BrainerceError, type Brand, type BulkInventoryResponse, type BulkSaveVariantsDto, type BulkSaveVariantsResponse, type BulkVariantInput, type BusinessHoursWindow, type Cart, type CartAppliedDiscount, type CartBundleOffer, type CartBundlesResponse, type CartIncludeOption, type CartIncludeOptions, type CartItem, type CartItemModifierLine, type CartNudge, type CartRecommendationsResponse, type CartStatus, type CartUpgradeSuggestion, type CartUpgradesResponse, type CartWithIncludes, type Category, type CategoryDetail, type CategoryNode, type CategorySitemapOptions, type CategorySuggestion, type Checkout, type CheckoutAddress, type CheckoutBumpsResponse, type CheckoutCustomFieldDefinition, type CheckoutFieldPricing, type CheckoutFieldVisibility, type CheckoutLineItem, type CheckoutPrefillData, type CheckoutStatus, type CompleteCheckoutResponse, type CompleteDraftDto, type ConfigureOAuthProviderDto as ConfigureOAuthProviderInput, type ConflictStatus, type ConnectorPlatform, type ContactFormFieldType, type ContactFormFieldValidation, type ContactFormPublic, type ContactFormPublicField, type ContactFormSummary, type Content, type ContentDataMap, type ContentStatus, type ContentSummary, type ContentType, type Coupon, type CouponCreateResponse, type CouponQueryParams, type CouponStatus, type CouponType, type CouponValidationWarning, type CreateAddressDto, type CreateAttributeDto as CreateAttributeInput, type CreateAttributeOptionDto as CreateAttributeOptionInput, type CreateBrandDto as CreateBrandInput, type CreateCategoryDto as CreateCategoryInput, type CreateCheckoutDto, type CreateContentInput, type CreateCouponDto, type CreateCustomApiDto, type CreateCustomerDto, type CreateEmailTemplateDto as CreateEmailTemplateInput, type CreateGuestOrderDto, type CreateInquiryInput, type CreateInquiryResponse, type CreateMetafieldDefinitionDto as CreateMetafieldDefinitionInput, type CreateModifierGroupInput, type CreateModifierInput, type CreateOrderDto, type CreateProductDto, type CreateRefundDto, type CreateShippingRateDto as CreateShippingRateInput, type CreateShippingZoneDto as CreateShippingZoneInput, type CreateTagDto as CreateTagInput, type CreateTaxRateDto as CreateTaxRateInput, type CreateVariantDto, type CustomApiAuthType, type CustomApiConnectionStatus, type CustomApiCredentials, type CustomApiIntegration, type CustomApiSyncConfig, type CustomApiSyncDirection, type CustomApiTestResult, type Customer, type CustomerAddress, type CustomerAuthResponse, type CustomerOAuthProvider, type CustomerProfile, type CustomerQueryParams, type DateAvailabilityConstraints, type DeleteProductResponse, type DiscountBanner, type DiscountRuleType, type DownloadFile, type DraftLineItem, type EditInventoryDto, type EmailDomain, type EmailEventSettings, type EmailEventType, type EmailSettings, type EmailTemplate, type EmailTemplatePreview, type EmailTemplatesResponse, type EmailVerificationResponse, type ExtendReservationResponse, type FaqContent, type FaqItem, type FooterColumn, type FooterContent, type FooterLink, type FooterSocialLink, type FormatPriceOptions, type FormatProductPriceOptions, type FreeAllocationPolicy, type FulfillOrderDto, type GuestCheckoutStartResponse, type GuestOrderResponse, type HeaderContent, type HeaderCta, type HeaderLogo, type HeaderNavItem, type InsufficientStockError, type InventoryInfo, type InventoryReservationStrategy, type InventorySyncStatus, type InventoryTrackingMode, type InvitationStatus, type InviteMemberDto as InviteMemberInput, type InviteStoreMemberDto as InviteStoreMemberInput, type JsonLdOptions, type ListModifierGroupsParams, type LocalCart, type LocalCartItem, type LockedVariant, type LoyaltyNextTierSummary, type LoyaltyReward, type LoyaltyStatus, type LoyaltyTierSummary, type MergeCartsDto, type MetafieldConflict, type MetafieldConflictResolution, type MetafieldDefinition, type MetafieldType, type Modifier, type ModifierGroup, type ModifierSelection, type ModifierSelectionType, type ModifierValidationCode, type ModifierValidationError, type MyProductReview, type OAuthAuthorizeResponse, type OAuthCallbackResponse, type OAuthConnection, type OAuthConnectionsResponse, type OAuthProviderConfig, type OAuthProviderType, type OAuthProvidersResponse, type Order, type OrderAddress, type OrderBump, type OrderCustomer, type OrderDownloadLink, type OrderItem, type OrderQueryParams, type OrderStatus, type OrderStatusChange, type PageContent, type PageSeo, type PaginatedResponse, type PaymentClientSdk, type PaymentConfig, type PaymentIntent, type PaymentProvider, type PaymentProviderConfig, type PaymentProvidersConfig, type PaymentStatus, type PaymentUrlOptions, type PickupLocation, type PlatformCouponCapabilities, type PlatformMetafieldMetadata, type PreviewEmailTemplateDto as PreviewEmailTemplateInput, type Product, type ProductAttributeInput, type ProductAvailability, type ProductCustomizationField, type ProductDiscount, type ProductDiscountBadge, type ProductImage, type ProductMetafield, type ProductMetafieldValue, type ProductModifierGroupAttachment, type ProductQueryParams, type ProductRecommendation, type ProductRecommendationsResponse, type ProductRelationType, type ProductReview, type ProductReviewAdmin, type ProductSuggestion, type ProductVariant, type PublicMetafieldDefinition, type PublishProductResponse, RTL_LOCALES, type RecommendationVariant, type ReconcileInventoryResponse, type RedeemRewardResult, type ReferralInfo, type Refund, type RefundLineItem, type RefundLineItemResponse, type RefundType, type RegisterCustomerDto, type ReservationInfo, type ResolveMetafieldConflictDto as ResolveMetafieldConflictInput, type ResolveSyncConflictDto as ResolveSyncConflictInput, type RichTextContent, SDK_VERSION, type SearchSuggestions, type SelectPickupLocationDto, type SelectShippingMethodDto, type SendInvoiceDto, type SessionCartRef, type SetBillingAddressDto, type SetCheckoutCustomFieldsDto, type SetCheckoutCustomerDto, type SetDefinitionProductsDto as SetDefinitionProductsInput, type SetMetafieldPlatformsDto as SetMetafieldPlatformsInput, type SetShippingAddressDto, type SetShippingAddressResponse, type ShippingDestinations, type ShippingLine, type ShippingRate, type ShippingRateConfig, type ShippingRateType, type ShippingSummaryEntry, type ShippingZone, type ShippingZoneQueryParams, type SitemapEntry, type StockAvailabilityRequest, type StockAvailabilityResponse, type StockAvailabilityResult, type StoreInfo, type StoreInvitation, type StoreInvitationDetails, type StoreMember, type StorePermission, type StoreRole, type StoreTeamResponse, type SubmitProductReviewInput, type SupportedLocaleObject, type SyncConflict, type SyncConflictResolution, type SyncJob, type Tag, type TaxBreakdown, type TaxBreakdownItem, type TaxRate, type TaxonomyQueryParams, type TeamInvitation, type TeamInvitationsResponse, type TeamMember, type TeamMembersResponse, type TeamRole, type UpdateAddressDto, type UpdateAttachmentInput, type UpdateAttributeDto as UpdateAttributeInput, type UpdateAttributeOptionDto as UpdateAttributeOptionInput, type UpdateBrandDto as UpdateBrandInput, type UpdateCartItemDto, type UpdateCategoryDto as UpdateCategoryInput, type UpdateContentInput, type UpdateCouponDto, type UpdateCustomApiDto, type UpdateCustomerDto, type UpdateDraftDto, type UpdateEmailSettingsDto as UpdateEmailSettingsInput, type UpdateEmailTemplateDto as UpdateEmailTemplateInput, type UpdateInventoryDto, type UpdateMemberRoleDto as UpdateMemberRoleInput, type UpdateMetafieldDefinitionDto as UpdateMetafieldDefinitionInput, type UpdateModifierGroupInput, type UpdateModifierInput, type UpdateOAuthProviderDto as UpdateOAuthProviderInput, type UpdateOrderDto, type UpdateOrderShippingDto, type UpdateProductDto, type UpdateShippingRateDto as UpdateShippingRateInput, type UpdateShippingZoneDto as UpdateShippingZoneInput, type UpdateStoreMemberDto as UpdateStoreMemberInput, type UpdateTagDto as UpdateTagInput, type UpdateTaxRateDto as UpdateTaxRateInput, type UpdateVariantDto, type UpdateVariantInventoryDto, type UpsertProductMetafieldDto as UpsertProductMetafieldInput, type UserStore, type UserStorePermissions, type VariantInventoryResponse, type VariantPlatformOverlay, type VariantStatus, type WaitForOrderOptions, type WaitForOrderResult, type WebhookEvent, type WebhookEventType, type WriteProductReviewInput, buildArticleJsonLd, buildBreadcrumbJsonLd, buildCollectionPageJsonLd, buildOrganizationJsonLd, buildProductJsonLd, buildWebsiteJsonLd, computeAvailableSlots, createWebhookHandler, deriveSeoDescription, enableDevGuards, formatMoney, formatPrice, formatProductPrice, formatVariantPrice, getBlogSitemapEntries, getCartItemImage, getCartItemName, getCartTotals, getCategorySitemapEntries, getDescriptionContent, getDirectionForLocale, formatPrice as getPriceDisplay, getProductCustomizationFields, getProductMetafield, getProductMetafieldValue, getProductMetafieldsByType, getProductPrice, getProductPriceInfo, getProductSwatches, getStockStatus, getVariantOptions, getVariantPrice, isAllowedPaymentUrl, isCalendarDateAllowed, isCouponApplicableToProduct, isDateValueAllowed, isHtmlDescription, isWebhookEventType, jsonLdScriptProps, parseWebhookEvent, resolveStoreLocalParts, safePaymentRedirect, stripHtml, validateDateAvailabilityConfig, verifyWebhook };
package/dist/index.js CHANGED
@@ -40,6 +40,7 @@ __export(index_exports, {
40
40
  buildOrganizationJsonLd: () => buildOrganizationJsonLd,
41
41
  buildProductJsonLd: () => buildProductJsonLd,
42
42
  buildWebsiteJsonLd: () => buildWebsiteJsonLd,
43
+ computeAvailableSlots: () => computeAvailableSlots,
43
44
  createWebhookHandler: () => createWebhookHandler,
44
45
  deriveSeoDescription: () => deriveSeoDescription,
45
46
  enableDevGuards: () => enableDevGuards,
@@ -66,13 +67,17 @@ __export(index_exports, {
66
67
  getVariantOptions: () => getVariantOptions,
67
68
  getVariantPrice: () => getVariantPrice,
68
69
  isAllowedPaymentUrl: () => isAllowedPaymentUrl,
70
+ isCalendarDateAllowed: () => isCalendarDateAllowed,
69
71
  isCouponApplicableToProduct: () => isCouponApplicableToProduct,
72
+ isDateValueAllowed: () => isDateValueAllowed,
70
73
  isHtmlDescription: () => isHtmlDescription,
71
74
  isWebhookEventType: () => isWebhookEventType,
72
75
  jsonLdScriptProps: () => jsonLdScriptProps,
73
76
  parseWebhookEvent: () => parseWebhookEvent,
77
+ resolveStoreLocalParts: () => resolveStoreLocalParts,
74
78
  safePaymentRedirect: () => safePaymentRedirect,
75
79
  stripHtml: () => stripHtml2,
80
+ validateDateAvailabilityConfig: () => validateDateAvailabilityConfig,
76
81
  verifyWebhook: () => verifyWebhook
77
82
  });
78
83
  module.exports = __toCommonJS(index_exports);
@@ -9189,6 +9194,183 @@ function formatAmount(amount, currency, locale) {
9189
9194
  }
9190
9195
  }
9191
9196
 
9197
+ // src/date-availability.ts
9198
+ var DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
9199
+ var TIME_RE = /^([01]\d|2[0-3]):[0-5]\d$/;
9200
+ function validateDateAvailabilityConfig(config, fieldType) {
9201
+ const errors = [];
9202
+ if (!config) return errors;
9203
+ if (config.minDate !== void 0 && !DATE_RE.test(config.minDate)) {
9204
+ errors.push("minDate must be in YYYY-MM-DD format");
9205
+ }
9206
+ if (config.maxDate !== void 0 && !DATE_RE.test(config.maxDate)) {
9207
+ errors.push("maxDate must be in YYYY-MM-DD format");
9208
+ }
9209
+ if (config.minDate && config.maxDate && DATE_RE.test(config.minDate) && DATE_RE.test(config.maxDate) && config.minDate > config.maxDate) {
9210
+ errors.push("minDate must be on or before maxDate");
9211
+ }
9212
+ if (config.blockedWeekdays) {
9213
+ for (const d of config.blockedWeekdays) {
9214
+ if (!Number.isInteger(d) || d < 0 || d > 6) {
9215
+ errors.push(`blockedWeekdays entries must be integers 0-6, got ${JSON.stringify(d)}`);
9216
+ break;
9217
+ }
9218
+ }
9219
+ }
9220
+ if (config.blockedDates) {
9221
+ for (const d of config.blockedDates) {
9222
+ if (!DATE_RE.test(d)) {
9223
+ errors.push(`blockedDates entries must be in YYYY-MM-DD format, got "${d}"`);
9224
+ break;
9225
+ }
9226
+ }
9227
+ }
9228
+ if (config.businessHours) {
9229
+ const seenWeekdays = /* @__PURE__ */ new Set();
9230
+ for (const w of config.businessHours) {
9231
+ if (!Number.isInteger(w.weekday) || w.weekday < 0 || w.weekday > 6) {
9232
+ errors.push(`businessHours.weekday must be an integer 0-6, got ${JSON.stringify(w.weekday)}`);
9233
+ continue;
9234
+ }
9235
+ if (seenWeekdays.has(w.weekday)) {
9236
+ errors.push(`businessHours has more than one window for weekday ${w.weekday}`);
9237
+ }
9238
+ seenWeekdays.add(w.weekday);
9239
+ const openValid = TIME_RE.test(w.open);
9240
+ const closeValid = TIME_RE.test(w.close);
9241
+ if (!openValid) errors.push(`businessHours.open must be HH:mm, got "${w.open}"`);
9242
+ if (!closeValid) errors.push(`businessHours.close must be HH:mm, got "${w.close}"`);
9243
+ if (openValid && closeValid && w.open >= w.close) {
9244
+ errors.push(`businessHours for weekday ${w.weekday}: open must be before close`);
9245
+ }
9246
+ }
9247
+ }
9248
+ if (config.slotDurationMinutes !== void 0) {
9249
+ if (!Number.isInteger(config.slotDurationMinutes) || config.slotDurationMinutes <= 0) {
9250
+ errors.push("slotDurationMinutes must be a positive integer");
9251
+ }
9252
+ if (!config.businessHours || config.businessHours.length === 0) {
9253
+ errors.push("slotDurationMinutes requires at least one businessHours window");
9254
+ }
9255
+ }
9256
+ if (fieldType === "DATE" && (config.businessHours?.length || config.slotDurationMinutes !== void 0)) {
9257
+ errors.push("businessHours/slotDurationMinutes only apply to DATETIME fields, not DATE");
9258
+ }
9259
+ return errors;
9260
+ }
9261
+ var WEEKDAY_TO_INDEX = {
9262
+ Sun: 0,
9263
+ Mon: 1,
9264
+ Tue: 2,
9265
+ Wed: 3,
9266
+ Thu: 4,
9267
+ Fri: 5,
9268
+ Sat: 6
9269
+ };
9270
+ function resolveStoreLocalParts(instant, timezone) {
9271
+ let parts;
9272
+ try {
9273
+ const fmt = new Intl.DateTimeFormat("en-US", {
9274
+ timeZone: timezone,
9275
+ weekday: "short",
9276
+ year: "numeric",
9277
+ month: "2-digit",
9278
+ day: "2-digit",
9279
+ hour: "2-digit",
9280
+ minute: "2-digit",
9281
+ hour12: false
9282
+ });
9283
+ parts = fmt.formatToParts(instant);
9284
+ } catch {
9285
+ return {
9286
+ dateYYYYMMDD: `${instant.getUTCFullYear()}-${pad2(instant.getUTCMonth() + 1)}-${pad2(instant.getUTCDate())}`,
9287
+ hhmm: `${pad2(instant.getUTCHours())}:${pad2(instant.getUTCMinutes())}`,
9288
+ weekday: instant.getUTCDay()
9289
+ };
9290
+ }
9291
+ const get = (type) => parts.find((p) => p.type === type)?.value ?? "";
9292
+ let hour = get("hour");
9293
+ if (hour === "24") hour = "00";
9294
+ return {
9295
+ dateYYYYMMDD: `${get("year")}-${get("month")}-${get("day")}`,
9296
+ hhmm: `${hour}:${get("minute")}`,
9297
+ weekday: WEEKDAY_TO_INDEX[get("weekday")] ?? instant.getUTCDay()
9298
+ };
9299
+ }
9300
+ function isCalendarDateAllowed(dateYYYYMMDD, config) {
9301
+ if (!config) return true;
9302
+ if (config.minDate && dateYYYYMMDD < config.minDate) return false;
9303
+ if (config.maxDate && dateYYYYMMDD > config.maxDate) return false;
9304
+ if (config.blockedDates?.includes(dateYYYYMMDD)) return false;
9305
+ if (config.blockedWeekdays?.length) {
9306
+ if (config.blockedWeekdays.includes(weekdayOfDateString(dateYYYYMMDD))) return false;
9307
+ }
9308
+ return true;
9309
+ }
9310
+ function computeAvailableSlots(config, dateYYYYMMDD) {
9311
+ if (!config) return [];
9312
+ if (!isCalendarDateAllowed(dateYYYYMMDD, config)) return [];
9313
+ if (!config.businessHours?.length || !config.slotDurationMinutes) return [];
9314
+ const weekday = weekdayOfDateString(dateYYYYMMDD);
9315
+ const windows = config.businessHours.filter((w) => w.weekday === weekday);
9316
+ if (windows.length === 0) return [];
9317
+ const slots = [];
9318
+ for (const w of windows) {
9319
+ const openMin = toMinutes(w.open);
9320
+ const closeMin = toMinutes(w.close);
9321
+ for (let t = openMin; t + config.slotDurationMinutes <= closeMin; t += config.slotDurationMinutes) {
9322
+ slots.push(minutesToHHMM(t));
9323
+ }
9324
+ }
9325
+ return slots;
9326
+ }
9327
+ function isDateValueAllowed(instant, config, fieldType, timezone) {
9328
+ if (!config) return { allowed: true };
9329
+ if (fieldType === "DATE") {
9330
+ const dateYYYYMMDD = `${instant.getUTCFullYear()}-${pad2(instant.getUTCMonth() + 1)}-${pad2(instant.getUTCDate())}`;
9331
+ if (!isCalendarDateAllowed(dateYYYYMMDD, config)) {
9332
+ return { allowed: false, reason: "date is outside the allowed range" };
9333
+ }
9334
+ return { allowed: true };
9335
+ }
9336
+ const local = resolveStoreLocalParts(instant, timezone);
9337
+ if (!isCalendarDateAllowed(local.dateYYYYMMDD, config)) {
9338
+ return { allowed: false, reason: "date is outside the allowed range" };
9339
+ }
9340
+ if (!config.businessHours?.length) {
9341
+ return { allowed: true };
9342
+ }
9343
+ const windows = config.businessHours.filter((w) => w.weekday === local.weekday);
9344
+ if (windows.length === 0) {
9345
+ return { allowed: false, reason: "no business hours are configured for this day" };
9346
+ }
9347
+ if (config.slotDurationMinutes) {
9348
+ const slots = computeAvailableSlots(config, local.dateYYYYMMDD);
9349
+ if (!slots.includes(local.hhmm)) {
9350
+ return { allowed: false, reason: "time does not match an available slot" };
9351
+ }
9352
+ return { allowed: true };
9353
+ }
9354
+ const inWindow = windows.some((w) => local.hhmm >= w.open && local.hhmm < w.close);
9355
+ if (!inWindow) {
9356
+ return { allowed: false, reason: "time is outside business hours" };
9357
+ }
9358
+ return { allowed: true };
9359
+ }
9360
+ function weekdayOfDateString(dateYYYYMMDD) {
9361
+ return (/* @__PURE__ */ new Date(`${dateYYYYMMDD}T00:00:00Z`)).getUTCDay();
9362
+ }
9363
+ function toMinutes(hhmm) {
9364
+ const [h, m] = hhmm.split(":").map(Number);
9365
+ return h * 60 + m;
9366
+ }
9367
+ function minutesToHHMM(totalMinutes) {
9368
+ return `${pad2(Math.floor(totalMinutes / 60))}:${pad2(totalMinutes % 60)}`;
9369
+ }
9370
+ function pad2(n) {
9371
+ return n.toString().padStart(2, "0");
9372
+ }
9373
+
9192
9374
  // src/jsonld.ts
9193
9375
  function absoluteUrl(siteUrl, path) {
9194
9376
  if (!path) return void 0;
@@ -9682,6 +9864,7 @@ function isCouponApplicableToProduct(coupon, productId) {
9682
9864
  buildOrganizationJsonLd,
9683
9865
  buildProductJsonLd,
9684
9866
  buildWebsiteJsonLd,
9867
+ computeAvailableSlots,
9685
9868
  createWebhookHandler,
9686
9869
  deriveSeoDescription,
9687
9870
  enableDevGuards,
@@ -9708,12 +9891,16 @@ function isCouponApplicableToProduct(coupon, productId) {
9708
9891
  getVariantOptions,
9709
9892
  getVariantPrice,
9710
9893
  isAllowedPaymentUrl,
9894
+ isCalendarDateAllowed,
9711
9895
  isCouponApplicableToProduct,
9896
+ isDateValueAllowed,
9712
9897
  isHtmlDescription,
9713
9898
  isWebhookEventType,
9714
9899
  jsonLdScriptProps,
9715
9900
  parseWebhookEvent,
9901
+ resolveStoreLocalParts,
9716
9902
  safePaymentRedirect,
9717
9903
  stripHtml,
9904
+ validateDateAvailabilityConfig,
9718
9905
  verifyWebhook
9719
9906
  });
package/dist/index.mjs CHANGED
@@ -9110,6 +9110,183 @@ function formatAmount(amount, currency, locale) {
9110
9110
  }
9111
9111
  }
9112
9112
 
9113
+ // src/date-availability.ts
9114
+ var DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
9115
+ var TIME_RE = /^([01]\d|2[0-3]):[0-5]\d$/;
9116
+ function validateDateAvailabilityConfig(config, fieldType) {
9117
+ const errors = [];
9118
+ if (!config) return errors;
9119
+ if (config.minDate !== void 0 && !DATE_RE.test(config.minDate)) {
9120
+ errors.push("minDate must be in YYYY-MM-DD format");
9121
+ }
9122
+ if (config.maxDate !== void 0 && !DATE_RE.test(config.maxDate)) {
9123
+ errors.push("maxDate must be in YYYY-MM-DD format");
9124
+ }
9125
+ if (config.minDate && config.maxDate && DATE_RE.test(config.minDate) && DATE_RE.test(config.maxDate) && config.minDate > config.maxDate) {
9126
+ errors.push("minDate must be on or before maxDate");
9127
+ }
9128
+ if (config.blockedWeekdays) {
9129
+ for (const d of config.blockedWeekdays) {
9130
+ if (!Number.isInteger(d) || d < 0 || d > 6) {
9131
+ errors.push(`blockedWeekdays entries must be integers 0-6, got ${JSON.stringify(d)}`);
9132
+ break;
9133
+ }
9134
+ }
9135
+ }
9136
+ if (config.blockedDates) {
9137
+ for (const d of config.blockedDates) {
9138
+ if (!DATE_RE.test(d)) {
9139
+ errors.push(`blockedDates entries must be in YYYY-MM-DD format, got "${d}"`);
9140
+ break;
9141
+ }
9142
+ }
9143
+ }
9144
+ if (config.businessHours) {
9145
+ const seenWeekdays = /* @__PURE__ */ new Set();
9146
+ for (const w of config.businessHours) {
9147
+ if (!Number.isInteger(w.weekday) || w.weekday < 0 || w.weekday > 6) {
9148
+ errors.push(`businessHours.weekday must be an integer 0-6, got ${JSON.stringify(w.weekday)}`);
9149
+ continue;
9150
+ }
9151
+ if (seenWeekdays.has(w.weekday)) {
9152
+ errors.push(`businessHours has more than one window for weekday ${w.weekday}`);
9153
+ }
9154
+ seenWeekdays.add(w.weekday);
9155
+ const openValid = TIME_RE.test(w.open);
9156
+ const closeValid = TIME_RE.test(w.close);
9157
+ if (!openValid) errors.push(`businessHours.open must be HH:mm, got "${w.open}"`);
9158
+ if (!closeValid) errors.push(`businessHours.close must be HH:mm, got "${w.close}"`);
9159
+ if (openValid && closeValid && w.open >= w.close) {
9160
+ errors.push(`businessHours for weekday ${w.weekday}: open must be before close`);
9161
+ }
9162
+ }
9163
+ }
9164
+ if (config.slotDurationMinutes !== void 0) {
9165
+ if (!Number.isInteger(config.slotDurationMinutes) || config.slotDurationMinutes <= 0) {
9166
+ errors.push("slotDurationMinutes must be a positive integer");
9167
+ }
9168
+ if (!config.businessHours || config.businessHours.length === 0) {
9169
+ errors.push("slotDurationMinutes requires at least one businessHours window");
9170
+ }
9171
+ }
9172
+ if (fieldType === "DATE" && (config.businessHours?.length || config.slotDurationMinutes !== void 0)) {
9173
+ errors.push("businessHours/slotDurationMinutes only apply to DATETIME fields, not DATE");
9174
+ }
9175
+ return errors;
9176
+ }
9177
+ var WEEKDAY_TO_INDEX = {
9178
+ Sun: 0,
9179
+ Mon: 1,
9180
+ Tue: 2,
9181
+ Wed: 3,
9182
+ Thu: 4,
9183
+ Fri: 5,
9184
+ Sat: 6
9185
+ };
9186
+ function resolveStoreLocalParts(instant, timezone) {
9187
+ let parts;
9188
+ try {
9189
+ const fmt = new Intl.DateTimeFormat("en-US", {
9190
+ timeZone: timezone,
9191
+ weekday: "short",
9192
+ year: "numeric",
9193
+ month: "2-digit",
9194
+ day: "2-digit",
9195
+ hour: "2-digit",
9196
+ minute: "2-digit",
9197
+ hour12: false
9198
+ });
9199
+ parts = fmt.formatToParts(instant);
9200
+ } catch {
9201
+ return {
9202
+ dateYYYYMMDD: `${instant.getUTCFullYear()}-${pad2(instant.getUTCMonth() + 1)}-${pad2(instant.getUTCDate())}`,
9203
+ hhmm: `${pad2(instant.getUTCHours())}:${pad2(instant.getUTCMinutes())}`,
9204
+ weekday: instant.getUTCDay()
9205
+ };
9206
+ }
9207
+ const get = (type) => parts.find((p) => p.type === type)?.value ?? "";
9208
+ let hour = get("hour");
9209
+ if (hour === "24") hour = "00";
9210
+ return {
9211
+ dateYYYYMMDD: `${get("year")}-${get("month")}-${get("day")}`,
9212
+ hhmm: `${hour}:${get("minute")}`,
9213
+ weekday: WEEKDAY_TO_INDEX[get("weekday")] ?? instant.getUTCDay()
9214
+ };
9215
+ }
9216
+ function isCalendarDateAllowed(dateYYYYMMDD, config) {
9217
+ if (!config) return true;
9218
+ if (config.minDate && dateYYYYMMDD < config.minDate) return false;
9219
+ if (config.maxDate && dateYYYYMMDD > config.maxDate) return false;
9220
+ if (config.blockedDates?.includes(dateYYYYMMDD)) return false;
9221
+ if (config.blockedWeekdays?.length) {
9222
+ if (config.blockedWeekdays.includes(weekdayOfDateString(dateYYYYMMDD))) return false;
9223
+ }
9224
+ return true;
9225
+ }
9226
+ function computeAvailableSlots(config, dateYYYYMMDD) {
9227
+ if (!config) return [];
9228
+ if (!isCalendarDateAllowed(dateYYYYMMDD, config)) return [];
9229
+ if (!config.businessHours?.length || !config.slotDurationMinutes) return [];
9230
+ const weekday = weekdayOfDateString(dateYYYYMMDD);
9231
+ const windows = config.businessHours.filter((w) => w.weekday === weekday);
9232
+ if (windows.length === 0) return [];
9233
+ const slots = [];
9234
+ for (const w of windows) {
9235
+ const openMin = toMinutes(w.open);
9236
+ const closeMin = toMinutes(w.close);
9237
+ for (let t = openMin; t + config.slotDurationMinutes <= closeMin; t += config.slotDurationMinutes) {
9238
+ slots.push(minutesToHHMM(t));
9239
+ }
9240
+ }
9241
+ return slots;
9242
+ }
9243
+ function isDateValueAllowed(instant, config, fieldType, timezone) {
9244
+ if (!config) return { allowed: true };
9245
+ if (fieldType === "DATE") {
9246
+ const dateYYYYMMDD = `${instant.getUTCFullYear()}-${pad2(instant.getUTCMonth() + 1)}-${pad2(instant.getUTCDate())}`;
9247
+ if (!isCalendarDateAllowed(dateYYYYMMDD, config)) {
9248
+ return { allowed: false, reason: "date is outside the allowed range" };
9249
+ }
9250
+ return { allowed: true };
9251
+ }
9252
+ const local = resolveStoreLocalParts(instant, timezone);
9253
+ if (!isCalendarDateAllowed(local.dateYYYYMMDD, config)) {
9254
+ return { allowed: false, reason: "date is outside the allowed range" };
9255
+ }
9256
+ if (!config.businessHours?.length) {
9257
+ return { allowed: true };
9258
+ }
9259
+ const windows = config.businessHours.filter((w) => w.weekday === local.weekday);
9260
+ if (windows.length === 0) {
9261
+ return { allowed: false, reason: "no business hours are configured for this day" };
9262
+ }
9263
+ if (config.slotDurationMinutes) {
9264
+ const slots = computeAvailableSlots(config, local.dateYYYYMMDD);
9265
+ if (!slots.includes(local.hhmm)) {
9266
+ return { allowed: false, reason: "time does not match an available slot" };
9267
+ }
9268
+ return { allowed: true };
9269
+ }
9270
+ const inWindow = windows.some((w) => local.hhmm >= w.open && local.hhmm < w.close);
9271
+ if (!inWindow) {
9272
+ return { allowed: false, reason: "time is outside business hours" };
9273
+ }
9274
+ return { allowed: true };
9275
+ }
9276
+ function weekdayOfDateString(dateYYYYMMDD) {
9277
+ return (/* @__PURE__ */ new Date(`${dateYYYYMMDD}T00:00:00Z`)).getUTCDay();
9278
+ }
9279
+ function toMinutes(hhmm) {
9280
+ const [h, m] = hhmm.split(":").map(Number);
9281
+ return h * 60 + m;
9282
+ }
9283
+ function minutesToHHMM(totalMinutes) {
9284
+ return `${pad2(Math.floor(totalMinutes / 60))}:${pad2(totalMinutes % 60)}`;
9285
+ }
9286
+ function pad2(n) {
9287
+ return n.toString().padStart(2, "0");
9288
+ }
9289
+
9113
9290
  // src/jsonld.ts
9114
9291
  function absoluteUrl(siteUrl, path) {
9115
9292
  if (!path) return void 0;
@@ -9602,6 +9779,7 @@ export {
9602
9779
  buildOrganizationJsonLd,
9603
9780
  buildProductJsonLd,
9604
9781
  buildWebsiteJsonLd,
9782
+ computeAvailableSlots,
9605
9783
  createWebhookHandler,
9606
9784
  deriveSeoDescription,
9607
9785
  enableDevGuards,
@@ -9628,12 +9806,16 @@ export {
9628
9806
  getVariantOptions,
9629
9807
  getVariantPrice,
9630
9808
  isAllowedPaymentUrl,
9809
+ isCalendarDateAllowed,
9631
9810
  isCouponApplicableToProduct,
9811
+ isDateValueAllowed,
9632
9812
  isHtmlDescription,
9633
9813
  isWebhookEventType,
9634
9814
  jsonLdScriptProps,
9635
9815
  parseWebhookEvent,
9816
+ resolveStoreLocalParts,
9636
9817
  safePaymentRedirect,
9637
9818
  stripHtml2 as stripHtml,
9819
+ validateDateAvailabilityConfig,
9638
9820
  verifyWebhook
9639
9821
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brainerce",
3
- "version": "1.48.0",
3
+ "version": "1.48.1",
4
4
  "description": "Official SDK for building e-commerce storefronts with Brainerce Platform. Perfect for vibe-coded sites, AI-built stores (Cursor, Lovable, v0), and custom storefronts.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -62,6 +62,7 @@
62
62
  "url": "https://github.com/brainerce/brainerce/issues"
63
63
  },
64
64
  "devDependencies": {
65
+ "@brainerce/types": "workspace:*",
65
66
  "@types/node": "^25.0.3",
66
67
  "@typescript-eslint/eslint-plugin": "^8.50.1",
67
68
  "@typescript-eslint/parser": "^8.50.1",