commerce-kit 0.52.0 → 0.53.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/api-types.d.ts +96 -2
- package/dist/browser.js +1 -1
- package/dist/browser.js.map +1 -1
- package/dist/index.d.ts +16 -3
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/sandbox-inspectors.d.ts +11 -7
- package/dist/sandbox-inspectors.js +1 -1
- package/dist/sandbox-inspectors.js.map +1 -1
- package/package.json +1 -1
package/dist/api-types.d.ts
CHANGED
|
@@ -4533,12 +4533,106 @@ type APICouponUpdateResult = {
|
|
|
4533
4533
|
updatedAt: string;
|
|
4534
4534
|
};
|
|
4535
4535
|
type APICouponGetByIdParams = {
|
|
4536
|
-
|
|
4536
|
+
idOrCode: string;
|
|
4537
4537
|
};
|
|
4538
4538
|
type APICouponDeleteResult = {
|
|
4539
4539
|
ok: boolean;
|
|
4540
4540
|
deleted: number;
|
|
4541
4541
|
};
|
|
4542
|
+
type APISupportCase = {
|
|
4543
|
+
id: string;
|
|
4544
|
+
number: number;
|
|
4545
|
+
subject: string;
|
|
4546
|
+
category: "other" | "orders_payments" | "products_catalog" | "domains_setup" | "billing_plans" | "store_builder";
|
|
4547
|
+
severity: "normal" | "high" | "low" | "critical";
|
|
4548
|
+
status: "open" | "answered" | "closed";
|
|
4549
|
+
createdAt: string;
|
|
4550
|
+
lastActivityAt: string;
|
|
4551
|
+
closedAt: string | null;
|
|
4552
|
+
};
|
|
4553
|
+
type APISupportCaseMessage = {
|
|
4554
|
+
id: string;
|
|
4555
|
+
authorKind: "merchant" | "support";
|
|
4556
|
+
authorLabel: string;
|
|
4557
|
+
body: string;
|
|
4558
|
+
attachments: {
|
|
4559
|
+
url: string;
|
|
4560
|
+
contentType: string;
|
|
4561
|
+
name?: string;
|
|
4562
|
+
}[];
|
|
4563
|
+
createdAt: string;
|
|
4564
|
+
};
|
|
4565
|
+
type APISupportCasesBrowseResult = {
|
|
4566
|
+
data: APISupportCase[];
|
|
4567
|
+
meta: {
|
|
4568
|
+
count: number;
|
|
4569
|
+
offset: number;
|
|
4570
|
+
limit: number;
|
|
4571
|
+
};
|
|
4572
|
+
};
|
|
4573
|
+
type APISupportCasesBrowseQueryParams = {
|
|
4574
|
+
offset?: number | undefined;
|
|
4575
|
+
limit?: number | undefined;
|
|
4576
|
+
query?: string | undefined;
|
|
4577
|
+
status?: "open" | "answered" | "closed" | "all" | undefined;
|
|
4578
|
+
severity?: "normal" | "high" | "low" | "critical" | "all" | undefined;
|
|
4579
|
+
};
|
|
4580
|
+
type APISupportCaseCreateBody = {
|
|
4581
|
+
body: string;
|
|
4582
|
+
subject?: string | undefined;
|
|
4583
|
+
category?: "other" | "orders_payments" | "products_catalog" | "domains_setup" | "billing_plans" | "store_builder" | undefined;
|
|
4584
|
+
severity?: "normal" | "high" | "low" | "critical" | undefined;
|
|
4585
|
+
author?: string | undefined;
|
|
4586
|
+
};
|
|
4587
|
+
type APISupportCaseCreateResult = {
|
|
4588
|
+
id: string;
|
|
4589
|
+
number: number;
|
|
4590
|
+
subject: string;
|
|
4591
|
+
category: "other" | "orders_payments" | "products_catalog" | "domains_setup" | "billing_plans" | "store_builder";
|
|
4592
|
+
severity: "normal" | "high" | "low" | "critical";
|
|
4593
|
+
status: "open" | "answered" | "closed";
|
|
4594
|
+
createdAt: string;
|
|
4595
|
+
lastActivityAt: string;
|
|
4596
|
+
closedAt: string | null;
|
|
4597
|
+
};
|
|
4598
|
+
type APISupportCaseGetResult = {
|
|
4599
|
+
id: string;
|
|
4600
|
+
number: number;
|
|
4601
|
+
subject: string;
|
|
4602
|
+
category: "other" | "orders_payments" | "products_catalog" | "domains_setup" | "billing_plans" | "store_builder";
|
|
4603
|
+
severity: "normal" | "high" | "low" | "critical";
|
|
4604
|
+
status: "open" | "answered" | "closed";
|
|
4605
|
+
createdAt: string;
|
|
4606
|
+
lastActivityAt: string;
|
|
4607
|
+
closedAt: string | null;
|
|
4608
|
+
} & {
|
|
4609
|
+
messages: APISupportCaseMessage[];
|
|
4610
|
+
};
|
|
4611
|
+
type APISupportCaseGetParams = {
|
|
4612
|
+
idOrNumber: string;
|
|
4613
|
+
};
|
|
4614
|
+
type APISupportCaseUpdateBody = {
|
|
4615
|
+
status: "open" | "closed";
|
|
4616
|
+
};
|
|
4617
|
+
type APISupportCaseUpdateResult = {
|
|
4618
|
+
id: string;
|
|
4619
|
+
number: number;
|
|
4620
|
+
subject: string;
|
|
4621
|
+
category: "other" | "orders_payments" | "products_catalog" | "domains_setup" | "billing_plans" | "store_builder";
|
|
4622
|
+
severity: "normal" | "high" | "low" | "critical";
|
|
4623
|
+
status: "open" | "answered" | "closed";
|
|
4624
|
+
createdAt: string;
|
|
4625
|
+
lastActivityAt: string;
|
|
4626
|
+
closedAt: string | null;
|
|
4627
|
+
};
|
|
4628
|
+
type APISupportCaseMessageCreateBody = {
|
|
4629
|
+
body: string;
|
|
4630
|
+
author?: string | undefined;
|
|
4631
|
+
};
|
|
4632
|
+
type APISupportCaseMessageCreateResult = {
|
|
4633
|
+
message: APISupportCaseMessage;
|
|
4634
|
+
status: APISupportCase["status"];
|
|
4635
|
+
};
|
|
4542
4636
|
type APIOrdersBrowseResult = {
|
|
4543
4637
|
data: ({
|
|
4544
4638
|
id: string;
|
|
@@ -8704,4 +8798,4 @@ type APICartDeleteResult = {
|
|
|
8704
8798
|
success: boolean;
|
|
8705
8799
|
};
|
|
8706
8800
|
|
|
8707
|
-
export type { APIBlogCategoriesBrowseQueryParams, APIBlogCategoriesBrowseResult, APIBlogCategoryCreateBody, APIBlogCategoryCreateResult, APIBlogCategoryDeleteResult, APIBlogCategoryGetByIdParams, APIBlogCategoryGetByIdResult, APIBlogCategoryUpdateBody, APIBlogCategoryUpdateResult, APIBrandAssignProductsBody, APIBrandAssignProductsResult, APIBrandCreateBody, APIBrandCreateResult, APIBrandDeleteResult, APIBrandGetByIdParams, APIBrandGetByIdResult, APIBrandUpdateBody, APIBrandUpdateResult, APIBrandsBrowseQueryParams, APIBrandsBrowseResult, APICartAddBody, APICartAddResult, APICartCreateBody, APICartCreateResult, APICartDeleteResult, APICartGetResult, APICartRemoveItemQueryParams, APICartRemoveItemResult, APICategoriesBrowseQueryParams, APICategoriesBrowseResult, APICategoryCreateBody, APICategoryCreateResult, APICategoryDeleteResult, APICategoryGetByIdParams, APICategoryGetByIdQueryParams, APICategoryGetByIdResult, APICategoryUpdateBody, APICategoryUpdateQueryParams, APICategoryUpdateResult, APICollectionCreateBody, APICollectionCreateResult, APICollectionDeleteResult, APICollectionGetByIdParams, APICollectionGetByIdQueryParams, APICollectionGetByIdResult, APICollectionUpdateBody, APICollectionUpdateResult, APICollectionsBrowseQueryParams, APICollectionsBrowseResult, APIContactMessageCreateBody, APIContactMessageCreateResult, APICouponCreateBody, APICouponCreateResult, APICouponDeleteResult, APICouponGetByIdParams, APICouponGetByIdResult, APICouponUpdateBody, APICouponUpdateResult, APICouponsBrowseQueryParams, APICouponsBrowseResult, APICustomerAddressCreateBody, APICustomerAddressCreateResult, APICustomerGetByIdParams, APICustomerGetByIdResult, APICustomerOrdersBrowseQueryParams, APICustomerOrdersBrowseResult, APICustomerUpdateBody, APICustomerUpdateResult, APICustomersBrowseQueryParams, APICustomersBrowseResult, APIEventAttendeesBrowseResult, APIEventCreateBody, APIEventCreateResult, APIEventGetByIdParams, APIEventGetByIdResult, APIEventUpdateBody, APIEventUpdateResult, APIEventsBrowseQueryParams, APIEventsBrowseResult, APIInstaviewImagesBrowseParams, APIInstaviewImagesBrowseQueryParams, APIInstaviewImagesBrowseResult, APIInventoryAdjustBody, APIInventoryAdjustResult, APIInventoryBrowseQueryParams, APIInventoryBrowseResult, APILegalPageCreateBody, APILegalPageCreateQueryParams, APILegalPageCreateResult, APILegalPageGetByPathParams, APILegalPageGetByPathQueryParams, APILegalPageGetByPathResult, APILegalPageUpdateBody, APILegalPageUpdateQueryParams, APILegalPageUpdateResult, APILegalPagesBrowseQueryParams, APILegalPagesBrowseResult, APIMeGetResult, APIOrderGetByIdParams, APIOrderGetByIdResult, APIOrderRefundGetParams, APIOrderRefundGetResult, APIOrderRefundsBrowseQueryParams, APIOrderRefundsBrowseResult, APIOrderRefundsParams, APIOrderUpdateBody, APIOrderUpdateResult, APIOrdersBrowseQueryParams, APIOrdersBrowseResult, APIPostCommentCreateBody, APIPostCommentCreateResult, APIPostCommentsBrowseQueryParams, APIPostCommentsBrowseResult, APIPostCreateBody, APIPostCreateResult, APIPostDeleteResult, APIPostGetByIdParams, APIPostGetByIdResult, APIPostUpdateBody, APIPostUpdateResult, APIPostsBrowseQueryParams, APIPostsBrowseResult, APIProductBatchBody, APIProductBatchResult, APIProductCreateBody, APIProductCreateResult, APIProductDeleteQueryParams, APIProductDeleteResult, APIProductFiltersResult, APIProductGetByIdParams, APIProductGetByIdQueryParams, APIProductGetByIdResult, APIProductReviewCreateBody, APIProductReviewCreateResult, APIProductReviewsBrowseQueryParams, APIProductReviewsBrowseResult, APIProductUpdateBody, APIProductUpdateQueryParams, APIProductUpdateResult, APIProductsBrowseQueryParams, APIProductsBrowseResult, APISearchQueryParams, APISearchResult, APISocialsGetResult, APISubscriberCreateBody, APISubscriberCreateResult, APISubscriberDeleteResult, APITicketAttendeeGetParams, APITicketAttendeeGetResult, APITicketsGetParams, APITicketsGetQueryParams, APITicketsGetResult, APITicketsUpdateBody, APITicketsUpdateResult, APIVariantCreateBody, APIVariantCreateResult, APIVariantGetByIdParams, APIVariantGetByIdQueryParams, APIVariantGetByIdResult, APIVariantUpdateBody, APIVariantUpdateResult, JSONContent };
|
|
8801
|
+
export type { APIBlogCategoriesBrowseQueryParams, APIBlogCategoriesBrowseResult, APIBlogCategoryCreateBody, APIBlogCategoryCreateResult, APIBlogCategoryDeleteResult, APIBlogCategoryGetByIdParams, APIBlogCategoryGetByIdResult, APIBlogCategoryUpdateBody, APIBlogCategoryUpdateResult, APIBrandAssignProductsBody, APIBrandAssignProductsResult, APIBrandCreateBody, APIBrandCreateResult, APIBrandDeleteResult, APIBrandGetByIdParams, APIBrandGetByIdResult, APIBrandUpdateBody, APIBrandUpdateResult, APIBrandsBrowseQueryParams, APIBrandsBrowseResult, APICartAddBody, APICartAddResult, APICartCreateBody, APICartCreateResult, APICartDeleteResult, APICartGetResult, APICartRemoveItemQueryParams, APICartRemoveItemResult, APICategoriesBrowseQueryParams, APICategoriesBrowseResult, APICategoryCreateBody, APICategoryCreateResult, APICategoryDeleteResult, APICategoryGetByIdParams, APICategoryGetByIdQueryParams, APICategoryGetByIdResult, APICategoryUpdateBody, APICategoryUpdateQueryParams, APICategoryUpdateResult, APICollectionCreateBody, APICollectionCreateResult, APICollectionDeleteResult, APICollectionGetByIdParams, APICollectionGetByIdQueryParams, APICollectionGetByIdResult, APICollectionUpdateBody, APICollectionUpdateResult, APICollectionsBrowseQueryParams, APICollectionsBrowseResult, APIContactMessageCreateBody, APIContactMessageCreateResult, APICouponCreateBody, APICouponCreateResult, APICouponDeleteResult, APICouponGetByIdParams, APICouponGetByIdResult, APICouponUpdateBody, APICouponUpdateResult, APICouponsBrowseQueryParams, APICouponsBrowseResult, APICustomerAddressCreateBody, APICustomerAddressCreateResult, APICustomerGetByIdParams, APICustomerGetByIdResult, APICustomerOrdersBrowseQueryParams, APICustomerOrdersBrowseResult, APICustomerUpdateBody, APICustomerUpdateResult, APICustomersBrowseQueryParams, APICustomersBrowseResult, APIEventAttendeesBrowseResult, APIEventCreateBody, APIEventCreateResult, APIEventGetByIdParams, APIEventGetByIdResult, APIEventUpdateBody, APIEventUpdateResult, APIEventsBrowseQueryParams, APIEventsBrowseResult, APIInstaviewImagesBrowseParams, APIInstaviewImagesBrowseQueryParams, APIInstaviewImagesBrowseResult, APIInventoryAdjustBody, APIInventoryAdjustResult, APIInventoryBrowseQueryParams, APIInventoryBrowseResult, APILegalPageCreateBody, APILegalPageCreateQueryParams, APILegalPageCreateResult, APILegalPageGetByPathParams, APILegalPageGetByPathQueryParams, APILegalPageGetByPathResult, APILegalPageUpdateBody, APILegalPageUpdateQueryParams, APILegalPageUpdateResult, APILegalPagesBrowseQueryParams, APILegalPagesBrowseResult, APIMeGetResult, APIOrderGetByIdParams, APIOrderGetByIdResult, APIOrderRefundGetParams, APIOrderRefundGetResult, APIOrderRefundsBrowseQueryParams, APIOrderRefundsBrowseResult, APIOrderRefundsParams, APIOrderUpdateBody, APIOrderUpdateResult, APIOrdersBrowseQueryParams, APIOrdersBrowseResult, APIPostCommentCreateBody, APIPostCommentCreateResult, APIPostCommentsBrowseQueryParams, APIPostCommentsBrowseResult, APIPostCreateBody, APIPostCreateResult, APIPostDeleteResult, APIPostGetByIdParams, APIPostGetByIdResult, APIPostUpdateBody, APIPostUpdateResult, APIPostsBrowseQueryParams, APIPostsBrowseResult, APIProductBatchBody, APIProductBatchResult, APIProductCreateBody, APIProductCreateResult, APIProductDeleteQueryParams, APIProductDeleteResult, APIProductFiltersResult, APIProductGetByIdParams, APIProductGetByIdQueryParams, APIProductGetByIdResult, APIProductReviewCreateBody, APIProductReviewCreateResult, APIProductReviewsBrowseQueryParams, APIProductReviewsBrowseResult, APIProductUpdateBody, APIProductUpdateQueryParams, APIProductUpdateResult, APIProductsBrowseQueryParams, APIProductsBrowseResult, APISearchQueryParams, APISearchResult, APISocialsGetResult, APISubscriberCreateBody, APISubscriberCreateResult, APISubscriberDeleteResult, APISupportCase, APISupportCaseCreateBody, APISupportCaseCreateResult, APISupportCaseGetParams, APISupportCaseGetResult, APISupportCaseMessage, APISupportCaseMessageCreateBody, APISupportCaseMessageCreateResult, APISupportCaseUpdateBody, APISupportCaseUpdateResult, APISupportCasesBrowseQueryParams, APISupportCasesBrowseResult, APITicketAttendeeGetParams, APITicketAttendeeGetResult, APITicketsGetParams, APITicketsGetQueryParams, APITicketsGetResult, APITicketsUpdateBody, APITicketsUpdateResult, APIVariantCreateBody, APIVariantCreateResult, APIVariantGetByIdParams, APIVariantGetByIdQueryParams, APIVariantGetByIdResult, APIVariantUpdateBody, APIVariantUpdateResult, JSONContent };
|
package/dist/browser.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
function w(){typeof window>"u"||(console.log("[YNS Sandbox Inspectors] module evaluated"),
|
|
1
|
+
function w(){typeof window>"u"||(console.log("[YNS Sandbox Inspectors] module evaluated"),f(),p())}w();function p(){if(window.parent===window)return;let r="yns-builder-annotations-script";if(document.getElementById(r))return;let s=process.env.NEXT_PUBLIC_YNS_TOOLBAR_BASE||"https://toolbar.yns.cx",t=document.createElement("script");t.id=r,t.async=!0,t.src=`${s}/annotations.js`,document.head.appendChild(t)}function f(){if(window.parent===window)return;let r=5e3,s=10,t=2e3,a=0,c="",d=0;function u(e,n){let o=Date.now();d>=s||e===c&&o-a<r||(a=o,c=e,d+=1,window.parent.postMessage({type:"runtime-error",message:e,stack:n?n.slice(0,t):void 0,pagePath:window.location.pathname},"*"))}window.addEventListener("error",e=>{let n=e.error,o=n instanceof Error?n.message:e.message||"Unknown error",i=n instanceof Error?n.stack:void 0;u(o,i)}),window.addEventListener("unhandledrejection",e=>{let n=e.reason,o=n instanceof Error?n.message:String(n??"Unhandled rejection"),i=n instanceof Error?n.stack:void 0;u(o,i)})}export{w as startSandboxInspectors};
|
|
2
2
|
//# sourceMappingURL=browser.js.map
|
package/dist/browser.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/sandbox-inspectors.ts"],"sourcesContent":["/**\n * Sandbox Inspectors — side-effect entry.\n *\n * Auto-mounts the design-mode + comment-mode inspectors inside per-store\n * storefronts running under the AI Builder sandbox dev server. Communicates\n * with the parent /design iframe via postMessage.\n *\n * Always-on: inspectors are passive postMessage listeners and don't affect the\n * page until the AI Builder iframe sends a `*-mode-toggle` message. Gating on\n * NODE_ENV is wrong (always \"production\" on Vercel) and any build-time gate\n * gets folded out by the commerce-kit bundle, leaving an empty file.\n */\n\n/**\n * Exported so `browser.tsx` can `export { startSandboxInspectors }` — the\n * named binding anchors this module against esbuild tree-shaking when\n * commerce-kit is bundled. Without it, an `export * from \"./sandbox-inspectors\"`\n * re-exports an empty binding set and esbuild DCEs the whole file.\n */\nexport function startSandboxInspectors(): void {\n\tif (typeof window === \"undefined\") return;\n\tconsole.log(\"[YNS Sandbox Inspectors] module evaluated\");\n\tinitDesignModeInspector();\n\tinitCommentModeInspector();\n\tinitRuntimeErrorReporter();\n}\n\n// Auto-start on import.\nstartSandboxInspectors();\n\n/**\n * Reports uncaught runtime errors (e.g. React's \"Maximum update depth\n * exceeded\" from an infinite render loop) to the parent /design iframe so the\n * AI Builder can surface a crash overlay instead of a silently frozen preview.\n *\n * Unlike the inspectors, this posts unsolicited messages — so it only attaches\n * when actually embedded in a parent frame. Render loops fire the same error\n * continuously; rate-limit hard so the parent isn't flooded.\n */\nfunction initRuntimeErrorReporter() {\n\tif (window.parent === window) return;\n\n\tconst MIN_INTERVAL_MS = 5_000;\n\tconst MAX_REPORTS_PER_LOAD = 10;\n\tconst MAX_STACK_LENGTH = 2_000;\n\n\tlet lastSentAt = 0;\n\tlet lastMessage = \"\";\n\tlet sentCount = 0;\n\n\tfunction report(message: string, stack: string | undefined) {\n\t\tconst now = Date.now();\n\t\tif (sentCount >= MAX_REPORTS_PER_LOAD) return;\n\t\tif (message === lastMessage && now - lastSentAt < MIN_INTERVAL_MS) return;\n\t\tlastSentAt = now;\n\t\tlastMessage = message;\n\t\tsentCount += 1;\n\t\twindow.parent.postMessage(\n\t\t\t{\n\t\t\t\ttype: \"runtime-error\",\n\t\t\t\tmessage,\n\t\t\t\tstack: stack ? stack.slice(0, MAX_STACK_LENGTH) : undefined,\n\t\t\t\tpagePath: window.location.pathname,\n\t\t\t},\n\t\t\t\"*\",\n\t\t);\n\t}\n\n\twindow.addEventListener(\"error\", (event) => {\n\t\tconst error: unknown = event.error;\n\t\tconst message = error instanceof Error ? error.message : event.message || \"Unknown error\";\n\t\tconst stack = error instanceof Error ? error.stack : undefined;\n\t\treport(message, stack);\n\t});\n\n\twindow.addEventListener(\"unhandledrejection\", (event) => {\n\t\tconst reason: unknown = event.reason;\n\t\tconst message = reason instanceof Error ? reason.message : String(reason ?? \"Unhandled rejection\");\n\t\tconst stack = reason instanceof Error ? reason.stack : undefined;\n\t\treport(message, stack);\n\t});\n}\n\ninterface ElementInfo {\n\ttag: string;\n\tid: string | undefined;\n\tclasses: string[];\n\ttextContent: string;\n\tcssSelector: string;\n\tboundingRect: { top: number; left: number; width: number; height: number };\n\tcomputedStyles: Partial<{\n\t\tcolor: string;\n\t\tbackgroundColor: string;\n\t\tfontSize: string;\n\t\tfontFamily: string;\n\t\tpadding: string;\n\t\tmargin: string;\n\t}>;\n}\n\nconst IGNORED_TAGS = new Set([\"HEAD\", \"SCRIPT\", \"STYLE\", \"NOSCRIPT\", \"HTML\"]);\n\nfunction generateCssSelector(el: Element): string {\n\tif (el.id) return `${el.tagName.toLowerCase()}#${CSS.escape(el.id)}`;\n\n\tconst parts: string[] = [];\n\tlet current: Element | null = el;\n\twhile (current && current !== document.body && current !== document.documentElement) {\n\t\tlet selector = current.tagName.toLowerCase();\n\n\t\tif (current.id) {\n\t\t\tparts.unshift(`${selector}#${CSS.escape(current.id)}`);\n\t\t\tbreak;\n\t\t}\n\n\t\tconst classes = Array.from(current.classList).filter((c) => !c.startsWith(\"data-yns-\"));\n\t\tif (classes.length > 0) {\n\t\t\tselector += `.${classes.map((c) => CSS.escape(c)).join(\".\")}`;\n\t\t}\n\n\t\tconst parent: Element | null = current.parentElement;\n\t\tconst tag = current.tagName;\n\t\tif (parent) {\n\t\t\tconst siblings = Array.from(parent.children).filter(\n\t\t\t\t(s) => s.tagName === tag && (classes.length === 0 || classes.every((c) => s.classList.contains(c))),\n\t\t\t);\n\t\t\tif (siblings.length > 1) {\n\t\t\t\tconst index = Array.from(parent.children).indexOf(current) + 1;\n\t\t\t\tselector += `:nth-child(${index})`;\n\t\t\t}\n\t\t}\n\n\t\tparts.unshift(selector);\n\t\tcurrent = current.parentElement;\n\t}\n\treturn parts.join(\" > \");\n}\n\nfunction buildElementInfo(el: Element, textLimit: number): ElementInfo {\n\tconst rect = el.getBoundingClientRect();\n\tconst computed = window.getComputedStyle(el);\n\tconst text = (el.textContent ?? \"\").trim();\n\treturn {\n\t\ttag: el.tagName.toLowerCase(),\n\t\tid: el.id || undefined,\n\t\tclasses: Array.from(el.classList).filter((c) => !c.startsWith(\"data-yns-\")),\n\t\ttextContent: text.length > textLimit ? `${text.slice(0, textLimit)}…` : text,\n\t\tcssSelector: generateCssSelector(el),\n\t\tboundingRect: { top: rect.top, left: rect.left, width: rect.width, height: rect.height },\n\t\tcomputedStyles: {\n\t\t\tcolor: computed.color,\n\t\t\tbackgroundColor: computed.backgroundColor,\n\t\t\tfontSize: computed.fontSize,\n\t\t\tfontFamily: computed.fontFamily,\n\t\t\tpadding: computed.padding,\n\t\t\tmargin: computed.margin,\n\t\t},\n\t};\n}\n\nfunction shouldIgnore(el: Element | null, overlayAttrs: string[]): el is null {\n\tif (!el?.tagName) return true;\n\tif (IGNORED_TAGS.has(el.tagName)) return true;\n\tfor (const attr of overlayAttrs) {\n\t\tif (el.hasAttribute?.(attr)) return true;\n\t}\n\treturn false;\n}\n\nfunction initDesignModeInspector() {\n\tlet enabled = false;\n\tlet hoveredElement: Element | null = null;\n\tlet selectedElement: { el: Element; cssSelector: string } | null = null;\n\n\tconst overlay = document.createElement(\"div\");\n\toverlay.setAttribute(\"data-yns-design-overlay\", \"hover\");\n\toverlay.style.cssText = [\n\t\t\"position: fixed\",\n\t\t\"pointer-events: none\",\n\t\t\"z-index: 2147483646\",\n\t\t\"border: 2px solid #3b82f6\",\n\t\t\"background: rgba(59, 130, 246, 0.08)\",\n\t\t\"border-radius: 3px\",\n\t\t\"display: none\",\n\t\t\"transition: top 0.05s, left 0.05s, width 0.05s, height 0.05s\",\n\t].join(\";\");\n\n\tconst label = document.createElement(\"div\");\n\tlabel.setAttribute(\"data-yns-design-overlay\", \"label\");\n\tlabel.style.cssText = [\n\t\t\"position: fixed\",\n\t\t\"pointer-events: none\",\n\t\t\"z-index: 2147483647\",\n\t\t\"background: #3b82f6\",\n\t\t\"color: #fff\",\n\t\t\"font-size: 11px\",\n\t\t\"font-family: ui-monospace, monospace\",\n\t\t\"padding: 2px 6px\",\n\t\t\"border-radius: 3px\",\n\t\t\"white-space: nowrap\",\n\t\t\"display: none\",\n\t].join(\";\");\n\n\tdocument.documentElement.appendChild(overlay);\n\tdocument.documentElement.appendChild(label);\n\n\tconst style = document.createElement(\"style\");\n\tstyle.setAttribute(\"data-yns-design-overlay\", \"style\");\n\tstyle.textContent = \"[data-yns-selected] { outline: 2px solid #3b82f6 !important; outline-offset: 1px; }\";\n\tdocument.head.appendChild(style);\n\n\tfunction positionOverlay(el: Element) {\n\t\tconst rect = el.getBoundingClientRect();\n\t\toverlay.style.top = `${rect.top}px`;\n\t\toverlay.style.left = `${rect.left}px`;\n\t\toverlay.style.width = `${rect.width}px`;\n\t\toverlay.style.height = `${rect.height}px`;\n\t\toverlay.style.display = \"block\";\n\n\t\tconst classes = Array.from(el.classList).filter((c) => !c.startsWith(\"data-yns-\"));\n\t\tconst labelText = el.tagName.toLowerCase() + (classes.length ? `.${classes[0]}` : \"\");\n\t\tlabel.textContent = labelText;\n\t\tlabel.style.left = `${rect.left}px`;\n\t\tlabel.style.top = `${Math.max(0, rect.top - 22)}px`;\n\t\tlabel.style.display = \"block\";\n\t}\n\n\tconst handleMouseMove = (e: MouseEvent) => {\n\t\tconst el = document.elementFromPoint(e.clientX, e.clientY);\n\t\tif (shouldIgnore(el, [\"data-yns-design-overlay\"])) {\n\t\t\toverlay.style.display = \"none\";\n\t\t\tlabel.style.display = \"none\";\n\t\t\thoveredElement = null;\n\t\t\treturn;\n\t\t}\n\t\thoveredElement = el;\n\t\trequestAnimationFrame(() => {\n\t\t\tif (hoveredElement === el && enabled && el) {\n\t\t\t\tpositionOverlay(el);\n\t\t\t}\n\t\t});\n\t};\n\n\tconst handleMouseLeave = () => {\n\t\toverlay.style.display = \"none\";\n\t\tlabel.style.display = \"none\";\n\t\thoveredElement = null;\n\t};\n\n\tconst handleClick = (e: MouseEvent) => {\n\t\tif (!enabled || !hoveredElement) return;\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\t\te.stopImmediatePropagation();\n\n\t\tconst el = hoveredElement;\n\t\tif (shouldIgnore(el, [\"data-yns-design-overlay\"])) return;\n\n\t\tconst info = buildElementInfo(el, 120);\n\t\tconst selector = info.cssSelector;\n\n\t\tif (selectedElement) {\n\t\t\tselectedElement.el.removeAttribute(\"data-yns-selected\");\n\t\t}\n\n\t\tif (selectedElement && selectedElement.cssSelector === selector) {\n\t\t\tselectedElement = null;\n\t\t\twindow.parent.postMessage({ type: \"element-deselected\", data: info }, \"*\");\n\t\t} else {\n\t\t\tselectedElement = { el, cssSelector: selector };\n\t\t\tel.setAttribute(\"data-yns-selected\", \"\");\n\t\t\twindow.parent.postMessage({ type: \"element-selected\", data: info }, \"*\");\n\t\t}\n\t};\n\n\tconst handleKeyDown = (e: KeyboardEvent) => {\n\t\tif (e.key === \"Escape\" && enabled) {\n\t\t\tdisableDesignMode();\n\t\t\twindow.parent.postMessage({ type: \"design-mode-cleared\" }, \"*\");\n\t\t}\n\t};\n\n\tfunction enableDesignMode() {\n\t\tenabled = true;\n\t\tdocument.addEventListener(\"mousemove\", handleMouseMove, true);\n\t\tdocument.addEventListener(\"mouseleave\", handleMouseLeave);\n\t\tdocument.addEventListener(\"click\", handleClick, true);\n\t\tdocument.addEventListener(\"keydown\", handleKeyDown, true);\n\t}\n\n\tfunction disableDesignMode() {\n\t\tenabled = false;\n\t\tdocument.removeEventListener(\"mousemove\", handleMouseMove, true);\n\t\tdocument.removeEventListener(\"mouseleave\", handleMouseLeave);\n\t\tdocument.removeEventListener(\"click\", handleClick, true);\n\t\tdocument.removeEventListener(\"keydown\", handleKeyDown, true);\n\n\t\toverlay.style.display = \"none\";\n\t\tlabel.style.display = \"none\";\n\t\thoveredElement = null;\n\n\t\tif (selectedElement) {\n\t\t\tselectedElement.el.removeAttribute(\"data-yns-selected\");\n\t\t\tselectedElement = null;\n\t\t}\n\t}\n\n\twindow.addEventListener(\"message\", (event) => {\n\t\tconst msg = event.data;\n\t\tif (!msg || typeof msg !== \"object\") return;\n\n\t\tif (msg.type === \"design-mode-toggle\") {\n\t\t\tif (msg.enabled) {\n\t\t\t\tenableDesignMode();\n\t\t\t} else {\n\t\t\t\tdisableDesignMode();\n\t\t\t\twindow.parent.postMessage({ type: \"design-mode-cleared\" }, \"*\");\n\t\t\t}\n\t\t}\n\n\t\tif (msg.type === \"design-mode-deselect\") {\n\t\t\tif (selectedElement) {\n\t\t\t\tselectedElement.el.removeAttribute(\"data-yns-selected\");\n\t\t\t\tselectedElement = null;\n\t\t\t}\n\t\t}\n\t});\n}\n\nfunction initCommentModeInspector() {\n\tlet enabled = false;\n\tlet hoveredElement: Element | null = null;\n\tlet pins: Array<{ id: string; selector: string; number: number }> = [];\n\n\tconst overlay = document.createElement(\"div\");\n\toverlay.setAttribute(\"data-yns-comment-overlay\", \"hover\");\n\toverlay.style.cssText = [\n\t\t\"position: fixed\",\n\t\t\"pointer-events: none\",\n\t\t\"z-index: 2147483644\",\n\t\t\"border: 2px dashed #10b981\",\n\t\t\"background: rgba(16, 185, 129, 0.06)\",\n\t\t\"border-radius: 3px\",\n\t\t\"display: none\",\n\t\t\"transition: top 0.05s, left 0.05s, width 0.05s, height 0.05s\",\n\t].join(\";\");\n\n\tconst cursorLabel = document.createElement(\"div\");\n\tcursorLabel.setAttribute(\"data-yns-comment-overlay\", \"cursor-label\");\n\tcursorLabel.textContent = \"Click to comment\";\n\tcursorLabel.style.cssText = [\n\t\t\"position: fixed\",\n\t\t\"pointer-events: none\",\n\t\t\"z-index: 2147483645\",\n\t\t\"background: #059669\",\n\t\t\"color: #fff\",\n\t\t\"font-size: 11px\",\n\t\t\"font-family: ui-sans-serif, system-ui, sans-serif\",\n\t\t\"padding: 3px 8px\",\n\t\t\"border-radius: 4px\",\n\t\t\"white-space: nowrap\",\n\t\t\"display: none\",\n\t\t\"box-shadow: 0 2px 6px rgba(0,0,0,0.15)\",\n\t].join(\";\");\n\n\tconst pinContainer = document.createElement(\"div\");\n\tpinContainer.setAttribute(\"data-yns-comment-overlay\", \"pins\");\n\tpinContainer.style.cssText =\n\t\t\"position: fixed; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; z-index: 2147483643;\";\n\n\tdocument.documentElement.appendChild(overlay);\n\tdocument.documentElement.appendChild(cursorLabel);\n\tdocument.documentElement.appendChild(pinContainer);\n\n\tfunction renderPins() {\n\t\tpinContainer.innerHTML = \"\";\n\t\tfor (const pin of pins) {\n\t\t\tlet el: Element | null = null;\n\t\t\ttry {\n\t\t\t\tel = document.querySelector(pin.selector);\n\t\t\t} catch {\n\t\t\t\tel = null;\n\t\t\t}\n\t\t\tif (!el) continue;\n\n\t\t\tconst r = el.getBoundingClientRect();\n\t\t\tconst pinEl = document.createElement(\"div\");\n\t\t\tpinEl.style.cssText = [\n\t\t\t\t\"position: fixed\",\n\t\t\t\t`top: ${r.top - 12}px`,\n\t\t\t\t`left: ${r.left + r.width / 2 - 12}px`,\n\t\t\t\t\"width: 24px\",\n\t\t\t\t\"height: 24px\",\n\t\t\t\t\"border-radius: 50%\",\n\t\t\t\t\"background: #059669\",\n\t\t\t\t\"color: #fff\",\n\t\t\t\t\"display: flex\",\n\t\t\t\t\"align-items: center\",\n\t\t\t\t\"justify-content: center\",\n\t\t\t\t\"font-size: 12px\",\n\t\t\t\t\"font-weight: 600\",\n\t\t\t\t\"font-family: ui-sans-serif, system-ui, sans-serif\",\n\t\t\t\t\"box-shadow: 0 2px 8px rgba(0,0,0,0.2)\",\n\t\t\t\t\"pointer-events: none\",\n\t\t\t].join(\";\");\n\t\t\tpinEl.textContent = String(pin.number);\n\t\t\tpinContainer.appendChild(pinEl);\n\t\t}\n\t}\n\n\tconst handleMouseMove = (e: MouseEvent) => {\n\t\tconst el = document.elementFromPoint(e.clientX, e.clientY);\n\t\tif (shouldIgnore(el, [\"data-yns-comment-overlay\", \"data-yns-design-overlay\"])) {\n\t\t\toverlay.style.display = \"none\";\n\t\t\tcursorLabel.style.display = \"none\";\n\t\t\thoveredElement = null;\n\t\t\treturn;\n\t\t}\n\t\thoveredElement = el;\n\t\trequestAnimationFrame(() => {\n\t\t\tif (hoveredElement === el && enabled && el) {\n\t\t\t\tconst rect = el.getBoundingClientRect();\n\t\t\t\toverlay.style.top = `${rect.top}px`;\n\t\t\t\toverlay.style.left = `${rect.left}px`;\n\t\t\t\toverlay.style.width = `${rect.width}px`;\n\t\t\t\toverlay.style.height = `${rect.height}px`;\n\t\t\t\toverlay.style.display = \"block\";\n\n\t\t\t\tcursorLabel.style.left = `${e.clientX + 14}px`;\n\t\t\t\tcursorLabel.style.top = `${e.clientY + 14}px`;\n\t\t\t\tcursorLabel.style.display = \"block\";\n\t\t\t}\n\t\t});\n\t};\n\n\tconst handleMouseLeave = () => {\n\t\toverlay.style.display = \"none\";\n\t\tcursorLabel.style.display = \"none\";\n\t\thoveredElement = null;\n\t};\n\n\tconst handleClick = (e: MouseEvent) => {\n\t\tif (!enabled || !hoveredElement) return;\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\t\te.stopImmediatePropagation();\n\n\t\tconst el = hoveredElement;\n\t\tif (shouldIgnore(el, [\"data-yns-comment-overlay\", \"data-yns-design-overlay\"])) return;\n\n\t\tconst info = buildElementInfo(el, 200);\n\t\tconst rect = el.getBoundingClientRect();\n\n\t\twindow.parent.postMessage(\n\t\t\t{\n\t\t\t\ttype: \"comment-click\",\n\t\t\t\tdata: {\n\t\t\t\t\telement: info,\n\t\t\t\t\tclickPosition: { x: e.clientX, y: e.clientY },\n\t\t\t\t\telementRect: { top: rect.top, left: rect.left, width: rect.width, height: rect.height },\n\t\t\t\t\tpagePath: window.location.pathname,\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"*\",\n\t\t);\n\t};\n\n\tconst handleKeyDown = (e: KeyboardEvent) => {\n\t\tif (e.key === \"Escape\" && enabled) {\n\t\t\tdisableCommentMode();\n\t\t\twindow.parent.postMessage({ type: \"comment-mode-cleared\" }, \"*\");\n\t\t}\n\t};\n\n\tfunction enableCommentMode() {\n\t\tenabled = true;\n\t\tdocument.body.style.cursor = \"crosshair\";\n\t\tdocument.addEventListener(\"mousemove\", handleMouseMove, true);\n\t\tdocument.addEventListener(\"mouseleave\", handleMouseLeave);\n\t\tdocument.addEventListener(\"click\", handleClick, true);\n\t\tdocument.addEventListener(\"keydown\", handleKeyDown, true);\n\t}\n\n\tfunction disableCommentMode() {\n\t\tenabled = false;\n\t\tdocument.body.style.cursor = \"\";\n\t\tdocument.removeEventListener(\"mousemove\", handleMouseMove, true);\n\t\tdocument.removeEventListener(\"mouseleave\", handleMouseLeave);\n\t\tdocument.removeEventListener(\"click\", handleClick, true);\n\t\tdocument.removeEventListener(\"keydown\", handleKeyDown, true);\n\n\t\toverlay.style.display = \"none\";\n\t\tcursorLabel.style.display = \"none\";\n\t\thoveredElement = null;\n\t}\n\n\tlet rafPending = false;\n\tconst scheduleRender = () => {\n\t\tif (rafPending) return;\n\t\trafPending = true;\n\t\trequestAnimationFrame(() => {\n\t\t\trafPending = false;\n\t\t\trenderPins();\n\t\t});\n\t};\n\twindow.addEventListener(\"scroll\", scheduleRender, { passive: true });\n\twindow.addEventListener(\"resize\", scheduleRender, { passive: true });\n\n\twindow.addEventListener(\"message\", (event) => {\n\t\tconst msg = event.data;\n\t\tif (!msg || typeof msg !== \"object\") return;\n\n\t\tif (msg.type === \"comment-mode-toggle\") {\n\t\t\tif (msg.enabled) enableCommentMode();\n\t\t\telse disableCommentMode();\n\t\t}\n\n\t\tif (msg.type === \"comment-pins-update\") {\n\t\t\tpins = msg.pins ?? [];\n\t\t\trenderPins();\n\t\t}\n\n\t\tif (msg.type === \"comment-pin-remove\") {\n\t\t\tpins = pins.filter((p) => p.id !== msg.pinId);\n\t\t\trenderPins();\n\t\t}\n\t});\n}\n"],"mappings":"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","names":["startSandboxInspectors","initDesignModeInspector","initCommentModeInspector","initRuntimeErrorReporter","MIN_INTERVAL_MS","MAX_REPORTS_PER_LOAD","MAX_STACK_LENGTH","lastSentAt","lastMessage","sentCount","report","message","stack","now","event","error","reason","IGNORED_TAGS","generateCssSelector","el","parts","current","selector","classes","c","parent","tag","s","index","buildElementInfo","textLimit","rect","computed","text","shouldIgnore","overlayAttrs","attr","enabled","hoveredElement","selectedElement","overlay","label","style","positionOverlay","labelText","handleMouseMove","e","handleMouseLeave","handleClick","info","handleKeyDown","disableDesignMode","enableDesignMode","msg","pins","cursorLabel","pinContainer","renderPins","pin","r","pinEl","disableCommentMode","enableCommentMode","rafPending","scheduleRender"]}
|
|
1
|
+
{"version":3,"sources":["../src/sandbox-inspectors.ts"],"sourcesContent":["/**\n * Sandbox Inspectors — side-effect entry.\n *\n * Runs inside per-store storefronts under the AI Builder sandbox dev server.\n * Two responsibilities:\n * 1. Report uncaught runtime errors to the parent /design iframe.\n * 2. Load the builder-annotations UI (blue annotation pins, popovers, creation\n * composer) from the central yns-toolbar CDN when embedded in the /design\n * iframe. The UI lives there — not here — so fixes ship by pushing the\n * toolbar repo instead of publishing commerce-kit + bumping every store.\n *\n * Always-on: both parts are gated at runtime on being embedded in a parent\n * frame. Gating on NODE_ENV is wrong (always \"production\" on Vercel) and any\n * build-time gate gets folded out by the commerce-kit bundle, leaving an empty\n * file.\n */\n\n/**\n * Exported so `browser.tsx` can `export { startSandboxInspectors }` — the\n * named binding anchors this module against esbuild tree-shaking when\n * commerce-kit is bundled. Without it, an `export * from \"./sandbox-inspectors\"`\n * re-exports an empty binding set and esbuild DCEs the whole file.\n */\nexport function startSandboxInspectors(): void {\n\tif (typeof window === \"undefined\") return;\n\tconsole.log(\"[YNS Sandbox Inspectors] module evaluated\");\n\tinitRuntimeErrorReporter();\n\tinitBuilderAnnotationsLoader();\n}\n\n// Auto-start on import.\nstartSandboxInspectors();\n\n/**\n * Injects the builder-annotations bundle from the yns-toolbar CDN. The bundle\n * self-gates on being framed too, so this is belt-and-braces; loading only when\n * framed keeps direct sandbox-URL visits (and feedback preview deploys, which\n * import this module top-level) free of the extra script.\n */\nfunction initBuilderAnnotationsLoader() {\n\tif (window.parent === window) return;\n\n\tconst SCRIPT_ID = \"yns-builder-annotations-script\";\n\tif (document.getElementById(SCRIPT_ID)) return;\n\n\tconst base = process.env.NEXT_PUBLIC_YNS_TOOLBAR_BASE || \"https://toolbar.yns.cx\";\n\tconst script = document.createElement(\"script\");\n\tscript.id = SCRIPT_ID;\n\tscript.async = true;\n\tscript.src = `${base}/annotations.js`;\n\tdocument.head.appendChild(script);\n}\n\n/**\n * Reports uncaught runtime errors (e.g. React's \"Maximum update depth\n * exceeded\" from an infinite render loop) to the parent /design iframe so the\n * AI Builder can surface a crash overlay instead of a silently frozen preview.\n *\n * Unlike the annotations UI, this posts unsolicited messages — so it only\n * attaches when actually embedded in a parent frame. Render loops fire the same\n * error continuously; rate-limit hard so the parent isn't flooded.\n */\nfunction initRuntimeErrorReporter() {\n\tif (window.parent === window) return;\n\n\tconst MIN_INTERVAL_MS = 5_000;\n\tconst MAX_REPORTS_PER_LOAD = 10;\n\tconst MAX_STACK_LENGTH = 2_000;\n\n\tlet lastSentAt = 0;\n\tlet lastMessage = \"\";\n\tlet sentCount = 0;\n\n\tfunction report(message: string, stack: string | undefined) {\n\t\tconst now = Date.now();\n\t\tif (sentCount >= MAX_REPORTS_PER_LOAD) return;\n\t\tif (message === lastMessage && now - lastSentAt < MIN_INTERVAL_MS) return;\n\t\tlastSentAt = now;\n\t\tlastMessage = message;\n\t\tsentCount += 1;\n\t\twindow.parent.postMessage(\n\t\t\t{\n\t\t\t\ttype: \"runtime-error\",\n\t\t\t\tmessage,\n\t\t\t\tstack: stack ? stack.slice(0, MAX_STACK_LENGTH) : undefined,\n\t\t\t\tpagePath: window.location.pathname,\n\t\t\t},\n\t\t\t\"*\",\n\t\t);\n\t}\n\n\twindow.addEventListener(\"error\", (event) => {\n\t\tconst error: unknown = event.error;\n\t\tconst message = error instanceof Error ? error.message : event.message || \"Unknown error\";\n\t\tconst stack = error instanceof Error ? error.stack : undefined;\n\t\treport(message, stack);\n\t});\n\n\twindow.addEventListener(\"unhandledrejection\", (event) => {\n\t\tconst reason: unknown = event.reason;\n\t\tconst message = reason instanceof Error ? reason.message : String(reason ?? \"Unhandled rejection\");\n\t\tconst stack = reason instanceof Error ? reason.stack : undefined;\n\t\treport(message, stack);\n\t});\n}\n"],"mappings":"AAuBO,SAASA,GAA+B,CAC1C,OAAO,OAAW,MACtB,QAAQ,IAAI,2CAA2C,EACvDC,EAAyB,EACzBC,EAA6B,EAC9B,CAGAF,EAAuB,EAQvB,SAASE,GAA+B,CACvC,GAAI,OAAO,SAAW,OAAQ,OAE9B,IAAMC,EAAY,iCAClB,GAAI,SAAS,eAAeA,CAAS,EAAG,OAExC,IAAMC,EAAO,QAAQ,IAAI,8BAAgC,yBACnDC,EAAS,SAAS,cAAc,QAAQ,EAC9CA,EAAO,GAAKF,EACZE,EAAO,MAAQ,GACfA,EAAO,IAAM,GAAGD,CAAI,kBACpB,SAAS,KAAK,YAAYC,CAAM,CACjC,CAWA,SAASJ,GAA2B,CACnC,GAAI,OAAO,SAAW,OAAQ,OAE9B,IAAMK,EAAkB,IAClBC,EAAuB,GACvBC,EAAmB,IAErBC,EAAa,EACbC,EAAc,GACdC,EAAY,EAEhB,SAASC,EAAOC,EAAiBC,EAA2B,CAC3D,IAAMC,EAAM,KAAK,IAAI,EACjBJ,GAAaJ,GACbM,IAAYH,GAAeK,EAAMN,EAAaH,IAClDG,EAAaM,EACbL,EAAcG,EACdF,GAAa,EACb,OAAO,OAAO,YACb,CACC,KAAM,gBACN,QAAAE,EACA,MAAOC,EAAQA,EAAM,MAAM,EAAGN,CAAgB,EAAI,OAClD,SAAU,OAAO,SAAS,QAC3B,EACA,GACD,EACD,CAEA,OAAO,iBAAiB,QAAUQ,GAAU,CAC3C,IAAMC,EAAiBD,EAAM,MACvBH,EAAUI,aAAiB,MAAQA,EAAM,QAAUD,EAAM,SAAW,gBACpEF,EAAQG,aAAiB,MAAQA,EAAM,MAAQ,OACrDL,EAAOC,EAASC,CAAK,CACtB,CAAC,EAED,OAAO,iBAAiB,qBAAuBE,GAAU,CACxD,IAAME,EAAkBF,EAAM,OACxBH,EAAUK,aAAkB,MAAQA,EAAO,QAAU,OAAOA,GAAU,qBAAqB,EAC3FJ,EAAQI,aAAkB,MAAQA,EAAO,MAAQ,OACvDN,EAAOC,EAASC,CAAK,CACtB,CAAC,CACF","names":["startSandboxInspectors","initRuntimeErrorReporter","initBuilderAnnotationsLoader","SCRIPT_ID","base","script","MIN_INTERVAL_MS","MAX_REPORTS_PER_LOAD","MAX_STACK_LENGTH","lastSentAt","lastMessage","sentCount","report","message","stack","now","event","error","reason"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { APIMeGetResult, APISocialsGetResult, APIBrandsBrowseQueryParams, APIBrandsBrowseResult, APIBrandGetByIdParams, APIBrandGetByIdResult, APIBrandCreateBody, APIBrandCreateResult, APIBrandUpdateBody, APIBrandUpdateResult, APIBrandDeleteResult, APIBrandAssignProductsBody, APIBrandAssignProductsResult, APIOrderRefundsParams, APIOrderRefundsBrowseQueryParams, APIOrderRefundsBrowseResult, APIOrderRefundGetParams, APIOrderRefundGetResult, APIProductBatchBody, APIProductBatchResult, APICartDeleteResult, APIProductsBrowseQueryParams, APIProductsBrowseResult, APIProductFiltersResult, APIProductGetByIdParams, APIProductGetByIdResult, APIOrdersBrowseQueryParams, APIOrdersBrowseResult, APIOrderGetByIdParams, APIOrderGetByIdResult, APICartCreateBody, APICartCreateResult, APICartGetResult, APICouponsBrowseQueryParams, APICouponsBrowseResult, APICouponGetByIdParams, APICouponGetByIdResult, APICouponCreateBody, APICouponCreateResult, APICouponUpdateBody, APICouponUpdateResult, APICouponDeleteResult, APICollectionGetByIdParams, APICollectionGetByIdResult, APICollectionsBrowseQueryParams, APICollectionsBrowseResult, APICollectionCreateBody, APICollectionCreateResult, APICollectionUpdateBody, APICollectionUpdateResult, APICollectionDeleteResult, APICategoryGetByIdParams, APICategoryGetByIdResult, APICategoriesBrowseQueryParams, APICategoriesBrowseResult, APIPostsBrowseQueryParams, APIPostsBrowseResult, APIPostGetByIdParams, APIPostGetByIdResult, APIPostCreateBody, APIPostCreateResult, APIPostUpdateBody, APIPostUpdateResult, APIPostDeleteResult, APIPostCommentsBrowseQueryParams, APIPostCommentsBrowseResult, APIPostCommentCreateBody, APIPostCommentCreateResult, APIBlogCategoriesBrowseQueryParams, APIBlogCategoriesBrowseResult, APIBlogCategoryGetByIdParams, APIBlogCategoryGetByIdResult, APIBlogCategoryCreateBody, APIBlogCategoryCreateResult, APIBlogCategoryUpdateBody, APIBlogCategoryUpdateResult, APIBlogCategoryDeleteResult, APICustomersBrowseQueryParams, APICustomersBrowseResult, APICustomerGetByIdParams, APICustomerGetByIdResult, APICustomerUpdateBody, APICustomerUpdateResult, APICustomerAddressCreateBody, APICustomerAddressCreateResult, APICustomerOrdersBrowseQueryParams, APICustomerOrdersBrowseResult, APIInventoryBrowseQueryParams, APIInventoryBrowseResult, APIInventoryAdjustBody, APIInventoryAdjustResult, APIVariantGetByIdParams, APIVariantGetByIdResult, APIVariantUpdateBody, APIVariantUpdateResult, APIVariantCreateBody, APIVariantCreateResult, APISubscriberCreateBody, APISubscriberCreateResult, APISubscriberDeleteResult, APIContactMessageCreateBody, APIContactMessageCreateResult, APIProductCreateBody, APIProductCreateResult, APIProductUpdateBody, APIProductUpdateResult, APIProductDeleteResult, APIProductReviewsBrowseQueryParams, APIProductReviewsBrowseResult, APIProductReviewCreateBody, APIProductReviewCreateResult, APIEventsBrowseQueryParams, APIEventsBrowseResult, APIEventGetByIdParams, APIEventGetByIdResult, APIEventCreateBody, APIEventCreateResult, APIEventUpdateBody, APIEventUpdateResult, APIEventAttendeesBrowseResult, APITicketsGetResult, APITicketsUpdateBody, APITicketsUpdateResult, APITicketAttendeeGetResult, APICategoryCreateBody, APICategoryCreateResult, APICategoryUpdateBody, APICategoryUpdateResult, APICategoryDeleteResult, APIOrderUpdateBody, APIOrderUpdateResult, APILegalPagesBrowseQueryParams, APILegalPagesBrowseResult, APILegalPageGetByPathQueryParams, APILegalPageGetByPathResult, APILegalPageCreateBody, APILegalPageCreateQueryParams, APILegalPageCreateResult, APILegalPageUpdateBody, APILegalPageUpdateQueryParams, APILegalPageUpdateResult, APISearchQueryParams, APISearchResult, APIInstaviewImagesBrowseParams, APIInstaviewImagesBrowseQueryParams, APIInstaviewImagesBrowseResult } from './api-types.js';
|
|
2
|
-
export { APICartAddBody, APICartAddResult, APICartRemoveItemQueryParams, APICartRemoveItemResult, APICategoryGetByIdQueryParams, APICategoryUpdateQueryParams, APICollectionGetByIdQueryParams, APILegalPageGetByPathParams, APIProductDeleteQueryParams, APIProductGetByIdQueryParams, APIProductUpdateQueryParams, APITicketAttendeeGetParams, APITicketsGetParams, APITicketsGetQueryParams, APIVariantGetByIdQueryParams, JSONContent } from './api-types.js';
|
|
1
|
+
import { APIMeGetResult, APISocialsGetResult, APIBrandsBrowseQueryParams, APIBrandsBrowseResult, APIBrandGetByIdParams, APIBrandGetByIdResult, APIBrandCreateBody, APIBrandCreateResult, APIBrandUpdateBody, APIBrandUpdateResult, APIBrandDeleteResult, APIBrandAssignProductsBody, APIBrandAssignProductsResult, APIOrderRefundsParams, APIOrderRefundsBrowseQueryParams, APIOrderRefundsBrowseResult, APIOrderRefundGetParams, APIOrderRefundGetResult, APIProductBatchBody, APIProductBatchResult, APICartDeleteResult, APIProductsBrowseQueryParams, APIProductsBrowseResult, APIProductFiltersResult, APIProductGetByIdParams, APIProductGetByIdResult, APIOrdersBrowseQueryParams, APIOrdersBrowseResult, APIOrderGetByIdParams, APIOrderGetByIdResult, APICartCreateBody, APICartCreateResult, APICartGetResult, APICouponsBrowseQueryParams, APICouponsBrowseResult, APICouponGetByIdParams, APICouponGetByIdResult, APICouponCreateBody, APICouponCreateResult, APICouponUpdateBody, APICouponUpdateResult, APICouponDeleteResult, APISupportCasesBrowseQueryParams, APISupportCasesBrowseResult, APISupportCaseGetParams, APISupportCaseGetResult, APISupportCaseCreateBody, APISupportCaseCreateResult, APISupportCaseUpdateBody, APISupportCaseUpdateResult, APISupportCaseMessageCreateBody, APISupportCaseMessageCreateResult, APICollectionGetByIdParams, APICollectionGetByIdResult, APICollectionsBrowseQueryParams, APICollectionsBrowseResult, APICollectionCreateBody, APICollectionCreateResult, APICollectionUpdateBody, APICollectionUpdateResult, APICollectionDeleteResult, APICategoryGetByIdParams, APICategoryGetByIdResult, APICategoriesBrowseQueryParams, APICategoriesBrowseResult, APIPostsBrowseQueryParams, APIPostsBrowseResult, APIPostGetByIdParams, APIPostGetByIdResult, APIPostCreateBody, APIPostCreateResult, APIPostUpdateBody, APIPostUpdateResult, APIPostDeleteResult, APIPostCommentsBrowseQueryParams, APIPostCommentsBrowseResult, APIPostCommentCreateBody, APIPostCommentCreateResult, APIBlogCategoriesBrowseQueryParams, APIBlogCategoriesBrowseResult, APIBlogCategoryGetByIdParams, APIBlogCategoryGetByIdResult, APIBlogCategoryCreateBody, APIBlogCategoryCreateResult, APIBlogCategoryUpdateBody, APIBlogCategoryUpdateResult, APIBlogCategoryDeleteResult, APICustomersBrowseQueryParams, APICustomersBrowseResult, APICustomerGetByIdParams, APICustomerGetByIdResult, APICustomerUpdateBody, APICustomerUpdateResult, APICustomerAddressCreateBody, APICustomerAddressCreateResult, APICustomerOrdersBrowseQueryParams, APICustomerOrdersBrowseResult, APIInventoryBrowseQueryParams, APIInventoryBrowseResult, APIInventoryAdjustBody, APIInventoryAdjustResult, APIVariantGetByIdParams, APIVariantGetByIdResult, APIVariantUpdateBody, APIVariantUpdateResult, APIVariantCreateBody, APIVariantCreateResult, APISubscriberCreateBody, APISubscriberCreateResult, APISubscriberDeleteResult, APIContactMessageCreateBody, APIContactMessageCreateResult, APIProductCreateBody, APIProductCreateResult, APIProductUpdateBody, APIProductUpdateResult, APIProductDeleteResult, APIProductReviewsBrowseQueryParams, APIProductReviewsBrowseResult, APIProductReviewCreateBody, APIProductReviewCreateResult, APIEventsBrowseQueryParams, APIEventsBrowseResult, APIEventGetByIdParams, APIEventGetByIdResult, APIEventCreateBody, APIEventCreateResult, APIEventUpdateBody, APIEventUpdateResult, APIEventAttendeesBrowseResult, APITicketsGetResult, APITicketsUpdateBody, APITicketsUpdateResult, APITicketAttendeeGetResult, APICategoryCreateBody, APICategoryCreateResult, APICategoryUpdateBody, APICategoryUpdateResult, APICategoryDeleteResult, APIOrderUpdateBody, APIOrderUpdateResult, APILegalPagesBrowseQueryParams, APILegalPagesBrowseResult, APILegalPageGetByPathQueryParams, APILegalPageGetByPathResult, APILegalPageCreateBody, APILegalPageCreateQueryParams, APILegalPageCreateResult, APILegalPageUpdateBody, APILegalPageUpdateQueryParams, APILegalPageUpdateResult, APISearchQueryParams, APISearchResult, APIInstaviewImagesBrowseParams, APIInstaviewImagesBrowseQueryParams, APIInstaviewImagesBrowseResult } from './api-types.js';
|
|
2
|
+
export { APICartAddBody, APICartAddResult, APICartRemoveItemQueryParams, APICartRemoveItemResult, APICategoryGetByIdQueryParams, APICategoryUpdateQueryParams, APICollectionGetByIdQueryParams, APILegalPageGetByPathParams, APIProductDeleteQueryParams, APIProductGetByIdQueryParams, APIProductUpdateQueryParams, APISupportCase, APISupportCaseMessage, APITicketAttendeeGetParams, APITicketsGetParams, APITicketsGetQueryParams, APIVariantGetByIdQueryParams, JSONContent } from './api-types.js';
|
|
3
3
|
|
|
4
4
|
interface CommerceConfig {
|
|
5
5
|
/** API key. Defaults to process.env.YNS_API_KEY */
|
|
@@ -77,6 +77,19 @@ declare class YNSProvider {
|
|
|
77
77
|
couponCreate(body: APICouponCreateBody): Promise<APICouponCreateResult>;
|
|
78
78
|
couponUpdate(params: APICouponGetByIdParams, body: APICouponUpdateBody): Promise<APICouponUpdateResult>;
|
|
79
79
|
couponDelete(params: APICouponGetByIdParams): Promise<APICouponDeleteResult>;
|
|
80
|
+
/** List the store's support cases (merchant ↔ YNS support), newest activity first. */
|
|
81
|
+
supportCaseBrowse(params?: APISupportCasesBrowseQueryParams): Promise<APISupportCasesBrowseResult>;
|
|
82
|
+
/**
|
|
83
|
+
* Look up a case with its message thread by UUID or case number ("123" or "000123").
|
|
84
|
+
* Resolves to `null` when not found. Internal YNS notes are never included.
|
|
85
|
+
*/
|
|
86
|
+
supportCaseGet(params: APISupportCaseGetParams): Promise<APISupportCaseGetResult | null>;
|
|
87
|
+
/** Open a support case with the YNS team. Omit `subject` to have one generated from the description. */
|
|
88
|
+
supportCaseCreate(body: APISupportCaseCreateBody): Promise<APISupportCaseCreateResult>;
|
|
89
|
+
/** Close (`status: "closed"`) or reopen (`status: "open"`) a case. */
|
|
90
|
+
supportCaseUpdate(params: APISupportCaseGetParams, body: APISupportCaseUpdateBody): Promise<APISupportCaseUpdateResult>;
|
|
91
|
+
/** Add a merchant-side reply to the case thread; replying reopens a closed or answered case. */
|
|
92
|
+
supportCaseReply(params: APISupportCaseGetParams, body: APISupportCaseMessageCreateBody): Promise<APISupportCaseMessageCreateResult>;
|
|
80
93
|
collectionGet(params: APICollectionGetByIdParams): Promise<APICollectionGetByIdResult | null>;
|
|
81
94
|
collectionBrowse(params: APICollectionsBrowseQueryParams): Promise<APICollectionsBrowseResult>;
|
|
82
95
|
collectionCreate(body: APICollectionCreateBody): Promise<APICollectionCreateResult>;
|
|
@@ -191,4 +204,4 @@ declare class YNSProvider {
|
|
|
191
204
|
|
|
192
205
|
declare function Commerce(config?: CommerceConfig): YNSProvider;
|
|
193
206
|
|
|
194
|
-
export { APIBlogCategoriesBrowseQueryParams, APIBlogCategoriesBrowseResult, APIBlogCategoryCreateBody, APIBlogCategoryCreateResult, APIBlogCategoryDeleteResult, APIBlogCategoryGetByIdParams, APIBlogCategoryGetByIdResult, APIBlogCategoryUpdateBody, APIBlogCategoryUpdateResult, APIBrandAssignProductsBody, APIBrandAssignProductsResult, APIBrandCreateBody, APIBrandCreateResult, APIBrandDeleteResult, APIBrandGetByIdParams, APIBrandGetByIdResult, APIBrandUpdateBody, APIBrandUpdateResult, APIBrandsBrowseQueryParams, APIBrandsBrowseResult, APICartCreateBody, APICartCreateResult, APICartDeleteResult, APICartGetResult, APICategoriesBrowseQueryParams, APICategoriesBrowseResult, APICategoryCreateBody, APICategoryCreateResult, APICategoryDeleteResult, APICategoryGetByIdParams, APICategoryGetByIdResult, APICategoryUpdateBody, APICategoryUpdateResult, APICollectionCreateBody, APICollectionCreateResult, APICollectionDeleteResult, APICollectionGetByIdParams, APICollectionGetByIdResult, type APICollectionImportMembershipsBody, type APICollectionImportMembershipsResult, APICollectionUpdateBody, APICollectionUpdateResult, APICollectionsBrowseQueryParams, APICollectionsBrowseResult, APIContactMessageCreateBody, APIContactMessageCreateResult, APICouponCreateBody, APICouponCreateResult, APICouponDeleteResult, APICouponGetByIdParams, APICouponGetByIdResult, APICouponUpdateBody, APICouponUpdateResult, APICouponsBrowseQueryParams, APICouponsBrowseResult, APICustomerAddressCreateBody, APICustomerAddressCreateResult, APICustomerGetByIdParams, APICustomerGetByIdResult, APICustomerOrdersBrowseQueryParams, APICustomerOrdersBrowseResult, APICustomerUpdateBody, APICustomerUpdateResult, APICustomersBrowseQueryParams, APICustomersBrowseResult, APIEventAttendeesBrowseResult, APIEventCreateBody, APIEventCreateResult, APIEventGetByIdParams, APIEventGetByIdResult, APIEventUpdateBody, APIEventUpdateResult, APIEventsBrowseQueryParams, APIEventsBrowseResult, APIInstaviewImagesBrowseParams, APIInstaviewImagesBrowseQueryParams, APIInstaviewImagesBrowseResult, APIInventoryAdjustBody, APIInventoryAdjustResult, APIInventoryBrowseQueryParams, APIInventoryBrowseResult, APILegalPageCreateBody, APILegalPageCreateQueryParams, APILegalPageCreateResult, APILegalPageGetByPathQueryParams, APILegalPageGetByPathResult, APILegalPageUpdateBody, APILegalPageUpdateQueryParams, APILegalPageUpdateResult, APILegalPagesBrowseQueryParams, APILegalPagesBrowseResult, APIMeGetResult, APIOrderGetByIdParams, APIOrderGetByIdResult, APIOrderRefundGetParams, APIOrderRefundGetResult, APIOrderRefundsBrowseQueryParams, APIOrderRefundsBrowseResult, APIOrderRefundsParams, APIOrderUpdateBody, APIOrderUpdateResult, APIOrdersBrowseQueryParams, APIOrdersBrowseResult, APIPostCommentCreateBody, APIPostCommentCreateResult, APIPostCommentsBrowseQueryParams, APIPostCommentsBrowseResult, APIPostCreateBody, APIPostCreateResult, APIPostDeleteResult, APIPostGetByIdParams, APIPostGetByIdResult, APIPostUpdateBody, APIPostUpdateResult, APIPostsBrowseQueryParams, APIPostsBrowseResult, APIProductBatchBody, APIProductBatchResult, APIProductCreateBody, APIProductCreateResult, APIProductDeleteResult, APIProductFiltersResult, APIProductGetByIdParams, APIProductGetByIdResult, APIProductReviewCreateBody, APIProductReviewCreateResult, APIProductReviewsBrowseQueryParams, APIProductReviewsBrowseResult, APIProductUpdateBody, APIProductUpdateResult, APIProductsBrowseQueryParams, APIProductsBrowseResult, APISearchQueryParams, APISearchResult, APISocialsGetResult, APISubscriberCreateBody, APISubscriberCreateResult, APISubscriberDeleteResult, APITicketAttendeeGetResult, APITicketsGetResult, APITicketsUpdateBody, APITicketsUpdateResult, APIVariantCreateBody, APIVariantCreateResult, APIVariantGetByIdParams, APIVariantGetByIdResult, APIVariantUpdateBody, APIVariantUpdateResult, Commerce, type CommerceConfig, YNSProvider };
|
|
207
|
+
export { APIBlogCategoriesBrowseQueryParams, APIBlogCategoriesBrowseResult, APIBlogCategoryCreateBody, APIBlogCategoryCreateResult, APIBlogCategoryDeleteResult, APIBlogCategoryGetByIdParams, APIBlogCategoryGetByIdResult, APIBlogCategoryUpdateBody, APIBlogCategoryUpdateResult, APIBrandAssignProductsBody, APIBrandAssignProductsResult, APIBrandCreateBody, APIBrandCreateResult, APIBrandDeleteResult, APIBrandGetByIdParams, APIBrandGetByIdResult, APIBrandUpdateBody, APIBrandUpdateResult, APIBrandsBrowseQueryParams, APIBrandsBrowseResult, APICartCreateBody, APICartCreateResult, APICartDeleteResult, APICartGetResult, APICategoriesBrowseQueryParams, APICategoriesBrowseResult, APICategoryCreateBody, APICategoryCreateResult, APICategoryDeleteResult, APICategoryGetByIdParams, APICategoryGetByIdResult, APICategoryUpdateBody, APICategoryUpdateResult, APICollectionCreateBody, APICollectionCreateResult, APICollectionDeleteResult, APICollectionGetByIdParams, APICollectionGetByIdResult, type APICollectionImportMembershipsBody, type APICollectionImportMembershipsResult, APICollectionUpdateBody, APICollectionUpdateResult, APICollectionsBrowseQueryParams, APICollectionsBrowseResult, APIContactMessageCreateBody, APIContactMessageCreateResult, APICouponCreateBody, APICouponCreateResult, APICouponDeleteResult, APICouponGetByIdParams, APICouponGetByIdResult, APICouponUpdateBody, APICouponUpdateResult, APICouponsBrowseQueryParams, APICouponsBrowseResult, APICustomerAddressCreateBody, APICustomerAddressCreateResult, APICustomerGetByIdParams, APICustomerGetByIdResult, APICustomerOrdersBrowseQueryParams, APICustomerOrdersBrowseResult, APICustomerUpdateBody, APICustomerUpdateResult, APICustomersBrowseQueryParams, APICustomersBrowseResult, APIEventAttendeesBrowseResult, APIEventCreateBody, APIEventCreateResult, APIEventGetByIdParams, APIEventGetByIdResult, APIEventUpdateBody, APIEventUpdateResult, APIEventsBrowseQueryParams, APIEventsBrowseResult, APIInstaviewImagesBrowseParams, APIInstaviewImagesBrowseQueryParams, APIInstaviewImagesBrowseResult, APIInventoryAdjustBody, APIInventoryAdjustResult, APIInventoryBrowseQueryParams, APIInventoryBrowseResult, APILegalPageCreateBody, APILegalPageCreateQueryParams, APILegalPageCreateResult, APILegalPageGetByPathQueryParams, APILegalPageGetByPathResult, APILegalPageUpdateBody, APILegalPageUpdateQueryParams, APILegalPageUpdateResult, APILegalPagesBrowseQueryParams, APILegalPagesBrowseResult, APIMeGetResult, APIOrderGetByIdParams, APIOrderGetByIdResult, APIOrderRefundGetParams, APIOrderRefundGetResult, APIOrderRefundsBrowseQueryParams, APIOrderRefundsBrowseResult, APIOrderRefundsParams, APIOrderUpdateBody, APIOrderUpdateResult, APIOrdersBrowseQueryParams, APIOrdersBrowseResult, APIPostCommentCreateBody, APIPostCommentCreateResult, APIPostCommentsBrowseQueryParams, APIPostCommentsBrowseResult, APIPostCreateBody, APIPostCreateResult, APIPostDeleteResult, APIPostGetByIdParams, APIPostGetByIdResult, APIPostUpdateBody, APIPostUpdateResult, APIPostsBrowseQueryParams, APIPostsBrowseResult, APIProductBatchBody, APIProductBatchResult, APIProductCreateBody, APIProductCreateResult, APIProductDeleteResult, APIProductFiltersResult, APIProductGetByIdParams, APIProductGetByIdResult, APIProductReviewCreateBody, APIProductReviewCreateResult, APIProductReviewsBrowseQueryParams, APIProductReviewsBrowseResult, APIProductUpdateBody, APIProductUpdateResult, APIProductsBrowseQueryParams, APIProductsBrowseResult, APISearchQueryParams, APISearchResult, APISocialsGetResult, APISubscriberCreateBody, APISubscriberCreateResult, APISubscriberDeleteResult, APISupportCaseCreateBody, APISupportCaseCreateResult, APISupportCaseGetParams, APISupportCaseGetResult, APISupportCaseMessageCreateBody, APISupportCaseMessageCreateResult, APISupportCaseUpdateBody, APISupportCaseUpdateResult, APISupportCasesBrowseQueryParams, APISupportCasesBrowseResult, APITicketAttendeeGetResult, APITicketsGetResult, APITicketsUpdateBody, APITicketsUpdateResult, APIVariantCreateBody, APIVariantCreateResult, APIVariantGetByIdParams, APIVariantGetByIdResult, APIVariantUpdateBody, APIVariantUpdateResult, Commerce, type CommerceConfig, YNSProvider };
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import"./chunk-PNKB6P4V.js";var g=process.env.YNS_API_KEY,m={YNS_API_KEY:g};var P={DEBUG:0,LOG:1,WARN:2,ERROR:3},p=process.env.NEXT_PUBLIC_LOG_LEVEL||"LOG",u=P[p],d="\x1B[0m",B="\x1B[34m",R="\x1B[32m",C="\x1B[33m",h="\x1B[31m",f="\u23F1\uFE0F",w="\u{1F41B}",S="\u2714\uFE0F",G="\u26A0\uFE0F",$="\u274C",y=`${f} `,v=`${B}${w}${d} `,E=`${R}${S}${d} `,U=`${C}${G}${d} `,O=`${h}${$}${d} `,I=c=>{let e=c?`[${c}] `:"";return{getLogger(t){return I([c,t].filter(Boolean).join(" > "))},time(t){u>P.DEBUG||console.time([y,e,t].filter(Boolean).join(" "))},timeEnd(t){u>P.DEBUG||console.timeEnd([y,e,t].filter(Boolean).join(" "))},debug(...t){u>P.DEBUG||console.log(...[v,e,...t].filter(Boolean))},log(...t){u>P.LOG||console.log(...[E,e,...t].filter(Boolean))},dir(t,s){u>P.LOG||console.dir(t,s)},warn(...t){u>P.WARN||console.warn(...[U,e,...t].filter(Boolean))},error(...t){u>P.ERROR||console.error(...[O,e,...t].filter(Boolean))}}},L=I();var l=class{#s;#t=I("YNSProvider");constructor(e={}){let t=e.token??m.YNS_API_KEY,s=m.YNS_API_KEY?.startsWith("sk-s-");if(!t)throw new Error("YNS API key is required. Set YNS_API_KEY environment variable or pass token in config.");let r=e.endpoint??(s?"https://yns.cx":"https://yns.store");this.#s={version:"v1",...e,token:t,endpoint:r},this.#t.debug("YNSProvider initialized",{endpoint:r,token:e.token?"from config":"from env"})}async#e(e,t="GET",s){let r=await this.#o(e,t,s);return this.#n(r,e,t)}async#r(e){let t=await this.#o(e,"GET");return t.status===404?null:this.#n(t,e,"GET")}async#o(e,t,s){let r=this.#t.getLogger("#restRequest"),o=`${this.#s.endpoint}/api/${this.#s.version}${e}`;return r.debug(`Making ${t} request to YNS API: ${o}`),fetch(o,{method:t,headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.#s.token}`},body:s?JSON.stringify(s):void 0})}async#n(e,t,s){let r=this.#t.getLogger("#restRequest"),o=`${this.#s.endpoint}/api/${this.#s.version}${t}`;if(!e.ok){let A=e.headers.get("content-type"),i=`YNS REST request failed: ${s} ${o} ${e.status} ${e.statusText}`;if(A?.includes("application/json"))try{let a=await e.json();i=a.error||a.message||i}catch(a){r.error("Failed to parse YNS error response as JSON",a)}else{let a=await e.text();r.error(`YNS API request failed: ${e.status} ${e.statusText}`,i,a)}throw new Error(i)}let n=e.headers.get("content-type");if(!n?.includes("application/json"))throw new Error(`YNS API returned ${n} instead of JSON for ${t}`);return e.json()}async#a(e,t){let s=this.#t.getLogger("#multipartRequest"),r=`${this.#s.endpoint}/api/${this.#s.version}${e}`;s.debug(`Making multipart POST to YNS API: ${r}`);let o=await fetch(r,{method:"POST",headers:{Authorization:`Bearer ${this.#s.token}`},body:t});if(!o.ok){let A=o.headers.get("content-type"),i=`YNS REST request failed: POST ${r} ${o.status} ${o.statusText}`;if(A?.includes("application/json"))try{let a=await o.json();i=a.error||a.message||i}catch(a){s.error("Failed to parse YNS error response as JSON",a)}else{let a=await o.text();s.error(`YNS API request failed: ${o.status} ${o.statusText}`,i,a)}throw new Error(i)}let n=o.headers.get("content-type");if(!n?.includes("application/json"))throw new Error(`YNS API returned ${n} instead of JSON for ${e}`);return o.json()}async meGet(){let e=this.#t.getLogger("meGet");e.debug("Fetching my information");let s=await this.#e("/me");return e.debug("Received my information:",s),s}async socialsGet(){let e=this.#t.getLogger("socialsGet");e.debug("Fetching store social links");let s=await this.#e("/socials");return e.debug("Received store social links:",s),s}async brandBrowse(e={}){let t=new URLSearchParams;e.limit&&t.append("limit",e.limit.toString()),e.offset&&t.append("offset",e.offset.toString()),e.query&&t.append("query",e.query),e.active!==void 0&&t.append("active",e.active.toString()),e.lang&&t.append("lang",e.lang);let r=`/brands${t.size?`?${t}`:""}`;return this.#e(r)}async brandGet(e){let t=`/brands/${e.idOrSlug}`;return this.#e(t)}async brandCreate(e){return this.#e("/brands","POST",e)}async brandUpdate(e,t){let s=`/brands/${e.idOrSlug}`;return this.#e(s,"PATCH",t)}async brandDelete(e){let t=`/brands/${e.idOrSlug}`;return this.#e(t,"DELETE")}async brandAssignProducts(e,t){let s=`/brands/${e.idOrSlug}/products`;return this.#e(s,"POST",t)}async orderRefundsBrowse(e){let t=new URLSearchParams;e.limit&&t.append("limit",e.limit.toString()),e.offset&&t.append("offset",e.offset.toString());let s=t.size?`?${t}`:"",r=`/orders/${e.id}/refunds${s}`;return this.#e(r)}async orderRefundGet(e){let t=`/orders/${e.id}/refunds/${e.refundId}`;return this.#e(t)}async productBatch(e){return this.#e("/products/batch","POST",e)}async cartDelete(e){let t=`/carts/${e.cartId}`;return this.#e(t,"DELETE")}async productBrowse(e){let t=this.#t.getLogger("productBrowse");t.debug("Browsing products with params:",e);let s=new URLSearchParams;e.limit&&s.append("limit",e.limit.toString()),e.offset&&s.append("offset",e.offset.toString()),e.category&&s.append("category",e.category),e.collection&&s.append("collection",e.collection),e.brand&&s.append("brand",e.brand),e.priceMin!==void 0&&s.append("priceMin",e.priceMin.toString()),e.priceMax!==void 0&&s.append("priceMax",e.priceMax.toString()),e.vts&&s.append("vts",e.vts),e.query&&s.append("query",e.query),e.active!==void 0&&s.append("active",e.active.toString()),e.orderBy&&s.append("orderBy",e.orderBy),e.orderDirection&&s.append("orderDirection",e.orderDirection);let o=`/products${s.size?`?${s}`:""}`;t.debug("Constructed pathname:",o);let n=await this.#e(o);return t.debug("Received product browse result:",{meta:n.meta}),n}async productFilters(){return await this.#e("/products/filters")}async productGet(e){let t=`/products/${e.idOrSlug}`,s=await this.#e(t);return s||null}async orderBrowse(e){let t=this.#t.getLogger("orderBrowse");t.debug("Browsing orders with params:",e);let s=new URLSearchParams;e.limit&&s.append("limit",e.limit.toString()),e.offset&&s.append("offset",e.offset.toString());let o=`/orders${s.size?`?${s}`:""}`;t.debug("Constructed pathname:",o);let n=await this.#e(o);return t.debug("Received orders browse result:",{meta:n.meta}),n}async orderGet(e){let t=`/orders/${e.id}`,s=await this.#e(t);return s||null}async cartUpsert(e){return await this.#e("/carts","POST",e)}async cartAddBundle(e){let t={bundleId:e.bundleId,selections:e.selections,...e.cartId?{cartId:e.cartId}:{},...e.currency?{currency:e.currency}:{}};return await this.#e("/carts","POST",t)}async cartRemoveItem(e){let t=`/carts/${e.cartId}/line-items/${e.variantId}`;return this.#e(t,"DELETE")}async cartGet(e){let t=`/carts/${e.cartId}`;return await this.#e(t)}async couponBrowse(e={}){let t=new URLSearchParams;e.limit&&t.append("limit",e.limit.toString()),e.offset&&t.append("offset",e.offset.toString()),e.query&&t.append("query",e.query);let r=`/coupons${t.size?`?${t}`:""}`;return this.#e(r)}async couponGet(e){let t=`/coupons/${e.id}`;return this.#r(t)}async couponCreate(e){return this.#e("/coupons","POST",e)}async couponUpdate(e,t){let s=`/coupons/${e.id}`;return this.#e(s,"PATCH",t)}async couponDelete(e){let t=`/coupons/${e.id}`;return this.#e(t,"DELETE")}async collectionGet(e){let t=`/collections/${e.idOrSlug}`;return await this.#e(t)}async collectionBrowse(e){let t=new URLSearchParams;e.limit&&t.append("limit",e.limit.toString()),e.offset&&t.append("offset",e.offset.toString()),e.query&&t.append("query",e.query),e.active!==void 0&&t.append("active",e.active.toString()),e.group&&t.append("group",e.group);let r=`/collections${t.size?`?${t}`:""}`;return await this.#e(r)}async collectionCreate(e){return this.#e("/collections","POST",e)}async collectionUpdate(e,t){let s=`/collections/${e.idOrSlug}`;return this.#e(s,"PATCH",t)}async collectionDelete(e){let t=`/collections/${e.idOrSlug}`;return this.#e(t,"DELETE")}async collectionImportMemberships(e){let t=new FormData;return t.append("file",e.file),this.#a("/collections/import-memberships",t)}async categoryGet(e){let t=`/categories/${e.idOrSlug}`;return await this.#e(t)}async categoriesBrowse(e){let t=new URLSearchParams;e.limit&&t.append("limit",e.limit.toString()),e.offset&&t.append("offset",e.offset.toString()),e.query&&t.append("query",e.query),e.active!==void 0&&t.append("active",e.active.toString());let r=`/categories${t.size?`?${t}`:""}`;return await this.#e(r)}async postBrowse(e={}){let t=new URLSearchParams;e.limit&&t.append("limit",e.limit.toString()),e.offset&&t.append("offset",e.offset.toString()),e.query&&t.append("query",e.query),e.active!==void 0&&t.append("active",e.active.toString()),e.tag&&t.append("tag",e.tag),e.categoryId&&t.append("categoryId",e.categoryId);let r=`/posts${t.size?`?${t}`:""}`;return this.#e(r)}async postGet(e){let t=`/posts/${e.idOrSlug}`;return this.#e(t)}async postCreate(e){return this.#e("/posts","POST",e)}async postUpdate(e,t){let s=`/posts/${e.idOrSlug}`;return this.#e(s,"PATCH",t)}async postDelete(e){let t=`/posts/${e.idOrSlug}`;return this.#e(t,"DELETE")}async postCommentsBrowse(e,t={}){let s=new URLSearchParams;t.limit&&s.append("limit",t.limit.toString()),t.offset&&s.append("offset",t.offset.toString());let r=s.size?`?${s}`:"",o=`/posts/${e.idOrSlug}/comments${r}`;return this.#e(o)}async postCommentCreate(e,t){let s=`/posts/${e.idOrSlug}/comments`;return this.#e(s,"POST",t)}async blogCategoryBrowse(e={}){let t=new URLSearchParams;e.limit&&t.append("limit",e.limit.toString()),e.offset&&t.append("offset",e.offset.toString()),e.query&&t.append("query",e.query),e.active!==void 0&&t.append("active",e.active.toString());let r=`/blog-categories${t.size?`?${t}`:""}`;return this.#e(r)}async blogCategoryGet(e){let t=`/blog-categories/${e.idOrSlug}`;return this.#e(t)}async blogCategoryCreate(e){return this.#e("/blog-categories","POST",e)}async blogCategoryUpdate(e,t){let s=`/blog-categories/${e.idOrSlug}`;return this.#e(s,"PATCH",t)}async blogCategoryDelete(e){let t=`/blog-categories/${e.idOrSlug}`;return this.#e(t,"DELETE")}async customerBrowse(e={}){let t=new URLSearchParams;e.limit&&t.append("limit",e.limit.toString()),e.offset&&t.append("offset",e.offset.toString()),e.search&&t.append("search",e.search);let r=`/customers${t.size?`?${t}`:""}`;return this.#e(r)}async customerGet(e){let t=`/customers/${e.id}`;return this.#e(t)}async customerUpdate(e,t){let s=`/customers/${e.id}`;return this.#e(s,"PATCH",t)}async customerAddressCreate(e,t){let s=`/customers/${e.id}/addresses`;return this.#e(s,"POST",t)}async customerAddressDelete(e){let t=`/customers/${e.customerId}/addresses/${e.addressId}`;await this.#e(t,"DELETE")}async customerOrdersBrowse(e,t={}){let s=new URLSearchParams;t.limit&&s.append("limit",t.limit.toString()),t.offset&&s.append("offset",t.offset.toString());let r=s.size?`?${s}`:"",o=`/customers/${e.id}/orders${r}`;return this.#e(o)}async inventoryBrowse(e={}){let t=new URLSearchParams;e.limit&&t.append("limit",e.limit.toString()),e.cursor&&t.append("cursor",e.cursor),e.lowStock!==void 0&&t.append("lowStock",e.lowStock.toString());let r=`/inventory${t.size?`?${t}`:""}`;return this.#e(r)}async inventoryAdjust(e,t){let s=`/inventory/${encodeURIComponent(e)}/adjust`;return this.#e(s,"POST",t)}async variantGet(e){let t=`/variants/${e.idOrSku}`;return this.#e(t)}async variantUpdate(e,t){let s=`/variants/${e.idOrSku}`;return this.#e(s,"PATCH",t)}async variantDelete(e){let t=`/variants/${e.idOrSku}`;await this.#e(t,"DELETE")}async variantCreate(e,t){let s=`/products/${e}/variants`;return this.#e(s,"POST",t)}async subscriberCreate(e){return this.#e("/subscribers","POST",e)}async subscriberDelete(e){let t=`/subscribers?email=${encodeURIComponent(e)}`;return this.#e(t,"DELETE")}async contactMessageCreate(e){return this.#e("/contact-messages","POST",e)}async productCreate(e){return this.#e("/products","POST",e)}async productUpdate(e,t){let s=`/products/${e.idOrSlug}`;return this.#e(s,"PATCH",t)}async productDelete(e){let t=`/products/${e.idOrSlug}`;return this.#e(t,"DELETE")}async productReviewsBrowse(e,t={}){let s=new URLSearchParams;t.limit&&s.append("limit",t.limit.toString()),t.offset&&s.append("offset",t.offset.toString());let r=s.size?`?${s}`:"",o=`/products/${e.idOrSlug}/reviews${r}`;return this.#e(o)}async productReviewCreate(e,t){let s=`/products/${e.idOrSlug}/reviews`;return this.#e(s,"POST",t)}async eventBrowse(e={}){let t=this.#t.getLogger("eventBrowse"),s=new URLSearchParams;e.offset!==void 0&&s.append("offset",e.offset.toString()),e.limit!==void 0&&s.append("limit",e.limit.toString());let o=`/events${s.size?`?${s}`:""}`;return t.debug("Browsing events:",o),this.#e(o)}async eventGet(e){let t=`/events/${e.idOrSlug}`;return this.#e(t)}async eventCreate(e){return this.#e("/events","POST",e)}async eventUpdate(e,t){let s=`/events/${e.idOrSlug}`;return this.#e(s,"PATCH",t)}async eventAttendeesBrowse(e){let t=`/events/${e.idOrSlug}/attendees`;return this.#e(t)}async ticketsGet(e){let t=this.#t.getLogger("ticketsGet"),s=new URLSearchParams({email:e.email}),r=`/tickets/${encodeURIComponent(e.code)}?${s}`;return t.debug("Fetching ticket bundle:",r),this.#r(r)}async ticketsUpdate(e,t){let s=`/tickets/${encodeURIComponent(e.code)}`;return this.#e(s,"PATCH",t)}async ticketAttendeeGet(e){let t=`/tickets/attendee/${encodeURIComponent(e.token)}`;return this.#r(t)}async categoryCreate(e){return this.#e("/categories","POST",e)}async categoryUpdate(e,t){let s=`/categories/${e.idOrSlug}`;return this.#e(s,"PATCH",t)}async categoryDelete(e){let t=`/categories/${e.idOrSlug}`;return this.#e(t,"DELETE")}async orderUpdate(e,t){let s=`/orders/${e.id}`;return this.#e(s,"PATCH",t)}async legalPageBrowse(e={}){return this.request("/legal-pages",{query:e})}async legalPageGet(e,t={}){let s=e.startsWith("/")?e.slice(1):e,r=`/legal-pages/${encodeURIComponent(s)}`;return this.request(r,{query:t})}async legalPageCreate(e,t={}){return this.request("/legal-pages",{method:"POST",body:e,query:t})}async legalPageUpdate(e,t,s={}){let r=e.startsWith("/")?e.slice(1):e,o=`/legal-pages/${encodeURIComponent(r)}`;return this.request(o,{method:"PATCH",body:t,query:s})}async search(e){return this.request("/search",{query:e})}async instaviewImagesBrowse(e,t={}){let s=new URLSearchParams;t.limit&&s.append("limit",t.limit.toString()),t.cursor&&s.append("cursor",t.cursor);let r=s.size?`?${s}`:"",o=`/instaview/accounts/${e.handle}/images${r}`;return this.#e(o)}async request(e,t){let s=t?.query?Object.entries(t.query).filter(o=>{let[,n]=o;return n!=null}):[],r=s.length>0?`?${new URLSearchParams(s.map(([o,n])=>[o,String(n)]))}`:"";return this.#e(`${e}${r}`,t?.method??"GET",t?.body)}};function T(c={}){return new l(c)}export{T as Commerce,l as YNSProvider};
|
|
1
|
+
import"./chunk-PNKB6P4V.js";var p=process.env.YNS_API_KEY,m={YNS_API_KEY:p};var P={DEBUG:0,LOG:1,WARN:2,ERROR:3},g=process.env.NEXT_PUBLIC_LOG_LEVEL||"LOG",u=P[g],d="\x1B[0m",B="\x1B[34m",C="\x1B[32m",R="\x1B[33m",h="\x1B[31m",f="\u23F1\uFE0F",w="\u{1F41B}",S="\u2714\uFE0F",G="\u26A0\uFE0F",$="\u274C",y=`${f} `,v=`${B}${w}${d} `,U=`${C}${S}${d} `,E=`${R}${G}${d} `,O=`${h}${$}${d} `,I=c=>{let e=c?`[${c}] `:"";return{getLogger(t){return I([c,t].filter(Boolean).join(" > "))},time(t){u>P.DEBUG||console.time([y,e,t].filter(Boolean).join(" "))},timeEnd(t){u>P.DEBUG||console.timeEnd([y,e,t].filter(Boolean).join(" "))},debug(...t){u>P.DEBUG||console.log(...[v,e,...t].filter(Boolean))},log(...t){u>P.LOG||console.log(...[U,e,...t].filter(Boolean))},dir(t,s){u>P.LOG||console.dir(t,s)},warn(...t){u>P.WARN||console.warn(...[E,e,...t].filter(Boolean))},error(...t){u>P.ERROR||console.error(...[O,e,...t].filter(Boolean))}}},L=I();var l=class{#s;#t=I("YNSProvider");constructor(e={}){let t=e.token??m.YNS_API_KEY,s=m.YNS_API_KEY?.startsWith("sk-s-");if(!t)throw new Error("YNS API key is required. Set YNS_API_KEY environment variable or pass token in config.");let r=e.endpoint??(s?"https://yns.cx":"https://yns.store");this.#s={version:"v1",...e,token:t,endpoint:r},this.#t.debug("YNSProvider initialized",{endpoint:r,token:e.token?"from config":"from env"})}async#e(e,t="GET",s){let r=await this.#o(e,t,s);return this.#a(r,e,t)}async#r(e){let t=await this.#o(e,"GET");return t.status===404?null:this.#a(t,e,"GET")}async#o(e,t,s){let r=this.#t.getLogger("#restRequest"),o=`${this.#s.endpoint}/api/${this.#s.version}${e}`;return r.debug(`Making ${t} request to YNS API: ${o}`),fetch(o,{method:t,headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.#s.token}`},body:s?JSON.stringify(s):void 0})}async#a(e,t,s){let r=this.#t.getLogger("#restRequest"),o=`${this.#s.endpoint}/api/${this.#s.version}${t}`;if(!e.ok){let A=e.headers.get("content-type"),i=`YNS REST request failed: ${s} ${o} ${e.status} ${e.statusText}`;if(A?.includes("application/json"))try{let n=await e.json();i=n.error||n.message||i}catch(n){r.error("Failed to parse YNS error response as JSON",n)}else{let n=await e.text();r.error(`YNS API request failed: ${e.status} ${e.statusText}`,i,n)}throw new Error(i)}let a=e.headers.get("content-type");if(!a?.includes("application/json"))throw new Error(`YNS API returned ${a} instead of JSON for ${t}`);return e.json()}async#n(e,t){let s=this.#t.getLogger("#multipartRequest"),r=`${this.#s.endpoint}/api/${this.#s.version}${e}`;s.debug(`Making multipart POST to YNS API: ${r}`);let o=await fetch(r,{method:"POST",headers:{Authorization:`Bearer ${this.#s.token}`},body:t});if(!o.ok){let A=o.headers.get("content-type"),i=`YNS REST request failed: POST ${r} ${o.status} ${o.statusText}`;if(A?.includes("application/json"))try{let n=await o.json();i=n.error||n.message||i}catch(n){s.error("Failed to parse YNS error response as JSON",n)}else{let n=await o.text();s.error(`YNS API request failed: ${o.status} ${o.statusText}`,i,n)}throw new Error(i)}let a=o.headers.get("content-type");if(!a?.includes("application/json"))throw new Error(`YNS API returned ${a} instead of JSON for ${e}`);return o.json()}async meGet(){let e=this.#t.getLogger("meGet");e.debug("Fetching my information");let s=await this.#e("/me");return e.debug("Received my information:",s),s}async socialsGet(){let e=this.#t.getLogger("socialsGet");e.debug("Fetching store social links");let s=await this.#e("/socials");return e.debug("Received store social links:",s),s}async brandBrowse(e={}){let t=new URLSearchParams;e.limit&&t.append("limit",e.limit.toString()),e.offset&&t.append("offset",e.offset.toString()),e.query&&t.append("query",e.query),e.active!==void 0&&t.append("active",e.active.toString()),e.lang&&t.append("lang",e.lang);let r=`/brands${t.size?`?${t}`:""}`;return this.#e(r)}async brandGet(e){let t=`/brands/${e.idOrSlug}`;return this.#e(t)}async brandCreate(e){return this.#e("/brands","POST",e)}async brandUpdate(e,t){let s=`/brands/${e.idOrSlug}`;return this.#e(s,"PATCH",t)}async brandDelete(e){let t=`/brands/${e.idOrSlug}`;return this.#e(t,"DELETE")}async brandAssignProducts(e,t){let s=`/brands/${e.idOrSlug}/products`;return this.#e(s,"POST",t)}async orderRefundsBrowse(e){let t=new URLSearchParams;e.limit&&t.append("limit",e.limit.toString()),e.offset&&t.append("offset",e.offset.toString());let s=t.size?`?${t}`:"",r=`/orders/${e.id}/refunds${s}`;return this.#e(r)}async orderRefundGet(e){let t=`/orders/${e.id}/refunds/${e.refundId}`;return this.#e(t)}async productBatch(e){return this.#e("/products/batch","POST",e)}async cartDelete(e){let t=`/carts/${e.cartId}`;return this.#e(t,"DELETE")}async productBrowse(e){let t=this.#t.getLogger("productBrowse");t.debug("Browsing products with params:",e);let s=new URLSearchParams;e.limit&&s.append("limit",e.limit.toString()),e.offset&&s.append("offset",e.offset.toString()),e.category&&s.append("category",e.category),e.collection&&s.append("collection",e.collection),e.brand&&s.append("brand",e.brand),e.priceMin!==void 0&&s.append("priceMin",e.priceMin.toString()),e.priceMax!==void 0&&s.append("priceMax",e.priceMax.toString()),e.vts&&s.append("vts",e.vts),e.query&&s.append("query",e.query),e.active!==void 0&&s.append("active",e.active.toString()),e.orderBy&&s.append("orderBy",e.orderBy),e.orderDirection&&s.append("orderDirection",e.orderDirection);let o=`/products${s.size?`?${s}`:""}`;t.debug("Constructed pathname:",o);let a=await this.#e(o);return t.debug("Received product browse result:",{meta:a.meta}),a}async productFilters(){return await this.#e("/products/filters")}async productGet(e){let t=`/products/${e.idOrSlug}`,s=await this.#e(t);return s||null}async orderBrowse(e){let t=this.#t.getLogger("orderBrowse");t.debug("Browsing orders with params:",e);let s=new URLSearchParams;e.limit&&s.append("limit",e.limit.toString()),e.offset&&s.append("offset",e.offset.toString());let o=`/orders${s.size?`?${s}`:""}`;t.debug("Constructed pathname:",o);let a=await this.#e(o);return t.debug("Received orders browse result:",{meta:a.meta}),a}async orderGet(e){let t=`/orders/${e.id}`,s=await this.#e(t);return s||null}async cartUpsert(e){return await this.#e("/carts","POST",e)}async cartAddBundle(e){let t={bundleId:e.bundleId,selections:e.selections,...e.cartId?{cartId:e.cartId}:{},...e.currency?{currency:e.currency}:{}};return await this.#e("/carts","POST",t)}async cartRemoveItem(e){let t=`/carts/${e.cartId}/line-items/${e.variantId}`;return this.#e(t,"DELETE")}async cartGet(e){let t=`/carts/${e.cartId}`;return await this.#e(t)}async couponBrowse(e={}){let t=new URLSearchParams;e.limit&&t.append("limit",e.limit.toString()),e.offset&&t.append("offset",e.offset.toString()),e.query&&t.append("query",e.query);let r=`/coupons${t.size?`?${t}`:""}`;return this.#e(r)}async couponGet(e){let t=`/coupons/${e.idOrCode}`;return this.#r(t)}async couponCreate(e){return this.#e("/coupons","POST",e)}async couponUpdate(e,t){let s=`/coupons/${e.idOrCode}`;return this.#e(s,"PATCH",t)}async couponDelete(e){let t=`/coupons/${e.idOrCode}`;return this.#e(t,"DELETE")}async supportCaseBrowse(e={}){let t=new URLSearchParams;e.limit&&t.append("limit",e.limit.toString()),e.offset&&t.append("offset",e.offset.toString()),e.query&&t.append("query",e.query),e.status&&t.append("status",e.status),e.severity&&t.append("severity",e.severity);let r=`/support-cases${t.size?`?${t}`:""}`;return this.#e(r)}async supportCaseGet(e){let t=`/support-cases/${e.idOrNumber}`;return this.#r(t)}async supportCaseCreate(e){return this.#e("/support-cases","POST",e)}async supportCaseUpdate(e,t){let s=`/support-cases/${e.idOrNumber}`;return this.#e(s,"PATCH",t)}async supportCaseReply(e,t){let s=`/support-cases/${e.idOrNumber}/messages`;return this.#e(s,"POST",t)}async collectionGet(e){let t=`/collections/${e.idOrSlug}`;return await this.#e(t)}async collectionBrowse(e){let t=new URLSearchParams;e.limit&&t.append("limit",e.limit.toString()),e.offset&&t.append("offset",e.offset.toString()),e.query&&t.append("query",e.query),e.active!==void 0&&t.append("active",e.active.toString()),e.group&&t.append("group",e.group);let r=`/collections${t.size?`?${t}`:""}`;return await this.#e(r)}async collectionCreate(e){return this.#e("/collections","POST",e)}async collectionUpdate(e,t){let s=`/collections/${e.idOrSlug}`;return this.#e(s,"PATCH",t)}async collectionDelete(e){let t=`/collections/${e.idOrSlug}`;return this.#e(t,"DELETE")}async collectionImportMemberships(e){let t=new FormData;return t.append("file",e.file),this.#n("/collections/import-memberships",t)}async categoryGet(e){let t=`/categories/${e.idOrSlug}`;return await this.#e(t)}async categoriesBrowse(e){let t=new URLSearchParams;e.limit&&t.append("limit",e.limit.toString()),e.offset&&t.append("offset",e.offset.toString()),e.query&&t.append("query",e.query),e.active!==void 0&&t.append("active",e.active.toString());let r=`/categories${t.size?`?${t}`:""}`;return await this.#e(r)}async postBrowse(e={}){let t=new URLSearchParams;e.limit&&t.append("limit",e.limit.toString()),e.offset&&t.append("offset",e.offset.toString()),e.query&&t.append("query",e.query),e.active!==void 0&&t.append("active",e.active.toString()),e.tag&&t.append("tag",e.tag),e.categoryId&&t.append("categoryId",e.categoryId);let r=`/posts${t.size?`?${t}`:""}`;return this.#e(r)}async postGet(e){let t=`/posts/${e.idOrSlug}`;return this.#e(t)}async postCreate(e){return this.#e("/posts","POST",e)}async postUpdate(e,t){let s=`/posts/${e.idOrSlug}`;return this.#e(s,"PATCH",t)}async postDelete(e){let t=`/posts/${e.idOrSlug}`;return this.#e(t,"DELETE")}async postCommentsBrowse(e,t={}){let s=new URLSearchParams;t.limit&&s.append("limit",t.limit.toString()),t.offset&&s.append("offset",t.offset.toString());let r=s.size?`?${s}`:"",o=`/posts/${e.idOrSlug}/comments${r}`;return this.#e(o)}async postCommentCreate(e,t){let s=`/posts/${e.idOrSlug}/comments`;return this.#e(s,"POST",t)}async blogCategoryBrowse(e={}){let t=new URLSearchParams;e.limit&&t.append("limit",e.limit.toString()),e.offset&&t.append("offset",e.offset.toString()),e.query&&t.append("query",e.query),e.active!==void 0&&t.append("active",e.active.toString());let r=`/blog-categories${t.size?`?${t}`:""}`;return this.#e(r)}async blogCategoryGet(e){let t=`/blog-categories/${e.idOrSlug}`;return this.#e(t)}async blogCategoryCreate(e){return this.#e("/blog-categories","POST",e)}async blogCategoryUpdate(e,t){let s=`/blog-categories/${e.idOrSlug}`;return this.#e(s,"PATCH",t)}async blogCategoryDelete(e){let t=`/blog-categories/${e.idOrSlug}`;return this.#e(t,"DELETE")}async customerBrowse(e={}){let t=new URLSearchParams;e.limit&&t.append("limit",e.limit.toString()),e.offset&&t.append("offset",e.offset.toString()),e.search&&t.append("search",e.search);let r=`/customers${t.size?`?${t}`:""}`;return this.#e(r)}async customerGet(e){let t=`/customers/${e.id}`;return this.#e(t)}async customerUpdate(e,t){let s=`/customers/${e.id}`;return this.#e(s,"PATCH",t)}async customerAddressCreate(e,t){let s=`/customers/${e.id}/addresses`;return this.#e(s,"POST",t)}async customerAddressDelete(e){let t=`/customers/${e.customerId}/addresses/${e.addressId}`;await this.#e(t,"DELETE")}async customerOrdersBrowse(e,t={}){let s=new URLSearchParams;t.limit&&s.append("limit",t.limit.toString()),t.offset&&s.append("offset",t.offset.toString());let r=s.size?`?${s}`:"",o=`/customers/${e.id}/orders${r}`;return this.#e(o)}async inventoryBrowse(e={}){let t=new URLSearchParams;e.limit&&t.append("limit",e.limit.toString()),e.cursor&&t.append("cursor",e.cursor),e.lowStock!==void 0&&t.append("lowStock",e.lowStock.toString());let r=`/inventory${t.size?`?${t}`:""}`;return this.#e(r)}async inventoryAdjust(e,t){let s=`/inventory/${encodeURIComponent(e)}/adjust`;return this.#e(s,"POST",t)}async variantGet(e){let t=`/variants/${e.idOrSku}`;return this.#e(t)}async variantUpdate(e,t){let s=`/variants/${e.idOrSku}`;return this.#e(s,"PATCH",t)}async variantDelete(e){let t=`/variants/${e.idOrSku}`;await this.#e(t,"DELETE")}async variantCreate(e,t){let s=`/products/${e}/variants`;return this.#e(s,"POST",t)}async subscriberCreate(e){return this.#e("/subscribers","POST",e)}async subscriberDelete(e){let t=`/subscribers?email=${encodeURIComponent(e)}`;return this.#e(t,"DELETE")}async contactMessageCreate(e){return this.#e("/contact-messages","POST",e)}async productCreate(e){return this.#e("/products","POST",e)}async productUpdate(e,t){let s=`/products/${e.idOrSlug}`;return this.#e(s,"PATCH",t)}async productDelete(e){let t=`/products/${e.idOrSlug}`;return this.#e(t,"DELETE")}async productReviewsBrowse(e,t={}){let s=new URLSearchParams;t.limit&&s.append("limit",t.limit.toString()),t.offset&&s.append("offset",t.offset.toString());let r=s.size?`?${s}`:"",o=`/products/${e.idOrSlug}/reviews${r}`;return this.#e(o)}async productReviewCreate(e,t){let s=`/products/${e.idOrSlug}/reviews`;return this.#e(s,"POST",t)}async eventBrowse(e={}){let t=this.#t.getLogger("eventBrowse"),s=new URLSearchParams;e.offset!==void 0&&s.append("offset",e.offset.toString()),e.limit!==void 0&&s.append("limit",e.limit.toString());let o=`/events${s.size?`?${s}`:""}`;return t.debug("Browsing events:",o),this.#e(o)}async eventGet(e){let t=`/events/${e.idOrSlug}`;return this.#e(t)}async eventCreate(e){return this.#e("/events","POST",e)}async eventUpdate(e,t){let s=`/events/${e.idOrSlug}`;return this.#e(s,"PATCH",t)}async eventAttendeesBrowse(e){let t=`/events/${e.idOrSlug}/attendees`;return this.#e(t)}async ticketsGet(e){let t=this.#t.getLogger("ticketsGet"),s=new URLSearchParams({email:e.email}),r=`/tickets/${encodeURIComponent(e.code)}?${s}`;return t.debug("Fetching ticket bundle:",r),this.#r(r)}async ticketsUpdate(e,t){let s=`/tickets/${encodeURIComponent(e.code)}`;return this.#e(s,"PATCH",t)}async ticketAttendeeGet(e){let t=`/tickets/attendee/${encodeURIComponent(e.token)}`;return this.#r(t)}async categoryCreate(e){return this.#e("/categories","POST",e)}async categoryUpdate(e,t){let s=`/categories/${e.idOrSlug}`;return this.#e(s,"PATCH",t)}async categoryDelete(e){let t=`/categories/${e.idOrSlug}`;return this.#e(t,"DELETE")}async orderUpdate(e,t){let s=`/orders/${e.id}`;return this.#e(s,"PATCH",t)}async legalPageBrowse(e={}){return this.request("/legal-pages",{query:e})}async legalPageGet(e,t={}){let s=e.startsWith("/")?e.slice(1):e,r=`/legal-pages/${encodeURIComponent(s)}`;return this.request(r,{query:t})}async legalPageCreate(e,t={}){return this.request("/legal-pages",{method:"POST",body:e,query:t})}async legalPageUpdate(e,t,s={}){let r=e.startsWith("/")?e.slice(1):e,o=`/legal-pages/${encodeURIComponent(r)}`;return this.request(o,{method:"PATCH",body:t,query:s})}async search(e){return this.request("/search",{query:e})}async instaviewImagesBrowse(e,t={}){let s=new URLSearchParams;t.limit&&s.append("limit",t.limit.toString()),t.cursor&&s.append("cursor",t.cursor);let r=s.size?`?${s}`:"",o=`/instaview/accounts/${e.handle}/images${r}`;return this.#e(o)}async request(e,t){let s=t?.query?Object.entries(t.query).filter(o=>{let[,a]=o;return a!=null}):[],r=s.length>0?`?${new URLSearchParams(s.map(([o,a])=>[o,String(a)]))}`:"";return this.#e(`${e}${r}`,t?.method??"GET",t?.body)}};function T(c={}){return new l(c)}export{T as Commerce,l as YNSProvider};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/env.ts","../src/logger.ts","../src/providers/yns.ts","../src/commerce.ts"],"sourcesContent":["const YNS_API_KEY = process.env.YNS_API_KEY;\n\nexport const env = {\n\tYNS_API_KEY,\n};\n","import type { InspectOptions } from \"node:util\";\n\ntype LogParms = [message: unknown, ...optionalParams: unknown[]];\n\n/**\n * Vercel only supports 3 levels of logging. We're adding additional DEBUG level.\n * https://vercel.com/docs/observability/runtime-logs#level\n *\n * ERROR - Fatal for a particular request. Should be fixed sooner than later.\n *\n * WARN - A note on something that should probably be looked at eventually.\n *\n * LOG - Detail on regular operation.\n *\n * DEBUG - Debug only info as well as time and timeEnd functions.\n */\nconst LogLevel = {\n\tDEBUG: 0,\n\tLOG: 1,\n\tWARN: 2,\n\tERROR: 3,\n} as const;\ntype LogLevel = keyof typeof LogLevel;\n\nconst strLogLevel = (process.env.NEXT_PUBLIC_LOG_LEVEL || \"LOG\") as LogLevel;\nconst valueLogLevel = LogLevel[strLogLevel];\n\nconst RESET = \"\\x1b[0m\";\nconst BLUE = \"\\x1b[34m\";\nconst GREEN = \"\\x1b[32m\";\nconst YELLOW = \"\\x1b[33m\";\nconst RED = \"\\x1b[31m\";\n\nconst TIME = `⏱️`;\nconst DEBUG = `🐛`;\nconst OK = `✔️`;\nconst WARN = `⚠️`;\nconst ERROR = `❌`;\n\nconst PREFIX_TIME = `${TIME} `;\nconst PREFIX_DEBUG = `${BLUE}${DEBUG}${RESET} `;\nconst PREFIX_OK = `${GREEN}${OK}${RESET} `;\nconst PREFIX_WARN = `${YELLOW}${WARN}${RESET} `;\nconst PREFIX_ERROR = `${RED}${ERROR}${RESET} `;\n\nexport const getLogger = (groupLabel?: string) => {\n\tconst PREFIX = groupLabel ? `[${groupLabel}] ` : \"\";\n\treturn {\n\t\tgetLogger(subGroupLabel: string) {\n\t\t\treturn getLogger([groupLabel, subGroupLabel].filter(Boolean).join(\" > \"));\n\t\t},\n\t\ttime(label: string) {\n\t\t\tif (valueLogLevel > LogLevel.DEBUG) return;\n\t\t\tconsole.time([PREFIX_TIME, PREFIX, label].filter(Boolean).join(\" \"));\n\t\t},\n\t\ttimeEnd(label: string) {\n\t\t\tif (valueLogLevel > LogLevel.DEBUG) return;\n\t\t\tconsole.timeEnd([PREFIX_TIME, PREFIX, label].filter(Boolean).join(\" \"));\n\t\t},\n\t\tdebug(...args: LogParms) {\n\t\t\tif (valueLogLevel > LogLevel.DEBUG) return;\n\t\t\tconsole.log(...[PREFIX_DEBUG, PREFIX, ...args].filter(Boolean));\n\t\t},\n\t\tlog(...args: LogParms) {\n\t\t\tif (valueLogLevel > LogLevel.LOG) return;\n\t\t\tconsole.log(...[PREFIX_OK, PREFIX, ...args].filter(Boolean));\n\t\t},\n\t\tdir(item?: unknown, options?: InspectOptions) {\n\t\t\tif (valueLogLevel > LogLevel.LOG) return;\n\t\t\tconsole.dir(item, options);\n\t\t},\n\t\twarn(...args: LogParms) {\n\t\t\tif (valueLogLevel > LogLevel.WARN) return;\n\t\t\tconsole.warn(...[PREFIX_WARN, PREFIX, ...args].filter(Boolean));\n\t\t},\n\t\terror(...args: LogParms) {\n\t\t\tif (valueLogLevel > LogLevel.ERROR) return;\n\t\t\tconsole.error(...[PREFIX_ERROR, PREFIX, ...args].filter(Boolean));\n\t\t},\n\t};\n};\n\nexport const logger = getLogger();\n","import type {\n\tAPIBlogCategoriesBrowseQueryParams,\n\tAPIBlogCategoriesBrowseResult,\n\tAPIBlogCategoryCreateBody,\n\tAPIBlogCategoryCreateResult,\n\tAPIBlogCategoryDeleteResult,\n\tAPIBlogCategoryGetByIdParams,\n\tAPIBlogCategoryGetByIdResult,\n\tAPIBlogCategoryUpdateBody,\n\tAPIBlogCategoryUpdateResult,\n\tAPIBrandAssignProductsBody,\n\tAPIBrandAssignProductsResult,\n\tAPIBrandCreateBody,\n\tAPIBrandCreateResult,\n\tAPIBrandDeleteResult,\n\tAPIBrandGetByIdParams,\n\tAPIBrandGetByIdResult,\n\tAPIBrandsBrowseQueryParams,\n\tAPIBrandsBrowseResult,\n\tAPIBrandUpdateBody,\n\tAPIBrandUpdateResult,\n\tAPICartCreateBody,\n\tAPICartCreateResult,\n\tAPICartDeleteResult,\n\tAPICartGetResult,\n\tAPICategoriesBrowseQueryParams,\n\tAPICategoriesBrowseResult,\n\tAPICategoryCreateBody,\n\tAPICategoryCreateResult,\n\tAPICategoryDeleteResult,\n\tAPICategoryGetByIdParams,\n\tAPICategoryGetByIdResult,\n\tAPICategoryUpdateBody,\n\tAPICategoryUpdateResult,\n\tAPICollectionCreateBody,\n\tAPICollectionCreateResult,\n\tAPICollectionDeleteResult,\n\tAPICollectionGetByIdParams,\n\tAPICollectionGetByIdResult,\n\tAPICollectionsBrowseQueryParams,\n\tAPICollectionsBrowseResult,\n\tAPICollectionUpdateBody,\n\tAPICollectionUpdateResult,\n\tAPIContactMessageCreateBody,\n\tAPIContactMessageCreateResult,\n\tAPICouponCreateBody,\n\tAPICouponCreateResult,\n\tAPICouponDeleteResult,\n\tAPICouponGetByIdParams,\n\tAPICouponGetByIdResult,\n\tAPICouponsBrowseQueryParams,\n\tAPICouponsBrowseResult,\n\tAPICouponUpdateBody,\n\tAPICouponUpdateResult,\n\tAPICustomerAddressCreateBody,\n\tAPICustomerAddressCreateResult,\n\tAPICustomerGetByIdParams,\n\tAPICustomerGetByIdResult,\n\tAPICustomerOrdersBrowseQueryParams,\n\tAPICustomerOrdersBrowseResult,\n\tAPICustomersBrowseQueryParams,\n\tAPICustomersBrowseResult,\n\tAPICustomerUpdateBody,\n\tAPICustomerUpdateResult,\n\tAPIEventAttendeesBrowseResult,\n\tAPIEventCreateBody,\n\tAPIEventCreateResult,\n\tAPIEventGetByIdParams,\n\tAPIEventGetByIdResult,\n\tAPIEventsBrowseQueryParams,\n\tAPIEventsBrowseResult,\n\tAPIEventUpdateBody,\n\tAPIEventUpdateResult,\n\tAPIInstaviewImagesBrowseParams,\n\tAPIInstaviewImagesBrowseQueryParams,\n\tAPIInstaviewImagesBrowseResult,\n\tAPIInventoryAdjustBody,\n\tAPIInventoryAdjustResult,\n\tAPIInventoryBrowseQueryParams,\n\tAPIInventoryBrowseResult,\n\tAPILegalPageCreateBody,\n\tAPILegalPageCreateQueryParams,\n\tAPILegalPageCreateResult,\n\tAPILegalPageGetByPathQueryParams,\n\tAPILegalPageGetByPathResult,\n\tAPILegalPagesBrowseQueryParams,\n\tAPILegalPagesBrowseResult,\n\tAPILegalPageUpdateBody,\n\tAPILegalPageUpdateQueryParams,\n\tAPILegalPageUpdateResult,\n\tAPIMeGetResult,\n\tAPIOrderGetByIdParams,\n\tAPIOrderGetByIdResult,\n\tAPIOrderRefundGetParams,\n\tAPIOrderRefundGetResult,\n\tAPIOrderRefundsBrowseQueryParams,\n\tAPIOrderRefundsBrowseResult,\n\tAPIOrderRefundsParams,\n\tAPIOrdersBrowseQueryParams,\n\tAPIOrdersBrowseResult,\n\tAPIOrderUpdateBody,\n\tAPIOrderUpdateResult,\n\tAPIPostCommentCreateBody,\n\tAPIPostCommentCreateResult,\n\tAPIPostCommentsBrowseQueryParams,\n\tAPIPostCommentsBrowseResult,\n\tAPIPostCreateBody,\n\tAPIPostCreateResult,\n\tAPIPostDeleteResult,\n\tAPIPostGetByIdParams,\n\tAPIPostGetByIdResult,\n\tAPIPostsBrowseQueryParams,\n\tAPIPostsBrowseResult,\n\tAPIPostUpdateBody,\n\tAPIPostUpdateResult,\n\tAPIProductBatchBody,\n\tAPIProductBatchResult,\n\tAPIProductCreateBody,\n\tAPIProductCreateResult,\n\tAPIProductDeleteResult,\n\tAPIProductFiltersResult,\n\tAPIProductGetByIdParams,\n\tAPIProductGetByIdResult,\n\tAPIProductReviewCreateBody,\n\tAPIProductReviewCreateResult,\n\tAPIProductReviewsBrowseQueryParams,\n\tAPIProductReviewsBrowseResult,\n\tAPIProductsBrowseQueryParams,\n\tAPIProductsBrowseResult,\n\tAPIProductUpdateBody,\n\tAPIProductUpdateResult,\n\tAPISearchQueryParams,\n\tAPISearchResult,\n\tAPISocialsGetResult,\n\tAPISubscriberCreateBody,\n\tAPISubscriberCreateResult,\n\tAPISubscriberDeleteResult,\n\tAPITicketAttendeeGetResult,\n\tAPITicketsGetResult,\n\tAPITicketsUpdateBody,\n\tAPITicketsUpdateResult,\n\tAPIVariantCreateBody,\n\tAPIVariantCreateResult,\n\tAPIVariantGetByIdParams,\n\tAPIVariantGetByIdResult,\n\tAPIVariantUpdateBody,\n\tAPIVariantUpdateResult,\n} from \"../api-types\";\nimport { env } from \"../env\";\nimport { getLogger } from \"../logger\";\nimport type { CommerceConfig } from \"../types\";\n\nexport type APICollectionImportMembershipsBody = { file: File | Blob };\n\nexport type APICollectionImportMembershipsResult = {\n\tok: true;\n\tprocessed: number;\n\tinserted: number;\n\tskipped_existing: number;\n\terrors: Array<{\n\t\trow: number;\n\t\tcollection_slug?: string;\n\t\tproduct_slug?: string;\n\t\treason: string;\n\t}>;\n};\n\nexport class YNSProvider {\n\t#config: CommerceConfig;\n\t#logger = getLogger(\"YNSProvider\");\n\n\tconstructor(config: CommerceConfig = {}) {\n\t\tconst token = config.token ?? env.YNS_API_KEY;\n\t\tconst isStaging = env.YNS_API_KEY?.startsWith(\"sk-s-\");\n\n\t\tif (!token) {\n\t\t\tthrow new Error(\n\t\t\t\t\"YNS API key is required. Set YNS_API_KEY environment variable or pass token in config.\",\n\t\t\t);\n\t\t}\n\t\tconst endpoint = config.endpoint ?? (isStaging ? \"https://yns.cx\" : \"https://yns.store\");\n\n\t\tthis.#config = { version: \"v1\", ...config, token, endpoint };\n\n\t\tthis.#logger.debug(\"YNSProvider initialized\", {\n\t\t\tendpoint,\n\t\t\ttoken: config.token ? `from config` : \"from env\",\n\t\t});\n\t}\n\n\tasync #restRequest<T>(\n\t\tpathname: `/${string}`,\n\t\tmethod: \"GET\" | \"POST\" | \"PATCH\" | \"DELETE\" = \"GET\",\n\t\tbody?: unknown,\n\t): Promise<T> {\n\t\tconst response = await this.#fetchJson(pathname, method, body);\n\t\treturn this.#parseResponse<T>(response, pathname, method);\n\t}\n\n\t/**\n\t * Like {@link #restRequest} but resolves to `null` on a 404 response. For lookups where\n\t * \"not found\" is an expected outcome (e.g. ticket access codes answered with a uniform 404).\n\t */\n\tasync #restRequestNullable<T>(pathname: `/${string}`): Promise<T | null> {\n\t\tconst response = await this.#fetchJson(pathname, \"GET\");\n\t\tif (response.status === 404) {\n\t\t\treturn null;\n\t\t}\n\t\treturn this.#parseResponse<T>(response, pathname, \"GET\");\n\t}\n\n\tasync #fetchJson(\n\t\tpathname: `/${string}`,\n\t\tmethod: \"GET\" | \"POST\" | \"PATCH\" | \"DELETE\",\n\t\tbody?: unknown,\n\t): Promise<Response> {\n\t\tconst logger = this.#logger.getLogger(\"#restRequest\");\n\n\t\tconst endpoint = `${this.#config.endpoint}/api/${this.#config.version}${pathname}`;\n\t\tlogger.debug(`Making ${method} request to YNS API: ${endpoint}`);\n\t\treturn fetch(endpoint, {\n\t\t\tmethod,\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\tAuthorization: `Bearer ${this.#config.token}`,\n\t\t\t},\n\t\t\tbody: body ? JSON.stringify(body) : undefined,\n\t\t});\n\t}\n\n\tasync #parseResponse<T>(response: Response, pathname: `/${string}`, method: string): Promise<T> {\n\t\tconst logger = this.#logger.getLogger(\"#restRequest\");\n\t\tconst endpoint = `${this.#config.endpoint}/api/${this.#config.version}${pathname}`;\n\n\t\tif (!response.ok) {\n\t\t\t// Handle different error types\n\t\t\tconst contentType = response.headers.get(\"content-type\");\n\t\t\tlet errorMessage = `YNS REST request failed: ${method} ${endpoint} ${response.status} ${response.statusText}`;\n\n\t\t\tif (contentType?.includes(\"application/json\")) {\n\t\t\t\ttry {\n\t\t\t\t\tconst errorData = await response.json();\n\t\t\t\t\terrorMessage = errorData.error || errorData.message || errorMessage;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tlogger.error(\"Failed to parse YNS error response as JSON\", error);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst errorText = await response.text();\n\t\t\t\tlogger.error(\n\t\t\t\t\t`YNS API request failed: ${response.status} ${response.statusText}`,\n\t\t\t\t\terrorMessage,\n\t\t\t\t\terrorText,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthrow new Error(errorMessage);\n\t\t}\n\n\t\t// Check if response is JSON before parsing\n\t\tconst contentType = response.headers.get(\"content-type\");\n\t\tif (!contentType?.includes(\"application/json\")) {\n\t\t\tthrow new Error(`YNS API returned ${contentType} instead of JSON for ${pathname}`);\n\t\t}\n\n\t\treturn response.json();\n\t}\n\n\tasync #multipartRequest<T>(pathname: `/${string}`, formData: FormData): Promise<T> {\n\t\tconst logger = this.#logger.getLogger(\"#multipartRequest\");\n\n\t\tconst endpoint = `${this.#config.endpoint}/api/${this.#config.version}${pathname}`;\n\t\tlogger.debug(`Making multipart POST to YNS API: ${endpoint}`);\n\t\tconst response = await fetch(endpoint, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${this.#config.token}`,\n\t\t\t},\n\t\t\tbody: formData,\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst contentType = response.headers.get(\"content-type\");\n\t\t\tlet errorMessage = `YNS REST request failed: POST ${endpoint} ${response.status} ${response.statusText}`;\n\n\t\t\tif (contentType?.includes(\"application/json\")) {\n\t\t\t\ttry {\n\t\t\t\t\tconst errorData = await response.json();\n\t\t\t\t\terrorMessage = errorData.error || errorData.message || errorMessage;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tlogger.error(\"Failed to parse YNS error response as JSON\", error);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst errorText = await response.text();\n\t\t\t\tlogger.error(\n\t\t\t\t\t`YNS API request failed: ${response.status} ${response.statusText}`,\n\t\t\t\t\terrorMessage,\n\t\t\t\t\terrorText,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthrow new Error(errorMessage);\n\t\t}\n\n\t\tconst contentType = response.headers.get(\"content-type\");\n\t\tif (!contentType?.includes(\"application/json\")) {\n\t\t\tthrow new Error(`YNS API returned ${contentType} instead of JSON for ${pathname}`);\n\t\t}\n\n\t\treturn response.json();\n\t}\n\n\tasync meGet(): Promise<APIMeGetResult> {\n\t\tconst logger = this.#logger.getLogger(\"meGet\");\n\t\tlogger.debug(\"Fetching my information\");\n\n\t\tconst pathname = `/me` as const;\n\t\tconst result = await this.#restRequest<APIMeGetResult>(pathname);\n\t\tlogger.debug(\"Received my information:\", result);\n\t\treturn result;\n\t}\n\n\tasync socialsGet(): Promise<APISocialsGetResult> {\n\t\tconst logger = this.#logger.getLogger(\"socialsGet\");\n\t\tlogger.debug(\"Fetching store social links\");\n\n\t\tconst pathname = `/socials` as const;\n\t\tconst result = await this.#restRequest<APISocialsGetResult>(pathname);\n\t\tlogger.debug(\"Received store social links:\", result);\n\t\treturn result;\n\t}\n\n\t// Brands ---------------------------------------------------------------\n\n\tasync brandBrowse(params: APIBrandsBrowseQueryParams = {}): Promise<APIBrandsBrowseResult> {\n\t\tconst queryParams = new URLSearchParams();\n\t\tif (params.limit) queryParams.append(\"limit\", params.limit.toString());\n\t\tif (params.offset) queryParams.append(\"offset\", params.offset.toString());\n\t\tif (params.query) queryParams.append(\"query\", params.query);\n\t\tif (params.active !== undefined) queryParams.append(\"active\", params.active.toString());\n\t\tif (params.lang) queryParams.append(\"lang\", params.lang);\n\t\tconst searchParams = queryParams.size ? `?${queryParams}` : \"\";\n\t\tconst pathname = `/brands${searchParams}` as const;\n\t\treturn this.#restRequest<APIBrandsBrowseResult>(pathname);\n\t}\n\n\tasync brandGet(params: APIBrandGetByIdParams): Promise<APIBrandGetByIdResult | null> {\n\t\tconst pathname = `/brands/${params.idOrSlug}` as const;\n\t\treturn this.#restRequest<APIBrandGetByIdResult>(pathname);\n\t}\n\n\tasync brandCreate(body: APIBrandCreateBody): Promise<APIBrandCreateResult> {\n\t\treturn this.#restRequest<APIBrandCreateResult>(\"/brands\", \"POST\", body);\n\t}\n\n\tasync brandUpdate(params: APIBrandGetByIdParams, body: APIBrandUpdateBody): Promise<APIBrandUpdateResult> {\n\t\tconst pathname = `/brands/${params.idOrSlug}` as const;\n\t\treturn this.#restRequest<APIBrandUpdateResult>(pathname, \"PATCH\", body);\n\t}\n\n\tasync brandDelete(params: APIBrandGetByIdParams): Promise<APIBrandDeleteResult> {\n\t\tconst pathname = `/brands/${params.idOrSlug}` as const;\n\t\treturn this.#restRequest<APIBrandDeleteResult>(pathname, \"DELETE\");\n\t}\n\n\tasync brandAssignProducts(\n\t\tparams: APIBrandGetByIdParams,\n\t\tbody: APIBrandAssignProductsBody,\n\t): Promise<APIBrandAssignProductsResult> {\n\t\tconst pathname = `/brands/${params.idOrSlug}/products` as const;\n\t\treturn this.#restRequest<APIBrandAssignProductsResult>(pathname, \"POST\", body);\n\t}\n\n\t// Order refunds --------------------------------------------------------\n\n\tasync orderRefundsBrowse(\n\t\tparams: APIOrderRefundsParams & APIOrderRefundsBrowseQueryParams,\n\t): Promise<APIOrderRefundsBrowseResult> {\n\t\tconst queryParams = new URLSearchParams();\n\t\tif (params.limit) queryParams.append(\"limit\", params.limit.toString());\n\t\tif (params.offset) queryParams.append(\"offset\", params.offset.toString());\n\t\tconst searchParams = queryParams.size ? `?${queryParams}` : \"\";\n\t\tconst pathname = `/orders/${params.id}/refunds${searchParams}` as const;\n\t\treturn this.#restRequest<APIOrderRefundsBrowseResult>(pathname);\n\t}\n\n\tasync orderRefundGet(params: APIOrderRefundGetParams): Promise<APIOrderRefundGetResult | null> {\n\t\tconst pathname = `/orders/${params.id}/refunds/${params.refundId}` as const;\n\t\treturn this.#restRequest<APIOrderRefundGetResult>(pathname);\n\t}\n\n\t// Product bulk ---------------------------------------------------------\n\n\tasync productBatch(body: APIProductBatchBody): Promise<APIProductBatchResult> {\n\t\treturn this.#restRequest<APIProductBatchResult>(\"/products/batch\", \"POST\", body);\n\t}\n\n\t// Cart -----------------------------------------------------------------\n\n\tasync cartDelete(params: { cartId: string }): Promise<APICartDeleteResult> {\n\t\tconst pathname = `/carts/${params.cartId}` as const;\n\t\treturn this.#restRequest<APICartDeleteResult>(pathname, \"DELETE\");\n\t}\n\n\tasync productBrowse(params: APIProductsBrowseQueryParams): Promise<APIProductsBrowseResult> {\n\t\tconst logger = this.#logger.getLogger(\"productBrowse\");\n\t\tlogger.debug(\"Browsing products with params:\", params);\n\n\t\tconst queryParams = new URLSearchParams();\n\t\tif (params.limit) queryParams.append(\"limit\", params.limit.toString());\n\t\tif (params.offset) queryParams.append(\"offset\", params.offset.toString());\n\t\tif (params.category) queryParams.append(\"category\", params.category);\n\t\tif (params.collection) queryParams.append(\"collection\", params.collection);\n\t\tif (params.brand) queryParams.append(\"brand\", params.brand);\n\t\tif (params.priceMin !== undefined) queryParams.append(\"priceMin\", params.priceMin.toString());\n\t\tif (params.priceMax !== undefined) queryParams.append(\"priceMax\", params.priceMax.toString());\n\t\tif (params.vts) queryParams.append(\"vts\", params.vts);\n\t\tif (params.query) queryParams.append(\"query\", params.query);\n\t\tif (params.active !== undefined) queryParams.append(\"active\", params.active.toString());\n\t\tif (params.orderBy) queryParams.append(\"orderBy\", params.orderBy);\n\t\tif (params.orderDirection) queryParams.append(\"orderDirection\", params.orderDirection);\n\n\t\tconst searchParams = queryParams.size ? `?${queryParams}` : \"\";\n\t\tconst pathname = `/products${searchParams}` as const;\n\t\tlogger.debug(\"Constructed pathname:\", pathname);\n\t\tconst result = await this.#restRequest<APIProductsBrowseResult>(pathname);\n\t\tlogger.debug(\"Received product browse result:\", { meta: result.meta });\n\t\treturn result;\n\t}\n\n\t/**\n\t * Available storefront filter facets for the store: price bounds, variant\n\t * types/values, and active categories, collections, and brands. Pair with\n\t * `productBrowse`'s `collection`, `brand`, `priceMin`/`priceMax`, and `vts`\n\t * params to build a filter UI.\n\t */\n\tasync productFilters(): Promise<APIProductFiltersResult> {\n\t\tconst result = await this.#restRequest<APIProductFiltersResult>(\"/products/filters\");\n\t\treturn result;\n\t}\n\n\tasync productGet(params: APIProductGetByIdParams): Promise<APIProductGetByIdResult | null> {\n\t\tconst pathname = `/products/${params.idOrSlug}` as const;\n\n\t\tconst result = await this.#restRequest<APIProductGetByIdResult>(pathname);\n\n\t\tif (!result) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tasync orderBrowse(params: APIOrdersBrowseQueryParams): Promise<APIOrdersBrowseResult> {\n\t\tconst logger = this.#logger.getLogger(\"orderBrowse\");\n\t\tlogger.debug(\"Browsing orders with params:\", params);\n\n\t\tconst queryParams = new URLSearchParams();\n\n\t\tif (params.limit) queryParams.append(\"limit\", params.limit.toString());\n\t\tif (params.offset) queryParams.append(\"offset\", params.offset.toString());\n\n\t\tconst searchParams = queryParams.size ? `?${queryParams}` : \"\";\n\t\tconst pathname = `/orders${searchParams}` as const;\n\t\tlogger.debug(\"Constructed pathname:\", pathname);\n\t\tconst result = await this.#restRequest<APIOrdersBrowseResult>(pathname);\n\t\tlogger.debug(\"Received orders browse result:\", { meta: result.meta });\n\t\treturn result;\n\t}\n\n\tasync orderGet(params: APIOrderGetByIdParams): Promise<APIOrderGetByIdResult | null> {\n\t\tconst pathname = `/orders/${params.id}` as const;\n\n\t\tconst result = await this.#restRequest<APIOrderGetByIdResult>(pathname);\n\n\t\tif (!result) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t// @todo\n\t// async cartAdd(params: APICartAddBody): Promise<APICartAddResult> {\n\t// \tconst body = {\n\t// \t\tvariantId: params.variantId,\n\t// \t\tcartId: params.cartId,\n\t// \t\tquantity: params.quantity,\n\t// \t\tsubscriptionId: params.subscriptionId,\n\t// \t};\n\n\t// \tconst result = await this.#restRequest<APICartCreateResult>(\"/carts\", \"PATCH\", body);\n\t// \treturn result;\n\t// }\n\n\tasync cartUpsert(body: APICartCreateBody): Promise<APICartCreateResult> {\n\t\tconst result = await this.#restRequest<APICartCreateResult>(\"/carts\", \"POST\", body);\n\t\treturn result;\n\t}\n\n\t/**\n\t * Add a configured bundle to the cart in one call. `selections` are the customer's per-group\n\t * choices; always-included (forced) items may be omitted — the server fills them in and\n\t * validates the rest against the bundle's groups. Omit `cartId` to start a new cart. The\n\t * returned cart prices the bundle line (componentTotal × (1 − discount)).\n\t */\n\tasync cartAddBundle(params: {\n\t\tbundleId: string;\n\t\tselections: NonNullable<APICartCreateBody[\"selections\"]>;\n\t\tcartId?: string;\n\t\tcurrency?: string;\n\t}): Promise<APICartCreateResult> {\n\t\tconst body: APICartCreateBody = {\n\t\t\tbundleId: params.bundleId,\n\t\t\tselections: params.selections,\n\t\t\t...(params.cartId ? { cartId: params.cartId } : {}),\n\t\t\t...(params.currency ? { currency: params.currency } : {}),\n\t\t};\n\t\tconst result = await this.#restRequest<APICartCreateResult>(\"/carts\", \"POST\", body);\n\t\treturn result;\n\t}\n\n\tasync cartRemoveItem(params: { cartId: string; variantId: string }): Promise<APICartGetResult> {\n\t\tconst pathname = `/carts/${params.cartId}/line-items/${params.variantId}` as const;\n\t\treturn this.#restRequest<APICartGetResult>(pathname, \"DELETE\");\n\t}\n\n\tasync cartGet(params: { cartId: string }): Promise<APICartGetResult | null> {\n\t\tconst pathname = `/carts/${params.cartId}` as const;\n\t\tconst result = await this.#restRequest<APICartGetResult>(pathname);\n\t\treturn result;\n\t}\n\n\tasync couponBrowse(params: APICouponsBrowseQueryParams = {}): Promise<APICouponsBrowseResult> {\n\t\tconst queryParams = new URLSearchParams();\n\t\tif (params.limit) queryParams.append(\"limit\", params.limit.toString());\n\t\tif (params.offset) queryParams.append(\"offset\", params.offset.toString());\n\t\tif (params.query) queryParams.append(\"query\", params.query);\n\n\t\tconst searchParams = queryParams.size ? `?${queryParams}` : \"\";\n\t\tconst pathname = `/coupons${searchParams}` as const;\n\n\t\treturn this.#restRequest<APICouponsBrowseResult>(pathname);\n\t}\n\n\t/** Look up a coupon by its UUID or its code. Resolves to `null` when not found. */\n\tasync couponGet(params: APICouponGetByIdParams): Promise<APICouponGetByIdResult | null> {\n\t\tconst pathname = `/coupons/${params.id}` as const;\n\t\treturn this.#restRequestNullable<APICouponGetByIdResult>(pathname);\n\t}\n\n\tasync couponCreate(body: APICouponCreateBody): Promise<APICouponCreateResult> {\n\t\treturn this.#restRequest<APICouponCreateResult>(\"/coupons\", \"POST\", body);\n\t}\n\n\tasync couponUpdate(\n\t\tparams: APICouponGetByIdParams,\n\t\tbody: APICouponUpdateBody,\n\t): Promise<APICouponUpdateResult> {\n\t\tconst pathname = `/coupons/${params.id}` as const;\n\t\treturn this.#restRequest<APICouponUpdateResult>(pathname, \"PATCH\", body);\n\t}\n\n\tasync couponDelete(params: APICouponGetByIdParams): Promise<APICouponDeleteResult> {\n\t\tconst pathname = `/coupons/${params.id}` as const;\n\t\treturn this.#restRequest<APICouponDeleteResult>(pathname, \"DELETE\");\n\t}\n\n\tasync collectionGet(params: APICollectionGetByIdParams): Promise<APICollectionGetByIdResult | null> {\n\t\tconst pathname = `/collections/${params.idOrSlug}` as const;\n\n\t\tconst result = await this.#restRequest<APICollectionGetByIdResult>(pathname);\n\t\treturn result;\n\t}\n\n\tasync collectionBrowse(params: APICollectionsBrowseQueryParams): Promise<APICollectionsBrowseResult> {\n\t\tconst queryParams = new URLSearchParams();\n\t\tif (params.limit) queryParams.append(\"limit\", params.limit.toString());\n\t\tif (params.offset) queryParams.append(\"offset\", params.offset.toString());\n\t\tif (params.query) queryParams.append(\"query\", params.query);\n\t\tif (params.active !== undefined) queryParams.append(\"active\", params.active.toString());\n\t\tif (params.group) queryParams.append(\"group\", params.group);\n\n\t\tconst searchParams = queryParams.size ? `?${queryParams}` : \"\";\n\t\tconst pathname = `/collections${searchParams}` as const;\n\n\t\tconst result = await this.#restRequest<APICollectionsBrowseResult>(pathname);\n\t\treturn result;\n\t}\n\n\tasync collectionCreate(body: APICollectionCreateBody): Promise<APICollectionCreateResult> {\n\t\treturn this.#restRequest<APICollectionCreateResult>(\"/collections\", \"POST\", body);\n\t}\n\n\tasync collectionUpdate(\n\t\tparams: APICollectionGetByIdParams,\n\t\tbody: APICollectionUpdateBody,\n\t): Promise<APICollectionUpdateResult> {\n\t\tconst pathname = `/collections/${params.idOrSlug}` as const;\n\t\treturn this.#restRequest<APICollectionUpdateResult>(pathname, \"PATCH\", body);\n\t}\n\n\tasync collectionDelete(params: APICollectionGetByIdParams): Promise<APICollectionDeleteResult> {\n\t\tconst pathname = `/collections/${params.idOrSlug}` as const;\n\t\treturn this.#restRequest<APICollectionDeleteResult>(pathname, \"DELETE\");\n\t}\n\n\tasync collectionImportMemberships(\n\t\tbody: APICollectionImportMembershipsBody,\n\t): Promise<APICollectionImportMembershipsResult> {\n\t\tconst formData = new FormData();\n\t\tformData.append(\"file\", body.file);\n\t\treturn this.#multipartRequest<APICollectionImportMembershipsResult>(\n\t\t\t\"/collections/import-memberships\",\n\t\t\tformData,\n\t\t);\n\t}\n\n\tasync categoryGet(params: APICategoryGetByIdParams): Promise<APICategoryGetByIdResult | null> {\n\t\tconst pathname = `/categories/${params.idOrSlug}` as const;\n\n\t\tconst result = await this.#restRequest<APICategoryGetByIdResult>(pathname);\n\t\treturn result;\n\t}\n\n\tasync categoriesBrowse(params: APICategoriesBrowseQueryParams): Promise<APICategoriesBrowseResult> {\n\t\tconst queryParams = new URLSearchParams();\n\t\tif (params.limit) queryParams.append(\"limit\", params.limit.toString());\n\t\tif (params.offset) queryParams.append(\"offset\", params.offset.toString());\n\t\tif (params.query) queryParams.append(\"query\", params.query);\n\t\tif (params.active !== undefined) queryParams.append(\"active\", params.active.toString());\n\n\t\tconst searchParams = queryParams.size ? `?${queryParams}` : \"\";\n\t\tconst pathname = `/categories${searchParams}` as const;\n\n\t\tconst result = await this.#restRequest<APICategoriesBrowseResult>(pathname);\n\t\treturn result;\n\t}\n\n\t// ============================================\n\t// Posts\n\t// ============================================\n\n\tasync postBrowse(params: APIPostsBrowseQueryParams = {}): Promise<APIPostsBrowseResult> {\n\t\tconst queryParams = new URLSearchParams();\n\t\tif (params.limit) queryParams.append(\"limit\", params.limit.toString());\n\t\tif (params.offset) queryParams.append(\"offset\", params.offset.toString());\n\t\tif (params.query) queryParams.append(\"query\", params.query);\n\t\tif (params.active !== undefined) queryParams.append(\"active\", params.active.toString());\n\t\tif (params.tag) queryParams.append(\"tag\", params.tag);\n\t\tif (params.categoryId) queryParams.append(\"categoryId\", params.categoryId);\n\n\t\tconst searchParams = queryParams.size ? `?${queryParams}` : \"\";\n\t\tconst pathname = `/posts${searchParams}` as const;\n\n\t\treturn this.#restRequest<APIPostsBrowseResult>(pathname);\n\t}\n\n\tasync postGet(params: APIPostGetByIdParams): Promise<APIPostGetByIdResult | null> {\n\t\tconst pathname = `/posts/${params.idOrSlug}` as const;\n\t\treturn this.#restRequest<APIPostGetByIdResult>(pathname);\n\t}\n\n\tasync postCreate(body: APIPostCreateBody): Promise<APIPostCreateResult> {\n\t\treturn this.#restRequest<APIPostCreateResult>(\"/posts\", \"POST\", body);\n\t}\n\n\tasync postUpdate(params: APIPostGetByIdParams, body: APIPostUpdateBody): Promise<APIPostUpdateResult> {\n\t\tconst pathname = `/posts/${params.idOrSlug}` as const;\n\t\treturn this.#restRequest<APIPostUpdateResult>(pathname, \"PATCH\", body);\n\t}\n\n\tasync postDelete(params: APIPostGetByIdParams): Promise<APIPostDeleteResult> {\n\t\tconst pathname = `/posts/${params.idOrSlug}` as const;\n\t\treturn this.#restRequest<APIPostDeleteResult>(pathname, \"DELETE\");\n\t}\n\n\tasync postCommentsBrowse(\n\t\tparams: APIPostGetByIdParams,\n\t\tqueryParams: APIPostCommentsBrowseQueryParams = {},\n\t): Promise<APIPostCommentsBrowseResult> {\n\t\tconst urlParams = new URLSearchParams();\n\t\tif (queryParams.limit) urlParams.append(\"limit\", queryParams.limit.toString());\n\t\tif (queryParams.offset) urlParams.append(\"offset\", queryParams.offset.toString());\n\n\t\tconst searchParams = urlParams.size ? `?${urlParams}` : \"\";\n\t\tconst pathname = `/posts/${params.idOrSlug}/comments${searchParams}` as const;\n\n\t\treturn this.#restRequest<APIPostCommentsBrowseResult>(pathname);\n\t}\n\n\tasync postCommentCreate(\n\t\tparams: APIPostGetByIdParams,\n\t\tbody: APIPostCommentCreateBody,\n\t): Promise<APIPostCommentCreateResult> {\n\t\tconst pathname = `/posts/${params.idOrSlug}/comments` as const;\n\t\treturn this.#restRequest<APIPostCommentCreateResult>(pathname, \"POST\", body);\n\t}\n\n\t// ============================================\n\t// Blog Categories\n\t// ============================================\n\n\tasync blogCategoryBrowse(\n\t\tparams: APIBlogCategoriesBrowseQueryParams = {},\n\t): Promise<APIBlogCategoriesBrowseResult> {\n\t\tconst queryParams = new URLSearchParams();\n\t\tif (params.limit) queryParams.append(\"limit\", params.limit.toString());\n\t\tif (params.offset) queryParams.append(\"offset\", params.offset.toString());\n\t\tif (params.query) queryParams.append(\"query\", params.query);\n\t\tif (params.active !== undefined) queryParams.append(\"active\", params.active.toString());\n\n\t\tconst searchParams = queryParams.size ? `?${queryParams}` : \"\";\n\t\tconst pathname = `/blog-categories${searchParams}` as const;\n\n\t\treturn this.#restRequest<APIBlogCategoriesBrowseResult>(pathname);\n\t}\n\n\tasync blogCategoryGet(params: APIBlogCategoryGetByIdParams): Promise<APIBlogCategoryGetByIdResult | null> {\n\t\tconst pathname = `/blog-categories/${params.idOrSlug}` as const;\n\t\treturn this.#restRequest<APIBlogCategoryGetByIdResult>(pathname);\n\t}\n\n\tasync blogCategoryCreate(body: APIBlogCategoryCreateBody): Promise<APIBlogCategoryCreateResult> {\n\t\treturn this.#restRequest<APIBlogCategoryCreateResult>(\"/blog-categories\", \"POST\", body);\n\t}\n\n\tasync blogCategoryUpdate(\n\t\tparams: APIBlogCategoryGetByIdParams,\n\t\tbody: APIBlogCategoryUpdateBody,\n\t): Promise<APIBlogCategoryUpdateResult> {\n\t\tconst pathname = `/blog-categories/${params.idOrSlug}` as const;\n\t\treturn this.#restRequest<APIBlogCategoryUpdateResult>(pathname, \"PATCH\", body);\n\t}\n\n\tasync blogCategoryDelete(params: APIBlogCategoryGetByIdParams): Promise<APIBlogCategoryDeleteResult> {\n\t\tconst pathname = `/blog-categories/${params.idOrSlug}` as const;\n\t\treturn this.#restRequest<APIBlogCategoryDeleteResult>(pathname, \"DELETE\");\n\t}\n\n\t// ============================================\n\t// Customers\n\t// ============================================\n\n\tasync customerBrowse(params: APICustomersBrowseQueryParams = {}): Promise<APICustomersBrowseResult> {\n\t\tconst queryParams = new URLSearchParams();\n\t\tif (params.limit) queryParams.append(\"limit\", params.limit.toString());\n\t\tif (params.offset) queryParams.append(\"offset\", params.offset.toString());\n\t\tif (params.search) queryParams.append(\"search\", params.search);\n\n\t\tconst searchParams = queryParams.size ? `?${queryParams}` : \"\";\n\t\tconst pathname = `/customers${searchParams}` as const;\n\n\t\treturn this.#restRequest<APICustomersBrowseResult>(pathname);\n\t}\n\n\tasync customerGet(params: APICustomerGetByIdParams): Promise<APICustomerGetByIdResult | null> {\n\t\tconst pathname = `/customers/${params.id}` as const;\n\t\treturn this.#restRequest<APICustomerGetByIdResult>(pathname);\n\t}\n\n\tasync customerUpdate(\n\t\tparams: APICustomerGetByIdParams,\n\t\tbody: APICustomerUpdateBody,\n\t): Promise<APICustomerUpdateResult> {\n\t\tconst pathname = `/customers/${params.id}` as const;\n\t\treturn this.#restRequest<APICustomerUpdateResult>(pathname, \"PATCH\", body);\n\t}\n\n\tasync customerAddressCreate(\n\t\tparams: APICustomerGetByIdParams,\n\t\tbody: APICustomerAddressCreateBody,\n\t): Promise<APICustomerAddressCreateResult> {\n\t\tconst pathname = `/customers/${params.id}/addresses` as const;\n\t\treturn this.#restRequest<APICustomerAddressCreateResult>(pathname, \"POST\", body);\n\t}\n\n\tasync customerAddressDelete(params: { customerId: string; addressId: string }): Promise<void> {\n\t\tconst pathname = `/customers/${params.customerId}/addresses/${params.addressId}` as const;\n\t\tawait this.#restRequest<unknown>(pathname, \"DELETE\");\n\t}\n\n\tasync customerOrdersBrowse(\n\t\tparams: APICustomerGetByIdParams,\n\t\tqueryParams: APICustomerOrdersBrowseQueryParams = {},\n\t): Promise<APICustomerOrdersBrowseResult> {\n\t\tconst urlParams = new URLSearchParams();\n\t\tif (queryParams.limit) urlParams.append(\"limit\", queryParams.limit.toString());\n\t\tif (queryParams.offset) urlParams.append(\"offset\", queryParams.offset.toString());\n\n\t\tconst searchParams = urlParams.size ? `?${urlParams}` : \"\";\n\t\tconst pathname = `/customers/${params.id}/orders${searchParams}` as const;\n\n\t\treturn this.#restRequest<APICustomerOrdersBrowseResult>(pathname);\n\t}\n\n\t// ============================================\n\t// Inventory\n\t// ============================================\n\n\tasync inventoryBrowse(params: APIInventoryBrowseQueryParams = {}): Promise<APIInventoryBrowseResult> {\n\t\tconst queryParams = new URLSearchParams();\n\t\tif (params.limit) queryParams.append(\"limit\", params.limit.toString());\n\t\tif (params.cursor) queryParams.append(\"cursor\", params.cursor);\n\t\tif (params.lowStock !== undefined) queryParams.append(\"lowStock\", params.lowStock.toString());\n\n\t\tconst searchParams = queryParams.size ? `?${queryParams}` : \"\";\n\t\tconst pathname = `/inventory${searchParams}` as const;\n\n\t\treturn this.#restRequest<APIInventoryBrowseResult>(pathname);\n\t}\n\n\tasync inventoryAdjust(sku: string, body: APIInventoryAdjustBody): Promise<APIInventoryAdjustResult> {\n\t\tconst pathname = `/inventory/${encodeURIComponent(sku)}/adjust` as const;\n\t\treturn this.#restRequest<APIInventoryAdjustResult>(pathname, \"POST\", body);\n\t}\n\n\t// ============================================\n\t// Variants\n\t// ============================================\n\n\tasync variantGet(params: APIVariantGetByIdParams): Promise<APIVariantGetByIdResult | null> {\n\t\tconst pathname = `/variants/${params.idOrSku}` as const;\n\t\treturn this.#restRequest<APIVariantGetByIdResult>(pathname);\n\t}\n\n\tasync variantUpdate(\n\t\tparams: APIVariantGetByIdParams,\n\t\tbody: APIVariantUpdateBody,\n\t): Promise<APIVariantUpdateResult> {\n\t\tconst pathname = `/variants/${params.idOrSku}` as const;\n\t\treturn this.#restRequest<APIVariantUpdateResult>(pathname, \"PATCH\", body);\n\t}\n\n\tasync variantDelete(params: APIVariantGetByIdParams): Promise<void> {\n\t\tconst pathname = `/variants/${params.idOrSku}` as const;\n\t\tawait this.#restRequest<unknown>(pathname, \"DELETE\");\n\t}\n\n\tasync variantCreate(productId: string, body: APIVariantCreateBody): Promise<APIVariantCreateResult> {\n\t\tconst pathname = `/products/${productId}/variants` as const;\n\t\treturn this.#restRequest<APIVariantCreateResult>(pathname, \"POST\", body);\n\t}\n\n\t// ============================================\n\t// Subscribers\n\t// ============================================\n\n\tasync subscriberCreate(body: APISubscriberCreateBody): Promise<APISubscriberCreateResult> {\n\t\treturn this.#restRequest<APISubscriberCreateResult>(\"/subscribers\", \"POST\", body);\n\t}\n\n\tasync subscriberDelete(email: string): Promise<APISubscriberDeleteResult> {\n\t\tconst pathname = `/subscribers?email=${encodeURIComponent(email)}` as const;\n\t\treturn this.#restRequest<APISubscriberDeleteResult>(pathname, \"DELETE\");\n\t}\n\n\t// ============================================\n\t// Contact Messages\n\t// ============================================\n\n\tasync contactMessageCreate(body: APIContactMessageCreateBody): Promise<APIContactMessageCreateResult> {\n\t\treturn this.#restRequest<APIContactMessageCreateResult>(\"/contact-messages\", \"POST\", body);\n\t}\n\n\t// ============================================\n\t// Product mutations\n\t// ============================================\n\n\tasync productCreate(body: APIProductCreateBody): Promise<APIProductCreateResult> {\n\t\treturn this.#restRequest<APIProductCreateResult>(\"/products\", \"POST\", body);\n\t}\n\n\tasync productUpdate(\n\t\tparams: APIProductGetByIdParams,\n\t\tbody: APIProductUpdateBody,\n\t): Promise<APIProductUpdateResult> {\n\t\tconst pathname = `/products/${params.idOrSlug}` as const;\n\t\treturn this.#restRequest<APIProductUpdateResult>(pathname, \"PATCH\", body);\n\t}\n\n\tasync productDelete(params: APIProductGetByIdParams): Promise<APIProductDeleteResult> {\n\t\tconst pathname = `/products/${params.idOrSlug}` as const;\n\t\treturn this.#restRequest<APIProductDeleteResult>(pathname, \"DELETE\");\n\t}\n\n\t// ============================================\n\t// Product Reviews\n\t// ============================================\n\n\tasync productReviewsBrowse(\n\t\tparams: APIProductGetByIdParams,\n\t\tqueryParams: APIProductReviewsBrowseQueryParams = {},\n\t): Promise<APIProductReviewsBrowseResult> {\n\t\tconst urlParams = new URLSearchParams();\n\t\tif (queryParams.limit) urlParams.append(\"limit\", queryParams.limit.toString());\n\t\tif (queryParams.offset) urlParams.append(\"offset\", queryParams.offset.toString());\n\n\t\tconst searchParams = urlParams.size ? `?${urlParams}` : \"\";\n\t\tconst pathname = `/products/${params.idOrSlug}/reviews${searchParams}` as const;\n\n\t\treturn this.#restRequest<APIProductReviewsBrowseResult>(pathname);\n\t}\n\n\tasync productReviewCreate(\n\t\tparams: APIProductGetByIdParams,\n\t\tbody: APIProductReviewCreateBody,\n\t): Promise<APIProductReviewCreateResult> {\n\t\tconst pathname = `/products/${params.idOrSlug}/reviews` as const;\n\t\treturn this.#restRequest<APIProductReviewCreateResult>(pathname, \"POST\", body);\n\t}\n\n\t// ============================================\n\t// Events (products flagged `flags.event` with a single non-shippable ticket variant)\n\t// ============================================\n\n\tasync eventBrowse(params: APIEventsBrowseQueryParams = {}): Promise<APIEventsBrowseResult> {\n\t\tconst logger = this.#logger.getLogger(\"eventBrowse\");\n\t\tconst queryParams = new URLSearchParams();\n\t\tif (params.offset !== undefined) queryParams.append(\"offset\", params.offset.toString());\n\t\tif (params.limit !== undefined) queryParams.append(\"limit\", params.limit.toString());\n\n\t\tconst searchParams = queryParams.size ? `?${queryParams}` : \"\";\n\t\tconst pathname = `/events${searchParams}` as const;\n\t\tlogger.debug(\"Browsing events:\", pathname);\n\t\treturn this.#restRequest<APIEventsBrowseResult>(pathname);\n\t}\n\n\tasync eventGet(params: APIEventGetByIdParams): Promise<APIEventGetByIdResult> {\n\t\tconst pathname = `/events/${params.idOrSlug}` as const;\n\t\treturn this.#restRequest<APIEventGetByIdResult>(pathname);\n\t}\n\n\tasync eventCreate(body: APIEventCreateBody): Promise<APIEventCreateResult> {\n\t\treturn this.#restRequest<APIEventCreateResult>(\"/events\", \"POST\", body);\n\t}\n\n\tasync eventUpdate(params: APIEventGetByIdParams, body: APIEventUpdateBody): Promise<APIEventUpdateResult> {\n\t\tconst pathname = `/events/${params.idOrSlug}` as const;\n\t\treturn this.#restRequest<APIEventUpdateResult>(pathname, \"PATCH\", body);\n\t}\n\n\tasync eventAttendeesBrowse(params: APIEventGetByIdParams): Promise<APIEventAttendeesBrowseResult> {\n\t\tconst pathname = `/events/${params.idOrSlug}/attendees` as const;\n\t\treturn this.#restRequest<APIEventAttendeesBrowseResult>(pathname);\n\t}\n\n\t// ============================================\n\t// Tickets (no-login buyer/attendee access to purchased event tickets)\n\t// ============================================\n\n\t/**\n\t * Buyer ticket lookup: the order's 6-character access code plus the purchase email.\n\t * Resolves to `null` on mismatch — the API answers a uniform 404 for an unknown code,\n\t * an email that doesn't match, or an order without tickets.\n\t */\n\tasync ticketsGet(params: { code: string; email: string }): Promise<APITicketsGetResult | null> {\n\t\tconst logger = this.#logger.getLogger(\"ticketsGet\");\n\t\tconst queryParams = new URLSearchParams({ email: params.email });\n\t\tconst pathname = `/tickets/${encodeURIComponent(params.code)}?${queryParams}` as const;\n\t\tlogger.debug(\"Fetching ticket bundle:\", pathname);\n\t\treturn this.#restRequestNullable<APITicketsGetResult>(pathname);\n\t}\n\n\t/**\n\t * Buyer bulk-edit of attendee names/emails. The body carries the purchase email; seat\n\t * tokens not belonging to the order are silently ignored. Throws on code/email mismatch\n\t * (404) or when the order is cancelled/refunded (409).\n\t */\n\tasync ticketsUpdate(params: { code: string }, body: APITicketsUpdateBody): Promise<APITicketsUpdateResult> {\n\t\tconst pathname = `/tickets/${encodeURIComponent(params.code)}` as const;\n\t\treturn this.#restRequest<APITicketsUpdateResult>(pathname, \"PATCH\", body);\n\t}\n\n\t/**\n\t * View-only attendee ticket by per-seat token (the capability embedded in the attendee\n\t * link/QR). Resolves to `null` for an unknown token. Attendee details can only be edited\n\t * by the buyer via {@link ticketsUpdate} — attendee links must not escalate.\n\t */\n\tasync ticketAttendeeGet(params: { token: string }): Promise<APITicketAttendeeGetResult | null> {\n\t\tconst pathname = `/tickets/attendee/${encodeURIComponent(params.token)}` as const;\n\t\treturn this.#restRequestNullable<APITicketAttendeeGetResult>(pathname);\n\t}\n\n\t// ============================================\n\t// Category mutations\n\t// ============================================\n\n\tasync categoryCreate(body: APICategoryCreateBody): Promise<APICategoryCreateResult> {\n\t\treturn this.#restRequest<APICategoryCreateResult>(\"/categories\", \"POST\", body);\n\t}\n\n\tasync categoryUpdate(\n\t\tparams: APICategoryGetByIdParams,\n\t\tbody: APICategoryUpdateBody,\n\t): Promise<APICategoryUpdateResult> {\n\t\tconst pathname = `/categories/${params.idOrSlug}` as const;\n\t\treturn this.#restRequest<APICategoryUpdateResult>(pathname, \"PATCH\", body);\n\t}\n\n\tasync categoryDelete(params: APICategoryGetByIdParams): Promise<APICategoryDeleteResult> {\n\t\tconst pathname = `/categories/${params.idOrSlug}` as const;\n\t\treturn this.#restRequest<APICategoryDeleteResult>(pathname, \"DELETE\");\n\t}\n\n\t// ============================================\n\t// Order mutations\n\t// ============================================\n\n\tasync orderUpdate(params: APIOrderGetByIdParams, body: APIOrderUpdateBody): Promise<APIOrderUpdateResult> {\n\t\tconst pathname = `/orders/${params.id}` as const;\n\t\treturn this.#restRequest<APIOrderUpdateResult>(pathname, \"PATCH\", body);\n\t}\n\n\t// ============================================\n\t// Legal Pages\n\t// ============================================\n\n\tasync legalPageBrowse(\n\t\tqueryParams: APILegalPagesBrowseQueryParams = {},\n\t): Promise<APILegalPagesBrowseResult> {\n\t\treturn this.request<APILegalPagesBrowseResult>(\"/legal-pages\", {\n\t\t\tquery: queryParams,\n\t\t});\n\t}\n\n\tasync legalPageGet(\n\t\tkey: string,\n\t\tqueryParams: APILegalPageGetByPathQueryParams = {},\n\t): Promise<APILegalPageGetByPathResult> {\n\t\tconst normalized = key.startsWith(\"/\") ? key.slice(1) : key;\n\t\tconst pathname = `/legal-pages/${encodeURIComponent(normalized)}` as const;\n\t\treturn this.request<APILegalPageGetByPathResult>(pathname, {\n\t\t\tquery: queryParams,\n\t\t});\n\t}\n\n\tasync legalPageCreate(\n\t\tbody: APILegalPageCreateBody,\n\t\tqueryParams: APILegalPageCreateQueryParams = {},\n\t): Promise<APILegalPageCreateResult> {\n\t\treturn this.request<APILegalPageCreateResult, APILegalPageCreateBody>(\"/legal-pages\", {\n\t\t\tmethod: \"POST\",\n\t\t\tbody,\n\t\t\tquery: queryParams,\n\t\t});\n\t}\n\n\tasync legalPageUpdate(\n\t\tkey: string,\n\t\tbody: APILegalPageUpdateBody,\n\t\tqueryParams: APILegalPageUpdateQueryParams = {},\n\t): Promise<APILegalPageUpdateResult> {\n\t\tconst normalized = key.startsWith(\"/\") ? key.slice(1) : key;\n\t\tconst pathname = `/legal-pages/${encodeURIComponent(normalized)}` as const;\n\t\treturn this.request<APILegalPageUpdateResult, APILegalPageUpdateBody>(pathname, {\n\t\t\tmethod: \"PATCH\",\n\t\t\tbody,\n\t\t\tquery: queryParams,\n\t\t});\n\t}\n\n\tasync search(params: APISearchQueryParams): Promise<APISearchResult> {\n\t\treturn this.request<APISearchResult>(\"/search\", {\n\t\t\tquery: params,\n\t\t});\n\t}\n\n\t// ============================================\n\t// Instaview\n\t// ============================================\n\n\tasync instaviewImagesBrowse(\n\t\tparams: APIInstaviewImagesBrowseParams,\n\t\tqueryParams: APIInstaviewImagesBrowseQueryParams = {},\n\t): Promise<APIInstaviewImagesBrowseResult> {\n\t\tconst urlParams = new URLSearchParams();\n\t\tif (queryParams.limit) urlParams.append(\"limit\", queryParams.limit.toString());\n\t\tif (queryParams.cursor) urlParams.append(\"cursor\", queryParams.cursor);\n\n\t\tconst searchParams = urlParams.size ? `?${urlParams}` : \"\";\n\t\tconst pathname = `/instaview/accounts/${params.handle}/images${searchParams}` as const;\n\n\t\treturn this.#restRequest<APIInstaviewImagesBrowseResult>(pathname);\n\t}\n\n\t/**\n\t * Make a raw API request to any endpoint.\n\t * Use this for new API features not yet supported by typed methods.\n\t *\n\t * @example\n\t * // GET request (default method)\n\t * const webhooks = await provider.request<Webhook[]>('/webhooks');\n\t *\n\t * // POST with typed body\n\t * const webhook = await provider.request<Webhook, CreateWebhookBody>('/webhooks', {\n\t * method: 'POST',\n\t * body: { url: 'https://...' }\n\t * });\n\t *\n\t * // GET with query parameters\n\t * const products = await provider.request<Product[]>('/products', {\n\t * query: { limit: 10, category: 'shoes' }\n\t * });\n\t *\n\t * // Path parameters via template literals\n\t * const product = await provider.request<Product>(`/products/${id}`);\n\t */\n\tasync request<TResponse = unknown, TBody = unknown>(\n\t\tpathname: `/${string}`,\n\t\toptions?: {\n\t\t\tmethod?: \"GET\" | \"POST\" | \"PATCH\" | \"DELETE\";\n\t\t\tbody?: TBody;\n\t\t\tquery?: Record<string, string | number | boolean | null | undefined>;\n\t\t},\n\t) {\n\t\tconst queryEntries = options?.query\n\t\t\t? Object.entries(options.query).filter((entry): entry is [string, string | number | boolean] => {\n\t\t\t\t\tconst [, value] = entry;\n\t\t\t\t\treturn value !== null && value !== undefined;\n\t\t\t\t})\n\t\t\t: [];\n\t\tconst queryString =\n\t\t\tqueryEntries.length > 0 ? `?${new URLSearchParams(queryEntries.map(([k, v]) => [k, String(v)]))}` : \"\";\n\n\t\treturn this.#restRequest<TResponse>(`${pathname}${queryString}`, options?.method ?? \"GET\", options?.body);\n\t}\n}\n","import { YNSProvider } from \"./providers/yns\";\nimport type { CommerceConfig } from \"./types\";\n\nexport function Commerce(config: CommerceConfig = {}): YNSProvider {\n\treturn new YNSProvider(config);\n}\n"],"mappings":"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","names":["YNS_API_KEY","env","LogLevel","strLogLevel","valueLogLevel","RESET","BLUE","GREEN","YELLOW","RED","TIME","DEBUG","OK","WARN","ERROR","PREFIX_TIME","PREFIX_DEBUG","PREFIX_OK","PREFIX_WARN","PREFIX_ERROR","getLogger","groupLabel","PREFIX","subGroupLabel","label","args","item","options","logger","YNSProvider","#config","#logger","getLogger","config","token","env","isStaging","endpoint","#restRequest","pathname","method","body","response","#fetchJson","#parseResponse","#restRequestNullable","logger","contentType","errorMessage","errorData","error","errorText","#multipartRequest","formData","result","params","queryParams","searchParams","urlParams","sku","productId","email","key","normalized","options","queryEntries","entry","value","queryString","k","v","Commerce","config","YNSProvider"]}
|
|
1
|
+
{"version":3,"sources":["../src/env.ts","../src/logger.ts","../src/providers/yns.ts","../src/commerce.ts"],"sourcesContent":["const YNS_API_KEY = process.env.YNS_API_KEY;\n\nexport const env = {\n\tYNS_API_KEY,\n};\n","import type { InspectOptions } from \"node:util\";\n\ntype LogParms = [message: unknown, ...optionalParams: unknown[]];\n\n/**\n * Vercel only supports 3 levels of logging. We're adding additional DEBUG level.\n * https://vercel.com/docs/observability/runtime-logs#level\n *\n * ERROR - Fatal for a particular request. Should be fixed sooner than later.\n *\n * WARN - A note on something that should probably be looked at eventually.\n *\n * LOG - Detail on regular operation.\n *\n * DEBUG - Debug only info as well as time and timeEnd functions.\n */\nconst LogLevel = {\n\tDEBUG: 0,\n\tLOG: 1,\n\tWARN: 2,\n\tERROR: 3,\n} as const;\ntype LogLevel = keyof typeof LogLevel;\n\nconst strLogLevel = (process.env.NEXT_PUBLIC_LOG_LEVEL || \"LOG\") as LogLevel;\nconst valueLogLevel = LogLevel[strLogLevel];\n\nconst RESET = \"\\x1b[0m\";\nconst BLUE = \"\\x1b[34m\";\nconst GREEN = \"\\x1b[32m\";\nconst YELLOW = \"\\x1b[33m\";\nconst RED = \"\\x1b[31m\";\n\nconst TIME = `⏱️`;\nconst DEBUG = `🐛`;\nconst OK = `✔️`;\nconst WARN = `⚠️`;\nconst ERROR = `❌`;\n\nconst PREFIX_TIME = `${TIME} `;\nconst PREFIX_DEBUG = `${BLUE}${DEBUG}${RESET} `;\nconst PREFIX_OK = `${GREEN}${OK}${RESET} `;\nconst PREFIX_WARN = `${YELLOW}${WARN}${RESET} `;\nconst PREFIX_ERROR = `${RED}${ERROR}${RESET} `;\n\nexport const getLogger = (groupLabel?: string) => {\n\tconst PREFIX = groupLabel ? `[${groupLabel}] ` : \"\";\n\treturn {\n\t\tgetLogger(subGroupLabel: string) {\n\t\t\treturn getLogger([groupLabel, subGroupLabel].filter(Boolean).join(\" > \"));\n\t\t},\n\t\ttime(label: string) {\n\t\t\tif (valueLogLevel > LogLevel.DEBUG) return;\n\t\t\tconsole.time([PREFIX_TIME, PREFIX, label].filter(Boolean).join(\" \"));\n\t\t},\n\t\ttimeEnd(label: string) {\n\t\t\tif (valueLogLevel > LogLevel.DEBUG) return;\n\t\t\tconsole.timeEnd([PREFIX_TIME, PREFIX, label].filter(Boolean).join(\" \"));\n\t\t},\n\t\tdebug(...args: LogParms) {\n\t\t\tif (valueLogLevel > LogLevel.DEBUG) return;\n\t\t\tconsole.log(...[PREFIX_DEBUG, PREFIX, ...args].filter(Boolean));\n\t\t},\n\t\tlog(...args: LogParms) {\n\t\t\tif (valueLogLevel > LogLevel.LOG) return;\n\t\t\tconsole.log(...[PREFIX_OK, PREFIX, ...args].filter(Boolean));\n\t\t},\n\t\tdir(item?: unknown, options?: InspectOptions) {\n\t\t\tif (valueLogLevel > LogLevel.LOG) return;\n\t\t\tconsole.dir(item, options);\n\t\t},\n\t\twarn(...args: LogParms) {\n\t\t\tif (valueLogLevel > LogLevel.WARN) return;\n\t\t\tconsole.warn(...[PREFIX_WARN, PREFIX, ...args].filter(Boolean));\n\t\t},\n\t\terror(...args: LogParms) {\n\t\t\tif (valueLogLevel > LogLevel.ERROR) return;\n\t\t\tconsole.error(...[PREFIX_ERROR, PREFIX, ...args].filter(Boolean));\n\t\t},\n\t};\n};\n\nexport const logger = getLogger();\n","import type {\n\tAPIBlogCategoriesBrowseQueryParams,\n\tAPIBlogCategoriesBrowseResult,\n\tAPIBlogCategoryCreateBody,\n\tAPIBlogCategoryCreateResult,\n\tAPIBlogCategoryDeleteResult,\n\tAPIBlogCategoryGetByIdParams,\n\tAPIBlogCategoryGetByIdResult,\n\tAPIBlogCategoryUpdateBody,\n\tAPIBlogCategoryUpdateResult,\n\tAPIBrandAssignProductsBody,\n\tAPIBrandAssignProductsResult,\n\tAPIBrandCreateBody,\n\tAPIBrandCreateResult,\n\tAPIBrandDeleteResult,\n\tAPIBrandGetByIdParams,\n\tAPIBrandGetByIdResult,\n\tAPIBrandsBrowseQueryParams,\n\tAPIBrandsBrowseResult,\n\tAPIBrandUpdateBody,\n\tAPIBrandUpdateResult,\n\tAPICartCreateBody,\n\tAPICartCreateResult,\n\tAPICartDeleteResult,\n\tAPICartGetResult,\n\tAPICategoriesBrowseQueryParams,\n\tAPICategoriesBrowseResult,\n\tAPICategoryCreateBody,\n\tAPICategoryCreateResult,\n\tAPICategoryDeleteResult,\n\tAPICategoryGetByIdParams,\n\tAPICategoryGetByIdResult,\n\tAPICategoryUpdateBody,\n\tAPICategoryUpdateResult,\n\tAPICollectionCreateBody,\n\tAPICollectionCreateResult,\n\tAPICollectionDeleteResult,\n\tAPICollectionGetByIdParams,\n\tAPICollectionGetByIdResult,\n\tAPICollectionsBrowseQueryParams,\n\tAPICollectionsBrowseResult,\n\tAPICollectionUpdateBody,\n\tAPICollectionUpdateResult,\n\tAPIContactMessageCreateBody,\n\tAPIContactMessageCreateResult,\n\tAPICouponCreateBody,\n\tAPICouponCreateResult,\n\tAPICouponDeleteResult,\n\tAPICouponGetByIdParams,\n\tAPICouponGetByIdResult,\n\tAPICouponsBrowseQueryParams,\n\tAPICouponsBrowseResult,\n\tAPICouponUpdateBody,\n\tAPICouponUpdateResult,\n\tAPICustomerAddressCreateBody,\n\tAPICustomerAddressCreateResult,\n\tAPICustomerGetByIdParams,\n\tAPICustomerGetByIdResult,\n\tAPICustomerOrdersBrowseQueryParams,\n\tAPICustomerOrdersBrowseResult,\n\tAPICustomersBrowseQueryParams,\n\tAPICustomersBrowseResult,\n\tAPICustomerUpdateBody,\n\tAPICustomerUpdateResult,\n\tAPIEventAttendeesBrowseResult,\n\tAPIEventCreateBody,\n\tAPIEventCreateResult,\n\tAPIEventGetByIdParams,\n\tAPIEventGetByIdResult,\n\tAPIEventsBrowseQueryParams,\n\tAPIEventsBrowseResult,\n\tAPIEventUpdateBody,\n\tAPIEventUpdateResult,\n\tAPIInstaviewImagesBrowseParams,\n\tAPIInstaviewImagesBrowseQueryParams,\n\tAPIInstaviewImagesBrowseResult,\n\tAPIInventoryAdjustBody,\n\tAPIInventoryAdjustResult,\n\tAPIInventoryBrowseQueryParams,\n\tAPIInventoryBrowseResult,\n\tAPILegalPageCreateBody,\n\tAPILegalPageCreateQueryParams,\n\tAPILegalPageCreateResult,\n\tAPILegalPageGetByPathQueryParams,\n\tAPILegalPageGetByPathResult,\n\tAPILegalPagesBrowseQueryParams,\n\tAPILegalPagesBrowseResult,\n\tAPILegalPageUpdateBody,\n\tAPILegalPageUpdateQueryParams,\n\tAPILegalPageUpdateResult,\n\tAPIMeGetResult,\n\tAPIOrderGetByIdParams,\n\tAPIOrderGetByIdResult,\n\tAPIOrderRefundGetParams,\n\tAPIOrderRefundGetResult,\n\tAPIOrderRefundsBrowseQueryParams,\n\tAPIOrderRefundsBrowseResult,\n\tAPIOrderRefundsParams,\n\tAPIOrdersBrowseQueryParams,\n\tAPIOrdersBrowseResult,\n\tAPIOrderUpdateBody,\n\tAPIOrderUpdateResult,\n\tAPIPostCommentCreateBody,\n\tAPIPostCommentCreateResult,\n\tAPIPostCommentsBrowseQueryParams,\n\tAPIPostCommentsBrowseResult,\n\tAPIPostCreateBody,\n\tAPIPostCreateResult,\n\tAPIPostDeleteResult,\n\tAPIPostGetByIdParams,\n\tAPIPostGetByIdResult,\n\tAPIPostsBrowseQueryParams,\n\tAPIPostsBrowseResult,\n\tAPIPostUpdateBody,\n\tAPIPostUpdateResult,\n\tAPIProductBatchBody,\n\tAPIProductBatchResult,\n\tAPIProductCreateBody,\n\tAPIProductCreateResult,\n\tAPIProductDeleteResult,\n\tAPIProductFiltersResult,\n\tAPIProductGetByIdParams,\n\tAPIProductGetByIdResult,\n\tAPIProductReviewCreateBody,\n\tAPIProductReviewCreateResult,\n\tAPIProductReviewsBrowseQueryParams,\n\tAPIProductReviewsBrowseResult,\n\tAPIProductsBrowseQueryParams,\n\tAPIProductsBrowseResult,\n\tAPIProductUpdateBody,\n\tAPIProductUpdateResult,\n\tAPISearchQueryParams,\n\tAPISearchResult,\n\tAPISocialsGetResult,\n\tAPISubscriberCreateBody,\n\tAPISubscriberCreateResult,\n\tAPISubscriberDeleteResult,\n\tAPISupportCaseCreateBody,\n\tAPISupportCaseCreateResult,\n\tAPISupportCaseGetParams,\n\tAPISupportCaseGetResult,\n\tAPISupportCaseMessageCreateBody,\n\tAPISupportCaseMessageCreateResult,\n\tAPISupportCasesBrowseQueryParams,\n\tAPISupportCasesBrowseResult,\n\tAPISupportCaseUpdateBody,\n\tAPISupportCaseUpdateResult,\n\tAPITicketAttendeeGetResult,\n\tAPITicketsGetResult,\n\tAPITicketsUpdateBody,\n\tAPITicketsUpdateResult,\n\tAPIVariantCreateBody,\n\tAPIVariantCreateResult,\n\tAPIVariantGetByIdParams,\n\tAPIVariantGetByIdResult,\n\tAPIVariantUpdateBody,\n\tAPIVariantUpdateResult,\n} from \"../api-types\";\nimport { env } from \"../env\";\nimport { getLogger } from \"../logger\";\nimport type { CommerceConfig } from \"../types\";\n\nexport type APICollectionImportMembershipsBody = { file: File | Blob };\n\nexport type APICollectionImportMembershipsResult = {\n\tok: true;\n\tprocessed: number;\n\tinserted: number;\n\tskipped_existing: number;\n\terrors: Array<{\n\t\trow: number;\n\t\tcollection_slug?: string;\n\t\tproduct_slug?: string;\n\t\treason: string;\n\t}>;\n};\n\nexport class YNSProvider {\n\t#config: CommerceConfig;\n\t#logger = getLogger(\"YNSProvider\");\n\n\tconstructor(config: CommerceConfig = {}) {\n\t\tconst token = config.token ?? env.YNS_API_KEY;\n\t\tconst isStaging = env.YNS_API_KEY?.startsWith(\"sk-s-\");\n\n\t\tif (!token) {\n\t\t\tthrow new Error(\n\t\t\t\t\"YNS API key is required. Set YNS_API_KEY environment variable or pass token in config.\",\n\t\t\t);\n\t\t}\n\t\tconst endpoint = config.endpoint ?? (isStaging ? \"https://yns.cx\" : \"https://yns.store\");\n\n\t\tthis.#config = { version: \"v1\", ...config, token, endpoint };\n\n\t\tthis.#logger.debug(\"YNSProvider initialized\", {\n\t\t\tendpoint,\n\t\t\ttoken: config.token ? `from config` : \"from env\",\n\t\t});\n\t}\n\n\tasync #restRequest<T>(\n\t\tpathname: `/${string}`,\n\t\tmethod: \"GET\" | \"POST\" | \"PATCH\" | \"DELETE\" = \"GET\",\n\t\tbody?: unknown,\n\t): Promise<T> {\n\t\tconst response = await this.#fetchJson(pathname, method, body);\n\t\treturn this.#parseResponse<T>(response, pathname, method);\n\t}\n\n\t/**\n\t * Like {@link #restRequest} but resolves to `null` on a 404 response. For lookups where\n\t * \"not found\" is an expected outcome (e.g. ticket access codes answered with a uniform 404).\n\t */\n\tasync #restRequestNullable<T>(pathname: `/${string}`): Promise<T | null> {\n\t\tconst response = await this.#fetchJson(pathname, \"GET\");\n\t\tif (response.status === 404) {\n\t\t\treturn null;\n\t\t}\n\t\treturn this.#parseResponse<T>(response, pathname, \"GET\");\n\t}\n\n\tasync #fetchJson(\n\t\tpathname: `/${string}`,\n\t\tmethod: \"GET\" | \"POST\" | \"PATCH\" | \"DELETE\",\n\t\tbody?: unknown,\n\t): Promise<Response> {\n\t\tconst logger = this.#logger.getLogger(\"#restRequest\");\n\n\t\tconst endpoint = `${this.#config.endpoint}/api/${this.#config.version}${pathname}`;\n\t\tlogger.debug(`Making ${method} request to YNS API: ${endpoint}`);\n\t\treturn fetch(endpoint, {\n\t\t\tmethod,\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\tAuthorization: `Bearer ${this.#config.token}`,\n\t\t\t},\n\t\t\tbody: body ? JSON.stringify(body) : undefined,\n\t\t});\n\t}\n\n\tasync #parseResponse<T>(response: Response, pathname: `/${string}`, method: string): Promise<T> {\n\t\tconst logger = this.#logger.getLogger(\"#restRequest\");\n\t\tconst endpoint = `${this.#config.endpoint}/api/${this.#config.version}${pathname}`;\n\n\t\tif (!response.ok) {\n\t\t\t// Handle different error types\n\t\t\tconst contentType = response.headers.get(\"content-type\");\n\t\t\tlet errorMessage = `YNS REST request failed: ${method} ${endpoint} ${response.status} ${response.statusText}`;\n\n\t\t\tif (contentType?.includes(\"application/json\")) {\n\t\t\t\ttry {\n\t\t\t\t\tconst errorData = await response.json();\n\t\t\t\t\terrorMessage = errorData.error || errorData.message || errorMessage;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tlogger.error(\"Failed to parse YNS error response as JSON\", error);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst errorText = await response.text();\n\t\t\t\tlogger.error(\n\t\t\t\t\t`YNS API request failed: ${response.status} ${response.statusText}`,\n\t\t\t\t\terrorMessage,\n\t\t\t\t\terrorText,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthrow new Error(errorMessage);\n\t\t}\n\n\t\t// Check if response is JSON before parsing\n\t\tconst contentType = response.headers.get(\"content-type\");\n\t\tif (!contentType?.includes(\"application/json\")) {\n\t\t\tthrow new Error(`YNS API returned ${contentType} instead of JSON for ${pathname}`);\n\t\t}\n\n\t\treturn response.json();\n\t}\n\n\tasync #multipartRequest<T>(pathname: `/${string}`, formData: FormData): Promise<T> {\n\t\tconst logger = this.#logger.getLogger(\"#multipartRequest\");\n\n\t\tconst endpoint = `${this.#config.endpoint}/api/${this.#config.version}${pathname}`;\n\t\tlogger.debug(`Making multipart POST to YNS API: ${endpoint}`);\n\t\tconst response = await fetch(endpoint, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${this.#config.token}`,\n\t\t\t},\n\t\t\tbody: formData,\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst contentType = response.headers.get(\"content-type\");\n\t\t\tlet errorMessage = `YNS REST request failed: POST ${endpoint} ${response.status} ${response.statusText}`;\n\n\t\t\tif (contentType?.includes(\"application/json\")) {\n\t\t\t\ttry {\n\t\t\t\t\tconst errorData = await response.json();\n\t\t\t\t\terrorMessage = errorData.error || errorData.message || errorMessage;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tlogger.error(\"Failed to parse YNS error response as JSON\", error);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst errorText = await response.text();\n\t\t\t\tlogger.error(\n\t\t\t\t\t`YNS API request failed: ${response.status} ${response.statusText}`,\n\t\t\t\t\terrorMessage,\n\t\t\t\t\terrorText,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthrow new Error(errorMessage);\n\t\t}\n\n\t\tconst contentType = response.headers.get(\"content-type\");\n\t\tif (!contentType?.includes(\"application/json\")) {\n\t\t\tthrow new Error(`YNS API returned ${contentType} instead of JSON for ${pathname}`);\n\t\t}\n\n\t\treturn response.json();\n\t}\n\n\tasync meGet(): Promise<APIMeGetResult> {\n\t\tconst logger = this.#logger.getLogger(\"meGet\");\n\t\tlogger.debug(\"Fetching my information\");\n\n\t\tconst pathname = `/me` as const;\n\t\tconst result = await this.#restRequest<APIMeGetResult>(pathname);\n\t\tlogger.debug(\"Received my information:\", result);\n\t\treturn result;\n\t}\n\n\tasync socialsGet(): Promise<APISocialsGetResult> {\n\t\tconst logger = this.#logger.getLogger(\"socialsGet\");\n\t\tlogger.debug(\"Fetching store social links\");\n\n\t\tconst pathname = `/socials` as const;\n\t\tconst result = await this.#restRequest<APISocialsGetResult>(pathname);\n\t\tlogger.debug(\"Received store social links:\", result);\n\t\treturn result;\n\t}\n\n\t// Brands ---------------------------------------------------------------\n\n\tasync brandBrowse(params: APIBrandsBrowseQueryParams = {}): Promise<APIBrandsBrowseResult> {\n\t\tconst queryParams = new URLSearchParams();\n\t\tif (params.limit) queryParams.append(\"limit\", params.limit.toString());\n\t\tif (params.offset) queryParams.append(\"offset\", params.offset.toString());\n\t\tif (params.query) queryParams.append(\"query\", params.query);\n\t\tif (params.active !== undefined) queryParams.append(\"active\", params.active.toString());\n\t\tif (params.lang) queryParams.append(\"lang\", params.lang);\n\t\tconst searchParams = queryParams.size ? `?${queryParams}` : \"\";\n\t\tconst pathname = `/brands${searchParams}` as const;\n\t\treturn this.#restRequest<APIBrandsBrowseResult>(pathname);\n\t}\n\n\tasync brandGet(params: APIBrandGetByIdParams): Promise<APIBrandGetByIdResult | null> {\n\t\tconst pathname = `/brands/${params.idOrSlug}` as const;\n\t\treturn this.#restRequest<APIBrandGetByIdResult>(pathname);\n\t}\n\n\tasync brandCreate(body: APIBrandCreateBody): Promise<APIBrandCreateResult> {\n\t\treturn this.#restRequest<APIBrandCreateResult>(\"/brands\", \"POST\", body);\n\t}\n\n\tasync brandUpdate(params: APIBrandGetByIdParams, body: APIBrandUpdateBody): Promise<APIBrandUpdateResult> {\n\t\tconst pathname = `/brands/${params.idOrSlug}` as const;\n\t\treturn this.#restRequest<APIBrandUpdateResult>(pathname, \"PATCH\", body);\n\t}\n\n\tasync brandDelete(params: APIBrandGetByIdParams): Promise<APIBrandDeleteResult> {\n\t\tconst pathname = `/brands/${params.idOrSlug}` as const;\n\t\treturn this.#restRequest<APIBrandDeleteResult>(pathname, \"DELETE\");\n\t}\n\n\tasync brandAssignProducts(\n\t\tparams: APIBrandGetByIdParams,\n\t\tbody: APIBrandAssignProductsBody,\n\t): Promise<APIBrandAssignProductsResult> {\n\t\tconst pathname = `/brands/${params.idOrSlug}/products` as const;\n\t\treturn this.#restRequest<APIBrandAssignProductsResult>(pathname, \"POST\", body);\n\t}\n\n\t// Order refunds --------------------------------------------------------\n\n\tasync orderRefundsBrowse(\n\t\tparams: APIOrderRefundsParams & APIOrderRefundsBrowseQueryParams,\n\t): Promise<APIOrderRefundsBrowseResult> {\n\t\tconst queryParams = new URLSearchParams();\n\t\tif (params.limit) queryParams.append(\"limit\", params.limit.toString());\n\t\tif (params.offset) queryParams.append(\"offset\", params.offset.toString());\n\t\tconst searchParams = queryParams.size ? `?${queryParams}` : \"\";\n\t\tconst pathname = `/orders/${params.id}/refunds${searchParams}` as const;\n\t\treturn this.#restRequest<APIOrderRefundsBrowseResult>(pathname);\n\t}\n\n\tasync orderRefundGet(params: APIOrderRefundGetParams): Promise<APIOrderRefundGetResult | null> {\n\t\tconst pathname = `/orders/${params.id}/refunds/${params.refundId}` as const;\n\t\treturn this.#restRequest<APIOrderRefundGetResult>(pathname);\n\t}\n\n\t// Product bulk ---------------------------------------------------------\n\n\tasync productBatch(body: APIProductBatchBody): Promise<APIProductBatchResult> {\n\t\treturn this.#restRequest<APIProductBatchResult>(\"/products/batch\", \"POST\", body);\n\t}\n\n\t// Cart -----------------------------------------------------------------\n\n\tasync cartDelete(params: { cartId: string }): Promise<APICartDeleteResult> {\n\t\tconst pathname = `/carts/${params.cartId}` as const;\n\t\treturn this.#restRequest<APICartDeleteResult>(pathname, \"DELETE\");\n\t}\n\n\tasync productBrowse(params: APIProductsBrowseQueryParams): Promise<APIProductsBrowseResult> {\n\t\tconst logger = this.#logger.getLogger(\"productBrowse\");\n\t\tlogger.debug(\"Browsing products with params:\", params);\n\n\t\tconst queryParams = new URLSearchParams();\n\t\tif (params.limit) queryParams.append(\"limit\", params.limit.toString());\n\t\tif (params.offset) queryParams.append(\"offset\", params.offset.toString());\n\t\tif (params.category) queryParams.append(\"category\", params.category);\n\t\tif (params.collection) queryParams.append(\"collection\", params.collection);\n\t\tif (params.brand) queryParams.append(\"brand\", params.brand);\n\t\tif (params.priceMin !== undefined) queryParams.append(\"priceMin\", params.priceMin.toString());\n\t\tif (params.priceMax !== undefined) queryParams.append(\"priceMax\", params.priceMax.toString());\n\t\tif (params.vts) queryParams.append(\"vts\", params.vts);\n\t\tif (params.query) queryParams.append(\"query\", params.query);\n\t\tif (params.active !== undefined) queryParams.append(\"active\", params.active.toString());\n\t\tif (params.orderBy) queryParams.append(\"orderBy\", params.orderBy);\n\t\tif (params.orderDirection) queryParams.append(\"orderDirection\", params.orderDirection);\n\n\t\tconst searchParams = queryParams.size ? `?${queryParams}` : \"\";\n\t\tconst pathname = `/products${searchParams}` as const;\n\t\tlogger.debug(\"Constructed pathname:\", pathname);\n\t\tconst result = await this.#restRequest<APIProductsBrowseResult>(pathname);\n\t\tlogger.debug(\"Received product browse result:\", { meta: result.meta });\n\t\treturn result;\n\t}\n\n\t/**\n\t * Available storefront filter facets for the store: price bounds, variant\n\t * types/values, and active categories, collections, and brands. Pair with\n\t * `productBrowse`'s `collection`, `brand`, `priceMin`/`priceMax`, and `vts`\n\t * params to build a filter UI.\n\t */\n\tasync productFilters(): Promise<APIProductFiltersResult> {\n\t\tconst result = await this.#restRequest<APIProductFiltersResult>(\"/products/filters\");\n\t\treturn result;\n\t}\n\n\tasync productGet(params: APIProductGetByIdParams): Promise<APIProductGetByIdResult | null> {\n\t\tconst pathname = `/products/${params.idOrSlug}` as const;\n\n\t\tconst result = await this.#restRequest<APIProductGetByIdResult>(pathname);\n\n\t\tif (!result) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tasync orderBrowse(params: APIOrdersBrowseQueryParams): Promise<APIOrdersBrowseResult> {\n\t\tconst logger = this.#logger.getLogger(\"orderBrowse\");\n\t\tlogger.debug(\"Browsing orders with params:\", params);\n\n\t\tconst queryParams = new URLSearchParams();\n\n\t\tif (params.limit) queryParams.append(\"limit\", params.limit.toString());\n\t\tif (params.offset) queryParams.append(\"offset\", params.offset.toString());\n\n\t\tconst searchParams = queryParams.size ? `?${queryParams}` : \"\";\n\t\tconst pathname = `/orders${searchParams}` as const;\n\t\tlogger.debug(\"Constructed pathname:\", pathname);\n\t\tconst result = await this.#restRequest<APIOrdersBrowseResult>(pathname);\n\t\tlogger.debug(\"Received orders browse result:\", { meta: result.meta });\n\t\treturn result;\n\t}\n\n\tasync orderGet(params: APIOrderGetByIdParams): Promise<APIOrderGetByIdResult | null> {\n\t\tconst pathname = `/orders/${params.id}` as const;\n\n\t\tconst result = await this.#restRequest<APIOrderGetByIdResult>(pathname);\n\n\t\tif (!result) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t// @todo\n\t// async cartAdd(params: APICartAddBody): Promise<APICartAddResult> {\n\t// \tconst body = {\n\t// \t\tvariantId: params.variantId,\n\t// \t\tcartId: params.cartId,\n\t// \t\tquantity: params.quantity,\n\t// \t\tsubscriptionId: params.subscriptionId,\n\t// \t};\n\n\t// \tconst result = await this.#restRequest<APICartCreateResult>(\"/carts\", \"PATCH\", body);\n\t// \treturn result;\n\t// }\n\n\tasync cartUpsert(body: APICartCreateBody): Promise<APICartCreateResult> {\n\t\tconst result = await this.#restRequest<APICartCreateResult>(\"/carts\", \"POST\", body);\n\t\treturn result;\n\t}\n\n\t/**\n\t * Add a configured bundle to the cart in one call. `selections` are the customer's per-group\n\t * choices; always-included (forced) items may be omitted — the server fills them in and\n\t * validates the rest against the bundle's groups. Omit `cartId` to start a new cart. The\n\t * returned cart prices the bundle line (componentTotal × (1 − discount)).\n\t */\n\tasync cartAddBundle(params: {\n\t\tbundleId: string;\n\t\tselections: NonNullable<APICartCreateBody[\"selections\"]>;\n\t\tcartId?: string;\n\t\tcurrency?: string;\n\t}): Promise<APICartCreateResult> {\n\t\tconst body: APICartCreateBody = {\n\t\t\tbundleId: params.bundleId,\n\t\t\tselections: params.selections,\n\t\t\t...(params.cartId ? { cartId: params.cartId } : {}),\n\t\t\t...(params.currency ? { currency: params.currency } : {}),\n\t\t};\n\t\tconst result = await this.#restRequest<APICartCreateResult>(\"/carts\", \"POST\", body);\n\t\treturn result;\n\t}\n\n\tasync cartRemoveItem(params: { cartId: string; variantId: string }): Promise<APICartGetResult> {\n\t\tconst pathname = `/carts/${params.cartId}/line-items/${params.variantId}` as const;\n\t\treturn this.#restRequest<APICartGetResult>(pathname, \"DELETE\");\n\t}\n\n\tasync cartGet(params: { cartId: string }): Promise<APICartGetResult | null> {\n\t\tconst pathname = `/carts/${params.cartId}` as const;\n\t\tconst result = await this.#restRequest<APICartGetResult>(pathname);\n\t\treturn result;\n\t}\n\n\tasync couponBrowse(params: APICouponsBrowseQueryParams = {}): Promise<APICouponsBrowseResult> {\n\t\tconst queryParams = new URLSearchParams();\n\t\tif (params.limit) queryParams.append(\"limit\", params.limit.toString());\n\t\tif (params.offset) queryParams.append(\"offset\", params.offset.toString());\n\t\tif (params.query) queryParams.append(\"query\", params.query);\n\n\t\tconst searchParams = queryParams.size ? `?${queryParams}` : \"\";\n\t\tconst pathname = `/coupons${searchParams}` as const;\n\n\t\treturn this.#restRequest<APICouponsBrowseResult>(pathname);\n\t}\n\n\t/** Look up a coupon by its UUID or its code. Resolves to `null` when not found. */\n\tasync couponGet(params: APICouponGetByIdParams): Promise<APICouponGetByIdResult | null> {\n\t\tconst pathname = `/coupons/${params.idOrCode}` as const;\n\t\treturn this.#restRequestNullable<APICouponGetByIdResult>(pathname);\n\t}\n\n\tasync couponCreate(body: APICouponCreateBody): Promise<APICouponCreateResult> {\n\t\treturn this.#restRequest<APICouponCreateResult>(\"/coupons\", \"POST\", body);\n\t}\n\n\tasync couponUpdate(\n\t\tparams: APICouponGetByIdParams,\n\t\tbody: APICouponUpdateBody,\n\t): Promise<APICouponUpdateResult> {\n\t\tconst pathname = `/coupons/${params.idOrCode}` as const;\n\t\treturn this.#restRequest<APICouponUpdateResult>(pathname, \"PATCH\", body);\n\t}\n\n\tasync couponDelete(params: APICouponGetByIdParams): Promise<APICouponDeleteResult> {\n\t\tconst pathname = `/coupons/${params.idOrCode}` as const;\n\t\treturn this.#restRequest<APICouponDeleteResult>(pathname, \"DELETE\");\n\t}\n\n\t/** List the store's support cases (merchant ↔ YNS support), newest activity first. */\n\tasync supportCaseBrowse(\n\t\tparams: APISupportCasesBrowseQueryParams = {},\n\t): Promise<APISupportCasesBrowseResult> {\n\t\tconst queryParams = new URLSearchParams();\n\t\tif (params.limit) queryParams.append(\"limit\", params.limit.toString());\n\t\tif (params.offset) queryParams.append(\"offset\", params.offset.toString());\n\t\tif (params.query) queryParams.append(\"query\", params.query);\n\t\tif (params.status) queryParams.append(\"status\", params.status);\n\t\tif (params.severity) queryParams.append(\"severity\", params.severity);\n\n\t\tconst searchParams = queryParams.size ? `?${queryParams}` : \"\";\n\t\tconst pathname = `/support-cases${searchParams}` as const;\n\n\t\treturn this.#restRequest<APISupportCasesBrowseResult>(pathname);\n\t}\n\n\t/**\n\t * Look up a case with its message thread by UUID or case number (\"123\" or \"000123\").\n\t * Resolves to `null` when not found. Internal YNS notes are never included.\n\t */\n\tasync supportCaseGet(params: APISupportCaseGetParams): Promise<APISupportCaseGetResult | null> {\n\t\tconst pathname = `/support-cases/${params.idOrNumber}` as const;\n\t\treturn this.#restRequestNullable<APISupportCaseGetResult>(pathname);\n\t}\n\n\t/** Open a support case with the YNS team. Omit `subject` to have one generated from the description. */\n\tasync supportCaseCreate(body: APISupportCaseCreateBody): Promise<APISupportCaseCreateResult> {\n\t\treturn this.#restRequest<APISupportCaseCreateResult>(\"/support-cases\", \"POST\", body);\n\t}\n\n\t/** Close (`status: \"closed\"`) or reopen (`status: \"open\"`) a case. */\n\tasync supportCaseUpdate(\n\t\tparams: APISupportCaseGetParams,\n\t\tbody: APISupportCaseUpdateBody,\n\t): Promise<APISupportCaseUpdateResult> {\n\t\tconst pathname = `/support-cases/${params.idOrNumber}` as const;\n\t\treturn this.#restRequest<APISupportCaseUpdateResult>(pathname, \"PATCH\", body);\n\t}\n\n\t/** Add a merchant-side reply to the case thread; replying reopens a closed or answered case. */\n\tasync supportCaseReply(\n\t\tparams: APISupportCaseGetParams,\n\t\tbody: APISupportCaseMessageCreateBody,\n\t): Promise<APISupportCaseMessageCreateResult> {\n\t\tconst pathname = `/support-cases/${params.idOrNumber}/messages` as const;\n\t\treturn this.#restRequest<APISupportCaseMessageCreateResult>(pathname, \"POST\", body);\n\t}\n\n\tasync collectionGet(params: APICollectionGetByIdParams): Promise<APICollectionGetByIdResult | null> {\n\t\tconst pathname = `/collections/${params.idOrSlug}` as const;\n\n\t\tconst result = await this.#restRequest<APICollectionGetByIdResult>(pathname);\n\t\treturn result;\n\t}\n\n\tasync collectionBrowse(params: APICollectionsBrowseQueryParams): Promise<APICollectionsBrowseResult> {\n\t\tconst queryParams = new URLSearchParams();\n\t\tif (params.limit) queryParams.append(\"limit\", params.limit.toString());\n\t\tif (params.offset) queryParams.append(\"offset\", params.offset.toString());\n\t\tif (params.query) queryParams.append(\"query\", params.query);\n\t\tif (params.active !== undefined) queryParams.append(\"active\", params.active.toString());\n\t\tif (params.group) queryParams.append(\"group\", params.group);\n\n\t\tconst searchParams = queryParams.size ? `?${queryParams}` : \"\";\n\t\tconst pathname = `/collections${searchParams}` as const;\n\n\t\tconst result = await this.#restRequest<APICollectionsBrowseResult>(pathname);\n\t\treturn result;\n\t}\n\n\tasync collectionCreate(body: APICollectionCreateBody): Promise<APICollectionCreateResult> {\n\t\treturn this.#restRequest<APICollectionCreateResult>(\"/collections\", \"POST\", body);\n\t}\n\n\tasync collectionUpdate(\n\t\tparams: APICollectionGetByIdParams,\n\t\tbody: APICollectionUpdateBody,\n\t): Promise<APICollectionUpdateResult> {\n\t\tconst pathname = `/collections/${params.idOrSlug}` as const;\n\t\treturn this.#restRequest<APICollectionUpdateResult>(pathname, \"PATCH\", body);\n\t}\n\n\tasync collectionDelete(params: APICollectionGetByIdParams): Promise<APICollectionDeleteResult> {\n\t\tconst pathname = `/collections/${params.idOrSlug}` as const;\n\t\treturn this.#restRequest<APICollectionDeleteResult>(pathname, \"DELETE\");\n\t}\n\n\tasync collectionImportMemberships(\n\t\tbody: APICollectionImportMembershipsBody,\n\t): Promise<APICollectionImportMembershipsResult> {\n\t\tconst formData = new FormData();\n\t\tformData.append(\"file\", body.file);\n\t\treturn this.#multipartRequest<APICollectionImportMembershipsResult>(\n\t\t\t\"/collections/import-memberships\",\n\t\t\tformData,\n\t\t);\n\t}\n\n\tasync categoryGet(params: APICategoryGetByIdParams): Promise<APICategoryGetByIdResult | null> {\n\t\tconst pathname = `/categories/${params.idOrSlug}` as const;\n\n\t\tconst result = await this.#restRequest<APICategoryGetByIdResult>(pathname);\n\t\treturn result;\n\t}\n\n\tasync categoriesBrowse(params: APICategoriesBrowseQueryParams): Promise<APICategoriesBrowseResult> {\n\t\tconst queryParams = new URLSearchParams();\n\t\tif (params.limit) queryParams.append(\"limit\", params.limit.toString());\n\t\tif (params.offset) queryParams.append(\"offset\", params.offset.toString());\n\t\tif (params.query) queryParams.append(\"query\", params.query);\n\t\tif (params.active !== undefined) queryParams.append(\"active\", params.active.toString());\n\n\t\tconst searchParams = queryParams.size ? `?${queryParams}` : \"\";\n\t\tconst pathname = `/categories${searchParams}` as const;\n\n\t\tconst result = await this.#restRequest<APICategoriesBrowseResult>(pathname);\n\t\treturn result;\n\t}\n\n\t// ============================================\n\t// Posts\n\t// ============================================\n\n\tasync postBrowse(params: APIPostsBrowseQueryParams = {}): Promise<APIPostsBrowseResult> {\n\t\tconst queryParams = new URLSearchParams();\n\t\tif (params.limit) queryParams.append(\"limit\", params.limit.toString());\n\t\tif (params.offset) queryParams.append(\"offset\", params.offset.toString());\n\t\tif (params.query) queryParams.append(\"query\", params.query);\n\t\tif (params.active !== undefined) queryParams.append(\"active\", params.active.toString());\n\t\tif (params.tag) queryParams.append(\"tag\", params.tag);\n\t\tif (params.categoryId) queryParams.append(\"categoryId\", params.categoryId);\n\n\t\tconst searchParams = queryParams.size ? `?${queryParams}` : \"\";\n\t\tconst pathname = `/posts${searchParams}` as const;\n\n\t\treturn this.#restRequest<APIPostsBrowseResult>(pathname);\n\t}\n\n\tasync postGet(params: APIPostGetByIdParams): Promise<APIPostGetByIdResult | null> {\n\t\tconst pathname = `/posts/${params.idOrSlug}` as const;\n\t\treturn this.#restRequest<APIPostGetByIdResult>(pathname);\n\t}\n\n\tasync postCreate(body: APIPostCreateBody): Promise<APIPostCreateResult> {\n\t\treturn this.#restRequest<APIPostCreateResult>(\"/posts\", \"POST\", body);\n\t}\n\n\tasync postUpdate(params: APIPostGetByIdParams, body: APIPostUpdateBody): Promise<APIPostUpdateResult> {\n\t\tconst pathname = `/posts/${params.idOrSlug}` as const;\n\t\treturn this.#restRequest<APIPostUpdateResult>(pathname, \"PATCH\", body);\n\t}\n\n\tasync postDelete(params: APIPostGetByIdParams): Promise<APIPostDeleteResult> {\n\t\tconst pathname = `/posts/${params.idOrSlug}` as const;\n\t\treturn this.#restRequest<APIPostDeleteResult>(pathname, \"DELETE\");\n\t}\n\n\tasync postCommentsBrowse(\n\t\tparams: APIPostGetByIdParams,\n\t\tqueryParams: APIPostCommentsBrowseQueryParams = {},\n\t): Promise<APIPostCommentsBrowseResult> {\n\t\tconst urlParams = new URLSearchParams();\n\t\tif (queryParams.limit) urlParams.append(\"limit\", queryParams.limit.toString());\n\t\tif (queryParams.offset) urlParams.append(\"offset\", queryParams.offset.toString());\n\n\t\tconst searchParams = urlParams.size ? `?${urlParams}` : \"\";\n\t\tconst pathname = `/posts/${params.idOrSlug}/comments${searchParams}` as const;\n\n\t\treturn this.#restRequest<APIPostCommentsBrowseResult>(pathname);\n\t}\n\n\tasync postCommentCreate(\n\t\tparams: APIPostGetByIdParams,\n\t\tbody: APIPostCommentCreateBody,\n\t): Promise<APIPostCommentCreateResult> {\n\t\tconst pathname = `/posts/${params.idOrSlug}/comments` as const;\n\t\treturn this.#restRequest<APIPostCommentCreateResult>(pathname, \"POST\", body);\n\t}\n\n\t// ============================================\n\t// Blog Categories\n\t// ============================================\n\n\tasync blogCategoryBrowse(\n\t\tparams: APIBlogCategoriesBrowseQueryParams = {},\n\t): Promise<APIBlogCategoriesBrowseResult> {\n\t\tconst queryParams = new URLSearchParams();\n\t\tif (params.limit) queryParams.append(\"limit\", params.limit.toString());\n\t\tif (params.offset) queryParams.append(\"offset\", params.offset.toString());\n\t\tif (params.query) queryParams.append(\"query\", params.query);\n\t\tif (params.active !== undefined) queryParams.append(\"active\", params.active.toString());\n\n\t\tconst searchParams = queryParams.size ? `?${queryParams}` : \"\";\n\t\tconst pathname = `/blog-categories${searchParams}` as const;\n\n\t\treturn this.#restRequest<APIBlogCategoriesBrowseResult>(pathname);\n\t}\n\n\tasync blogCategoryGet(params: APIBlogCategoryGetByIdParams): Promise<APIBlogCategoryGetByIdResult | null> {\n\t\tconst pathname = `/blog-categories/${params.idOrSlug}` as const;\n\t\treturn this.#restRequest<APIBlogCategoryGetByIdResult>(pathname);\n\t}\n\n\tasync blogCategoryCreate(body: APIBlogCategoryCreateBody): Promise<APIBlogCategoryCreateResult> {\n\t\treturn this.#restRequest<APIBlogCategoryCreateResult>(\"/blog-categories\", \"POST\", body);\n\t}\n\n\tasync blogCategoryUpdate(\n\t\tparams: APIBlogCategoryGetByIdParams,\n\t\tbody: APIBlogCategoryUpdateBody,\n\t): Promise<APIBlogCategoryUpdateResult> {\n\t\tconst pathname = `/blog-categories/${params.idOrSlug}` as const;\n\t\treturn this.#restRequest<APIBlogCategoryUpdateResult>(pathname, \"PATCH\", body);\n\t}\n\n\tasync blogCategoryDelete(params: APIBlogCategoryGetByIdParams): Promise<APIBlogCategoryDeleteResult> {\n\t\tconst pathname = `/blog-categories/${params.idOrSlug}` as const;\n\t\treturn this.#restRequest<APIBlogCategoryDeleteResult>(pathname, \"DELETE\");\n\t}\n\n\t// ============================================\n\t// Customers\n\t// ============================================\n\n\tasync customerBrowse(params: APICustomersBrowseQueryParams = {}): Promise<APICustomersBrowseResult> {\n\t\tconst queryParams = new URLSearchParams();\n\t\tif (params.limit) queryParams.append(\"limit\", params.limit.toString());\n\t\tif (params.offset) queryParams.append(\"offset\", params.offset.toString());\n\t\tif (params.search) queryParams.append(\"search\", params.search);\n\n\t\tconst searchParams = queryParams.size ? `?${queryParams}` : \"\";\n\t\tconst pathname = `/customers${searchParams}` as const;\n\n\t\treturn this.#restRequest<APICustomersBrowseResult>(pathname);\n\t}\n\n\tasync customerGet(params: APICustomerGetByIdParams): Promise<APICustomerGetByIdResult | null> {\n\t\tconst pathname = `/customers/${params.id}` as const;\n\t\treturn this.#restRequest<APICustomerGetByIdResult>(pathname);\n\t}\n\n\tasync customerUpdate(\n\t\tparams: APICustomerGetByIdParams,\n\t\tbody: APICustomerUpdateBody,\n\t): Promise<APICustomerUpdateResult> {\n\t\tconst pathname = `/customers/${params.id}` as const;\n\t\treturn this.#restRequest<APICustomerUpdateResult>(pathname, \"PATCH\", body);\n\t}\n\n\tasync customerAddressCreate(\n\t\tparams: APICustomerGetByIdParams,\n\t\tbody: APICustomerAddressCreateBody,\n\t): Promise<APICustomerAddressCreateResult> {\n\t\tconst pathname = `/customers/${params.id}/addresses` as const;\n\t\treturn this.#restRequest<APICustomerAddressCreateResult>(pathname, \"POST\", body);\n\t}\n\n\tasync customerAddressDelete(params: { customerId: string; addressId: string }): Promise<void> {\n\t\tconst pathname = `/customers/${params.customerId}/addresses/${params.addressId}` as const;\n\t\tawait this.#restRequest<unknown>(pathname, \"DELETE\");\n\t}\n\n\tasync customerOrdersBrowse(\n\t\tparams: APICustomerGetByIdParams,\n\t\tqueryParams: APICustomerOrdersBrowseQueryParams = {},\n\t): Promise<APICustomerOrdersBrowseResult> {\n\t\tconst urlParams = new URLSearchParams();\n\t\tif (queryParams.limit) urlParams.append(\"limit\", queryParams.limit.toString());\n\t\tif (queryParams.offset) urlParams.append(\"offset\", queryParams.offset.toString());\n\n\t\tconst searchParams = urlParams.size ? `?${urlParams}` : \"\";\n\t\tconst pathname = `/customers/${params.id}/orders${searchParams}` as const;\n\n\t\treturn this.#restRequest<APICustomerOrdersBrowseResult>(pathname);\n\t}\n\n\t// ============================================\n\t// Inventory\n\t// ============================================\n\n\tasync inventoryBrowse(params: APIInventoryBrowseQueryParams = {}): Promise<APIInventoryBrowseResult> {\n\t\tconst queryParams = new URLSearchParams();\n\t\tif (params.limit) queryParams.append(\"limit\", params.limit.toString());\n\t\tif (params.cursor) queryParams.append(\"cursor\", params.cursor);\n\t\tif (params.lowStock !== undefined) queryParams.append(\"lowStock\", params.lowStock.toString());\n\n\t\tconst searchParams = queryParams.size ? `?${queryParams}` : \"\";\n\t\tconst pathname = `/inventory${searchParams}` as const;\n\n\t\treturn this.#restRequest<APIInventoryBrowseResult>(pathname);\n\t}\n\n\tasync inventoryAdjust(sku: string, body: APIInventoryAdjustBody): Promise<APIInventoryAdjustResult> {\n\t\tconst pathname = `/inventory/${encodeURIComponent(sku)}/adjust` as const;\n\t\treturn this.#restRequest<APIInventoryAdjustResult>(pathname, \"POST\", body);\n\t}\n\n\t// ============================================\n\t// Variants\n\t// ============================================\n\n\tasync variantGet(params: APIVariantGetByIdParams): Promise<APIVariantGetByIdResult | null> {\n\t\tconst pathname = `/variants/${params.idOrSku}` as const;\n\t\treturn this.#restRequest<APIVariantGetByIdResult>(pathname);\n\t}\n\n\tasync variantUpdate(\n\t\tparams: APIVariantGetByIdParams,\n\t\tbody: APIVariantUpdateBody,\n\t): Promise<APIVariantUpdateResult> {\n\t\tconst pathname = `/variants/${params.idOrSku}` as const;\n\t\treturn this.#restRequest<APIVariantUpdateResult>(pathname, \"PATCH\", body);\n\t}\n\n\tasync variantDelete(params: APIVariantGetByIdParams): Promise<void> {\n\t\tconst pathname = `/variants/${params.idOrSku}` as const;\n\t\tawait this.#restRequest<unknown>(pathname, \"DELETE\");\n\t}\n\n\tasync variantCreate(productId: string, body: APIVariantCreateBody): Promise<APIVariantCreateResult> {\n\t\tconst pathname = `/products/${productId}/variants` as const;\n\t\treturn this.#restRequest<APIVariantCreateResult>(pathname, \"POST\", body);\n\t}\n\n\t// ============================================\n\t// Subscribers\n\t// ============================================\n\n\tasync subscriberCreate(body: APISubscriberCreateBody): Promise<APISubscriberCreateResult> {\n\t\treturn this.#restRequest<APISubscriberCreateResult>(\"/subscribers\", \"POST\", body);\n\t}\n\n\tasync subscriberDelete(email: string): Promise<APISubscriberDeleteResult> {\n\t\tconst pathname = `/subscribers?email=${encodeURIComponent(email)}` as const;\n\t\treturn this.#restRequest<APISubscriberDeleteResult>(pathname, \"DELETE\");\n\t}\n\n\t// ============================================\n\t// Contact Messages\n\t// ============================================\n\n\tasync contactMessageCreate(body: APIContactMessageCreateBody): Promise<APIContactMessageCreateResult> {\n\t\treturn this.#restRequest<APIContactMessageCreateResult>(\"/contact-messages\", \"POST\", body);\n\t}\n\n\t// ============================================\n\t// Product mutations\n\t// ============================================\n\n\tasync productCreate(body: APIProductCreateBody): Promise<APIProductCreateResult> {\n\t\treturn this.#restRequest<APIProductCreateResult>(\"/products\", \"POST\", body);\n\t}\n\n\tasync productUpdate(\n\t\tparams: APIProductGetByIdParams,\n\t\tbody: APIProductUpdateBody,\n\t): Promise<APIProductUpdateResult> {\n\t\tconst pathname = `/products/${params.idOrSlug}` as const;\n\t\treturn this.#restRequest<APIProductUpdateResult>(pathname, \"PATCH\", body);\n\t}\n\n\tasync productDelete(params: APIProductGetByIdParams): Promise<APIProductDeleteResult> {\n\t\tconst pathname = `/products/${params.idOrSlug}` as const;\n\t\treturn this.#restRequest<APIProductDeleteResult>(pathname, \"DELETE\");\n\t}\n\n\t// ============================================\n\t// Product Reviews\n\t// ============================================\n\n\tasync productReviewsBrowse(\n\t\tparams: APIProductGetByIdParams,\n\t\tqueryParams: APIProductReviewsBrowseQueryParams = {},\n\t): Promise<APIProductReviewsBrowseResult> {\n\t\tconst urlParams = new URLSearchParams();\n\t\tif (queryParams.limit) urlParams.append(\"limit\", queryParams.limit.toString());\n\t\tif (queryParams.offset) urlParams.append(\"offset\", queryParams.offset.toString());\n\n\t\tconst searchParams = urlParams.size ? `?${urlParams}` : \"\";\n\t\tconst pathname = `/products/${params.idOrSlug}/reviews${searchParams}` as const;\n\n\t\treturn this.#restRequest<APIProductReviewsBrowseResult>(pathname);\n\t}\n\n\tasync productReviewCreate(\n\t\tparams: APIProductGetByIdParams,\n\t\tbody: APIProductReviewCreateBody,\n\t): Promise<APIProductReviewCreateResult> {\n\t\tconst pathname = `/products/${params.idOrSlug}/reviews` as const;\n\t\treturn this.#restRequest<APIProductReviewCreateResult>(pathname, \"POST\", body);\n\t}\n\n\t// ============================================\n\t// Events (products flagged `flags.event` with a single non-shippable ticket variant)\n\t// ============================================\n\n\tasync eventBrowse(params: APIEventsBrowseQueryParams = {}): Promise<APIEventsBrowseResult> {\n\t\tconst logger = this.#logger.getLogger(\"eventBrowse\");\n\t\tconst queryParams = new URLSearchParams();\n\t\tif (params.offset !== undefined) queryParams.append(\"offset\", params.offset.toString());\n\t\tif (params.limit !== undefined) queryParams.append(\"limit\", params.limit.toString());\n\n\t\tconst searchParams = queryParams.size ? `?${queryParams}` : \"\";\n\t\tconst pathname = `/events${searchParams}` as const;\n\t\tlogger.debug(\"Browsing events:\", pathname);\n\t\treturn this.#restRequest<APIEventsBrowseResult>(pathname);\n\t}\n\n\tasync eventGet(params: APIEventGetByIdParams): Promise<APIEventGetByIdResult> {\n\t\tconst pathname = `/events/${params.idOrSlug}` as const;\n\t\treturn this.#restRequest<APIEventGetByIdResult>(pathname);\n\t}\n\n\tasync eventCreate(body: APIEventCreateBody): Promise<APIEventCreateResult> {\n\t\treturn this.#restRequest<APIEventCreateResult>(\"/events\", \"POST\", body);\n\t}\n\n\tasync eventUpdate(params: APIEventGetByIdParams, body: APIEventUpdateBody): Promise<APIEventUpdateResult> {\n\t\tconst pathname = `/events/${params.idOrSlug}` as const;\n\t\treturn this.#restRequest<APIEventUpdateResult>(pathname, \"PATCH\", body);\n\t}\n\n\tasync eventAttendeesBrowse(params: APIEventGetByIdParams): Promise<APIEventAttendeesBrowseResult> {\n\t\tconst pathname = `/events/${params.idOrSlug}/attendees` as const;\n\t\treturn this.#restRequest<APIEventAttendeesBrowseResult>(pathname);\n\t}\n\n\t// ============================================\n\t// Tickets (no-login buyer/attendee access to purchased event tickets)\n\t// ============================================\n\n\t/**\n\t * Buyer ticket lookup: the order's 6-character access code plus the purchase email.\n\t * Resolves to `null` on mismatch — the API answers a uniform 404 for an unknown code,\n\t * an email that doesn't match, or an order without tickets.\n\t */\n\tasync ticketsGet(params: { code: string; email: string }): Promise<APITicketsGetResult | null> {\n\t\tconst logger = this.#logger.getLogger(\"ticketsGet\");\n\t\tconst queryParams = new URLSearchParams({ email: params.email });\n\t\tconst pathname = `/tickets/${encodeURIComponent(params.code)}?${queryParams}` as const;\n\t\tlogger.debug(\"Fetching ticket bundle:\", pathname);\n\t\treturn this.#restRequestNullable<APITicketsGetResult>(pathname);\n\t}\n\n\t/**\n\t * Buyer bulk-edit of attendee names/emails. The body carries the purchase email; seat\n\t * tokens not belonging to the order are silently ignored. Throws on code/email mismatch\n\t * (404) or when the order is cancelled/refunded (409).\n\t */\n\tasync ticketsUpdate(params: { code: string }, body: APITicketsUpdateBody): Promise<APITicketsUpdateResult> {\n\t\tconst pathname = `/tickets/${encodeURIComponent(params.code)}` as const;\n\t\treturn this.#restRequest<APITicketsUpdateResult>(pathname, \"PATCH\", body);\n\t}\n\n\t/**\n\t * View-only attendee ticket by per-seat token (the capability embedded in the attendee\n\t * link/QR). Resolves to `null` for an unknown token. Attendee details can only be edited\n\t * by the buyer via {@link ticketsUpdate} — attendee links must not escalate.\n\t */\n\tasync ticketAttendeeGet(params: { token: string }): Promise<APITicketAttendeeGetResult | null> {\n\t\tconst pathname = `/tickets/attendee/${encodeURIComponent(params.token)}` as const;\n\t\treturn this.#restRequestNullable<APITicketAttendeeGetResult>(pathname);\n\t}\n\n\t// ============================================\n\t// Category mutations\n\t// ============================================\n\n\tasync categoryCreate(body: APICategoryCreateBody): Promise<APICategoryCreateResult> {\n\t\treturn this.#restRequest<APICategoryCreateResult>(\"/categories\", \"POST\", body);\n\t}\n\n\tasync categoryUpdate(\n\t\tparams: APICategoryGetByIdParams,\n\t\tbody: APICategoryUpdateBody,\n\t): Promise<APICategoryUpdateResult> {\n\t\tconst pathname = `/categories/${params.idOrSlug}` as const;\n\t\treturn this.#restRequest<APICategoryUpdateResult>(pathname, \"PATCH\", body);\n\t}\n\n\tasync categoryDelete(params: APICategoryGetByIdParams): Promise<APICategoryDeleteResult> {\n\t\tconst pathname = `/categories/${params.idOrSlug}` as const;\n\t\treturn this.#restRequest<APICategoryDeleteResult>(pathname, \"DELETE\");\n\t}\n\n\t// ============================================\n\t// Order mutations\n\t// ============================================\n\n\tasync orderUpdate(params: APIOrderGetByIdParams, body: APIOrderUpdateBody): Promise<APIOrderUpdateResult> {\n\t\tconst pathname = `/orders/${params.id}` as const;\n\t\treturn this.#restRequest<APIOrderUpdateResult>(pathname, \"PATCH\", body);\n\t}\n\n\t// ============================================\n\t// Legal Pages\n\t// ============================================\n\n\tasync legalPageBrowse(\n\t\tqueryParams: APILegalPagesBrowseQueryParams = {},\n\t): Promise<APILegalPagesBrowseResult> {\n\t\treturn this.request<APILegalPagesBrowseResult>(\"/legal-pages\", {\n\t\t\tquery: queryParams,\n\t\t});\n\t}\n\n\tasync legalPageGet(\n\t\tkey: string,\n\t\tqueryParams: APILegalPageGetByPathQueryParams = {},\n\t): Promise<APILegalPageGetByPathResult> {\n\t\tconst normalized = key.startsWith(\"/\") ? key.slice(1) : key;\n\t\tconst pathname = `/legal-pages/${encodeURIComponent(normalized)}` as const;\n\t\treturn this.request<APILegalPageGetByPathResult>(pathname, {\n\t\t\tquery: queryParams,\n\t\t});\n\t}\n\n\tasync legalPageCreate(\n\t\tbody: APILegalPageCreateBody,\n\t\tqueryParams: APILegalPageCreateQueryParams = {},\n\t): Promise<APILegalPageCreateResult> {\n\t\treturn this.request<APILegalPageCreateResult, APILegalPageCreateBody>(\"/legal-pages\", {\n\t\t\tmethod: \"POST\",\n\t\t\tbody,\n\t\t\tquery: queryParams,\n\t\t});\n\t}\n\n\tasync legalPageUpdate(\n\t\tkey: string,\n\t\tbody: APILegalPageUpdateBody,\n\t\tqueryParams: APILegalPageUpdateQueryParams = {},\n\t): Promise<APILegalPageUpdateResult> {\n\t\tconst normalized = key.startsWith(\"/\") ? key.slice(1) : key;\n\t\tconst pathname = `/legal-pages/${encodeURIComponent(normalized)}` as const;\n\t\treturn this.request<APILegalPageUpdateResult, APILegalPageUpdateBody>(pathname, {\n\t\t\tmethod: \"PATCH\",\n\t\t\tbody,\n\t\t\tquery: queryParams,\n\t\t});\n\t}\n\n\tasync search(params: APISearchQueryParams): Promise<APISearchResult> {\n\t\treturn this.request<APISearchResult>(\"/search\", {\n\t\t\tquery: params,\n\t\t});\n\t}\n\n\t// ============================================\n\t// Instaview\n\t// ============================================\n\n\tasync instaviewImagesBrowse(\n\t\tparams: APIInstaviewImagesBrowseParams,\n\t\tqueryParams: APIInstaviewImagesBrowseQueryParams = {},\n\t): Promise<APIInstaviewImagesBrowseResult> {\n\t\tconst urlParams = new URLSearchParams();\n\t\tif (queryParams.limit) urlParams.append(\"limit\", queryParams.limit.toString());\n\t\tif (queryParams.cursor) urlParams.append(\"cursor\", queryParams.cursor);\n\n\t\tconst searchParams = urlParams.size ? `?${urlParams}` : \"\";\n\t\tconst pathname = `/instaview/accounts/${params.handle}/images${searchParams}` as const;\n\n\t\treturn this.#restRequest<APIInstaviewImagesBrowseResult>(pathname);\n\t}\n\n\t/**\n\t * Make a raw API request to any endpoint.\n\t * Use this for new API features not yet supported by typed methods.\n\t *\n\t * @example\n\t * // GET request (default method)\n\t * const webhooks = await provider.request<Webhook[]>('/webhooks');\n\t *\n\t * // POST with typed body\n\t * const webhook = await provider.request<Webhook, CreateWebhookBody>('/webhooks', {\n\t * method: 'POST',\n\t * body: { url: 'https://...' }\n\t * });\n\t *\n\t * // GET with query parameters\n\t * const products = await provider.request<Product[]>('/products', {\n\t * query: { limit: 10, category: 'shoes' }\n\t * });\n\t *\n\t * // Path parameters via template literals\n\t * const product = await provider.request<Product>(`/products/${id}`);\n\t */\n\tasync request<TResponse = unknown, TBody = unknown>(\n\t\tpathname: `/${string}`,\n\t\toptions?: {\n\t\t\tmethod?: \"GET\" | \"POST\" | \"PATCH\" | \"DELETE\";\n\t\t\tbody?: TBody;\n\t\t\tquery?: Record<string, string | number | boolean | null | undefined>;\n\t\t},\n\t) {\n\t\tconst queryEntries = options?.query\n\t\t\t? Object.entries(options.query).filter((entry): entry is [string, string | number | boolean] => {\n\t\t\t\t\tconst [, value] = entry;\n\t\t\t\t\treturn value !== null && value !== undefined;\n\t\t\t\t})\n\t\t\t: [];\n\t\tconst queryString =\n\t\t\tqueryEntries.length > 0 ? `?${new URLSearchParams(queryEntries.map(([k, v]) => [k, String(v)]))}` : \"\";\n\n\t\treturn this.#restRequest<TResponse>(`${pathname}${queryString}`, options?.method ?? \"GET\", options?.body);\n\t}\n}\n","import { YNSProvider } from \"./providers/yns\";\nimport type { CommerceConfig } from \"./types\";\n\nexport function Commerce(config: CommerceConfig = {}): YNSProvider {\n\treturn new YNSProvider(config);\n}\n"],"mappings":"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","names":["YNS_API_KEY","env","LogLevel","strLogLevel","valueLogLevel","RESET","BLUE","GREEN","YELLOW","RED","TIME","DEBUG","OK","WARN","ERROR","PREFIX_TIME","PREFIX_DEBUG","PREFIX_OK","PREFIX_WARN","PREFIX_ERROR","getLogger","groupLabel","PREFIX","subGroupLabel","label","args","item","options","logger","YNSProvider","#config","#logger","getLogger","config","token","env","isStaging","endpoint","#restRequest","pathname","method","body","response","#fetchJson","#parseResponse","#restRequestNullable","logger","contentType","errorMessage","errorData","error","errorText","#multipartRequest","formData","result","params","queryParams","searchParams","urlParams","sku","productId","email","key","normalized","options","queryEntries","entry","value","queryString","k","v","Commerce","config","YNSProvider"]}
|
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Sandbox Inspectors — side-effect entry.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Runs inside per-store storefronts under the AI Builder sandbox dev server.
|
|
5
|
+
* Two responsibilities:
|
|
6
|
+
* 1. Report uncaught runtime errors to the parent /design iframe.
|
|
7
|
+
* 2. Load the builder-annotations UI (blue annotation pins, popovers, creation
|
|
8
|
+
* composer) from the central yns-toolbar CDN when embedded in the /design
|
|
9
|
+
* iframe. The UI lives there — not here — so fixes ship by pushing the
|
|
10
|
+
* toolbar repo instead of publishing commerce-kit + bumping every store.
|
|
7
11
|
*
|
|
8
|
-
* Always-on:
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
+
* Always-on: both parts are gated at runtime on being embedded in a parent
|
|
13
|
+
* frame. Gating on NODE_ENV is wrong (always "production" on Vercel) and any
|
|
14
|
+
* build-time gate gets folded out by the commerce-kit bundle, leaving an empty
|
|
15
|
+
* file.
|
|
12
16
|
*/
|
|
13
17
|
/**
|
|
14
18
|
* Exported so `browser.tsx` can `export { startSandboxInspectors }` — the
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
function
|
|
1
|
+
function w(){typeof window>"u"||(console.log("[YNS Sandbox Inspectors] module evaluated"),p(),f())}w();function f(){if(window.parent===window)return;let r="yns-builder-annotations-script";if(document.getElementById(r))return;let s=process.env.NEXT_PUBLIC_YNS_TOOLBAR_BASE||"https://toolbar.yns.cx",t=document.createElement("script");t.id=r,t.async=!0,t.src=`${s}/annotations.js`,document.head.appendChild(t)}function p(){if(window.parent===window)return;let r=5e3,s=10,t=2e3,a=0,c="",d=0;function u(e,n){let o=Date.now();d>=s||e===c&&o-a<r||(a=o,c=e,d+=1,window.parent.postMessage({type:"runtime-error",message:e,stack:n?n.slice(0,t):void 0,pagePath:window.location.pathname},"*"))}window.addEventListener("error",e=>{let n=e.error,o=n instanceof Error?n.message:e.message||"Unknown error",i=n instanceof Error?n.stack:void 0;u(o,i)}),window.addEventListener("unhandledrejection",e=>{let n=e.reason,o=n instanceof Error?n.message:String(n??"Unhandled rejection"),i=n instanceof Error?n.stack:void 0;u(o,i)})}export{w as startSandboxInspectors};
|
|
2
2
|
//# sourceMappingURL=sandbox-inspectors.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/sandbox-inspectors.ts"],"sourcesContent":["/**\n * Sandbox Inspectors — side-effect entry.\n *\n * Auto-mounts the design-mode + comment-mode inspectors inside per-store\n * storefronts running under the AI Builder sandbox dev server. Communicates\n * with the parent /design iframe via postMessage.\n *\n * Always-on: inspectors are passive postMessage listeners and don't affect the\n * page until the AI Builder iframe sends a `*-mode-toggle` message. Gating on\n * NODE_ENV is wrong (always \"production\" on Vercel) and any build-time gate\n * gets folded out by the commerce-kit bundle, leaving an empty file.\n */\n\n/**\n * Exported so `browser.tsx` can `export { startSandboxInspectors }` — the\n * named binding anchors this module against esbuild tree-shaking when\n * commerce-kit is bundled. Without it, an `export * from \"./sandbox-inspectors\"`\n * re-exports an empty binding set and esbuild DCEs the whole file.\n */\nexport function startSandboxInspectors(): void {\n\tif (typeof window === \"undefined\") return;\n\tconsole.log(\"[YNS Sandbox Inspectors] module evaluated\");\n\tinitDesignModeInspector();\n\tinitCommentModeInspector();\n\tinitRuntimeErrorReporter();\n}\n\n// Auto-start on import.\nstartSandboxInspectors();\n\n/**\n * Reports uncaught runtime errors (e.g. React's \"Maximum update depth\n * exceeded\" from an infinite render loop) to the parent /design iframe so the\n * AI Builder can surface a crash overlay instead of a silently frozen preview.\n *\n * Unlike the inspectors, this posts unsolicited messages — so it only attaches\n * when actually embedded in a parent frame. Render loops fire the same error\n * continuously; rate-limit hard so the parent isn't flooded.\n */\nfunction initRuntimeErrorReporter() {\n\tif (window.parent === window) return;\n\n\tconst MIN_INTERVAL_MS = 5_000;\n\tconst MAX_REPORTS_PER_LOAD = 10;\n\tconst MAX_STACK_LENGTH = 2_000;\n\n\tlet lastSentAt = 0;\n\tlet lastMessage = \"\";\n\tlet sentCount = 0;\n\n\tfunction report(message: string, stack: string | undefined) {\n\t\tconst now = Date.now();\n\t\tif (sentCount >= MAX_REPORTS_PER_LOAD) return;\n\t\tif (message === lastMessage && now - lastSentAt < MIN_INTERVAL_MS) return;\n\t\tlastSentAt = now;\n\t\tlastMessage = message;\n\t\tsentCount += 1;\n\t\twindow.parent.postMessage(\n\t\t\t{\n\t\t\t\ttype: \"runtime-error\",\n\t\t\t\tmessage,\n\t\t\t\tstack: stack ? stack.slice(0, MAX_STACK_LENGTH) : undefined,\n\t\t\t\tpagePath: window.location.pathname,\n\t\t\t},\n\t\t\t\"*\",\n\t\t);\n\t}\n\n\twindow.addEventListener(\"error\", (event) => {\n\t\tconst error: unknown = event.error;\n\t\tconst message = error instanceof Error ? error.message : event.message || \"Unknown error\";\n\t\tconst stack = error instanceof Error ? error.stack : undefined;\n\t\treport(message, stack);\n\t});\n\n\twindow.addEventListener(\"unhandledrejection\", (event) => {\n\t\tconst reason: unknown = event.reason;\n\t\tconst message = reason instanceof Error ? reason.message : String(reason ?? \"Unhandled rejection\");\n\t\tconst stack = reason instanceof Error ? reason.stack : undefined;\n\t\treport(message, stack);\n\t});\n}\n\ninterface ElementInfo {\n\ttag: string;\n\tid: string | undefined;\n\tclasses: string[];\n\ttextContent: string;\n\tcssSelector: string;\n\tboundingRect: { top: number; left: number; width: number; height: number };\n\tcomputedStyles: Partial<{\n\t\tcolor: string;\n\t\tbackgroundColor: string;\n\t\tfontSize: string;\n\t\tfontFamily: string;\n\t\tpadding: string;\n\t\tmargin: string;\n\t}>;\n}\n\nconst IGNORED_TAGS = new Set([\"HEAD\", \"SCRIPT\", \"STYLE\", \"NOSCRIPT\", \"HTML\"]);\n\nfunction generateCssSelector(el: Element): string {\n\tif (el.id) return `${el.tagName.toLowerCase()}#${CSS.escape(el.id)}`;\n\n\tconst parts: string[] = [];\n\tlet current: Element | null = el;\n\twhile (current && current !== document.body && current !== document.documentElement) {\n\t\tlet selector = current.tagName.toLowerCase();\n\n\t\tif (current.id) {\n\t\t\tparts.unshift(`${selector}#${CSS.escape(current.id)}`);\n\t\t\tbreak;\n\t\t}\n\n\t\tconst classes = Array.from(current.classList).filter((c) => !c.startsWith(\"data-yns-\"));\n\t\tif (classes.length > 0) {\n\t\t\tselector += `.${classes.map((c) => CSS.escape(c)).join(\".\")}`;\n\t\t}\n\n\t\tconst parent: Element | null = current.parentElement;\n\t\tconst tag = current.tagName;\n\t\tif (parent) {\n\t\t\tconst siblings = Array.from(parent.children).filter(\n\t\t\t\t(s) => s.tagName === tag && (classes.length === 0 || classes.every((c) => s.classList.contains(c))),\n\t\t\t);\n\t\t\tif (siblings.length > 1) {\n\t\t\t\tconst index = Array.from(parent.children).indexOf(current) + 1;\n\t\t\t\tselector += `:nth-child(${index})`;\n\t\t\t}\n\t\t}\n\n\t\tparts.unshift(selector);\n\t\tcurrent = current.parentElement;\n\t}\n\treturn parts.join(\" > \");\n}\n\nfunction buildElementInfo(el: Element, textLimit: number): ElementInfo {\n\tconst rect = el.getBoundingClientRect();\n\tconst computed = window.getComputedStyle(el);\n\tconst text = (el.textContent ?? \"\").trim();\n\treturn {\n\t\ttag: el.tagName.toLowerCase(),\n\t\tid: el.id || undefined,\n\t\tclasses: Array.from(el.classList).filter((c) => !c.startsWith(\"data-yns-\")),\n\t\ttextContent: text.length > textLimit ? `${text.slice(0, textLimit)}…` : text,\n\t\tcssSelector: generateCssSelector(el),\n\t\tboundingRect: { top: rect.top, left: rect.left, width: rect.width, height: rect.height },\n\t\tcomputedStyles: {\n\t\t\tcolor: computed.color,\n\t\t\tbackgroundColor: computed.backgroundColor,\n\t\t\tfontSize: computed.fontSize,\n\t\t\tfontFamily: computed.fontFamily,\n\t\t\tpadding: computed.padding,\n\t\t\tmargin: computed.margin,\n\t\t},\n\t};\n}\n\nfunction shouldIgnore(el: Element | null, overlayAttrs: string[]): el is null {\n\tif (!el?.tagName) return true;\n\tif (IGNORED_TAGS.has(el.tagName)) return true;\n\tfor (const attr of overlayAttrs) {\n\t\tif (el.hasAttribute?.(attr)) return true;\n\t}\n\treturn false;\n}\n\nfunction initDesignModeInspector() {\n\tlet enabled = false;\n\tlet hoveredElement: Element | null = null;\n\tlet selectedElement: { el: Element; cssSelector: string } | null = null;\n\n\tconst overlay = document.createElement(\"div\");\n\toverlay.setAttribute(\"data-yns-design-overlay\", \"hover\");\n\toverlay.style.cssText = [\n\t\t\"position: fixed\",\n\t\t\"pointer-events: none\",\n\t\t\"z-index: 2147483646\",\n\t\t\"border: 2px solid #3b82f6\",\n\t\t\"background: rgba(59, 130, 246, 0.08)\",\n\t\t\"border-radius: 3px\",\n\t\t\"display: none\",\n\t\t\"transition: top 0.05s, left 0.05s, width 0.05s, height 0.05s\",\n\t].join(\";\");\n\n\tconst label = document.createElement(\"div\");\n\tlabel.setAttribute(\"data-yns-design-overlay\", \"label\");\n\tlabel.style.cssText = [\n\t\t\"position: fixed\",\n\t\t\"pointer-events: none\",\n\t\t\"z-index: 2147483647\",\n\t\t\"background: #3b82f6\",\n\t\t\"color: #fff\",\n\t\t\"font-size: 11px\",\n\t\t\"font-family: ui-monospace, monospace\",\n\t\t\"padding: 2px 6px\",\n\t\t\"border-radius: 3px\",\n\t\t\"white-space: nowrap\",\n\t\t\"display: none\",\n\t].join(\";\");\n\n\tdocument.documentElement.appendChild(overlay);\n\tdocument.documentElement.appendChild(label);\n\n\tconst style = document.createElement(\"style\");\n\tstyle.setAttribute(\"data-yns-design-overlay\", \"style\");\n\tstyle.textContent = \"[data-yns-selected] { outline: 2px solid #3b82f6 !important; outline-offset: 1px; }\";\n\tdocument.head.appendChild(style);\n\n\tfunction positionOverlay(el: Element) {\n\t\tconst rect = el.getBoundingClientRect();\n\t\toverlay.style.top = `${rect.top}px`;\n\t\toverlay.style.left = `${rect.left}px`;\n\t\toverlay.style.width = `${rect.width}px`;\n\t\toverlay.style.height = `${rect.height}px`;\n\t\toverlay.style.display = \"block\";\n\n\t\tconst classes = Array.from(el.classList).filter((c) => !c.startsWith(\"data-yns-\"));\n\t\tconst labelText = el.tagName.toLowerCase() + (classes.length ? `.${classes[0]}` : \"\");\n\t\tlabel.textContent = labelText;\n\t\tlabel.style.left = `${rect.left}px`;\n\t\tlabel.style.top = `${Math.max(0, rect.top - 22)}px`;\n\t\tlabel.style.display = \"block\";\n\t}\n\n\tconst handleMouseMove = (e: MouseEvent) => {\n\t\tconst el = document.elementFromPoint(e.clientX, e.clientY);\n\t\tif (shouldIgnore(el, [\"data-yns-design-overlay\"])) {\n\t\t\toverlay.style.display = \"none\";\n\t\t\tlabel.style.display = \"none\";\n\t\t\thoveredElement = null;\n\t\t\treturn;\n\t\t}\n\t\thoveredElement = el;\n\t\trequestAnimationFrame(() => {\n\t\t\tif (hoveredElement === el && enabled && el) {\n\t\t\t\tpositionOverlay(el);\n\t\t\t}\n\t\t});\n\t};\n\n\tconst handleMouseLeave = () => {\n\t\toverlay.style.display = \"none\";\n\t\tlabel.style.display = \"none\";\n\t\thoveredElement = null;\n\t};\n\n\tconst handleClick = (e: MouseEvent) => {\n\t\tif (!enabled || !hoveredElement) return;\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\t\te.stopImmediatePropagation();\n\n\t\tconst el = hoveredElement;\n\t\tif (shouldIgnore(el, [\"data-yns-design-overlay\"])) return;\n\n\t\tconst info = buildElementInfo(el, 120);\n\t\tconst selector = info.cssSelector;\n\n\t\tif (selectedElement) {\n\t\t\tselectedElement.el.removeAttribute(\"data-yns-selected\");\n\t\t}\n\n\t\tif (selectedElement && selectedElement.cssSelector === selector) {\n\t\t\tselectedElement = null;\n\t\t\twindow.parent.postMessage({ type: \"element-deselected\", data: info }, \"*\");\n\t\t} else {\n\t\t\tselectedElement = { el, cssSelector: selector };\n\t\t\tel.setAttribute(\"data-yns-selected\", \"\");\n\t\t\twindow.parent.postMessage({ type: \"element-selected\", data: info }, \"*\");\n\t\t}\n\t};\n\n\tconst handleKeyDown = (e: KeyboardEvent) => {\n\t\tif (e.key === \"Escape\" && enabled) {\n\t\t\tdisableDesignMode();\n\t\t\twindow.parent.postMessage({ type: \"design-mode-cleared\" }, \"*\");\n\t\t}\n\t};\n\n\tfunction enableDesignMode() {\n\t\tenabled = true;\n\t\tdocument.addEventListener(\"mousemove\", handleMouseMove, true);\n\t\tdocument.addEventListener(\"mouseleave\", handleMouseLeave);\n\t\tdocument.addEventListener(\"click\", handleClick, true);\n\t\tdocument.addEventListener(\"keydown\", handleKeyDown, true);\n\t}\n\n\tfunction disableDesignMode() {\n\t\tenabled = false;\n\t\tdocument.removeEventListener(\"mousemove\", handleMouseMove, true);\n\t\tdocument.removeEventListener(\"mouseleave\", handleMouseLeave);\n\t\tdocument.removeEventListener(\"click\", handleClick, true);\n\t\tdocument.removeEventListener(\"keydown\", handleKeyDown, true);\n\n\t\toverlay.style.display = \"none\";\n\t\tlabel.style.display = \"none\";\n\t\thoveredElement = null;\n\n\t\tif (selectedElement) {\n\t\t\tselectedElement.el.removeAttribute(\"data-yns-selected\");\n\t\t\tselectedElement = null;\n\t\t}\n\t}\n\n\twindow.addEventListener(\"message\", (event) => {\n\t\tconst msg = event.data;\n\t\tif (!msg || typeof msg !== \"object\") return;\n\n\t\tif (msg.type === \"design-mode-toggle\") {\n\t\t\tif (msg.enabled) {\n\t\t\t\tenableDesignMode();\n\t\t\t} else {\n\t\t\t\tdisableDesignMode();\n\t\t\t\twindow.parent.postMessage({ type: \"design-mode-cleared\" }, \"*\");\n\t\t\t}\n\t\t}\n\n\t\tif (msg.type === \"design-mode-deselect\") {\n\t\t\tif (selectedElement) {\n\t\t\t\tselectedElement.el.removeAttribute(\"data-yns-selected\");\n\t\t\t\tselectedElement = null;\n\t\t\t}\n\t\t}\n\t});\n}\n\nfunction initCommentModeInspector() {\n\tlet enabled = false;\n\tlet hoveredElement: Element | null = null;\n\tlet pins: Array<{ id: string; selector: string; number: number }> = [];\n\n\tconst overlay = document.createElement(\"div\");\n\toverlay.setAttribute(\"data-yns-comment-overlay\", \"hover\");\n\toverlay.style.cssText = [\n\t\t\"position: fixed\",\n\t\t\"pointer-events: none\",\n\t\t\"z-index: 2147483644\",\n\t\t\"border: 2px dashed #10b981\",\n\t\t\"background: rgba(16, 185, 129, 0.06)\",\n\t\t\"border-radius: 3px\",\n\t\t\"display: none\",\n\t\t\"transition: top 0.05s, left 0.05s, width 0.05s, height 0.05s\",\n\t].join(\";\");\n\n\tconst cursorLabel = document.createElement(\"div\");\n\tcursorLabel.setAttribute(\"data-yns-comment-overlay\", \"cursor-label\");\n\tcursorLabel.textContent = \"Click to comment\";\n\tcursorLabel.style.cssText = [\n\t\t\"position: fixed\",\n\t\t\"pointer-events: none\",\n\t\t\"z-index: 2147483645\",\n\t\t\"background: #059669\",\n\t\t\"color: #fff\",\n\t\t\"font-size: 11px\",\n\t\t\"font-family: ui-sans-serif, system-ui, sans-serif\",\n\t\t\"padding: 3px 8px\",\n\t\t\"border-radius: 4px\",\n\t\t\"white-space: nowrap\",\n\t\t\"display: none\",\n\t\t\"box-shadow: 0 2px 6px rgba(0,0,0,0.15)\",\n\t].join(\";\");\n\n\tconst pinContainer = document.createElement(\"div\");\n\tpinContainer.setAttribute(\"data-yns-comment-overlay\", \"pins\");\n\tpinContainer.style.cssText =\n\t\t\"position: fixed; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; z-index: 2147483643;\";\n\n\tdocument.documentElement.appendChild(overlay);\n\tdocument.documentElement.appendChild(cursorLabel);\n\tdocument.documentElement.appendChild(pinContainer);\n\n\tfunction renderPins() {\n\t\tpinContainer.innerHTML = \"\";\n\t\tfor (const pin of pins) {\n\t\t\tlet el: Element | null = null;\n\t\t\ttry {\n\t\t\t\tel = document.querySelector(pin.selector);\n\t\t\t} catch {\n\t\t\t\tel = null;\n\t\t\t}\n\t\t\tif (!el) continue;\n\n\t\t\tconst r = el.getBoundingClientRect();\n\t\t\tconst pinEl = document.createElement(\"div\");\n\t\t\tpinEl.style.cssText = [\n\t\t\t\t\"position: fixed\",\n\t\t\t\t`top: ${r.top - 12}px`,\n\t\t\t\t`left: ${r.left + r.width / 2 - 12}px`,\n\t\t\t\t\"width: 24px\",\n\t\t\t\t\"height: 24px\",\n\t\t\t\t\"border-radius: 50%\",\n\t\t\t\t\"background: #059669\",\n\t\t\t\t\"color: #fff\",\n\t\t\t\t\"display: flex\",\n\t\t\t\t\"align-items: center\",\n\t\t\t\t\"justify-content: center\",\n\t\t\t\t\"font-size: 12px\",\n\t\t\t\t\"font-weight: 600\",\n\t\t\t\t\"font-family: ui-sans-serif, system-ui, sans-serif\",\n\t\t\t\t\"box-shadow: 0 2px 8px rgba(0,0,0,0.2)\",\n\t\t\t\t\"pointer-events: none\",\n\t\t\t].join(\";\");\n\t\t\tpinEl.textContent = String(pin.number);\n\t\t\tpinContainer.appendChild(pinEl);\n\t\t}\n\t}\n\n\tconst handleMouseMove = (e: MouseEvent) => {\n\t\tconst el = document.elementFromPoint(e.clientX, e.clientY);\n\t\tif (shouldIgnore(el, [\"data-yns-comment-overlay\", \"data-yns-design-overlay\"])) {\n\t\t\toverlay.style.display = \"none\";\n\t\t\tcursorLabel.style.display = \"none\";\n\t\t\thoveredElement = null;\n\t\t\treturn;\n\t\t}\n\t\thoveredElement = el;\n\t\trequestAnimationFrame(() => {\n\t\t\tif (hoveredElement === el && enabled && el) {\n\t\t\t\tconst rect = el.getBoundingClientRect();\n\t\t\t\toverlay.style.top = `${rect.top}px`;\n\t\t\t\toverlay.style.left = `${rect.left}px`;\n\t\t\t\toverlay.style.width = `${rect.width}px`;\n\t\t\t\toverlay.style.height = `${rect.height}px`;\n\t\t\t\toverlay.style.display = \"block\";\n\n\t\t\t\tcursorLabel.style.left = `${e.clientX + 14}px`;\n\t\t\t\tcursorLabel.style.top = `${e.clientY + 14}px`;\n\t\t\t\tcursorLabel.style.display = \"block\";\n\t\t\t}\n\t\t});\n\t};\n\n\tconst handleMouseLeave = () => {\n\t\toverlay.style.display = \"none\";\n\t\tcursorLabel.style.display = \"none\";\n\t\thoveredElement = null;\n\t};\n\n\tconst handleClick = (e: MouseEvent) => {\n\t\tif (!enabled || !hoveredElement) return;\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\t\te.stopImmediatePropagation();\n\n\t\tconst el = hoveredElement;\n\t\tif (shouldIgnore(el, [\"data-yns-comment-overlay\", \"data-yns-design-overlay\"])) return;\n\n\t\tconst info = buildElementInfo(el, 200);\n\t\tconst rect = el.getBoundingClientRect();\n\n\t\twindow.parent.postMessage(\n\t\t\t{\n\t\t\t\ttype: \"comment-click\",\n\t\t\t\tdata: {\n\t\t\t\t\telement: info,\n\t\t\t\t\tclickPosition: { x: e.clientX, y: e.clientY },\n\t\t\t\t\telementRect: { top: rect.top, left: rect.left, width: rect.width, height: rect.height },\n\t\t\t\t\tpagePath: window.location.pathname,\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"*\",\n\t\t);\n\t};\n\n\tconst handleKeyDown = (e: KeyboardEvent) => {\n\t\tif (e.key === \"Escape\" && enabled) {\n\t\t\tdisableCommentMode();\n\t\t\twindow.parent.postMessage({ type: \"comment-mode-cleared\" }, \"*\");\n\t\t}\n\t};\n\n\tfunction enableCommentMode() {\n\t\tenabled = true;\n\t\tdocument.body.style.cursor = \"crosshair\";\n\t\tdocument.addEventListener(\"mousemove\", handleMouseMove, true);\n\t\tdocument.addEventListener(\"mouseleave\", handleMouseLeave);\n\t\tdocument.addEventListener(\"click\", handleClick, true);\n\t\tdocument.addEventListener(\"keydown\", handleKeyDown, true);\n\t}\n\n\tfunction disableCommentMode() {\n\t\tenabled = false;\n\t\tdocument.body.style.cursor = \"\";\n\t\tdocument.removeEventListener(\"mousemove\", handleMouseMove, true);\n\t\tdocument.removeEventListener(\"mouseleave\", handleMouseLeave);\n\t\tdocument.removeEventListener(\"click\", handleClick, true);\n\t\tdocument.removeEventListener(\"keydown\", handleKeyDown, true);\n\n\t\toverlay.style.display = \"none\";\n\t\tcursorLabel.style.display = \"none\";\n\t\thoveredElement = null;\n\t}\n\n\tlet rafPending = false;\n\tconst scheduleRender = () => {\n\t\tif (rafPending) return;\n\t\trafPending = true;\n\t\trequestAnimationFrame(() => {\n\t\t\trafPending = false;\n\t\t\trenderPins();\n\t\t});\n\t};\n\twindow.addEventListener(\"scroll\", scheduleRender, { passive: true });\n\twindow.addEventListener(\"resize\", scheduleRender, { passive: true });\n\n\twindow.addEventListener(\"message\", (event) => {\n\t\tconst msg = event.data;\n\t\tif (!msg || typeof msg !== \"object\") return;\n\n\t\tif (msg.type === \"comment-mode-toggle\") {\n\t\t\tif (msg.enabled) enableCommentMode();\n\t\t\telse disableCommentMode();\n\t\t}\n\n\t\tif (msg.type === \"comment-pins-update\") {\n\t\t\tpins = msg.pins ?? [];\n\t\t\trenderPins();\n\t\t}\n\n\t\tif (msg.type === \"comment-pin-remove\") {\n\t\t\tpins = pins.filter((p) => p.id !== msg.pinId);\n\t\t\trenderPins();\n\t\t}\n\t});\n}\n"],"mappings":"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","names":["startSandboxInspectors","initDesignModeInspector","initCommentModeInspector","initRuntimeErrorReporter","MIN_INTERVAL_MS","MAX_REPORTS_PER_LOAD","MAX_STACK_LENGTH","lastSentAt","lastMessage","sentCount","report","message","stack","now","event","error","reason","IGNORED_TAGS","generateCssSelector","el","parts","current","selector","classes","c","parent","tag","s","index","buildElementInfo","textLimit","rect","computed","text","shouldIgnore","overlayAttrs","attr","enabled","hoveredElement","selectedElement","overlay","label","style","positionOverlay","labelText","handleMouseMove","e","handleMouseLeave","handleClick","info","handleKeyDown","disableDesignMode","enableDesignMode","msg","pins","cursorLabel","pinContainer","renderPins","pin","r","pinEl","disableCommentMode","enableCommentMode","rafPending","scheduleRender"]}
|
|
1
|
+
{"version":3,"sources":["../src/sandbox-inspectors.ts"],"sourcesContent":["/**\n * Sandbox Inspectors — side-effect entry.\n *\n * Runs inside per-store storefronts under the AI Builder sandbox dev server.\n * Two responsibilities:\n * 1. Report uncaught runtime errors to the parent /design iframe.\n * 2. Load the builder-annotations UI (blue annotation pins, popovers, creation\n * composer) from the central yns-toolbar CDN when embedded in the /design\n * iframe. The UI lives there — not here — so fixes ship by pushing the\n * toolbar repo instead of publishing commerce-kit + bumping every store.\n *\n * Always-on: both parts are gated at runtime on being embedded in a parent\n * frame. Gating on NODE_ENV is wrong (always \"production\" on Vercel) and any\n * build-time gate gets folded out by the commerce-kit bundle, leaving an empty\n * file.\n */\n\n/**\n * Exported so `browser.tsx` can `export { startSandboxInspectors }` — the\n * named binding anchors this module against esbuild tree-shaking when\n * commerce-kit is bundled. Without it, an `export * from \"./sandbox-inspectors\"`\n * re-exports an empty binding set and esbuild DCEs the whole file.\n */\nexport function startSandboxInspectors(): void {\n\tif (typeof window === \"undefined\") return;\n\tconsole.log(\"[YNS Sandbox Inspectors] module evaluated\");\n\tinitRuntimeErrorReporter();\n\tinitBuilderAnnotationsLoader();\n}\n\n// Auto-start on import.\nstartSandboxInspectors();\n\n/**\n * Injects the builder-annotations bundle from the yns-toolbar CDN. The bundle\n * self-gates on being framed too, so this is belt-and-braces; loading only when\n * framed keeps direct sandbox-URL visits (and feedback preview deploys, which\n * import this module top-level) free of the extra script.\n */\nfunction initBuilderAnnotationsLoader() {\n\tif (window.parent === window) return;\n\n\tconst SCRIPT_ID = \"yns-builder-annotations-script\";\n\tif (document.getElementById(SCRIPT_ID)) return;\n\n\tconst base = process.env.NEXT_PUBLIC_YNS_TOOLBAR_BASE || \"https://toolbar.yns.cx\";\n\tconst script = document.createElement(\"script\");\n\tscript.id = SCRIPT_ID;\n\tscript.async = true;\n\tscript.src = `${base}/annotations.js`;\n\tdocument.head.appendChild(script);\n}\n\n/**\n * Reports uncaught runtime errors (e.g. React's \"Maximum update depth\n * exceeded\" from an infinite render loop) to the parent /design iframe so the\n * AI Builder can surface a crash overlay instead of a silently frozen preview.\n *\n * Unlike the annotations UI, this posts unsolicited messages — so it only\n * attaches when actually embedded in a parent frame. Render loops fire the same\n * error continuously; rate-limit hard so the parent isn't flooded.\n */\nfunction initRuntimeErrorReporter() {\n\tif (window.parent === window) return;\n\n\tconst MIN_INTERVAL_MS = 5_000;\n\tconst MAX_REPORTS_PER_LOAD = 10;\n\tconst MAX_STACK_LENGTH = 2_000;\n\n\tlet lastSentAt = 0;\n\tlet lastMessage = \"\";\n\tlet sentCount = 0;\n\n\tfunction report(message: string, stack: string | undefined) {\n\t\tconst now = Date.now();\n\t\tif (sentCount >= MAX_REPORTS_PER_LOAD) return;\n\t\tif (message === lastMessage && now - lastSentAt < MIN_INTERVAL_MS) return;\n\t\tlastSentAt = now;\n\t\tlastMessage = message;\n\t\tsentCount += 1;\n\t\twindow.parent.postMessage(\n\t\t\t{\n\t\t\t\ttype: \"runtime-error\",\n\t\t\t\tmessage,\n\t\t\t\tstack: stack ? stack.slice(0, MAX_STACK_LENGTH) : undefined,\n\t\t\t\tpagePath: window.location.pathname,\n\t\t\t},\n\t\t\t\"*\",\n\t\t);\n\t}\n\n\twindow.addEventListener(\"error\", (event) => {\n\t\tconst error: unknown = event.error;\n\t\tconst message = error instanceof Error ? error.message : event.message || \"Unknown error\";\n\t\tconst stack = error instanceof Error ? error.stack : undefined;\n\t\treport(message, stack);\n\t});\n\n\twindow.addEventListener(\"unhandledrejection\", (event) => {\n\t\tconst reason: unknown = event.reason;\n\t\tconst message = reason instanceof Error ? reason.message : String(reason ?? \"Unhandled rejection\");\n\t\tconst stack = reason instanceof Error ? reason.stack : undefined;\n\t\treport(message, stack);\n\t});\n}\n"],"mappings":"AAuBO,SAASA,GAA+B,CAC1C,OAAO,OAAW,MACtB,QAAQ,IAAI,2CAA2C,EACvDC,EAAyB,EACzBC,EAA6B,EAC9B,CAGAF,EAAuB,EAQvB,SAASE,GAA+B,CACvC,GAAI,OAAO,SAAW,OAAQ,OAE9B,IAAMC,EAAY,iCAClB,GAAI,SAAS,eAAeA,CAAS,EAAG,OAExC,IAAMC,EAAO,QAAQ,IAAI,8BAAgC,yBACnDC,EAAS,SAAS,cAAc,QAAQ,EAC9CA,EAAO,GAAKF,EACZE,EAAO,MAAQ,GACfA,EAAO,IAAM,GAAGD,CAAI,kBACpB,SAAS,KAAK,YAAYC,CAAM,CACjC,CAWA,SAASJ,GAA2B,CACnC,GAAI,OAAO,SAAW,OAAQ,OAE9B,IAAMK,EAAkB,IAClBC,EAAuB,GACvBC,EAAmB,IAErBC,EAAa,EACbC,EAAc,GACdC,EAAY,EAEhB,SAASC,EAAOC,EAAiBC,EAA2B,CAC3D,IAAMC,EAAM,KAAK,IAAI,EACjBJ,GAAaJ,GACbM,IAAYH,GAAeK,EAAMN,EAAaH,IAClDG,EAAaM,EACbL,EAAcG,EACdF,GAAa,EACb,OAAO,OAAO,YACb,CACC,KAAM,gBACN,QAAAE,EACA,MAAOC,EAAQA,EAAM,MAAM,EAAGN,CAAgB,EAAI,OAClD,SAAU,OAAO,SAAS,QAC3B,EACA,GACD,EACD,CAEA,OAAO,iBAAiB,QAAUQ,GAAU,CAC3C,IAAMC,EAAiBD,EAAM,MACvBH,EAAUI,aAAiB,MAAQA,EAAM,QAAUD,EAAM,SAAW,gBACpEF,EAAQG,aAAiB,MAAQA,EAAM,MAAQ,OACrDL,EAAOC,EAASC,CAAK,CACtB,CAAC,EAED,OAAO,iBAAiB,qBAAuBE,GAAU,CACxD,IAAME,EAAkBF,EAAM,OACxBH,EAAUK,aAAkB,MAAQA,EAAO,QAAU,OAAOA,GAAU,qBAAqB,EAC3FJ,EAAQI,aAAkB,MAAQA,EAAO,MAAQ,OACvDN,EAAOC,EAASC,CAAK,CACtB,CAAC,CACF","names":["startSandboxInspectors","initRuntimeErrorReporter","initBuilderAnnotationsLoader","SCRIPT_ID","base","script","MIN_INTERVAL_MS","MAX_REPORTS_PER_LOAD","MAX_STACK_LENGTH","lastSentAt","lastMessage","sentCount","report","message","stack","now","event","error","reason"]}
|