@rankwrangler/cli 0.8.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/dist/CHANGELOG.md +55 -0
- package/dist/cli-options.d.ts +1 -0
- package/dist/cli-product-command.js +7 -0
- package/dist/index.js +1 -0
- package/dist/usage.js +1 -0
- package/package.json +8 -3
- package/dist/history-response.d.ts +0 -41
- package/dist/history-response.js +0 -26
package/README.md
CHANGED
|
@@ -7,6 +7,7 @@ npm install -g @rankwrangler/cli
|
|
|
7
7
|
|
|
8
8
|
rw auth set ak_...
|
|
9
9
|
rw product get B0DV53VS61
|
|
10
|
+
rw product get B0DV53VS61 --shortName
|
|
10
11
|
rw product search "retro gardening shirt"
|
|
11
12
|
rw product history B0DV53VS61 --bucket week
|
|
12
13
|
rw keyword get "retro gardening shirt"
|
|
@@ -20,5 +21,7 @@ data and expose no refresh control; Product search retains its separate search c
|
|
|
20
21
|
data contains `keyword`, `searchedAt`, and compact results with `organicSearchPlacement`. Output is
|
|
21
22
|
a JSON `{ ok, data }` envelope; failures use `{ ok: false, error }` on stderr.
|
|
22
23
|
The CLI does not expose Catalog, Operation, provider status, or polling commands.
|
|
24
|
+
`--shortName` adds a nullable image-informed `listing.shortName` to a single Product get, waiting
|
|
25
|
+
up to 20 seconds for generation and returning `null` if it is still running.
|
|
23
26
|
|
|
24
27
|
See the [CLI reference](../../docs/reference/cli.md) for options and release workflow.
|
package/dist/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,61 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## v0.10.0 - 2026-10-20
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Add optional `include` on `product.get` for `marketData`, `shortName`, and `cutoutThumbnail`.
|
|
10
|
+
The default remains `marketData`.
|
|
11
|
+
- Add image-informed design short names. A Product get that includes `shortName` waits up to 20
|
|
12
|
+
seconds. `rw product get <asin> --shortName` requests that include together with `marketData`.
|
|
13
|
+
The response carries `listing.shortName`, or `null` when no name is ready.
|
|
14
|
+
- Add on-demand transparent 128×128 cutout thumbnails through `cutoutThumbnail` on that same
|
|
15
|
+
`include` list. RankWrangler centers the subject and reuses the cutout until the listing image
|
|
16
|
+
changes.
|
|
17
|
+
- Advertise the website URL and a 128px icon in hosted MCP server info.
|
|
18
|
+
- Name the stale ingestion check on `GET /api/health` when the service is degraded, and include
|
|
19
|
+
the deployed commit as `revision` on both health responses.
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
|
|
23
|
+
- Breaking: replace `isUnavailable` with `amazonListingStatus` (`active` or `deleted`) on Product
|
|
24
|
+
listings, search results, and basic `getMany` results. A deleted listing keeps its last-known
|
|
25
|
+
title and thumbnail. `active` means the Amazon detail page exists. The dashboard marks deleted
|
|
26
|
+
listings.
|
|
27
|
+
- Return last-known `getMany` listings immediately and refresh stale listings in the background.
|
|
28
|
+
Short names and cutouts stay on single Product get.
|
|
29
|
+
|
|
30
|
+
### Fixed
|
|
31
|
+
|
|
32
|
+
- Show the server error when the dashboard Products read fails, and reserve the empty catalog
|
|
33
|
+
state for a successful read with no rows.
|
|
34
|
+
- Load the API usage card across the UTC day boundary.
|
|
35
|
+
- Fail an Amazon Catalog read that does not start within 2 minutes with a retryable capacity
|
|
36
|
+
error.
|
|
37
|
+
- Require a second overdue Product before Keepa or SP-API freshness degrades `GET /api/health`,
|
|
38
|
+
and wait out a top search terms report that is still pending.
|
|
39
|
+
|
|
40
|
+
## v0.9.0 - 2026-08-09
|
|
41
|
+
|
|
42
|
+
### Added
|
|
43
|
+
|
|
44
|
+
- Add short-lived typed Provider-attempt telemetry for Keepa and SP-API operations, including
|
|
45
|
+
outcome, latency, and error context for operator diagnostics.
|
|
46
|
+
|
|
47
|
+
### Changed
|
|
48
|
+
|
|
49
|
+
- Breaking: replace the `product.getMany` available/unavailable result union with one fixed shape
|
|
50
|
+
containing identity, nullable title, resolved thumbnail, and `isUnavailable`. Unavailable Amazon
|
|
51
|
+
listings retain their last-known title and thumbnail data.
|
|
52
|
+
|
|
53
|
+
### Fixed
|
|
54
|
+
|
|
55
|
+
- Advertise Claude-compatible MCP Product and keyword schemas so fresh chats can discover and call
|
|
56
|
+
`getMany` directly, with clear unavailable-listing semantics in the Product tool description.
|
|
57
|
+
- Stop unavailable Products from triggering automatic Keepa synchronization when their dashboard
|
|
58
|
+
drawer opens.
|
|
59
|
+
|
|
5
60
|
## v0.8.0 - 2026-08-09
|
|
6
61
|
|
|
7
62
|
### Added
|
package/dist/cli-options.d.ts
CHANGED
|
@@ -3,6 +3,9 @@ export const runProductCommand = async (command, client, config, options, fail)
|
|
|
3
3
|
if (command.verb !== 'search' && options.refresh) {
|
|
4
4
|
fail('INVALID_INPUT', '--refresh is only supported for product search');
|
|
5
5
|
}
|
|
6
|
+
if (command.verb !== 'get' && options.shortName) {
|
|
7
|
+
fail('INVALID_INPUT', '--shortName is only supported for product get');
|
|
8
|
+
}
|
|
6
9
|
if (command.verb === 'get') {
|
|
7
10
|
return await runProductGet(command.args, client, config, options, fail);
|
|
8
11
|
}
|
|
@@ -19,10 +22,14 @@ export const runProductCommand = async (command, client, config, options, fail)
|
|
|
19
22
|
const runProductGet = async (args, client, config, options, fail) => {
|
|
20
23
|
const marketplaceId = requireMarketplaceId(options, config);
|
|
21
24
|
const asins = requireAsins(args, fail);
|
|
25
|
+
if (asins.length > 1 && options.shortName) {
|
|
26
|
+
fail('INVALID_INPUT', '--shortName requires exactly one ASIN');
|
|
27
|
+
}
|
|
22
28
|
if (asins.length === 1) {
|
|
23
29
|
return await client.product.get.mutate({
|
|
24
30
|
marketplaceId,
|
|
25
31
|
asin: asins[0],
|
|
32
|
+
...(options.shortName ? { include: ['marketData', 'shortName'] } : {}),
|
|
26
33
|
});
|
|
27
34
|
}
|
|
28
35
|
return await client.product.getMany.mutate({
|
package/dist/index.js
CHANGED
package/dist/usage.js
CHANGED
|
@@ -39,6 +39,7 @@ export const printUsage = (paths) => {
|
|
|
39
39
|
' --baseUrl <origin> Override API origin',
|
|
40
40
|
` -m, --marketplace <id> Override marketplace (default: ${DEFAULT_MARKETPLACE_ID})`,
|
|
41
41
|
' --refresh Product search refresh (separate Search contract)',
|
|
42
|
+
' --shortName Generate a design name for one Merch Product',
|
|
42
43
|
' --metrics <list> Product history metrics: salesRank,price (default: salesRank,price)',
|
|
43
44
|
' --bucket <unit> Product history buckets: auto,day,week,month (default: auto)',
|
|
44
45
|
' --days <N> Product history lookback (30-3650, default: 365)',
|
package/package.json
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rankwrangler/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Official RankWrangler command line interface",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/merchbaseco/rankwrangler.git",
|
|
8
|
+
"directory": "packages/cli"
|
|
9
|
+
},
|
|
5
10
|
"type": "module",
|
|
6
11
|
"bin": {
|
|
7
12
|
"rw": "dist/index.js",
|
|
@@ -24,8 +29,8 @@
|
|
|
24
29
|
"provenance": true
|
|
25
30
|
},
|
|
26
31
|
"dependencies": {
|
|
27
|
-
"@merchbaseco/access": "0.
|
|
28
|
-
"@rankwrangler/http-client": "^0.
|
|
32
|
+
"@merchbaseco/access": "0.4.0",
|
|
33
|
+
"@rankwrangler/http-client": "^0.10.0",
|
|
29
34
|
"keytar": "7.9.0"
|
|
30
35
|
},
|
|
31
36
|
"devDependencies": {
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
export declare const HISTORY_METRIC_ALIASES: readonly ["bsr", "price"];
|
|
2
|
-
export type HistoryMetricAlias = (typeof HISTORY_METRIC_ALIASES)[number];
|
|
3
|
-
type HistoryPointTuple = [string, number | null] | [string, null, 1];
|
|
4
|
-
export type AgentHistorySeries = {
|
|
5
|
-
bsr?: {
|
|
6
|
-
unit: 'rank';
|
|
7
|
-
category: {
|
|
8
|
-
id: number;
|
|
9
|
-
name: string | null;
|
|
10
|
-
} | null;
|
|
11
|
-
points: HistoryPointTuple[];
|
|
12
|
-
};
|
|
13
|
-
price?: {
|
|
14
|
-
unit: 'minorCurrency';
|
|
15
|
-
currencyCode: 'USD';
|
|
16
|
-
valueScale: 100;
|
|
17
|
-
points: HistoryPointTuple[];
|
|
18
|
-
};
|
|
19
|
-
};
|
|
20
|
-
export type AgentHistoryResponse = {
|
|
21
|
-
schemaVersion?: number;
|
|
22
|
-
status?: string;
|
|
23
|
-
syncTriggered: boolean;
|
|
24
|
-
latestImportAt: string | null;
|
|
25
|
-
series?: AgentHistorySeries;
|
|
26
|
-
};
|
|
27
|
-
export declare const buildCliHistoryResponse: ({ asin, marketplaceId, metrics, response, }: {
|
|
28
|
-
asin: string;
|
|
29
|
-
marketplaceId: string;
|
|
30
|
-
metrics: HistoryMetricAlias[];
|
|
31
|
-
response: AgentHistoryResponse;
|
|
32
|
-
}) => {
|
|
33
|
-
schemaVersion: number;
|
|
34
|
-
asin: string;
|
|
35
|
-
marketplaceId: string;
|
|
36
|
-
status: string;
|
|
37
|
-
latestImportAt: string | null;
|
|
38
|
-
syncTriggered: boolean;
|
|
39
|
-
series: AgentHistorySeries;
|
|
40
|
-
};
|
|
41
|
-
export {};
|
package/dist/history-response.js
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
export const HISTORY_METRIC_ALIASES = ['bsr', 'price'];
|
|
2
|
-
export const buildCliHistoryResponse = ({ asin, marketplaceId, metrics, response, }) => {
|
|
3
|
-
const series = {
|
|
4
|
-
...(metrics.includes('bsr') && response.series?.bsr ? { bsr: response.series.bsr } : {}),
|
|
5
|
-
...(metrics.includes('price') && response.series?.price
|
|
6
|
-
? { price: response.series.price }
|
|
7
|
-
: {}),
|
|
8
|
-
};
|
|
9
|
-
const hasAnyPoints = Object.values(series).some(metricSeries => metricSeries.points.length > 0);
|
|
10
|
-
const status = normalizeHistoryStatus(response.status);
|
|
11
|
-
return {
|
|
12
|
-
schemaVersion: response.schemaVersion ?? 1,
|
|
13
|
-
asin,
|
|
14
|
-
marketplaceId,
|
|
15
|
-
status: status ?? (response.syncTriggered ? 'collecting' : hasAnyPoints ? 'ready' : 'empty'),
|
|
16
|
-
latestImportAt: response.latestImportAt,
|
|
17
|
-
syncTriggered: response.syncTriggered,
|
|
18
|
-
series,
|
|
19
|
-
};
|
|
20
|
-
};
|
|
21
|
-
const normalizeHistoryStatus = (status) => {
|
|
22
|
-
if (status === 'ready' || status === 'collecting' || status === 'empty') {
|
|
23
|
-
return status;
|
|
24
|
-
}
|
|
25
|
-
return null;
|
|
26
|
-
};
|