@kotao/storefront 0.2.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/LICENSE +21 -0
- package/README.md +34 -0
- package/dist/cart-documents-CwwRTvm8.d.ts +21 -0
- package/dist/cart-documents.d.ts +2 -0
- package/dist/cart-documents.js +3 -0
- package/dist/cart-documents.js.map +1 -0
- package/dist/chunk-2IWNUDSZ.js +104 -0
- package/dist/chunk-2IWNUDSZ.js.map +1 -0
- package/dist/chunk-3YQXJNR7.js +70 -0
- package/dist/chunk-3YQXJNR7.js.map +1 -0
- package/dist/chunk-5QOFKGKD.js +51 -0
- package/dist/chunk-5QOFKGKD.js.map +1 -0
- package/dist/chunk-GCQI6OKH.js +239 -0
- package/dist/chunk-GCQI6OKH.js.map +1 -0
- package/dist/chunk-ISAFEOR2.js +214 -0
- package/dist/chunk-ISAFEOR2.js.map +1 -0
- package/dist/chunk-MYDKIJRH.js +81 -0
- package/dist/chunk-MYDKIJRH.js.map +1 -0
- package/dist/chunk-OGWYTYYS.js +72 -0
- package/dist/chunk-OGWYTYYS.js.map +1 -0
- package/dist/chunk-PXZ737N3.js +439 -0
- package/dist/chunk-PXZ737N3.js.map +1 -0
- package/dist/chunk-QOEEUTHQ.js +110 -0
- package/dist/chunk-QOEEUTHQ.js.map +1 -0
- package/dist/chunk-U5677AEA.js +1690 -0
- package/dist/chunk-U5677AEA.js.map +1 -0
- package/dist/chunk-XMTWFJCZ.js +138 -0
- package/dist/chunk-XMTWFJCZ.js.map +1 -0
- package/dist/client-D9YYA2w6.d.ts +159 -0
- package/dist/customer-account-api-types.d.ts +144 -0
- package/dist/customer-account-api-types.js +3 -0
- package/dist/customer-account-api-types.js.map +1 -0
- package/dist/editor.d.ts +112 -0
- package/dist/editor.js +3 -0
- package/dist/editor.js.map +1 -0
- package/dist/image.d.ts +89 -0
- package/dist/image.js +3 -0
- package/dist/image.js.map +1 -0
- package/dist/index.d.ts +183 -0
- package/dist/index.js +208 -0
- package/dist/index.js.map +1 -0
- package/dist/pagination-CPgH3fAa.d.ts +77 -0
- package/dist/product.d.ts +105 -0
- package/dist/product.js +4 -0
- package/dist/product.js.map +1 -0
- package/dist/react-router.d.ts +29 -0
- package/dist/react-router.js +33 -0
- package/dist/react-router.js.map +1 -0
- package/dist/react.d.ts +299 -0
- package/dist/react.js +1813 -0
- package/dist/react.js.map +1 -0
- package/dist/routing-BfUp49o8.d.ts +302 -0
- package/dist/seo.d.ts +155 -0
- package/dist/seo.js +4 -0
- package/dist/seo.js.map +1 -0
- package/dist/settings.d.ts +87 -0
- package/dist/settings.js +3 -0
- package/dist/settings.js.map +1 -0
- package/dist/shop-DkQmro-Y.d.ts +202 -0
- package/dist/store-DQK1nhob.d.ts +67 -0
- package/dist/storefront-api-types.d.ts +312 -0
- package/dist/storefront-api-types.js +3 -0
- package/dist/storefront-api-types.js.map +1 -0
- package/dist/types-BDhHWZsP.d.ts +77 -0
- package/dist/types-Df3bGbKU.d.ts +167 -0
- package/package.json +82 -0
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
import { S as StorefrontClient, C as CacheStrategy, K as KotaoCache } from './client-D9YYA2w6.js';
|
|
2
|
+
import { C as CartFormAction, a as Cart, b as CartLineInput, c as CartAttribute, d as CartBuyerIdentityInput, e as CartMutationResult, f as CartLineUpdateInput, g as CartMetafield, h as CartMetafieldIdentifier, i as CartDeliveryAddress, j as CartSelectedDeliveryOption, H as HydrogenSession } from './types-Df3bGbKU.js';
|
|
3
|
+
|
|
4
|
+
interface CartCreateInput {
|
|
5
|
+
readonly lines?: readonly CartLineInput[];
|
|
6
|
+
readonly note?: string | null;
|
|
7
|
+
readonly attributes?: readonly CartAttribute[];
|
|
8
|
+
readonly buyerIdentity?: CartBuyerIdentityInput;
|
|
9
|
+
}
|
|
10
|
+
interface CartDispatchAction {
|
|
11
|
+
readonly action: CartFormAction;
|
|
12
|
+
readonly inputs: Record<string, unknown>;
|
|
13
|
+
}
|
|
14
|
+
interface CartHandler {
|
|
15
|
+
get(): Promise<Cart | null>;
|
|
16
|
+
getCart(): Promise<Cart | null>;
|
|
17
|
+
create(input?: CartCreateInput): Promise<CartMutationResult>;
|
|
18
|
+
addLines(lines: readonly CartLineInput[]): Promise<CartMutationResult>;
|
|
19
|
+
updateLines(lines: readonly CartLineUpdateInput[]): Promise<CartMutationResult>;
|
|
20
|
+
removeLines(lineIds: readonly string[]): Promise<CartMutationResult>;
|
|
21
|
+
updateBuyerIdentity(buyerIdentity: CartBuyerIdentityInput): Promise<CartMutationResult>;
|
|
22
|
+
updateDiscountCodes(discountCodes: readonly string[]): Promise<CartMutationResult>;
|
|
23
|
+
setCartId(cartId: string): Headers;
|
|
24
|
+
cartCreate(input?: CartCreateInput): Promise<CartMutationResult>;
|
|
25
|
+
linesAdd(lines: readonly CartLineInput[]): Promise<CartMutationResult>;
|
|
26
|
+
linesUpdate(lines: readonly CartLineUpdateInput[]): Promise<CartMutationResult>;
|
|
27
|
+
linesRemove(lineIds: readonly string[]): Promise<CartMutationResult>;
|
|
28
|
+
buyerIdentityUpdate(buyerIdentity: CartBuyerIdentityInput): Promise<CartMutationResult>;
|
|
29
|
+
discountCodesUpdate(discountCodes: readonly string[]): Promise<CartMutationResult>;
|
|
30
|
+
giftCardCodesAdd(giftCardCodes: readonly string[]): Promise<CartMutationResult>;
|
|
31
|
+
giftCardCodesRemove(giftCardCodes: readonly string[]): Promise<CartMutationResult>;
|
|
32
|
+
noteUpdate(note: string | null): Promise<CartMutationResult>;
|
|
33
|
+
attributesUpdate(attributes: readonly CartAttribute[]): Promise<CartMutationResult>;
|
|
34
|
+
metafieldsSet(metafields: readonly CartMetafield[]): Promise<CartMutationResult>;
|
|
35
|
+
metafieldsDelete(metafields: readonly CartMetafieldIdentifier[]): Promise<CartMutationResult>;
|
|
36
|
+
deliveryAddressesReplace(addresses: readonly CartDeliveryAddress[]): Promise<CartMutationResult>;
|
|
37
|
+
selectedDeliveryOptionsUpdate(selectedDeliveryOptions: readonly CartSelectedDeliveryOption[]): Promise<CartMutationResult>;
|
|
38
|
+
dispatch(action: CartDispatchAction): Promise<CartMutationResult>;
|
|
39
|
+
}
|
|
40
|
+
type MaybePromise<T> = T | Promise<T>;
|
|
41
|
+
type CartGetId = () => MaybePromise<string | null | undefined>;
|
|
42
|
+
type CartSetId = (cartId: string) => MaybePromise<string | Headers | null | undefined | void>;
|
|
43
|
+
interface RequestCartHandlerOptions {
|
|
44
|
+
request: Request;
|
|
45
|
+
storefront: StorefrontClient;
|
|
46
|
+
}
|
|
47
|
+
interface HydrogenCartHandlerOptions {
|
|
48
|
+
storefront: StorefrontClient;
|
|
49
|
+
customerAccount?: unknown;
|
|
50
|
+
getCartId: CartGetId;
|
|
51
|
+
setCartId: CartSetId;
|
|
52
|
+
}
|
|
53
|
+
type CreateCartHandlerOptions = RequestCartHandlerOptions | HydrogenCartHandlerOptions;
|
|
54
|
+
declare function cartGetIdDefault(headers: Headers): CartGetId;
|
|
55
|
+
declare function cartSetIdDefault(): CartSetId;
|
|
56
|
+
declare function createCartHandler(opts: CreateCartHandlerOptions): CartHandler;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Typed customer-account shapes for the `@kotao/storefront` SDK surface (#91). The names/signatures
|
|
60
|
+
* mirror Hydrogen's Customer Account API so a Hydrogen→Kotao theme migration stays mechanical
|
|
61
|
+
* (ADR-0003). Kotao-native storefronts use the same-origin `/api/storefront` proxy, while migrated
|
|
62
|
+
* Hydrogen server contexts can keep Shopify Customer Account OAuth/session semantics.
|
|
63
|
+
*/
|
|
64
|
+
interface CustomerAccount {
|
|
65
|
+
readonly id: string;
|
|
66
|
+
readonly email: string;
|
|
67
|
+
readonly firstName: string | null;
|
|
68
|
+
readonly lastName: string | null;
|
|
69
|
+
readonly displayName: string | null;
|
|
70
|
+
}
|
|
71
|
+
interface Money {
|
|
72
|
+
readonly amount: string;
|
|
73
|
+
readonly currencyCode: string;
|
|
74
|
+
}
|
|
75
|
+
interface Order {
|
|
76
|
+
readonly id: string;
|
|
77
|
+
readonly number: string;
|
|
78
|
+
readonly processedAt: string;
|
|
79
|
+
readonly financialStatus: string;
|
|
80
|
+
readonly fulfillmentStatus: string;
|
|
81
|
+
readonly totalPrice: Money;
|
|
82
|
+
}
|
|
83
|
+
/** Order-history page info. Named distinctly from the SDK's relay-style `PageInfo` (pagination) to
|
|
84
|
+
* avoid a barrel name collision. */
|
|
85
|
+
interface OrderPageInfo {
|
|
86
|
+
readonly hasNextPage: boolean;
|
|
87
|
+
readonly endCursor: string | null;
|
|
88
|
+
}
|
|
89
|
+
interface OrderConnection {
|
|
90
|
+
readonly nodes: readonly Order[];
|
|
91
|
+
readonly pageInfo: OrderPageInfo;
|
|
92
|
+
}
|
|
93
|
+
interface RequestLoginCodeInput {
|
|
94
|
+
readonly email: string;
|
|
95
|
+
}
|
|
96
|
+
interface RequestLoginCodeResult {
|
|
97
|
+
readonly status: 'sent' | 'rate_limited' | 'error';
|
|
98
|
+
}
|
|
99
|
+
interface VerifyLoginCodeInput {
|
|
100
|
+
readonly email: string;
|
|
101
|
+
readonly code: string;
|
|
102
|
+
/** Same-origin path to redirect to after successful verification (optional). */
|
|
103
|
+
readonly returnTo?: string;
|
|
104
|
+
}
|
|
105
|
+
interface CustomerAccountGraphQLError {
|
|
106
|
+
readonly message: string;
|
|
107
|
+
readonly [key: string]: unknown;
|
|
108
|
+
}
|
|
109
|
+
interface CustomerAccountGraphQLResult<T = unknown> {
|
|
110
|
+
readonly data: T | null;
|
|
111
|
+
readonly errors?: readonly CustomerAccountGraphQLError[];
|
|
112
|
+
}
|
|
113
|
+
interface CustomerAccountGraphQLOptions {
|
|
114
|
+
readonly variables?: Record<string, unknown>;
|
|
115
|
+
}
|
|
116
|
+
interface OrdersOptions {
|
|
117
|
+
readonly first?: number;
|
|
118
|
+
readonly after?: string;
|
|
119
|
+
}
|
|
120
|
+
/** Maps the backend `AddressDTO` shape (kernel fields renamed to Shopify-compatible names). */
|
|
121
|
+
interface Address {
|
|
122
|
+
readonly id: string;
|
|
123
|
+
readonly firstName: string | null;
|
|
124
|
+
readonly lastName: string | null;
|
|
125
|
+
readonly company: string | null;
|
|
126
|
+
readonly address1: string | null;
|
|
127
|
+
readonly address2: string | null;
|
|
128
|
+
readonly city: string | null;
|
|
129
|
+
readonly province: string | null;
|
|
130
|
+
readonly provinceCode: string | null;
|
|
131
|
+
readonly country: string | null;
|
|
132
|
+
readonly countryCode: string | null;
|
|
133
|
+
readonly zip: string | null;
|
|
134
|
+
readonly phone: string | null;
|
|
135
|
+
readonly default: boolean;
|
|
136
|
+
}
|
|
137
|
+
/** Input for creating or updating an address — same as `Address` minus the server-assigned `id`. */
|
|
138
|
+
type AddressInput = Omit<Address, 'id'>;
|
|
139
|
+
interface AddressConnection {
|
|
140
|
+
readonly nodes: readonly Address[];
|
|
141
|
+
}
|
|
142
|
+
type CustomerAccountErrorCode = 'unauthenticated' | 'unreachable' | 'api_error';
|
|
143
|
+
/**
|
|
144
|
+
* Typed failure for account/order reads — the SDK never lets a bare network throw or a non-200
|
|
145
|
+
* escape to theme code (acceptance criterion). `unauthenticated` = no/invalid session (401);
|
|
146
|
+
* `unreachable` = the proxy fetch itself failed; `api_error` = any other non-OK response.
|
|
147
|
+
*/
|
|
148
|
+
declare class CustomerAccountError extends Error {
|
|
149
|
+
readonly code: CustomerAccountErrorCode;
|
|
150
|
+
constructor(code: CustomerAccountErrorCode, message: string);
|
|
151
|
+
}
|
|
152
|
+
interface CustomerAccountClient {
|
|
153
|
+
/**
|
|
154
|
+
* Hydrogen-compatible Customer Account GraphQL read. Kotao sessions go through the same-origin
|
|
155
|
+
* proxy; Hydrogen AppSession credentials can call Shopify's Customer Account API directly. When
|
|
156
|
+
* logged out it returns a GraphQL-shaped error instead of throwing so Hydrogen loaders can run their
|
|
157
|
+
* normal logout/login branch.
|
|
158
|
+
*/
|
|
159
|
+
query<T = unknown>(query: string, options?: CustomerAccountGraphQLOptions): Promise<CustomerAccountGraphQLResult<T>>;
|
|
160
|
+
/** Hydrogen-compatible Customer Account GraphQL mutation through the active customer-account mode. */
|
|
161
|
+
mutate<T = unknown>(mutation: string, options?: CustomerAccountGraphQLOptions): Promise<CustomerAccountGraphQLResult<T>>;
|
|
162
|
+
/** Hydrogen-compatible login redirect entrypoint. */
|
|
163
|
+
login(): Response | Promise<Response>;
|
|
164
|
+
/** Hydrogen-compatible authorize callback entrypoint. */
|
|
165
|
+
authorize(): Response | Promise<Response>;
|
|
166
|
+
/** Throws the login redirect when unauthenticated, matching Hydrogen loader usage. */
|
|
167
|
+
handleAuthStatus(): Promise<void>;
|
|
168
|
+
/**
|
|
169
|
+
* POST to the proxy `/account/send` endpoint to trigger an OTP email. Returns a typed status:
|
|
170
|
+
* `sent` (200), `rate_limited` (429), or `error` (any other failure). Never throws.
|
|
171
|
+
*/
|
|
172
|
+
requestLoginCode(input: RequestLoginCodeInput): Promise<RequestLoginCodeResult>;
|
|
173
|
+
/**
|
|
174
|
+
* POST to the proxy `/account/verify` endpoint with the OTP code. Returns the raw proxy `Response`
|
|
175
|
+
* so its `Set-Cookie` and 302 redirect headers propagate to the theme's RR7 action unchanged —
|
|
176
|
+
* do NOT swallow or re-create this Response.
|
|
177
|
+
*/
|
|
178
|
+
verifyLoginCode(input: VerifyLoginCodeInput): Promise<Response>;
|
|
179
|
+
/** 302 logout redirect; also clears the active customer-account session cookie. */
|
|
180
|
+
logout(): Response | Promise<Response>;
|
|
181
|
+
/** Boolean session check — never throws (false on absent/invalid/unreachable). */
|
|
182
|
+
isLoggedIn(): Promise<boolean>;
|
|
183
|
+
/**
|
|
184
|
+
* The active customer credential, or null. In Kotao proxy mode this is the opaque per-shop session
|
|
185
|
+
* token from the cookie; in Hydrogen AppSession mode this is Shopify's Customer Account access
|
|
186
|
+
* token and may refresh the session before resolving. Treat it as a credential: do not log it or
|
|
187
|
+
* send it to unrelated origins.
|
|
188
|
+
*/
|
|
189
|
+
getAccessToken(): Promise<string | null>;
|
|
190
|
+
/** The current customer profile; throws {@link CustomerAccountError} on failure. */
|
|
191
|
+
account(): Promise<CustomerAccount>;
|
|
192
|
+
/** Cursor-paginated order history; throws {@link CustomerAccountError} on failure. */
|
|
193
|
+
orders(options?: OrdersOptions): Promise<OrderConnection>;
|
|
194
|
+
/** List all saved addresses for the authenticated customer; throws {@link CustomerAccountError} on failure. */
|
|
195
|
+
addresses(): Promise<AddressConnection>;
|
|
196
|
+
/** Create a new address; returns the raw proxy Response. */
|
|
197
|
+
createAddress(input: AddressInput): Promise<Response>;
|
|
198
|
+
/** Update an existing address by id; returns the raw proxy Response. */
|
|
199
|
+
updateAddress(id: string, input: AddressInput): Promise<Response>;
|
|
200
|
+
/** Delete an address by id; returns the raw proxy Response. */
|
|
201
|
+
deleteAddress(id: string): Promise<Response>;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
declare const GEO_HEADER = "x-kotao-geo";
|
|
205
|
+
declare const GEO_SIGNATURE_HEADER = "x-kotao-geo-signature";
|
|
206
|
+
/**
|
|
207
|
+
* Trusted geo surfaced to themes as `context.geo`. In untrusted WFP mode `request.cf` is
|
|
208
|
+
* stripped, so the Gateway Worker (#81) injects this as signed `x-kotao-*` headers and the
|
|
209
|
+
* SDK verifies them here. Both sides share this module so the contract can never drift.
|
|
210
|
+
*/
|
|
211
|
+
interface Geo {
|
|
212
|
+
country: string | null;
|
|
213
|
+
city: string | null;
|
|
214
|
+
colo: string | null;
|
|
215
|
+
botScore: number | null;
|
|
216
|
+
clientIp: string | null;
|
|
217
|
+
}
|
|
218
|
+
/** Gateway side (#81): produce the two header values for a geo payload. */
|
|
219
|
+
declare function signGeo(geo: Geo, key: string): Promise<{
|
|
220
|
+
payload: string;
|
|
221
|
+
signature: string;
|
|
222
|
+
}>;
|
|
223
|
+
/** SDK side: reconstruct typed geo from signed headers. Returns null on any failure — never trusts unsigned data. */
|
|
224
|
+
declare function verifyGeo(headers: Headers, key: string): Promise<Geo | null>;
|
|
225
|
+
|
|
226
|
+
type WithCache = <T>(key: string, strategy: CacheStrategy, fn: () => Promise<T>) => Promise<T>;
|
|
227
|
+
/** Mirrors Hydrogen's `createWithCache`: SWR caching for arbitrary third-party data. */
|
|
228
|
+
declare const createWithCache: (cache: KotaoCache) => WithCache;
|
|
229
|
+
|
|
230
|
+
interface KotaoEnv {
|
|
231
|
+
STOREFRONT_API_ENDPOINT: string;
|
|
232
|
+
STOREFRONT_API_TOKEN: string;
|
|
233
|
+
STOREFRONT_API_TOKEN_HEADER?: string;
|
|
234
|
+
STOREFRONT_GEO_SIGNING_KEY: string;
|
|
235
|
+
/**
|
|
236
|
+
* Per-deploy font CDN base `https://cdn.kotao.{stage}/{org}/fonts` (bound by apps/storefront-build).
|
|
237
|
+
* Migrated themes stamp it onto the render runtime so `font_face`/`font_url` resolve fonts from the
|
|
238
|
+
* org's R2-native CDN instead of the retired `/kotao-cdn/fonts/{id}` carve-out.
|
|
239
|
+
*/
|
|
240
|
+
FONT_CDN_BASE?: string;
|
|
241
|
+
KOTAO_SITE_ID?: string;
|
|
242
|
+
KOTAO_SHOP_ID?: string;
|
|
243
|
+
/**
|
|
244
|
+
* Local-dev only: HMAC key for self-signing the shop-context the proxy verifies. In production
|
|
245
|
+
* the Gateway signs it (this is unset), so its presence is what enables the local signer below.
|
|
246
|
+
* Must match the api proxy's STOREFRONT_SHOP_CONTEXT_KEY.
|
|
247
|
+
*/
|
|
248
|
+
STOREFRONT_SHOP_CONTEXT_KEY?: string;
|
|
249
|
+
SESSION_SECRET?: string;
|
|
250
|
+
PUBLIC_STOREFRONT_API_TOKEN?: string;
|
|
251
|
+
PRIVATE_STOREFRONT_API_TOKEN?: string;
|
|
252
|
+
PUBLIC_STORE_DOMAIN?: string;
|
|
253
|
+
PUBLIC_STOREFRONT_ID?: string;
|
|
254
|
+
PUBLIC_CUSTOMER_ACCOUNT_API_CLIENT_ID?: string;
|
|
255
|
+
PUBLIC_CUSTOMER_ACCOUNT_API_URL?: string;
|
|
256
|
+
PUBLIC_CHECKOUT_DOMAIN?: string;
|
|
257
|
+
SHOP_ID?: string;
|
|
258
|
+
}
|
|
259
|
+
interface KotaoSession extends HydrogenSession {
|
|
260
|
+
readonly isLoggedIn: boolean;
|
|
261
|
+
}
|
|
262
|
+
interface KotaoContext {
|
|
263
|
+
readonly storefront: StorefrontClient;
|
|
264
|
+
readonly cart: CartHandler;
|
|
265
|
+
readonly customerAccount: CustomerAccountClient;
|
|
266
|
+
readonly geo: Geo | null;
|
|
267
|
+
readonly withCache: WithCache;
|
|
268
|
+
readonly locale: string | null;
|
|
269
|
+
/** Cookie-presence hint. `isLoggedIn` is true when the session cookie is present in the request.
|
|
270
|
+
* The authoritative check (HMAC verification) happens server-side in the proxy. */
|
|
271
|
+
readonly session: KotaoSession;
|
|
272
|
+
readonly env: any;
|
|
273
|
+
readonly waitUntil: (p: Promise<unknown>) => void;
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Framework-agnostic per-request context, mirroring Hydrogen's `createHydrogenContext`:
|
|
277
|
+
* storefront client + verified geo + SWR cache + locale + session seam.
|
|
278
|
+
*/
|
|
279
|
+
declare function createKotaoContext(request: Request, env: KotaoEnv, executionCtx: ExecutionContext, deps?: {
|
|
280
|
+
openCache?: (name: string) => Promise<Cache>;
|
|
281
|
+
session?: HydrogenSession;
|
|
282
|
+
}): Promise<KotaoContext>;
|
|
283
|
+
|
|
284
|
+
declare const ROUTING_LOCALE_HEADER = "x-kotao-route-locale";
|
|
285
|
+
declare const ROUTING_ORIGINAL_PATHNAME_HEADER = "x-kotao-original-pathname";
|
|
286
|
+
interface StrippedLocalePath {
|
|
287
|
+
readonly locale: string | null;
|
|
288
|
+
readonly pathname: string;
|
|
289
|
+
}
|
|
290
|
+
interface LocalizePathOptions {
|
|
291
|
+
readonly primaryLocale?: string | null;
|
|
292
|
+
}
|
|
293
|
+
declare function isLocalePathSegment(segment: string): boolean;
|
|
294
|
+
declare function localeFromAcceptLanguage(header: string | null | undefined, availableLocales?: readonly string[]): string | null;
|
|
295
|
+
declare function localeFromPathname(pathname: string): string | null;
|
|
296
|
+
declare function originalPathnameFromRequest(request: Request): string;
|
|
297
|
+
declare function localeFromRequest(request: Request): string | null;
|
|
298
|
+
declare function stripLocalePrefixFromPathname(pathname: string): StrippedLocalePath;
|
|
299
|
+
declare function stripLocalePrefixFromRequest(request: Request): Request;
|
|
300
|
+
declare function localizePath(path: string, locale: string | null | undefined, options?: LocalizePathOptions): string;
|
|
301
|
+
|
|
302
|
+
export { type Address as A, isLocalePathSegment as B, type CartDispatchAction as C, localeFromAcceptLanguage as D, localeFromPathname as E, localeFromRequest as F, GEO_HEADER as G, type HydrogenCartHandlerOptions as H, localizePath as I, originalPathnameFromRequest as J, type KotaoEnv as K, type LocalizePathOptions as L, type Money as M, signGeo as N, type Order as O, stripLocalePrefixFromPathname as P, verifyGeo as Q, ROUTING_LOCALE_HEADER as R, type StrippedLocalePath as S, type VerifyLoginCodeInput as V, type WithCache as W, type KotaoContext as a, type KotaoSession as b, type CustomerAccountClient as c, type AddressConnection as d, type CartGetId as e, type CartHandler as f, type CartSetId as g, type CreateCartHandlerOptions as h, type CustomerAccount as i, CustomerAccountError as j, type CustomerAccountErrorCode as k, GEO_SIGNATURE_HEADER as l, type Geo as m, type OrderConnection as n, type OrderPageInfo as o, type OrdersOptions as p, ROUTING_ORIGINAL_PATHNAME_HEADER as q, type RequestCartHandlerOptions as r, stripLocalePrefixFromRequest as s, type RequestLoginCodeInput as t, type RequestLoginCodeResult as u, cartGetIdDefault as v, cartSetIdDefault as w, createCartHandler as x, createKotaoContext as y, createWithCache as z };
|
package/dist/seo.d.ts
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { S as SeoConfig, b as SeoDescriptor, J as JsonLd } from './types-BDhHWZsP.js';
|
|
2
|
+
export { A as Alternate, O as OpenGraph, a as OpenGraphImage, T as TwitterCard } from './types-BDhHWZsP.js';
|
|
3
|
+
import { S as StorefrontClient } from './client-D9YYA2w6.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Merge SEO config across levels and emit a flat, deduplicated descriptor list (RR7 `meta`-compatible):
|
|
7
|
+
* title, description, canonical, robots, Open Graph, Twitter Card, hreflang alternates, and JSON-LD.
|
|
8
|
+
* Open Graph / Twitter titles + descriptions fall back to the page title/description (Hydrogen-shaped).
|
|
9
|
+
*/
|
|
10
|
+
declare function getSeoMeta(...configs: SeoConfig[]): SeoDescriptor[];
|
|
11
|
+
/**
|
|
12
|
+
* Serialize a JSON-LD object for inline `<script>` injection. Escapes `<` to `<` so a value
|
|
13
|
+
* containing `</script>` cannot break out of the script element (XSS guard). Use in any hand-rolled
|
|
14
|
+
* renderer; the `<Seo/>` component uses this.
|
|
15
|
+
*/
|
|
16
|
+
declare function serializeJsonLd(obj: JsonLd): string;
|
|
17
|
+
|
|
18
|
+
interface BreadcrumbItem {
|
|
19
|
+
readonly name: string;
|
|
20
|
+
readonly url: string;
|
|
21
|
+
}
|
|
22
|
+
declare function breadcrumbListJsonLd(items: readonly BreadcrumbItem[]): JsonLd;
|
|
23
|
+
interface OrganizationInput {
|
|
24
|
+
readonly name: string;
|
|
25
|
+
readonly url?: string;
|
|
26
|
+
readonly logo?: string;
|
|
27
|
+
readonly sameAs?: readonly string[];
|
|
28
|
+
}
|
|
29
|
+
declare function organizationJsonLd(input: OrganizationInput): JsonLd;
|
|
30
|
+
interface WebSiteInput {
|
|
31
|
+
readonly name: string;
|
|
32
|
+
readonly url: string;
|
|
33
|
+
/** A URL template with `{search_term_string}` to enable the sitelinks search box. */
|
|
34
|
+
readonly searchUrlTemplate?: string;
|
|
35
|
+
}
|
|
36
|
+
declare function websiteJsonLd(input: WebSiteInput): JsonLd;
|
|
37
|
+
|
|
38
|
+
interface OfferInput {
|
|
39
|
+
readonly price: string | number;
|
|
40
|
+
readonly currency: string;
|
|
41
|
+
/** schema.org ItemAvailability short name, e.g. 'InStock' | 'OutOfStock' | 'PreOrder'. */
|
|
42
|
+
readonly availability?: string;
|
|
43
|
+
readonly url?: string;
|
|
44
|
+
readonly sku?: string;
|
|
45
|
+
}
|
|
46
|
+
interface ProductJsonLdInput {
|
|
47
|
+
readonly name: string;
|
|
48
|
+
readonly description?: string;
|
|
49
|
+
readonly sku?: string;
|
|
50
|
+
readonly image?: string | readonly string[];
|
|
51
|
+
readonly brand?: string;
|
|
52
|
+
readonly url?: string;
|
|
53
|
+
readonly offer?: OfferInput;
|
|
54
|
+
}
|
|
55
|
+
declare function productJsonLd(input: ProductJsonLdInput): JsonLd;
|
|
56
|
+
|
|
57
|
+
interface AddressInput {
|
|
58
|
+
readonly streetAddress?: string;
|
|
59
|
+
readonly locality?: string;
|
|
60
|
+
readonly region?: string;
|
|
61
|
+
readonly postalCode?: string;
|
|
62
|
+
readonly country?: string;
|
|
63
|
+
}
|
|
64
|
+
interface GeoInput {
|
|
65
|
+
readonly latitude: number;
|
|
66
|
+
readonly longitude: number;
|
|
67
|
+
}
|
|
68
|
+
interface LocalBusinessInput {
|
|
69
|
+
readonly name: string;
|
|
70
|
+
/** schema.org type, e.g. 'LocalBusiness' | 'Restaurant' | 'Store'. Defaults to 'LocalBusiness'. */
|
|
71
|
+
readonly type?: string;
|
|
72
|
+
readonly url?: string;
|
|
73
|
+
readonly telephone?: string;
|
|
74
|
+
readonly priceRange?: string;
|
|
75
|
+
readonly image?: string | readonly string[];
|
|
76
|
+
readonly address?: AddressInput;
|
|
77
|
+
readonly geo?: GeoInput;
|
|
78
|
+
/** schema.org openingHours strings, e.g. ['Mo-Fr 09:00-17:00', 'Sa 10:00-14:00']. */
|
|
79
|
+
readonly openingHours?: readonly string[];
|
|
80
|
+
/** Restaurant fields (used when type is 'Restaurant'). */
|
|
81
|
+
readonly servesCuisine?: string | readonly string[];
|
|
82
|
+
readonly menu?: string;
|
|
83
|
+
readonly acceptsReservations?: boolean;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* LocalBusiness JSON-LD — the brick-and-mortar / restaurant differentiator beyond Shopify's defaults
|
|
87
|
+
* (the SDK table calls this out). `restaurantJsonLd` is the same builder pinned to `Restaurant`.
|
|
88
|
+
*/
|
|
89
|
+
declare function localBusinessJsonLd(input: LocalBusinessInput): JsonLd;
|
|
90
|
+
declare function restaurantJsonLd(input: Omit<LocalBusinessInput, 'type'>): JsonLd;
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* sitemap.xml + sitemap-index factories. The entry source is injected (the caller resolves it from the
|
|
94
|
+
* Storefront API or a search index — an open question, NOT decided here): build the entry list, then call
|
|
95
|
+
* these. The index shape exists so large catalogs split into child sitemaps rather than one document.
|
|
96
|
+
*/
|
|
97
|
+
type ChangeFreq = 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never';
|
|
98
|
+
interface SitemapEntry {
|
|
99
|
+
readonly loc: string;
|
|
100
|
+
readonly lastmod?: string;
|
|
101
|
+
readonly changefreq?: ChangeFreq;
|
|
102
|
+
/** 0.0–1.0 (clamped). */
|
|
103
|
+
readonly priority?: number;
|
|
104
|
+
}
|
|
105
|
+
interface SitemapIndexEntry {
|
|
106
|
+
readonly loc: string;
|
|
107
|
+
readonly lastmod?: string;
|
|
108
|
+
}
|
|
109
|
+
declare function buildSitemapXml(entries: readonly SitemapEntry[]): string;
|
|
110
|
+
declare function buildSitemapIndexXml(sitemaps: readonly SitemapIndexEntry[]): string;
|
|
111
|
+
declare function sitemapResponse(entries: readonly SitemapEntry[]): Response;
|
|
112
|
+
declare function sitemapIndexResponse(sitemaps: readonly SitemapIndexEntry[]): Response;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* robots.txt factory. Non-production / preview deployments auto-disallow ALL crawling; production allows
|
|
116
|
+
* and references the sitemap. `production` comes from the SDK's stage signal (context.env), NEVER the
|
|
117
|
+
* request Host/URL (stage-pinned-config rule, AGENTS.md §Environments).
|
|
118
|
+
*/
|
|
119
|
+
interface RobotsOptions {
|
|
120
|
+
readonly production: boolean;
|
|
121
|
+
readonly sitemapUrl?: string;
|
|
122
|
+
}
|
|
123
|
+
declare function buildRobotsTxt(options: RobotsOptions): string;
|
|
124
|
+
declare function robotsResponse(options: RobotsOptions): Response;
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Slug-change 301 handler. The redirect store is owned elsewhere (catalog/storefront-API work); this
|
|
128
|
+
* owns only the request-handling shape. The lookup is injected: given the current path, it returns the
|
|
129
|
+
* canonical target (or null). A self-redirect (target === path) returns null to avoid an immediate loop.
|
|
130
|
+
*/
|
|
131
|
+
type RedirectLookup = (path: string) => Promise<string | null> | string | null;
|
|
132
|
+
interface RedirectOptions {
|
|
133
|
+
/** 301 (permanent, default) or 302 (temporary). */
|
|
134
|
+
readonly status?: 301 | 302;
|
|
135
|
+
}
|
|
136
|
+
interface StorefrontRedirectOptions extends RedirectOptions {
|
|
137
|
+
readonly request: Request;
|
|
138
|
+
readonly response: Response;
|
|
139
|
+
readonly storefront: StorefrontClient;
|
|
140
|
+
}
|
|
141
|
+
declare function resolveRedirect(lookup: RedirectLookup, path: string, options?: RedirectOptions): Promise<Response | null>;
|
|
142
|
+
declare const URL_REDIRECT_QUERY = "#graphql\n query UrlRedirect($path: String!) {\n urlRedirect(path: $path) {\n target\n }\n }\n";
|
|
143
|
+
/**
|
|
144
|
+
* Look up `path` in the storefront-api's url_redirects and, if found, return a 301 Response.
|
|
145
|
+
* Returns null when there is no redirect, a self-redirect, or the lookup query fails (so the caller
|
|
146
|
+
* falls through to its normal 404 — a lookup failure must never become a 500).
|
|
147
|
+
*/
|
|
148
|
+
declare function resolveStorefrontRedirect(storefront: StorefrontClient, path: string, options?: RedirectOptions): Promise<Response | null>;
|
|
149
|
+
/**
|
|
150
|
+
* Hydrogen-compatible 404 redirect helper. It preserves the original response when there is no
|
|
151
|
+
* matching URL redirect, mirroring the server.ts pattern used by Hydrogen demo stores.
|
|
152
|
+
*/
|
|
153
|
+
declare function storefrontRedirect(options: StorefrontRedirectOptions): Promise<Response>;
|
|
154
|
+
|
|
155
|
+
export { type AddressInput, type BreadcrumbItem, type ChangeFreq, type GeoInput, JsonLd, type LocalBusinessInput, type OfferInput, type OrganizationInput, type ProductJsonLdInput, type RedirectLookup, type RedirectOptions, type RobotsOptions, SeoConfig, SeoDescriptor, type SitemapEntry, type SitemapIndexEntry, type StorefrontRedirectOptions, URL_REDIRECT_QUERY, type WebSiteInput, breadcrumbListJsonLd, buildRobotsTxt, buildSitemapIndexXml, buildSitemapXml, getSeoMeta, localBusinessJsonLd, organizationJsonLd, productJsonLd, resolveRedirect, resolveStorefrontRedirect, restaurantJsonLd, robotsResponse, serializeJsonLd, sitemapIndexResponse, sitemapResponse, storefrontRedirect, websiteJsonLd };
|
package/dist/seo.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { URL_REDIRECT_QUERY, breadcrumbListJsonLd, buildRobotsTxt, buildSitemapIndexXml, buildSitemapXml, localBusinessJsonLd, organizationJsonLd, productJsonLd, resolveRedirect, resolveStorefrontRedirect, restaurantJsonLd, robotsResponse, sitemapIndexResponse, sitemapResponse, storefrontRedirect, websiteJsonLd } from './chunk-ISAFEOR2.js';
|
|
2
|
+
export { getSeoMeta, serializeJsonLd } from './chunk-MYDKIJRH.js';
|
|
3
|
+
//# sourceMappingURL=seo.js.map
|
|
4
|
+
//# sourceMappingURL=seo.js.map
|
package/dist/seo.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"seo.js"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { SectionSchema, Preset, ValuesDocument, SettingInput, SectionInstance } from '@kotao/storefront-contracts/theme';
|
|
2
|
+
import { a as ResolvedSection, b as ResolvedSettings, T as ThemeSettingsSnapshot } from './store-DQK1nhob.js';
|
|
3
|
+
export { R as ResolvedBlock, c as ThemeSettingsStore, d as createThemeSettingsStore } from './store-DQK1nhob.js';
|
|
4
|
+
import { f as StorefrontAuthHeader } from './client-D9YYA2w6.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The settings-as-data merge engine (ADR-0003 §"Settings-as-data customizer", #93). Pure: it resolves
|
|
8
|
+
* a section's effective settings with the universal three-layer order
|
|
9
|
+
*
|
|
10
|
+
* stored value → preset value → input `defaultValue`
|
|
11
|
+
*
|
|
12
|
+
* and composes that over a whole values document (`resolveThemeSettings`). It lives in the SDK (not a
|
|
13
|
+
* commerce module) because it consumes `@kotao/storefront-contracts` types — the storefront layer that
|
|
14
|
+
* may import them (turbo boundaries forbids a module from doing so). The per-shop stored values come from
|
|
15
|
+
* the web module's settings store, read server-side and handed to the SDK as a snapshot.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Resolve one settings layer: for every input the schema declares, take the stored value, else the
|
|
20
|
+
* preset value, else the input's `defaultValue`. Only declared inputs appear (stray stored keys for
|
|
21
|
+
* removed settings are dropped).
|
|
22
|
+
*/
|
|
23
|
+
declare function mergeSettings(inputs: readonly SettingInput[], stored: Readonly<Record<string, unknown>> | undefined, preset: Readonly<Record<string, unknown>> | undefined): ResolvedSettings;
|
|
24
|
+
/**
|
|
25
|
+
* Resolve a full section instance: its settings plus each contained block's settings, all three-layer
|
|
26
|
+
* merged against the section's schema (block instances come from the stored values).
|
|
27
|
+
*/
|
|
28
|
+
declare function mergeSection(args: {
|
|
29
|
+
readonly schema: SectionSchema;
|
|
30
|
+
readonly preset?: Preset;
|
|
31
|
+
readonly instance?: SectionInstance;
|
|
32
|
+
}): ResolvedSection;
|
|
33
|
+
interface ResolveThemeSettingsArgs {
|
|
34
|
+
/** Section schemas keyed by section `type` (from the deployment manifest). */
|
|
35
|
+
readonly schemas: Readonly<Record<string, SectionSchema>>;
|
|
36
|
+
/** Optional default preset per section `type`. */
|
|
37
|
+
readonly presets?: Readonly<Record<string, Preset>>;
|
|
38
|
+
/** The per-shop stored values document (from the web module's settings store). */
|
|
39
|
+
readonly values: ValuesDocument;
|
|
40
|
+
/** Template-specific values documents, keyed by handles like `index`, `product`, or `cart`. */
|
|
41
|
+
readonly templates?: Partial<Record<string, ValuesDocument>>;
|
|
42
|
+
/** Layout section-group values documents, keyed by handles like `header-group`. */
|
|
43
|
+
readonly sectionGroups?: Partial<Record<string, ValuesDocument>>;
|
|
44
|
+
/** Global theme-token inputs (logo/colors/fonts), merged the same way. */
|
|
45
|
+
readonly globalInputs?: readonly SettingInput[];
|
|
46
|
+
readonly globalStored?: Readonly<Record<string, unknown>>;
|
|
47
|
+
readonly globalPreset?: Readonly<Record<string, unknown>>;
|
|
48
|
+
}
|
|
49
|
+
/** Compose the merge over an entire values document → the snapshot a theme renders from. */
|
|
50
|
+
declare function resolveThemeSettings(args: ResolveThemeSettingsArgs): ThemeSettingsSnapshot;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* The stored settings a theme hydrates from (#93): the layout document's ordered section instances +
|
|
54
|
+
* the global theme tokens. Pass to {@link resolveThemeSettings} together with the theme's bundled
|
|
55
|
+
* section schemas + presets to produce the merged {@link ThemeSettingsSnapshot}.
|
|
56
|
+
*/
|
|
57
|
+
interface StoredThemeSettings {
|
|
58
|
+
readonly shopId: string;
|
|
59
|
+
readonly sections: readonly SectionInstance[];
|
|
60
|
+
readonly global: Record<string, unknown>;
|
|
61
|
+
readonly templates?: Readonly<Partial<Record<string, ValuesDocument>>>;
|
|
62
|
+
readonly sectionGroups?: Readonly<Partial<Record<string, ValuesDocument>>>;
|
|
63
|
+
}
|
|
64
|
+
interface FetchThemeSettingsOptions {
|
|
65
|
+
/** Injectable for tests; defaults to the global `fetch`. */
|
|
66
|
+
readonly fetch?: typeof fetch;
|
|
67
|
+
/** Same-origin settings endpoint (default `/api/storefront/settings`). */
|
|
68
|
+
readonly endpoint?: string;
|
|
69
|
+
/**
|
|
70
|
+
* Explicit local-preview escape hatch for server-side theme workers that call the Kotao API directly.
|
|
71
|
+
* Production themes should keep the default same-origin path.
|
|
72
|
+
*/
|
|
73
|
+
readonly allowCrossOrigin?: boolean;
|
|
74
|
+
/** Optional server-side auth headers for local previews. Never pass browser-visible tokens here. */
|
|
75
|
+
readonly auth?: {
|
|
76
|
+
readonly token: string;
|
|
77
|
+
readonly tokenHeader?: StorefrontAuthHeader;
|
|
78
|
+
readonly siteId?: string;
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Fetch the shop's stored settings document via the same-origin `/api/storefront/settings` carve-out.
|
|
83
|
+
* The shop is resolved server-side from the Gateway-signed context — the theme sends no id and no token.
|
|
84
|
+
*/
|
|
85
|
+
declare function fetchThemeSettings(options?: FetchThemeSettingsOptions): Promise<StoredThemeSettings>;
|
|
86
|
+
|
|
87
|
+
export { type FetchThemeSettingsOptions, type ResolveThemeSettingsArgs, ResolvedSection, ResolvedSettings, type StoredThemeSettings, ThemeSettingsSnapshot, fetchThemeSettings, mergeSection, mergeSettings, resolveThemeSettings };
|
package/dist/settings.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"settings.js"}
|