@rankwrangler/cli 0.1.2 → 0.2.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.
Files changed (3) hide show
  1. package/README.md +3 -2
  2. package/dist/index.js +55 -61
  3. package/package.json +3 -2
package/README.md CHANGED
@@ -11,8 +11,9 @@ npm install -g @rankwrangler/cli
11
11
  ## Usage
12
12
 
13
13
  ```bash
14
- rankwrangler config set api-key rrk_...
15
- rankwrangler products get B0DV53VS61
14
+ rw config set api-key rrk_...
15
+ rw products get B0DV53VS61
16
+ # `rankwrangler` is also supported as an alias
16
17
  ```
17
18
 
18
19
  ## Development
package/dist/index.js CHANGED
@@ -11,18 +11,22 @@ const DEFAULT_MARKETPLACE_ID = 'ATVPDKIKX0DER';
11
11
  const CONFIG_DIR = path.join(homedir(), '.rankwrangler');
12
12
  const CONFIG_PATH = path.join(CONFIG_DIR, 'config.json');
13
13
  const DEFAULT_OUTPUT_PRETTY = true;
14
+ const SUPPORTED_COMMANDS = new Set([
15
+ 'products:get',
16
+ 'api-key:status',
17
+ 'api-key:validate',
18
+ 'config:show',
19
+ 'config:clear',
20
+ 'config:set',
21
+ ]);
14
22
  const { positionals, values } = parseArgs({
15
23
  args: process.argv.slice(2),
16
24
  options: {
17
25
  help: { type: 'boolean', short: 'h' },
18
26
  apiKey: { type: 'string' },
19
- licenseKey: { type: 'string' },
20
27
  baseUrl: { type: 'string' },
21
- url: { type: 'string' },
22
28
  marketplace: { type: 'string', short: 'm' },
23
- marketplaceId: { type: 'string' },
24
29
  asin: { type: 'string', multiple: true },
25
- asins: { type: 'string', multiple: true },
26
30
  },
27
31
  allowPositionals: true,
28
32
  });
@@ -37,6 +41,10 @@ const main = async () => {
37
41
  fail('UNKNOWN_COMMAND', 'Unknown command', { command: positionals.join(' ') });
38
42
  return;
39
43
  }
44
+ if (!isSupportedCommand(command)) {
45
+ fail('UNKNOWN_COMMAND', 'Unknown command', { command: `${command.resource} ${command.verb}` });
46
+ return;
47
+ }
40
48
  const config = await loadConfig();
41
49
  if (command.resource === 'config') {
42
50
  const response = await runConfigCommand(command, config);
@@ -45,7 +53,7 @@ const main = async () => {
45
53
  }
46
54
  const apiKey = resolveApiKey(config);
47
55
  if (!apiKey) {
48
- fail('MISSING_CONFIG', 'api key is required. set via `config set api-key <value>`');
56
+ fail('MISSING_CONFIG', 'API key is required. set via `config set api-key <value>`');
49
57
  return;
50
58
  }
51
59
  const baseUrl = resolveBaseUrl(config);
@@ -65,11 +73,11 @@ const runApiCommand = async (command, client, config) => {
65
73
  }
66
74
  return client.getProductInfoBatch.mutate({ marketplaceId, asins });
67
75
  }
