keepa-api 0.1.0 → 0.2.2

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 CHANGED
@@ -78,7 +78,7 @@ The client reads `process.env.KEEPA_API_KEY` if you don't pass `apiKey` explicit
78
78
  | Param | Type | Default | Notes |
79
79
  |-------|------|---------|-------|
80
80
  | `asins` | `string[]` | (required) | Validated + uppercased. Throws on malformed input. |
81
- | `marketplace` | `'US' \| 'UK' \| 'DE' \| 'FR' \| 'JP' \| 'CA' \| 'IT' \| 'ES' \| 'IN' \| 'MX' \| 'AU'` | `'US'` | Case-insensitive. Throws on unknown. |
81
+ | `marketplace` | `'US' \| 'GB' \| 'DE' \| 'FR' \| 'JP' \| 'CA' \| 'IT' \| 'ES' \| 'IN' \| 'MX' \| 'BR'` | `'US'` | Case-insensitive. Throws on unknown. |
82
82
  | `days` | `number` | `1` | Days of price history. Must be a positive integer (validated pre-flight). |
83
83
 
84
84
  The SDK maps Keepa's raw wire shape into a friendlier `KeepaProduct`:
@@ -86,9 +86,9 @@ The SDK maps Keepa's raw wire shape into a friendlier `KeepaProduct`:
86
86
  - `images: string[]` — full image URLs (region-neutral CDN). Replaces Keepa's awkward `imagesCSV` string.
87
87
  - `bsr: number | null` — most recent real BSR for the product's `rootCategory`. `null` when missing or every history entry is Keepa's `-1` "no data captured" sentinel.
88
88
 
89
- The raw `salesRanks` record is preserved for consumers that need to walk the full rank history. Other Keepa fields (`title`, `parentAsin`, `categoryTree`, `variations`, `bulletPoints`, …) pass through unchanged.
89
+ The raw `salesRanks` record is preserved for consumers that need to walk the full rank history. Other Keepa fields (`title`, `parentAsin`, `categoryTree`, `variations`, `features`, …) pass through unchanged.
90
90
 
91
- **Stub records:** Keepa returns one record per requested ASIN even when it has no data — these stubs have `title === undefined`. Filter with `isFoundProduct` (below).
91
+ **Stub records:** Keepa returns one record per requested ASIN even when it has no data — these stubs have `title === null`. Filter with `isFoundProduct` (below).
92
92
 
93
93
  ### Helpers
94
94
 
