sapixdb 0.1.0 → 0.2.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.
@@ -1,41 +1,124 @@
1
- import type { SapixClientConfig, WriteResult, NucleotideRecord, QueryOptions } from "./types.js";
2
- export declare class CollectionQuery<T = Record<string, unknown>> {
3
- private readonly config;
1
+ import type { AgentStatusResponse, ChainHeadResponse, QueryResult, RecordView, SaqlQuery, StrandRecordsResponse, WriteResponse } from "./types.js";
2
+ type Requester = <T>(method: string, path: string, body?: unknown) => Promise<T>;
3
+ /**
4
+ * A read-only view of a collection scoped to a specific point in time.
5
+ * Returned by `CollectionClient.asOf(timestampHlc)`.
6
+ *
7
+ * @example
8
+ * const snapshot = db.collection("orders").asOf(record.timestamp_hlc);
9
+ * const results = await snapshot.latest({ limit: 10 });
10
+ */
11
+ export declare class CollectionSnapshot {
4
12
  private readonly name;
5
- private readonly asOfTimestamp?;
6
- constructor(config: SapixClientConfig, name: string, asOfTimestamp?: string | undefined);
7
- /** Fetch all versions matching filter (full history). */
8
- all(options?: Omit<QueryOptions, "latest">): Promise<NucleotideRecord<T>[]>;
9
- /** Fetch only the latest version of each matching record. */
10
- latest(options?: Omit<QueryOptions, "latest">): Promise<NucleotideRecord<T>[]>;
11
- /** Find records matching a filter, latest version only. */
12
- find(filter: Record<string, unknown>, options?: Omit<QueryOptions, "filter" | "latest">): Promise<NucleotideRecord<T>[]>;
13
- /** Find one record matching a filter, or null. */
14
- findOne(filter: Record<string, unknown>): Promise<NucleotideRecord<T> | null>;
15
- private _query;
13
+ private readonly timestampHlc;
14
+ private readonly req;
15
+ constructor(name: string, timestampHlc: number, req: Requester);
16
+ /** Records written at or before this snapshot timestamp, newest-first. */
17
+ latest(opts?: {
18
+ limit?: number;
19
+ }): Promise<QueryResult>;
20
+ /**
21
+ * Equality-filter scan bounded by the snapshot timestamp.
22
+ * `filter` is a `{field: value}` object — first key is used.
23
+ */
24
+ find(filter: Record<string, unknown>, opts?: {
25
+ limit?: number;
26
+ }): Promise<QueryResult>;
27
+ findOne(filter: Record<string, unknown>): Promise<RecordView | null>;
16
28
  }
17
- export declare class CollectionClient<T = Record<string, unknown>> {
18
- private readonly config;
19
- private readonly name;
20
- constructor(config: SapixClientConfig, name: string);
29
+ /**
30
+ * Client for a named SapixDB agent (collection).
31
+ * All operations route to `/v1/agents/{name}/...`.
32
+ *
33
+ * Obtain via `SapixClient.collection(name)` or `SapixClient.agent(name)`.
34
+ *
35
+ * @example
36
+ * const orders = db.collection("orders");
37
+ *
38
+ * // Write
39
+ * const record = await orders.write({ total: 99.99, status: "pending" });
40
+ *
41
+ * // Read
42
+ * const latest = await orders.latest({ limit: 20 });
43
+ * const pending = await orders.find({ status: "pending" });
44
+ * const one = await orders.findOne({ status: "pending" });
45
+ * const byHash = await orders.get(record.content_hash);
46
+ *
47
+ * // History (chronological)
48
+ * const history = await orders.history({ limit: 100, offset: 0 });
49
+ *
50
+ * // Time travel
51
+ * const snapshot = await orders.asOf(record.timestamp_hlc).latest();
52
+ *
53
+ * // Direct SaQL
54
+ * const result = await orders.query({ type: "latest", limit: 5 });
55
+ *
56
+ * // Realtime — handled on SapixClient
57
+ * client.subscribeAgent("orders", (event) => console.log(event));
58
+ */
59
+ export declare class CollectionClient {
60
+ readonly name: string;
61
+ private readonly req;
62
+ constructor(name: string, req: Requester);
63
+ /**
64
+ * Append a JSON record to the agent's strand.
65
+ * `data` can be any JSON-serialisable object.
66
+ */
67
+ write(data: Record<string, unknown>): Promise<WriteResponse>;
68
+ /** Alias for `write` — matches Python/Go SDK naming. */
69
+ writeJson(data: Record<string, unknown>): Promise<WriteResponse>;
70
+ /**
71
+ * Fetch a single record by its BLAKE3 content hash.
72
+ * Use `record.content_hash` from a previous write or query.
73
+ */
74
+ get(contentHash: string): Promise<RecordView>;
75
+ /**
76
+ * Return the most recent records, newest-first.
77
+ *
78
+ * Pass `filter: { field: value }` to run an equality scan (uses a field
79
+ * index when one is available for that field, otherwise a full strand scan).
80
+ */
81
+ latest(opts?: {
82
+ limit?: number;
83
+ filter?: Record<string, unknown>;
84
+ }): Promise<QueryResult>;
85
+ /**
86
+ * Return records in chronological order (oldest-first) with pagination.
87
+ * Uses `GET /v1/agents/{name}/strand/records`.
88
+ */
89
+ history(opts?: {
90
+ limit?: number;
91
+ offset?: number;
92
+ }): Promise<StrandRecordsResponse>;
93
+ /**
94
+ * Equality-filter scan across the full strand.
95
+ * `filter` is a `{field: value}` object — first key is used.
96
+ *
97
+ * Uses a field index when one exists for that field; otherwise falls back
98
+ * to a full strand scan on the server.
99
+ */
100
+ find(filter: Record<string, unknown>, opts?: {
101
+ limit?: number;
102
+ }): Promise<QueryResult>;
103
+ /** Return the first matching record, or `null` if none. */
104
+ findOne(filter: Record<string, unknown>): Promise<RecordView | null>;
105
+ /** Execute any SaQL query directly against this agent. */
106
+ query(q: SaqlQuery): Promise<QueryResult>;
107
+ /** Current chain head hash and record count. */
108
+ head(): Promise<ChainHeadResponse>;
109
+ /** Agent status: record count, chain head, zone, schema version, caged state. */
110
+ status(): Promise<AgentStatusResponse>;
21
111
  /**
22
- * Return a query scoped to a specific point in time.
23
- * @param timestamp ISO 8601 string, e.g. "2026-05-12T10:00:00Z"
112
+ * Scope reads to a point in time identified by an HLC timestamp.
113
+ * Returns a `CollectionSnapshot` call `.latest()` or `.find()` on it.
114
+ *
115
+ * @param timestampHlc — `NucleotideRecord.timestamp_hlc` from any prior record
116
+ *
117
+ * @example
118
+ * const snapshot = orders.asOf(record.timestamp_hlc);
119
+ * const state = await snapshot.latest({ limit: 50 });
24
120
  */
25
- asOf(timestamp: string): CollectionQuery<T>;
26
- /** Write a new record. Every write is a new nucleotide — nothing is overwritten. */
27
- write(data: Partial<T> & Record<string, unknown>): Promise<WriteResult>;
28
- /** Write multiple records in one call. */
29
- writeBatch(records: Array<Partial<T> & Record<string, unknown>>): Promise<WriteResult[]>;
30
- /** Fetch a single record by its nucleotide ID. */
31
- get(id: string): Promise<NucleotideRecord<T>>;
32
- /** Query the latest version of all records in this collection. */
33
- latest(options?: Omit<QueryOptions, "latest">): Promise<NucleotideRecord<T>[]>;
34
- /** Query ALL versions (full history) in this collection. */
35
- history(options?: Omit<QueryOptions, "latest">): Promise<NucleotideRecord<T>[]>;
36
- /** Find records matching a filter (latest version only). */
37
- find(filter: Record<string, unknown>, options?: Omit<QueryOptions, "filter" | "latest">): Promise<NucleotideRecord<T>[]>;
38
- /** Find one record or return null. */
39
- findOne(filter: Record<string, unknown>): Promise<NucleotideRecord<T> | null>;
121
+ asOf(timestampHlc: number): CollectionSnapshot;
40
122
  }
123
+ export {};
41
124
  //# sourceMappingURL=collection.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"collection.d.ts","sourceRoot":"","sources":["../src/collection.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,iBAAiB,EACjB,WAAW,EACX,gBAAgB,EAChB,YAAY,EACb,MAAM,YAAY,CAAC;AAEpB,qBAAa,eAAe,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAEpD,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC;gBAFd,MAAM,EAAE,iBAAiB,EACzB,IAAI,EAAE,MAAM,EACZ,aAAa,CAAC,EAAE,MAAM,YAAA;IAGzC,yDAAyD;IACnD,GAAG,CAAC,OAAO,GAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC;IAIrF,6DAA6D;IACvD,MAAM,CAAC,OAAO,GAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC;IAIxF,2DAA2D;IACrD,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,GAAG,QAAQ,CAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC;IAIlI,kDAAkD;IAC5C,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;YAKrE,MAAM;CAerB;AAED,qBAAa,gBAAgB,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAErD,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,IAAI;gBADJ,MAAM,EAAE,iBAAiB,EACzB,IAAI,EAAE,MAAM;IAG/B;;;OAGG;IACH,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,CAAC,CAAC,CAAC;IAI3C,oFAAoF;IAC9E,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC;IAS7E,0CAA0C;IACpC,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAK9F,kDAAkD;IAC5C,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC;IAenD,kEAAkE;IAC5D,MAAM,CAAC,OAAO,GAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC;IAIxF,4DAA4D;IACtD,OAAO,CAAC,OAAO,GAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC;IAIzF,4DAA4D;IACtD,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,GAAG,QAAQ,CAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC;IAIlI,sCAAsC;IAChC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;CAGpF"}
1
+ {"version":3,"file":"collection.d.ts","sourceRoot":"","sources":["../src/collection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,iBAAiB,EACjB,WAAW,EACX,UAAU,EACV,SAAS,EACT,qBAAqB,EAErB,aAAa,EACd,MAAM,YAAY,CAAC;AAEpB,KAAK,SAAS,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;AAIjF;;;;;;;GAOG;AACH,qBAAa,kBAAkB;IAE3B,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,GAAG;gBAFH,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,MAAM,EACpB,GAAG,EAAE,SAAS;IAGjC,0EAA0E;IAC1E,MAAM,CAAC,IAAI,GAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,OAAO,CAAC,WAAW,CAAC;IAQ3D;;;OAGG;IACH,IAAI,CACF,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,IAAI,GAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAO,GAC5B,OAAO,CAAC,WAAW,CAAC;IAYjB,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;CAI3E;AAID;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,qBAAa,gBAAgB;aAET,IAAI,EAAE,MAAM;IAC5B,OAAO,CAAC,QAAQ,CAAC,GAAG;gBADJ,IAAI,EAAE,MAAM,EACX,GAAG,EAAE,SAAS;IAKjC;;;OAGG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC;IAI5D,wDAAwD;IACxD,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC;IAMhE;;;OAGG;IACH,GAAG,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAI7C;;;;;OAKG;IACH,MAAM,CAAC,IAAI,GAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAO,GAAG,OAAO,CAAC,WAAW,CAAC;IAiB7F;;;OAGG;IACH,OAAO,CAAC,IAAI,GAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAQvF;;;;;;OAMG;IACH,IAAI,CACF,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,IAAI,GAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAO,GAC5B,OAAO,CAAC,WAAW,CAAC;IAYvB,2DAA2D;IACrD,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAK1E,0DAA0D;IAC1D,KAAK,CAAC,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;IAIzC,gDAAgD;IAChD,IAAI,IAAI,OAAO,CAAC,iBAAiB,CAAC;IAIlC,iFAAiF;IACjF,MAAM,IAAI,OAAO,CAAC,mBAAmB,CAAC;IAMtC;;;;;;;;;OASG;IACH,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,kBAAkB;CAG/C"}
@@ -1,87 +1,190 @@
1
- import { request } from "./http.js";
2
- import { SapixNotFoundError } from "./errors.js";
3
- export class CollectionQuery {
4
- constructor(config, name, asOfTimestamp) {
5
- this.config = config;
1
+ // ── CollectionSnapshot ────────────────────────────────────────────────────────
2
+ /**
3
+ * A read-only view of a collection scoped to a specific point in time.
4
+ * Returned by `CollectionClient.asOf(timestampHlc)`.
5
+ *
6
+ * @example
7
+ * const snapshot = db.collection("orders").asOf(record.timestamp_hlc);
8
+ * const results = await snapshot.latest({ limit: 10 });
9
+ */
10
+ export class CollectionSnapshot {
11
+ name;
12
+ timestampHlc;
13
+ req;
14
+ constructor(name, timestampHlc, req) {
6
15
  this.name = name;
7
- this.asOfTimestamp = asOfTimestamp;
16
+ this.timestampHlc = timestampHlc;
17
+ this.req = req;
8
18
  }
9
- /** Fetch all versions matching filter (full history). */
10
- async all(options = {}) {
11
- return this._query({ ...options, latest: false });
19
+ /** Records written at or before this snapshot timestamp, newest-first. */
20
+ latest(opts = {}) {
21
+ return this.req("POST", `/v1/agents/${this.name}/query`, {
22
+ type: "as_of",
23
+ timestamp_hlc: this.timestampHlc,
24
+ limit: opts.limit ?? 20,
25
+ });
12
26
  }
13
- /** Fetch only the latest version of each matching record. */
14
- async latest(options = {}) {
15
- return this._query({ ...options, latest: true });
16
- }
17
- /** Find records matching a filter, latest version only. */
18
- async find(filter, options = {}) {
19
- return this._query({ filter, latest: true, ...options });
27
+ /**
28
+ * Equality-filter scan bounded by the snapshot timestamp.
29
+ * `filter` is a `{field: value}` object — first key is used.
30
+ */
31
+ find(filter, opts = {}) {
32
+ const [field, value] = Object.entries(filter)[0] ?? [];
33
+ const whereFilter = field
34
+ ? { field, op: "eq", value }
35
+ : undefined;
36
+ return this.req("POST", `/v1/agents/${this.name}/query`, {
37
+ type: "scan",
38
+ limit: opts.limit ?? 20,
39
+ ...(whereFilter ? { filter: whereFilter } : {}),
40
+ });
20
41
  }
21
- /** Find one record matching a filter, or null. */
22
42
  async findOne(filter) {
23
- const results = await this.find(filter, { limit: 1 });
24
- return results[0] ?? null;
25
- }
26
- async _query(options) {
27
- const body = {
28
- collection: this.name,
29
- ...options,
30
- };
31
- if (this.asOfTimestamp)
32
- body.as_of = this.asOfTimestamp;
33
- const res = await request(this.config, "POST", `/v1/${this.config.agent}/strand/query`, body);
34
- return res.results;
43
+ const result = await this.find(filter, { limit: 1 });
44
+ return result.records[0] ?? null;
35
45
  }
36
46
  }
47
+ // ── CollectionClient ──────────────────────────────────────────────────────────
48
+ /**
49
+ * Client for a named SapixDB agent (collection).
50
+ * All operations route to `/v1/agents/{name}/...`.
51
+ *
52
+ * Obtain via `SapixClient.collection(name)` or `SapixClient.agent(name)`.
53
+ *
54
+ * @example
55
+ * const orders = db.collection("orders");
56
+ *
57
+ * // Write
58
+ * const record = await orders.write({ total: 99.99, status: "pending" });
59
+ *
60
+ * // Read
61
+ * const latest = await orders.latest({ limit: 20 });
62
+ * const pending = await orders.find({ status: "pending" });
63
+ * const one = await orders.findOne({ status: "pending" });
64
+ * const byHash = await orders.get(record.content_hash);
65
+ *
66
+ * // History (chronological)
67
+ * const history = await orders.history({ limit: 100, offset: 0 });
68
+ *
69
+ * // Time travel
70
+ * const snapshot = await orders.asOf(record.timestamp_hlc).latest();
71
+ *
72
+ * // Direct SaQL
73
+ * const result = await orders.query({ type: "latest", limit: 5 });
74
+ *
75
+ * // Realtime — handled on SapixClient
76
+ * client.subscribeAgent("orders", (event) => console.log(event));
77
+ */
37
78
  export class CollectionClient {
38
- constructor(config, name) {
39
- this.config = config;
79
+ name;
80
+ req;
81
+ constructor(name, req) {
40
82
  this.name = name;
83
+ this.req = req;
41
84
  }
85
+ // ── Writes ──────────────────────────────────────────────────────────────────
42
86
  /**
43
- * Return a query scoped to a specific point in time.
44
- * @param timestamp ISO 8601 string, e.g. "2026-05-12T10:00:00Z"
87
+ * Append a JSON record to the agent's strand.
88
+ * `data` can be any JSON-serialisable object.
45
89
  */
46
- asOf(timestamp) {
47
- return new CollectionQuery(this.config, this.name, timestamp);
48
- }
49
- /** Write a new record. Every write is a new nucleotide — nothing is overwritten. */
50
- async write(data) {
51
- return request(this.config, "POST", `/v1/${this.config.agent}/strand/write`, { collection: this.name, data });
52
- }
53
- /** Write multiple records in one call. */
54
- async writeBatch(records) {
55
- const results = await Promise.all(records.map((data) => this.write(data)));
56
- return results;
57
- }
58
- /** Fetch a single record by its nucleotide ID. */
59
- async get(id) {
60
- try {
61
- return await request(this.config, "GET", `/v1/${this.config.agent}/strand/${id}`);
62
- }
63
- catch (err) {
64
- if (err instanceof Error && "status" in err && err.status === 404) {
65
- throw new SapixNotFoundError(id);
90
+ write(data) {
91
+ return this.req("POST", `/v1/agents/${this.name}/records/json`, { data });
92
+ }
93
+ /** Alias for `write` matches Python/Go SDK naming. */
94
+ writeJson(data) {
95
+ return this.write(data);
96
+ }
97
+ // ── Reads ───────────────────────────────────────────────────────────────────
98
+ /**
99
+ * Fetch a single record by its BLAKE3 content hash.
100
+ * Use `record.content_hash` from a previous write or query.
101
+ */
102
+ get(contentHash) {
103
+ return this.req("GET", `/v1/agents/${this.name}/records/${contentHash}`);
104
+ }
105
+ /**
106
+ * Return the most recent records, newest-first.
107
+ *
108
+ * Pass `filter: { field: value }` to run an equality scan (uses a field
109
+ * index when one is available for that field, otherwise a full strand scan).
110
+ */
111
+ latest(opts = {}) {
112
+ if (opts.filter) {
113
+ const [field, value] = Object.entries(opts.filter)[0] ?? [];
114
+ if (field !== undefined) {
115
+ return this.req("POST", `/v1/agents/${this.name}/query`, {
116
+ type: "scan",
117
+ limit: opts.limit ?? 20,
118
+ filter: { field, op: "eq", value },
119
+ });
66
120
  }
67
- throw err;
68
121
  }
122
+ return this.req("POST", `/v1/agents/${this.name}/query`, {
123
+ type: "latest",
124
+ limit: opts.limit ?? 20,
125
+ });
69
126
  }
70
- /** Query the latest version of all records in this collection. */
71
- async latest(options = {}) {
72
- return new CollectionQuery(this.config, this.name).latest(options);
73
- }
74
- /** Query ALL versions (full history) in this collection. */
75
- async history(options = {}) {
76
- return new CollectionQuery(this.config, this.name).all(options);
127
+ /**
128
+ * Return records in chronological order (oldest-first) with pagination.
129
+ * Uses `GET /v1/agents/{name}/strand/records`.
130
+ */
131
+ history(opts = {}) {
132
+ const params = new URLSearchParams();
133
+ if (opts.limit !== undefined)
134
+ params.set("limit", String(opts.limit));
135
+ if (opts.offset !== undefined)
136
+ params.set("offset", String(opts.offset));
137
+ const qs = params.size > 0 ? `?${params}` : "";
138
+ return this.req("GET", `/v1/agents/${this.name}/strand/records${qs}`);
77
139
  }
78
- /** Find records matching a filter (latest version only). */
79
- async find(filter, options = {}) {
80
- return new CollectionQuery(this.config, this.name).find(filter, options);
140
+ /**
141
+ * Equality-filter scan across the full strand.
142
+ * `filter` is a `{field: value}` object — first key is used.
143
+ *
144
+ * Uses a field index when one exists for that field; otherwise falls back
145
+ * to a full strand scan on the server.
146
+ */
147
+ find(filter, opts = {}) {
148
+ const [field, value] = Object.entries(filter)[0] ?? [];
149
+ const whereFilter = field
150
+ ? { field, op: "eq", value }
151
+ : undefined;
152
+ return this.req("POST", `/v1/agents/${this.name}/query`, {
153
+ type: "scan",
154
+ limit: opts.limit ?? 20,
155
+ ...(whereFilter ? { filter: whereFilter } : {}),
156
+ });
81
157
  }
82
- /** Find one record or return null. */
158
+ /** Return the first matching record, or `null` if none. */
83
159
  async findOne(filter) {
84
- return new CollectionQuery(this.config, this.name).findOne(filter);
160
+ const result = await this.find(filter, { limit: 1 });
161
+ return result.records[0] ?? null;
162
+ }
163
+ /** Execute any SaQL query directly against this agent. */
164
+ query(q) {
165
+ return this.req("POST", `/v1/agents/${this.name}/query`, q);
166
+ }
167
+ /** Current chain head hash and record count. */
168
+ head() {
169
+ return this.req("GET", `/v1/agents/${this.name}/strand/head`);
170
+ }
171
+ /** Agent status: record count, chain head, zone, schema version, caged state. */
172
+ status() {
173
+ return this.req("GET", `/v1/agents/${this.name}/status`);
174
+ }
175
+ // ── Time travel ─────────────────────────────────────────────────────────────
176
+ /**
177
+ * Scope reads to a point in time identified by an HLC timestamp.
178
+ * Returns a `CollectionSnapshot` — call `.latest()` or `.find()` on it.
179
+ *
180
+ * @param timestampHlc — `NucleotideRecord.timestamp_hlc` from any prior record
181
+ *
182
+ * @example
183
+ * const snapshot = orders.asOf(record.timestamp_hlc);
184
+ * const state = await snapshot.latest({ limit: 50 });
185
+ */
186
+ asOf(timestampHlc) {
187
+ return new CollectionSnapshot(this.name, timestampHlc, this.req);
85
188
  }
86
189
  }
87
190
  //# sourceMappingURL=collection.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"collection.js","sourceRoot":"","sources":["../src/collection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAQjD,MAAM,OAAO,eAAe;IAC1B,YACmB,MAAyB,EACzB,IAAY,EACZ,aAAsB;QAFtB,WAAM,GAAN,MAAM,CAAmB;QACzB,SAAI,GAAJ,IAAI,CAAQ;QACZ,kBAAa,GAAb,aAAa,CAAS;IACtC,CAAC;IAEJ,yDAAyD;IACzD,KAAK,CAAC,GAAG,CAAC,UAAwC,EAAE;QAClD,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IACpD,CAAC;IAED,6DAA6D;IAC7D,KAAK,CAAC,MAAM,CAAC,UAAwC,EAAE;QACrD,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IACnD,CAAC;IAED,2DAA2D;IAC3D,KAAK,CAAC,IAAI,CAAC,MAA+B,EAAE,UAAmD,EAAE;QAC/F,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED,kDAAkD;IAClD,KAAK,CAAC,OAAO,CAAC,MAA+B;QAC3C,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;QACtD,OAAO,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;IAC5B,CAAC;IAEO,KAAK,CAAC,MAAM,CAAC,OAA0C;QAC7D,MAAM,IAAI,GAA4B;YACpC,UAAU,EAAE,IAAI,CAAC,IAAI;YACrB,GAAG,OAAO;SACX,CAAC;QACF,IAAI,IAAI,CAAC,aAAa;YAAE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC;QAExD,MAAM,GAAG,GAAG,MAAM,OAAO,CACvB,IAAI,CAAC,MAAM,EACX,MAAM,EACN,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,eAAe,EACvC,IAAI,CACL,CAAC;QACF,OAAO,GAAG,CAAC,OAAO,CAAC;IACrB,CAAC;CACF;AAED,MAAM,OAAO,gBAAgB;IAC3B,YACmB,MAAyB,EACzB,IAAY;QADZ,WAAM,GAAN,MAAM,CAAmB;QACzB,SAAI,GAAJ,IAAI,CAAQ;IAC5B,CAAC;IAEJ;;;OAGG;IACH,IAAI,CAAC,SAAiB;QACpB,OAAO,IAAI,eAAe,CAAI,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IACnE,CAAC;IAED,oFAAoF;IACpF,KAAK,CAAC,KAAK,CAAC,IAA0C;QACpD,OAAO,OAAO,CACZ,IAAI,CAAC,MAAM,EACX,MAAM,EACN,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,eAAe,EACvC,EAAE,UAAU,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,CAChC,CAAC;IACJ,CAAC;IAED,0CAA0C;IAC1C,KAAK,CAAC,UAAU,CAAC,OAAoD;QACnE,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC3E,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,kDAAkD;IAClD,KAAK,CAAC,GAAG,CAAC,EAAU;QAClB,IAAI,CAAC;YACH,OAAO,MAAM,OAAO,CAClB,IAAI,CAAC,MAAM,EACX,KAAK,EACL,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,WAAW,EAAE,EAAE,CACxC,CAAC;QACJ,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,IAAI,GAAG,YAAY,KAAK,IAAI,QAAQ,IAAI,GAAG,IAAK,GAA2B,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBAC3F,MAAM,IAAI,kBAAkB,CAAC,EAAE,CAAC,CAAC;YACnC,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;IAED,kEAAkE;IAClE,KAAK,CAAC,MAAM,CAAC,UAAwC,EAAE;QACrD,OAAO,IAAI,eAAe,CAAI,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACxE,CAAC;IAED,4DAA4D;IAC5D,KAAK,CAAC,OAAO,CAAC,UAAwC,EAAE;QACtD,OAAO,IAAI,eAAe,CAAI,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACrE,CAAC;IAED,4DAA4D;IAC5D,KAAK,CAAC,IAAI,CAAC,MAA+B,EAAE,UAAmD,EAAE;QAC/F,OAAO,IAAI,eAAe,CAAI,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9E,CAAC;IAED,sCAAsC;IACtC,KAAK,CAAC,OAAO,CAAC,MAA+B;QAC3C,OAAO,IAAI,eAAe,CAAI,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACxE,CAAC;CACF"}
1
+ {"version":3,"file":"collection.js","sourceRoot":"","sources":["../src/collection.ts"],"names":[],"mappings":"AAaA,iFAAiF;AAEjF;;;;;;;GAOG;AACH,MAAM,OAAO,kBAAkB;IAEV;IACA;IACA;IAHnB,YACmB,IAAY,EACZ,YAAoB,EACpB,GAAc;QAFd,SAAI,GAAJ,IAAI,CAAQ;QACZ,iBAAY,GAAZ,YAAY,CAAQ;QACpB,QAAG,GAAH,GAAG,CAAW;IAC9B,CAAC;IAEJ,0EAA0E;IAC1E,MAAM,CAAC,OAA2B,EAAE;QAClC,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,cAAc,IAAI,CAAC,IAAI,QAAQ,EAAE;YACvD,IAAI,EAAE,OAAO;YACb,aAAa,EAAE,IAAI,CAAC,YAAY;YAChC,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,EAAE;SACxB,CAAC,CAAC;IACL,CAAC;IAED;;;OAGG;IACH,IAAI,CACF,MAA+B,EAC/B,OAA2B,EAAE;QAE7B,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACvD,MAAM,WAAW,GAA4B,KAAK;YAChD,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE;YAC5B,CAAC,CAAC,SAAS,CAAC;QACd,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,cAAc,IAAI,CAAC,IAAI,QAAQ,EAAE;YACvD,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,EAAE;YACvB,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAChD,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,MAA+B;QAC3C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;QACrD,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;IACnC,CAAC;CACF;AAED,iFAAiF;AAEjF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,OAAO,gBAAgB;IAET;IACC;IAFnB,YACkB,IAAY,EACX,GAAc;QADf,SAAI,GAAJ,IAAI,CAAQ;QACX,QAAG,GAAH,GAAG,CAAW;IAC9B,CAAC;IAEJ,+EAA+E;IAE/E;;;OAGG;IACH,KAAK,CAAC,IAA6B;QACjC,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,cAAc,IAAI,CAAC,IAAI,eAAe,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5E,CAAC;IAED,wDAAwD;IACxD,SAAS,CAAC,IAA6B;QACrC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,+EAA+E;IAE/E;;;OAGG;IACH,GAAG,CAAC,WAAmB;QACrB,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,cAAc,IAAI,CAAC,IAAI,YAAY,WAAW,EAAE,CAAC,CAAC;IAC3E,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,OAA6D,EAAE;QACpE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAC5D,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,cAAc,IAAI,CAAC,IAAI,QAAQ,EAAE;oBACvD,IAAI,EAAE,MAAM;oBACZ,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,EAAE;oBACvB,MAAM,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAwB;iBACzD,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,cAAc,IAAI,CAAC,IAAI,QAAQ,EAAE;YACvD,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,EAAE;SACxB,CAAC,CAAC;IACL,CAAC;IAED;;;OAGG;IACH,OAAO,CAAC,OAA4C,EAAE;QACpD,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;QACrC,IAAI,IAAI,CAAC,KAAK,KAAM,SAAS;YAAE,MAAM,CAAC,GAAG,CAAC,OAAO,EAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QACxE,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS;YAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;QACzE,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/C,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,cAAc,IAAI,CAAC,IAAI,kBAAkB,EAAE,EAAE,CAAC,CAAC;IACxE,CAAC;IAED;;;;;;OAMG;IACH,IAAI,CACF,MAA+B,EAC/B,OAA2B,EAAE;QAE7B,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACvD,MAAM,WAAW,GAA4B,KAAK;YAChD,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE;YAC5B,CAAC,CAAC,SAAS,CAAC;QACd,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,cAAc,IAAI,CAAC,IAAI,QAAQ,EAAE;YACvD,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,EAAE;YACvB,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAChD,CAAC,CAAC;IACL,CAAC;IAED,2DAA2D;IAC3D,KAAK,CAAC,OAAO,CAAC,MAA+B;QAC3C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;QACrD,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;IACnC,CAAC;IAED,0DAA0D;IAC1D,KAAK,CAAC,CAAY;QAChB,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,cAAc,IAAI,CAAC,IAAI,QAAQ,EAAE,CAAC,CAAC,CAAC;IAC9D,CAAC;IAED,gDAAgD;IAChD,IAAI;QACF,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,cAAc,IAAI,CAAC,IAAI,cAAc,CAAC,CAAC;IAChE,CAAC;IAED,iFAAiF;IACjF,MAAM;QACJ,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,cAAc,IAAI,CAAC,IAAI,SAAS,CAAC,CAAC;IAC3D,CAAC;IAED,+EAA+E;IAE/E;;;;;;;;;OASG;IACH,IAAI,CAAC,YAAoB;QACvB,OAAO,IAAI,kBAAkB,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;IACnE,CAAC;CACF"}
package/dist/errors.d.ts CHANGED
@@ -1,12 +1,30 @@
1
1
  export declare class SapixError extends Error {
2
2
  readonly status?: number | undefined;
3
- readonly code?: string | undefined;
4
- constructor(message: string, status?: number | undefined, code?: string | undefined);
3
+ readonly body?: string | undefined;
4
+ constructor(message: string, status?: number | undefined, body?: string | undefined);
5
+ static fromResponse(resp: Response): Promise<SapixError>;
5
6
  }
6
- export declare class SapixNetworkError extends SapixError {
7
- constructor(cause: unknown);
8
- }
9
- export declare class SapixNotFoundError extends SapixError {
10
- constructor(id: string);
7
+ /**
8
+ * Thrown when an API key exceeds its configured requests-per-second limit (HTTP 429).
9
+ *
10
+ * @example
11
+ * import { SapixRateLimitError } from "@sapixdb/client";
12
+ *
13
+ * try {
14
+ * await orders.write(data);
15
+ * } catch (err) {
16
+ * if (err instanceof SapixRateLimitError) {
17
+ * const delay = err.rpsLimit ? 1000 / err.rpsLimit : 1000;
18
+ * await new Promise(r => setTimeout(r, delay));
19
+ * await orders.write(data); // retry once
20
+ * } else throw err;
21
+ * }
22
+ */
23
+ export declare class SapixRateLimitError extends SapixError {
24
+ /** The key's configured limit in requests/second, parsed from the server message. */
25
+ readonly rpsLimit?: number | undefined;
26
+ constructor(message: string,
27
+ /** The key's configured limit in requests/second, parsed from the server message. */
28
+ rpsLimit?: number | undefined);
11
29
  }
12
30
  //# sourceMappingURL=errors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,UAAW,SAAQ,KAAK;aAGjB,MAAM,CAAC,EAAE,MAAM;aACf,IAAI,CAAC,EAAE,MAAM;gBAF7B,OAAO,EAAE,MAAM,EACC,MAAM,CAAC,EAAE,MAAM,YAAA,EACf,IAAI,CAAC,EAAE,MAAM,YAAA;CAKhC;AAED,qBAAa,iBAAkB,SAAQ,UAAU;gBACnC,KAAK,EAAE,OAAO;CAI3B;AAED,qBAAa,kBAAmB,SAAQ,UAAU;gBACpC,EAAE,EAAE,MAAM;CAIvB"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,UAAW,SAAQ,KAAK;aAGjB,MAAM,CAAC,EAAE,MAAM;aACf,IAAI,CAAC,EAAE,MAAM;gBAF7B,OAAO,EAAE,MAAM,EACC,MAAM,CAAC,EAAE,MAAM,YAAA,EACf,IAAI,CAAC,EAAE,MAAM,YAAA;WAMlB,YAAY,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;CA0B/D;AAED;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,mBAAoB,SAAQ,UAAU;IAG/C,qFAAqF;aACrE,QAAQ,CAAC,EAAE,MAAM;gBAFjC,OAAO,EAAE,MAAM;IACf,qFAAqF;IACrE,QAAQ,CAAC,EAAE,MAAM,YAAA;CAKpC"}
package/dist/errors.js CHANGED
@@ -1,21 +1,60 @@
1
1
  export class SapixError extends Error {
2
- constructor(message, status, code) {
2
+ status;
3
+ body;
4
+ constructor(message, status, body) {
3
5
  super(message);
4
6
  this.status = status;
5
- this.code = code;
7
+ this.body = body;
6
8
  this.name = "SapixError";
7
9
  }
8
- }
9
- export class SapixNetworkError extends SapixError {
10
- constructor(cause) {
11
- super(`Network error: ${cause instanceof Error ? cause.message : String(cause)}`);
12
- this.name = "SapixNetworkError";
10
+ static async fromResponse(resp) {
11
+ let body;
12
+ try {
13
+ body = await resp.text();
14
+ }
15
+ catch {
16
+ body = "<unreadable>";
17
+ }
18
+ if (resp.status === 429) {
19
+ let message = "rate limit exceeded";
20
+ let rpsLimit;
21
+ try {
22
+ const data = JSON.parse(body);
23
+ message = data.message ?? data.error ?? message;
24
+ const m = message.match(/rate limit of (\d+) req\/s/);
25
+ if (m)
26
+ rpsLimit = Number(m[1]);
27
+ }
28
+ catch { /* body was not JSON */ }
29
+ return new SapixRateLimitError(message, rpsLimit);
30
+ }
31
+ return new SapixError(`sapix-agent returned ${resp.status} ${resp.statusText}: ${body}`, resp.status, body);
13
32
  }
14
33
  }
15
- export class SapixNotFoundError extends SapixError {
16
- constructor(id) {
17
- super(`Record not found: ${id}`, 404, "NOT_FOUND");
18
- this.name = "SapixNotFoundError";
34
+ /**
35
+ * Thrown when an API key exceeds its configured requests-per-second limit (HTTP 429).
36
+ *
37
+ * @example
38
+ * import { SapixRateLimitError } from "@sapixdb/client";
39
+ *
40
+ * try {
41
+ * await orders.write(data);
42
+ * } catch (err) {
43
+ * if (err instanceof SapixRateLimitError) {
44
+ * const delay = err.rpsLimit ? 1000 / err.rpsLimit : 1000;
45
+ * await new Promise(r => setTimeout(r, delay));
46
+ * await orders.write(data); // retry once
47
+ * } else throw err;
48
+ * }
49
+ */
50
+ export class SapixRateLimitError extends SapixError {
51
+ rpsLimit;
52
+ constructor(message,
53
+ /** The key's configured limit in requests/second, parsed from the server message. */
54
+ rpsLimit) {
55
+ super(message, 429);
56
+ this.rpsLimit = rpsLimit;
57
+ this.name = "SapixRateLimitError";
19
58
  }
20
59
  }
21
60
  //# sourceMappingURL=errors.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,UAAW,SAAQ,KAAK;IACnC,YACE,OAAe,EACC,MAAe,EACf,IAAa;QAE7B,KAAK,CAAC,OAAO,CAAC,CAAC;QAHC,WAAM,GAAN,MAAM,CAAS;QACf,SAAI,GAAJ,IAAI,CAAS;QAG7B,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;IAC3B,CAAC;CACF;AAED,MAAM,OAAO,iBAAkB,SAAQ,UAAU;IAC/C,YAAY,KAAc;QACxB,KAAK,CAAC,kBAAkB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAClF,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;IAClC,CAAC;CACF;AAED,MAAM,OAAO,kBAAmB,SAAQ,UAAU;IAChD,YAAY,EAAU;QACpB,KAAK,CAAC,qBAAqB,EAAE,EAAE,EAAE,GAAG,EAAE,WAAW,CAAC,CAAC;QACnD,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,UAAW,SAAQ,KAAK;IAGjB;IACA;IAHlB,YACE,OAAe,EACC,MAAe,EACf,IAAa;QAE7B,KAAK,CAAC,OAAO,CAAC,CAAC;QAHC,WAAM,GAAN,MAAM,CAAS;QACf,SAAI,GAAJ,IAAI,CAAS;QAG7B,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;IAC3B,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,IAAc;QACtC,IAAI,IAAY,CAAC;QACjB,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QAC3B,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,GAAG,cAAc,CAAC;QACxB,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACxB,IAAI,OAAO,GAAG,qBAAqB,CAAC;YACpC,IAAI,QAA4B,CAAC;YACjC,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAyC,CAAC;gBACtE,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,KAAK,IAAI,OAAO,CAAC;gBAChD,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC;gBACtD,IAAI,CAAC;oBAAE,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACjC,CAAC;YAAC,MAAM,CAAC,CAAC,uBAAuB,CAAC,CAAC;YACnC,OAAO,IAAI,mBAAmB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACpD,CAAC;QAED,OAAO,IAAI,UAAU,CACnB,wBAAwB,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,UAAU,KAAK,IAAI,EAAE,EACjE,IAAI,CAAC,MAAM,EACX,IAAI,CACL,CAAC;IACJ,CAAC;CACF;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,OAAO,mBAAoB,SAAQ,UAAU;IAI/B;IAHlB,YACE,OAAe;IACf,qFAAqF;IACrE,QAAiB;QAEjC,KAAK,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAFJ,aAAQ,GAAR,QAAQ,CAAS;QAGjC,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF"}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  export { SapixClient } from "./client.js";
2
- export { CollectionClient, CollectionQuery } from "./collection.js";
3
- export { GraphClient } from "./graph.js";
4
- export { SapixError, SapixNetworkError, SapixNotFoundError } from "./errors.js";
5
- export type { SapixClientConfig, WriteResult, NucleotideRecord, QueryOptions, GraphEdge, GraphEdgeInput, TraverseOptions, TraverseResult, HealthResponse, IngestOptions, } from "./types.js";
2
+ export { AdminClient } from "./admin.js";
3
+ export { CollectionClient, CollectionSnapshot } from "./collection.js";
4
+ export { SapixError, SapixRateLimitError } from "./errors.js";
5
+ export { openAgentStream, openGlobalStream } from "./stream.js";
6
+ export type { AddEdgeRequest, AddRecordRefRequest, AgentStatusResponse, ApiKeyPatch, ApiKeyUsage, ApiKeyView, ChainHeadResponse, CreateApiKeyRequest, CreateApiKeyResponse, EdgeView, GenesisRequest, GenesisResponse, HealthResponse, ListApiKeysResponse, QueryResult, RecordRefView, RecordView, SapixClientOptions, SaqlQuery, StrandRecordsResponse, WhereFilter, WriteResponse, } from "./types.js";
7
+ export type { StreamEvent, SubscribeOptions } from "./stream.js";
6
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACpE,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAChF,YAAY,EACV,iBAAiB,EACjB,WAAW,EACX,gBAAgB,EAChB,YAAY,EACZ,SAAS,EACT,cAAc,EACd,eAAe,EACf,cAAc,EACd,cAAc,EACd,aAAa,GACd,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAChE,YAAY,EACV,cAAc,EACd,mBAAmB,EACnB,mBAAmB,EACnB,WAAW,EACX,WAAW,EACX,UAAU,EACV,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,EACpB,QAAQ,EACR,cAAc,EACd,eAAe,EACf,cAAc,EACd,mBAAmB,EACnB,WAAW,EACX,aAAa,EACb,UAAU,EACV,kBAAkB,EAClB,SAAS,EACT,qBAAqB,EACrB,WAAW,EACX,aAAa,GACd,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC"}
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  export { SapixClient } from "./client.js";
2
- export { CollectionClient, CollectionQuery } from "./collection.js";
3
- export { GraphClient } from "./graph.js";
4
- export { SapixError, SapixNetworkError, SapixNotFoundError } from "./errors.js";
2
+ export { AdminClient } from "./admin.js";
3
+ export { CollectionClient, CollectionSnapshot } from "./collection.js";
4
+ export { SapixError, SapixRateLimitError } from "./errors.js";
5
+ export { openAgentStream, openGlobalStream } from "./stream.js";
5
6
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACpE,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC"}