@magicstoreai/hydrogen 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CATALOGUE.md +931 -0
- package/LICENSE +21 -0
- package/README.md +100 -0
- package/dist/core.cjs +746 -0
- package/dist/core.cjs.map +1 -0
- package/dist/core.d.cts +252 -0
- package/dist/core.d.ts +252 -0
- package/dist/core.js +706 -0
- package/dist/core.js.map +1 -0
- package/dist/index.cjs +1046 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +790 -0
- package/dist/index.d.ts +790 -0
- package/dist/index.js +1000 -0
- package/dist/index.js.map +1 -0
- package/dist/seo.cjs +101 -0
- package/dist/seo.cjs.map +1 -0
- package/dist/seo.d.cts +83 -0
- package/dist/seo.d.ts +83 -0
- package/dist/seo.js +73 -0
- package/dist/seo.js.map +1 -0
- package/dist/server.cjs +172 -0
- package/dist/server.cjs.map +1 -0
- package/dist/server.d.cts +67 -0
- package/dist/server.d.ts +67 -0
- package/dist/server.js +139 -0
- package/dist/server.js.map +1 -0
- package/package.json +64 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 MagicStore
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# @magicstoreai/hydrogen
|
|
2
|
+
|
|
3
|
+
React building blocks for MagicStore storefronts, on top of
|
|
4
|
+
[`@magicstoreai/storefront-client`](../storefront-client). The backend is the same for every
|
|
5
|
+
storefront; this package is the part every storefront would otherwise write again.
|
|
6
|
+
|
|
7
|
+
| Entry | What | Runs |
|
|
8
|
+
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------- |
|
|
9
|
+
| `@magicstoreai/hydrogen` | `MagicStoreProvider`, `useCustomer`, `useCart`, `useWishlist`, `useAnalytics`, `useVariantSelection`, `ProductProvider`, `<Money>`, `<Image>`, `<Pagination>` | client (`"use client"`) |
|
|
10
|
+
| `@magicstoreai/hydrogen/core` | The same logic without React: `CartController`, `CustomerSessionController`, `WishlistController`, `AnalyticsController`, `formatMoney`, variant selection | anywhere |
|
|
11
|
+
| `@magicstoreai/hydrogen/server` | `createWebhookHandler`, `verifyWebhookSignature`, `nextCacheFetch`, cache tags | server, edge |
|
|
12
|
+
| `@magicstoreai/hydrogen/seo` | `pageMeta`, `productJsonLd`, `breadcrumbJsonLd`, `jsonLdScript` | anywhere |
|
|
13
|
+
|
|
14
|
+
Every export with its props or signature, an example and the API operations it calls:
|
|
15
|
+
[CATALOGUE.md](CATALOGUE.md) — generated from the sources (`pnpm --filter @magicstoreai/hydrogen
|
|
16
|
+
catalogue`) and shipped in the package. A test fails when it is stale or a component or hook has no
|
|
17
|
+
`@example` in its TSDoc; `@wraps Controller` gives a hook its controller's operations.
|
|
18
|
+
|
|
19
|
+
## A storefront in a few lines
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
'use client';
|
|
23
|
+
import { MagicStoreProvider, Money, useCart, useVariantSelection } from '@magicstoreai/hydrogen';
|
|
24
|
+
|
|
25
|
+
export function Providers({ shop, children }) {
|
|
26
|
+
return (
|
|
27
|
+
<MagicStoreProvider shopDomain="shop.example.uz" shop={shop} locale="uz">
|
|
28
|
+
{children}
|
|
29
|
+
</MagicStoreProvider>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function BuyBox({ product }) {
|
|
34
|
+
const { selectedVariant, setOption, isAvailable } = useVariantSelection(product);
|
|
35
|
+
const { addLine, status } = useCart();
|
|
36
|
+
return (
|
|
37
|
+
<>
|
|
38
|
+
<Money data={selectedVariant?.price ?? product.price} />
|
|
39
|
+
{product.options.map((option) =>
|
|
40
|
+
option.values.map((value) => (
|
|
41
|
+
<button
|
|
42
|
+
key={value}
|
|
43
|
+
disabled={!isAvailable(option.name, value)}
|
|
44
|
+
onClick={() => setOption(option.name, value)}
|
|
45
|
+
>
|
|
46
|
+
{value}
|
|
47
|
+
</button>
|
|
48
|
+
)),
|
|
49
|
+
)}
|
|
50
|
+
<button
|
|
51
|
+
disabled={!selectedVariant?.availableForSale || status === 'updating'}
|
|
52
|
+
onClick={() => addLine({ productId: product.id, variantId: selectedVariant!.id })}
|
|
53
|
+
>
|
|
54
|
+
Add to cart
|
|
55
|
+
</button>
|
|
56
|
+
</>
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## What it takes care of
|
|
62
|
+
|
|
63
|
+
- **Customer.** OTP, Telegram `initData`, OQ and Click sign-in; the session is kept in storage and the
|
|
64
|
+
hourly access token is refreshed before it expires — one refresh for every caller waiting.
|
|
65
|
+
- **Cart.** The cart id is kept, never shown; the first add creates the cart; quantity changes show
|
|
66
|
+
at once and roll back if the server refuses; changes go out in order; a cart the server no longer
|
|
67
|
+
has is dropped. On sign-in the cart becomes the customer's (merged into theirs if they had one);
|
|
68
|
+
on sign-out it stays with the customer.
|
|
69
|
+
- **Wishlist.** A guest's list lives in the browser and moves into the customer's list at sign-in.
|
|
70
|
+
- **Money.** `shop.moneyFormat` and the locale decide the symbol and its place (`12 500 сум`,
|
|
71
|
+
`$129.99`). Amounts are never rounded on the client.
|
|
72
|
+
- **Analytics.** Page, product, collection views and searches, batched; the visitor id also goes out
|
|
73
|
+
as `X-Session-Id`, so carts and orders join the visit. Cart and checkout steps are recorded by the
|
|
74
|
+
server.
|
|
75
|
+
|
|
76
|
+
## Next.js cache + webhooks
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
// lib/magicstore.ts — server side
|
|
80
|
+
import { createStorefrontClient } from '@magicstoreai/storefront-client';
|
|
81
|
+
import { nextCacheFetch } from '@magicstoreai/hydrogen/server';
|
|
82
|
+
|
|
83
|
+
export const api = createStorefrontClient({
|
|
84
|
+
shopDomain: process.env.SHOP_DOMAIN!,
|
|
85
|
+
fetch: nextCacheFetch(),
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// app/api/magicstore/webhook/route.ts
|
|
89
|
+
import { revalidateTag } from 'next/cache';
|
|
90
|
+
import { createWebhookHandler } from '@magicstoreai/hydrogen/server';
|
|
91
|
+
|
|
92
|
+
export const POST = createWebhookHandler({
|
|
93
|
+
secret: process.env.MAGICSTORE_WEBHOOK_SECRET!,
|
|
94
|
+
revalidateTag,
|
|
95
|
+
});
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Public reads are cached under `magicstore:shop | catalog | pages | home`; the matching webhook topic
|
|
99
|
+
revalidates them. Anything personal (a customer token on the call, carts, checkouts, orders) is
|
|
100
|
+
`no-store`.
|