@occluze/tether 0.6.7 → 0.7.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.
Files changed (250) hide show
  1. package/README.md +11 -11
  2. package/dist/esm/astro.js +2 -2
  3. package/dist/esm/chunks/account-UIPWJQ3Y.js +1 -0
  4. package/dist/esm/chunks/account-pages-6ROA6Y4V.js +1 -0
  5. package/dist/esm/chunks/analytics-2V632IRV.js +1 -0
  6. package/dist/esm/chunks/chunk-4GCXM764.js +1 -0
  7. package/dist/esm/chunks/chunk-56FCLJJD.js +1 -0
  8. package/dist/esm/chunks/chunk-5Z5O3767.js +1 -0
  9. package/dist/esm/chunks/chunk-6OZJCAGZ.js +1 -0
  10. package/dist/esm/chunks/chunk-A5SYCVQM.js +1 -0
  11. package/dist/esm/chunks/chunk-BA4LQJJQ.js +1 -0
  12. package/dist/esm/chunks/chunk-BFTZR4OB.js +4 -0
  13. package/dist/esm/chunks/chunk-C5JYQCWH.js +1 -0
  14. package/dist/esm/chunks/chunk-E5YO6274.js +1 -0
  15. package/dist/esm/chunks/chunk-MPDWM2NN.js +1 -0
  16. package/dist/esm/chunks/chunk-T44MUL4Y.js +1 -0
  17. package/dist/esm/chunks/chunk-YLUULATY.js +1 -0
  18. package/dist/esm/chunks/diagnose-3FEKRIEK.js +14 -0
  19. package/dist/esm/chunks/extras-6POFBNOP.js +1 -0
  20. package/dist/esm/chunks/markets-ui-FD6NI2OG.js +1 -0
  21. package/dist/esm/chunks/search-UJ73YBQ5.js +1 -0
  22. package/dist/esm/index.js +1 -1
  23. package/dist/esm/server.js +2 -1
  24. package/dist/presets/barba.esm.js +55 -39
  25. package/dist/tether.account-pages.js +781 -495
  26. package/dist/tether.account-pages.min.js +1 -1
  27. package/dist/tether.account.js +462 -381
  28. package/dist/tether.account.min.js +1 -1
  29. package/dist/tether.analytics.js +299 -194
  30. package/dist/tether.analytics.min.js +1 -1
  31. package/dist/tether.diagnose.js +354 -262
  32. package/dist/tether.diagnose.min.js +2 -2
  33. package/dist/tether.extras.js +82 -45
  34. package/dist/tether.extras.min.js +1 -1
  35. package/dist/tether.js +3653 -2116
  36. package/dist/tether.markets.js +238 -150
  37. package/dist/tether.markets.min.js +1 -1
  38. package/dist/tether.min.js +3 -3
  39. package/dist/tether.min.js.map +4 -4
  40. package/dist/tether.search.js +207 -136
  41. package/dist/tether.search.min.js +1 -1
  42. package/dist/types/server/src/shared/account-orders.d.ts +44 -0
  43. package/dist/types/server/src/shared/account-routes.d.ts +153 -0
  44. package/dist/types/server/src/shared/api-versions.d.ts +13 -0
  45. package/dist/types/server/src/shared/error-message.d.ts +2 -0
  46. package/dist/types/server/src/shared/json.d.ts +25 -0
  47. package/dist/types/server/src/shared/market-codes.d.ts +16 -0
  48. package/dist/types/src/account/addresses-view.d.ts +5 -0
  49. package/dist/types/src/account/answers.d.ts +40 -0
  50. package/dist/types/src/account/markup.d.ts +19 -0
  51. package/dist/types/src/account/operations.d.ts +41 -0
  52. package/dist/types/src/account/order-lines.d.ts +13 -0
  53. package/dist/types/src/account/order-list.d.ts +12 -0
  54. package/dist/types/src/account/order-page.d.ts +6 -0
  55. package/dist/types/src/account/page-answers.d.ts +182 -0
  56. package/dist/types/src/account/page-events.d.ts +2 -0
  57. package/dist/types/src/account/server-client.d.ts +60 -0
  58. package/dist/types/src/account/subscriptions-view.d.ts +2 -0
  59. package/dist/types/src/account-api.d.ts +18 -0
  60. package/dist/types/src/account-marks.d.ts +15 -0
  61. package/dist/types/src/account-pages.d.ts +8 -0
  62. package/dist/types/src/account.d.ts +64 -0
  63. package/dist/types/src/amounts.d.ts +12 -0
  64. package/dist/types/src/analytics-shopify.d.ts +41 -0
  65. package/dist/types/src/analytics.d.ts +2 -0
  66. package/dist/types/src/api-version.d.ts +28 -0
  67. package/dist/types/src/astro.d.ts +42 -0
  68. package/dist/types/src/cart/cart-shape.d.ts +43 -0
  69. package/dist/types/src/cart/checkout.d.ts +16 -0
  70. package/dist/types/src/cart/drawer.d.ts +18 -0
  71. package/dist/types/src/cart/mutations.d.ts +79 -0
  72. package/dist/types/src/cart/render.d.ts +17 -0
  73. package/dist/types/src/cart/store.d.ts +182 -0
  74. package/dist/types/src/cart.d.ts +106 -0
  75. package/dist/types/src/client.d.ts +100 -0
  76. package/dist/types/src/collection.d.ts +25 -0
  77. package/dist/types/src/config-sections.d.ts +40 -0
  78. package/dist/types/src/config.d.ts +185 -0
  79. package/dist/types/src/controls/cart-controls.d.ts +2 -0
  80. package/dist/types/src/controls/discount.d.ts +2 -0
  81. package/dist/types/src/controls/extras.d.ts +5 -0
  82. package/dist/types/src/controls/navigation.d.ts +12 -0
  83. package/dist/types/src/diagnose-markup.d.ts +19 -0
  84. package/dist/types/src/diagnose.d.ts +60 -0
  85. package/dist/types/src/dom.d.ts +75 -0
  86. package/dist/types/src/extras.d.ts +21 -0
  87. package/dist/types/src/fragments.d.ts +158 -0
  88. package/dist/types/src/globals.d.ts +15 -0
  89. package/dist/types/src/images.d.ts +20 -0
  90. package/dist/types/src/index.d.ts +167 -0
  91. package/dist/types/src/initial.d.ts +56 -0
  92. package/dist/types/src/lazy.d.ts +28 -0
  93. package/dist/types/src/loader.d.ts +84 -0
  94. package/dist/types/src/market-codes.d.ts +6 -0
  95. package/dist/types/src/markets-ui.d.ts +32 -0
  96. package/dist/types/src/markets.d.ts +72 -0
  97. package/dist/types/src/markup.d.ts +131 -0
  98. package/dist/types/src/mounting.d.ts +46 -0
  99. package/dist/types/src/page-market.d.ts +27 -0
  100. package/dist/types/src/presets/barba.d.ts +56 -0
  101. package/dist/types/src/product-events.d.ts +2 -0
  102. package/dist/types/src/product-render.d.ts +17 -0
  103. package/dist/types/src/product-shape.d.ts +88 -0
  104. package/dist/types/src/product-state.d.ts +110 -0
  105. package/dist/types/src/product.d.ts +66 -0
  106. package/dist/types/src/repeaters.d.ts +16 -0
  107. package/dist/types/src/search.d.ts +33 -0
  108. package/dist/types/src/selling-plans.d.ts +64 -0
  109. package/dist/types/src/server.d.ts +88 -0
  110. package/dist/types/src/shopify-values.d.ts +46 -0
  111. package/dist/types/src/status.d.ts +33 -0
  112. package/dist/types/src/storage.d.ts +12 -0
  113. package/dist/types/src/store-html.d.ts +39 -0
  114. package/dist/types/src/storefront/catalog.d.ts +38 -0
  115. package/dist/types/src/storefront/json-ld.d.ts +20 -0
  116. package/dist/types/src/variant-render.d.ts +14 -0
  117. package/package.json +42 -22
  118. package/src/account/addresses-view.ts +58 -0
  119. package/src/account/answers.ts +79 -0
  120. package/src/account/markup.ts +36 -0
  121. package/src/account/operations.ts +145 -0
  122. package/src/account/order-lines.ts +75 -0
  123. package/src/account/order-list.ts +107 -0
  124. package/src/account/order-page.ts +137 -0
  125. package/src/account/page-answers.ts +317 -0
  126. package/src/account/page-events.ts +253 -0
  127. package/src/account/server-client.ts +183 -0
  128. package/src/account/subscriptions-view.ts +115 -0
  129. package/src/account-api.ts +98 -0
  130. package/src/account-marks.ts +35 -0
  131. package/src/account-pages.ts +81 -0
  132. package/src/account.ts +284 -0
  133. package/src/amounts.ts +64 -0
  134. package/src/analytics-shopify.ts +246 -0
  135. package/src/analytics.ts +315 -0
  136. package/src/api-version.ts +79 -0
  137. package/src/astro.ts +272 -0
  138. package/src/cart/cart-shape.ts +25 -0
  139. package/src/cart/checkout.ts +101 -0
  140. package/src/cart/drawer.ts +125 -0
  141. package/src/cart/mutations.ts +237 -0
  142. package/src/cart/render.ts +266 -0
  143. package/src/cart/store.ts +279 -0
  144. package/src/cart.ts +345 -0
  145. package/src/client.ts +391 -0
  146. package/src/collection.ts +175 -0
  147. package/src/config-sections.ts +284 -0
  148. package/src/config.ts +480 -0
  149. package/src/controls/cart-controls.ts +123 -0
  150. package/src/controls/discount.ts +75 -0
  151. package/src/controls/extras.ts +54 -0
  152. package/src/controls/navigation.ts +77 -0
  153. package/src/diagnose-markup.ts +298 -0
  154. package/src/diagnose.ts +294 -0
  155. package/src/dom.ts +268 -0
  156. package/src/extras.ts +136 -0
  157. package/src/fragments.ts +261 -0
  158. package/src/globals.d.ts +15 -0
  159. package/src/images.ts +91 -0
  160. package/src/index.ts +415 -0
  161. package/src/initial.ts +101 -0
  162. package/src/lazy-iife.ts +197 -0
  163. package/src/lazy.ts +42 -0
  164. package/src/loader.ts +363 -0
  165. package/src/market-codes.ts +6 -0
  166. package/src/markets-ui.ts +227 -0
  167. package/src/markets.ts +246 -0
  168. package/src/markup.ts +127 -0
  169. package/src/mounting.ts +264 -0
  170. package/src/page-market.ts +110 -0
  171. package/src/part-integrity.ts +7 -0
  172. package/src/parts/account-pages.ts +7 -0
  173. package/src/parts/account.ts +7 -0
  174. package/src/parts/analytics.ts +7 -0
  175. package/src/parts/diagnose.ts +7 -0
  176. package/src/parts/extras.ts +7 -0
  177. package/src/parts/markets.ts +7 -0
  178. package/src/parts/search.ts +7 -0
  179. package/src/presets/barba.ts +194 -0
  180. package/src/product-events.ts +115 -0
  181. package/src/product-render.ts +218 -0
  182. package/src/product-shape.ts +49 -0
  183. package/src/product-state.ts +318 -0
  184. package/src/product.ts +308 -0
  185. package/src/repeaters.ts +161 -0
  186. package/src/search.ts +305 -0
  187. package/src/selling-plans.ts +145 -0
  188. package/src/server.ts +211 -0
  189. package/src/shopify-values.ts +91 -0
  190. package/src/status.ts +106 -0
  191. package/src/storage.ts +34 -0
  192. package/src/store-html.ts +359 -0
  193. package/src/storefront/catalog.ts +196 -0
  194. package/src/storefront/json-ld.ts +144 -0
  195. package/src/variant-render.ts +139 -0
  196. package/dist/esm/chunks/account-Q6E2TFEV.js +0 -1
  197. package/dist/esm/chunks/account-pages-UZXR4R5F.js +0 -1
  198. package/dist/esm/chunks/analytics-IJBKATUP.js +0 -1
  199. package/dist/esm/chunks/chunk-4QJKLPYR.js +0 -1
  200. package/dist/esm/chunks/chunk-64TUD3QR.js +0 -1
  201. package/dist/esm/chunks/chunk-AJLPU2JC.js +0 -4
  202. package/dist/esm/chunks/chunk-FIOZPPC5.js +0 -1
  203. package/dist/esm/chunks/chunk-K2YEQAIH.js +0 -1
  204. package/dist/esm/chunks/chunk-KIDH76B7.js +0 -1
  205. package/dist/esm/chunks/chunk-PAYT5ZD7.js +0 -1
  206. package/dist/esm/chunks/chunk-RREHGH4A.js +0 -1
  207. package/dist/esm/chunks/chunk-SSJT43CJ.js +0 -1
  208. package/dist/esm/chunks/chunk-VC46IEJQ.js +0 -1
  209. package/dist/esm/chunks/diagnose-3WVAWNTX.js +0 -14
  210. package/dist/esm/chunks/extras-7I7WJX35.js +0 -1
  211. package/dist/esm/chunks/markets-ui-545XLFTE.js +0 -1
  212. package/dist/esm/chunks/search-NILMGYXG.js +0 -1
  213. package/src/account-pages.js +0 -318
  214. package/src/account.js +0 -385
  215. package/src/analytics.js +0 -232
  216. package/src/api-version.js +0 -35
  217. package/src/astro.js +0 -101
  218. package/src/cart.js +0 -559
  219. package/src/client.js +0 -131
  220. package/src/collection.js +0 -114
  221. package/src/config.js +0 -85
  222. package/src/diagnose.js +0 -246
  223. package/src/dom.js +0 -288
  224. package/src/extras.js +0 -63
  225. package/src/fragments.js +0 -144
  226. package/src/index.js +0 -395
  227. package/src/initial.js +0 -75
  228. package/src/lazy-iife.js +0 -46
  229. package/src/lazy.js +0 -18
  230. package/src/loader.js +0 -198
  231. package/src/markets-ui.js +0 -90
  232. package/src/markets.js +0 -133
  233. package/src/mounting.js +0 -154
  234. package/src/parts/account-pages.js +0 -3
  235. package/src/parts/account.js +0 -3
  236. package/src/parts/analytics.js +0 -3
  237. package/src/parts/diagnose.js +0 -3
  238. package/src/parts/extras.js +0 -3
  239. package/src/parts/markets.js +0 -3
  240. package/src/parts/search.js +0 -3
  241. package/src/presets/barba.js +0 -100
  242. package/src/product.js +0 -570
  243. package/src/search.js +0 -153
  244. package/src/selling-plans.js +0 -94
  245. package/src/server.js +0 -252
  246. package/src/status.js +0 -66
  247. package/types/astro.d.ts +0 -17
  248. package/types/barba.d.ts +0 -16
  249. package/types/index.d.ts +0 -426
  250. package/types/server.d.ts +0 -110
