stratus-db 0.3.0 → 0.5.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.
- package/README.md +10 -1
- package/package.json +1 -1
- package/stratus-db.js +42 -12
package/README.md
CHANGED
|
@@ -57,7 +57,8 @@ Gateway's 403 Forbidden for a brand-new key, which works within a minute or two
|
|
|
57
57
|
- Catalog: `listDbs({deleted})`, `dbByName(name)`, `dbRecord(id)`, `createDb({name, primaryKey})`,
|
|
58
58
|
`renameDb(id, name)`, `deleteDb(id)`.
|
|
59
59
|
- A database: `status(id)`, `transact(id, {tx, retract, delete, txId, match})`, `query(id, q)`,
|
|
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)
|
|
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, {required})` (att an attribute, or an array of 2 to 8 for a
|
|
61
|
+
multi-attribute index: queried by tuples, `["=", ["a", "b"], [x, y]]`; docs/query.md),
|
|
61
62
|
`awaitIndex(id, att)`, `dropIndex(id, att)`, `history(id, {from, limit})`, `historyAll`,
|
|
62
63
|
`fork(id, {t, name})` (a new database, this one as of t), `excise(id, {rows,
|
|
63
64
|
attributes})` (erasure: rows and {pk, att} out of the state, indexes, history and forks),
|
|
@@ -65,6 +66,14 @@ Gateway's 403 Forbidden for a brand-new key, which works within a minute or two
|
|
|
65
66
|
- Keys (with a key reaching every database): `listKeys()`, `createKey({name, scope})`,
|
|
66
67
|
`revokeKey(keyId)`.
|
|
67
68
|
- Codec: `encode`, `decode` (typed-JSON text), `toJSONValue`, `fromJSONValue`.
|
|
69
|
+
- `rowId(n)`: a row named by its row id.
|
|
70
|
+
|
|
71
|
+
**Keys and row ids.** A primary key is a UUID (`squuid()`), a string or an integer (a long:
|
|
72
|
+
past 2^53, pass a `BigInt`). Every row also carries `"stratus/id"`, a row id the database assigns
|
|
73
|
+
when the row is made. `transact` answers `{ t, pks, ids }`. Where a key goes - `pull`, `delete`,
|
|
74
|
+
a row's key attribute - `rowId(n)` names a row by its id; a bare integer is always a primary key.
|
|
75
|
+
Queries return rows in row id order (the order they were made), `{ order: "desc" }` newest first;
|
|
76
|
+
`next` is a row id.
|
|
68
77
|
|
|
69
78
|
Queries: docs/query.md ("JSON"). Requests go to `<url>/v1/dbs/<id>/...` with `Authorization:
|
|
70
79
|
Bearer <apiKey>`.
|
package/package.json
CHANGED
package/stratus-db.js
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
// "Authorization: Bearer <key>".
|
|
16
16
|
|
|
17
17
|
/** The client's version: package.json's, which release-js.yml checks against it. */
|
|
18
|
-
export const VERSION = "0.
|
|
18
|
+
export const VERSION = "0.5.0";
|
|
19
19
|
|
|
20
20
|
const USER_AGENT = `stratus-db-js/${VERSION}`;
|
|
21
21
|
const IN_NODE = typeof process !== "undefined" && process.versions != null && process.versions.node != null;
|
|
@@ -269,6 +269,13 @@ export const localDate = (text) => LocalDate.parse(text);
|
|
|
269
269
|
export const double = (v) => new Double(v);
|
|
270
270
|
export const list = (...items) => List.from(items);
|
|
271
271
|
|
|
272
|
+
/**
|
|
273
|
+
* A row id, tagged: { "stratus/id": n }. Every row carries its row id (row["stratus/id"]), a
|
|
274
|
+
* long the database assigns when the row is made; a command or a pull names a row by it where a
|
|
275
|
+
* bare integer would be a primary key.
|
|
276
|
+
*/
|
|
277
|
+
export const rowId = (n) => ({ "stratus/id": n });
|
|
278
|
+
|
|
272
279
|
// ------------------------------------------------------------------ Typed JSON
|
|
273
280
|
// Typed JSON (docs/json.md): stratus's encoding, MongoDB Extended JSON v2's tags where they
|
|
274
281
|
// mean the same and stratus's own where it has none. encode/decode work on JSON text;
|
|
@@ -529,6 +536,15 @@ function queryString(params) {
|
|
|
529
536
|
|
|
530
537
|
function attName(att) { return att instanceof Keyword ? att.fullName : String(att).replace(/^:/, ""); }
|
|
531
538
|
|
|
539
|
+
// An index's name: an attribute's, or a multi-attribute index's (an array) joined by commas -
|
|
540
|
+
// how the status keys it, and the DELETE path names it.
|
|
541
|
+
function indexName(att) { return Array.isArray(att) ? att.map(attName).join(",") : attName(att); }
|
|
542
|
+
|
|
543
|
+
// The DELETE path of an index: each name's parts encoded, its slashes and commas kept.
|
|
544
|
+
function indexPath(att) {
|
|
545
|
+
return indexName(att).split(",").map((n) => n.split("/").map(encodeURIComponent).join("/")).join(",");
|
|
546
|
+
}
|
|
547
|
+
|
|
532
548
|
/** A client of the stratus service at opts.url (see the module's comment for opts). */
|
|
533
549
|
export function connect(opts) {
|
|
534
550
|
return new Client(opts);
|
|
@@ -664,9 +680,11 @@ export class Client {
|
|
|
664
680
|
}
|
|
665
681
|
|
|
666
682
|
/**
|
|
667
|
-
* Transacts: { t, pks, duplicate? }
|
|
668
|
-
*
|
|
669
|
-
*
|
|
683
|
+
* Transacts: { t, pks, ids, duplicate? } - pks and ids are tx's rows' primary keys and row ids,
|
|
684
|
+
* in order. tx: rows (each with its primary key: squuid(); or naming its row by rowId(n) in
|
|
685
|
+
* the key's place), retract: rows of attributes to remove, delete: primary keys (or rowId(n)),
|
|
686
|
+
* txId: makes a retry safe, match: rows whose attributes must hold those values now (else a
|
|
687
|
+
* 409 "conflict").
|
|
670
688
|
*/
|
|
671
689
|
async transact(id, { tx, retract, delete: del, txId, match }) {
|
|
672
690
|
const body = {};
|
|
@@ -678,7 +696,11 @@ export class Client {
|
|
|
678
696
|
return Client.ok(await this.callDb(id, "POST", "/transact", body));
|
|
679
697
|
}
|
|
680
698
|
|
|
681
|
-
/**
|
|
699
|
+
/**
|
|
700
|
+
* One page of query q (docs/query.md, "JSON"): { rows, next, t } - rows in row id order (the
|
|
701
|
+
* order they were made; { order: "desc" }: newest first), next the cursor (a row id) to pass
|
|
702
|
+
* as after.
|
|
703
|
+
*/
|
|
682
704
|
async query(id, q = {}) {
|
|
683
705
|
const { asOf, ...rest } = q;
|
|
684
706
|
return Client.ok(await this.callDb(id, "POST", "/query", asOf === undefined ? rest : { ...rest, "as-of": asOf }));
|
|
@@ -696,25 +718,33 @@ export class Client {
|
|
|
696
718
|
}
|
|
697
719
|
|
|
698
720
|
/**
|
|
699
|
-
* The rows of primary keys
|
|
700
|
-
* they stood after transaction t.
|
|
721
|
+
* The rows of pks (primary keys, or rowId(n)), in order (null where there is none); { asOf: t }
|
|
722
|
+
* reads them as they stood after transaction t.
|
|
701
723
|
*/
|
|
702
724
|
async pull(id, pks, { asOf } = {}) {
|
|
703
725
|
return (Client.ok(await this.callDb(id, "POST", "/pull", asOf === undefined ? { pks } : { pks, "as-of": asOf }))).rows;
|
|
704
726
|
}
|
|
705
727
|
|
|
706
|
-
/**
|
|
707
|
-
|
|
708
|
-
|
|
728
|
+
/**
|
|
729
|
+
* Requests a value index on att: { att, state } ("building" until a checkpoint builds it).
|
|
730
|
+
* att is an attribute, or an array of 2 to 8 for a multi-attribute index (its rows keyed by
|
|
731
|
+
* the tuple of their values; queried by tuple predicates), with { required }: the attributes
|
|
732
|
+
* a row needs a value of to be in it.
|
|
733
|
+
*/
|
|
734
|
+
async requestIndex(id, att, { required } = {}) {
|
|
735
|
+
const body = { att: Array.isArray(att) ? att.map(attName) : attName(att) };
|
|
736
|
+
if (required !== undefined) body.required = required.map(attName);
|
|
737
|
+
return Client.ok(await this.callDb(id, "POST", "/indexes", body));
|
|
709
738
|
}
|
|
710
739
|
|
|
740
|
+
/** Drops att's index (an attribute, or a multi-attribute index's array). */
|
|
711
741
|
async dropIndex(id, att) {
|
|
712
|
-
return Client.ok(await this.callDb(id, "DELETE", `/indexes/${
|
|
742
|
+
return Client.ok(await this.callDb(id, "DELETE", `/indexes/${indexPath(att)}`));
|
|
713
743
|
}
|
|
714
744
|
|
|
715
745
|
/** Waits until att's index is ready (rejects if it failed, or after timeoutMs). */
|
|
716
746
|
async awaitIndex(id, att, { timeoutMs = 60000, intervalMs = 200 } = {}) {
|
|
717
|
-
const name =
|
|
747
|
+
const name = indexName(att);
|
|
718
748
|
const deadline = Date.now() + timeoutMs;
|
|
719
749
|
for (;;) {
|
|
720
750
|
const s = await this.status(id);
|