keepa-api 0.2.3 → 0.3.1
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 +31 -3
- package/dist/index.cjs +398 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +206 -0
- package/dist/index.d.ts +206 -8
- package/dist/index.js +346 -7
- package/dist/index.js.map +1 -1
- package/package.json +14 -5
- package/dist/client.d.ts +0 -21
- package/dist/client.d.ts.map +0 -1
- package/dist/client.js +0 -38
- package/dist/client.js.map +0 -1
- package/dist/core/error.d.ts +0 -27
- package/dist/core/error.d.ts.map +0 -1
- package/dist/core/error.js +0 -61
- package/dist/core/error.js.map +0 -1
- package/dist/core/request.d.ts +0 -15
- package/dist/core/request.d.ts.map +0 -1
- package/dist/core/request.js +0 -36
- package/dist/core/request.js.map +0 -1
- package/dist/core/resource.d.ts +0 -6
- package/dist/core/resource.d.ts.map +0 -1
- package/dist/core/resource.js +0 -7
- package/dist/core/resource.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/lib/asin.d.ts +0 -10
- package/dist/lib/asin.d.ts.map +0 -1
- package/dist/lib/asin.js +0 -19
- package/dist/lib/asin.js.map +0 -1
- package/dist/lib/marketplace.d.ts +0 -17
- package/dist/lib/marketplace.d.ts.map +0 -1
- package/dist/lib/marketplace.js +0 -27
- package/dist/lib/marketplace.js.map +0 -1
- package/dist/resources/index.d.ts +0 -2
- package/dist/resources/index.d.ts.map +0 -1
- package/dist/resources/index.js +0 -2
- package/dist/resources/index.js.map +0 -1
- package/dist/resources/products/constant.d.ts +0 -7
- package/dist/resources/products/constant.d.ts.map +0 -1
- package/dist/resources/products/constant.js +0 -15
- package/dist/resources/products/constant.js.map +0 -1
- package/dist/resources/products/error.d.ts +0 -10
- package/dist/resources/products/error.d.ts.map +0 -1
- package/dist/resources/products/error.js +0 -14
- package/dist/resources/products/error.js.map +0 -1
- package/dist/resources/products/index.d.ts +0 -6
- package/dist/resources/products/index.d.ts.map +0 -1
- package/dist/resources/products/index.js +0 -8
- package/dist/resources/products/index.js.map +0 -1
- package/dist/resources/products/product.raw.type.d.ts +0 -36
- package/dist/resources/products/product.raw.type.d.ts.map +0 -1
- package/dist/resources/products/product.raw.type.js +0 -6
- package/dist/resources/products/product.raw.type.js.map +0 -1
- package/dist/resources/products/product.type.d.ts +0 -48
- package/dist/resources/products/product.type.d.ts.map +0 -1
- package/dist/resources/products/product.type.js +0 -2
- package/dist/resources/products/product.type.js.map +0 -1
- package/dist/resources/products/product.util.d.ts +0 -15
- package/dist/resources/products/product.util.d.ts.map +0 -1
- package/dist/resources/products/product.util.js +0 -56
- package/dist/resources/products/product.util.js.map +0 -1
- package/dist/resources/products/products.d.ts +0 -9
- package/dist/resources/products/products.d.ts.map +0 -1
- package/dist/resources/products/products.js +0 -40
- package/dist/resources/products/products.js.map +0 -1
- package/dist/version.d.ts +0 -2
- package/dist/version.d.ts.map +0 -1
- package/dist/version.js +0 -2
- package/dist/version.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,8 +1,347 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
// src/core/error.ts
|
|
2
|
+
function scrubApiKey(text) {
|
|
3
|
+
return text.replace(/([?&])key=[^&\s]*/gi, "$1key=REDACTED");
|
|
4
|
+
}
|
|
5
|
+
var KeepaError = class extends Error {
|
|
6
|
+
constructor(message) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = "KeepaError";
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
var APIError = class _APIError extends KeepaError {
|
|
12
|
+
status;
|
|
13
|
+
context;
|
|
14
|
+
body;
|
|
15
|
+
constructor(status, context, body, message) {
|
|
16
|
+
const safeBody = scrubApiKey(body);
|
|
17
|
+
super(scrubApiKey(message ?? `Keepa ${context} error (${status}): ${safeBody}`));
|
|
18
|
+
this.name = "APIError";
|
|
19
|
+
this.status = status;
|
|
20
|
+
this.context = context;
|
|
21
|
+
this.body = safeBody;
|
|
22
|
+
}
|
|
23
|
+
static async from(response, context) {
|
|
24
|
+
const body = await response.text().catch(() => "");
|
|
25
|
+
switch (response.status) {
|
|
26
|
+
case 429:
|
|
27
|
+
return new RateLimitError(context, body);
|
|
28
|
+
case 401:
|
|
29
|
+
return new AuthenticationError(context, body);
|
|
30
|
+
default:
|
|
31
|
+
return new _APIError(response.status, context, body);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
var RateLimitError = class extends APIError {
|
|
36
|
+
constructor(context, body) {
|
|
37
|
+
super(429, context, body, "Keepa rate limit exceeded, please wait or upgrade plan");
|
|
38
|
+
this.name = "RateLimitError";
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
var AuthenticationError = class extends APIError {
|
|
42
|
+
constructor(context, body) {
|
|
43
|
+
super(
|
|
44
|
+
401,
|
|
45
|
+
context,
|
|
46
|
+
body,
|
|
47
|
+
`Keepa authentication failed for ${context}: invalid or missing API key`
|
|
48
|
+
);
|
|
49
|
+
this.name = "AuthenticationError";
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
var NetworkError = class extends KeepaError {
|
|
53
|
+
context;
|
|
54
|
+
cause;
|
|
55
|
+
constructor(context, cause) {
|
|
56
|
+
const raw = cause instanceof Error ? cause.message : String(cause);
|
|
57
|
+
super(`Keepa ${context} network error: ${scrubApiKey(raw)}`);
|
|
58
|
+
this.name = "NetworkError";
|
|
59
|
+
this.context = context;
|
|
60
|
+
this.cause = cause;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// src/core/request.ts
|
|
65
|
+
function buildUrl(baseURL, path, query) {
|
|
66
|
+
if (!query) return `${baseURL}${path}`;
|
|
67
|
+
const parts = [];
|
|
68
|
+
for (const [key, value] of Object.entries(query)) {
|
|
69
|
+
if (value === void 0) continue;
|
|
70
|
+
const stringValue = Array.isArray(value) ? value.join(",") : String(value);
|
|
71
|
+
parts.push(`${encodeURIComponent(key)}=${encodeKeepaValue(stringValue)}`);
|
|
72
|
+
}
|
|
73
|
+
return parts.length ? `${baseURL}${path}?${parts.join("&")}` : `${baseURL}${path}`;
|
|
74
|
+
}
|
|
75
|
+
function encodeKeepaValue(value) {
|
|
76
|
+
return encodeURIComponent(value).replace(/%2C/g, ",");
|
|
77
|
+
}
|
|
78
|
+
async function request(config, args) {
|
|
79
|
+
const query = { key: config.apiKey, ...args.query };
|
|
80
|
+
const url = buildUrl(config.baseURL, args.path, query);
|
|
81
|
+
let res;
|
|
82
|
+
try {
|
|
83
|
+
res = await config.fetch(url);
|
|
84
|
+
} catch (cause) {
|
|
85
|
+
throw new NetworkError(args.context, cause);
|
|
86
|
+
}
|
|
87
|
+
if (!res.ok) throw await APIError.from(res, args.context);
|
|
88
|
+
return await res.json();
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// src/core/resource.ts
|
|
92
|
+
var APIResource = class {
|
|
93
|
+
_client;
|
|
94
|
+
constructor(client) {
|
|
95
|
+
this._client = client;
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
// src/lib/marketplace.ts
|
|
100
|
+
var MARKETPLACE_DOMAINS = {
|
|
101
|
+
US: 1,
|
|
102
|
+
GB: 2,
|
|
103
|
+
DE: 3,
|
|
104
|
+
FR: 4,
|
|
105
|
+
JP: 5,
|
|
106
|
+
CA: 6,
|
|
107
|
+
IT: 8,
|
|
108
|
+
ES: 9,
|
|
109
|
+
IN: 10,
|
|
110
|
+
MX: 11,
|
|
111
|
+
BR: 12
|
|
112
|
+
};
|
|
113
|
+
var SUPPORTED_LIST = Object.keys(MARKETPLACE_DOMAINS).join(", ");
|
|
114
|
+
function resolveDomainId(marketplace) {
|
|
115
|
+
const key = (marketplace ?? "US").toUpperCase();
|
|
116
|
+
const domainId = MARKETPLACE_DOMAINS[key];
|
|
117
|
+
if (!domainId) {
|
|
118
|
+
throw new Error(
|
|
119
|
+
`Invalid marketplace "${marketplace}". Supported: ${SUPPORTED_LIST}`
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
return domainId;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// src/lib/asin.ts
|
|
126
|
+
var ASIN_LENGTH = 10;
|
|
127
|
+
var ASIN_REGEX = /^[A-Z0-9]{10}$/;
|
|
128
|
+
function isValidAsin(value) {
|
|
129
|
+
return ASIN_REGEX.test(value);
|
|
130
|
+
}
|
|
131
|
+
function normalizeAsins(asins) {
|
|
132
|
+
const normalized = asins.map((asin) => asin.trim().toUpperCase());
|
|
133
|
+
const invalid = normalized.filter((asin) => !isValidAsin(asin));
|
|
134
|
+
if (invalid.length > 0) {
|
|
135
|
+
throw new Error(
|
|
136
|
+
`Invalid ASIN(s): ${invalid.join(", ")}. ASINs must be ${ASIN_LENGTH} alphanumeric characters (e.g. B00MNV8E0C).`
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
return normalized;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// src/resources/products/constant.ts
|
|
143
|
+
var PRODUCT_PATH = "/product";
|
|
144
|
+
var PRODUCT_LIST_CONTEXT = "products.list";
|
|
145
|
+
var DEFAULT_DAYS = 1;
|
|
146
|
+
var AMAZON_IMAGE_BASE = "https://m.media-amazon.com/images/I";
|
|
147
|
+
var KEEPA_NO_DATA_SENTINEL = -1;
|
|
148
|
+
var CsvType = {
|
|
149
|
+
AMAZON: 0,
|
|
150
|
+
NEW: 1,
|
|
151
|
+
USED: 2,
|
|
152
|
+
SALES: 3,
|
|
153
|
+
LISTPRICE: 4,
|
|
154
|
+
COLLECTIBLE: 5,
|
|
155
|
+
REFURBISHED: 6,
|
|
156
|
+
NEW_FBM_SHIPPING: 7,
|
|
157
|
+
LIGHTNING_DEAL: 8,
|
|
158
|
+
WAREHOUSE: 9,
|
|
159
|
+
NEW_FBA: 10,
|
|
160
|
+
COUNT_NEW: 11,
|
|
161
|
+
COUNT_USED: 12,
|
|
162
|
+
COUNT_REFURBISHED: 13,
|
|
163
|
+
COUNT_COLLECTIBLE: 14,
|
|
164
|
+
EXTRA_INFO_UPDATES: 15,
|
|
165
|
+
RATING: 16,
|
|
166
|
+
COUNT_REVIEWS: 17,
|
|
167
|
+
BUY_BOX_SHIPPING: 18,
|
|
168
|
+
USED_NEW_SHIPPING: 19,
|
|
169
|
+
USED_VERY_GOOD_SHIPPING: 20,
|
|
170
|
+
USED_GOOD_SHIPPING: 21,
|
|
171
|
+
USED_ACCEPTABLE_SHIPPING: 22,
|
|
172
|
+
COLLECTIBLE_NEW_SHIPPING: 23,
|
|
173
|
+
COLLECTIBLE_VERY_GOOD_SHIPPING: 24,
|
|
174
|
+
COLLECTIBLE_GOOD_SHIPPING: 25,
|
|
175
|
+
COLLECTIBLE_ACCEPTABLE_SHIPPING: 26,
|
|
176
|
+
REFURBISHED_SHIPPING: 27,
|
|
177
|
+
EBAY_NEW_SHIPPING: 28,
|
|
178
|
+
EBAY_USED_SHIPPING: 29,
|
|
179
|
+
TRADE_IN: 30,
|
|
180
|
+
RENTAL: 31,
|
|
181
|
+
BUY_BOX_USED_SHIPPING: 32,
|
|
182
|
+
PRIME_EXCL: 33,
|
|
183
|
+
COUNT_NEW_FBA: 34,
|
|
184
|
+
COUNT_NEW_FBM: 35
|
|
185
|
+
};
|
|
186
|
+
var KEEPA_EPOCH_UNIX_MS = 129384e7;
|
|
187
|
+
var VALID_IMAGE_FILENAME = /^[A-Za-z0-9._-]+\.(jpg|jpeg|png|webp)$/i;
|
|
188
|
+
|
|
189
|
+
// src/resources/products/error.ts
|
|
190
|
+
var ProductNotFoundError = class extends KeepaError {
|
|
191
|
+
asin;
|
|
192
|
+
constructor(asin) {
|
|
193
|
+
super(`Keepa: no product found for ASIN ${asin}`);
|
|
194
|
+
this.name = "ProductNotFoundError";
|
|
195
|
+
this.asin = asin;
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
// src/resources/products/product.util.ts
|
|
200
|
+
function toKeepaProduct(raw) {
|
|
201
|
+
const amazon = parsePriceHistory(raw.csv?.[CsvType.AMAZON]);
|
|
202
|
+
const list = parsePriceHistory(raw.csv?.[CsvType.LISTPRICE]);
|
|
203
|
+
return {
|
|
204
|
+
asin: raw.asin,
|
|
205
|
+
title: raw.title,
|
|
206
|
+
description: raw.description,
|
|
207
|
+
parentAsin: raw.parentAsin,
|
|
208
|
+
categoryTree: raw.categoryTree,
|
|
209
|
+
rootCategory: raw.rootCategory,
|
|
210
|
+
salesRanks: raw.salesRanks,
|
|
211
|
+
variations: raw.variations,
|
|
212
|
+
features: raw.features,
|
|
213
|
+
images: rawImagesToUrls(raw.images),
|
|
214
|
+
bsr: extractBsr(raw.salesRanks, raw.rootCategory),
|
|
215
|
+
price: amazon.at(-1)?.price ?? null,
|
|
216
|
+
listPrice: list.at(-1)?.price ?? null,
|
|
217
|
+
history: {
|
|
218
|
+
price: { amazon, list }
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
function pairKeepaSeries(series) {
|
|
223
|
+
if (!series) return [];
|
|
224
|
+
const points = [];
|
|
225
|
+
for (let i = 0; i + 1 < series.length; i += 2) {
|
|
226
|
+
const value = series[i + 1];
|
|
227
|
+
if (value === KEEPA_NO_DATA_SENTINEL) continue;
|
|
228
|
+
points.push({ timestamp: series[i], value });
|
|
229
|
+
}
|
|
230
|
+
return points;
|
|
231
|
+
}
|
|
232
|
+
function keepaMinutesToDate(minutes) {
|
|
233
|
+
return new Date(minutes * 6e4 + KEEPA_EPOCH_UNIX_MS);
|
|
234
|
+
}
|
|
235
|
+
function parsePriceHistory(series) {
|
|
236
|
+
return pairKeepaSeries(series).map(({ timestamp, value }) => ({
|
|
237
|
+
timestamp: keepaMinutesToDate(timestamp),
|
|
238
|
+
price: value / 100
|
|
239
|
+
}));
|
|
240
|
+
}
|
|
241
|
+
function rawImagesToUrls(images) {
|
|
242
|
+
if (!images || images.length === 0) return [];
|
|
243
|
+
return images.filter((img) => typeof img.l === "string" && VALID_IMAGE_FILENAME.test(img.l)).map((img) => `${AMAZON_IMAGE_BASE}/${img.l}`);
|
|
244
|
+
}
|
|
245
|
+
function isFoundProduct(product) {
|
|
246
|
+
return product.title != null;
|
|
247
|
+
}
|
|
248
|
+
function extractBsr(salesRanks, rootCategory) {
|
|
249
|
+
if (!salesRanks || rootCategory === void 0) return null;
|
|
250
|
+
return pairKeepaSeries(salesRanks[String(rootCategory)]).at(-1)?.value ?? null;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// src/resources/products/products.ts
|
|
254
|
+
var Products = class extends APIResource {
|
|
255
|
+
async list(params) {
|
|
256
|
+
if (params.asins.length === 0) {
|
|
257
|
+
throw new Error("At least one ASIN is required");
|
|
258
|
+
}
|
|
259
|
+
if (params.days !== void 0 && (!Number.isInteger(params.days) || params.days < 1)) {
|
|
260
|
+
throw new Error(`Invalid days: ${params.days}. Must be a positive integer.`);
|
|
261
|
+
}
|
|
262
|
+
const asins = normalizeAsins(params.asins);
|
|
263
|
+
const domain = resolveDomainId(params.marketplace);
|
|
264
|
+
const data = await this._client._request({
|
|
265
|
+
path: PRODUCT_PATH,
|
|
266
|
+
query: {
|
|
267
|
+
domain,
|
|
268
|
+
asin: asins,
|
|
269
|
+
days: params.days ?? DEFAULT_DAYS,
|
|
270
|
+
history: params.history ? 1 : 0
|
|
271
|
+
},
|
|
272
|
+
context: PRODUCT_LIST_CONTEXT
|
|
273
|
+
});
|
|
274
|
+
return (data.products ?? []).map(toKeepaProduct);
|
|
275
|
+
}
|
|
276
|
+
/** Throws `ProductNotFoundError` when Keepa returns no product or a stub. */
|
|
277
|
+
async retrieve(params) {
|
|
278
|
+
const { asin, ...rest } = params;
|
|
279
|
+
const [product] = await this.list({ ...rest, asins: [asin] });
|
|
280
|
+
if (!product || !isFoundProduct(product)) {
|
|
281
|
+
throw new ProductNotFoundError(asin);
|
|
282
|
+
}
|
|
283
|
+
return product;
|
|
284
|
+
}
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
// src/client.ts
|
|
288
|
+
var DEFAULT_BASE_URL = "https://api.keepa.com";
|
|
289
|
+
var KeepaClient = class {
|
|
290
|
+
apiKey;
|
|
291
|
+
baseURL;
|
|
292
|
+
fetch;
|
|
293
|
+
products;
|
|
294
|
+
constructor(options = {}) {
|
|
295
|
+
const envApiKey = typeof process !== "undefined" ? process.env?.KEEPA_API_KEY : void 0;
|
|
296
|
+
const apiKey = options.apiKey || envApiKey;
|
|
297
|
+
if (!apiKey) {
|
|
298
|
+
throw new Error(
|
|
299
|
+
"Missing Keepa API key. Pass it as `new KeepaClient({ apiKey })` or set KEEPA_API_KEY in your environment."
|
|
300
|
+
);
|
|
301
|
+
}
|
|
302
|
+
this.apiKey = apiKey;
|
|
303
|
+
this.baseURL = (options.baseURL ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
304
|
+
this.fetch = options.fetch ?? globalThis.fetch.bind(globalThis);
|
|
305
|
+
this.products = new Products(this);
|
|
306
|
+
}
|
|
307
|
+
_request(args) {
|
|
308
|
+
const config = {
|
|
309
|
+
apiKey: this.apiKey,
|
|
310
|
+
baseURL: this.baseURL,
|
|
311
|
+
fetch: this.fetch
|
|
312
|
+
};
|
|
313
|
+
return request(config, args);
|
|
314
|
+
}
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
// src/version.ts
|
|
318
|
+
var VERSION = "0.1.0";
|
|
319
|
+
export {
|
|
320
|
+
AMAZON_IMAGE_BASE,
|
|
321
|
+
APIError,
|
|
322
|
+
APIResource,
|
|
323
|
+
ASIN_LENGTH,
|
|
324
|
+
ASIN_REGEX,
|
|
325
|
+
AuthenticationError,
|
|
326
|
+
CsvType,
|
|
327
|
+
DEFAULT_DAYS,
|
|
328
|
+
KEEPA_NO_DATA_SENTINEL,
|
|
329
|
+
KeepaClient,
|
|
330
|
+
KeepaError,
|
|
331
|
+
MARKETPLACE_DOMAINS,
|
|
332
|
+
NetworkError,
|
|
333
|
+
PRODUCT_LIST_CONTEXT,
|
|
334
|
+
PRODUCT_PATH,
|
|
335
|
+
ProductNotFoundError,
|
|
336
|
+
Products,
|
|
337
|
+
RateLimitError,
|
|
338
|
+
VERSION,
|
|
339
|
+
KeepaClient as default,
|
|
340
|
+
extractBsr,
|
|
341
|
+
isFoundProduct,
|
|
342
|
+
isValidAsin,
|
|
343
|
+
normalizeAsins,
|
|
344
|
+
parsePriceHistory,
|
|
345
|
+
resolveDomainId
|
|
346
|
+
};
|
|
8
347
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,IAAI,OAAO,EAAE,WAAW,EAAsB,MAAM,aAAa,CAAC;AAEtF,OAAO,EACL,UAAU,EACV,QAAQ,EACR,cAAc,EACd,mBAAmB,EACnB,YAAY,GACb,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,OAAO,EACL,mBAAmB,EACnB,eAAe,GAGhB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,WAAW,EACX,UAAU,EACV,WAAW,EACX,cAAc,GACf,MAAM,eAAe,CAAC;AAEvB,cAAc,sBAAsB,CAAC;AAErC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"sources":["../src/core/error.ts","../src/core/request.ts","../src/core/resource.ts","../src/lib/marketplace.ts","../src/lib/asin.ts","../src/resources/products/constant.ts","../src/resources/products/error.ts","../src/resources/products/product.util.ts","../src/resources/products/products.ts","../src/client.ts","../src/version.ts"],"sourcesContent":["/** Defense-in-depth — keeps the API key out of error messages even when a\n * transport error or upstream response echoes the request URL back. */\nexport function scrubApiKey(text: string): string {\n return text.replace(/([?&])key=[^&\\s]*/gi, '$1key=REDACTED');\n}\n\nexport class KeepaError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'KeepaError';\n }\n}\n\nexport class APIError extends KeepaError {\n readonly status: number;\n readonly context: string;\n readonly body: string;\n\n constructor(status: number, context: string, body: string, message?: string) {\n const safeBody = scrubApiKey(body);\n super(scrubApiKey(message ?? `Keepa ${context} error (${status}): ${safeBody}`));\n this.name = 'APIError';\n this.status = status;\n this.context = context;\n this.body = safeBody;\n }\n\n static async from(response: Response, context: string): Promise<APIError> {\n const body = await response.text().catch(() => '');\n switch (response.status) {\n case 429:\n return new RateLimitError(context, body);\n case 401:\n return new AuthenticationError(context, body);\n default:\n return new APIError(response.status, context, body);\n }\n }\n}\n\nexport class RateLimitError extends APIError {\n constructor(context: string, body: string) {\n super(429, context, body, 'Keepa rate limit exceeded, please wait or upgrade plan');\n this.name = 'RateLimitError';\n }\n}\n\nexport class AuthenticationError extends APIError {\n constructor(context: string, body: string) {\n super(\n 401,\n context,\n body,\n `Keepa authentication failed for ${context}: invalid or missing API key`,\n );\n this.name = 'AuthenticationError';\n }\n}\n\nexport class NetworkError extends KeepaError {\n readonly context: string;\n override readonly cause: unknown;\n\n constructor(context: string, cause: unknown) {\n const raw = cause instanceof Error ? cause.message : String(cause);\n super(`Keepa ${context} network error: ${scrubApiKey(raw)}`);\n this.name = 'NetworkError';\n this.context = context;\n this.cause = cause;\n }\n}\n","import { APIError, NetworkError } from './error.js';\n\nexport type QueryValue = string | number | string[] | number[] | undefined;\nexport type QueryParams = Record<string, QueryValue>;\n\nexport interface RequestArgs {\n path: string;\n query?: QueryParams;\n context: string;\n}\n\nexport interface RequestConfig {\n baseURL: string;\n apiKey: string;\n fetch: typeof globalThis.fetch;\n}\n\nexport function buildUrl(baseURL: string, path: string, query?: QueryParams): string {\n if (!query) return `${baseURL}${path}`;\n const parts: string[] = [];\n for (const [key, value] of Object.entries(query)) {\n if (value === undefined) continue;\n const stringValue = Array.isArray(value) ? value.join(',') : String(value);\n parts.push(`${encodeURIComponent(key)}=${encodeKeepaValue(stringValue)}`);\n }\n return parts.length ? `${baseURL}${path}?${parts.join('&')}` : `${baseURL}${path}`;\n}\n\n// Keep commas literal — Keepa's category endpoint rejects %2C-encoded commas\n// in comma-separated lists (asin=A,B,C, category=1,2,3).\nfunction encodeKeepaValue(value: string): string {\n return encodeURIComponent(value).replace(/%2C/g, ',');\n}\n\nexport async function request<T>(config: RequestConfig, args: RequestArgs): Promise<T> {\n const query: QueryParams = { key: config.apiKey, ...args.query };\n const url = buildUrl(config.baseURL, args.path, query);\n let res: Response;\n try {\n res = await config.fetch(url);\n } catch (cause) {\n throw new NetworkError(args.context, cause);\n }\n if (!res.ok) throw await APIError.from(res, args.context);\n return (await res.json()) as T;\n}\n","import type { KeepaClient } from '../client.js';\n\nexport abstract class APIResource {\n protected _client: KeepaClient;\n\n constructor(client: KeepaClient) {\n this._client = client;\n }\n}\n","// Keys are ISO 3166-1 alpha-2; values are Keepa's `domain` query parameter.\n// Domain 7 is skipped — reserved (formerly Amazon China, retired).\nexport const MARKETPLACE_DOMAINS = {\n US: 1,\n GB: 2,\n DE: 3,\n FR: 4,\n JP: 5,\n CA: 6,\n IT: 8,\n ES: 9,\n IN: 10,\n MX: 11,\n BR: 12,\n} as const;\n\nexport type Marketplace = keyof typeof MARKETPLACE_DOMAINS;\nexport type DomainId = (typeof MARKETPLACE_DOMAINS)[Marketplace];\n\nconst SUPPORTED_LIST = Object.keys(MARKETPLACE_DOMAINS).join(', ');\n\nexport function resolveDomainId(marketplace: string | undefined): DomainId {\n const key = (marketplace ?? 'US').toUpperCase() as Marketplace;\n const domainId = MARKETPLACE_DOMAINS[key];\n if (!domainId) {\n throw new Error(\n `Invalid marketplace \"${marketplace}\". Supported: ${SUPPORTED_LIST}`,\n );\n }\n return domainId;\n}\n","export const ASIN_LENGTH = 10;\nexport const ASIN_REGEX = /^[A-Z0-9]{10}$/;\n\n/** Structural check only — a passing ASIN may still not exist in Keepa's\n * database; use `isFoundProduct` for that. */\nexport function isValidAsin(value: string): boolean {\n return ASIN_REGEX.test(value);\n}\n\nexport function normalizeAsins(asins: string[]): string[] {\n const normalized = asins.map((asin) => asin.trim().toUpperCase());\n const invalid = normalized.filter((asin) => !isValidAsin(asin));\n if (invalid.length > 0) {\n throw new Error(\n `Invalid ASIN(s): ${invalid.join(', ')}. ASINs must be ${ASIN_LENGTH} alphanumeric characters (e.g. B00MNV8E0C).`,\n );\n }\n return normalized;\n}\n","export const PRODUCT_PATH = '/product';\n// `<resource>.<method>` tag carried on errors so log aggregators can filter cleanly.\nexport const PRODUCT_LIST_CONTEXT = 'products.list';\nexport const DEFAULT_DAYS = 1;\n\n// Region-neutral CDN — serves identical images regardless of the marketplace.\nexport const AMAZON_IMAGE_BASE = 'https://m.media-amazon.com/images/I';\n\n// Keepa stores `-1` in salesRanks/price arrays as \"no data captured at that timestamp\".\nexport const KEEPA_NO_DATA_SENTINEL = -1;\n\n// First-dim index into Keepa's csv history matrix. Names mirror Keepa's own enum\n// verbatim (see https://keepa.com/#!discuss/t/product-object/116).\nexport const CsvType = {\n AMAZON: 0,\n NEW: 1,\n USED: 2,\n SALES: 3,\n LISTPRICE: 4,\n COLLECTIBLE: 5,\n REFURBISHED: 6,\n NEW_FBM_SHIPPING: 7,\n LIGHTNING_DEAL: 8,\n WAREHOUSE: 9,\n NEW_FBA: 10,\n COUNT_NEW: 11,\n COUNT_USED: 12,\n COUNT_REFURBISHED: 13,\n COUNT_COLLECTIBLE: 14,\n EXTRA_INFO_UPDATES: 15,\n RATING: 16,\n COUNT_REVIEWS: 17,\n BUY_BOX_SHIPPING: 18,\n USED_NEW_SHIPPING: 19,\n USED_VERY_GOOD_SHIPPING: 20,\n USED_GOOD_SHIPPING: 21,\n USED_ACCEPTABLE_SHIPPING: 22,\n COLLECTIBLE_NEW_SHIPPING: 23,\n COLLECTIBLE_VERY_GOOD_SHIPPING: 24,\n COLLECTIBLE_GOOD_SHIPPING: 25,\n COLLECTIBLE_ACCEPTABLE_SHIPPING: 26,\n REFURBISHED_SHIPPING: 27,\n EBAY_NEW_SHIPPING: 28,\n EBAY_USED_SHIPPING: 29,\n TRADE_IN: 30,\n RENTAL: 31,\n BUY_BOX_USED_SHIPPING: 32,\n PRIME_EXCL: 33,\n COUNT_NEW_FBA: 34,\n COUNT_NEW_FBM: 35,\n} as const;\nexport type CsvType = (typeof CsvType)[keyof typeof CsvType];\n\n// 2011-01-01 00:00 UTC — origin of Keepa's csv minute timestamps. Convert with\n// `new Date(km * 60_000 + KEEPA_EPOCH_UNIX_MS)`.\nexport const KEEPA_EPOCH_UNIX_MS = 1_293_840_000_000;\n\n// Defense-in-depth allowlist for filenames in imagesCSV — rejects path-traversal\n// / SSRF-shaped strings if the CSV is ever influenced by untrusted input.\nexport const VALID_IMAGE_FILENAME = /^[A-Za-z0-9._-]+\\.(jpg|jpeg|png|webp)$/i;\n","import { KeepaError } from '../../core/error.js';\n\n/** Thrown when Keepa returns no product, or returns a stub (title === null).\n * `asin` carries the caller's original input unchanged. */\nexport class ProductNotFoundError extends KeepaError {\n readonly asin: string;\n\n constructor(asin: string) {\n super(`Keepa: no product found for ASIN ${asin}`);\n this.name = 'ProductNotFoundError';\n this.asin = asin;\n }\n}\n","import {\n AMAZON_IMAGE_BASE,\n CsvType,\n KEEPA_EPOCH_UNIX_MS,\n KEEPA_NO_DATA_SENTINEL,\n VALID_IMAGE_FILENAME,\n} from './constant.js';\nimport type { KeepaProduct, PriceHistoryEntry } from './product.type.js';\nimport type { KeepaImageRaw, KeepaProductRaw } from './product.raw.type.js';\n\nexport function toKeepaProduct(raw: KeepaProductRaw): KeepaProduct {\n const amazon = parsePriceHistory(raw.csv?.[CsvType.AMAZON]);\n const list = parsePriceHistory(raw.csv?.[CsvType.LISTPRICE]);\n return {\n asin: raw.asin,\n title: raw.title,\n description: raw.description,\n parentAsin: raw.parentAsin,\n categoryTree: raw.categoryTree,\n rootCategory: raw.rootCategory,\n salesRanks: raw.salesRanks,\n variations: raw.variations,\n features: raw.features,\n images: rawImagesToUrls(raw.images),\n bsr: extractBsr(raw.salesRanks, raw.rootCategory),\n price: amazon.at(-1)?.price ?? null,\n listPrice: list.at(-1)?.price ?? null,\n history: {\n price: { amazon, list },\n },\n };\n}\n\ninterface KeepaSeriesPoint {\n /** Keepa minutes — use `keepaMinutesToDate` for a JS Date. */\n timestamp: number;\n value: number;\n}\n\n// Pair up Keepa's flat `[ts, value, ts, value, ...]` series. Drops `-1` no-data\n// sentinels; the `i + 1 < length` bound silently skips a dangling odd element.\nfunction pairKeepaSeries(series: number[] | undefined): KeepaSeriesPoint[] {\n if (!series) return [];\n const points: KeepaSeriesPoint[] = [];\n for (let i = 0; i + 1 < series.length; i += 2) {\n const value = series[i + 1]!;\n if (value === KEEPA_NO_DATA_SENTINEL) continue;\n points.push({ timestamp: series[i]!, value });\n }\n return points;\n}\n\nfunction keepaMinutesToDate(minutes: number): Date {\n return new Date(minutes * 60_000 + KEEPA_EPOCH_UNIX_MS);\n}\n\n// Keepa stores prices as integers in the smallest unit (cents/pence/etc.) and\n// scales JPY/INR/BRL the same way, so /100 produces the marketplace's major unit\n// uniformly across all supported regions.\nexport function parsePriceHistory(series: number[] | undefined): PriceHistoryEntry[] {\n return pairKeepaSeries(series).map(({ timestamp, value }) => ({\n timestamp: keepaMinutesToDate(timestamp),\n price: value / 100,\n }));\n}\n\n// Defense-in-depth — rejects path-traversal / SSRF-shaped filenames in case the\n// raw CSV is ever influenced by untrusted input.\nfunction rawImagesToUrls(images: KeepaImageRaw[] | undefined): string[] {\n if (!images || images.length === 0) return [];\n return images\n .filter((img) => typeof img.l === 'string' && VALID_IMAGE_FILENAME.test(img.l))\n .map((img) => `${AMAZON_IMAGE_BASE}/${img.l}`);\n}\n\n/** Stubs for unknown ASINs come back with `title: null`. */\nexport function isFoundProduct(product: KeepaProduct): boolean {\n return product.title != null;\n}\n\n/** Latest non-sentinel rank from Keepa's `[ts, rank, ts, rank, ...]` salesRanks\n * series for the product's rootCategory. */\nexport function extractBsr(\n salesRanks: Record<string, number[]> | undefined,\n rootCategory: number | undefined,\n): number | null {\n if (!salesRanks || rootCategory === undefined) return null;\n return pairKeepaSeries(salesRanks[String(rootCategory)]).at(-1)?.value ?? null;\n}\n","import { APIResource } from '../../core/resource.js';\nimport { resolveDomainId } from '../../lib/marketplace.js';\nimport { normalizeAsins } from '../../lib/asin.js';\nimport {\n PRODUCT_PATH,\n PRODUCT_LIST_CONTEXT,\n DEFAULT_DAYS,\n} from './constant.js';\nimport type {\n KeepaProduct,\n ProductListParams,\n ProductRetrieveParams,\n} from './product.type.js';\nimport type { KeepaProductResponseRaw } from './product.raw.type.js';\nimport { ProductNotFoundError } from './error.js';\nimport { toKeepaProduct, isFoundProduct } from './product.util.js';\n\nexport class Products extends APIResource {\n async list(params: ProductListParams): Promise<KeepaProduct[]> {\n if (params.asins.length === 0) {\n throw new Error('At least one ASIN is required');\n }\n if (\n params.days !== undefined &&\n (!Number.isInteger(params.days) || params.days < 1)\n ) {\n throw new Error(`Invalid days: ${params.days}. Must be a positive integer.`);\n }\n const asins = normalizeAsins(params.asins);\n const domain = resolveDomainId(params.marketplace);\n const data = await this._client._request<KeepaProductResponseRaw>({\n path: PRODUCT_PATH,\n query: {\n domain,\n asin: asins,\n days: params.days ?? DEFAULT_DAYS,\n history: params.history ? 1 : 0,\n },\n context: PRODUCT_LIST_CONTEXT,\n });\n return (data.products ?? []).map(toKeepaProduct);\n }\n\n /** Throws `ProductNotFoundError` when Keepa returns no product or a stub. */\n async retrieve(params: ProductRetrieveParams): Promise<KeepaProduct> {\n const { asin, ...rest } = params;\n const [product] = await this.list({ ...rest, asins: [asin] });\n if (!product || !isFoundProduct(product)) {\n throw new ProductNotFoundError(asin);\n }\n return product;\n }\n}\n","import { request } from './core/request.js';\nimport type { RequestArgs, RequestConfig } from './core/request.js';\nimport { Products } from './resources/products/products.js';\n\nexport interface ClientOptions {\n /** Falls back to `process.env.KEEPA_API_KEY` when omitted. */\n apiKey?: string;\n baseURL?: string;\n fetch?: typeof globalThis.fetch;\n}\n\nconst DEFAULT_BASE_URL = 'https://api.keepa.com';\n\nexport class KeepaClient {\n readonly apiKey: string;\n readonly baseURL: string;\n readonly fetch: typeof globalThis.fetch;\n\n readonly products: Products;\n\n constructor(options: ClientOptions = {}) {\n // `process` is undefined in browsers / Workers / edge runtimes — guard so the\n // constructor throws our friendly error instead of a raw ReferenceError there.\n const envApiKey =\n typeof process !== 'undefined' ? process.env?.KEEPA_API_KEY : undefined;\n const apiKey = options.apiKey || envApiKey;\n if (!apiKey) {\n throw new Error(\n 'Missing Keepa API key. Pass it as `new KeepaClient({ apiKey })` or set KEEPA_API_KEY in your environment.',\n );\n }\n this.apiKey = apiKey;\n // Strip trailing slash so `${baseURL}${path}` never produces `//product`.\n this.baseURL = (options.baseURL ?? DEFAULT_BASE_URL).replace(/\\/+$/, '');\n // Unbound Node fetch throws \"Illegal invocation\" when called with undefined `this`.\n this.fetch = options.fetch ?? globalThis.fetch.bind(globalThis);\n\n this.products = new Products(this);\n }\n\n _request<T>(args: RequestArgs): Promise<T> {\n const config: RequestConfig = {\n apiKey: this.apiKey,\n baseURL: this.baseURL,\n fetch: this.fetch,\n };\n return request<T>(config, args);\n }\n}\n\nexport default KeepaClient;\n","export const VERSION = '0.1.0';\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,14 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "keepa-api",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "TypeScript SDK for the Keepa API.",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"main": "./dist/index.
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
7
8
|
"types": "./dist/index.d.ts",
|
|
8
9
|
"exports": {
|
|
9
10
|
".": {
|
|
10
|
-
"
|
|
11
|
-
|
|
11
|
+
"import": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"default": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"require": {
|
|
16
|
+
"types": "./dist/index.d.cts",
|
|
17
|
+
"default": "./dist/index.cjs"
|
|
18
|
+
}
|
|
12
19
|
}
|
|
13
20
|
},
|
|
14
21
|
"files": [
|
|
@@ -17,7 +24,8 @@
|
|
|
17
24
|
"LICENSE"
|
|
18
25
|
],
|
|
19
26
|
"scripts": {
|
|
20
|
-
"build": "
|
|
27
|
+
"build": "tsup",
|
|
28
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
21
29
|
"test": "vitest run",
|
|
22
30
|
"test:watch": "vitest",
|
|
23
31
|
"example": "tsx examples/basic.ts",
|
|
@@ -46,6 +54,7 @@
|
|
|
46
54
|
"devDependencies": {
|
|
47
55
|
"@types/node": "^22.10.0",
|
|
48
56
|
"dotenv": "^16.4.0",
|
|
57
|
+
"tsup": "^8.5.1",
|
|
49
58
|
"tsx": "^4.19.0",
|
|
50
59
|
"typescript": "^5.6.0",
|
|
51
60
|
"vitest": "^2.1.0"
|
package/dist/client.d.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import type { RequestArgs } from './core/request.js';
|
|
2
|
-
import { Products } from './resources/products/products.js';
|
|
3
|
-
export interface ClientOptions {
|
|
4
|
-
/** Keepa API key. Falls back to `process.env.KEEPA_API_KEY`. */
|
|
5
|
-
apiKey?: string;
|
|
6
|
-
/** Base URL for the Keepa API. Defaults to `https://api.keepa.com`. */
|
|
7
|
-
baseURL?: string;
|
|
8
|
-
/** Custom fetch implementation. Defaults to `globalThis.fetch`. */
|
|
9
|
-
fetch?: typeof globalThis.fetch;
|
|
10
|
-
}
|
|
11
|
-
export declare class KeepaClient {
|
|
12
|
-
readonly apiKey: string;
|
|
13
|
-
readonly baseURL: string;
|
|
14
|
-
readonly fetch: typeof globalThis.fetch;
|
|
15
|
-
readonly products: Products;
|
|
16
|
-
constructor(options?: ClientOptions);
|
|
17
|
-
/** Internal: used by APIResource subclasses to perform a request. */
|
|
18
|
-
_request<T>(args: RequestArgs): Promise<T>;
|
|
19
|
-
}
|
|
20
|
-
export default KeepaClient;
|
|
21
|
-
//# sourceMappingURL=client.d.ts.map
|
package/dist/client.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAiB,MAAM,mBAAmB,CAAC;AACpE,OAAO,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAE5D,MAAM,WAAW,aAAa;IAC5B,gEAAgE;IAChE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uEAAuE;IACvE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CACjC;AAID,qBAAa,WAAW;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IAExC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;gBAEhB,OAAO,GAAE,aAAkB;IAuBvC,qEAAqE;IACrE,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC;CAQ3C;AAED,eAAe,WAAW,CAAC"}
|
package/dist/client.js
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { request } from './core/request.js';
|
|
2
|
-
import { Products } from './resources/products/products.js';
|
|
3
|
-
const DEFAULT_BASE_URL = 'https://api.keepa.com';
|
|
4
|
-
export class KeepaClient {
|
|
5
|
-
apiKey;
|
|
6
|
-
baseURL;
|
|
7
|
-
fetch;
|
|
8
|
-
products;
|
|
9
|
-
constructor(options = {}) {
|
|
10
|
-
// `process` is undefined in browsers / Cloudflare Workers / edge runtimes — guard it
|
|
11
|
-
// so the constructor throws our friendly "Missing Keepa API key" message instead of a
|
|
12
|
-
// raw ReferenceError on those targets.
|
|
13
|
-
const envApiKey = typeof process !== 'undefined' ? process.env?.KEEPA_API_KEY : undefined;
|
|
14
|
-
const apiKey = options.apiKey || envApiKey;
|
|
15
|
-
if (!apiKey) {
|
|
16
|
-
throw new Error('Missing Keepa API key. Pass it as `new KeepaClient({ apiKey })` or set KEEPA_API_KEY in your environment.');
|
|
17
|
-
}
|
|
18
|
-
this.apiKey = apiKey;
|
|
19
|
-
// Strip a trailing slash so `${baseURL}${path}` never produces `//product`.
|
|
20
|
-
this.baseURL = (options.baseURL ?? DEFAULT_BASE_URL).replace(/\/+$/, '');
|
|
21
|
-
// Bind `globalThis` once: an unbound reference to Node's fetch throws
|
|
22
|
-
// "Illegal invocation" when called with an undefined `this`. Bind once at
|
|
23
|
-
// construction so every _request call uses the cached bound function.
|
|
24
|
-
this.fetch = options.fetch ?? globalThis.fetch.bind(globalThis);
|
|
25
|
-
this.products = new Products(this);
|
|
26
|
-
}
|
|
27
|
-
/** Internal: used by APIResource subclasses to perform a request. */
|
|
28
|
-
_request(args) {
|
|
29
|
-
const config = {
|
|
30
|
-
apiKey: this.apiKey,
|
|
31
|
-
baseURL: this.baseURL,
|
|
32
|
-
fetch: this.fetch,
|
|
33
|
-
};
|
|
34
|
-
return request(config, args);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
export default KeepaClient;
|
|
38
|
-
//# sourceMappingURL=client.js.map
|
package/dist/client.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAE5C,OAAO,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAW5D,MAAM,gBAAgB,GAAG,uBAAuB,CAAC;AAEjD,MAAM,OAAO,WAAW;IACb,MAAM,CAAS;IACf,OAAO,CAAS;IAChB,KAAK,CAA0B;IAE/B,QAAQ,CAAW;IAE5B,YAAY,UAAyB,EAAE;QACrC,qFAAqF;QACrF,sFAAsF;QACtF,uCAAuC;QACvC,MAAM,SAAS,GACb,OAAO,OAAO,KAAK,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC;QAC1E,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,SAAS,CAAC;QAC3C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CACb,2GAA2G,CAC5G,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,4EAA4E;QAC5E,IAAI,CAAC,OAAO,GAAG,CAAC,OAAO,CAAC,OAAO,IAAI,gBAAgB,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QACzE,sEAAsE;QACtE,0EAA0E;QAC1E,sEAAsE;QACtE,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAEhE,IAAI,CAAC,QAAQ,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC;IACrC,CAAC;IAED,qEAAqE;IACrE,QAAQ,CAAI,IAAiB;QAC3B,MAAM,MAAM,GAAkB;YAC5B,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,KAAK,EAAE,IAAI,CAAC,KAAK;SAClB,CAAC;QACF,OAAO,OAAO,CAAI,MAAM,EAAE,IAAI,CAAC,CAAC;IAClC,CAAC;CACF;AAED,eAAe,WAAW,CAAC"}
|
package/dist/core/error.d.ts
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/** Replace any `?key=...` or `&key=...` segment with a REDACTED placeholder.
|
|
2
|
-
* Defense-in-depth: keeps the API key out of error messages even when an
|
|
3
|
-
* underlying transport error or upstream response echoes the request URL.
|
|
4
|
-
* Exported for use by callers that build their own error wrappers. */
|
|
5
|
-
export declare function scrubApiKey(text: string): string;
|
|
6
|
-
export declare class KeepaError extends Error {
|
|
7
|
-
constructor(message: string);
|
|
8
|
-
}
|
|
9
|
-
export declare class APIError extends KeepaError {
|
|
10
|
-
readonly status: number;
|
|
11
|
-
readonly context: string;
|
|
12
|
-
readonly body: string;
|
|
13
|
-
constructor(status: number, context: string, body: string, message?: string);
|
|
14
|
-
static from(response: Response, context: string): Promise<APIError>;
|
|
15
|
-
}
|
|
16
|
-
export declare class RateLimitError extends APIError {
|
|
17
|
-
constructor(context: string, body: string);
|
|
18
|
-
}
|
|
19
|
-
export declare class AuthenticationError extends APIError {
|
|
20
|
-
constructor(context: string, body: string);
|
|
21
|
-
}
|
|
22
|
-
export declare class NetworkError extends KeepaError {
|
|
23
|
-
readonly context: string;
|
|
24
|
-
readonly cause: unknown;
|
|
25
|
-
constructor(context: string, cause: unknown);
|
|
26
|
-
}
|
|
27
|
-
//# sourceMappingURL=error.d.ts.map
|
package/dist/core/error.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../src/core/error.ts"],"names":[],"mappings":"AAAA;;;uEAGuE;AACvE,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,qBAAa,UAAW,SAAQ,KAAK;gBACvB,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,QAAS,SAAQ,UAAU;IACtC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAEV,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM;WAS9D,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;CAW1E;AAED,qBAAa,cAAe,SAAQ,QAAQ;gBAC9B,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;CAI1C;AAED,qBAAa,mBAAoB,SAAQ,QAAQ;gBACnC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;CAS1C;AAED,qBAAa,YAAa,SAAQ,UAAU;IAC1C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,SAAkB,KAAK,EAAE,OAAO,CAAC;gBAErB,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO;CAO5C"}
|
package/dist/core/error.js
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
/** Replace any `?key=...` or `&key=...` segment with a REDACTED placeholder.
|
|
2
|
-
* Defense-in-depth: keeps the API key out of error messages even when an
|
|
3
|
-
* underlying transport error or upstream response echoes the request URL.
|
|
4
|
-
* Exported for use by callers that build their own error wrappers. */
|
|
5
|
-
export function scrubApiKey(text) {
|
|
6
|
-
return text.replace(/([?&])key=[^&\s]*/gi, '$1key=REDACTED');
|
|
7
|
-
}
|
|
8
|
-
export class KeepaError extends Error {
|
|
9
|
-
constructor(message) {
|
|
10
|
-
super(message);
|
|
11
|
-
this.name = 'KeepaError';
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
export class APIError extends KeepaError {
|
|
15
|
-
status;
|
|
16
|
-
context;
|
|
17
|
-
body;
|
|
18
|
-
constructor(status, context, body, message) {
|
|
19
|
-
const safeBody = scrubApiKey(body);
|
|
20
|
-
super(scrubApiKey(message ?? `Keepa ${context} error (${status}): ${safeBody}`));
|
|
21
|
-
this.name = 'APIError';
|
|
22
|
-
this.status = status;
|
|
23
|
-
this.context = context;
|
|
24
|
-
this.body = safeBody;
|
|
25
|
-
}
|
|
26
|
-
static async from(response, context) {
|
|
27
|
-
const body = await response.text().catch(() => '');
|
|
28
|
-
switch (response.status) {
|
|
29
|
-
case 429:
|
|
30
|
-
return new RateLimitError(context, body);
|
|
31
|
-
case 401:
|
|
32
|
-
return new AuthenticationError(context, body);
|
|
33
|
-
default:
|
|
34
|
-
return new APIError(response.status, context, body);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
export class RateLimitError extends APIError {
|
|
39
|
-
constructor(context, body) {
|
|
40
|
-
super(429, context, body, 'Keepa rate limit exceeded, please wait or upgrade plan');
|
|
41
|
-
this.name = 'RateLimitError';
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
export class AuthenticationError extends APIError {
|
|
45
|
-
constructor(context, body) {
|
|
46
|
-
super(401, context, body, `Keepa authentication failed for ${context}: invalid or missing API key`);
|
|
47
|
-
this.name = 'AuthenticationError';
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
export class NetworkError extends KeepaError {
|
|
51
|
-
context;
|
|
52
|
-
cause;
|
|
53
|
-
constructor(context, cause) {
|
|
54
|
-
const raw = cause instanceof Error ? cause.message : String(cause);
|
|
55
|
-
super(`Keepa ${context} network error: ${scrubApiKey(raw)}`);
|
|
56
|
-
this.name = 'NetworkError';
|
|
57
|
-
this.context = context;
|
|
58
|
-
this.cause = cause;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
//# sourceMappingURL=error.js.map
|
package/dist/core/error.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"error.js","sourceRoot":"","sources":["../../src/core/error.ts"],"names":[],"mappings":"AAAA;;;uEAGuE;AACvE,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO,IAAI,CAAC,OAAO,CAAC,qBAAqB,EAAE,gBAAgB,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,OAAO,UAAW,SAAQ,KAAK;IACnC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;IAC3B,CAAC;CACF;AAED,MAAM,OAAO,QAAS,SAAQ,UAAU;IAC7B,MAAM,CAAS;IACf,OAAO,CAAS;IAChB,IAAI,CAAS;IAEtB,YAAY,MAAc,EAAE,OAAe,EAAE,IAAY,EAAE,OAAgB;QACzE,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;QACnC,KAAK,CAAC,WAAW,CAAC,OAAO,IAAI,SAAS,OAAO,WAAW,MAAM,MAAM,QAAQ,EAAE,CAAC,CAAC,CAAC;QACjF,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;QACvB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,QAAQ,CAAC;IACvB,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,QAAkB,EAAE,OAAe;QACnD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QACnD,QAAQ,QAAQ,CAAC,MAAM,EAAE,CAAC;YACxB,KAAK,GAAG;gBACN,OAAO,IAAI,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;YAC3C,KAAK,GAAG;gBACN,OAAO,IAAI,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;YAChD;gBACE,OAAO,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QACxD,CAAC;IACH,CAAC;CACF;AAED,MAAM,OAAO,cAAe,SAAQ,QAAQ;IAC1C,YAAY,OAAe,EAAE,IAAY;QACvC,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,wDAAwD,CAAC,CAAC;QACpF,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IAC/B,CAAC;CACF;AAED,MAAM,OAAO,mBAAoB,SAAQ,QAAQ;IAC/C,YAAY,OAAe,EAAE,IAAY;QACvC,KAAK,CACH,GAAG,EACH,OAAO,EACP,IAAI,EACJ,mCAAmC,OAAO,8BAA8B,CACzE,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF;AAED,MAAM,OAAO,YAAa,SAAQ,UAAU;IACjC,OAAO,CAAS;IACP,KAAK,CAAU;IAEjC,YAAY,OAAe,EAAE,KAAc;QACzC,MAAM,GAAG,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACnE,KAAK,CAAC,SAAS,OAAO,mBAAmB,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC7D,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;QAC3B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;CACF"}
|
package/dist/core/request.d.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export type QueryValue = string | number | string[] | number[] | undefined;
|
|
2
|
-
export type QueryParams = Record<string, QueryValue>;
|
|
3
|
-
export interface RequestArgs {
|
|
4
|
-
path: string;
|
|
5
|
-
query?: QueryParams;
|
|
6
|
-
context: string;
|
|
7
|
-
}
|
|
8
|
-
export interface RequestConfig {
|
|
9
|
-
baseURL: string;
|
|
10
|
-
apiKey: string;
|
|
11
|
-
fetch: typeof globalThis.fetch;
|
|
12
|
-
}
|
|
13
|
-
export declare function buildUrl(baseURL: string, path: string, query?: QueryParams): string;
|
|
14
|
-
export declare function request<T>(config: RequestConfig, args: RequestArgs): Promise<T>;
|
|
15
|
-
//# sourceMappingURL=request.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/core/request.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC;AAC3E,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AAErD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CAChC;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,WAAW,GAAG,MAAM,CASnF;AAWD,wBAAsB,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC,CAWrF"}
|