stratus-db 0.2.1 → 0.3.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 +6 -7
  2. package/package.json +1 -1
  3. package/stratus-db.js +11 -51
package/README.md CHANGED
@@ -59,20 +59,19 @@ Gateway's 403 Forbidden for a brand-new key, which works within a minute or two
59
59
  - A database: `status(id)`, `transact(id, {tx, retract, delete, txId, match})`, `query(id, q)`,
60
60
  `queryAll(id, q)` (async iterator), `pull(id, pks, {asOf})` (and `asOf: t` in a query: the database as it stood after t), `requestIndex(id, att)`,
61
61
  `awaitIndex(id, att)`, `dropIndex(id, att)`, `history(id, {from, limit})`, `historyAll`,
62
- `fork(id, {t, name})` (hosted: a new database, this one as of t), `excise(id, {rows,
62
+ `fork(id, {t, name})` (a new database, this one as of t), `excise(id, {rows,
63
63
  attributes})` (erasure: rows and {pk, att} out of the state, indexes, history and forks),
64
64
  `setHistoryRetention(id, days)` (history kept 30 to 36500 days, or `null` for forever).
65
- - Keys (hosted, with a key reaching every database): `listKeys()`, `createKey({name, scope})`,
65
+ - Keys (with a key reaching every database): `listKeys()`, `createKey({name, scope})`,
66
66
  `revokeKey(keyId)`.
67
67
  - Codec: `encode`, `decode` (typed-JSON text), `toJSONValue`, `fromJSONValue`.
68
68
 
69
- Queries: docs/query.md ("JSON"). Addressing: `"hosted"` (default: `<url>/v1/dbs/<id>/...`,
70
- `Authorization: Bearer <apiKey>`) or `"function-urls"` (the internal service's Function URLs,
71
- resolved through its catalog; `caller` for a local service).
69
+ Queries: docs/query.md ("JSON"). Requests go to `<url>/v1/dbs/<id>/...` with `Authorization:
70
+ Bearer <apiKey>`.
72
71
 
73
72
  ## Tests
74
73
 
75
74
  `node --test test/ejson.test.js` (the codec: velojity's own output in
76
75
  `clients/fixtures/velojity-ejson.json`, which stratus's client-fixtures-test keeps current), and
77
- `scripts/test-js-client` from the repo root: the codec, then the client against the local
78
- service.
76
+ `scripts/test-js-client` from the repo root: the codec, then the client against the hosted
77
+ product run locally.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stratus-db",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "The stratus-db service from JavaScript: typed JSON over fetch, no dependencies.",
5
5
  "homepage": "https://stratus-db.com",
6
6
  "license": "Apache-2.0",
package/stratus-db.js CHANGED
@@ -11,14 +11,11 @@
11
11
  // await s.transact(id, { tx: [{ "order/id": squuid(), "order/status": kw("status/new") }] });
12
12
  // const { rows } = await s.query(id, { where: ["=", "order/status", kw("status/new")] });
13
13
  //
14
- // Addressing: "hosted" (the default) - the catalog at <url>/v1/dbs, a database at
15
- // <url>/v1/dbs/<id>/..., the API key as "Authorization: Bearer <key>". "function-urls" - the
16
- // internal service: the catalog at url, each database at the Function URL its catalog record
17
- // names (looked up, cached for resolveMs, and again when one answers 403 or 404); for testing
18
- // against a local service, opts.caller names the caller (x-stratus-caller).
14
+ // Addressing: the catalog at <url>/v1/dbs, a database at <url>/v1/dbs/<id>/..., the API key as
15
+ // "Authorization: Bearer <key>".
19
16
 
20
17
  /** The client's version: package.json's, which release-js.yml checks against it. */
21
- export const VERSION = "0.2.1";
18
+ export const VERSION = "0.3.0";
22
19
 
23
20
  const USER_AGENT = `stratus-db-js/${VERSION}`;
24
21
  const IN_NODE = typeof process !== "undefined" && process.versions != null && process.versions.node != null;
@@ -542,28 +539,20 @@ const GATEWAY_FORBIDDEN = /^\s*\{\s*"message"\s*:\s*"Forbidden"\s*\}\s*$/;
542
539
  export class Client {
543
540
  /**
544
541
  * @param {object} opts
545
- * @param {string} opts.url the service's base URL (hosted), or the catalog's URL (function-urls)
542
+ * @param {string} opts.url the service's base URL
546
543
  * @param {string} [opts.apiKey] sent as "Authorization: Bearer <key>"
547
- * @param {"hosted"|"function-urls"} [opts.addressing]
548
- * @param {string} [opts.caller] x-stratus-caller, for a local service
549
544
  * @param {number} [opts.retries] attempts after a 429 (default 10)
550
545
  * @param {number} [opts.newKeyWaitMs] how long to keep retrying API Gateway's own 403 Forbidden, which a
551
546
  * brand-new key gets for its first minute or so (default 120000; 0: never)
552
- * @param {number} [opts.resolveMs] function-urls: how long a database's URL is cached (5 minutes)
553
547
  * @param {typeof fetch} [opts.fetch] default globalThis.fetch
554
548
  */
555
549
  constructor(opts) {
556
550
  if (!opts?.url) throw new TypeError("connect needs { url }");
557
551
  this.url = trimSlash(opts.url);
558
- this.addressing = opts.addressing ?? "hosted";
559
- if (!["hosted", "function-urls"].includes(this.addressing)) throw new TypeError(`addressing: ${this.addressing}`);
560
552
  this.apiKey = opts.apiKey;
561
- this.caller = opts.caller;
562
553
  this.retries = opts.retries ?? 10;
563
554
  this.newKeyWaitMs = opts.newKeyWaitMs ?? 120000;
564
- this.resolveMs = opts.resolveMs ?? 300000;
565
555
  this.fetch = opts.fetch ?? globalThis.fetch;
566
- this.urls = { at: 0, byId: new Map() };
567
556
  }
568
557
 
569
558
  // -- requests
@@ -574,7 +563,6 @@ export class Client {
574
563
  if (IN_NODE) headers["user-agent"] = USER_AGENT;
575
564
  if (body !== undefined) headers["content-type"] = "application/json";
576
565
  if (this.apiKey) headers.authorization = `Bearer ${this.apiKey}`;
577
- if (this.caller) headers["x-stratus-caller"] = this.caller;
578
566
  const started = Date.now();
579
567
  for (let attempt = 0, forbidden = 0; ; attempt++) {
580
568
  const r = await this.fetch(url, { method, headers, body: body === undefined ? undefined : encode(body) });
@@ -606,42 +594,14 @@ export class Client {
606
594
  throw new StratusError(r.status, isObj ? b.error : null, isObj ? b.message : String(b ?? ""), b);
607
595
  }
608
596
 
609
- catalogUrl(path) {
610
- return this.addressing === "hosted" ? `${this.url}/v1${path}` : `${this.url}${path}`;
611
- }
612
-
613
597
  /** method path body to the catalog: { status, body }. */
614
598
  callCatalog(method, path, body) {
615
- return this.send(this.catalogUrl(path), method, body);
616
- }
617
-
618
- async resolve() {
619
- const recs = Client.ok(await this.callCatalog("GET", "/dbs"));
620
- const byId = new Map();
621
- for (const r of recs) if (r.url) byId.set(String(r.id), r.url);
622
- this.urls = { at: Date.now(), byId };
623
- return byId;
624
- }
625
-
626
- async dbBase(id) {
627
- const key = String(id);
628
- if (this.addressing === "hosted") return `${this.url}/v1/dbs/${encodeURIComponent(key)}`;
629
- const { at, byId } = this.urls;
630
- if (byId.has(key) && Date.now() - at < this.resolveMs) return trimSlash(byId.get(key));
631
- const u = (await this.resolve()).get(key);
632
- return u === undefined ? null : trimSlash(u);
599
+ return this.send(`${this.url}/v1${path}`, method, body);
633
600
  }
634
601
 
635
602
  /** method path body to database id: { status, body }. */
636
- async callDb(id, method, path, body) {
637
- const base = await this.dbBase(id);
638
- if (base === null) return { status: 404, body: { error: "no-database", message: `No database ${id}` } };
639
- const r = await this.send(base + path, method, body);
640
- if (this.addressing === "function-urls" && (r.status === 403 || r.status === 404)) {
641
- const again = (await this.resolve()).get(String(id));
642
- if (again !== undefined && trimSlash(again) !== base) return this.send(trimSlash(again) + path, method, body);
643
- }
644
- return r;
603
+ callDb(id, method, path, body) {
604
+ return this.send(`${this.url}/v1/dbs/${encodeURIComponent(String(id))}${path}`, method, body);
645
605
  }
646
606
 
647
607
  // -- the catalog
@@ -676,7 +636,7 @@ export class Client {
676
636
  return Client.ok(await this.callCatalog("DELETE", `/dbs/${encodeURIComponent(String(id))}`));
677
637
  }
678
638
 
679
- // -- keys (hosted: an account's keys, managed with a key whose scope is every database)
639
+ // -- keys (an account's keys, managed with a key whose scope is every database)
680
640
 
681
641
  /** The account's keys' records (no secrets). */
682
642
  async listKeys() {
@@ -700,7 +660,7 @@ export class Client {
700
660
 
701
661
  /** The database's state: { id, "primary-key", t, "checkpoint-t", indexes, "index-errors", status }. */
702
662
  async status(id) {
703
- return Client.ok(await this.callDb(id, "GET", this.addressing === "hosted" ? "/status" : "/"));
663
+ return Client.ok(await this.callDb(id, "GET", "/status"));
704
664
  }
705
665
 
706
666
  /**
@@ -767,7 +727,7 @@ export class Client {
767
727
  }
768
728
 
769
729
  /**
770
- * Forks database id (hosted): a new database, this one as of t (default its latest), recorded
730
+ * Forks database id: a new database, this one as of t (default its latest), recorded
771
731
  * in both logs. The fork's record ({ id, "fork-of": { db, t }, ... }).
772
732
  */
773
733
  async fork(id, { t, name } = {}) {
@@ -779,7 +739,7 @@ export class Client {
779
739
 
780
740
  /**
781
741
  * Excises rows (primary keys) and attributes ({ pk, att }) - erasure: gone from the current
782
- * state, its indexes and history (and, hosted, the database's forks): { t, rows, attributes }.
742
+ * state, its indexes and history (and the database's forks): { t, rows, attributes }.
783
743
  */
784
744
  async excise(id, { rows, attributes } = {}) {
785
745
  const body = {};