@profullstack/nichedb 0.47.0 → 0.49.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 (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.js +52 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@profullstack/nichedb",
3
- "version": "0.47.0",
3
+ "version": "0.49.0",
4
4
  "description": "CLI and MCP bridge for NicheDB: browse collections, manage sources and feeds, search items, from any deployment",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
package/src/index.js CHANGED
@@ -15,7 +15,7 @@ import { homedir, tmpdir } from 'node:os';
15
15
  import { join } from 'node:path';
16
16
  import { createInterface } from 'node:readline';
17
17
 
18
- export const VERSION = '0.47.0';
18
+ export const VERSION = '0.49.0';
19
19
  const GEO_FLAGS = ['lat', 'long', 'radius', 'unit', 'bbox', 'sort', 'offset'];
20
20
  const DEFAULT_API = process.env.NICHEDB_API ?? 'https://nichedb.dev';
21
21
  const CONFIG_DIR = join(process.env.XDG_CONFIG_HOME ?? join(homedir(), '.config'), 'nichedb');
@@ -189,6 +189,13 @@ export const COMMANDS = [
189
189
  'Population from the world to the ZIP code: an area, its measures and its largest children.',
190
190
  options: ['--level country|state|city|zip', '--limit', '--offset', '--json'],
191
191
  },
192
+ {
193
+ name: 'isbn',
194
+ usage: 'isbn <isbn> [--zip <zip>] | isbn --title <t> [--author <a>] [--zip <zip>]',
195
+ summary:
196
+ 'Where to buy a book: the edition, sellers new/used/ebook/library, and shops near a ZIP.',
197
+ options: ['--title', '--author', '--zip', '--json'],
198
+ },
192
199
  {
193
200
  name: 'tlds',
194
201
  usage: 'tlds [<query>] [--registrar <slug>] [--type <t>] [--max-renew <n>] [--trap] [--sort …]',
@@ -850,6 +857,50 @@ export async function run(
850
857
  out(await res.text());
851
858
  return 0;
852
859
  }
860
+ case 'isbn': {
861
+ const qs = new URLSearchParams();
862
+ if (rest[0]) qs.set('isbn', rest[0]);
863
+ if (flags.title) qs.set('title', flags.title);
864
+ if (flags.author) qs.set('author', flags.author);
865
+ if (flags.zip) qs.set('zip', flags.zip);
866
+ if (!qs.has('isbn') && !qs.has('title')) throw new Error('isbn <isbn> | isbn --title <t>');
867
+ const b = await client.get(`/api/v1/books/buy?${qs}`);
868
+ if (json) {
869
+ out(JSON.stringify(b, null, 2));
870
+ return 0;
871
+ }
872
+ const e = b.edition;
873
+ out(`${b.title ?? '(unknown title)'}${b.author ? ` — ${b.author}` : ''}`);
874
+ if (b.isbn)
875
+ out(` ISBN-13 ${b.isbn.isbn13}${b.isbn.isbn10 ? ` ISBN-10 ${b.isbn.isbn10}` : ''}`);
876
+ if (e)
877
+ out(
878
+ ` ${[e.publishers?.[0], e.publishDate, e.pages ? `${e.pages} pages` : null].filter(Boolean).join(' · ')}`,
879
+ );
880
+ for (const kind of ['new', 'used', 'ebook', 'borrow']) {
881
+ const links = b.online.filter((l) => l.kind === kind);
882
+ if (!links.length) continue;
883
+ out(`\n${kind}`);
884
+ for (const l of links) out(` ${pad(l.vendor, 22)} ${l.url}`);
885
+ }
886
+ if (b.inStore) {
887
+ out(`\nin store near ${b.inStore.near ?? b.inStore.zip}`);
888
+ for (const s of b.inStore.storeFinders) out(` ${pad(s.vendor, 22)} ${s.url}`);
889
+ for (const [label, list] of [
890
+ ['bookshops', b.inStore.bookshops],
891
+ ['libraries', b.inStore.libraries],
892
+ ]) {
893
+ out(`\n${label}`);
894
+ for (const p of list)
895
+ out(
896
+ ` ${pad(`${p.miles ?? '?'} mi`, 8)} ${p.name}${p.address ? `, ${p.address}` : ''}${p.phone ? ` ${p.phone}` : ''}`,
897
+ );
898
+ if (!list.length) out(' (none mapped within 10 miles)');
899
+ }
900
+ if (b.inStore.error) out(`\n${b.inStore.error}`);
901
+ }
902
+ return 0;
903
+ }
853
904
  case 'population': {
854
905
  const qs = new URLSearchParams();
855
906
  if (flags.level) qs.set('level', flags.level);