@@ -105,7 +105,7 @@ for (const product of real) {
105
105
 
106
106
  | Helper | Signature | Returns |
107
107
  |--------|-----------|---------|
108
- | `isFoundProduct(product)` | `(product: KeepaProduct) => boolean` | `true` only if Keepa returned real data (`title` is non-empty). |
108
+ | `isFoundProduct(product)` | `(product: KeepaProduct) => boolean` | `true` only if Keepa returned real data (stubs have `title === null`). |
109
109
  | `parseImagesCsv(csv)` | `(csv: string \| undefined) => string[]` | Build the full image-URL list from a raw Keepa imagesCSV. Used internally to fill `images`; exported for advanced use. |
110
110
  | `extractBsr(salesRanks, rootCategory)` | `(salesRanks: Record<string, number[]> \| undefined, rootCategory: number \| undefined) => number \| null` | Most recent real BSR from Keepa's raw `[ts, rank, ...]` history. Used internally to fill `bsr`; exported for advanced use. |
111
111
  | `extractImageUrl(imagesCSV)` | `(imagesCSV: string \| undefined) => string \| null` | Single URL — equivalent to `parseImagesCsv(imagesCSV)[0] ?? null`. Exported for advanced use. |
@@ -133,17 +133,17 @@ normalizeAsins(['B07XYZ']); // throws: Invalid ASIN(s): B07XYZ. ...
133
133
  import { MARKETPLACE_DOMAINS, resolveDomainId } from 'keepa-api';
134
134
 
135
135
  MARKETPLACE_DOMAINS.US; // 1
136
- resolveDomainId('uk'); // 2 (case-insensitive)
136
+ resolveDomainId('gb'); // 2 (case-insensitive)
137
137
  resolveDomainId(undefined); // 1 (defaults to US)
138
138
  ```
139
139
 
140
140
  | Code | Domain ID | Code | Domain ID |
141
141
  |------|-----------|------|-----------|
142
142
  | US | 1 | IT | 8 |
143
- | UK | 2 | ES | 9 |
143
+ | GB | 2 | ES | 9 |
144
144
  | DE | 3 | IN | 10 |
145
145
  | FR | 4 | MX | 11 |
146
- | JP | 5 | AU | 13 |
146
+ | JP | 5 | BR | 12 |
147
147
  | CA | 6 | | |
148
148
 
149
149
  ### Errors
@@ -1,6 +1,6 @@
1
1
  export declare const MARKETPLACE_DOMAINS: {
2
2
  readonly US: 1;
3
- readonly UK: 2;
3
+ readonly GB: 2;
4
4
  readonly DE: 3;
5
5
  readonly FR: 4;
6
6
  readonly JP: 5;
@@ -9,7 +9,7 @@ export declare const MARKETPLACE_DOMAINS: {
9
9
  readonly ES: 9;
10
10
  readonly IN: 10;
11
11
  readonly MX: 11;
12
- readonly AU: 13;
12
+ readonly BR: 12;
13
13
  };
14
14
  export type Marketplace = keyof typeof MARKETPLACE_DOMAINS;
15
15
  export type DomainId = (typeof MARKETPLACE_DOMAINS)[Marketplace];
@@ -1 +1 @@
1
- {"version":3,"file":"marketplace.d.ts","sourceRoot":"","sources":["../../src/lib/marketplace.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,mBAAmB;;;;;;;;;;;;CAYtB,CAAC;AAEX,MAAM,MAAM,WAAW,GAAG,MAAM,OAAO,mBAAmB,CAAC;AAC3D,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,WAAW,CAAC,CAAC;AAIjE,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,QAAQ,CASzE"}
1
+ {"version":3,"file":"marketplace.d.ts","sourceRoot":"","sources":["../../src/lib/marketplace.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,mBAAmB;;;;;;;;;;;;CAYtB,CAAC;AAEX,MAAM,MAAM,WAAW,GAAG,MAAM,OAAO,mBAAmB,CAAC;AAC3D,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,WAAW,CAAC,CAAC;AAIjE,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,QAAQ,CASzE"}
@@ -1,9 +1,10 @@
1
- // The 11 marketplaces consumed by the existing internal projects. Keepa supports more
2
- // (AE, NL, PL, SE, BR, TR, …); extend this map and the README marketplace table when
3
- // a new region is needed. The numeric id is Keepa's `domain` query parameter value.
1
+ // The full set of marketplaces Keepa currently supports. Codes are ISO 3166-1
2
+ // alpha-2; the numeric id is Keepa's `domain` query parameter value. Domain 7
3
+ // is reserved (formerly Amazon China, retired). Update the README marketplace
4
+ // table alongside any change here.
4
5
  export const MARKETPLACE_DOMAINS = {
5
6
  US: 1,
6
- UK: 2,
7
+ GB: 2,
7
8
  DE: 3,
8
9
  FR: 4,
9
10
  JP: 5,
@@ -12,7 +13,7 @@ export const MARKETPLACE_DOMAINS = {
12
13
  ES: 9,
13
14
  IN: 10,
14
15
  MX: 11,
15
- AU: 13,
16
+ BR: 12,
16
17
  };
17
18
  const SUPPORTED_LIST = Object.keys(MARKETPLACE_DOMAINS).join(', ');
18
19
  export function resolveDomainId(marketplace) {
@@ -1 +1 @@
1
- {"version":3,"file":"marketplace.js","sourceRoot":"","sources":["../../src/lib/marketplace.ts"],"names":[],"mappings":"AAAA,sFAAsF;AACtF,qFAAqF;AACrF,oFAAoF;AACpF,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,EAAE,EAAE,CAAC;IACL,EAAE,EAAE,CAAC;IACL,EAAE,EAAE,CAAC;IACL,EAAE,EAAE,CAAC;IACL,EAAE,EAAE,CAAC;IACL,EAAE,EAAE,CAAC;IACL,EAAE,EAAE,CAAC;IACL,EAAE,EAAE,CAAC;IACL,EAAE,EAAE,EAAE;IACN,EAAE,EAAE,EAAE;IACN,EAAE,EAAE,EAAE;CACE,CAAC;AAKX,MAAM,cAAc,GAAG,MAAM,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEnE,MAAM,UAAU,eAAe,CAAC,WAA+B;IAC7D,MAAM,GAAG,GAAG,CAAC,WAAW,IAAI,IAAI,CAAC,CAAC,WAAW,EAAiB,CAAC;IAC/D,MAAM,QAAQ,GAAG,mBAAmB,CAAC,GAAG,CAAC,CAAC;IAC1C,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CACb,wBAAwB,WAAW,iBAAiB,cAAc,EAAE,CACrE,CAAC;IACJ,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
1
+ {"version":3,"file":"marketplace.js","sourceRoot":"","sources":["../../src/lib/marketplace.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,8EAA8E;AAC9E,8EAA8E;AAC9E,mCAAmC;AACnC,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,EAAE,EAAE,CAAC;IACL,EAAE,EAAE,CAAC;IACL,EAAE,EAAE,CAAC;IACL,EAAE,EAAE,CAAC;IACL,EAAE,EAAE,CAAC;IACL,EAAE,EAAE,CAAC;IACL,EAAE,EAAE,CAAC;IACL,EAAE,EAAE,CAAC;IACL,EAAE,EAAE,EAAE;IACN,EAAE,EAAE,EAAE;IACN,EAAE,EAAE,EAAE;CACE,CAAC;AAKX,MAAM,cAAc,GAAG,MAAM,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEnE,MAAM,UAAU,eAAe,CAAC,WAA+B;IAC7D,MAAM,GAAG,GAAG,CAAC,WAAW,IAAI,IAAI,CAAC,CAAC,WAAW,EAAiB,CAAC;IAC/D,MAAM,QAAQ,GAAG,mBAAmB,CAAC,GAAG,CAAC,CAAC;IAC1C,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CACb,wBAAwB,WAAW,iBAAiB,cAAc,EAAE,CACrE,CAAC;IACJ,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { KeepaError } from '../../core/error.js';
2
+ /** Thrown by `Products.retrieve` when Keepa has no record for the requested ASIN
3
+ * (either no product object returned, or a stub with no title). The `asin`
4
+ * property carries the value the caller passed in, unchanged, so it can be
5
+ * surfaced in user-facing messages without re-deriving it. */
6
+ export declare class ProductNotFoundError extends KeepaError {
7
+ readonly asin: string;
8
+ constructor(asin: string);
9
+ }
10
+ //# sourceMappingURL=error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../../src/resources/products/error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD;;;+DAG+D;AAC/D,qBAAa,oBAAqB,SAAQ,UAAU;IAClD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAEV,IAAI,EAAE,MAAM;CAKzB"}
@@ -0,0 +1,14 @@
1
+ import { KeepaError } from '../../core/error.js';
2
+ /** Thrown by `Products.retrieve` when Keepa has no record for the requested ASIN
3
+ * (either no product object returned, or a stub with no title). The `asin`
4
+ * property carries the value the caller passed in, unchanged, so it can be
5
+ * surfaced in user-facing messages without re-deriving it. */
6
+ export class ProductNotFoundError extends KeepaError {
7
+ asin;
8
+ constructor(asin) {
9
+ super(`Keepa: no product found for ASIN ${asin}`);
10
+ this.name = 'ProductNotFoundError';
11
+ this.asin = asin;
12
+ }
13
+ }
14
+ //# sourceMappingURL=error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error.js","sourceRoot":"","sources":["../../../src/resources/products/error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD;;;+DAG+D;AAC/D,MAAM,OAAO,oBAAqB,SAAQ,UAAU;IACzC,IAAI,CAAS;IAEtB,YAAY,IAAY;QACtB,KAAK,CAAC,oCAAoC,IAAI,EAAE,CAAC,CAAC;QAClD,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;QACnC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF"}
@@ -1,4 +1,6 @@
1
- export { Products, extractBsr, extractImageUrl, isFoundProduct, parseImagesCsv, } from './products.js';
2
- export type { ProductListParams, KeepaProduct, KeepaVariation, KeepaVariationAttribute, KeepaCategoryNode, } from './product.type.js';
1
+ export { Products } from './products.js';
2
+ export { extractBsr, isFoundProduct } from './product.util.js';
3
+ export { ProductNotFoundError } from './error.js';
4
+ export type { ProductListParams, ProductRetrieveParams, KeepaProduct, KeepaVariation, KeepaVariationAttribute, KeepaCategoryNode, } from './product.type.js';
3
5
  export { PRODUCT_PATH, PRODUCT_LIST_CONTEXT, DEFAULT_DAYS, AMAZON_IMAGE_BASE, KEEPA_NO_DATA_SENTINEL, } from './constant.js';
4
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/resources/products/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,UAAU,EACV,eAAe,EACf,cAAc,EACd,cAAc,GACf,MAAM,eAAe,CAAC;AAEvB,YAAY,EACV,iBAAiB,EACjB,YAAY,EACZ,cAAc,EACd,uBAAuB,EACvB,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAM3B,OAAO,EACL,YAAY,EACZ,oBAAoB,EACpB,YAAY,EACZ,iBAAiB,EACjB,sBAAsB,GACvB,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/resources/products/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAElD,YAAY,EACV,iBAAiB,EACjB,qBAAqB,EACrB,YAAY,EACZ,cAAc,EACd,uBAAuB,EACvB,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAM3B,OAAO,EACL,YAAY,EACZ,oBAAoB,EACpB,YAAY,EACZ,iBAAiB,EACjB,sBAAsB,GACvB,MAAM,eAAe,CAAC"}
@@ -1,4 +1,6 @@
1
- export { Products, extractBsr, extractImageUrl, isFoundProduct, parseImagesCsv, } from './products.js';
1
+ export { Products } from './products.js';
2
+ export { extractBsr, isFoundProduct } from './product.util.js';
3
+ export { ProductNotFoundError } from './error.js';
2
4
  // NOTE: raw Keepa wire types (KeepaProductRaw, KeepaProductResponseRaw) are
3
5
  // intentionally NOT re-exported. They are an implementation detail — Products.list
4
6
  // maps them to the consumer-friendly KeepaProduct shape before returning.
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/resources/products/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,UAAU,EACV,eAAe,EACf,cAAc,EACd,cAAc,GACf,MAAM,eAAe,CAAC;AAUvB,4EAA4E;AAC5E,mFAAmF;AACnF,0EAA0E;AAE1E,OAAO,EACL,YAAY,EACZ,oBAAoB,EACpB,YAAY,EACZ,iBAAiB,EACjB,sBAAsB,GACvB,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/resources/products/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAWlD,4EAA4E;AAC5E,mFAAmF;AACnF,0EAA0E;AAE1E,OAAO,EACL,YAAY,EACZ,oBAAoB,EACpB,YAAY,EACZ,iBAAiB,EACjB,sBAAsB,GACvB,MAAM,eAAe,CAAC"}
@@ -10,6 +10,14 @@ export interface KeepaVariationRaw {
10
10
  asin: string;
11
11
  attributes?: KeepaVariationAttributeRaw[];
12
12
  }
13
+ export interface KeepaImageRaw {
14
+ l: string;
15
+ lH: number;
16
+ lW: number;
17
+ m: string;
18
+ mH: number;
19
+ mW: number;
20
+ }
13
21
  export interface KeepaProductRaw {
14
22
  asin: string;
15
23
  title?: string;
@@ -18,9 +26,9 @@ export interface KeepaProductRaw {
18
26
  categoryTree?: KeepaCategoryNodeRaw[];
19
27
  rootCategory?: number;
20
28
  salesRanks?: Record<string, number[]>;
21
- imagesCSV?: string;
29
+ images?: KeepaImageRaw[];
22
30
  variations?: KeepaVariationRaw[];
23
- bulletPoints?: string[];
31
+ features?: string[];
24
32
  }
25
33
  export interface KeepaProductResponseRaw {
26
34
  products?: KeepaProductRaw[];
@@ -1 +1 @@
1
- {"version":3,"file":"product.raw.type.d.ts","sourceRoot":"","sources":["../../../src/resources/products/product.raw.type.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,0BAA0B;IACzC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,0BAA0B,EAAE,CAAC;CAC3C;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,oBAAoB,EAAE,CAAC;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,iBAAiB,EAAE,CAAC;IACjC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,EAAE,eAAe,EAAE,CAAC;CAC9B"}
1
+ {"version":3,"file":"product.raw.type.d.ts","sourceRoot":"","sources":["../../../src/resources/products/product.raw.type.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,0BAA0B;IACzC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,0BAA0B,EAAE,CAAC;CAC3C;AAID,MAAM,WAAW,aAAa;IAC5B,CAAC,EAAE,MAAM,CAAC;IACV,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,CAAC,EAAE,MAAM,CAAC;IACV,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,oBAAoB,EAAE,CAAC;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACtC,MAAM,CAAC,EAAE,aAAa,EAAE,CAAC;IACzB,UAAU,CAAC,EAAE,iBAAiB,EAAE,CAAC;IACjC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,EAAE,eAAe,EAAE,CAAC;CAC9B"}
@@ -6,6 +6,13 @@ export interface ProductListParams {
6
6
  /** Days of price history to include. Defaults to 1. */
7
7
  days?: number;
8
8
  }
9
+ export interface ProductRetrieveParams {
10
+ asin: string;
11
+ /** Marketplace code (case-insensitive at runtime). Defaults to 'US'. */
12
+ marketplace?: Marketplace;
13
+ /** Days of price history to include. Defaults to 1. */
14
+ days?: number;
15
+ }
9
16
  export interface KeepaCategoryNode {
10
17
  catId: number;
11
18
  name: string;
@@ -31,7 +38,7 @@ export interface KeepaProduct {
31
38
  rootCategory?: number;
32
39
  salesRanks?: Record<string, number[]>;
33
40
  variations?: KeepaVariation[];
34
- bulletPoints?: string[];
41
+ features?: string[];
35
42
  /** Full image URLs derived from imagesCSV using a region-neutral Amazon CDN. */
36
43
  images: string[];
37
44
  /** Most recent real BSR for the rootCategory. Null when missing or every entry is
@@ -1 +1 @@
1
- {"version":3,"file":"product.type.d.ts","sourceRoot":"","sources":["../../../src/resources/products/product.type.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE5D,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,wEAAwE;IACxE,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,uBAAuB,EAAE,CAAC;CACxC;AAED;;;+DAG+D;AAC/D,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,iBAAiB,EAAE,CAAC;IACnC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACtC,UAAU,CAAC,EAAE,cAAc,EAAE,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IAExB,gFAAgF;IAChF,MAAM,EAAE,MAAM,EAAE,CAAC;IAEjB;oDACgD;IAChD,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACpB"}
1
+ {"version":3,"file":"product.type.d.ts","sourceRoot":"","sources":["../../../src/resources/products/product.type.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE5D,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,wEAAwE;IACxE,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,wEAAwE;IACxE,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,uBAAuB,EAAE,CAAC;CACxC;AAED;;;+DAG+D;AAC/D,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,iBAAiB,EAAE,CAAC;IACnC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACtC,UAAU,CAAC,EAAE,cAAc,EAAE,CAAC;IAC9B,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IAEpB,gFAAgF;IAChF,MAAM,EAAE,MAAM,EAAE,CAAC;IAEjB;oDACgD;IAChD,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACpB"}
@@ -0,0 +1,15 @@
1
+ import type { KeepaProduct } from './product.type.js';
2
+ import type { KeepaProductRaw } from './product.raw.type.js';
3
+ /** Map Keepa's raw wire shape into the consumer-friendly KeepaProduct. */
4
+ export declare function toKeepaProduct(raw: KeepaProductRaw): KeepaProduct;
5
+ /** Returns true when Keepa returned an actual product record (not just a stub
6
+ * for an unknown ASIN). Stubs come back with `title: null`; real listings
7
+ * always have a string. Use as a `.filter()` predicate to drop empty matches. */
8
+ export declare function isFoundProduct(product: KeepaProduct): boolean;
9
+ /** Extract the most recent real BSR from Keepa's `[ts, rank, ts, rank, ...]` salesRanks array.
10
+ * Walks backward through rank entries (odd indices) and skips Keepa's `-1` sentinel which
11
+ * marks "no data captured at that timestamp". Returns `null` if every entry is sentinel.
12
+ * Most consumers won't need this — `Products.list` already fills `bsr` on every returned
13
+ * product. Useful when working with a raw Keepa response. */
14
+ export declare function extractBsr(salesRanks: Record<string, number[]> | undefined, rootCategory: number | undefined): number | null;
15
+ //# sourceMappingURL=product.util.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"product.util.d.ts","sourceRoot":"","sources":["../../../src/resources/products/product.util.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAiB,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE5E,0EAA0E;AAC1E,wBAAgB,cAAc,CAAC,GAAG,EAAE,eAAe,GAAG,YAAY,CAcjE;AAYD;;kFAEkF;AAClF,wBAAgB,cAAc,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAE7D;AAED;;;;8DAI8D;AAC9D,wBAAgB,UAAU,CACxB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,SAAS,EAChD,YAAY,EAAE,MAAM,GAAG,SAAS,GAC/B,MAAM,GAAG,IAAI,CAaf"}
@@ -0,0 +1,56 @@
1
+ import { AMAZON_IMAGE_BASE, KEEPA_NO_DATA_SENTINEL, VALID_IMAGE_FILENAME, } from './constant.js';
2
+ /** Map Keepa's raw wire shape into the consumer-friendly KeepaProduct. */
3
+ export function toKeepaProduct(raw) {
4
+ return {
5
+ asin: raw.asin,
6
+ title: raw.title,
7
+ description: raw.description,
8
+ parentAsin: raw.parentAsin,
9
+ categoryTree: raw.categoryTree,
10
+ rootCategory: raw.rootCategory,
11
+ salesRanks: raw.salesRanks,
12
+ variations: raw.variations,
13
+ features: raw.features,
14
+ images: rawImagesToUrls(raw.images),
15
+ bsr: extractBsr(raw.salesRanks, raw.rootCategory),
16
+ };
17
+ }
18
+ /** Convert Keepa's raw images array into full Amazon image URLs (the large
19
+ * variant). Filters entries whose filename doesn't match the expected
20
+ * alphanumeric image-name pattern as defense-in-depth. */
21
+ function rawImagesToUrls(images) {
22
+ if (!images || images.length === 0)
23
+ return [];
24
+ return images
25
+ .filter((img) => typeof img.l === 'string' && VALID_IMAGE_FILENAME.test(img.l))
26
+ .map((img) => `${AMAZON_IMAGE_BASE}/${img.l}`);
27
+ }
28
+ /** Returns true when Keepa returned an actual product record (not just a stub
29
+ * for an unknown ASIN). Stubs come back with `title: null`; real listings
30
+ * always have a string. Use as a `.filter()` predicate to drop empty matches. */
31
+ export function isFoundProduct(product) {
32
+ return product.title != null;
33
+ }
34
+ /** Extract the most recent real BSR from Keepa's `[ts, rank, ts, rank, ...]` salesRanks array.
35
+ * Walks backward through rank entries (odd indices) and skips Keepa's `-1` sentinel which
36
+ * marks "no data captured at that timestamp". Returns `null` if every entry is sentinel.
37
+ * Most consumers won't need this — `Products.list` already fills `bsr` on every returned
38
+ * product. Useful when working with a raw Keepa response. */
39
+ export function extractBsr(salesRanks, rootCategory) {
40
+ if (!salesRanks || rootCategory === undefined)
41
+ return null;
42
+ const ranks = salesRanks[String(rootCategory)];
43
+ if (!ranks || ranks.length < 2)
44
+ return null;
45
+ // Keepa pairs are [ts, rank, ts, rank, ...]. If length is even, the last index
46
+ // is a rank; if odd (truncated/schema drift), it's a dangling timestamp — skip
47
+ // back one slot so we always start on a rank.
48
+ const start = ranks.length % 2 === 0 ? ranks.length - 1 : ranks.length - 2;
49
+ for (let i = start; i >= 1; i -= 2) {
50
+ const rank = ranks[i];
51
+ if (rank !== undefined && rank !== KEEPA_NO_DATA_SENTINEL)
52
+ return rank;
53
+ }
54
+ return null;
55
+ }
56
+ //# sourceMappingURL=product.util.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"product.util.js","sourceRoot":"","sources":["../../../src/resources/products/product.util.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,eAAe,CAAC;AAIvB,0EAA0E;AAC1E,MAAM,UAAU,cAAc,CAAC,GAAoB;IACjD,OAAO;QACL,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,WAAW,EAAE,GAAG,CAAC,WAAW;QAC5B,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,YAAY,EAAE,GAAG,CAAC,YAAY;QAC9B,YAAY,EAAE,GAAG,CAAC,YAAY;QAC9B,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,MAAM,EAAE,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC;QACnC,GAAG,EAAE,UAAU,CAAC,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,YAAY,CAAC;KAClD,CAAC;AACJ,CAAC;AAED;;2DAE2D;AAC3D,SAAS,eAAe,CAAC,MAAmC;IAC1D,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAC9C,OAAO,MAAM;SACV,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,GAAG,CAAC,CAAC,KAAK,QAAQ,IAAI,oBAAoB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;SAC9E,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,iBAAiB,IAAI,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;AACnD,CAAC;AAED;;kFAEkF;AAClF,MAAM,UAAU,cAAc,CAAC,OAAqB;IAClD,OAAO,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC;AAC/B,CAAC;AAED;;;;8DAI8D;AAC9D,MAAM,UAAU,UAAU,CACxB,UAAgD,EAChD,YAAgC;IAEhC,IAAI,CAAC,UAAU,IAAI,YAAY,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAC3D,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;IAC/C,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAC5C,+EAA+E;IAC/E,+EAA+E;IAC/E,8CAA8C;IAC9C,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;IAC3E,KAAK,IAAI,CAAC,GAAG,KAAK,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,sBAAsB;YAAE,OAAO,IAAI,CAAC;IACzE,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -1,31 +1,9 @@
1
1
  import { APIResource } from '../../core/resource.js';
2
- import type { KeepaProduct, ProductListParams } from './product.type.js';
2
+ import type { KeepaProduct, ProductListParams, ProductRetrieveParams } from './product.type.js';
3
3
  export declare class Products extends APIResource {
4
4
  list(params: ProductListParams): Promise<KeepaProduct[]>;
5
+ /** Fetch a single product by ASIN. Throws `ProductNotFoundError` when Keepa
6
+ * has no record for the ASIN (no product returned, or a stub with no title). */
7
+ retrieve(params: ProductRetrieveParams): Promise<KeepaProduct>;
5
8
  }
6
- /** Returns true when Keepa returned an actual product record (not just a stub
7
- * for an unknown ASIN). Use as a `.filter()` predicate to drop empty matches.
8
- *
9
- * We use `title.length > 0` because it's the strongest single correlate of
10
- * "Keepa has data" — stubs for unknown ASINs come back without a title, and
11
- * every real listing has one. If Keepa's stub format changes (e.g. they start
12
- * returning a placeholder title), tighten this predicate to also require
13
- * `categoryTree` or another non-string field. */
14
- export declare function isFoundProduct(product: KeepaProduct): boolean;
15
- /** Build the full image-URL list from a Keepa imagesCSV string. Region-neutral CDN.
16
- * Filters out entries that don't look like image filenames (path traversal,
17
- * arbitrary extensions, etc.) — defense in case the CSV is ever influenced by
18
- * untrusted input. Most consumers won't need this directly: `Products.list`
19
- * already fills `images[]` on every returned product. */
20
- export declare function parseImagesCsv(imagesCSV: string | undefined): string[];
21
- /** Extract the most recent real BSR from Keepa's `[ts, rank, ts, rank, ...]` salesRanks array.
22
- * Walks backward through rank entries (odd indices) and skips Keepa's `-1` sentinel which
23
- * marks "no data captured at that timestamp". Returns `null` if every entry is sentinel.
24
- * Most consumers won't need this — `Products.list` already fills `bsr` on every returned
25
- * product. Useful when working with a raw Keepa response. */
26
- export declare function extractBsr(salesRanks: Record<string, number[]> | undefined, rootCategory: number | undefined): number | null;
27
- /** Build a single Amazon image URL from the first entry in Keepa's imagesCSV.
28
- * Equivalent to `parseImagesCsv(imagesCSV)[0] ?? null`. Useful when working with
29
- * a raw Keepa response. */
30
- export declare function extractImageUrl(imagesCSV: string | undefined): string | null;
31
9
  //# sourceMappingURL=products.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"products.d.ts","sourceRoot":"","sources":["../../../src/resources/products/products.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAWrD,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAGzE,qBAAa,QAAS,SAAQ,WAAW;IACjC,IAAI,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;CAuB/D;AAmBD;;;;;;;kDAOkD;AAClD,wBAAgB,cAAc,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAE7D;AAED;;;;0DAI0D;AAC1D,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,CAMtE;AAED;;;;8DAI8D;AAC9D,wBAAgB,UAAU,CACxB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,SAAS,EAChD,YAAY,EAAE,MAAM,GAAG,SAAS,GAC/B,MAAM,GAAG,IAAI,CAaf;AAED;;4BAE4B;AAC5B,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAE5E"}
1
+ {"version":3,"file":"products.d.ts","sourceRoot":"","sources":["../../../src/resources/products/products.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAQrD,OAAO,KAAK,EACV,YAAY,EACZ,iBAAiB,EACjB,qBAAqB,EACtB,MAAM,mBAAmB,CAAC;AAK3B,qBAAa,QAAS,SAAQ,WAAW;IACjC,IAAI,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAwB9D;qFACiF;IAC3E,QAAQ,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,YAAY,CAAC;CAQrE"}
@@ -1,7 +1,9 @@
1
1
  import { APIResource } from '../../core/resource.js';
2
2
  import { resolveDomainId } from '../../lib/marketplace.js';
3
3
  import { normalizeAsins } from '../../lib/asin.js';
4
- import { PRODUCT_PATH, PRODUCT_LIST_CONTEXT, DEFAULT_DAYS, AMAZON_IMAGE_BASE, KEEPA_NO_DATA_SENTINEL, VALID_IMAGE_FILENAME, } from './constant.js';
4
+ import { PRODUCT_PATH, PRODUCT_LIST_CONTEXT, DEFAULT_DAYS, } from './constant.js';
5
+ import { ProductNotFoundError } from './error.js';
6
+ import { toKeepaProduct, isFoundProduct } from './product.util.js';
5
7
  export class Products extends APIResource {
6
8
  async list(params) {
7
9
  if (params.asins.length === 0) {
@@ -24,73 +26,15 @@ export class Products extends APIResource {
24
26
  });
25
27
  return (data.products ?? []).map(toKeepaProduct);
26
28
  }
27
- }
28
- /** Map Keepa's raw wire shape into the consumer-friendly KeepaProduct. */
29
- function toKeepaProduct(raw) {
30
- return {
31
- asin: raw.asin,
32
- title: raw.title,
33
- description: raw.description,
34
- parentAsin: raw.parentAsin,
35
- categoryTree: raw.categoryTree,
36
- rootCategory: raw.rootCategory,
37
- salesRanks: raw.salesRanks,
38
- variations: raw.variations,
39
- bulletPoints: raw.bulletPoints,
40
- images: parseImagesCsv(raw.imagesCSV),
41
- bsr: extractBsr(raw.salesRanks, raw.rootCategory),
42
- };
43
- }
44
- /** Returns true when Keepa returned an actual product record (not just a stub
45
- * for an unknown ASIN). Use as a `.filter()` predicate to drop empty matches.
46
- *
47
- * We use `title.length > 0` because it's the strongest single correlate of
48
- * "Keepa has data" — stubs for unknown ASINs come back without a title, and
49
- * every real listing has one. If Keepa's stub format changes (e.g. they start
50
- * returning a placeholder title), tighten this predicate to also require
51
- * `categoryTree` or another non-string field. */
52
- export function isFoundProduct(product) {
53
- return typeof product.title === 'string' && product.title.length > 0;
54
- }
55
- /** Build the full image-URL list from a Keepa imagesCSV string. Region-neutral CDN.
56
- * Filters out entries that don't look like image filenames (path traversal,
57
- * arbitrary extensions, etc.) — defense in case the CSV is ever influenced by
58
- * untrusted input. Most consumers won't need this directly: `Products.list`
59
- * already fills `images[]` on every returned product. */
60
- export function parseImagesCsv(imagesCSV) {
61
- if (!imagesCSV)
62
- return [];
63
- return imagesCSV
64
- .split(',')
65
- .filter((entry) => VALID_IMAGE_FILENAME.test(entry))
66
- .map((filename) => `${AMAZON_IMAGE_BASE}/${filename}`);
67
- }
68
- /** Extract the most recent real BSR from Keepa's `[ts, rank, ts, rank, ...]` salesRanks array.
69
- * Walks backward through rank entries (odd indices) and skips Keepa's `-1` sentinel which
70
- * marks "no data captured at that timestamp". Returns `null` if every entry is sentinel.
71
- * Most consumers won't need this — `Products.list` already fills `bsr` on every returned
72
- * product. Useful when working with a raw Keepa response. */
73
- export function extractBsr(salesRanks, rootCategory) {
74
- if (!salesRanks || rootCategory === undefined)
75
- return null;
76
- const ranks = salesRanks[String(rootCategory)];
77
- if (!ranks || ranks.length < 2)
78
- return null;
79
- // Keepa pairs are [ts, rank, ts, rank, ...]. If length is even, the last index
80
- // is a rank; if odd (truncated/schema drift), it's a dangling timestamp — skip
81
- // back one slot so we always start on a rank.
82
- const start = ranks.length % 2 === 0 ? ranks.length - 1 : ranks.length - 2;
83
- for (let i = start; i >= 1; i -= 2) {
84
- const rank = ranks[i];
85
- if (rank !== undefined && rank !== KEEPA_NO_DATA_SENTINEL)
86
- return rank;
29
+ /** Fetch a single product by ASIN. Throws `ProductNotFoundError` when Keepa
30
+ * has no record for the ASIN (no product returned, or a stub with no title). */
31
+ async retrieve(params) {
32
+ const { asin, ...rest } = params;
33
+ const [product] = await this.list({ ...rest, asins: [asin] });
34
+ if (!product || !isFoundProduct(product)) {
35
+ throw new ProductNotFoundError(asin);
36
+ }
37
+ return product;
87
38
  }
88
- return null;
89
- }
90
- /** Build a single Amazon image URL from the first entry in Keepa's imagesCSV.
91
- * Equivalent to `parseImagesCsv(imagesCSV)[0] ?? null`. Useful when working with
92
- * a raw Keepa response. */
93
- export function extractImageUrl(imagesCSV) {
94
- return parseImagesCsv(imagesCSV)[0] ?? null;
95
39
  }
96
40
  //# sourceMappingURL=products.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"products.js","sourceRoot":"","sources":["../../../src/resources/products/products.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"products.js","sourceRoot":"","sources":["../../../src/resources/products/products.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EACL,YAAY,EACZ,oBAAoB,EACpB,YAAY,GACb,MAAM,eAAe,CAAC;AAOvB,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnE,MAAM,OAAO,QAAS,SAAQ,WAAW;IACvC,KAAK,CAAC,IAAI,CAAC,MAAyB;QAClC,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;QACnD,CAAC;QACD,IACE,MAAM,CAAC,IAAI,KAAK,SAAS;YACzB,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC,EACnD,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,iBAAiB,MAAM,CAAC,IAAI,+BAA+B,CAAC,CAAC;QAC/E,CAAC;QACD,MAAM,KAAK,GAAG,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC3C,MAAM,MAAM,GAAG,eAAe,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QACnD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CAA0B;YAChE,IAAI,EAAE,YAAY;YAClB,KAAK,EAAE;gBACL,MAAM;gBACN,IAAI,EAAE,KAAK;gBACX,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,YAAY;aAClC;YACD,OAAO,EAAE,oBAAoB;SAC9B,CAAC,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IACnD,CAAC;IAED;qFACiF;IACjF,KAAK,CAAC,QAAQ,CAAC,MAA6B;QAC1C,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,MAAM,CAAC;QACjC,MAAM,CAAC,OAAO,CAAC,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC9D,IAAI,CAAC,OAAO,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC;YACzC,MAAM,IAAI,oBAAoB,CAAC,IAAI,CAAC,CAAC;QACvC,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;CACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "keepa-api",
3
- "version": "0.1.0",
3
+ "version": "0.2.2",
4
4
  "description": "TypeScript SDK for the Keepa API.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -35,6 +35,14 @@
35
35
  "asin"
36
36
  ],
37
37
  "license": "MIT",
38
+ "repository": {
39
+ "type": "git",
40
+ "url": "git+https://github.com/bilalyasin1616/keepa-api.git"
41
+ },
42
+ "bugs": {
43
+ "url": "https://github.com/bilalyasin1616/keepa-api/issues"
44
+ },
45
+ "homepage": "https://github.com/bilalyasin1616/keepa-api#readme",
38
46
  "devDependencies": {
39
47
  "@types/node": "^22.10.0",
40
48
  "dotenv": "^16.4.0",