amaprice 1.0.3 → 1.0.5

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
@@ -12,13 +12,21 @@ npm install -g amaprice
12
12
 
13
13
  ```bash
14
14
  # One-shot price lookup
15
+ amaprice "https://www.amazon.de/dp/B0DZ5P7JD6"
16
+ amaprice B0DZ5P7JD6
15
17
  amaprice price "https://www.amazon.de/dp/B0DZ5P7JD6"
18
+ amaprice price B0DZ5P7JD6
19
+ amaprice price
20
+ # then paste full Amazon URL or ASIN when prompted
16
21
 
17
22
  # JSON output (for scripts / AI agents)
18
23
  amaprice price "https://www.amazon.de/dp/B0DZ5P7JD6" --json
19
24
 
20
25
  # Track a product's price over time
21
26
  amaprice track "https://www.amazon.de/dp/B0DZ5P7JD6"
27
+ amaprice track B0DZ5P7JD6
28
+ amaprice track
29
+ # then paste full Amazon URL or ASIN when prompted
22
30
 
23
31
  # View price history
24
32
  amaprice history B0DZ5P7JD6
@@ -31,14 +39,15 @@ amaprice list
31
39
 
32
40
  | Command | Description |
33
41
  |---|---|
34
- | `amaprice price <url>` | One-shot price lookup |
35
- | `amaprice track <url>` | Track a product's price |
42
+ | `amaprice [url\|asin]` | Shortcut for `amaprice price [url\|asin]` |
43
+ | `amaprice price [url\|asin]` | One-shot price lookup (or prompt if omitted) |
44
+ | `amaprice track [url\|asin]` | Track a product's price (or prompt if omitted) |
36
45
  | `amaprice history <url\|asin>` | Show price history (`--limit N`, default 30) |
37
46
  | `amaprice list` | Show all tracked products with latest price |
38
47
 
39
48
  All commands support `--json` for machine-readable output.
40
49
 
41
- When passing Amazon URLs that contain query parameters (`?` / `&`), always wrap the URL in quotes so your shell treats it as a single argument.
50
+ If your URL contains query parameters (`?` / `&`), either wrap it in quotes or run the command without an argument and paste the full URL into the prompt.
42
51
 
43
52
  ## Community Price Database
44
53
 
package/bin/cli.js CHANGED
@@ -2,6 +2,16 @@
2
2
 
3
3
  const { program } = require('commander');
4
4
  const pkg = require('../package.json');
5
+ const KNOWN_COMMANDS = new Set(['price', 'track', 'history', 'list', 'help']);
6
+
7
+ const userArgs = process.argv.slice(2);
8
+ if (userArgs.length > 0) {
9
+ const firstArg = userArgs[0];
10
+ // Convenience mode: treat `amaprice <url-or-asin>` as `amaprice price <url-or-asin>`.
11
+ if (!firstArg.startsWith('-') && !KNOWN_COMMANDS.has(firstArg)) {
12
+ process.argv.splice(2, 0, 'price');
13
+ }
14
+ }
5
15
 
6
16
  program
7
17
  .name('amaprice')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "amaprice",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "CLI tool to scrape and track Amazon product prices",
5
5
  "main": "src/scraper.js",
6
6
  "type": "commonjs",
@@ -22,7 +22,7 @@ module.exports = function (program) {
22
22
  }))));
23
23
  } else {
24
24
  if (products.length === 0) {
25
- console.log('No tracked products. Use `amaprice track <url>` to start tracking.');
25
+ console.log('No tracked products. Use `amaprice track <url-or-asin>` to start tracking.');
26
26
  return;
27
27
  }
28
28
 
@@ -1,20 +1,23 @@
1
- const { isAmazonUrl } = require('../url');
1
+ const { normalizeAmazonInput } = require('../url');
2
+ const { resolveCliInput } = require('../input');
2
3
  const { scrapePrice } = require('../scraper');
3
4
  const { upsertProduct, insertPrice } = require('../db');
4
5
 
5
6
  module.exports = function (program) {
6
7
  program
7
- .command('price <url>')
8
- .description('One-shot price lookup for an Amazon product')
8
+ .command('price [input...]')
9
+ .description('One-shot price lookup for an Amazon product URL or ASIN')
9
10
  .option('--json', 'Output as JSON')
10
- .action(async (url, opts) => {
11
- if (!isAmazonUrl(url)) {
12
- console.error('Error: URL does not appear to be an Amazon link.');
11
+ .action(async (inputParts, opts) => {
12
+ const input = await resolveCliInput(inputParts);
13
+ const normalized = normalizeAmazonInput(input);
14
+ if (!normalized) {
15
+ console.error('Error: Input must be an Amazon product URL or a valid ASIN.');
13
16
  process.exit(1);
14
17
  }
15
18
 
16
19
  try {
17
- const result = await scrapePrice(url);
20
+ const result = await scrapePrice(normalized.url);
18
21
 
19
22
  if (opts.json) {
20
23
  console.log(JSON.stringify({
@@ -1,20 +1,23 @@
1
- const { isAmazonUrl, extractAsin, extractDomain } = require('../url');
1
+ const { normalizeAmazonInput } = require('../url');
2
+ const { resolveCliInput } = require('../input');
2
3
  const { scrapePrice } = require('../scraper');
3
4
  const { upsertProduct, insertPrice } = require('../db');
4
5
 
5
6
  module.exports = function (program) {
6
7
  program
7
- .command('track <url>')
8
+ .command('track [input...]')
8
9
  .description('Save product + current price to Supabase')
9
10
  .option('--json', 'Output as JSON')
10
- .action(async (url, opts) => {
11
- if (!isAmazonUrl(url)) {
12
- console.error('Error: URL does not appear to be an Amazon link.');
11
+ .action(async (inputParts, opts) => {
12
+ const input = await resolveCliInput(inputParts);
13
+ const normalized = normalizeAmazonInput(input);
14
+ if (!normalized) {
15
+ console.error('Error: Input must be an Amazon product URL or a valid ASIN.');
13
16
  process.exit(1);
14
17
  }
15
18
 
16
19
  try {
17
- const result = await scrapePrice(url);
20
+ const result = await scrapePrice(normalized.url);
18
21
 
19
22
  if (!result.price) {
20
23
  console.error('Error: Could not extract price from the page.');
package/src/input.js ADDED
@@ -0,0 +1,35 @@
1
+ const readline = require('node:readline');
2
+
3
+ async function readStdin() {
4
+ let data = '';
5
+ for await (const chunk of process.stdin) {
6
+ data += chunk;
7
+ }
8
+ return data.trim();
9
+ }
10
+
11
+ function ask(promptText) {
12
+ return new Promise((resolve) => {
13
+ const rl = readline.createInterface({
14
+ input: process.stdin,
15
+ output: process.stdout,
16
+ });
17
+ rl.question(promptText, (answer) => {
18
+ rl.close();
19
+ resolve(String(answer || '').trim());
20
+ });
21
+ });
22
+ }
23
+
24
+ async function resolveCliInput(inputParts, promptText = 'Amazon URL or ASIN: ') {
25
+ const joined = Array.isArray(inputParts) ? inputParts.join(' ').trim() : String(inputParts || '').trim();
26
+ if (joined) return joined;
27
+
28
+ if (!process.stdin.isTTY) {
29
+ return readStdin();
30
+ }
31
+
32
+ return ask(promptText);
33
+ }
34
+
35
+ module.exports = { resolveCliInput };
package/src/url.js CHANGED
@@ -37,4 +37,28 @@ function canonicalUrl(asin, domain = 'amazon.de') {
37
37
  return `https://www.${domain}/dp/${asin}`;
38
38
  }
39
39
 
40
- module.exports = { isAmazonUrl, extractAsin, extractDomain, canonicalUrl, AMAZON_DOMAINS };
40
+ function normalizeAmazonInput(input, defaultDomain = 'amazon.de') {
41
+ const raw = String(input || '').trim();
42
+ if (!raw) return null;
43
+
44
+ const asin = extractAsin(raw);
45
+ if (asin) {
46
+ const domain = isAmazonUrl(raw) ? extractDomain(raw) : defaultDomain;
47
+ return {
48
+ asin,
49
+ domain,
50
+ url: canonicalUrl(asin, domain),
51
+ };
52
+ }
53
+
54
+ return null;
55
+ }
56
+
57
+ module.exports = {
58
+ isAmazonUrl,
59
+ extractAsin,
60
+ extractDomain,
61
+ canonicalUrl,
62
+ normalizeAmazonInput,
63
+ AMAZON_DOMAINS,
64
+ };