package/types/index.d.ts DELETED
@@ -1,426 +0,0 @@
1
- // Type definitions for @occluze/tether
2
- // Shopify Storefront API objects are typed loosely (`ShopifyProduct` etc.): Tether passes them
3
- // through as Shopify returns them. See https://shopify.dev/docs/api/storefront for the full shape.
4
-
5
- export interface Money { amount: string; currencyCode: string }
6
- export interface ShopifyImage { url: string; altText?: string | null; width?: number; height?: number }
7
-
8
- export interface ShopifySellingPlan {
9
- id: string;
10
- name: string;
11
- description?: string | null;
12
- recurringDeliveries?: boolean;
13
- options: { name: string; value: string }[];
14
- priceAdjustments: unknown[];
15
- /** Added by Tether: the plan's group. */
16
- group?: { name: string; [k: string]: unknown };
17
- }
18
-
19
- export interface ShopifyVariant {
20
- id: string;
21
- title: string;
22
- availableForSale: boolean;
23
- currentlyNotInStock?: boolean;
24
- quantityAvailable?: number | null;
25
- sku?: string | null;
26
- barcode?: string | null;
27
- selectedOptions: { name: string; value: string }[];
28
- image?: ShopifyImage | null;
29
- price: Money;
30
- compareAtPrice?: Money | null;
31
- unitPrice?: Money | null;
32
- sellingPlanAllocations?: { nodes: unknown[] };
33
- [k: string]: unknown;
34
- }
35
-
36
- export interface ShopifyProduct {
37
- id: string;
38
- handle: string;
39
- title: string;
40
- description: string;
41
- descriptionHtml: string;
42
- productType?: string;
43
- vendor?: string;
44
- tags: string[];
45
- availableForSale: boolean;
46
- requiresSellingPlan?: boolean;
47
- featuredImage?: ShopifyImage | null;
48
- images: { nodes: ShopifyImage[] };
49
- priceRange: { minVariantPrice: Money; maxVariantPrice: Money };
50
- options: { name: string; optionValues: { name: string; swatch?: unknown }[] }[];
51
- variants: { nodes: ShopifyVariant[] };
52
- sellingPlanGroups?: { nodes: unknown[] };
53
- metafields?: ({ namespace: string; key: string; type: string; value: string; reference?: unknown } | null)[];
54
- seo?: { title?: string | null; description?: string | null };
55
- onlineStoreUrl?: string | null;
56
- [k: string]: unknown;
57
- }
58
-
59
- export interface ShopifyCartLine {
60
- id: string;
61
- quantity: number;
62
- merchandise: ShopifyVariant & { product: Pick<ShopifyProduct, 'id' | 'handle' | 'title'> & Record<string, unknown> };
63
- sellingPlanAllocation?: { sellingPlan: { id: string; name: string } } | null;
64
- attributes?: { key: string; value: string }[];
65
- cost: { totalAmount: Money; subtotalAmount: Money; amountPerQuantity: Money; compareAtAmountPerQuantity?: Money | null };
66
- [k: string]: unknown;
67
- }
68
-
69
- export interface ShopifyCart {
70
- id: string;
71
- checkoutUrl: string;
72
- totalQuantity: number;
73
- note?: string | null;
74
- lines: { nodes: ShopifyCartLine[] };
75
- cost: Record<string, Money | null | undefined>;
76
- discountCodes: { code: string; applicable: boolean }[];
77
- attributes: { key: string; value: string }[];
78
- buyerIdentity?: { countryCode?: string | null; email?: string | null };
79
- [k: string]: unknown;
80
- }
81
-
82
- export interface MarketsConfig {
83
- /** true: saved choice, server hints, Webflow Localization. Or a list of those sources. false: off. */
84
- detect?: boolean | ('saved' | 'server' | 'webflow')[];
85
- /** Webflow locale (subdirectory or html lang) -> market. */
86
- locales?: Record<string, { country?: string; language?: string; locale?: string }>;
87
- /** Cookie with the visitor's country, set by your server (default "tether_country"). */
88
- cookie?: string;
89
- /** Remember the visitor's country choice (default true). */
90
- remember?: boolean;
91
- /** With locales: ignore an html lang that isn't in the map. */
92
- strict?: boolean;
93
- }
94
-
95
- export interface TetherConfig {
96
- /** your-store.myshopify.com */
97
- domain: string;
98
- /** Public Storefront API access token (never an Admin token). */
99
- token: string;
100
- /** Pinned Shopify API version, e.g. "2026-07". Never "unstable". */
101
- apiVersion?: string;
102
- /** ISO country code for prices and currency, e.g. "NL". */
103
- country?: string;
104
- /** Language for translated content, e.g. "NL". */
105
- language?: string;
106
- /** Intl locale for money and dates, e.g. "nl-NL". */
107
- locale?: string;
108
- markets?: MarketsConfig | null;
109
- /** Attribute prefix (default "tether"). */
110
- prefix?: string;
111
- /** Product URL template: "/product" or "/product?handle={handle}" ({handle}, {id}). */
112
- productPath?: string;
113
- collectionPath?: string;
114
- /** Metafields to fetch: "namespace.key" or { namespace, key }. */
115
- metafields?: (string | { namespace: string; key: string })[];
116
- imagesFirst?: number;
117
- variantsFirst?: number;
118
- sellingPlanGroupsFirst?: number;
119
- sellingPlansFirst?: number;
120
- collectionFirst?: number;
121
- retries?: number;
122
- /** Products handed over by the server (tether/server hydrate()): refresh once in the background (default true). */
123
- revalidate?: boolean;
124
- /** Seconds a Shopify answer may be cached (default 60). Shopify caches identical queries, prices included, for hours otherwise; 0 = Shopify's caching. */
125
- maxAge?: number;
126
- /** Analytics (optional part): GA4/GTM dataLayer events, Shopify's analytics (experimental), or your own handler. */
127
- analytics?: {
128
- dataLayer?: boolean | string;
129
- shopify?: boolean | { consent?: 'no-banner' | 'default-banner' | 'custom-banner'; proxy?: string };
130
- onEvent?: (name: string, data: Record<string, unknown>) => void;
131
- } | null;
132
- /** Customer accounts (optional part): the Headless channel's Customer Account API client id, and options. */
133
- account?: {
134
- /** Browser mode: the Customer Account API client id. */
135
- clientId?: string;
136
- /** Server mode (recommended): the Worker's account routes, a URL or a path on this site ('/_tether/account'). */
137
- server?: string;
138
- /** Your own order page: tether-order-bind="url" links there, e.g. '/account/order?id={id}' (else Shopify's status page). */
139
- orderUrl?: string;
140
- /** Shopify's subscription management page (tether-account-link="subscriptions"); payment methods are changed there too. */
141
- subscriptionsUrl?: string;
142
- /** A separate page for payment methods (tether-account-link="payment"); default subscriptionsUrl. */
143
- paymentUrl?: string;
144
- /** The page Shopify sends the visitor back to after login (registered as callback URI). Default: the current page. */
145
- callbackUrl?: string;
146
- /** Where Shopify sends the visitor after logout (registered as logout URI). Default: the home page. */
147
- logoutUrl?: string;
148
- /** Keep the login across tabs and browser restarts (localStorage instead of sessionStorage). */
149
- remember?: boolean;
150
- /** Your own token endpoint, if the browser can't call Shopify's (it forwards the form body). */
151
- tokenUrl?: string;
152
- /** The *.myshopify.com domain, if domain is something else. */
153
- shopDomain?: string;
154
- locale?: string;
155
- } | null;
156
- /** tether-show="low-stock" at this many or fewer (default 5). */
157
- lowStock?: number;
158
- /** true: ?variant= (and selling_plan=) follow the visitor's choice on the page's main product. */
159
- variantUrl?: boolean;
160
- /** Your text for Shopify's cart warnings (stock, codes), e.g. translated by code. Return nothing to keep Shopify's. */
161
- warningText?: ((warning: CartWarning) => string | null | undefined) | null;
162
- /** Mount on Astro View Transitions (astro:page-load) and close the cart on navigation (default true). */
163
- astro?: boolean;
164
- storageKey?: string | null;
165
- cartDrawerOpenClass?: string;
166
- openCartOnAdd?: boolean;
167
- /** Move focus into the open cart, keep Tab inside it, restore it on close (default true). */
168
- cartFocus?: boolean;
169
- checkoutTarget?: '_self' | '_blank';
170
- defaultPurchase?: 'one-time' | 'subscription';
171
- /** Mount the document on DOMContentLoaded (default true). False with page transitions. */
172
- autoMount?: boolean;
173
- /** Mount elements added later (CMS load more, filters). */
174
- observe?: boolean;
175
- /** Folder of the optional parts (tether.markets.min.js, tether.diagnose.min.js) for the <script> build. */
176
- partsUrl?: string | null;
177
- formatMoney?: ((money: Money, locale?: string) => string) | null;
178
- onLayoutChange?: ((reason: string) => void) | null;
179
- onCartOpen?: ((drawers: HTMLElement[]) => void) | null;
180
- onCartClose?: ((drawers: HTMLElement[]) => void) | null;
181
- onLineEnter?: ((node: HTMLElement) => void) | null;
182
- onLineLeave?: ((node: HTMLElement, done: () => void) => void) | null;
183
- onValueChange?: ((el: HTMLElement, previousText: string) => void) | null;
184
- /** Every failure that reaches the visitor. Send it to Sentry or similar. */
185
- onError?: ((error: TetherError | Error, context: string) => void) | null;
186
- debug?: boolean;
187
- }
188
-
189
- export type TetherErrorCode = 'NOT_FOUND' | 'NETWORK' | 'NOT_CONFIGURED' | 'INVALID_COUNTRY' | 'ERROR' | `HTTP_${number}`;
190
-
191
- export declare class TetherError extends Error {
192
- name: 'TetherError';
193
- code: TetherErrorCode | string;
194
- status?: number;
195
- errors?: { message: string; extensions?: Record<string, unknown> }[];
196
- userErrors?: { field?: string[]; message: string }[];
197
- constructor(message: string, opts?: { status?: number; errors?: unknown[]; userErrors?: unknown[]; code?: string });
198
- }
199
-
200
- export type Attributes = Record<string, string | number | boolean> | { key: string; value: string }[];
201
-
202
- export interface LineInput {
203
- variantId?: string;
204
- merchandiseId?: string;
205
- quantity?: number;
206
- sellingPlanId?: string | null;
207
- attributes?: Attributes;
208
- }
209
-
210
- /** Shopify's note on the last cart change; target is the cart line id it's about. */
211
- export interface CartWarning { code: string; message: string; target?: string }
212
-
213
- export interface Cart {
214
- readonly state: ShopifyCart | null;
215
- readonly lines: ShopifyCartLine[];
216
- readonly count: number;
217
- lastError: Error | null;
218
- /** Shopify's notes on the last change, e.g. less stock than asked (code MERCHANDISE_NOT_ENOUGH_STOCK). */
219
- readonly warnings: CartWarning[];
220
- /** true once the saved cart (or the absence of one) is known. */
221
- readonly loaded: boolean;
222
- id(): string | null;
223
- init(): Promise<ShopifyCart | null>;
224
- /** add(variantId, qty) · add({ variantId, quantity, sellingPlanId, attributes }) · add([line, line]) */
225
- add(input: string | LineInput | LineInput[], quantity?: number, opts?: Omit<LineInput, 'variantId' | 'quantity'>): Promise<ShopifyCart>;
226
- /** updateLine(id, 3) · updateLine(id, { sellingPlanId: null }) switches to one-time. */
227
- updateLine(lineId: string, patch: number | (LineInput & { quantity?: number })): Promise<ShopifyCart>;
228
- removeLine(lineIds: string | string[]): Promise<ShopifyCart>;
229
- /** +1 / -1 for a line; quick clicks add up and show at once (use it for your own +/- buttons). */
230
- changeQuantity(lineId: string, delta: number): Promise<ShopifyCart | null>;
231
- /** The quantity to show for a line: what the visitor asked for while an update is on its way. */
232
- quantityOf(line: ShopifyCartLine): number;
233
- clear(): Promise<ShopifyCart | null>;
234
- setNote(note: string): Promise<ShopifyCart>;
235
- setAttributes(attributes: Attributes): Promise<ShopifyCart>;
236
- setDiscountCodes(codes: string[]): Promise<ShopifyCart>;
237
- /** Rejects with code INVALID_DISCOUNT (and doesn't keep the code) when Shopify doesn't accept it. */
238
- applyDiscount(code: string): Promise<ShopifyCart>;
239
- removeDiscount(code: string): Promise<ShopifyCart>;
240
- setBuyerIdentity(identity: { countryCode?: string; email?: string; phone?: string }, opts?: { create?: boolean }): Promise<ShopifyCart | null>;
241
- checkout(target?: '_self' | '_blank'): Promise<void>;
242
- open(): void;
243
- close(): void;
244
- toggle(): void;
245
- isOpen(): boolean;
246
- drawers(): HTMLElement[];
247
- render(): void;
248
- /** For framework islands: fn(cart, meta) now, when the saved cart has loaded and after every change. Returns unsubscribe. */
249
- subscribe(fn: (cart: ShopifyCart | null, meta: { open: boolean; count: number; loaded: boolean; warnings: CartWarning[] }) => void): () => void;
250
- }
251
-
252
- export interface ProductScope {
253
- readonly root: HTMLElement;
254
- product: ShopifyProduct;
255
- variant: ShopifyVariant | null;
256
- selected: Record<string, string>;
257
- quantity: number;
258
- plans: ShopifySellingPlan[];
259
- purchase: 'one-time' | 'subscription';
260
- planId: string | null;
261
- readonly plan: ShopifySellingPlan | null;
262
- readonly isSubscription: boolean;
263
- readonly subscriptionAvailable: boolean;
264
- select(option: string, value: string): void;
265
- selectVariant(id: string): void;
266
- setPurchase(mode: 'one-time' | 'subscription'): void;
267
- selectPlan(ref: string): void;
268
- setQuantity(n: number | string): void;
269
- getLine(): LineInput | null;
270
- addToCart(): Promise<ShopifyCart | null>;
271
- update(product: ShopifyProduct): void;
272
- }
273
-
274
- export interface SellingPlanHelpers {
275
- allPlans(product: ShopifyProduct): ShopifySellingPlan[];
276
- hasPlans(product: ShopifyProduct): boolean;
277
- allocationFor(variant: ShopifyVariant, planId: string | null): unknown | null;
278
- plansForVariant(product: ShopifyProduct, variant: ShopifyVariant): ShopifySellingPlan[];
279
- planPrice(variant: ShopifyVariant, planId: string): Money | null;
280
- planCheckoutCharge(variant: ShopifyVariant, planId: string): Money | null;
281
- planSavings(variant: ShopifyVariant, planId: string): { amount: Money | null; percentage: number };
282
- planAdjustment(plan: ShopifySellingPlan | null | undefined): { type: 'percentage' | 'amount' | 'price'; value: number | Money } | null;
283
- findPlan(product: ShopifyProduct, ref: string | null | undefined): ShopifySellingPlan | null;
284
- toGid(value: string | number, type: string): string | null;
285
- GID: { product(v: string | number): string | null; variant(v: string | number): string | null; sellingPlan(v: string | number): string | null };
286
- }
287
-
288
- export interface ProductPage {
289
- collection: Record<string, unknown> | null;
290
- products: ShopifyProduct[];
291
- pageInfo: { hasNextPage: boolean; endCursor: string | null };
292
- }
293
-
294
- export interface Localization {
295
- country?: { isoCode: string; name: string; currency?: { isoCode: string; symbol: string } };
296
- language?: { isoCode: string; name: string };
297
- availableCountries: { isoCode: string; name: string; currency?: { isoCode: string; symbol: string }; availableLanguages?: { isoCode: string; name: string }[] }[];
298
- }
299
-
300
- export interface DiagnoseReport {
301
- version: string;
302
- config: Record<string, unknown>;
303
- apiVersion: { version: string; ok: boolean; monthsLeft?: number; next?: string; note: string };
304
- market: { country?: string; language?: string; locale?: string; sources: Record<string, string> } | null;
305
- reachable: boolean;
306
- shop: { name?: string; url?: string; currency?: string } | null;
307
- latencyMs: number | null;
308
- products: { key: string; handle?: string; title?: string; plans?: number; error?: string }[];
309
- sellingPlans: { product: string; group?: string; plan: string; id: string }[];
310
- problems: { level: 'error' | 'warn'; message: string; element?: string }[];
311
- }
312
-
313
- /** Events on document, as `tether:<name>` (or your prefix). Detail types for Tether.on(). */
314
- export interface TetherEvents {
315
- ready: { cart: ShopifyCart | null };
316
- 'product-ready': { product: ShopifyProduct; scope: ProductScope };
317
- 'product-updated': { product: ShopifyProduct; scope: ProductScope };
318
- 'product-not-found': { key: string | null; source: string };
319
- 'variant-changed': { product: ShopifyProduct; variant: ShopifyVariant; selected: Record<string, string>; purchase: 'one-time' | 'subscription'; sellingPlanId: string | null };
320
- 'product-added': { product: ShopifyProduct; variant: ShopifyVariant; line: LineInput };
321
- added: { cart: ShopifyCart; lines: LineInput[] };
322
- 'group-added': { group: string | null; lines: LineInput[] };
323
- 'cart-warning': { warnings: CartWarning[] };
324
- 'cart-updated': { cart: ShopifyCart | null; reason: string };
325
- 'cart-toggled': { open: boolean };
326
- 'cart-error': { error: Error };
327
- checkout: { url: string; cart: ShopifyCart };
328
- 'list-ready': { products: ShopifyProduct[]; collection: Record<string, unknown> | null };
329
- 'country-changed': { country: string; language?: string };
330
- 'discount-applied': { code: string };
331
- 'discount-invalid': { code: string };
332
- 'layout-changed': { reason: string };
333
- error: { error: Error; context: string; key?: string };
334
- }
335
-
336
- export interface Tether {
337
- readonly VERSION: string;
338
- /** Configure (window.TETHER_CONFIG + overrides) and load the cart. */
339
- init(overrides?: Partial<TetherConfig>): Promise<Tether | null>;
340
- /** Mount product scopes and lists inside root (call per page container with Barba/Swup). */
341
- mount(root?: ParentNode): number;
342
- /** Call before a page transition removes the page (closes the cart drawer). */
343
- unmount(): void;
344
- readonly config: TetherConfig;
345
- readonly ready: Promise<Tether | null>;
346
- /** Any Storefront API query, with @inContext added for the current market. */
347
- query<T = any>(query: string, variables?: Record<string, unknown>, opts?: { context?: boolean }): Promise<T>;
348
- withContext(query: string, ctx?: { country?: string; language?: string }): string;
349
- cart: Cart;
350
- getProduct(handleOrId: string): Promise<ShopifyProduct>;
351
- getProducts(opts?: { collection?: string; query?: string; first?: number; after?: string | null; sortKey?: string; reverse?: boolean; filters?: unknown[] }): Promise<ProductPage>;
352
- getRecommendations(product: string | Pick<ShopifyProduct, 'id'>, intent?: 'RELATED' | 'COMPLEMENTARY'): Promise<ShopifyProduct[]>;
353
- getScope(el: Element | null | undefined): ProductScope | null;
354
- addGroup(button: Element): Promise<ShopifyCart | null>;
355
- /** Customer accounts (loads the account part): login(), logout(), customer(), orders(), query(gql, vars), getToken(). */
356
- account: {
357
- login(opts?: { returnTo?: string; locale?: string }): Promise<void>;
358
- logout(opts?: { returnTo?: string }): Promise<void>;
359
- customer(): Promise<{ id: string; firstName?: string | null; lastName?: string | null; displayName?: string; emailAddress?: { emailAddress: string } | null } | null>;
360
- orders(opts?: { first?: number }): Promise<Array<{ id: string; name: string; processedAt: string; financialStatus?: string; fulfillmentStatus?: string; statusPageUrl: string; totalPrice: Money }>>;
361
- query<T = any>(query: string, variables?: Record<string, unknown>): Promise<T>;
362
- getToken(): Promise<string | null>;
363
- /** One order in full (lines, totals, addresses, fulfillments with tracking, returnable lines); null if not the customer's. */
364
- order(id: string | number): Promise<Record<string, any> | null>;
365
- updateProfile(fields: { firstName?: string; lastName?: string }): Promise<{ firstName?: string | null; lastName?: string | null }>;
366
- addresses(): Promise<Array<CustomerAddress & { isDefault: boolean }>>;
367
- saveAddress(address: Partial<CustomerAddressInput> | null, opts?: { id?: string; isDefault?: boolean }): Promise<CustomerAddress>;
368
- deleteAddress(id: string): Promise<string>;
369
- subscriptions(): Promise<Array<Record<string, any>>>;
370
- subscriptionAction(id: string | number, action: 'pause' | 'resume' | 'skip' | 'unskip' | 'cancel'): Promise<Record<string, any>>;
371
- requestReturn(orderId: string | number, lines: Array<{ lineItemId: string; quantity: number; reasonId?: string; note?: string }>): Promise<{ id: string; status: string }>;
372
- };
373
- primeProduct(product: ShopifyProduct): void;
374
- normalizeProductKey(raw: string | number): string | null;
375
- clearProductCache(): void;
376
- formatMoney(money: Money | null | undefined): string;
377
- /** Shopify CDN image at a size: imageUrl(line.merchandise.image?.url, { width: 160 }). */
378
- imageUrl(url: string | null | undefined, size?: { width?: number; height?: number; crop?: string }): string;
379
- plans: SellingPlanHelpers;
380
- TetherError: typeof TetherError;
381
- resolveProductKey(el: Element, location?: Location | URL): { key: string | null; fromUrl: boolean; raw: string };
382
- /** Switch market: prices, currency, cart and every product on the page follow. */
383
- setCountry(code: string, opts?: SetCountryOptions): Promise<ShopifyCart | null>;
384
- detectMarket(markets?: MarketsConfig): Promise<{ country?: string; language?: string; locale?: string; sources: Record<string, string> }>;
385
- getLocalization(): Promise<Localization>;
386
- /** Logs and returns what's wrong on this page (config, token, API version, plans, markup). */
387
- diagnose(opts?: { root?: ParentNode; silent?: boolean }): Promise<DiagnoseReport>;
388
- /** Listen to a Tether event; returns a function that stops listening. */
389
- on<K extends keyof TetherEvents>(name: K, fn: (detail: TetherEvents[K], event: CustomEvent<TetherEvents[K]>) => void): () => void;
390
- on(name: string, fn: (detail: any, event: CustomEvent) => void): () => void;
391
- }
392
-
393
- export declare const VERSION: string;
394
- export declare function init(overrides?: Partial<TetherConfig>): Promise<Tether | null>;
395
- export declare function mount(root?: ParentNode): number;
396
- export declare function unmount(): void;
397
- export declare function getScope(el: Element | null | undefined): ProductScope | null;
398
- export declare function addGroup(button: Element): Promise<ShopifyCart | null>;
399
- export interface SetCountryOptions {
400
- /** Shopify language (translations); null clears it. Default: the markets.locales entry for that country, else unchanged. */
401
- language?: string | null;
402
- /** Money format, e.g. 'de-DE'. Default: the markets.locales entry for that country, else unchanged. */
403
- locale?: string;
404
- remember?: boolean;
405
- }
406
- export declare function setCountry(code: string, opts?: SetCountryOptions): Promise<ShopifyCart | null>;
407
- export declare const api: Tether;
408
- declare const tether: Tether;
409
- export default tether;
410
-
411
- declare global {
412
- interface Window {
413
- Tether: Tether;
414
- TETHER_CONFIG?: Partial<TetherConfig>;
415
- TETHER_COUNTRY?: string;
416
- TETHER_LANGUAGE?: string;
417
- }
418
- }
419
-
420
- export interface CustomerAddressInput {
421
- firstName: string; lastName: string; company: string; address1: string; address2: string;
422
- city: string; zip: string; zoneCode: string; countryCode: string; phoneNumber: string;
423
- }
424
- export interface CustomerAddress extends Partial<CustomerAddressInput> {
425
- id: string; province?: string | null; country?: string | null; formatted: string[];
426
- }
package/types/server.d.ts DELETED
@@ -1,110 +0,0 @@
1
- import type { ShopifyProduct, ShopifyVariant, Money, TetherError, SellingPlanHelpers, TetherConfig } from './index.js';
2
- export type { ShopifyProduct, ShopifyVariant, ShopifyCart, ShopifyCartLine, Money } from './index.js';
3
-
4
- export interface StorefrontOptions extends Partial<Pick<TetherConfig,
5
- 'apiVersion' | 'country' | 'language' | 'locale' | 'productPath' | 'maxAge' | 'lowStock' | 'defaultPurchase' | 'metafields' | 'imagesFirst' | 'variantsFirst' | 'sellingPlanGroupsFirst' | 'sellingPlansFirst' | 'retries'>> {
6
- /** your-store.myshopify.com (or pass import.meta.env with PUBLIC_SHOPIFY_DOMAIN). */
7
- domain?: string;
8
- /** Public Storefront API token (or PUBLIC_SHOPIFY_STOREFRONT_TOKEN in import.meta.env). */
9
- token?: string;
10
- /** Your site's address, e.g. https://shop.example: product URLs in jsonLd() without passing url. */
11
- siteUrl?: string;
12
- /** Products per request for allProducts() (default 25). */
13
- pageSize?: number;
14
- /** Custom fetch (tests, caching). */
15
- fetch?: typeof fetch;
16
- PUBLIC_SHOPIFY_DOMAIN?: string;
17
- PUBLIC_SHOPIFY_STOREFRONT_TOKEN?: string;
18
- /** Astro's import.meta.env carries these too; ignored. */
19
- MODE?: string; BASE_URL?: string; PROD?: boolean; DEV?: boolean; SSR?: boolean; SITE?: string; ASSETS_PREFIX?: string;
20
- }
21
-
22
- export interface ShopifyCollection {
23
- id: string; handle: string; title: string; description: string; descriptionHtml: string;
24
- image?: { url: string; altText?: string | null } | null;
25
- seo?: { title?: string | null; description?: string | null };
26
- }
27
-
28
- export interface ProductQuery {
29
- collection?: string;
30
- /** A Shopify search query; null or '' = every product (e.g. searchParams.get('q')). */
31
- query?: string | null;
32
- first?: number;
33
- after?: string | null;
34
- sortKey?: string;
35
- reverse?: boolean;
36
- filters?: unknown[];
37
- }
38
-
39
- export interface Storefront {
40
- readonly config: Required<Pick<StorefrontOptions, 'domain' | 'token'>> & StorefrontOptions;
41
- query<T = any>(query: string, variables?: Record<string, unknown>, opts?: { context?: boolean }): Promise<T>;
42
- /** By handle, numeric id, gid or product URL. null when it doesn't exist. */
43
- getProduct(handleOrId: string | number | null | undefined): Promise<ShopifyProduct | null>;
44
- getProducts(opts?: ProductQuery): Promise<{ collection: ShopifyCollection | null; products: ShopifyProduct[]; pageInfo: { hasNextPage: boolean; endCursor: string | null } }>;
45
- /** Every product (of a collection or a search query), page by page. For getStaticPaths(). */
46
- allProducts(opts?: Omit<ProductQuery, 'first' | 'after'>): Promise<ShopifyProduct[]>;
47
- getCollection(handle: string, opts?: Omit<ProductQuery, 'collection'>): Promise<(ShopifyCollection & { products: ShopifyProduct[]; pageInfo: { hasNextPage: boolean; endCursor: string | null } }) | null>;
48
- allCollections(): Promise<ShopifyCollection[]>;
49
- /** By handle, id or product (runs in parallel with getProduct when you pass the handle). */
50
- getRecommendations(product: string | number | Pick<ShopifyProduct, 'id'>, intent?: 'RELATED' | 'COMPLEMENTARY'): Promise<ShopifyProduct[]>;
51
- /**
52
- * A <script type="application/json" data-tether-hydrate> tag: the browser script renders these
53
- * products without its own request, then refreshes prices and stock once in the background.
54
- * Astro: <Fragment set:html={shop.hydrate(product)} />
55
- */
56
- hydrate(products: ShopifyProduct | ShopifyProduct[], opts?: {
57
- /** For lists: without descriptions and variant images, about 40% smaller. */
58
- card?: boolean;
59
- /** Images a card keeps (default 2: the main one and a hover image). */
60
- images?: number;
61
- }): string;
62
- formatMoney(money: Money | null | undefined, locale?: string): string;
63
- /** 30 -> '30%' (nl, en) / '30 %' (de, fr), the way Tether shows savings. '' for 0. */
64
- formatPercent(n: number, locale?: string): string;
65
- productUrl(handle: string, opts?: { productPath?: string; id?: string }): string;
66
- /** Shopify CDN image at a size. Use the element's max-width value, so the browser keeps the image. */
67
- imageUrl(url: string | null | undefined, size?: ImageSize): string;
68
- /**
69
- * What Tether shows first for this product (variant, price, purchase mode, tether-show conditions),
70
- * so the server renders the same and nothing flashes. Pass Astro.url.searchParams.get('variant') in SSR.
71
- */
72
- initialState(product: ShopifyProduct, opts?: InitialOptions): InitialState;
73
- initialState(product: ShopifyProduct | null | undefined, opts?: InitialOptions): InitialState | null;
74
- /** schema.org Product / ProductGroup data for search engines, as a <script type="application/ld+json"> tag. */
75
- jsonLd(product: ShopifyProduct | null, opts?: { url?: string; brand?: string }): string;
76
- jsonLdData(product: ShopifyProduct | null, opts?: { url?: string; brand?: string }): Record<string, unknown> | null;
77
- plans: SellingPlanHelpers;
78
- }
79
-
80
- export interface InitialState {
81
- variant: ShopifyVariant;
82
- /** option name -> value of that variant: is-selected on those buttons. */
83
- selected: Record<string, string>;
84
- purchase: 'one-time' | 'subscription';
85
- plan: { id: string; name: string } | null;
86
- plans: { id: string; name: string; price: Money; savings: number; selected: boolean; available: boolean }[];
87
- savings: number;
88
- /** The price Tether shows first (the plan price for products that require a subscription). */
89
- price: Money;
90
- /** Set only when on sale. */
91
- compareAtPrice: Money | null;
92
- available: boolean;
93
- /** tether-show conditions: hidden={!state.show['out-of-stock']}. */
94
- show: Record<'in-stock' | 'out-of-stock' | 'backorder' | 'on-sale' | 'not-on-sale' | 'has-variants' | 'single-variant' | 'low-stock' | 'subscription-available' | 'subscription-unavailable' | 'subscription-only' | 'one-time-available' | 'subscription-selected' | 'one-time-selected' | 'plenty-in-stock' | 'has-savings', boolean>;
95
- /** true for option values without an available variant: class is-unavailable. */
96
- isUnavailable(optionName: string, value: string): boolean;
97
- }
98
- export interface InitialOptions { variant?: string | null; sellingPlan?: string | null; defaultPurchase?: 'one-time' | 'subscription' }
99
- export declare function initialState(product: ShopifyProduct, opts?: InitialOptions): InitialState;
100
- export declare function initialState(product: ShopifyProduct | null | undefined, opts?: InitialOptions): InitialState | null;
101
-
102
- export interface ImageSize { width?: number; height?: number; crop?: 'center' | 'top' | 'bottom' | 'left' | 'right' }
103
- export declare function imageUrl(url: string | null | undefined, size?: ImageSize): string;
104
- export declare function createStorefront(options?: StorefrontOptions): Storefront;
105
- export declare function formatMoney(money: Money | null | undefined, locale?: string): string;
106
- export declare function productUrl(handle: string, opts?: { productPath?: string; id?: string }): string;
107
- export declare function productKey(raw: string | number): string | null;
108
- export declare function withContext(query: string, ctx?: { country?: string; language?: string }): string;
109
- export declare const plans: SellingPlanHelpers;
110
- export { TetherError };