commerce-kit 0.65.0 → 0.67.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/README.md +98 -1
- package/dist/api-types.d.ts +614 -1
- package/dist/index.d.ts +63 -8
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/uploads.d.ts +54 -0
- package/dist/uploads.js +23 -0
- package/dist/uploads.js.map +1 -0
- package/package.json +7 -1
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\tAPICartCouponApplyResult,\n\tAPICartCouponRemoveResult,\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\tAPIProductGetByIdQueryParams,\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\t\t// Prices come back in this currency, with its own `…Gross` twins; `lang` picks the translation.\n\t\tif (params.currency) queryParams.append(\"currency\", params.currency);\n\t\tif (params.lang) queryParams.append(\"lang\", params.lang);\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\t/**\n\t * A single product by id or slug. `lang` selects the translation (and resolves a translated\n\t * slug); `currency` prices the variants in that currency, twins included.\n\t */\n\tasync productGet(\n\t\tparams: APIProductGetByIdParams & APIProductGetByIdQueryParams,\n\t): Promise<APIProductGetByIdResult | null> {\n\t\tconst queryParams = new URLSearchParams();\n\t\tif (params.lang) queryParams.append(\"lang\", params.lang);\n\t\tif (params.currency) queryParams.append(\"currency\", params.currency);\n\n\t\tconst searchParams = queryParams.size ? `?${queryParams}` : \"\";\n\t\tconst pathname = `/products/${params.idOrSlug}${searchParams}` 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\t/**\n\t * Validate and attach a coupon to the cart. Failures surface as an ApiError with\n\t * status 422 and a machine-readable `reason` (couponNotFound, couponHasExpired,\n\t * couponMaxUsesReached, couponIsNotValidYet, couponMinProductCountNotMet,\n\t * couponMaxProductCountExceeded, couponIsNotApplicable). Returns the updated cart.\n\t */\n\tasync cartCouponApply(params: { cartId: string; code: string }): Promise<APICartCouponApplyResult> {\n\t\tconst pathname = `/carts/${params.cartId}/coupon` as const;\n\t\treturn this.#restRequest<APICartCouponApplyResult>(pathname, \"POST\", { code: params.code });\n\t}\n\n\t/** Detach the applied coupon from the cart, if any. */\n\tasync cartCouponRemove(params: { cartId: string }): Promise<APICartCouponRemoveResult> {\n\t\tconst pathname = `/carts/${params.cartId}/coupon` as const;\n\t\treturn this.#restRequest<APICartCouponRemoveResult>(pathname, \"DELETE\");\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
|
+
{"version":3,"sources":["../src/env.ts","../src/keyless.ts","../src/logger.ts","../src/providers/yns.ts","../src/commerce.ts"],"sourcesContent":["const YNS_API_KEY = process.env.YNS_API_KEY;\nconst YNS_STORE_ID = process.env.YNS_STORE_ID;\n\nexport const env = {\n\tYNS_API_KEY,\n\tYNS_STORE_ID,\n};\n","/**\n * Catalog reads the platform also answers without an API key, so its CDN can keep the answer.\n * A request qualifies only when the keyless answer is the one the key would get.\n */\n\n/** `GET` paths that answer without a key. Lists also need `active=true`: without it a key sees inactive rows too. */\nconst KEYLESS_LISTS: ReadonlySet<string> = new Set([\"/products\", \"/collections\", \"/categories\", \"/brands\"]);\nconst KEYLESS_SINGLETONS: ReadonlySet<string> = new Set([\"/products/filters\", \"/legal-pages\"]);\nconst KEYLESS_DETAILS: ReadonlySet<string> = new Set([\n\t\"products\",\n\t\"collections\",\n\t\"categories\",\n\t\"brands\",\n\t\"legal-pages\",\n]);\n/** Second segments that are their own endpoints, not an id or slug. */\nconst NOT_A_RESOURCE: ReadonlySet<string> = new Set([\"batch\", \"import\", \"import-memberships\", \"filters\"]);\n\nconst isKeylessPath = (path: string, query: URLSearchParams): boolean => {\n\tif (KEYLESS_SINGLETONS.has(path)) return true;\n\tif (KEYLESS_LISTS.has(path)) return query.get(\"active\") === \"true\";\n\n\tconst [resource, idOrSlug, child, ...rest] = path.split(\"/\").slice(1);\n\tif (!resource || !idOrSlug || rest.length > 0 || NOT_A_RESOURCE.has(idOrSlug)) return false;\n\tif (child === undefined) return KEYLESS_DETAILS.has(resource);\n\treturn resource === \"products\" && child === \"reviews\";\n};\n\n/**\n * The keyless form of a `GET` pathname, or `null` when the request needs the key.\n *\n * `store` goes first and the other parameters are sorted, so two requests that mean the same\n * thing are one URL, and therefore one cached copy.\n */\nexport const keylessPathname = (pathname: `/${string}`, storeId: string): `/${string}` | null => {\n\tconst [path = \"\", search = \"\"] = pathname.split(\"?\");\n\tconst query = new URLSearchParams(search);\n\tconst active = query.get(\"active\");\n\t// Private custom fields are for keys with `catalog:write`: a keyless read is refused.\n\tconst privateFields = query.get(\"metafields\") === \"all\";\n\tif (\n\t\tquery.has(\"store\") ||\n\t\t(active !== null && active !== \"true\") ||\n\t\tprivateFields ||\n\t\t!isKeylessPath(path, query)\n\t) {\n\t\treturn null;\n\t}\n\n\tconst sorted = [...query.entries()].sort(([a, aValue], [b, bValue]) =>\n\t\ta === b ? aValue.localeCompare(bValue) : a.localeCompare(b),\n\t);\n\tconst keyless = new URLSearchParams([[\"store\", storeId], ...sorted]);\n\treturn `/${path.slice(1)}?${keyless}`;\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\tAPICartCouponApplyResult,\n\tAPICartCouponRemoveResult,\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\tAPIMetafieldDefinitionArchiveResult,\n\tAPIMetafieldDefinitionConversionPreviewResult,\n\tAPIMetafieldDefinitionConvertBody,\n\tAPIMetafieldDefinitionConvertResult,\n\tAPIMetafieldDefinitionCreateBody,\n\tAPIMetafieldDefinitionCreateResult,\n\tAPIMetafieldDefinitionDeleteBody,\n\tAPIMetafieldDefinitionDeleteResult,\n\tAPIMetafieldDefinitionGetQueryParams,\n\tAPIMetafieldDefinitionGetResult,\n\tAPIMetafieldDefinitionParams,\n\tAPIMetafieldDefinitionRestoreResult,\n\tAPIMetafieldDefinitionsBrowseQueryParams,\n\tAPIMetafieldDefinitionsBrowseResult,\n\tAPIMetafieldDefinitionTranslationParams,\n\tAPIMetafieldDefinitionTranslationPutBody,\n\tAPIMetafieldDefinitionTranslationPutResult,\n\tAPIMetafieldDefinitionUpdateBody,\n\tAPIMetafieldDefinitionUpdateResult,\n\tAPIMetafieldsTranslateMissingBody,\n\tAPIMetafieldsTranslateMissingResult,\n\tAPIMetafieldTranslationsPutBody,\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\tAPIProductFiltersQueryParams,\n\tAPIProductFiltersResult,\n\tAPIProductGetByIdParams,\n\tAPIProductGetByIdQueryParams,\n\tAPIProductGetByIdResult,\n\tAPIProductMetafieldTranslationsPutParams,\n\tAPIProductMetafieldTranslationsPutResult,\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\tAPIVariantMetafieldTranslationsPutParams,\n\tAPIVariantMetafieldTranslationsPutResult,\n\tAPIVariantUpdateBody,\n\tAPIVariantUpdateResult,\n} from \"../api-types\";\nimport { env } from \"../env\";\nimport { keylessPathname } from \"../keyless\";\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\n/** Answers that mean \"this platform or this request does not take keyless reads\": ask again with the key. */\nconst KEYLESS_REFUSALS: ReadonlySet<number> = new Set([400, 401, 403]);\n\nexport class YNSProvider {\n\t#config: CommerceConfig;\n\t#logger = getLogger(\"YNSProvider\");\n\t/** `null` once keyless reads are off for this process: opted out, refused, or no store id. */\n\t#storeId: Promise<string | null> | null = null;\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\" | \"PUT\" | \"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\t/**\n\t * The store id for keyless reads: from the config, then the environment, then one keyed\n\t * `GET /me`, asked once per process. Any failure leaves every request keyed, as before.\n\t */\n\t#resolveStoreId(): Promise<string | null> {\n\t\tconst configured = this.#config.store;\n\t\tif (configured === false) return Promise.resolve(null);\n\t\tthis.#storeId ??= (async () => {\n\t\t\tconst known = configured ?? env.YNS_STORE_ID;\n\t\t\tif (known) return known;\n\t\t\ttry {\n\t\t\t\tconst response = await this.#fetchKeyed(\"/me\", \"GET\");\n\t\t\t\tif (!response.ok) return null;\n\t\t\t\tconst me: { store?: { id?: unknown } } = await response.json();\n\t\t\t\treturn typeof me.store?.id === \"string\" ? me.store.id : null;\n\t\t\t} catch {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t})();\n\t\treturn this.#storeId;\n\t}\n\n\tasync #fetchJson(\n\t\tpathname: `/${string}`,\n\t\tmethod: \"GET\" | \"POST\" | \"PUT\" | \"PATCH\" | \"DELETE\",\n\t\tbody?: unknown,\n\t): Promise<Response> {\n\t\tif (method !== \"GET\") return this.#fetchKeyed(pathname, method, body);\n\n\t\tconst storeId = await this.#resolveStoreId();\n\t\tconst keyless = storeId ? keylessPathname(pathname, storeId) : null;\n\t\tif (!keyless) return this.#fetchKeyed(pathname, method);\n\n\t\tconst logger = this.#logger.getLogger(\"#restRequest\");\n\t\tconst endpoint = `${this.#config.endpoint}/api/${this.#config.version}${keyless}`;\n\t\tlogger.debug(`Making keyless GET request to YNS API: ${endpoint}`);\n\t\tconst response = await fetch(endpoint, { method, headers: { \"Content-Type\": \"application/json\" } });\n\t\tif (!KEYLESS_REFUSALS.has(response.status)) return response;\n\n\t\t// A platform that still wants the key answers 401 to every keyless read, so stop trying.\n\t\tif (response.status !== 400) this.#storeId = Promise.resolve(null);\n\t\tlogger.debug(`Keyless request answered ${response.status}, asking again with the key`);\n\t\treturn this.#fetchKeyed(pathname, method);\n\t}\n\n\tasync #fetchKeyed(\n\t\tpathname: `/${string}`,\n\t\tmethod: \"GET\" | \"POST\" | \"PUT\" | \"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\t\t// Prices come back in this currency, with its own `…Gross` twins; `lang` picks the translation.\n\t\tif (params.currency) queryParams.append(\"currency\", params.currency);\n\t\tif (params.lang) queryParams.append(\"lang\", params.lang);\n\t\t// Custom fields: `filter` narrows by their values (`product.custom.material:wool,silk;\n\t\t// variant.custom.weight:100..300`), `include` adds the values of every product and\n\t\t// variant to the list, `metafields: \"all\"` adds private fields (needs a key with\n\t\t// `catalog:write`; refused without a key).\n\t\tif (params.filter) queryParams.append(\"filter\", params.filter);\n\t\tif (params.include) queryParams.append(\"include\", params.include);\n\t\tif (params.metafields) queryParams.append(\"metafields\", params.metafields);\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, active categories, collections and brands, and the filterable custom\n\t * fields (`metafields`, present only when the store has any) with their options or\n\t * number range. Pair with `productBrowse`'s `collection`, `brand`, `priceMin`/`priceMax`,\n\t * `vts` and `filter` params to build a filter UI. `lang` translates field names and\n\t * option labels.\n\t */\n\tasync productFilters(params: APIProductFiltersQueryParams = {}): Promise<APIProductFiltersResult> {\n\t\tconst queryParams = new URLSearchParams();\n\t\tif (params.lang) queryParams.append(\"lang\", params.lang);\n\n\t\tconst searchParams = queryParams.size ? `?${queryParams}` : \"\";\n\t\tconst pathname = `/products/filters${searchParams}` as const;\n\t\treturn this.#restRequest<APIProductFiltersResult>(pathname);\n\t}\n\n\t/**\n\t * A single product by id or slug. `lang` selects the translation (and resolves a translated\n\t * slug); `currency` prices the variants in that currency, twins included. The product and\n\t * its variants carry their custom fields under `metafields`; `metafields: \"all\"` adds the\n\t * private ones (needs a key with `catalog:write`; refused without a key).\n\t */\n\tasync productGet(\n\t\tparams: APIProductGetByIdParams & APIProductGetByIdQueryParams,\n\t): Promise<APIProductGetByIdResult | null> {\n\t\tconst queryParams = new URLSearchParams();\n\t\tif (params.lang) queryParams.append(\"lang\", params.lang);\n\t\tif (params.currency) queryParams.append(\"currency\", params.currency);\n\t\tif (params.metafields) queryParams.append(\"metafields\", params.metafields);\n\n\t\tconst searchParams = queryParams.size ? `?${queryParams}` : \"\";\n\t\tconst pathname = `/products/${params.idOrSlug}${searchParams}` 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\t/**\n\t * Remove a variant from the cart. A variant can sit on several lines when they carry different\n\t * `properties` (personalisation); pass `lineItemId` to remove just that one line, otherwise all\n\t * of the variant's one-time lines go.\n\t */\n\tasync cartRemoveItem(params: {\n\t\tcartId: string;\n\t\tvariantId: string;\n\t\tlineItemId?: string;\n\t}): Promise<APICartGetResult> {\n\t\tconst searchParams = params.lineItemId\n\t\t\t? `?${new URLSearchParams({ lineItemId: params.lineItemId })}`\n\t\t\t: \"\";\n\t\tconst pathname = `/carts/${params.cartId}/line-items/${params.variantId}${searchParams}` 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\t/**\n\t * Validate and attach a coupon to the cart. Failures surface as an ApiError with\n\t * status 422 and a machine-readable `reason` (couponNotFound, couponHasExpired,\n\t * couponMaxUsesReached, couponIsNotValidYet, couponMinProductCountNotMet,\n\t * couponMaxProductCountExceeded, couponIsNotApplicable). Returns the updated cart.\n\t */\n\tasync cartCouponApply(params: { cartId: string; code: string }): Promise<APICartCouponApplyResult> {\n\t\tconst pathname = `/carts/${params.cartId}/coupon` as const;\n\t\treturn this.#restRequest<APICartCouponApplyResult>(pathname, \"POST\", { code: params.code });\n\t}\n\n\t/** Detach the applied coupon from the cart, if any. */\n\tasync cartCouponRemove(params: { cartId: string }): Promise<APICartCouponRemoveResult> {\n\t\tconst pathname = `/carts/${params.cartId}/coupon` as const;\n\t\treturn this.#restRequest<APICartCouponRemoveResult>(pathname, \"DELETE\");\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// Custom fields (metafields)\n\t// ============================================\n\t//\n\t// A field is defined once per store (name, kind of value, products or variants) and each\n\t// product or variant then holds its own value under `metafields`. Values are written with\n\t// the product or variant (`productCreate`, `productUpdate`, `variantCreate`,\n\t// `variantUpdate`); the methods here manage the fields and their translations. Variant\n\t// `attributes` keep coming back, derived from the variant's fields.\n\n\t/** The store's fields, in display order. Archived ones only with `includeArchived: \"true\"`. */\n\tasync metafieldDefinitionBrowse(\n\t\tparams: APIMetafieldDefinitionsBrowseQueryParams = {},\n\t): Promise<APIMetafieldDefinitionsBrowseResult> {\n\t\tconst queryParams = new URLSearchParams();\n\t\tif (params.ownerType) queryParams.append(\"ownerType\", params.ownerType);\n\t\tif (params.includeArchived) queryParams.append(\"includeArchived\", params.includeArchived);\n\t\tif (params.lang) queryParams.append(\"lang\", params.lang);\n\t\tif (params.metafields) queryParams.append(\"metafields\", params.metafields);\n\n\t\tconst searchParams = queryParams.size ? `?${queryParams}` : \"\";\n\t\tconst pathname = `/metafield-definitions${searchParams}` as const;\n\t\treturn this.#restRequest<APIMetafieldDefinitionsBrowseResult>(pathname);\n\t}\n\n\t/** One field, by id or by its address `<ownerType>.<namespace>.<key>`, e.g. `product.custom.material`. */\n\tasync metafieldDefinitionGet(\n\t\tparams: APIMetafieldDefinitionParams & APIMetafieldDefinitionGetQueryParams,\n\t): Promise<APIMetafieldDefinitionGetResult | null> {\n\t\tconst queryParams = new URLSearchParams();\n\t\tif (params.lang) queryParams.append(\"lang\", params.lang);\n\t\tif (params.metafields) queryParams.append(\"metafields\", params.metafields);\n\n\t\tconst searchParams = queryParams.size ? `?${queryParams}` : \"\";\n\t\tconst pathname = `/metafield-definitions/${params.idOrKey}${searchParams}` as const;\n\t\treturn this.#restRequestNullable<APIMetafieldDefinitionGetResult>(pathname);\n\t}\n\n\tasync metafieldDefinitionCreate(\n\t\tbody: APIMetafieldDefinitionCreateBody,\n\t): Promise<APIMetafieldDefinitionCreateResult> {\n\t\treturn this.#restRequest<APIMetafieldDefinitionCreateResult>(\"/metafield-definitions\", \"POST\", body);\n\t}\n\n\t/** Name, description, switches, options, limits. The kind of value cannot change here. */\n\tasync metafieldDefinitionUpdate(\n\t\tparams: APIMetafieldDefinitionParams,\n\t\tbody: APIMetafieldDefinitionUpdateBody,\n\t): Promise<APIMetafieldDefinitionUpdateResult> {\n\t\tconst pathname = `/metafield-definitions/${params.idOrKey}` as const;\n\t\treturn this.#restRequest<APIMetafieldDefinitionUpdateResult>(pathname, \"PATCH\", body);\n\t}\n\n\t/**\n\t * Archive: the field leaves the admin, the storefront and the API, every value is kept.\n\t * `metafieldDefinitionRestore` brings it back; `metafieldDefinitionDelete` removes it for good.\n\t */\n\tasync metafieldDefinitionArchive(\n\t\tparams: APIMetafieldDefinitionParams,\n\t): Promise<APIMetafieldDefinitionArchiveResult> {\n\t\tconst pathname = `/metafield-definitions/${params.idOrKey}` as const;\n\t\treturn this.#restRequest<APIMetafieldDefinitionArchiveResult>(pathname, \"DELETE\");\n\t}\n\n\tasync metafieldDefinitionRestore(\n\t\tparams: APIMetafieldDefinitionParams,\n\t): Promise<APIMetafieldDefinitionRestoreResult> {\n\t\tconst pathname = `/metafield-definitions/${params.idOrKey}/restore` as const;\n\t\treturn this.#restRequest<APIMetafieldDefinitionRestoreResult>(pathname, \"POST\");\n\t}\n\n\t/**\n\t * Delete an ARCHIVED field for good, with every value and translation it holds. `confirm`\n\t * repeats the field's key and `expectedValueCount` the number of values it holds (a 409\n\t * tells the real count); both guard against deleting the wrong field.\n\t */\n\tasync metafieldDefinitionDelete(\n\t\tparams: APIMetafieldDefinitionParams,\n\t\tbody: APIMetafieldDefinitionDeleteBody,\n\t): Promise<APIMetafieldDefinitionDeleteResult> {\n\t\tconst pathname = `/metafield-definitions/${params.idOrKey}/purge` as const;\n\t\treturn this.#restRequest<APIMetafieldDefinitionDeleteResult>(pathname, \"POST\", body);\n\t}\n\n\t/**\n\t * What turning a text field into a choice would do: every distinct value in use and a\n\t * suggested grouping into options. Hand the groups and the `planHash` to\n\t * `metafieldDefinitionConvertToChoice`.\n\t */\n\tasync metafieldDefinitionConversionPreview(\n\t\tparams: APIMetafieldDefinitionParams,\n\t): Promise<APIMetafieldDefinitionConversionPreviewResult> {\n\t\tconst pathname = `/metafield-definitions/${params.idOrKey}/convert-to-choice` as const;\n\t\treturn this.#restRequest<APIMetafieldDefinitionConversionPreviewResult>(pathname);\n\t}\n\n\t/** In place: the field keeps its key and id, each value becomes the option of its group. */\n\tasync metafieldDefinitionConvertToChoice(\n\t\tparams: APIMetafieldDefinitionParams,\n\t\tbody: APIMetafieldDefinitionConvertBody,\n\t): Promise<APIMetafieldDefinitionConvertResult> {\n\t\tconst pathname = `/metafield-definitions/${params.idOrKey}/convert-to-choice` as const;\n\t\treturn this.#restRequest<APIMetafieldDefinitionConvertResult>(pathname, \"POST\", body);\n\t}\n\n\t/** The field's name, description and option labels in one language. `null` clears a part. */\n\tasync metafieldDefinitionTranslationPut(\n\t\tparams: APIMetafieldDefinitionTranslationParams,\n\t\tbody: APIMetafieldDefinitionTranslationPutBody,\n\t): Promise<APIMetafieldDefinitionTranslationPutResult> {\n\t\tconst pathname = `/metafield-definitions/${params.idOrKey}/translations/${params.locale}` as const;\n\t\treturn this.#restRequest<APIMetafieldDefinitionTranslationPutResult>(pathname, \"PUT\", body);\n\t}\n\n\t/** Translated values of a product's fields in one language. `value: null` removes one. */\n\tasync productMetafieldTranslationsPut(\n\t\tparams: APIProductMetafieldTranslationsPutParams,\n\t\tbody: APIMetafieldTranslationsPutBody,\n\t): Promise<APIProductMetafieldTranslationsPutResult> {\n\t\tconst pathname = `/products/${params.idOrSlug}/metafields/translations/${params.locale}` as const;\n\t\treturn this.#restRequest<APIProductMetafieldTranslationsPutResult>(pathname, \"PUT\", body);\n\t}\n\n\t/** Translated values of a variant's fields in one language. `value: null` removes one. */\n\tasync variantMetafieldTranslationsPut(\n\t\tparams: APIVariantMetafieldTranslationsPutParams,\n\t\tbody: APIMetafieldTranslationsPutBody,\n\t): Promise<APIVariantMetafieldTranslationsPutResult> {\n\t\tconst pathname = `/variants/${params.idOrSku}/metafields/translations/${params.locale}` as const;\n\t\treturn this.#restRequest<APIVariantMetafieldTranslationsPutResult>(pathname, \"PUT\", body);\n\t}\n\n\t/**\n\t * Machine-translate the field values that have no translation yet. Translations a person\n\t * wrote are never replaced. With `productIds` it runs right away and returns what it wrote;\n\t * without, it starts a background run over the whole catalogue (answered 202 with a `runId`).\n\t */\n\tasync metafieldsTranslateMissing(\n\t\tbody: APIMetafieldsTranslateMissingBody = {},\n\t): Promise<APIMetafieldsTranslateMissingResult> {\n\t\treturn this.#restRequest<APIMetafieldsTranslateMissingResult>(\n\t\t\t\"/metafields/translate-missing\",\n\t\t\t\"POST\",\n\t\t\tbody,\n\t\t);\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","YNS_STORE_ID","env","KEYLESS_LISTS","KEYLESS_SINGLETONS","KEYLESS_DETAILS","NOT_A_RESOURCE","isKeylessPath","path","query","resource","idOrSlug","child","rest","keylessPathname","pathname","storeId","search","active","privateFields","sorted","a","aValue","b","bValue","keyless","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","KEYLESS_REFUSALS","YNSProvider","#config","#logger","getLogger","#storeId","config","token","env","isStaging","endpoint","#restRequest","pathname","method","body","response","#fetchJson","#parseResponse","#restRequestNullable","#resolveStoreId","configured","known","#fetchKeyed","me","storeId","keyless","keylessPathname","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"]}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shopper file uploads for personalised products (a photo for a portrait, a print-ready PDF).
|
|
3
|
+
*
|
|
4
|
+
* Browser-only. The storefront calls `uploadLineItemFile(file, { variantId })` from its product
|
|
5
|
+
* page; the platform hands out a short-lived token for exactly one file (its `/checkout/api/**`
|
|
6
|
+
* endpoint is already forwarded by every tenant's proxy, so the storefront needs no route of its
|
|
7
|
+
* own and no API key in the browser), and the file goes straight into the store's private storage.
|
|
8
|
+
* The returned `uploadId` is what a cart line's file property carries:
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* const { uploadId } = await uploadLineItemFile(file, { variantId });
|
|
12
|
+
* await cartUpsert({ variantId, quantity: 1, properties: [lineItemFileProperty({ key: "photo", label: "Photo", uploadId })] });
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* Requires the store's Customer Uploads module. Images (JPEG, PNG, WebP, GIF, HEIC/HEIF, AVIF,
|
|
16
|
+
* TIFF) and PDF, up to 20 MB.
|
|
17
|
+
*/
|
|
18
|
+
declare const LINE_ITEM_UPLOAD_ENDPOINT = "/checkout/api/line-item-uploads";
|
|
19
|
+
declare const MAX_LINE_ITEM_UPLOAD_BYTES: number;
|
|
20
|
+
declare const ACCEPTED_LINE_ITEM_UPLOAD_TYPES: string;
|
|
21
|
+
declare class LineItemUploadError extends Error {
|
|
22
|
+
readonly status: number;
|
|
23
|
+
constructor(message: string, status: number);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Upload one file for a cart line. Throws `LineItemUploadError` with the platform's message and
|
|
27
|
+
* HTTP status (400 unsupported file, 404 uploads off for this store, 429 too many uploads).
|
|
28
|
+
*/
|
|
29
|
+
declare function uploadLineItemFile(file: File, options: {
|
|
30
|
+
variantId: string;
|
|
31
|
+
/** Defaults to the platform endpoint every tenant proxy forwards. */
|
|
32
|
+
endpoint?: string;
|
|
33
|
+
onUploadProgress?: (event: {
|
|
34
|
+
loaded: number;
|
|
35
|
+
total: number;
|
|
36
|
+
percentage: number;
|
|
37
|
+
}) => void;
|
|
38
|
+
abortSignal?: AbortSignal;
|
|
39
|
+
}): Promise<{
|
|
40
|
+
uploadId: string;
|
|
41
|
+
}>;
|
|
42
|
+
/** The cart line property that attaches an uploaded file. */
|
|
43
|
+
declare const lineItemFileProperty: ({ key, label, uploadId, }: {
|
|
44
|
+
key: string;
|
|
45
|
+
label?: string;
|
|
46
|
+
uploadId: string;
|
|
47
|
+
}) => {
|
|
48
|
+
key: string;
|
|
49
|
+
label?: string;
|
|
50
|
+
type: "file";
|
|
51
|
+
value: string;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export { ACCEPTED_LINE_ITEM_UPLOAD_TYPES, LINE_ITEM_UPLOAD_ENDPOINT, LineItemUploadError, MAX_LINE_ITEM_UPLOAD_BYTES, lineItemFileProperty, uploadLineItemFile };
|