@fayz-ai/storefront 0.81.0 → 0.83.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/analytics/bus.d.ts +3 -1
- package/dist/analytics/bus.d.ts.map +1 -1
- package/dist/analytics/posthog.d.ts.map +1 -1
- package/dist/app/router.d.ts +1 -1
- package/dist/blocks/registry.d.ts.map +1 -1
- package/dist/chunk-4REZOGGW.js +153 -0
- package/dist/chunk-4REZOGGW.js.map +1 -0
- package/dist/{chunk-CWHGBPRP.js → chunk-7GX7JLF7.js} +309 -178
- package/dist/chunk-7GX7JLF7.js.map +1 -0
- package/dist/{chunk-2KCORAVB.js → chunk-7N5HKQBM.js} +3 -2
- package/dist/chunk-7N5HKQBM.js.map +1 -0
- package/dist/{chunk-OIPNINZQ.js → chunk-XDK5H5Y3.js} +4 -4
- package/dist/{chunk-OIPNINZQ.js.map → chunk-XDK5H5Y3.js.map} +1 -1
- package/dist/components/delivery/StoreCover.d.ts.map +1 -1
- package/dist/document/config.d.ts +24 -0
- package/dist/document/config.d.ts.map +1 -1
- package/dist/edge.d.ts +2 -1
- package/dist/edge.d.ts.map +1 -1
- package/dist/edge.js +57 -10
- package/dist/edge.js.map +1 -1
- package/dist/experiments/assign.d.ts +101 -0
- package/dist/experiments/assign.d.ts.map +1 -0
- package/dist/experiments/react.d.ts +99 -0
- package/dist/experiments/react.d.ts.map +1 -0
- package/dist/host/edge-handler.d.ts +32 -2
- package/dist/host/edge-handler.d.ts.map +1 -1
- package/dist/host/store-host.d.ts +11 -1
- package/dist/host/store-host.d.ts.map +1 -1
- package/dist/host.d.ts +2 -0
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +10 -4
- package/dist/host.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -6
- package/dist/index.js.map +1 -1
- package/dist/render.js +4 -3
- package/dist/render.js.map +1 -1
- package/dist/tanstack.d.ts.map +1 -1
- package/dist/tanstack.js +4 -3
- package/dist/tanstack.js.map +1 -1
- package/package.json +2 -2
- package/dist/chunk-2KCORAVB.js.map +0 -1
- package/dist/chunk-CWHGBPRP.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StoreCover.d.ts","sourceRoot":"","sources":["../../../src/components/delivery/StoreCover.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"StoreCover.d.ts","sourceRoot":"","sources":["../../../src/components/delivery/StoreCover.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAazB;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,UAAU,CAAC,EAAE,WAAW,EAAE,aAAa,EAAE,EAAE;IACzD,WAAW,CAAC,EAAE,MAAM,IAAI,CAAA;IACxB,8EAA8E;IAC9E,aAAa,CAAC,EAAE,MAAM,IAAI,CAAA;CAC3B,qBAqKA"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import React, { type ReactNode } from 'react';
|
|
2
2
|
import type { StorefrontAnalyticsConfig } from '../analytics/posthog';
|
|
3
|
+
import type { StorefrontExperiment } from '../experiments/assign';
|
|
4
|
+
import type { Experimental } from '../experiments/react';
|
|
3
5
|
import type { EntityDeclarationInput } from '@fayz-ai/core';
|
|
4
6
|
import type { ShopProvider } from '@fayz-ai/shop/provider';
|
|
5
7
|
import type { MockShopSeed } from '@fayz-ai/shop/mock';
|
|
@@ -236,6 +238,16 @@ export interface StorefrontConfig {
|
|
|
236
238
|
* de configuração é exatamente isso.
|
|
237
239
|
*/
|
|
238
240
|
delivery?: StorefrontDeliveryConfig;
|
|
241
|
+
/**
|
|
242
|
+
* The A/B tests this store runs, by PostHog flag key. This is the source of
|
|
243
|
+
* truth for who sees what: the edge buckets each visitor locally with
|
|
244
|
+
* PostHog's hashing, before render, and any setting typed `Experimental<…>`,
|
|
245
|
+
* any `experiment` block or any `useExperiment(key)` call reads it. The
|
|
246
|
+
* PostHog Experiment on the same key reads the results. A key not declared,
|
|
247
|
+
* or not `status: 'running'`, is always 'control'. See
|
|
248
|
+
* docs/storefront/EXPERIMENTS.md.
|
|
249
|
+
*/
|
|
250
|
+
experiments?: Record<string, StorefrontExperiment>;
|
|
239
251
|
/**
|
|
240
252
|
* Payment behavior. v1 default 'mock' instantly marks orders paid with NO
|
|
241
253
|
* real charge (demo). M4 sets 'pix-mercadopago' so orders stay pending until
|
|
@@ -321,6 +333,8 @@ export interface StorefrontConfig {
|
|
|
321
333
|
/** Code-level route overrides/custom routes. Kept out of serialized manifests. */
|
|
322
334
|
routes?: readonly StorefrontRouteDefinition[];
|
|
323
335
|
}
|
|
336
|
+
/** See `StorefrontDeliveryConfig.coverSize`. */
|
|
337
|
+
export type StorefrontCoverSize = 'full' | 'compact';
|
|
324
338
|
/** Entrega ou retirada, do ponto de vista da vitrine. */
|
|
325
339
|
export type FulfillmentMode = 'delivery' | 'pickup';
|
|
326
340
|
export interface StorefrontDeliveryConfig {
|
|
@@ -336,6 +350,15 @@ export interface StorefrontDeliveryConfig {
|
|
|
336
350
|
coverImage?: string;
|
|
337
351
|
/** O logo, no quadrado sobre a capa. Cai para a inicial do nome. */
|
|
338
352
|
logoImage?: string;
|
|
353
|
+
/**
|
|
354
|
+
* How much of the first screen the cover takes. 'full' (default) is the
|
|
355
|
+
* cover as a store styles it; 'compact' shrinks it to a band so the first
|
|
356
|
+
* dishes — photo, price, add button — are visible without scrolling on a
|
|
357
|
+
* phone. The cover carries `data-cover-size`, so a store's own cover CSS can
|
|
358
|
+
* follow it. Bindable to an experiment:
|
|
359
|
+
* `{ experiment: 'menu-cover-compact', variants: { control: 'full', compact: 'compact' } }`.
|
|
360
|
+
*/
|
|
361
|
+
coverSize?: Experimental<StorefrontCoverSize>;
|
|
339
362
|
/** "Rio de Janeiro, RJ" — a linha sob o nome. */
|
|
340
363
|
locality?: string;
|
|
341
364
|
/**
|
|
@@ -401,6 +424,7 @@ export interface ResolvedStorefrontConfig extends StorefrontConfig {
|
|
|
401
424
|
menuPath: string;
|
|
402
425
|
coverImage?: string;
|
|
403
426
|
logoImage?: string;
|
|
427
|
+
coverSize?: StorefrontDeliveryConfig['coverSize'];
|
|
404
428
|
locality?: string;
|
|
405
429
|
highlightSlugs?: readonly string[];
|
|
406
430
|
fulfillmentModes: readonly FulfillmentMode[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/document/config.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/document/config.ts"],"names":[],"mappings":"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"}
|
package/dist/edge.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export { posthogProxy, isPostHogProxyPath, type PostHogProxyOptions } from './analytics/edge';
|
|
2
|
-
export { createStorefrontEdge, serveStorageImage, isStorageRequest, imageFormatKey, edgeCacheKey, edgeCacheable, type StorefrontEdgeOptions, } from './host/edge-handler';
|
|
2
|
+
export { createStorefrontEdge, serveStorageImage, isStorageRequest, imageFormatKey, edgeCacheKey, edgeCacheable, assignForRequest, type StorefrontEdgeOptions, type StorefrontEdgeExperiments, } from './host/edge-handler';
|
|
3
|
+
export { assignExperiments, posthogHash, posthogVariant, inPosthogRollout, experimentVariantTable, runningExperiments, isBotUserAgent, readVisitorId, visitorCookie, experimentCacheSuffix, encodeExperimentHeader, decodeExperimentHeader, validateExperiments, EXPERIMENT_HEADER, VISITOR_COOKIE, CONTROL, type ExperimentAssignments, type ExperimentAssignment, type StorefrontExperiment, } from './experiments/assign';
|
|
3
4
|
//# sourceMappingURL=edge.d.ts.map
|
package/dist/edge.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"edge.d.ts","sourceRoot":"","sources":["../src/edge.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,KAAK,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AAC7F,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,YAAY,EACZ,aAAa,EACb,KAAK,qBAAqB,
|
|
1
|
+
{"version":3,"file":"edge.d.ts","sourceRoot":"","sources":["../src/edge.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,KAAK,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AAC7F,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,YAAY,EACZ,aAAa,EACb,gBAAgB,EAChB,KAAK,qBAAqB,EAC1B,KAAK,yBAAyB,GAC/B,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACL,iBAAiB,EACjB,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,sBAAsB,EACtB,kBAAkB,EAClB,cAAc,EACd,aAAa,EACb,aAAa,EACb,qBAAqB,EACrB,sBAAsB,EACtB,sBAAsB,EACtB,mBAAmB,EACnB,iBAAiB,EACjB,cAAc,EACd,OAAO,EACP,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,GAC1B,MAAM,sBAAsB,CAAA"}
|
package/dist/edge.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { runningExperiments, NO_ASSIGNMENTS, isBotUserAgent, readPinnedVisitorId, readVisitorId, isPinnableVisitorId, visitorCookie, assignExperiments, experimentCacheSuffix, EXPERIMENT_HEADER, encodeExperimentHeader } from './chunk-4REZOGGW.js';
|
|
2
|
+
export { CONTROL, EXPERIMENT_HEADER, VISITOR_COOKIE, assignExperiments, decodeExperimentHeader, encodeExperimentHeader, experimentCacheSuffix, experimentVariantTable, inPosthogRollout, isBotUserAgent, posthogHash, posthogVariant, readVisitorId, runningExperiments, validateExperiments, visitorCookie } from './chunk-4REZOGGW.js';
|
|
3
|
+
|
|
1
4
|
// src/analytics/edge.ts
|
|
2
5
|
function isPostHogProxyPath(pathname, prefix = "/ingest") {
|
|
3
6
|
return pathname === prefix || pathname.startsWith(`${prefix}/`);
|
|
@@ -58,7 +61,7 @@ async function serveStorageImage(request, url, supabaseUrl) {
|
|
|
58
61
|
headers.set("vary", "Accept");
|
|
59
62
|
return new Response(response.body, { status: 200, headers });
|
|
60
63
|
}
|
|
61
|
-
function edgeCacheKey(request, buildId) {
|
|
64
|
+
function edgeCacheKey(request, buildId, variant = "") {
|
|
62
65
|
if (request.method !== "GET") return null;
|
|
63
66
|
const url = new URL(request.url);
|
|
64
67
|
for (const key of [...url.searchParams.keys()]) {
|
|
@@ -67,6 +70,7 @@ function edgeCacheKey(request, buildId) {
|
|
|
67
70
|
url.hash = "";
|
|
68
71
|
if (isStorageRequest(url)) url.searchParams.set("_fmt", imageFormatKey(request));
|
|
69
72
|
url.searchParams.set("_build", buildId);
|
|
73
|
+
if (variant) url.searchParams.set("_exp", variant);
|
|
70
74
|
return new Request(url.toString(), { method: "GET" });
|
|
71
75
|
}
|
|
72
76
|
function edgeCacheable(response) {
|
|
@@ -79,6 +83,45 @@ function withHeader(response, name, value) {
|
|
|
79
83
|
headers.set(name, value);
|
|
80
84
|
return new Response(response.body, { status: response.status, statusText: response.statusText, headers });
|
|
81
85
|
}
|
|
86
|
+
function withCookies(response, cookies) {
|
|
87
|
+
if (!cookies.length) return response;
|
|
88
|
+
const headers = new Headers(response.headers);
|
|
89
|
+
for (const cookie of cookies) headers.append("set-cookie", cookie);
|
|
90
|
+
return new Response(response.body, { status: response.status, statusText: response.statusText, headers });
|
|
91
|
+
}
|
|
92
|
+
function isPageRequest(request, url) {
|
|
93
|
+
if (request.method !== "GET") return false;
|
|
94
|
+
if (isStorageRequest(url) || isPostHogProxyPath(url.pathname)) return false;
|
|
95
|
+
if (/\.[a-z0-9]{1,8}$/i.test(url.pathname)) return false;
|
|
96
|
+
if (url.pathname.startsWith("/_serverFn") || url.pathname.startsWith("/_server")) return false;
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
async function assignForRequest(request, options) {
|
|
100
|
+
const running = runningExperiments(options.declared);
|
|
101
|
+
const keys = Object.keys(running);
|
|
102
|
+
const none = { assignments: NO_ASSIGNMENTS, variant: "", cookies: [] };
|
|
103
|
+
if (!keys.length) return none;
|
|
104
|
+
if (isBotUserAgent(request.headers.get("user-agent"))) return none;
|
|
105
|
+
const cookieHeader = request.headers.get("cookie");
|
|
106
|
+
const pinned = readPinnedVisitorId(cookieHeader);
|
|
107
|
+
const known = pinned ?? readVisitorId(cookieHeader, options.posthogKey ?? "");
|
|
108
|
+
const distinctId = known && isPinnableVisitorId(known) ? known : crypto.randomUUID();
|
|
109
|
+
const cookies = pinned ? [] : [visitorCookie(distinctId, new URL(request.url).protocol === "https:")];
|
|
110
|
+
try {
|
|
111
|
+
const assignments = await assignExperiments({ experiments: running, distinctId });
|
|
112
|
+
return { assignments, variant: experimentCacheSuffix(assignments, keys), cookies };
|
|
113
|
+
} catch {
|
|
114
|
+
return { ...none, cookies };
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
function withAssignment(request, assignments) {
|
|
118
|
+
const headers = new Headers(request.headers);
|
|
119
|
+
headers.delete(EXPERIMENT_HEADER);
|
|
120
|
+
if (Object.keys(assignments.flags).length) {
|
|
121
|
+
headers.set(EXPERIMENT_HEADER, encodeExperimentHeader({ flags: assignments.flags }));
|
|
122
|
+
}
|
|
123
|
+
return new Request(request, { headers });
|
|
124
|
+
}
|
|
82
125
|
function createStorefrontEdge(options) {
|
|
83
126
|
async function respond(request) {
|
|
84
127
|
const url = new URL(request.url);
|
|
@@ -87,20 +130,24 @@ function createStorefrontEdge(options) {
|
|
|
87
130
|
if (options.isCanonicalHost(url)) return response;
|
|
88
131
|
return withHeader(response, "x-robots-tag", "noindex, nofollow");
|
|
89
132
|
}
|
|
90
|
-
return async (
|
|
91
|
-
|
|
92
|
-
if (
|
|
93
|
-
const
|
|
94
|
-
|
|
133
|
+
return async (incoming) => {
|
|
134
|
+
const url = new URL(incoming.url);
|
|
135
|
+
if (isPostHogProxyPath(url.pathname)) return posthogProxy(incoming);
|
|
136
|
+
const page = options.experiments && isPageRequest(incoming, url) ? await assignForRequest(incoming, options.experiments) : null;
|
|
137
|
+
const request = page ? withAssignment(incoming, page.assignments) : incoming;
|
|
138
|
+
const finish = (response2) => withCookies(response2, page?.cookies ?? []);
|
|
139
|
+
if (options.dev || !options.cache) return finish(await respond(request));
|
|
140
|
+
const key = edgeCacheKey(request, options.buildId, page?.variant ?? "");
|
|
141
|
+
if (!key) return finish(await respond(request));
|
|
95
142
|
const hit = await options.cache.match(key);
|
|
96
|
-
if (hit) return withHeader(hit, "x-edge-cache", "HIT");
|
|
143
|
+
if (hit) return finish(withHeader(hit, "x-edge-cache", "HIT"));
|
|
97
144
|
const response = await respond(request);
|
|
98
|
-
if (!edgeCacheable(response)) return withHeader(response, "x-edge-cache", "BYPASS");
|
|
145
|
+
if (!edgeCacheable(response)) return finish(withHeader(response, "x-edge-cache", "BYPASS"));
|
|
99
146
|
options.waitUntil(options.cache.put(key, response.clone()));
|
|
100
|
-
return withHeader(response, "x-edge-cache", "MISS");
|
|
147
|
+
return finish(withHeader(response, "x-edge-cache", "MISS"));
|
|
101
148
|
};
|
|
102
149
|
}
|
|
103
150
|
|
|
104
|
-
export { createStorefrontEdge, edgeCacheKey, edgeCacheable, imageFormatKey, isPostHogProxyPath, isStorageRequest, posthogProxy, serveStorageImage };
|
|
151
|
+
export { assignForRequest, createStorefrontEdge, edgeCacheKey, edgeCacheable, imageFormatKey, isPostHogProxyPath, isStorageRequest, posthogProxy, serveStorageImage };
|
|
105
152
|
//# sourceMappingURL=edge.js.map
|
|
106
153
|
//# sourceMappingURL=edge.js.map
|
package/dist/edge.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/analytics/edge.ts","../src/host/edge-handler.ts"],"names":[],"mappings":"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","file":"edge.js","sourcesContent":["/**\n * The store's own door to PostHog, for a Worker (or any fetch-style) host.\n *\n * Events sent to the store's domain under `/ingest` are not dropped by ad\n * blockers the way requests to a known analytics host are, and the store needs\n * no PostHog setting of its own: every store forwards to the same project.\n *\n * if (url.pathname.startsWith('/ingest')) return posthogProxy(request)\n */\nexport interface PostHogProxyOptions {\n /** The path the storefront's analytics client sends to. Default `/ingest`. */\n prefix?: string\n /** PostHog's region. Default `us`. */\n region?: 'us' | 'eu'\n}\n\nexport function isPostHogProxyPath(pathname: string, prefix = '/ingest'): boolean {\n return pathname === prefix || pathname.startsWith(`${prefix}/`)\n}\n\nexport async function posthogProxy(request: Request, options: PostHogProxyOptions = {}): Promise<Response> {\n const prefix = options.prefix ?? '/ingest'\n const region = options.region ?? 'us'\n const url = new URL(request.url)\n const path = url.pathname.slice(prefix.length) || '/'\n // The SDK's script and its remote config live on the assets host.\n const host = path.startsWith('/static/') || path.startsWith('/array/')\n ? `${region}-assets.i.posthog.com`\n : `${region}.i.posthog.com`\n const target = new URL(`https://${host}${path}${url.search}`)\n\n const headers = new Headers(request.headers)\n headers.delete('cookie')\n headers.set('host', host)\n // PostHog geolocates from the visitor, not from the Worker.\n const ip = request.headers.get('cf-connecting-ip') ?? request.headers.get('x-forwarded-for')\n if (ip) headers.set('x-forwarded-for', ip)\n\n const init: RequestInit = { method: request.method, headers, redirect: 'manual' }\n if (request.method !== 'GET' && request.method !== 'HEAD') init.body = await request.arrayBuffer()\n const response = await fetch(target, init)\n const out = new Response(response.body, response)\n out.headers.delete('set-cookie')\n return out\n}\n","import { isPostHogProxyPath, posthogProxy } from '../analytics/edge'\n\n// ---------------------------------------------------------------------------\n// The Worker in front of a server-rendered store.\n//\n// Four jobs a store's request handler has before the framework renders\n// anything, first written for artorious-shop and the same for every store:\n//\n// 1. Analytics through the store's own domain (`/ingest` → PostHog), so ad\n// blockers that drop requests to a known analytics host do not drop it.\n// 2. The store's photos from the store's own origin. The bytes live in\n// Supabase Storage; a photo addressed at the storage project is a second\n// origin the browser pays DNS + TLS for (measured 156–241 ms TTFB against\n// 112–141 ms same-origin). Only public objects of the `shop-images`\n// bucket are forwarded — this is not a general proxy.\n// 3. A real edge cache. Public pages already leave with `Cache-Control:\n// public, s-maxage=…`, but on workers.dev nothing in front honours it, so\n// every view paid the full render. The Workers Cache API makes the header\n// mean what it says. Marketing parameters (utm_*, fbclid…) are dropped\n// from the key: ad traffic hits the same entry as everyone else.\n// 4. `X-Robots-Tag: noindex` on any host that is not the store's address, so\n// the deployment URL never competes with the domain.\n// ---------------------------------------------------------------------------\n\n/** `/storage/v1/object/public/shop-images/…` or the `render/image` variant of it. */\nconst STORAGE_PATH = /^\\/storage\\/v1\\/(object|render\\/image)\\/public\\/(shop-images\\/[^?#]+)$/\n\n/** Query parameters the renderer understands. Anything else is dropped rather\n * than forwarded, so a crawler cannot mint unlimited distinct variants. */\nconst RENDER_PARAMS = new Set(['width', 'height', 'quality', 'format', 'resize'])\n\n/** A year: the object path carries a timestamp and is never overwritten. */\nconst IMMUTABLE = 'public, max-age=31536000, s-maxage=31536000, immutable'\n\nconst TRACKING_PARAM = /^(utm_[a-z0-9_]+|fbclid|gclid|gbraid|wbraid|msclkid|ttclid|igshid|mc_cid|mc_eid|_ga|ref)$/i\n\nexport function isStorageRequest(url: URL): boolean {\n return STORAGE_PATH.test(url.pathname)\n}\n\n/**\n * Which format this visitor gets — the only part of the request, besides the\n * URL, that changes the bytes. The renderer answers WebP or the original\n * depending on `accept` and declares no `Vary`, so every cache in front of it\n * has to put the answer in the key itself.\n */\nexport function imageFormatKey(request: Request): 'webp' | 'orig' {\n return /image\\/webp/.test(request.headers.get('accept') ?? '') ? 'webp' : 'orig'\n}\n\n/** Answer a storage request from Supabase, on the store's own origin. */\nexport async function serveStorageImage(request: Request, url: URL, supabaseUrl: string | undefined): Promise<Response> {\n const match = STORAGE_PATH.exec(url.pathname)\n if (!match) return new Response('Not found', { status: 404 })\n const base = supabaseUrl?.replace(/\\/$/, '')\n if (!base) return new Response('Storage is not configured', { status: 502 })\n\n const [, kind, objectPath] = match\n const upstream = new URL(`${base}/storage/v1/${kind}/public/${objectPath}`)\n for (const [key, value] of url.searchParams) {\n if (RENDER_PARAMS.has(key)) upstream.searchParams.set(key, value)\n }\n // A canonical `accept`, not the visitor's verbatim: two browsers that both\n // take WebP must produce the same upstream request.\n const webp = imageFormatKey(request) === 'webp'\n const response = await fetch(upstream.toString(), { headers: { accept: webp ? 'image/webp,image/*;q=0.8' : 'image/*' } })\n if (!response.ok) {\n // Upstream's status is passed through (a deleted photo must not look like\n // a 200), never its cache directives.\n return new Response(response.status === 404 ? 'Not found' : 'Upstream error', {\n status: response.status === 404 ? 404 : 502,\n headers: { 'cache-control': 'public, max-age=60' },\n })\n }\n const headers = new Headers()\n headers.set('content-type', response.headers.get('content-type') ?? 'image/jpeg')\n headers.set('cache-control', IMMUTABLE)\n headers.set('x-image-origin', 'supabase')\n headers.set('vary', 'Accept')\n return new Response(response.body, { status: 200, headers })\n}\n\n/** The cache key for a request, or null when it is not cacheable. */\nexport function edgeCacheKey(request: Request, buildId: string): Request | null {\n if (request.method !== 'GET') return null\n const url = new URL(request.url)\n for (const key of [...url.searchParams.keys()]) {\n if (TRACKING_PARAM.test(key)) url.searchParams.delete(key)\n }\n url.hash = ''\n if (isStorageRequest(url)) url.searchParams.set('_fmt', imageFormatKey(request))\n // Cached HTML names this build's hashed chunks, and a deploy deletes them.\n // Keyed by build, old pages stop matching the moment the new Worker serves.\n url.searchParams.set('_build', buildId)\n return new Request(url.toString(), { method: 'GET' })\n}\n\n/** Only what the response itself declares shareable and fresh for a while. */\nexport function edgeCacheable(response: Response): boolean {\n if (response.status !== 200) return false\n const cc = response.headers.get('cache-control') ?? ''\n return /\\bpublic\\b/.test(cc) && /\\bs-maxage=[1-9]\\d*/.test(cc) && !/\\b(no-store|private)\\b/.test(cc)\n}\n\nfunction withHeader(response: Response, name: string, value: string): Response {\n const headers = new Headers(response.headers)\n headers.set(name, value)\n return new Response(response.body, { status: response.status, statusText: response.statusText, headers })\n}\n\nexport interface StorefrontEdgeOptions {\n /** The framework's own handler (TanStack Start's `handler.fetch`). */\n render(request: Request): Response | Promise<Response>\n /** From the store host: `host.isCanonicalHost`. */\n isCanonicalHost(url: URL): boolean\n /** One id per build, for the cache key. */\n buildId: string\n /** The Supabase project the photos live in (`PUBLIC_SUPABASE_URL`). */\n supabaseUrl?: string\n /** Keeps the Worker alive past the response (`waitUntil` from 'cloudflare:workers'). */\n waitUntil(promise: Promise<unknown>): void\n /** The Workers cache (`caches.default`). Omitted: no edge cache. */\n cache?: Cache\n /**\n * Development: NEVER cache. The Cloudflare vite plugin runs the Worker in\n * workerd locally too, and an entry cannot be purged, only outlived — a\n * price edited and reloaded shows the old one with nothing in the browser\n * able to help.\n */\n dev?: boolean\n}\n\n/** The Worker's `fetch`, from the store's pieces. */\nexport function createStorefrontEdge(options: StorefrontEdgeOptions): (request: Request) => Promise<Response> {\n async function respond(request: Request): Promise<Response> {\n const url = new URL(request.url)\n if (isStorageRequest(url)) return serveStorageImage(request, url, options.supabaseUrl)\n const response = await options.render(request)\n if (options.isCanonicalHost(url)) return response\n return withHeader(response, 'x-robots-tag', 'noindex, nofollow')\n }\n\n return async (request) => {\n // Analytics leaves through the store's own domain, never cached.\n if (isPostHogProxyPath(new URL(request.url).pathname)) return posthogProxy(request)\n if (options.dev || !options.cache) return respond(request)\n\n const key = edgeCacheKey(request, options.buildId)\n if (!key) return respond(request)\n const hit = await options.cache.match(key)\n if (hit) return withHeader(hit, 'x-edge-cache', 'HIT')\n\n const response = await respond(request)\n if (!edgeCacheable(response)) return withHeader(response, 'x-edge-cache', 'BYPASS')\n options.waitUntil(options.cache.put(key, response.clone()))\n return withHeader(response, 'x-edge-cache', 'MISS')\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/analytics/edge.ts","../src/host/edge-handler.ts"],"names":["response"],"mappings":"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","file":"edge.js","sourcesContent":["/**\n * The store's own door to PostHog, for a Worker (or any fetch-style) host.\n *\n * Events sent to the store's domain under `/ingest` are not dropped by ad\n * blockers the way requests to a known analytics host are, and the store needs\n * no PostHog setting of its own: every store forwards to the same project.\n *\n * if (url.pathname.startsWith('/ingest')) return posthogProxy(request)\n */\nexport interface PostHogProxyOptions {\n /** The path the storefront's analytics client sends to. Default `/ingest`. */\n prefix?: string\n /** PostHog's region. Default `us`. */\n region?: 'us' | 'eu'\n}\n\nexport function isPostHogProxyPath(pathname: string, prefix = '/ingest'): boolean {\n return pathname === prefix || pathname.startsWith(`${prefix}/`)\n}\n\nexport async function posthogProxy(request: Request, options: PostHogProxyOptions = {}): Promise<Response> {\n const prefix = options.prefix ?? '/ingest'\n const region = options.region ?? 'us'\n const url = new URL(request.url)\n const path = url.pathname.slice(prefix.length) || '/'\n // The SDK's script and its remote config live on the assets host.\n const host = path.startsWith('/static/') || path.startsWith('/array/')\n ? `${region}-assets.i.posthog.com`\n : `${region}.i.posthog.com`\n const target = new URL(`https://${host}${path}${url.search}`)\n\n const headers = new Headers(request.headers)\n headers.delete('cookie')\n headers.set('host', host)\n // PostHog geolocates from the visitor, not from the Worker.\n const ip = request.headers.get('cf-connecting-ip') ?? request.headers.get('x-forwarded-for')\n if (ip) headers.set('x-forwarded-for', ip)\n\n const init: RequestInit = { method: request.method, headers, redirect: 'manual' }\n if (request.method !== 'GET' && request.method !== 'HEAD') init.body = await request.arrayBuffer()\n const response = await fetch(target, init)\n const out = new Response(response.body, response)\n out.headers.delete('set-cookie')\n return out\n}\n","import { isPostHogProxyPath, posthogProxy } from '../analytics/edge'\nimport {\n EXPERIMENT_HEADER,\n NO_ASSIGNMENTS,\n assignExperiments,\n encodeExperimentHeader,\n experimentCacheSuffix,\n runningExperiments,\n isBotUserAgent,\n readVisitorId,\n readPinnedVisitorId,\n isPinnableVisitorId,\n visitorCookie,\n type ExperimentAssignments,\n type StorefrontExperiment,\n} from '../experiments/assign'\n\n// ---------------------------------------------------------------------------\n// The Worker in front of a server-rendered store.\n//\n// Five jobs a store's request handler has before the framework renders\n// anything, first written for artorious-shop and the same for every store:\n//\n// 1. Analytics through the store's own domain (`/ingest` → PostHog), so ad\n// blockers that drop requests to a known analytics host do not drop it.\n// 2. The store's photos from the store's own origin. The bytes live in\n// Supabase Storage; a photo addressed at the storage project is a second\n// origin the browser pays DNS + TLS for (measured 156–241 ms TTFB against\n// 112–141 ms same-origin). Only public objects of the `shop-images`\n// bucket are forwarded — this is not a general proxy.\n// 3. A real edge cache. Public pages already leave with `Cache-Control:\n// public, s-maxage=…`, but on workers.dev nothing in front honours it, so\n// every view paid the full render. The Workers Cache API makes the header\n// mean what it says. Marketing parameters (utm_*, fbclid…) are dropped\n// from the key: ad traffic hits the same entry as everyone else.\n// 4. `X-Robots-Tag: noindex` on any host that is not the store's address, so\n// the deployment URL never competes with the domain.\n// 5. A/B assignment. With a running experiment, every page request is\n// assigned its variants HERE, before render, locally with PostHog's\n// bucketing (experiments/assign.ts — no network), and the edge cache is\n// keyed by them: one entry per combination of variants, so a cached page\n// is never one visitor's variant served to another.\n// ---------------------------------------------------------------------------\n\n/** `/storage/v1/object/public/shop-images/…` or the `render/image` variant of it. */\nconst STORAGE_PATH = /^\\/storage\\/v1\\/(object|render\\/image)\\/public\\/(shop-images\\/[^?#]+)$/\n\n/** Query parameters the renderer understands. Anything else is dropped rather\n * than forwarded, so a crawler cannot mint unlimited distinct variants. */\nconst RENDER_PARAMS = new Set(['width', 'height', 'quality', 'format', 'resize'])\n\n/** A year: the object path carries a timestamp and is never overwritten. */\nconst IMMUTABLE = 'public, max-age=31536000, s-maxage=31536000, immutable'\n\nconst TRACKING_PARAM = /^(utm_[a-z0-9_]+|fbclid|gclid|gbraid|wbraid|msclkid|ttclid|igshid|mc_cid|mc_eid|_ga|ref)$/i\n\nexport function isStorageRequest(url: URL): boolean {\n return STORAGE_PATH.test(url.pathname)\n}\n\n/**\n * Which format this visitor gets — the only part of the request, besides the\n * URL, that changes the bytes. The renderer answers WebP or the original\n * depending on `accept` and declares no `Vary`, so every cache in front of it\n * has to put the answer in the key itself.\n */\nexport function imageFormatKey(request: Request): 'webp' | 'orig' {\n return /image\\/webp/.test(request.headers.get('accept') ?? '') ? 'webp' : 'orig'\n}\n\n/** Answer a storage request from Supabase, on the store's own origin. */\nexport async function serveStorageImage(request: Request, url: URL, supabaseUrl: string | undefined): Promise<Response> {\n const match = STORAGE_PATH.exec(url.pathname)\n if (!match) return new Response('Not found', { status: 404 })\n const base = supabaseUrl?.replace(/\\/$/, '')\n if (!base) return new Response('Storage is not configured', { status: 502 })\n\n const [, kind, objectPath] = match\n const upstream = new URL(`${base}/storage/v1/${kind}/public/${objectPath}`)\n for (const [key, value] of url.searchParams) {\n if (RENDER_PARAMS.has(key)) upstream.searchParams.set(key, value)\n }\n // A canonical `accept`, not the visitor's verbatim: two browsers that both\n // take WebP must produce the same upstream request.\n const webp = imageFormatKey(request) === 'webp'\n const response = await fetch(upstream.toString(), { headers: { accept: webp ? 'image/webp,image/*;q=0.8' : 'image/*' } })\n if (!response.ok) {\n // Upstream's status is passed through (a deleted photo must not look like\n // a 200), never its cache directives.\n return new Response(response.status === 404 ? 'Not found' : 'Upstream error', {\n status: response.status === 404 ? 404 : 502,\n headers: { 'cache-control': 'public, max-age=60' },\n })\n }\n const headers = new Headers()\n headers.set('content-type', response.headers.get('content-type') ?? 'image/jpeg')\n headers.set('cache-control', IMMUTABLE)\n headers.set('x-image-origin', 'supabase')\n headers.set('vary', 'Accept')\n return new Response(response.body, { status: 200, headers })\n}\n\n/** The cache key for a request, or null when it is not cacheable. `variant`\n * is the experiment part (`experimentCacheSuffix`); empty means control. */\nexport function edgeCacheKey(request: Request, buildId: string, variant = ''): Request | null {\n if (request.method !== 'GET') return null\n const url = new URL(request.url)\n for (const key of [...url.searchParams.keys()]) {\n if (TRACKING_PARAM.test(key)) url.searchParams.delete(key)\n }\n url.hash = ''\n if (isStorageRequest(url)) url.searchParams.set('_fmt', imageFormatKey(request))\n // Cached HTML names this build's hashed chunks, and a deploy deletes them.\n // Keyed by build, old pages stop matching the moment the new Worker serves.\n url.searchParams.set('_build', buildId)\n if (variant) url.searchParams.set('_exp', variant)\n return new Request(url.toString(), { method: 'GET' })\n}\n\n/** Only what the response itself declares shareable and fresh for a while. */\nexport function edgeCacheable(response: Response): boolean {\n if (response.status !== 200) return false\n const cc = response.headers.get('cache-control') ?? ''\n return /\\bpublic\\b/.test(cc) && /\\bs-maxage=[1-9]\\d*/.test(cc) && !/\\b(no-store|private)\\b/.test(cc)\n}\n\nfunction withHeader(response: Response, name: string, value: string): Response {\n const headers = new Headers(response.headers)\n headers.set(name, value)\n return new Response(response.body, { status: response.status, statusText: response.statusText, headers })\n}\n\n/** Adds cookies without touching the ones the page already sets. */\nfunction withCookies(response: Response, cookies: readonly string[]): Response {\n if (!cookies.length) return response\n const headers = new Headers(response.headers)\n for (const cookie of cookies) headers.append('set-cookie', cookie)\n return new Response(response.body, { status: response.status, statusText: response.statusText, headers })\n}\n\nexport interface StorefrontEdgeOptions {\n /** The framework's own handler (TanStack Start's `handler.fetch`). */\n render(request: Request): Response | Promise<Response>\n /** From the store host: `host.isCanonicalHost`. */\n isCanonicalHost(url: URL): boolean\n /** One id per build, for the cache key. */\n buildId: string\n /** The Supabase project the photos live in (`PUBLIC_SUPABASE_URL`). */\n supabaseUrl?: string\n /** Keeps the Worker alive past the response (`waitUntil` from 'cloudflare:workers'). */\n waitUntil(promise: Promise<unknown>): void\n /** The Workers cache (`caches.default`). Omitted: no edge cache. */\n cache?: Cache\n /**\n * Development: NEVER cache. The Cloudflare vite plugin runs the Worker in\n * workerd locally too, and an entry cannot be purged, only outlived — a\n * price edited and reloaded shows the old one with nothing in the browser\n * able to help.\n */\n dev?: boolean\n /**\n * A/B tests: the store's declared experiments (`config.experiments`).\n * Nothing running: no assignment, no cookie, the cache key is the page's\n * alone — exactly the handler without tests.\n */\n experiments?: StorefrontEdgeExperiments\n}\n\nexport interface StorefrontEdgeExperiments {\n declared: Record<string, StorefrontExperiment> | undefined\n /**\n * The PostHog project token (`phc_…`), the same the storefront sends with —\n * used only to read PostHog's own cookie, so a returning visitor is bucketed\n * by the id PostHog already knows them by. Optional: without it, `fz_vid`.\n */\n posthogKey?: string\n}\n\n/** A page a visitor navigates to — not an asset, a photo, a feed or a POST. */\nfunction isPageRequest(request: Request, url: URL): boolean {\n if (request.method !== 'GET') return false\n if (isStorageRequest(url) || isPostHogProxyPath(url.pathname)) return false\n // Hashed bundles, fonts, images, the sitemap: anything with an extension.\n if (/\\.[a-z0-9]{1,8}$/i.test(url.pathname)) return false\n // TanStack's server functions and the router's data requests.\n if (url.pathname.startsWith('/_serverFn') || url.pathname.startsWith('/_server')) return false\n return true\n}\n\ninterface PageAssignment {\n assignments: ExperimentAssignments\n /** The cache-key part; empty for control. */\n variant: string\n /** Cookies for THIS visitor's response: a new id. */\n cookies: string[]\n}\n\n/**\n * Decide this request's variants — locally, with PostHog's bucketing, no\n * network. Never throws.\n */\nexport async function assignForRequest(request: Request, options: StorefrontEdgeExperiments): Promise<PageAssignment> {\n const running = runningExperiments(options.declared)\n const keys = Object.keys(running)\n const none: PageAssignment = { assignments: NO_ASSIGNMENTS, variant: '', cookies: [] }\n // Nothing running: no id, no cookie, the page's plain cache entry.\n if (!keys.length) return none\n // Crawlers and unfurlers see control and get no id: what is indexed and\n // shared must not depend on a coin flip, and a bot is not an exposure.\n if (isBotUserAgent(request.headers.get('user-agent'))) return none\n const cookieHeader = request.headers.get('cookie')\n // The bucket id is pinned in `fz_vid` the first time and read from there\n // ever after. A returning visitor without one is pinned to the anonymous id\n // PostHog already knows them by; an identified id (an e-mail) is never\n // stored — they get a fresh anonymous one.\n const pinned = readPinnedVisitorId(cookieHeader)\n const known = pinned ?? readVisitorId(cookieHeader, options.posthogKey ?? '')\n const distinctId = known && isPinnableVisitorId(known) ? known : crypto.randomUUID()\n const cookies = pinned ? [] : [visitorCookie(distinctId, new URL(request.url).protocol === 'https:')]\n try {\n const assignments = await assignExperiments({ experiments: running, distinctId })\n return { assignments, variant: experimentCacheSuffix(assignments, keys), cookies }\n } catch {\n // No SubtleCrypto (not a Worker, not a modern runtime): everyone control.\n return { ...none, cookies }\n }\n}\n\n/**\n * The request the renderer sees: the same, plus the variants — and ONLY the\n * variants. The visitor id stays out of the header on purpose: the rendered\n * HTML is cached and shared by every visitor in the same variant bucket, and\n * an id in it would hand one visitor's identity to the next. The browser\n * reads its own id from the cookie (`readVisitorId(document.cookie, …)`).\n */\nfunction withAssignment(request: Request, assignments: ExperimentAssignments): Request {\n const headers = new Headers(request.headers)\n headers.delete(EXPERIMENT_HEADER) // never trust one the visitor sent\n if (Object.keys(assignments.flags).length) {\n headers.set(EXPERIMENT_HEADER, encodeExperimentHeader({ flags: assignments.flags }))\n }\n return new Request(request, { headers })\n}\n\n/** The Worker's `fetch`, from the store's pieces. */\nexport function createStorefrontEdge(options: StorefrontEdgeOptions): (request: Request) => Promise<Response> {\n async function respond(request: Request): Promise<Response> {\n const url = new URL(request.url)\n if (isStorageRequest(url)) return serveStorageImage(request, url, options.supabaseUrl)\n const response = await options.render(request)\n if (options.isCanonicalHost(url)) return response\n return withHeader(response, 'x-robots-tag', 'noindex, nofollow')\n }\n\n return async (incoming) => {\n const url = new URL(incoming.url)\n // Analytics leaves through the store's own domain, never cached.\n if (isPostHogProxyPath(url.pathname)) return posthogProxy(incoming)\n\n // Variants first: they change the HTML, so they are part of the cache key.\n const page = options.experiments && isPageRequest(incoming, url)\n ? await assignForRequest(incoming, options.experiments)\n : null\n const request = page ? withAssignment(incoming, page.assignments) : incoming\n // Cookies are added to what THIS visitor receives, never to the cached\n // copy (a shared entry carrying one visitor's id would hand it to the\n // next), and appended, so a cookie the page itself sets survives.\n const finish = (response: Response) => withCookies(response, page?.cookies ?? [])\n\n if (options.dev || !options.cache) return finish(await respond(request))\n\n const key = edgeCacheKey(request, options.buildId, page?.variant ?? '')\n if (!key) return finish(await respond(request))\n const hit = await options.cache.match(key)\n if (hit) return finish(withHeader(hit, 'x-edge-cache', 'HIT'))\n\n const response = await respond(request)\n if (!edgeCacheable(response)) return finish(withHeader(response, 'x-edge-cache', 'BYPASS'))\n options.waitUntil(options.cache.put(key, response.clone()))\n return finish(withHeader(response, 'x-edge-cache', 'MISS'))\n }\n}\n"]}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/** The variant every visitor gets when nothing else can be decided. */
|
|
2
|
+
export declare const CONTROL = "control";
|
|
3
|
+
/** Request header the edge hands the assignment to the renderer in. */
|
|
4
|
+
export declare const EXPERIMENT_HEADER = "x-fayz-experiments";
|
|
5
|
+
/** First-party cookie holding the anonymous id when PostHog has not set one yet. */
|
|
6
|
+
export declare const VISITOR_COOKIE = "fz_vid";
|
|
7
|
+
/** One experiment the store runs. */
|
|
8
|
+
export interface StorefrontExperiment {
|
|
9
|
+
/**
|
|
10
|
+
* The variant keys, in the order the PostHog flag lists them (the order
|
|
11
|
+
* buckets are laid out in). Must include 'control'.
|
|
12
|
+
*/
|
|
13
|
+
variants: readonly string[];
|
|
14
|
+
/**
|
|
15
|
+
* 'running' assigns visitors; 'off' (the default) shows everyone control and
|
|
16
|
+
* counts no one. Launching or stopping a test is flipping this and deploying.
|
|
17
|
+
*/
|
|
18
|
+
status?: 'running' | 'off';
|
|
19
|
+
/** Percent of visitors per variant, summing to 100. Default: even, remainder to the first. */
|
|
20
|
+
split?: Readonly<Record<string, number>>;
|
|
21
|
+
/** Percent of visitors in the experiment at all (the rest see control, uncounted). Default 100. */
|
|
22
|
+
rollout?: number;
|
|
23
|
+
/** What is being tested and why — for whoever reads the config next. */
|
|
24
|
+
description?: string;
|
|
25
|
+
}
|
|
26
|
+
/** What a visitor sees for one experiment. */
|
|
27
|
+
export interface ExperimentAssignment {
|
|
28
|
+
variant: string;
|
|
29
|
+
/** Reserved for per-variant data. Local assignment does not set it. */
|
|
30
|
+
payload?: unknown;
|
|
31
|
+
}
|
|
32
|
+
/** Everything the edge decided for one request. */
|
|
33
|
+
export interface ExperimentAssignments {
|
|
34
|
+
/** The id the variants were computed for. Kept at the edge: it never
|
|
35
|
+
* travels into the rendered (and cached) page — see `withAssignment`. */
|
|
36
|
+
distinctId?: string;
|
|
37
|
+
/**
|
|
38
|
+
* By flag key, ONLY the experiments this visitor is in — 'control' included
|
|
39
|
+
* when bucketed into control. A declared key missing here renders control
|
|
40
|
+
* but reports no exposure: the visitor is outside the experiment.
|
|
41
|
+
*/
|
|
42
|
+
flags: Record<string, ExperimentAssignment>;
|
|
43
|
+
}
|
|
44
|
+
/** The empty decision: every experiment at control. */
|
|
45
|
+
export declare const NO_ASSIGNMENTS: ExperimentAssignments;
|
|
46
|
+
/**
|
|
47
|
+
* Problems with a store's experiment declarations, empty when valid. Checked
|
|
48
|
+
* when the host is created, so a typo fails the build rather than silently
|
|
49
|
+
* running a page with no variants.
|
|
50
|
+
*/
|
|
51
|
+
export declare function validateExperiments(experiments: Record<string, StorefrontExperiment> | undefined): string[];
|
|
52
|
+
export declare function isBotUserAgent(userAgent: string | null | undefined): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* The visitor's stable anonymous id, if the browser already has one:
|
|
55
|
+
* posthog-js's own cookie first (so the edge evaluates flags for the very id
|
|
56
|
+
* the browser reports events under), then the store's first-party cookie.
|
|
57
|
+
*/
|
|
58
|
+
export declare function readVisitorId(cookieHeader: string | null | undefined, posthogKey: string): string | undefined;
|
|
59
|
+
/** The `fz_vid` the edge pinned for this browser, if any. */
|
|
60
|
+
export declare function readPinnedVisitorId(cookieHeader: string | null | undefined): string | undefined;
|
|
61
|
+
/** Whether an id may be stored in `fz_vid` (an anonymous id, never an e-mail). */
|
|
62
|
+
export declare function isPinnableVisitorId(id: string): boolean;
|
|
63
|
+
/** `Set-Cookie` for a newly minted visitor id: a year, first-party, not readable cross-site. */
|
|
64
|
+
export declare function visitorCookie(id: string, secure?: boolean): string;
|
|
65
|
+
/** PostHog's bucket for `key` and `distinctId`, in [0, 1]. */
|
|
66
|
+
export declare function posthogHash(key: string, distinctId: string, salt?: string): Promise<number>;
|
|
67
|
+
/** In the rollout when the bucket is at or below the percentage — PostHog's `>` check, inverted. */
|
|
68
|
+
export declare function inPosthogRollout(key: string, distinctId: string, rolloutPercentage: number): Promise<boolean>;
|
|
69
|
+
/** PostHog's variant for a bucketed visitor: the `[min, max)` range its 'variant' hash falls in. */
|
|
70
|
+
export declare function posthogVariant(key: string, distinctId: string, variants: ReadonlyArray<{
|
|
71
|
+
key: string;
|
|
72
|
+
rollout_percentage: number;
|
|
73
|
+
}>): Promise<string | undefined>;
|
|
74
|
+
/** The split as PostHog's variant list: declared order, even by default (remainder to the first). */
|
|
75
|
+
export declare function experimentVariantTable(experiment: StorefrontExperiment): Array<{
|
|
76
|
+
key: string;
|
|
77
|
+
rollout_percentage: number;
|
|
78
|
+
}>;
|
|
79
|
+
/** Experiments that assign anyone. */
|
|
80
|
+
export declare function runningExperiments(experiments: Record<string, StorefrontExperiment> | undefined): Record<string, StorefrontExperiment>;
|
|
81
|
+
/**
|
|
82
|
+
* This visitor's variants, computed locally. Only running experiments the
|
|
83
|
+
* visitor's bucket falls inside the rollout of appear in `flags`.
|
|
84
|
+
*/
|
|
85
|
+
export declare function assignExperiments(input: {
|
|
86
|
+
experiments: Record<string, StorefrontExperiment> | undefined;
|
|
87
|
+
distinctId: string;
|
|
88
|
+
}): Promise<ExperimentAssignments>;
|
|
89
|
+
/** The variant of `key`, control when unassigned. */
|
|
90
|
+
export declare function variantOf(assignments: ExperimentAssignments | null | undefined, key: string): string;
|
|
91
|
+
/**
|
|
92
|
+
* The part of the edge cache key that depends on the visitor: one entry per
|
|
93
|
+
* combination of variants, in a fixed order. Control-only visitors (and every
|
|
94
|
+
* crawler) share the plain key with the page as it was before any experiment.
|
|
95
|
+
*/
|
|
96
|
+
export declare function experimentCacheSuffix(assignments: ExperimentAssignments, keys: readonly string[]): string;
|
|
97
|
+
/** The assignment as a header value (URI-encoded JSON: payloads may carry any text). */
|
|
98
|
+
export declare function encodeExperimentHeader(assignments: ExperimentAssignments): string;
|
|
99
|
+
/** The renderer's side: never throws, garbage reads as no assignment. */
|
|
100
|
+
export declare function decodeExperimentHeader(value: string | null | undefined): ExperimentAssignments | null;
|
|
101
|
+
//# sourceMappingURL=assign.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assign.d.ts","sourceRoot":"","sources":["../../src/experiments/assign.ts"],"names":[],"mappings":"AAcA,uEAAuE;AACvE,eAAO,MAAM,OAAO,YAAY,CAAA;AAEhC,uEAAuE;AACvE,eAAO,MAAM,iBAAiB,uBAAuB,CAAA;AAErD,oFAAoF;AACpF,eAAO,MAAM,cAAc,WAAW,CAAA;AAEtC,qCAAqC;AACrC,MAAM,WAAW,oBAAoB;IACnC;;;OAGG;IACH,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;IAC3B;;;OAGG;IACH,MAAM,CAAC,EAAE,SAAS,GAAG,KAAK,CAAA;IAC1B,8FAA8F;IAC9F,KAAK,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IACxC,mGAAmG;IACnG,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,wEAAwE;IACxE,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,8CAA8C;AAC9C,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAA;IACf,uEAAuE;IACvE,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,mDAAmD;AACnD,MAAM,WAAW,qBAAqB;IACpC;8EAC0E;IAC1E,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;;OAIG;IACH,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAA;CAC5C;AAED,uDAAuD;AACvD,eAAO,MAAM,cAAc,EAAE,qBAA6E,CAAA;AAI1G;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,GAAG,SAAS,GAAG,MAAM,EAAE,CAoC3G;AAQD,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAG5E;AAYD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAgB7G;AAID,6DAA6D;AAC7D,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAG/F;AAED,kFAAkF;AAClF,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED,gGAAgG;AAChG,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,UAAO,GAAG,MAAM,CAE/D;AAoBD,8DAA8D;AAC9D,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,SAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAG7F;AAED,oGAAoG;AACpG,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAEnH;AAED,oGAAoG;AACpG,wBAAsB,cAAc,CAClC,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,aAAa,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,kBAAkB,EAAE,MAAM,CAAA;CAAE,CAAC,GACnE,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAS7B;AAED,qGAAqG;AACrG,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,oBAAoB,GAAG,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,kBAAkB,EAAE,MAAM,CAAA;CAAE,CAAC,CAK3H;AAED,sCAAsC;AACtC,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,GAAG,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAEtI;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,KAAK,EAAE;IAC7C,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,GAAG,SAAS,CAAA;IAC7D,UAAU,EAAE,MAAM,CAAA;CACnB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAQjC;AAED,qDAAqD;AACrD,wBAAgB,SAAS,CAAC,WAAW,EAAE,qBAAqB,GAAG,IAAI,GAAG,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAEpG;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,qBAAqB,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAOzG;AAED,wFAAwF;AACxF,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,qBAAqB,GAAG,MAAM,CAEjF;AAED,yEAAyE;AACzE,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,qBAAqB,GAAG,IAAI,CAkBrG"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type BlockNode } from '@fayz-ai/core';
|
|
3
|
+
import { type ExperimentAssignment, type ExperimentAssignments } from './assign';
|
|
4
|
+
/** A setting whose value depends on an experiment's variant. */
|
|
5
|
+
export interface ExperimentBinding<T> {
|
|
6
|
+
/** The PostHog flag key, declared in the store's `experiments`. */
|
|
7
|
+
experiment: string;
|
|
8
|
+
/** The value for each variant; a variant not listed falls back to `control`. */
|
|
9
|
+
variants: {
|
|
10
|
+
control: T;
|
|
11
|
+
} & Record<string, T>;
|
|
12
|
+
}
|
|
13
|
+
/** A plain value, or one bound to an experiment. */
|
|
14
|
+
export type Experimental<T> = T | ExperimentBinding<T>;
|
|
15
|
+
export declare function isExperimentBinding<T>(value: Experimental<T> | undefined): value is ExperimentBinding<T>;
|
|
16
|
+
/** The value of a setting for a given variant (control when unbound or unmatched). */
|
|
17
|
+
export declare function resolveExperimental<T>(value: Experimental<T>, variant: string): T;
|
|
18
|
+
/** The assignment the page was rendered with, for the analytics client. */
|
|
19
|
+
export declare function getExperimentBootstrap(): ExperimentAssignments | null;
|
|
20
|
+
export interface ExperimentProviderProps {
|
|
21
|
+
/** What the edge decided for this request (`StoreRouteData.experiments`). */
|
|
22
|
+
assignments: ExperimentAssignments | null | undefined;
|
|
23
|
+
/** The page being shown. A new path is a new page view: exposures are reported again. */
|
|
24
|
+
path: string;
|
|
25
|
+
children?: React.ReactNode;
|
|
26
|
+
}
|
|
27
|
+
export declare function ExperimentProvider({ assignments, path, children }: ExperimentProviderProps): React.JSX.Element;
|
|
28
|
+
/**
|
|
29
|
+
* The variant this visitor sees for `key`, and its payload.
|
|
30
|
+
*
|
|
31
|
+
* 'control' whenever anything is missing — no provider, an undeclared key, no
|
|
32
|
+
* assignment (the experiment is off, the visitor is outside its rollout or is
|
|
33
|
+
* a crawler). The first render that reads an experiment the visitor is in
|
|
34
|
+
* reports the exposure (once per page view): that is the event PostHog's
|
|
35
|
+
* experiment analysis counts visitors from.
|
|
36
|
+
*/
|
|
37
|
+
export declare function useExperiment(key: string): ExperimentAssignment;
|
|
38
|
+
/** A setting resolved for this visitor; reads (and reports) the experiment only when bound. */
|
|
39
|
+
export declare function useExperimentValue<T>(value: Experimental<T>): T;
|
|
40
|
+
export declare function useExperimentValue<T>(value: Experimental<T> | undefined): T | undefined;
|
|
41
|
+
/**
|
|
42
|
+
* The `experiment` block: its children are `experimentVariant` blocks, and
|
|
43
|
+
* only the one named after this visitor's variant renders (the `control` one
|
|
44
|
+
* when nothing matches). How a document tests a section without code:
|
|
45
|
+
*
|
|
46
|
+
* { type: 'experiment', props: { experiment: 'home-hero-copy' }, children: [
|
|
47
|
+
* { type: 'experimentVariant', props: { variant: 'control' }, children: [hero A] },
|
|
48
|
+
* { type: 'experimentVariant', props: { variant: 'test' }, children: [hero B] },
|
|
49
|
+
* ] }
|
|
50
|
+
*/
|
|
51
|
+
export declare function ExperimentBlock({ experiment, node }: {
|
|
52
|
+
experiment?: string;
|
|
53
|
+
node?: BlockNode;
|
|
54
|
+
}): React.JSX.Element | null;
|
|
55
|
+
/** One variant's blocks. Renders its children; only meaningful inside `experiment`. */
|
|
56
|
+
export declare function ExperimentVariantBlock({ node }: {
|
|
57
|
+
variant?: string;
|
|
58
|
+
node?: BlockNode;
|
|
59
|
+
}): React.JSX.Element;
|
|
60
|
+
export declare const experimentBlockMeta: {
|
|
61
|
+
label: string;
|
|
62
|
+
description: string;
|
|
63
|
+
settings: {
|
|
64
|
+
id: string;
|
|
65
|
+
type: "text";
|
|
66
|
+
label: string;
|
|
67
|
+
required: boolean;
|
|
68
|
+
help: string;
|
|
69
|
+
}[];
|
|
70
|
+
presets: {
|
|
71
|
+
name: string;
|
|
72
|
+
props: {
|
|
73
|
+
experiment: string;
|
|
74
|
+
};
|
|
75
|
+
}[];
|
|
76
|
+
enabledOn: string[];
|
|
77
|
+
};
|
|
78
|
+
export declare const experimentVariantBlockMeta: {
|
|
79
|
+
label: string;
|
|
80
|
+
description: string;
|
|
81
|
+
parent: string[];
|
|
82
|
+
settings: {
|
|
83
|
+
id: string;
|
|
84
|
+
type: "text";
|
|
85
|
+
label: string;
|
|
86
|
+
required: boolean;
|
|
87
|
+
help: string;
|
|
88
|
+
}[];
|
|
89
|
+
presets: {
|
|
90
|
+
name: string;
|
|
91
|
+
props: {
|
|
92
|
+
variant: string;
|
|
93
|
+
};
|
|
94
|
+
}[];
|
|
95
|
+
enabledOn: string[];
|
|
96
|
+
};
|
|
97
|
+
/** Test seam. */
|
|
98
|
+
export declare function resetExperimentBootstrap(): void;
|
|
99
|
+
//# sourceMappingURL=react.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../../src/experiments/react.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAA8C,KAAK,SAAS,EAAE,MAAM,eAAe,CAAA;AAG1F,OAAO,EAA+B,KAAK,oBAAoB,EAAE,KAAK,qBAAqB,EAAE,MAAM,UAAU,CAAA;AAa7G,gEAAgE;AAChE,MAAM,WAAW,iBAAiB,CAAC,CAAC;IAClC,mEAAmE;IACnE,UAAU,EAAE,MAAM,CAAA;IAClB,gFAAgF;IAChF,QAAQ,EAAE;QAAE,OAAO,EAAE,CAAC,CAAA;KAAE,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;CAC7C;AAED,oDAAoD;AACpD,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAA;AAEtD,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,SAAS,GAAG,KAAK,IAAI,iBAAiB,CAAC,CAAC,CAAC,CAOxG;AAED,sFAAsF;AACtF,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,CAAC,CAGjF;AAOD,2EAA2E;AAC3E,wBAAgB,sBAAsB,IAAI,qBAAqB,GAAG,IAAI,CAErE;AAYD,MAAM,WAAW,uBAAuB;IACtC,6EAA6E;IAC7E,WAAW,EAAE,qBAAqB,GAAG,IAAI,GAAG,SAAS,CAAA;IACrD,yFAAyF;IACzF,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAC3B;AAED,wBAAgB,kBAAkB,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,uBAAuB,qBAe1F;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,oBAAoB,CAe/D;AAED,+FAA+F;AAC/F,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;AAChE,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,SAAS,GAAG,CAAC,GAAG,SAAS,CAAA;AAWxF;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,SAAS,CAAA;CAAE,4BAU9F;AAED,uFAAuF;AACvF,wBAAgB,sBAAsB,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,SAAS,CAAA;CAAE,qBAEtF;AAED,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;CAe/B,CAAA;AAED,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;CAkBtC,CAAA;AAED,iBAAiB;AACjB,wBAAgB,wBAAwB,IAAI,IAAI,CAE/C"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ExperimentAssignments, type StorefrontExperiment } from '../experiments/assign';
|
|
1
2
|
export declare function isStorageRequest(url: URL): boolean;
|
|
2
3
|
/**
|
|
3
4
|
* Which format this visitor gets — the only part of the request, besides the
|
|
@@ -8,8 +9,9 @@ export declare function isStorageRequest(url: URL): boolean;
|
|
|
8
9
|
export declare function imageFormatKey(request: Request): 'webp' | 'orig';
|
|
9
10
|
/** Answer a storage request from Supabase, on the store's own origin. */
|
|
10
11
|
export declare function serveStorageImage(request: Request, url: URL, supabaseUrl: string | undefined): Promise<Response>;
|
|
11
|
-
/** The cache key for a request, or null when it is not cacheable.
|
|
12
|
-
|
|
12
|
+
/** The cache key for a request, or null when it is not cacheable. `variant`
|
|
13
|
+
* is the experiment part (`experimentCacheSuffix`); empty means control. */
|
|
14
|
+
export declare function edgeCacheKey(request: Request, buildId: string, variant?: string): Request | null;
|
|
13
15
|
/** Only what the response itself declares shareable and fresh for a while. */
|
|
14
16
|
export declare function edgeCacheable(response: Response): boolean;
|
|
15
17
|
export interface StorefrontEdgeOptions {
|
|
@@ -32,7 +34,35 @@ export interface StorefrontEdgeOptions {
|
|
|
32
34
|
* able to help.
|
|
33
35
|
*/
|
|
34
36
|
dev?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* A/B tests: the store's declared experiments (`config.experiments`).
|
|
39
|
+
* Nothing running: no assignment, no cookie, the cache key is the page's
|
|
40
|
+
* alone — exactly the handler without tests.
|
|
41
|
+
*/
|
|
42
|
+
experiments?: StorefrontEdgeExperiments;
|
|
43
|
+
}
|
|
44
|
+
export interface StorefrontEdgeExperiments {
|
|
45
|
+
declared: Record<string, StorefrontExperiment> | undefined;
|
|
46
|
+
/**
|
|
47
|
+
* The PostHog project token (`phc_…`), the same the storefront sends with —
|
|
48
|
+
* used only to read PostHog's own cookie, so a returning visitor is bucketed
|
|
49
|
+
* by the id PostHog already knows them by. Optional: without it, `fz_vid`.
|
|
50
|
+
*/
|
|
51
|
+
posthogKey?: string;
|
|
52
|
+
}
|
|
53
|
+
interface PageAssignment {
|
|
54
|
+
assignments: ExperimentAssignments;
|
|
55
|
+
/** The cache-key part; empty for control. */
|
|
56
|
+
variant: string;
|
|
57
|
+
/** Cookies for THIS visitor's response: a new id. */
|
|
58
|
+
cookies: string[];
|
|
35
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* Decide this request's variants — locally, with PostHog's bucketing, no
|
|
62
|
+
* network. Never throws.
|
|
63
|
+
*/
|
|
64
|
+
export declare function assignForRequest(request: Request, options: StorefrontEdgeExperiments): Promise<PageAssignment>;
|
|
36
65
|
/** The Worker's `fetch`, from the store's pieces. */
|
|
37
66
|
export declare function createStorefrontEdge(options: StorefrontEdgeOptions): (request: Request) => Promise<Response>;
|
|
67
|
+
export {};
|
|
38
68
|
//# sourceMappingURL=edge-handler.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"edge-handler.d.ts","sourceRoot":"","sources":["../../src/host/edge-handler.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"edge-handler.d.ts","sourceRoot":"","sources":["../../src/host/edge-handler.ts"],"names":[],"mappings":"AACA,OAAO,EAYL,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EAC1B,MAAM,uBAAuB,CAAA;AAyC9B,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAElD;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAEhE;AAED,yEAAyE;AACzE,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,QAAQ,CAAC,CA6BtH;AAED;6EAC6E;AAC7E,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,SAAK,GAAG,OAAO,GAAG,IAAI,CAa5F;AAED,8EAA8E;AAC9E,wBAAgB,aAAa,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAIzD;AAgBD,MAAM,WAAW,qBAAqB;IACpC,sEAAsE;IACtE,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;IACtD,mDAAmD;IACnD,eAAe,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAA;IAClC,2CAA2C;IAC3C,OAAO,EAAE,MAAM,CAAA;IACf,uEAAuE;IACvE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,wFAAwF;IACxF,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,CAAA;IAC1C,oEAAoE;IACpE,KAAK,CAAC,EAAE,KAAK,CAAA;IACb;;;;;OAKG;IACH,GAAG,CAAC,EAAE,OAAO,CAAA;IACb;;;;OAIG;IACH,WAAW,CAAC,EAAE,yBAAyB,CAAA;CACxC;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,GAAG,SAAS,CAAA;IAC1D;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAaD,UAAU,cAAc;IACtB,WAAW,EAAE,qBAAqB,CAAA;IAClC,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAA;IACf,qDAAqD;IACrD,OAAO,EAAE,MAAM,EAAE,CAAA;CAClB;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAAC,cAAc,CAAC,CAyBpH;AAkBD,qDAAqD;AACrD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAoC5G"}
|