commerce-kit 0.9.1 → 0.10.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 +116 -0
- package/dist/index.d.ts +23 -7
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# commerce-kit
|
|
2
|
+
|
|
3
|
+
TypeScript SDK for the [Your Next Store](https://yournextstore.com) API.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bun add commerce-kit
|
|
9
|
+
# or
|
|
10
|
+
npm install commerce-kit
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { Commerce } from 'commerce-kit';
|
|
17
|
+
|
|
18
|
+
const commerce = Commerce();
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
That's it! The SDK reads `YNS_API_KEY` from environment and auto-detects the endpoint:
|
|
22
|
+
- `sk-live-*` → `https://yns.store`
|
|
23
|
+
- `sk-test-*` → `https://yns.cx`
|
|
24
|
+
|
|
25
|
+
## Products
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
// List products
|
|
29
|
+
const { data, meta } = await commerce.productBrowse({
|
|
30
|
+
limit: 10,
|
|
31
|
+
offset: 0,
|
|
32
|
+
category: 'shoes',
|
|
33
|
+
query: 'running',
|
|
34
|
+
active: true,
|
|
35
|
+
orderBy: 'createdAt',
|
|
36
|
+
orderDirection: 'desc',
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// Get single product by ID or slug
|
|
40
|
+
const product = await commerce.productGet({ idOrSlug: 'running-shoes' });
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Cart
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
// Create or update cart
|
|
47
|
+
const cart = await commerce.cartUpsert({
|
|
48
|
+
cartId: 'cart_123', // optional, creates new if omitted
|
|
49
|
+
variantId: 'variant_456',
|
|
50
|
+
quantity: 2,
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// Get cart
|
|
54
|
+
const cart = await commerce.cartGet({ cartId: 'cart_123' });
|
|
55
|
+
|
|
56
|
+
// Remove item from cart
|
|
57
|
+
await commerce.cartRemoveItem({
|
|
58
|
+
cartId: 'cart_123',
|
|
59
|
+
variantId: 'variant_456',
|
|
60
|
+
});
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Orders
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
// List orders
|
|
67
|
+
const { data, meta } = await commerce.orderBrowse({
|
|
68
|
+
limit: 10,
|
|
69
|
+
offset: 0,
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// Get single order
|
|
73
|
+
const order = await commerce.orderGet({ id: 'order_789' });
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Raw API Requests
|
|
77
|
+
|
|
78
|
+
For endpoints not yet implemented in the SDK, use the `request()` method:
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
// GET request
|
|
82
|
+
const webhooks = await commerce.request<Webhook[]>('/webhooks');
|
|
83
|
+
|
|
84
|
+
// POST with body
|
|
85
|
+
const webhook = await commerce.request<Webhook, CreateWebhookBody>('/webhooks', {
|
|
86
|
+
method: 'POST',
|
|
87
|
+
body: { url: 'https://example.com/hook', events: ['order.created'] },
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// GET with query parameters
|
|
91
|
+
const results = await commerce.request<SearchResult>('/search', {
|
|
92
|
+
query: { q: 'shoes', limit: 5 },
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// Path parameters via template literals
|
|
96
|
+
const variant = await commerce.request<Variant>(`/products/${productId}/variants/${variantId}`);
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## TypeScript
|
|
100
|
+
|
|
101
|
+
All API types are exported:
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
import type {
|
|
105
|
+
APIProductsBrowseResult,
|
|
106
|
+
APIProductGetByIdResult,
|
|
107
|
+
APICartCreateBody,
|
|
108
|
+
APIOrderGetByIdResult,
|
|
109
|
+
YNSConfig,
|
|
110
|
+
CommerceConfig,
|
|
111
|
+
} from 'commerce-kit';
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## License
|
|
115
|
+
|
|
116
|
+
AGPL-3.0-only
|
package/dist/index.d.ts
CHANGED
|
@@ -1,14 +1,26 @@
|
|
|
1
1
|
import { APIProductsBrowseQueryParams, APIProductsBrowseResult, APIProductGetByIdParams, APIProductGetByIdResult, APIOrdersBrowseQueryParams, APIOrdersBrowseResult, APIOrderGetByIdParams, APIOrderGetByIdResult, APICartCreateBody, APICartCreateResult, APICartGetResult } from './api-types.js';
|
|
2
2
|
export { APICartAddBody, APICartAddResult, APICartRemoveItemQueryParams, APICartRemoveItemResult, JSONContent } from './api-types.js';
|
|
3
3
|
|
|
4
|
-
interface
|
|
5
|
-
|
|
6
|
-
endpoint: string;
|
|
7
|
-
token: string;
|
|
4
|
+
interface BaseConfig {
|
|
5
|
+
timeout?: number;
|
|
8
6
|
}
|
|
9
|
-
|
|
7
|
+
interface YNSConfig extends BaseConfig {
|
|
8
|
+
provider?: "yns";
|
|
9
|
+
/** API key (sk-test-* or sk-live-*). Defaults to process.env.YNS_API_KEY */
|
|
10
|
+
token?: string;
|
|
11
|
+
/** Override the auto-detected endpoint */
|
|
12
|
+
endpoint?: string;
|
|
13
|
+
version?: "v1";
|
|
14
|
+
}
|
|
15
|
+
interface StripeConfig extends BaseConfig {
|
|
16
|
+
provider: "stripe";
|
|
17
|
+
secretKey: string;
|
|
18
|
+
}
|
|
19
|
+
type CommerceConfig = YNSConfig | StripeConfig;
|
|
20
|
+
|
|
21
|
+
declare class YNSProvider {
|
|
10
22
|
#private;
|
|
11
|
-
constructor(config
|
|
23
|
+
constructor(config?: YNSConfig);
|
|
12
24
|
productBrowse(params: APIProductsBrowseQueryParams): Promise<APIProductsBrowseResult>;
|
|
13
25
|
productGet(params: APIProductGetByIdParams): Promise<APIProductGetByIdResult | null>;
|
|
14
26
|
orderBrowse(params: APIOrdersBrowseQueryParams): Promise<APIOrdersBrowseResult>;
|
|
@@ -50,4 +62,8 @@ declare class YnsProvider {
|
|
|
50
62
|
}): Promise<TResponse>;
|
|
51
63
|
}
|
|
52
64
|
|
|
53
|
-
|
|
65
|
+
declare function Commerce(): YNSProvider;
|
|
66
|
+
declare function Commerce(config: YNSConfig): YNSProvider;
|
|
67
|
+
declare function Commerce(config: StripeConfig): never;
|
|
68
|
+
|
|
69
|
+
export { APICartCreateBody, APICartCreateResult, APICartGetResult, APIOrderGetByIdParams, APIOrderGetByIdResult, APIOrdersBrowseQueryParams, APIOrdersBrowseResult, APIProductGetByIdParams, APIProductGetByIdResult, APIProductsBrowseQueryParams, APIProductsBrowseResult, type BaseConfig, Commerce, type CommerceConfig, type StripeConfig, type YNSConfig, YNSProvider };
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import"./chunk-PNKB6P4V.js";var
|
|
1
|
+
import"./chunk-PNKB6P4V.js";var i={DEBUG:0,LOG:1,WARN:2,ERROR:3},I=process.env.NEXT_PUBLIC_LOG_LEVEL||"LOG",c=i[I],l="\x1B[0m",R="\x1B[34m",w="\x1B[32m",B="\x1B[33m",E="\x1B[31m",S="\u23F1\uFE0F",h="\u{1F41B}",C="\u2714\uFE0F",$="\u26A0\uFE0F",v="\u274C",m=`${S} `,A=`${R}${h}${l} `,L=`${w}${C}${l} `,N=`${B}${$}${l} `,O=`${E}${v}${l} `,p=a=>{let e=a?`[${a}] `:"";return{getLogger(t){return p([a,t].filter(Boolean).join(" > "))},time(t){c>i.DEBUG||console.time([m,e,t].filter(Boolean).join(" "))},timeEnd(t){c>i.DEBUG||console.timeEnd([m,e,t].filter(Boolean).join(" "))},debug(...t){c>i.DEBUG||console.log(...[A,e,...t].filter(Boolean))},log(...t){c>i.LOG||console.log(...[L,e,...t].filter(Boolean))},dir(t,r){c>i.LOG||console.dir(t,r)},warn(...t){c>i.WARN||console.warn(...[N,e,...t].filter(Boolean))},error(...t){c>i.ERROR||console.error(...[O,e,...t].filter(Boolean))}}},G=p();var P={live:"https://yns.store",test:"https://yns.cx"};var d=class{#t;#r=p("YNSProvider");constructor(e={}){let t=e.token??process.env.YNS_API_KEY;if(!t)throw new Error("YNS API key is required. Set YNS_API_KEY environment variable or pass token in config.");let r=t.startsWith("sk-test-"),s=e.endpoint??(r?P.test:P.live);this.#t={version:"v1",...e,token:t,endpoint:s},this.#r.debug("YNSProvider initialized",{endpoint:s,isTest:r})}async#e(e,t="GET",r){let s=this.#r.getLogger("#restRequest"),n=`${this.#t.endpoint}/api/${this.#t.version}${e}`;s.debug(`Making ${t} request to YNS API: ${n}`);let o=await fetch(n,{method:t,headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.#t.token}`},body:r?JSON.stringify(r):void 0});if(!o.ok){let y=o.headers.get("content-type"),g=`YNS REST request failed: ${t} ${n} ${o.status} ${o.statusText}`;if(y?.includes("application/json"))try{let u=await o.json();g=u.error||u.message||g}catch(u){s.error("Failed to parse YNS error response as JSON",u)}else{let u=await o.text();s.error(`YNS API request failed: ${o.status} ${o.statusText}`,g,u)}throw new Error(g)}let f=o.headers.get("content-type");if(!f?.includes("application/json"))throw new Error(`YNS API returned ${f} instead of JSON for ${e}`);return o.json()}async productBrowse(e){let t=this.#r.getLogger("productBrowse");t.debug("Browsing products with params:",e);let r=new URLSearchParams;e.limit&&r.append("limit",e.limit.toString()),e.offset&&r.append("offset",e.offset.toString()),e.category&&r.append("category",e.category),e.query&&r.append("query",e.query),e.active!==void 0&&r.append("active",e.active.toString()),e.orderBy&&r.append("orderBy",e.orderBy),e.orderDirection&&r.append("orderDirection",e.orderDirection);let n=`/products${r.size?`?${r}`:""}`;t.debug("Constructed pathname:",n);let o=await this.#e(n);return t.debug("Received product browse result:",{meta:o.meta}),o}async productGet(e){let t=`/products/${e.idOrSlug}`,r=await this.#e(t);return r||null}async orderBrowse(e){let t=this.#r.getLogger("orderBrowse");t.debug("Browsing orders with params:",e);let r=new URLSearchParams;e.limit&&r.append("limit",e.limit.toString()),e.offset&&r.append("offset",e.offset.toString());let n=`/orders${r.size?`?${r}`:""}`;t.debug("Constructed pathname:",n);let o=await this.#e(n);return t.debug("Received orders browse result:",{meta:o.meta}),o}async orderGet(e){let t=`/orders/${e.id}`,r=await this.#e(t);return r||null}async cartUpsert(e){return await this.#e("/carts","POST",e)}async cartRemoveItem(e){let t=`/carts/${e.cartId}/line-items/${e.variantId}`,r=await this.#e(t,"DELETE");return null}async cartGet(e){let t=`/carts/${e.cartId}`;return await this.#e(t)}async request(e,t){let r=t?.query?`?${new URLSearchParams(Object.entries(t.query).map(([s,n])=>[s,String(n)]))}`:"";return this.#e(`${e}${r}`,t?.method??"GET",t?.body)}};function T(a={}){let e=a.provider??"yns";switch(e){case"yns":return new d(a);case"stripe":throw new Error("Stripe provider not yet implemented");default:{let t=e;throw new Error(`Unknown provider: ${t}`)}}}export{T as Commerce,d as YNSProvider};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/logger.ts","../src/providers/yns.ts"],"sourcesContent":["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\tAPICartCreateBody,\n\tAPICartCreateResult,\n\tAPICartGetResult,\n\tAPIOrderGetByIdParams,\n\tAPIOrderGetByIdResult,\n\tAPIOrdersBrowseQueryParams,\n\tAPIOrdersBrowseResult,\n\tAPIProductGetByIdParams,\n\tAPIProductGetByIdResult,\n\tAPIProductsBrowseQueryParams,\n\tAPIProductsBrowseResult,\n} from \"../api-types\";\nimport { getLogger } from \"../logger\";\n\ninterface YnsProviderConfig {\n\tversion: \"v1\";\n\tendpoint: string;\n\ttoken: string;\n}\n\nexport class YnsProvider {\n\t#config;\n\t#logger = getLogger(\"YnsProvider\");\n\tconstructor(config: YnsProviderConfig) {\n\t\tthis.#config = config;\n\t\tthis.#logger.debug(\"YnsProvider initialized\");\n\t}\n\n\tasync #restRequest<T>(\n\t\tpathname: `/${string}`,\n\t\tmethod: \"GET\" | \"POST\" | \"PUT\" | \"DELETE\" = \"GET\",\n\t\tbody?: unknown,\n\t): Promise<T> {\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\tconst response = await 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\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 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.query) queryParams.append(\"query\", params.query);\n\t\tif (params.active !== undefined) queryParams.append(\"active\", params.active.toString());\n\t\tif (params.orderBy) queryParams.append(\"orderBy\", params.orderBy);\n\t\tif (params.orderDirection) queryParams.append(\"orderDirection\", params.orderDirection);\n\n\t\tconst searchParams = queryParams.size ? `?${queryParams}` : \"\";\n\t\tconst pathname = `/products${searchParams}` as const;\n\t\tlogger.debug(\"Constructed pathname:\", pathname);\n\t\tconst result = await this.#restRequest<APIProductsBrowseResult>(pathname);\n\t\tlogger.debug(\"Received product browse result:\", { meta: result.meta });\n\t\treturn result;\n\t}\n\n\tasync productGet(params: APIProductGetByIdParams): Promise<APIProductGetByIdResult | null> {\n\t\tconst pathname = `/products/${params.idOrSlug}` as const;\n\n\t\tconst result = await this.#restRequest<APIProductGetByIdResult>(pathname);\n\n\t\tif (!result) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tasync orderBrowse(params: APIOrdersBrowseQueryParams): Promise<APIOrdersBrowseResult> {\n\t\tconst logger = this.#logger.getLogger(\"orderBrowse\");\n\t\tlogger.debug(\"Browsing orders with params:\", params);\n\n\t\tconst queryParams = new URLSearchParams();\n\n\t\tif (params.limit) queryParams.append(\"limit\", params.limit.toString());\n\t\tif (params.offset) queryParams.append(\"offset\", params.offset.toString());\n\n\t\tconst searchParams = queryParams.size ? `?${queryParams}` : \"\";\n\t\tconst pathname = `/orders${searchParams}` as const;\n\t\tlogger.debug(\"Constructed pathname:\", pathname);\n\t\tconst result = await this.#restRequest<APIOrdersBrowseResult>(pathname);\n\t\tlogger.debug(\"Received orders browse result:\", { meta: result.meta });\n\t\treturn result;\n\t}\n\n\tasync orderGet(params: APIOrderGetByIdParams): Promise<APIOrderGetByIdResult | null> {\n\t\tconst pathname = `/orders/${params.id}` as const;\n\n\t\tconst result = await this.#restRequest<APIOrderGetByIdResult>(pathname);\n\n\t\tif (!result) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t// @todo\n\t// async cartAdd(params: APICartAddBody): Promise<APICartAddResult> {\n\t// \tconst body = {\n\t// \t\tvariantId: params.variantId,\n\t// \t\tcartId: params.cartId,\n\t// \t\tquantity: params.quantity,\n\t// \t\tsubscriptionId: params.subscriptionId,\n\t// \t};\n\n\t// \tconst result = await this.#restRequest<APICartCreateResult>(\"/carts\", \"PUT\", 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\tasync cartRemoveItem(params: { cartId: string; variantId: string }): Promise<null> {\n\t\tconst pathname = `/carts/${params.cartId}/line-items/${params.variantId}` as const;\n\t\tconst result = await this.#restRequest<unknown>(pathname, \"DELETE\");\n\t\t// return result;\n\t\treturn null;\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 * 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\" | \"PUT\" | \"DELETE\";\n\t\t\tbody?: TBody;\n\t\t\tquery?: Record<string, string | number | boolean>;\n\t\t},\n\t): Promise<TResponse> {\n\t\tconst queryString = options?.query\n\t\t\t? `?${new URLSearchParams(Object.entries(options.query).map(([k, v]) => [k, String(v)]))}`\n\t\t\t: \"\";\n\n\t\treturn this.#restRequest<TResponse>(\n\t\t\t`${pathname}${queryString}` as `/${string}`,\n\t\t\toptions?.method ?? \"GET\",\n\t\t\toptions?.body,\n\t\t);\n\t}\n}\n"],"mappings":"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","names":["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","#restRequest","pathname","method","body","logger","endpoint","response","contentType","errorMessage","errorData","error","errorText","params","queryParams","result","options","queryString","k","v"]}
|
|
1
|
+
{"version":3,"sources":["../src/logger.ts","../src/types.ts","../src/providers/yns.ts","../src/commerce.ts"],"sourcesContent":["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","export interface BaseConfig {\n\ttimeout?: number;\n}\n\nexport interface YNSConfig extends BaseConfig {\n\tprovider?: \"yns\";\n\t/** API key (sk-test-* or sk-live-*). Defaults to process.env.YNS_API_KEY */\n\ttoken?: string;\n\t/** Override the auto-detected endpoint */\n\tendpoint?: string;\n\tversion?: \"v1\";\n}\n\nexport const YNS_ENDPOINTS = {\n\tlive: \"https://yns.store\",\n\ttest: \"https://yns.cx\",\n} as const;\n\nexport interface StripeConfig extends BaseConfig {\n\tprovider: \"stripe\";\n\tsecretKey: string;\n}\n\nexport type CommerceConfig = YNSConfig | StripeConfig;\n","import type {\n\tAPICartCreateBody,\n\tAPICartCreateResult,\n\tAPICartGetResult,\n\tAPIOrderGetByIdParams,\n\tAPIOrderGetByIdResult,\n\tAPIOrdersBrowseQueryParams,\n\tAPIOrdersBrowseResult,\n\tAPIProductGetByIdParams,\n\tAPIProductGetByIdResult,\n\tAPIProductsBrowseQueryParams,\n\tAPIProductsBrowseResult,\n} from \"../api-types\";\nimport { getLogger } from \"../logger\";\nimport { YNS_ENDPOINTS, type YNSConfig } from \"../types\";\n\nexport class YNSProvider {\n\t#config: YNSConfig & { token: string; endpoint: string; version: \"v1\" };\n\t#logger = getLogger(\"YNSProvider\");\n\tconstructor(config: YNSConfig = {}) {\n\t\tconst token = config.token ?? process.env.YNS_API_KEY;\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 isTest = token.startsWith(\"sk-test-\");\n\t\tconst endpoint = config.endpoint ?? (isTest ? YNS_ENDPOINTS.test : YNS_ENDPOINTS.live);\n\t\tthis.#config = { version: \"v1\", ...config, token, endpoint };\n\t\tthis.#logger.debug(\"YNSProvider initialized\", { endpoint, isTest });\n\t}\n\n\tasync #restRequest<T>(\n\t\tpathname: `/${string}`,\n\t\tmethod: \"GET\" | \"POST\" | \"PUT\" | \"DELETE\" = \"GET\",\n\t\tbody?: unknown,\n\t): Promise<T> {\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\tconst response = await 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\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 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.query) queryParams.append(\"query\", params.query);\n\t\tif (params.active !== undefined) queryParams.append(\"active\", params.active.toString());\n\t\tif (params.orderBy) queryParams.append(\"orderBy\", params.orderBy);\n\t\tif (params.orderDirection) queryParams.append(\"orderDirection\", params.orderDirection);\n\n\t\tconst searchParams = queryParams.size ? `?${queryParams}` : \"\";\n\t\tconst pathname = `/products${searchParams}` as const;\n\t\tlogger.debug(\"Constructed pathname:\", pathname);\n\t\tconst result = await this.#restRequest<APIProductsBrowseResult>(pathname);\n\t\tlogger.debug(\"Received product browse result:\", { meta: result.meta });\n\t\treturn result;\n\t}\n\n\tasync productGet(params: APIProductGetByIdParams): Promise<APIProductGetByIdResult | null> {\n\t\tconst pathname = `/products/${params.idOrSlug}` as const;\n\n\t\tconst result = await this.#restRequest<APIProductGetByIdResult>(pathname);\n\n\t\tif (!result) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tasync orderBrowse(params: APIOrdersBrowseQueryParams): Promise<APIOrdersBrowseResult> {\n\t\tconst logger = this.#logger.getLogger(\"orderBrowse\");\n\t\tlogger.debug(\"Browsing orders with params:\", params);\n\n\t\tconst queryParams = new URLSearchParams();\n\n\t\tif (params.limit) queryParams.append(\"limit\", params.limit.toString());\n\t\tif (params.offset) queryParams.append(\"offset\", params.offset.toString());\n\n\t\tconst searchParams = queryParams.size ? `?${queryParams}` : \"\";\n\t\tconst pathname = `/orders${searchParams}` as const;\n\t\tlogger.debug(\"Constructed pathname:\", pathname);\n\t\tconst result = await this.#restRequest<APIOrdersBrowseResult>(pathname);\n\t\tlogger.debug(\"Received orders browse result:\", { meta: result.meta });\n\t\treturn result;\n\t}\n\n\tasync orderGet(params: APIOrderGetByIdParams): Promise<APIOrderGetByIdResult | null> {\n\t\tconst pathname = `/orders/${params.id}` as const;\n\n\t\tconst result = await this.#restRequest<APIOrderGetByIdResult>(pathname);\n\n\t\tif (!result) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t// @todo\n\t// async cartAdd(params: APICartAddBody): Promise<APICartAddResult> {\n\t// \tconst body = {\n\t// \t\tvariantId: params.variantId,\n\t// \t\tcartId: params.cartId,\n\t// \t\tquantity: params.quantity,\n\t// \t\tsubscriptionId: params.subscriptionId,\n\t// \t};\n\n\t// \tconst result = await this.#restRequest<APICartCreateResult>(\"/carts\", \"PUT\", 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\tasync cartRemoveItem(params: { cartId: string; variantId: string }): Promise<null> {\n\t\tconst pathname = `/carts/${params.cartId}/line-items/${params.variantId}` as const;\n\t\tconst result = await this.#restRequest<unknown>(pathname, \"DELETE\");\n\t\t// return result;\n\t\treturn null;\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 * 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\" | \"PUT\" | \"DELETE\";\n\t\t\tbody?: TBody;\n\t\t\tquery?: Record<string, string | number | boolean>;\n\t\t},\n\t): Promise<TResponse> {\n\t\tconst queryString = options?.query\n\t\t\t? `?${new URLSearchParams(Object.entries(options.query).map(([k, v]) => [k, String(v)]))}`\n\t\t\t: \"\";\n\n\t\treturn this.#restRequest<TResponse>(\n\t\t\t`${pathname}${queryString}` as `/${string}`,\n\t\t\toptions?.method ?? \"GET\",\n\t\t\toptions?.body,\n\t\t);\n\t}\n}\n","import { YNSProvider } from \"./providers/yns\";\nimport type { CommerceConfig, StripeConfig, YNSConfig } from \"./types\";\n\nexport function Commerce(): YNSProvider;\nexport function Commerce(config: YNSConfig): YNSProvider;\nexport function Commerce(config: StripeConfig): never;\nexport function Commerce(config: CommerceConfig = {}): YNSProvider {\n\tconst provider = config.provider ?? \"yns\";\n\n\tswitch (provider) {\n\t\tcase \"yns\":\n\t\t\treturn new YNSProvider(config as YNSConfig);\n\t\tcase \"stripe\":\n\t\t\tthrow new Error(\"Stripe provider not yet implemented\");\n\t\tdefault: {\n\t\t\tconst _exhaustive: never = provider;\n\t\t\tthrow new Error(`Unknown provider: ${_exhaustive}`);\n\t\t}\n\t}\n}\n"],"mappings":"4BAgBA,IAAMA,EAAW,CAChB,MAAO,EACP,IAAK,EACL,KAAM,EACN,MAAO,CACR,EAGMC,EAAe,QAAQ,IAAI,uBAAyB,MACpDC,EAAgBF,EAASC,CAAW,EAEpCE,EAAQ,UACRC,EAAO,WACPC,EAAQ,WACRC,EAAS,WACTC,EAAM,WAENC,EAAO,eACPC,EAAQ,YACRC,EAAK,eACLC,EAAO,eACPC,EAAQ,SAERC,EAAc,GAAGL,CAAI,IACrBM,EAAe,GAAGV,CAAI,GAAGK,CAAK,GAAGN,CAAK,IACtCY,EAAY,GAAGV,CAAK,GAAGK,CAAE,GAAGP,CAAK,IACjCa,EAAc,GAAGV,CAAM,GAAGK,CAAI,GAAGR,CAAK,IACtCc,EAAe,GAAGV,CAAG,GAAGK,CAAK,GAAGT,CAAK,IAE9Be,EAAaC,GAAwB,CACjD,IAAMC,EAASD,EAAa,IAAIA,CAAU,KAAO,GACjD,MAAO,CACN,UAAUE,EAAuB,CAChC,OAAOH,EAAU,CAACC,EAAYE,CAAa,EAAE,OAAO,OAAO,EAAE,KAAK,KAAK,CAAC,CACzE,EACA,KAAKC,EAAe,CACfpB,EAAgBF,EAAS,OAC7B,QAAQ,KAAK,CAACa,EAAaO,EAAQE,CAAK,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,CAAC,CACpE,EACA,QAAQA,EAAe,CAClBpB,EAAgBF,EAAS,OAC7B,QAAQ,QAAQ,CAACa,EAAaO,EAAQE,CAAK,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,CAAC,CACvE,EACA,SAASC,EAAgB,CACpBrB,EAAgBF,EAAS,OAC7B,QAAQ,IAAI,GAAG,CAACc,EAAcM,EAAQ,GAAGG,CAAI,EAAE,OAAO,OAAO,CAAC,CAC/D,EACA,OAAOA,EAAgB,CAClBrB,EAAgBF,EAAS,KAC7B,QAAQ,IAAI,GAAG,CAACe,EAAWK,EAAQ,GAAGG,CAAI,EAAE,OAAO,OAAO,CAAC,CAC5D,EACA,IAAIC,EAAgBC,EAA0B,CACzCvB,EAAgBF,EAAS,KAC7B,QAAQ,IAAIwB,EAAMC,CAAO,CAC1B,EACA,QAAQF,EAAgB,CACnBrB,EAAgBF,EAAS,MAC7B,QAAQ,KAAK,GAAG,CAACgB,EAAaI,EAAQ,GAAGG,CAAI,EAAE,OAAO,OAAO,CAAC,CAC/D,EACA,SAASA,EAAgB,CACpBrB,EAAgBF,EAAS,OAC7B,QAAQ,MAAM,GAAG,CAACiB,EAAcG,EAAQ,GAAGG,CAAI,EAAE,OAAO,OAAO,CAAC,CACjE,CACD,CACD,EAEaG,EAASR,EAAU,ECrEzB,IAAMS,EAAgB,CAC5B,KAAM,oBACN,KAAM,gBACP,ECAO,IAAMC,EAAN,KAAkB,CACxBC,GACAC,GAAUC,EAAU,aAAa,EACjC,YAAYC,EAAoB,CAAC,EAAG,CACnC,IAAMC,EAAQD,EAAO,OAAS,QAAQ,IAAI,YAC1C,GAAI,CAACC,EACJ,MAAM,IAAI,MACT,wFACD,EAED,IAAMC,EAASD,EAAM,WAAW,UAAU,EACpCE,EAAWH,EAAO,WAAaE,EAASE,EAAc,KAAOA,EAAc,MACjF,KAAKP,GAAU,CAAE,QAAS,KAAM,GAAGG,EAAQ,MAAAC,EAAO,SAAAE,CAAS,EAC3D,KAAKL,GAAQ,MAAM,0BAA2B,CAAE,SAAAK,EAAU,OAAAD,CAAO,CAAC,CACnE,CAEA,KAAMG,GACLC,EACAC,EAA4C,MAC5CC,EACa,CACb,IAAMC,EAAS,KAAKX,GAAQ,UAAU,cAAc,EAE9CK,EAAW,GAAG,KAAKN,GAAQ,QAAQ,QAAQ,KAAKA,GAAQ,OAAO,GAAGS,CAAQ,GAChFG,EAAO,MAAM,UAAUF,CAAM,wBAAwBJ,CAAQ,EAAE,EAC/D,IAAMO,EAAW,MAAM,MAAMP,EAAU,CACtC,OAAAI,EACA,QAAS,CACR,eAAgB,mBAChB,cAAe,UAAU,KAAKV,GAAQ,KAAK,EAC5C,EACA,KAAMW,EAAO,KAAK,UAAUA,CAAI,EAAI,MACrC,CAAC,EAED,GAAI,CAACE,EAAS,GAAI,CAEjB,IAAMC,EAAcD,EAAS,QAAQ,IAAI,cAAc,EACnDE,EAAe,4BAA4BL,CAAM,IAAIJ,CAAQ,IAAIO,EAAS,MAAM,IAAIA,EAAS,UAAU,GAE3G,GAAIC,GAAa,SAAS,kBAAkB,EAC3C,GAAI,CACH,IAAME,EAAY,MAAMH,EAAS,KAAK,EACtCE,EAAeC,EAAU,OAASA,EAAU,SAAWD,CACxD,OAASE,EAAO,CACfL,EAAO,MAAM,6CAA8CK,CAAK,CACjE,KACM,CACN,IAAMC,EAAY,MAAML,EAAS,KAAK,EACtCD,EAAO,MACN,2BAA2BC,EAAS,MAAM,IAAIA,EAAS,UAAU,GACjEE,EACAG,CACD,CACD,CAEA,MAAM,IAAI,MAAMH,CAAY,CAC7B,CAGA,IAAMD,EAAcD,EAAS,QAAQ,IAAI,cAAc,EACvD,GAAI,CAACC,GAAa,SAAS,kBAAkB,EAC5C,MAAM,IAAI,MAAM,oBAAoBA,CAAW,wBAAwBL,CAAQ,EAAE,EAGlF,OAAOI,EAAS,KAAK,CACtB,CAEA,MAAM,cAAcM,EAAwE,CAC3F,IAAMP,EAAS,KAAKX,GAAQ,UAAU,eAAe,EACrDW,EAAO,MAAM,iCAAkCO,CAAM,EAErD,IAAMC,EAAc,IAAI,gBACpBD,EAAO,OAAOC,EAAY,OAAO,QAASD,EAAO,MAAM,SAAS,CAAC,EACjEA,EAAO,QAAQC,EAAY,OAAO,SAAUD,EAAO,OAAO,SAAS,CAAC,EACpEA,EAAO,UAAUC,EAAY,OAAO,WAAYD,EAAO,QAAQ,EAC/DA,EAAO,OAAOC,EAAY,OAAO,QAASD,EAAO,KAAK,EACtDA,EAAO,SAAW,QAAWC,EAAY,OAAO,SAAUD,EAAO,OAAO,SAAS,CAAC,EAClFA,EAAO,SAASC,EAAY,OAAO,UAAWD,EAAO,OAAO,EAC5DA,EAAO,gBAAgBC,EAAY,OAAO,iBAAkBD,EAAO,cAAc,EAGrF,IAAMV,EAAW,YADIW,EAAY,KAAO,IAAIA,CAAW,GAAK,EACnB,GACzCR,EAAO,MAAM,wBAAyBH,CAAQ,EAC9C,IAAMY,EAAS,MAAM,KAAKb,GAAsCC,CAAQ,EACxE,OAAAG,EAAO,MAAM,kCAAmC,CAAE,KAAMS,EAAO,IAAK,CAAC,EAC9DA,CACR,CAEA,MAAM,WAAWF,EAA0E,CAC1F,IAAMV,EAAW,aAAaU,EAAO,QAAQ,GAEvCE,EAAS,MAAM,KAAKb,GAAsCC,CAAQ,EAExE,OAAKY,GACG,IAIT,CAEA,MAAM,YAAYF,EAAoE,CACrF,IAAMP,EAAS,KAAKX,GAAQ,UAAU,aAAa,EACnDW,EAAO,MAAM,+BAAgCO,CAAM,EAEnD,IAAMC,EAAc,IAAI,gBAEpBD,EAAO,OAAOC,EAAY,OAAO,QAASD,EAAO,MAAM,SAAS,CAAC,EACjEA,EAAO,QAAQC,EAAY,OAAO,SAAUD,EAAO,OAAO,SAAS,CAAC,EAGxE,IAAMV,EAAW,UADIW,EAAY,KAAO,IAAIA,CAAW,GAAK,EACrB,GACvCR,EAAO,MAAM,wBAAyBH,CAAQ,EAC9C,IAAMY,EAAS,MAAM,KAAKb,GAAoCC,CAAQ,EACtE,OAAAG,EAAO,MAAM,iCAAkC,CAAE,KAAMS,EAAO,IAAK,CAAC,EAC7DA,CACR,CAEA,MAAM,SAASF,EAAsE,CACpF,IAAMV,EAAW,WAAWU,EAAO,EAAE,GAE/BE,EAAS,MAAM,KAAKb,GAAoCC,CAAQ,EAEtE,OAAKY,GACG,IAIT,CAeA,MAAM,WAAWV,EAAuD,CAEvE,OADe,MAAM,KAAKH,GAAkC,SAAU,OAAQG,CAAI,CAEnF,CAEA,MAAM,eAAeQ,EAA8D,CAClF,IAAMV,EAAW,UAAUU,EAAO,MAAM,eAAeA,EAAO,SAAS,GACjEE,EAAS,MAAM,KAAKb,GAAsBC,EAAU,QAAQ,EAElE,OAAO,IACR,CAEA,MAAM,QAAQU,EAA8D,CAC3E,IAAMV,EAAW,UAAUU,EAAO,MAAM,GAExC,OADe,MAAM,KAAKX,GAA+BC,CAAQ,CAElE,CAwBA,MAAM,QACLA,EACAa,EAKqB,CACrB,IAAMC,EAAcD,GAAS,MAC1B,IAAI,IAAI,gBAAgB,OAAO,QAAQA,EAAQ,KAAK,EAAE,IAAI,CAAC,CAACE,EAAGC,CAAC,IAAM,CAACD,EAAG,OAAOC,CAAC,CAAC,CAAC,CAAC,CAAC,GACtF,GAEH,OAAO,KAAKjB,GACX,GAAGC,CAAQ,GAAGc,CAAW,GACzBD,GAAS,QAAU,MACnBA,GAAS,IACV,CACD,CACD,EClNO,SAASI,EAASC,EAAyB,CAAC,EAAgB,CAClE,IAAMC,EAAWD,EAAO,UAAY,MAEpC,OAAQC,EAAU,CACjB,IAAK,MACJ,OAAO,IAAIC,EAAYF,CAAmB,EAC3C,IAAK,SACJ,MAAM,IAAI,MAAM,qCAAqC,EACtD,QAAS,CACR,IAAMG,EAAqBF,EAC3B,MAAM,IAAI,MAAM,qBAAqBE,CAAW,EAAE,CACnD,CACD,CACD","names":["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","YNS_ENDPOINTS","YNSProvider","#config","#logger","getLogger","config","token","isTest","endpoint","YNS_ENDPOINTS","#restRequest","pathname","method","body","logger","response","contentType","errorMessage","errorData","error","errorText","params","queryParams","result","options","queryString","k","v","Commerce","config","provider","YNSProvider","_exhaustive"]}
|