@profullstack/nichedb 0.51.0 → 0.52.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 +88 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@profullstack/nichedb",
3
- "version": "0.51.0",
3
+ "version": "0.52.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.51.0';
18
+ export const VERSION = '0.52.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');
@@ -176,6 +176,14 @@ export const COMMANDS = [
176
176
  summary: 'The feeds your key follows.',
177
177
  options: ['--json'],
178
178
  },
179
+ {
180
+ name: 'webhooks',
181
+ usage:
182
+ 'webhooks [list] | add <url> [--events a,b] [--description …] | rm|test|secret|rotate|enable|disable <id> | deliveries [<id>]',
183
+ summary:
184
+ 'Account webhooks (key required): signed Standard Webhooks POSTs for feed.item.published, feed.followed and more.',
185
+ options: ['--events', '--description', '--limit', '--json'],
186
+ },
179
187
  {
180
188
  name: 'rss',
181
189
  usage: 'rss <feed>',
@@ -867,6 +875,85 @@ export async function run(
867
875
  for (const f of feeds) out(`${pad(f.slug, 30)} ${f.name}`);
868
876
  return 0;
869
877
  }
878
+ case 'webhooks':
879
+ case 'webhook': {
880
+ const [sub = 'list', arg] = rest;
881
+ const base = '/api/v1/webhooks';
882
+ const id = () => {
883
+ if (!arg) throw new Error(`webhooks ${sub} <id>`);
884
+ return `${base}/${encodeURIComponent(arg)}`;
885
+ };
886
+ const show = (r, text) => out(json ? JSON.stringify(r, null, 2) : text);
887
+ if (sub === 'list' || sub === 'ls') {
888
+ const r = await client.get(base);
889
+ if (json) {
890
+ show(r);
891
+ return 0;
892
+ }
893
+ for (const e of r.endpoints)
894
+ out(
895
+ `${pad(e.id, 28)} ${pad(e.enabled ? 'on' : 'off', 4)} ${pad(e.events.join(','), 24)} ${e.url}`,
896
+ );
897
+ if (r.endpoints.length === 0) out('(no webhooks)');
898
+ out(`\nevents: ${r.event_types.join(', ')}`);
899
+ return 0;
900
+ }
901
+ if (sub === 'add' || sub === 'create') {
902
+ if (!arg) throw new Error('webhooks add <url> [--events a,b]');
903
+ const r = await client.post(base, {
904
+ url: arg,
905
+ events: csv(flags.events),
906
+ description: typeof flags.description === 'string' ? flags.description : '',
907
+ });
908
+ show(
909
+ r,
910
+ `${r.endpoint.id} ${r.endpoint.url}\nsecret: ${r.secret}\n(also: nichedb webhooks secret ${r.endpoint.id})`,
911
+ );
912
+ return 0;
913
+ }
914
+ if (sub === 'rm' || sub === 'delete') {
915
+ show(await client.del(id()), `Removed ${arg}.`);
916
+ return 0;
917
+ }
918
+ if (sub === 'test') {
919
+ const r = await client.post(`${id()}/test`, {});
920
+ show(
921
+ r,
922
+ r.ok ? `Delivered (HTTP ${r.status}).` : `Failed: ${r.error ?? `HTTP ${r.status}`}`,
923
+ );
924
+ return r.ok ? 0 : 1;
925
+ }
926
+ if (sub === 'secret') {
927
+ const r = await client.get(`${id()}/secret`);
928
+ show(r, r.secret);
929
+ return 0;
930
+ }
931
+ if (sub === 'rotate') {
932
+ const r = await client.post(`${id()}/rotate`, {});
933
+ show(r, `${r.secret}\n(the old secret has stopped working)`);
934
+ return 0;
935
+ }
936
+ if (sub === 'enable' || sub === 'disable') {
937
+ const r = await client.patch(id(), { enabled: sub === 'enable' });
938
+ show(r, `${r.id} ${r.enabled ? 'on' : 'off'}`);
939
+ return 0;
940
+ }
941
+ if (sub === 'deliveries') {
942
+ const limit = flags.limit ? `?limit=${Number(flags.limit)}` : '';
943
+ const r = await client.get(`${arg ? `${id()}/deliveries` : `${base}/deliveries`}${limit}`);
944
+ if (json) {
945
+ show(r);
946
+ return 0;
947
+ }
948
+ for (const d of r.deliveries)
949
+ out(
950
+ `${pad(d.id, 28)} ${pad(d.status, 9)} ${pad(d.last_status ?? '-', 4)} ${pad(d.event_type, 22)} ${when(d.created_at)} ${d.last_error ?? ''}`,
951
+ );
952
+ if (r.deliveries.length === 0) out('(no deliveries)');
953
+ return 0;
954
+ }
955
+ throw new Error('webhooks list|add|rm|test|secret|rotate|enable|disable|deliveries');
956
+ }
870
957
  case 'rss': {
871
958
  const url = `${client.base}/f/${rest[0]}.rss`;
872
959
  if (!flags.fetch) {