@sdg.la/wishlist-stack-sdk 0.9.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 +279 -0
- package/dist/index.cjs +371 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +348 -0
- package/dist/index.d.ts +348 -0
- package/dist/index.js +363 -0
- package/dist/index.js.map +1 -0
- package/package.json +32 -0
package/README.md
ADDED
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
# @sdg.la/wishlist-stack-sdk
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@sdg.la/wishlist-stack-sdk)
|
|
4
|
+
[](https://www.typescriptlang.org/)
|
|
5
|
+
|
|
6
|
+
TypeScript/JavaScript SDK for the Wishlist Stack API.
|
|
7
|
+
|
|
8
|
+
## Table of Contents
|
|
9
|
+
|
|
10
|
+
- [Features](#features)
|
|
11
|
+
- [Requirements](#requirements)
|
|
12
|
+
- [Installation](#installation)
|
|
13
|
+
- [Quick Start](#quick-start)
|
|
14
|
+
- [Usage](#usage)
|
|
15
|
+
- [Server / Node.js / Workers](#server--nodejs--workers)
|
|
16
|
+
- [Browser](#browser)
|
|
17
|
+
- [Class API](#class-api)
|
|
18
|
+
- [Error Handling](#error-handling)
|
|
19
|
+
- [Pagination](#pagination)
|
|
20
|
+
- [API Reference](#api-reference)
|
|
21
|
+
- [Groups](#groups)
|
|
22
|
+
- [Lists](#lists)
|
|
23
|
+
- [Shared](#shared)
|
|
24
|
+
- [TypeScript Types](#typescript-types)
|
|
25
|
+
- [Related Packages](#related-packages)
|
|
26
|
+
- [License](#license)
|
|
27
|
+
|
|
28
|
+
## Features
|
|
29
|
+
|
|
30
|
+
- **TypeScript-first** — Full type definitions with exported types for all requests and responses
|
|
31
|
+
- **Universal** — Works in Node.js, browsers, and edge runtimes (Cloudflare Workers, Deno, etc.)
|
|
32
|
+
- **Flexible API** — Choose between functional `createWishlistStackClient()` or class-based `new WishlistStackClient()`
|
|
33
|
+
- **Built-in error handling** — Structured `WishlistStackApiError` with status codes and API error messages
|
|
34
|
+
- **Pagination support** — All list endpoints support `page` and `pageSize` parameters
|
|
35
|
+
|
|
36
|
+
## Requirements
|
|
37
|
+
|
|
38
|
+
- **Node.js 18+** (uses native `fetch`) or provide a custom `fetch` implementation
|
|
39
|
+
- **Modern browsers** with native `fetch` support
|
|
40
|
+
|
|
41
|
+
## Installation
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
npm install @sdg.la/wishlist-stack-sdk
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
yarn add @sdg.la/wishlist-stack-sdk
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
pnpm add @sdg.la/wishlist-stack-sdk
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Quick Start
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
import { createWishlistStackClient } from '@sdg.la/wishlist-stack-sdk';
|
|
59
|
+
|
|
60
|
+
const client = createWishlistStackClient({
|
|
61
|
+
apiKey: 'your-merchant-api-key',
|
|
62
|
+
customerAccessToken: 'customer-access-token', // required for authenticated endpoints
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// Fetch all groups
|
|
66
|
+
const { groups } = await client.groups.getAll();
|
|
67
|
+
|
|
68
|
+
// Fetch all lists
|
|
69
|
+
const { lists } = await client.lists.getAll();
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Usage
|
|
73
|
+
|
|
74
|
+
### Server / Node.js / Workers
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
import { createWishlistStackClient } from '@sdg.la/wishlist-stack-sdk';
|
|
78
|
+
|
|
79
|
+
const client = createWishlistStackClient({
|
|
80
|
+
apiKey: process.env.WISHLIST_STACK_API_KEY!,
|
|
81
|
+
baseUrl: process.env.WISHLIST_STACK_BASE_URL, // optional, defaults to production
|
|
82
|
+
customerAccessToken: '...customer_access_token...',
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
const { groups } = await client.groups.getAll();
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Browser
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
import { createWishlistStackClient } from '@sdg.la/wishlist-stack-sdk';
|
|
92
|
+
|
|
93
|
+
const client = createWishlistStackClient({
|
|
94
|
+
apiKey: 'YOUR_API_KEY',
|
|
95
|
+
baseUrl: 'https://wishlist-js.fly.dev', // optional
|
|
96
|
+
customerAccessToken: '...optional...',
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
const { lists } = await client.lists.getAll();
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
> **Note:** If you use a strict Content Security Policy (CSP), you must allow your API domain in `connect-src`.
|
|
103
|
+
|
|
104
|
+
### Class API
|
|
105
|
+
|
|
106
|
+
If you prefer a class-based API, use `WishlistStackSDK`:
|
|
107
|
+
|
|
108
|
+
```ts
|
|
109
|
+
import { WishlistStackSDK } from '@sdg.la/wishlist-stack-sdk';
|
|
110
|
+
|
|
111
|
+
const client = new WishlistStackSDK({
|
|
112
|
+
apiKey: process.env.WISHLIST_STACK_API_KEY!,
|
|
113
|
+
baseUrl: process.env.WISHLIST_STACK_BASE_URL,
|
|
114
|
+
customerAccessToken: '...optional...',
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
await client.groups.getAll();
|
|
118
|
+
await client.lists.getById('list-id');
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
**Back-compat aliases** are available on the class:
|
|
122
|
+
|
|
123
|
+
```ts
|
|
124
|
+
await client.getGroups(); // alias for client.groups.getAll()
|
|
125
|
+
await client.getGroupById('id'); // alias for client.groups.getById('id')
|
|
126
|
+
await client.getLists(); // alias for client.lists.getAll()
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Error Handling
|
|
130
|
+
|
|
131
|
+
Non-2xx responses throw `WishlistStackApiError`. Use the `isWishlistStackApiError` type guard for safe handling:
|
|
132
|
+
|
|
133
|
+
```ts
|
|
134
|
+
import { isWishlistStackApiError } from '@sdg.la/wishlist-stack-sdk';
|
|
135
|
+
|
|
136
|
+
try {
|
|
137
|
+
await client.groups.getAll();
|
|
138
|
+
} catch (error) {
|
|
139
|
+
if (isWishlistStackApiError(error)) {
|
|
140
|
+
console.log(error.status); // HTTP status code
|
|
141
|
+
console.log(error.apiErrors); // Array of { message, field? }
|
|
142
|
+
console.log(error.apiErrorMessages); // Array of error message strings
|
|
143
|
+
console.log(error.requestId); // Request ID for debugging
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Pagination
|
|
149
|
+
|
|
150
|
+
Endpoints that return lists support pagination via query parameters:
|
|
151
|
+
|
|
152
|
+
```ts
|
|
153
|
+
// Paginate groups
|
|
154
|
+
await client.groups.getAll({ page: 2, pageSize: 10 });
|
|
155
|
+
|
|
156
|
+
// Paginate lists within a group
|
|
157
|
+
await client.groups.getById('group-id', { page: 1, pageSize: 25 });
|
|
158
|
+
|
|
159
|
+
// Paginate items within a list
|
|
160
|
+
await client.lists.getById('list-id', { page: 1, pageSize: 25 });
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
**Pagination response structure:**
|
|
164
|
+
|
|
165
|
+
```ts
|
|
166
|
+
{
|
|
167
|
+
page: number;
|
|
168
|
+
pageSize: number;
|
|
169
|
+
totalCount: number;
|
|
170
|
+
totalPages: number;
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## API Reference
|
|
175
|
+
|
|
176
|
+
### Groups
|
|
177
|
+
|
|
178
|
+
| Method | Endpoint | Description |
|
|
179
|
+
|--------|----------|-------------|
|
|
180
|
+
| `groups.getAll(query?)` | `GET /api/groups` | Fetch all groups for the authenticated customer |
|
|
181
|
+
| `groups.getById(groupId, query?)` | `GET /api/groups/{groupId}` | Fetch a single group by ID (lists are paginated) |
|
|
182
|
+
| `groups.create(body)` | `POST /api/groups` | Create a new group |
|
|
183
|
+
| `groups.update(groupId, body)` | `PATCH /api/groups/{groupId}` | Update group name/description |
|
|
184
|
+
| `groups.remove(groupId)` | `DELETE /api/groups/{groupId}` | Remove a group |
|
|
185
|
+
| `groups.reorder(groupId, body)` | `POST /api/groups/{groupId}/reorder` | Reorder lists within a group |
|
|
186
|
+
| `groups.share(groupId)` | `POST /api/groups/{groupId}/share` | Mark a group as shared (public read-only) |
|
|
187
|
+
| `groups.unshare(groupId)` | `DELETE /api/groups/{groupId}/share` | Revoke sharing for a group |
|
|
188
|
+
|
|
189
|
+
**Parameters:**
|
|
190
|
+
|
|
191
|
+
```ts
|
|
192
|
+
// Query parameters (for getAll, getById)
|
|
193
|
+
{ page?: number; pageSize?: number }
|
|
194
|
+
|
|
195
|
+
// Create/Update body
|
|
196
|
+
{ name?: string; description?: string }
|
|
197
|
+
|
|
198
|
+
// Reorder body
|
|
199
|
+
{ listIds: string[] }
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Lists
|
|
203
|
+
|
|
204
|
+
| Method | Endpoint | Description |
|
|
205
|
+
|--------|----------|-------------|
|
|
206
|
+
| `lists.getAll(query?)` | `GET /api/lists` | Fetch all lists for the authenticated customer |
|
|
207
|
+
| `lists.getById(listId, query?)` | `GET /api/lists/{listId}` | Fetch a single list by ID (items are paginated) |
|
|
208
|
+
| `lists.create(body)` | `POST /api/lists` | Create a new list |
|
|
209
|
+
| `lists.update(listId, body)` | `PATCH /api/lists/{listId}` | Update list name/description |
|
|
210
|
+
| `lists.remove(listId)` | `DELETE /api/lists/{listId}` | Remove a list |
|
|
211
|
+
| `lists.addItems(listId, body)` | `POST /api/lists/{listId}/add` | Add items to a list |
|
|
212
|
+
| `lists.updateItem(listId, itemId, body)` | `PATCH /api/lists/{listId}/items/{itemId}` | Update an item on a list |
|
|
213
|
+
| `lists.removeItem(listId, itemId)` | `DELETE /api/lists/{listId}/items/{itemId}` | Remove an item from a list |
|
|
214
|
+
| `lists.share(listId)` | `POST /api/lists/{listId}/share` | Mark a list as shared (public read-only) |
|
|
215
|
+
| `lists.unshare(listId)` | `DELETE /api/lists/{listId}/share` | Revoke sharing for a list |
|
|
216
|
+
|
|
217
|
+
**Parameters:**
|
|
218
|
+
|
|
219
|
+
```ts
|
|
220
|
+
// Query parameters (for getAll, getById)
|
|
221
|
+
{ page?: number; pageSize?: number }
|
|
222
|
+
|
|
223
|
+
// Create/Update body
|
|
224
|
+
{ name?: string; description?: string }
|
|
225
|
+
|
|
226
|
+
// Add items body
|
|
227
|
+
{ items: Array<{ variantId: string; quantity?: number; note?: string }> }
|
|
228
|
+
|
|
229
|
+
// Update item body
|
|
230
|
+
{ quantity?: number; note?: string }
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### Shared
|
|
234
|
+
|
|
235
|
+
Public read-only endpoints for accessing shared lists and groups:
|
|
236
|
+
|
|
237
|
+
| Method | Endpoint | Description |
|
|
238
|
+
|--------|----------|-------------|
|
|
239
|
+
| `shared.getSharedList(listId)` | `GET /api/shared/list/{listId}` | Fetch a public shared list |
|
|
240
|
+
| `shared.getSharedGroup(groupId)` | `GET /api/shared/group/{groupId}` | Fetch a public shared group |
|
|
241
|
+
|
|
242
|
+
## TypeScript Types
|
|
243
|
+
|
|
244
|
+
The package exports all types for use in your application:
|
|
245
|
+
|
|
246
|
+
```ts
|
|
247
|
+
import type {
|
|
248
|
+
// Client types
|
|
249
|
+
CreateWishlistStackClientOptions,
|
|
250
|
+
WishlistStackClient,
|
|
251
|
+
|
|
252
|
+
// Error types
|
|
253
|
+
WishlistStackApiError,
|
|
254
|
+
WishlistStackApiErrorDetails,
|
|
255
|
+
|
|
256
|
+
// Response types
|
|
257
|
+
GetGroupsResponse,
|
|
258
|
+
GetGroupResponse,
|
|
259
|
+
GroupSummary,
|
|
260
|
+
GroupDetail,
|
|
261
|
+
GetListsResponse,
|
|
262
|
+
GetListResponse,
|
|
263
|
+
ListSummary,
|
|
264
|
+
ListDetail,
|
|
265
|
+
HydratedWishlistItem,
|
|
266
|
+
HydratedProduct,
|
|
267
|
+
HydratedVariant,
|
|
268
|
+
|
|
269
|
+
// Common types
|
|
270
|
+
Pagination,
|
|
271
|
+
PaginationParams,
|
|
272
|
+
} from '@sdg.la/wishlist-stack-sdk';
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
## Related Packages
|
|
276
|
+
|
|
277
|
+
| Package | Description |
|
|
278
|
+
|---------|-------------|
|
|
279
|
+
| [`@sdg.la/wishlist-stack-hydrogen`](https://www.npmjs.com/package/@sdg.la/wishlist-stack-hydrogen) | Hydrogen/Remix integration with React hooks and middleware |
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
5
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
6
|
+
|
|
7
|
+
// src/constants.ts
|
|
8
|
+
var MAX_PAGINATION_SIZE = 25;
|
|
9
|
+
var BASE_URL = "https://wishlist-js.fly.dev";
|
|
10
|
+
|
|
11
|
+
// src/client/query.ts
|
|
12
|
+
function toQueryString(query) {
|
|
13
|
+
if (!query) return "";
|
|
14
|
+
const params = new URLSearchParams();
|
|
15
|
+
for (const [key, value] of Object.entries(query)) {
|
|
16
|
+
if (value === void 0 || value === null) continue;
|
|
17
|
+
if (Array.isArray(value)) {
|
|
18
|
+
for (const v of value) {
|
|
19
|
+
if (v === void 0 || v === null) continue;
|
|
20
|
+
params.append(key, String(v));
|
|
21
|
+
}
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
params.set(key, String(value));
|
|
25
|
+
}
|
|
26
|
+
const qs = params.toString();
|
|
27
|
+
return qs ? `?${qs}` : "";
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// src/client/errors.ts
|
|
31
|
+
function isRecord(value) {
|
|
32
|
+
return typeof value === "object" && value !== null;
|
|
33
|
+
}
|
|
34
|
+
function isApiErrorItemLike(value) {
|
|
35
|
+
return isRecord(value) && "message" in value;
|
|
36
|
+
}
|
|
37
|
+
function extractApiErrors(body) {
|
|
38
|
+
if (!isRecord(body)) return void 0;
|
|
39
|
+
const errors = body.errors;
|
|
40
|
+
if (!Array.isArray(errors)) return void 0;
|
|
41
|
+
const out = [];
|
|
42
|
+
for (const e of errors) {
|
|
43
|
+
if (!isApiErrorItemLike(e)) continue;
|
|
44
|
+
const msg = typeof e.message === "string" ? e.message : void 0;
|
|
45
|
+
if (!msg) continue;
|
|
46
|
+
const field = typeof e.field === "string" ? e.field : void 0;
|
|
47
|
+
out.push(field ? { message: msg, field } : { message: msg });
|
|
48
|
+
}
|
|
49
|
+
return out.length ? out : void 0;
|
|
50
|
+
}
|
|
51
|
+
var WishlistStackApiError = class extends Error {
|
|
52
|
+
constructor(message, details) {
|
|
53
|
+
super(message);
|
|
54
|
+
__publicField(this, "name", "WishlistStackApiError");
|
|
55
|
+
__publicField(this, "status");
|
|
56
|
+
__publicField(this, "url");
|
|
57
|
+
__publicField(this, "method");
|
|
58
|
+
__publicField(this, "requestId");
|
|
59
|
+
__publicField(this, "body");
|
|
60
|
+
this.status = details.status;
|
|
61
|
+
this.url = details.url;
|
|
62
|
+
this.method = details.method;
|
|
63
|
+
this.requestId = details.requestId;
|
|
64
|
+
this.body = details.body;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Best-effort extraction of API error items from the response body.
|
|
68
|
+
* Useful for UI/logging without needing to know the exact response shape.
|
|
69
|
+
*/
|
|
70
|
+
get apiErrors() {
|
|
71
|
+
return extractApiErrors(this.body);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Convenience: extracted error messages (if present).
|
|
75
|
+
*/
|
|
76
|
+
get apiErrorMessages() {
|
|
77
|
+
const errs = this.apiErrors;
|
|
78
|
+
return errs?.map((e) => e.message);
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
function isWishlistStackApiError(value) {
|
|
82
|
+
if (!isRecord(value)) return false;
|
|
83
|
+
return value.name === "WishlistStackApiError" && typeof value.status === "number" && typeof value.url === "string" && typeof value.method === "string";
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// src/client/request.ts
|
|
87
|
+
async function safeParseJson(res) {
|
|
88
|
+
const contentType = res.headers.get("content-type") ?? "";
|
|
89
|
+
if (!contentType.toLowerCase().includes("application/json")) return void 0;
|
|
90
|
+
try {
|
|
91
|
+
return await res.json();
|
|
92
|
+
} catch {
|
|
93
|
+
return void 0;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function createRequest(ctx) {
|
|
97
|
+
return async function request(args) {
|
|
98
|
+
const url = `${ctx.baseUrl}${args.path}${toQueryString(args.query)}`;
|
|
99
|
+
const headers = {
|
|
100
|
+
"X-Wishlist-Stack-Api-Key": ctx.apiKey,
|
|
101
|
+
...args.headers ?? {}
|
|
102
|
+
};
|
|
103
|
+
if (args.auth === "authenticated") {
|
|
104
|
+
const token = ctx.customerAccessToken;
|
|
105
|
+
if (token) headers["X-Shopify-Customer-Access-Token"] = token;
|
|
106
|
+
}
|
|
107
|
+
let body;
|
|
108
|
+
if (args.body !== void 0) {
|
|
109
|
+
headers["content-type"] ?? (headers["content-type"] = "application/json");
|
|
110
|
+
body = JSON.stringify(args.body);
|
|
111
|
+
}
|
|
112
|
+
const controller = args.timeoutMs ? new AbortController() : void 0;
|
|
113
|
+
const timeout = args.timeoutMs && controller ? setTimeout(() => controller.abort(), args.timeoutMs) : void 0;
|
|
114
|
+
const signal = args.signal ? args.signal : controller ? controller.signal : void 0;
|
|
115
|
+
const res = await ctx.fetch(url, {
|
|
116
|
+
method: args.method,
|
|
117
|
+
headers,
|
|
118
|
+
body,
|
|
119
|
+
signal
|
|
120
|
+
});
|
|
121
|
+
if (timeout) clearTimeout(timeout);
|
|
122
|
+
if (!res.ok) {
|
|
123
|
+
const errBody = await safeParseJson(res);
|
|
124
|
+
const requestId = res.headers.get("fly-request-id") ?? res.headers.get("x-request-id") ?? void 0;
|
|
125
|
+
throw new WishlistStackApiError(`Wishlist Stack API request failed (${res.status})`, {
|
|
126
|
+
status: res.status,
|
|
127
|
+
url,
|
|
128
|
+
method: args.method,
|
|
129
|
+
requestId,
|
|
130
|
+
body: errBody
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
if (res.status === 204) return void 0;
|
|
134
|
+
const parsed = await safeParseJson(res);
|
|
135
|
+
if (parsed === void 0) {
|
|
136
|
+
const text = await res.text().catch(() => "");
|
|
137
|
+
return text;
|
|
138
|
+
}
|
|
139
|
+
return parsed;
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// src/resources/lists/index.ts
|
|
144
|
+
function createListsResource(request) {
|
|
145
|
+
return {
|
|
146
|
+
/** Returns all lists for the authenticated customer under the current merchant. */
|
|
147
|
+
getAll: (query) => request({
|
|
148
|
+
method: "GET",
|
|
149
|
+
path: "/api/lists",
|
|
150
|
+
auth: "authenticated",
|
|
151
|
+
query
|
|
152
|
+
}),
|
|
153
|
+
/** Fetch list details by id. */
|
|
154
|
+
getById: (listId, query) => request({
|
|
155
|
+
method: "GET",
|
|
156
|
+
path: `/api/lists/${encodeURIComponent(listId)}`,
|
|
157
|
+
auth: "authenticated",
|
|
158
|
+
query
|
|
159
|
+
}),
|
|
160
|
+
/** Create a new list. */
|
|
161
|
+
create: (body) => request({
|
|
162
|
+
method: "POST",
|
|
163
|
+
path: "/api/lists",
|
|
164
|
+
auth: "authenticated",
|
|
165
|
+
body
|
|
166
|
+
}),
|
|
167
|
+
/** Update list name/description. */
|
|
168
|
+
update: (listId, body) => request({
|
|
169
|
+
method: "PATCH",
|
|
170
|
+
path: `/api/lists/${encodeURIComponent(listId)}`,
|
|
171
|
+
auth: "authenticated",
|
|
172
|
+
body
|
|
173
|
+
}),
|
|
174
|
+
/** Remove a list. */
|
|
175
|
+
remove: (listId) => request({
|
|
176
|
+
method: "DELETE",
|
|
177
|
+
path: `/api/lists/${encodeURIComponent(listId)}`,
|
|
178
|
+
auth: "authenticated"
|
|
179
|
+
}),
|
|
180
|
+
/** Add one or more items to a list. */
|
|
181
|
+
addItems: (listId, body) => request({
|
|
182
|
+
method: "POST",
|
|
183
|
+
path: `/api/lists/${encodeURIComponent(listId)}/add`,
|
|
184
|
+
auth: "authenticated",
|
|
185
|
+
body
|
|
186
|
+
}),
|
|
187
|
+
/** Update an item on a list. */
|
|
188
|
+
updateItem: (listId, itemId, body) => request({
|
|
189
|
+
method: "PATCH",
|
|
190
|
+
path: `/api/lists/${encodeURIComponent(listId)}/items/${encodeURIComponent(itemId)}`,
|
|
191
|
+
auth: "authenticated",
|
|
192
|
+
body
|
|
193
|
+
}),
|
|
194
|
+
/** Remove an item from a list. */
|
|
195
|
+
removeItem: (listId, itemId) => request({
|
|
196
|
+
method: "DELETE",
|
|
197
|
+
path: `/api/lists/${encodeURIComponent(listId)}/items/${encodeURIComponent(itemId)}`,
|
|
198
|
+
auth: "authenticated"
|
|
199
|
+
}),
|
|
200
|
+
/** Mark list as shared (public read-only). */
|
|
201
|
+
share: (listId) => request({
|
|
202
|
+
method: "POST",
|
|
203
|
+
path: `/api/lists/${encodeURIComponent(listId)}/share`,
|
|
204
|
+
auth: "authenticated"
|
|
205
|
+
}),
|
|
206
|
+
/** Revoke list sharing. */
|
|
207
|
+
unshare: (listId) => request({
|
|
208
|
+
method: "DELETE",
|
|
209
|
+
path: `/api/lists/${encodeURIComponent(listId)}/share`,
|
|
210
|
+
auth: "authenticated"
|
|
211
|
+
}),
|
|
212
|
+
/**
|
|
213
|
+
* Legacy endpoint kept in the OpenAPI spec (`/api/wishlists/{id}/add`).
|
|
214
|
+
* Prefer `addItems(listId, body)` unless your server only supports the legacy route.
|
|
215
|
+
*/
|
|
216
|
+
addItemsLegacy: (id, body) => request({
|
|
217
|
+
method: "POST",
|
|
218
|
+
path: `/api/wishlists/${encodeURIComponent(id)}/add`,
|
|
219
|
+
auth: "authenticated",
|
|
220
|
+
body
|
|
221
|
+
})
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// src/resources/groups/index.ts
|
|
226
|
+
function createGroupsResource(request) {
|
|
227
|
+
return {
|
|
228
|
+
/** Fetch groups for the authenticated customer. */
|
|
229
|
+
getAll: (query) => request({
|
|
230
|
+
method: "GET",
|
|
231
|
+
path: "/api/groups",
|
|
232
|
+
auth: "authenticated",
|
|
233
|
+
query
|
|
234
|
+
}),
|
|
235
|
+
/** Fetch group details by id. */
|
|
236
|
+
getById: (groupId, query) => request({
|
|
237
|
+
method: "GET",
|
|
238
|
+
path: `/api/groups/${encodeURIComponent(groupId)}`,
|
|
239
|
+
auth: "authenticated",
|
|
240
|
+
query
|
|
241
|
+
}),
|
|
242
|
+
/** Create a new group. */
|
|
243
|
+
create: (body) => request({
|
|
244
|
+
method: "POST",
|
|
245
|
+
path: "/api/groups",
|
|
246
|
+
auth: "authenticated",
|
|
247
|
+
body
|
|
248
|
+
}),
|
|
249
|
+
/** Update group name/description. */
|
|
250
|
+
update: (groupId, body) => request({
|
|
251
|
+
method: "PATCH",
|
|
252
|
+
path: `/api/groups/${encodeURIComponent(groupId)}`,
|
|
253
|
+
auth: "authenticated",
|
|
254
|
+
body
|
|
255
|
+
}),
|
|
256
|
+
/** Remove a group. */
|
|
257
|
+
remove: (groupId) => request({
|
|
258
|
+
method: "DELETE",
|
|
259
|
+
path: `/api/groups/${encodeURIComponent(groupId)}`,
|
|
260
|
+
auth: "authenticated"
|
|
261
|
+
}),
|
|
262
|
+
/** Reorder a group (spec uses listIds payload). */
|
|
263
|
+
reorder: (groupId, body) => request({
|
|
264
|
+
method: "POST",
|
|
265
|
+
path: `/api/groups/${encodeURIComponent(groupId)}/reorder`,
|
|
266
|
+
auth: "authenticated",
|
|
267
|
+
body
|
|
268
|
+
}),
|
|
269
|
+
/** Mark group as shared (public read-only). */
|
|
270
|
+
share: (groupId) => request({
|
|
271
|
+
method: "POST",
|
|
272
|
+
path: `/api/groups/${encodeURIComponent(groupId)}/share`,
|
|
273
|
+
auth: "authenticated"
|
|
274
|
+
}),
|
|
275
|
+
/** Revoke group sharing. */
|
|
276
|
+
unshare: (groupId) => request({
|
|
277
|
+
method: "DELETE",
|
|
278
|
+
path: `/api/groups/${encodeURIComponent(groupId)}/share`,
|
|
279
|
+
auth: "authenticated"
|
|
280
|
+
})
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// src/resources/shared/index.ts
|
|
285
|
+
function createSharedResource(request) {
|
|
286
|
+
return {
|
|
287
|
+
/** Public read-only view of a shared list. Requires only merchant apiKey. */
|
|
288
|
+
getSharedList: (listId) => request({
|
|
289
|
+
method: "GET",
|
|
290
|
+
path: `/api/shared/list/${encodeURIComponent(listId)}`,
|
|
291
|
+
auth: "merchant"
|
|
292
|
+
}),
|
|
293
|
+
/** Public read-only view of a shared group. Requires only merchant apiKey. */
|
|
294
|
+
getSharedGroup: (groupId) => request({
|
|
295
|
+
method: "GET",
|
|
296
|
+
path: `/api/shared/group/${encodeURIComponent(groupId)}`,
|
|
297
|
+
auth: "merchant"
|
|
298
|
+
})
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// src/client/createWishlistStackClient.ts
|
|
303
|
+
function createWishlistStackClient(opts) {
|
|
304
|
+
if (!opts.apiKey) {
|
|
305
|
+
throw new Error(
|
|
306
|
+
"merchant api key is required. Pass it to createWishlistStackClient({ apiKey })"
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
const fetchImpl = opts.fetch ?? (typeof globalThis.fetch === "function" ? ((input, init) => globalThis.fetch(input, init)) : void 0);
|
|
310
|
+
if (!fetchImpl) {
|
|
311
|
+
throw new Error(
|
|
312
|
+
"No fetch implementation found. Provide one via createWishlistStackClient({ fetch }) or use Node 18+ / modern browsers."
|
|
313
|
+
);
|
|
314
|
+
}
|
|
315
|
+
const request = createRequest({
|
|
316
|
+
baseUrl: opts.baseUrl ?? BASE_URL,
|
|
317
|
+
apiKey: opts.apiKey,
|
|
318
|
+
customerAccessToken: opts.customerAccessToken,
|
|
319
|
+
fetch: fetchImpl
|
|
320
|
+
});
|
|
321
|
+
return {
|
|
322
|
+
lists: createListsResource(request),
|
|
323
|
+
groups: createGroupsResource(request),
|
|
324
|
+
shared: createSharedResource(request)
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// src/WishlistStackClient.ts
|
|
329
|
+
var WishlistStackClient = class {
|
|
330
|
+
constructor(opts) {
|
|
331
|
+
__publicField(this, "lists");
|
|
332
|
+
__publicField(this, "groups");
|
|
333
|
+
__publicField(this, "shared");
|
|
334
|
+
const client = createWishlistStackClient(opts);
|
|
335
|
+
this.lists = client.lists;
|
|
336
|
+
this.groups = client.groups;
|
|
337
|
+
this.shared = client.shared;
|
|
338
|
+
}
|
|
339
|
+
/** Back-compat alias: `client.groups.getAll()` */
|
|
340
|
+
getGroups() {
|
|
341
|
+
return this.groups.getAll();
|
|
342
|
+
}
|
|
343
|
+
/** Back-compat alias: `client.groups.getById(groupId)` */
|
|
344
|
+
getGroupById(groupId) {
|
|
345
|
+
return this.groups.getById(groupId);
|
|
346
|
+
}
|
|
347
|
+
/** Back-compat alias: `client.lists.getAll()` */
|
|
348
|
+
getLists() {
|
|
349
|
+
return this.lists.getAll();
|
|
350
|
+
}
|
|
351
|
+
};
|
|
352
|
+
|
|
353
|
+
// src/types/pagination.ts
|
|
354
|
+
var DEFAULT_PAGE = 1;
|
|
355
|
+
var DEFAULT_PAGE_SIZE = MAX_PAGINATION_SIZE;
|
|
356
|
+
|
|
357
|
+
// src/types/query-options.ts
|
|
358
|
+
function withPagination(query, pagination) {
|
|
359
|
+
if (!query && !pagination) return void 0;
|
|
360
|
+
return { ...query ?? {}, ...pagination ?? {} };
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
exports.DEFAULT_PAGE = DEFAULT_PAGE;
|
|
364
|
+
exports.DEFAULT_PAGE_SIZE = DEFAULT_PAGE_SIZE;
|
|
365
|
+
exports.WishlistStackApiError = WishlistStackApiError;
|
|
366
|
+
exports.WishlistStackSDK = WishlistStackClient;
|
|
367
|
+
exports.createWishlistStackClient = createWishlistStackClient;
|
|
368
|
+
exports.isWishlistStackApiError = isWishlistStackApiError;
|
|
369
|
+
exports.withPagination = withPagination;
|
|
370
|
+
//# sourceMappingURL=index.cjs.map
|
|
371
|
+
//# sourceMappingURL=index.cjs.map
|