68
- if (command.resource === 'license' && command.verb === 'status') {
69
- return client.license.status.mutate();
76
+ if (command.resource === 'api-key' && command.verb === 'status') {
77
+ return client.apiKey.status.mutate();
70
78
  }
71
- if (command.resource === 'license' && command.verb === 'validate') {
72
- return client.license.validate.mutate();
79
+ if (command.resource === 'api-key' && command.verb === 'validate') {
80
+ return client.apiKey.validate.mutate();
73
81
  }
74
82
  fail('UNKNOWN_COMMAND', 'Unknown command', {
75
83
  command: `${command.resource} ${command.verb}`,
@@ -108,7 +116,7 @@ const runConfigCommand = async (command, config) => {
108
116
  else if (key === 'base-url') {
109
117
  nextConfig.baseUrl = normalizeBaseUrl(value);
110
118
  }
111
- else if (key === 'marketplace' || key === 'marketplace-id') {
119
+ else if (key === 'marketplace') {
112
120
  nextConfig.marketplaceId = value;
113
121
  }
114
122
  else {
@@ -128,11 +136,7 @@ const runConfigCommand = async (command, config) => {
128
136
  return null;
129
137
  };
130
138
  const requireMarketplaceId = (config) => {
131
- const marketplaceId = values.marketplaceId ??
132
- values.marketplace ??
133
- config.marketplaceId ??
134
- process.env.RR_MARKETPLACE_ID ??
135
- DEFAULT_MARKETPLACE_ID;
139
+ const marketplaceId = values.marketplace ?? config.marketplaceId ?? process.env.RR_MARKETPLACE_ID ?? DEFAULT_MARKETPLACE_ID;
136
140
  return marketplaceId;
137
141
  };
138
142
  const requireAsins = (commandArgs) => {
@@ -143,7 +147,7 @@ const requireAsins = (commandArgs) => {
143
147
  return Array.from(new Set(candidates.map(normalizeAsin)));
144
148
  };
145
149
  const collectAsinCandidates = (commandArgs) => {
146
- const optionAsins = [...(values.asin ?? []), ...(values.asins ?? [])];
150
+ const optionAsins = [...(values.asin ?? [])];
147
151
  const envAsins = process.env.RR_ASINS
148
152
  ? process.env.RR_ASINS.split(',').map(value => value.trim())
149
153
  : [];
@@ -160,10 +164,10 @@ const normalizeAsin = (value) => {
160
164
  return normalized;
161
165
  };
162
166
  const resolveApiKey = (config) => {
163
- return values.apiKey ?? values.licenseKey ?? config.apiKey ?? process.env.RR_LICENSE_KEY;
167
+ return values.apiKey ?? config.apiKey ?? process.env.RR_API_KEY;
164
168
  };
165
169
  const resolveBaseUrl = (config) => {
166
- const configured = values.baseUrl ?? values.url ?? config.baseUrl ?? process.env.RR_API_URL;
170
+ const configured = values.baseUrl ?? config.baseUrl ?? process.env.RR_API_URL;
167
171
  return normalizeBaseUrl(configured ?? DEFAULT_API_BASE_URL);
168
172
  };
169
173
  const normalizeBaseUrl = (value) => {
@@ -177,32 +181,18 @@ const normalizeBaseUrl = (value) => {
177
181
  };
178
182
  const resolveCommand = (inputPositionals) => {
179
183
  const [first, second, ...rest] = inputPositionals;
180
- if (!first) {
181
- return null;
182
- }
183
- if (first === 'get-product-info') {
184
- return {
185
- resource: 'products',
186
- verb: 'get',
187
- args: rest,
188
- };
189
- }
190
- if (first === 'get-product-info-batch') {
191
- return {
192
- resource: 'products',
193
- verb: 'get',
194
- args: rest,
195
- };
196
- }
197
- if (!second) {
184
+ if (!first || !second) {
198
185
  return null;
199
186
  }
200
187
  return {
201
188
  resource: first,
202
- verb: first === 'products' && second === 'get-batch' ? 'get' : second,
189
+ verb: second,
203
190
  args: rest,
204
191
  };
205
192
  };
193
+ const isSupportedCommand = (command) => {
194
+ return SUPPORTED_COMMANDS.has(`${command.resource}:${command.verb}`);
195
+ };
206
196
  const loadConfig = async () => {
207
197
  try {
208
198
  const raw = await readFile(CONFIG_PATH, 'utf8');
@@ -275,40 +265,44 @@ const fail = (code, message, details) => {
275
265
  };
276
266
  const printUsage = () => {
277
267
  const usage = [
278
- 'RankWrangler CLI',
279
- '',
280
- 'Command Shape',
281
- ' rankwrangler <resource> <verb> [args...] [flags...]',
268
+ 'NAME',
269
+ ' rw, rankwrangler - RankWrangler command line interface',
282
270
  '',
283
- 'Principles',
284
- ' - Resource-first, verb-second commands',
285
- ' - JSON-only output with {"ok": true|false, ...} envelope',
286
- ' - One command maps to one API capability',
271
+ 'SYNOPSIS',
272
+ ' rw <resource> <verb> [args...] [options]',
273
+ ' rankwrangler <resource> <verb> [args...] [options]',
287
274
  '',
288
- 'API Commands',
289
- ' products get <ASIN...> [--marketplace <id>|-m <id>]',
290
- ' license status',
291
- ' license validate',
292
- '',
293
- 'Config Commands',
275
+ 'COMMANDS',
276
+ ' products get <ASIN...>',
277
+ ' api-key status',
278
+ ' api-key validate',
294
279
  ' config show',
295
280
  ' config clear',
296
281
  ' config set api-key <value>',
297
282
  ' config set base-url <origin>',
298
283
  ' config set marketplace <marketplaceId>',
299
284
  '',
300
- 'Global Flags',
301
- ' --apiKey <value> Override API key (alias: --licenseKey)',
302
- ' --baseUrl <origin> Override API origin (alias: --url)',
303
- ` --marketplace <id>, -m Override marketplace (default: ${DEFAULT_MARKETPLACE_ID})`,
304
- ' --marketplaceId <id> Compatibility alias for --marketplace',
285
+ 'OPTIONS',
286
+ ' -h, --help Show this help message',
287
+ ' --apiKey <value> Override API key',
288
+ ' --baseUrl <origin> Override API origin',
289
+ ` -m, --marketplace <id> Override marketplace (default: ${DEFAULT_MARKETPLACE_ID})`,
305
290
  ' --asin <ASIN> Add ASIN (repeatable)',
306
- ' --asins <ASIN> Add ASIN (repeatable, compatibility alias)',
307
291
  '',
308
- 'Legacy Aliases (still supported)',
309
- ' get-product-info',
310
- ' get-product-info-batch',
311
- ' products get-batch',
292
+ 'FILES',
293
+ ` ${CONFIG_PATH} Local CLI config`,
294
+ '',
295
+ 'ENVIRONMENT',
296
+ ' RR_API_KEY API key fallback',
297
+ ' RR_API_URL API origin fallback',
298
+ ' RR_MARKETPLACE_ID Marketplace fallback',
299
+ ' RR_ASIN Single ASIN fallback',
300
+ ' RR_ASINS Comma-separated ASIN fallback',
301
+ '',
302
+ 'EXAMPLES',
303
+ ' rw config set api-key rrk_...',
304
+ ' rw products get B0DV53VS61',
305
+ ' rankwrangler api-key status',
312
306
  ];
313
307
  console.log(usage.join('\n'));
314
308
  };
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "@rankwrangler/cli",
3
- "version": "0.1.2",
3
+ "version": "0.2.0",
4
4
  "description": "Official RankWrangler command line interface",
5
5
  "type": "module",
6
6
  "bin": {
7
+ "rw": "dist/index.js",
7
8
  "rankwrangler": "dist/index.js"
8
9
  },
9
10
  "main": "./dist/index.js",
@@ -19,7 +20,7 @@
19
20
  "access": "public"
20
21
  },
21
22
  "dependencies": {
22
- "@rankwrangler/http-client": "^0.1.2"
23
+ "@rankwrangler/http-client": "^0.2.0"
23
24
  },
24
25
  "devDependencies": {
25
26
  "@types/node": "^24.3.0",