sapixdb 0.1.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 ADDED
@@ -0,0 +1,295 @@
1
+ # SapixDB JavaScript / TypeScript SDK
2
+
3
+ Official SDK for [SapixDB](https://sapixdb.com) — the agent-native living database.
4
+
5
+ Zero dependencies. Works in Node.js 18+, Bun, Deno, and modern browsers.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install sapixdb
11
+ # or
12
+ bun add sapixdb
13
+ ```
14
+
15
+ ## Quick Start
16
+
17
+ ```typescript
18
+ import { SapixClient } from "sapixdb";
19
+
20
+ const db = new SapixClient({
21
+ url: "http://localhost:7475",
22
+ agent: "my-app",
23
+ });
24
+
25
+ // Write a record
26
+ const record = await db.collection("products").write({
27
+ name: "T-Shirt",
28
+ price: 29.99,
29
+ stock: 100,
30
+ });
31
+ console.log(record.id); // "nuc_abc123"
32
+ console.log(record.hash); // "sha3:e7f2a1..."
33
+
34
+ // Read latest records
35
+ const products = await db.collection("products").latest();
36
+
37
+ // Filter
38
+ const shirts = await db.collection("products").find({ category: "apparel" });
39
+
40
+ // Time travel — what did the DB look like yesterday?
41
+ const yesterday = await db
42
+ .collection("orders")
43
+ .asOf("2026-05-11T00:00:00Z")
44
+ .latest();
45
+ ```
46
+
47
+ ## API Reference
48
+
49
+ ### `new SapixClient(config)`
50
+
51
+ | Option | Type | Default | Description |
52
+ |--------|------|---------|-------------|
53
+ | `url` | `string` | — | SapixDB agent URL |
54
+ | `agent` | `string` | — | Agent ID (matches `SAPIX_AGENT_ID`) |
55
+ | `headers` | `Record<string,string>` | `{}` | Extra HTTP headers |
56
+ | `timeout` | `number` | `10000` | Request timeout (ms) |
57
+
58
+ ---
59
+
60
+ ### `db.collection(name)`
61
+
62
+ Returns a `CollectionClient` for the given collection name.
63
+
64
+ #### `.write(data)` → `WriteResult`
65
+
66
+ Append a new record. Nothing is ever overwritten.
67
+
68
+ ```typescript
69
+ const result = await db.collection("orders").write({
70
+ customer_id: "cust_001",
71
+ total: 149.99,
72
+ status: "placed",
73
+ });
74
+ // result.id — nucleotide ID
75
+ // result.hash — cryptographic fingerprint
76
+ // result.timestamp — ISO 8601 timestamp
77
+ ```
78
+
79
+ #### `.writeBatch(records[])` → `WriteResult[]`
80
+
81
+ Write multiple records in parallel.
82
+
83
+ ```typescript
84
+ await db.collection("products").writeBatch([
85
+ { name: "T-Shirt", price: 29.99 },
86
+ { name: "Sneakers", price: 89.99 },
87
+ ]);
88
+ ```
89
+
90
+ #### `.get(id)` → `NucleotideRecord`
91
+
92
+ Fetch a single record by its nucleotide ID.
93
+
94
+ ```typescript
95
+ const record = await db.collection("orders").get("nuc_abc123");
96
+ console.log(record.data.status); // "placed"
97
+ ```
98
+
99
+ #### `.latest(options?)` → `NucleotideRecord[]`
100
+
101
+ Fetch the latest version of every record in the collection.
102
+
103
+ #### `.history(options?)` → `NucleotideRecord[]`
104
+
105
+ Fetch ALL versions — the full append-only history.
106
+
107
+ #### `.find(filter, options?)` → `NucleotideRecord[]`
108
+
109
+ Find records matching a filter (latest version only).
110
+
111
+ ```typescript
112
+ const pending = await db.collection("orders").find({ status: "pending" });
113
+ ```
114
+
115
+ #### `.findOne(filter)` → `NucleotideRecord | null`
116
+
117
+ Find the first matching record, or `null`.
118
+
119
+ #### `.asOf(timestamp)` → `CollectionQuery`
120
+
121
+ Scope all subsequent reads to a specific point in time.
122
+
123
+ ```typescript
124
+ // What did Alice's record look like 2 hours ago?
125
+ const snapshot = await db
126
+ .collection("users")
127
+ .asOf("2026-05-12T08:00:00Z")
128
+ .find({ name: "Alice" });
129
+ ```
130
+
131
+ ---
132
+
133
+ ### `db.graph`
134
+
135
+ #### `.relate(src, dst, type, weight?)` → `void`
136
+
137
+ Create a typed directed edge between two records.
138
+
139
+ ```typescript
140
+ await db.graph.relate(orderId, customerId, "placed_by");
141
+ await db.graph.relate(productId, categoryId, "belongs_to");
142
+ await db.graph.relate(managerId, reportId, "manages", 1.0);
143
+ ```
144
+
145
+ #### `.addEdge(edge)` → `void`
146
+
147
+ Full edge creation with all options.
148
+
149
+ ```typescript
150
+ await db.graph.addEdge({
151
+ src: "nuc_abc123",
152
+ dst: "nuc_def456",
153
+ edge_type: "manages",
154
+ weight: 1.0,
155
+ });
156
+ ```
157
+
158
+ #### `.traverse(fromId, options?)` → `TraverseResult`
159
+
160
+ Walk the graph from a starting node.
161
+
162
+ ```typescript
163
+ const { nodes, edges } = await db.graph.traverse("nuc_abc123", {
164
+ depth: 3,
165
+ direction: "outbound", // "outbound" | "inbound" | "both"
166
+ });
167
+ ```
168
+
169
+ #### `.neighbors(id, direction?)` → `NucleotideRecord[]`
170
+
171
+ Get direct neighbours of a node.
172
+
173
+ ---
174
+
175
+ ### `db.ingest(collection, data)` → `WriteResult`
176
+
177
+ Write via the ingest endpoint — designed for AI agents, webhooks, and automated pipelines.
178
+
179
+ ```typescript
180
+ await db.ingest("ai_decisions", {
181
+ model: "gpt-4o",
182
+ action: "approve_loan",
183
+ confidence: 0.94,
184
+ reasoning: "Credit score 780, DTI 28%",
185
+ });
186
+ ```
187
+
188
+ ---
189
+
190
+ ### `db.health()` / `db.ping()`
191
+
192
+ ```typescript
193
+ const { status, agent } = await db.health(); // throws on failure
194
+ const alive = await db.ping(); // returns true/false, never throws
195
+ ```
196
+
197
+ ---
198
+
199
+ ## TypeScript Generics
200
+
201
+ Pass your type as a generic to get full autocomplete and type checking:
202
+
203
+ ```typescript
204
+ interface Product {
205
+ name: string;
206
+ price: number;
207
+ stock: number;
208
+ category?: string;
209
+ }
210
+
211
+ const products = db.collection<Product>("products");
212
+
213
+ const result = await products.write({ name: "T-Shirt", price: 29.99, stock: 100 });
214
+ const items = await products.latest();
215
+ // items[0].data.price is typed as number ✓
216
+ ```
217
+
218
+ ---
219
+
220
+ ## Error Handling
221
+
222
+ ```typescript
223
+ import { SapixError, SapixNetworkError, SapixNotFoundError } from "sapixdb";
224
+
225
+ try {
226
+ const record = await db.collection("orders").get("nuc_missing");
227
+ } catch (err) {
228
+ if (err instanceof SapixNotFoundError) {
229
+ console.log("Record does not exist");
230
+ } else if (err instanceof SapixNetworkError) {
231
+ console.log("Cannot reach SapixDB — is it running?");
232
+ } else if (err instanceof SapixError) {
233
+ console.log(`SapixDB error ${err.status}: ${err.message}`);
234
+ }
235
+ }
236
+ ```
237
+
238
+ ---
239
+
240
+ ## Full Example: Online Store
241
+
242
+ ```typescript
243
+ import { SapixClient } from "sapixdb";
244
+
245
+ const db = new SapixClient({ url: "http://localhost:7475", agent: "store" });
246
+
247
+ // ── 1. Add products ───────────────────────────────────────────────
248
+ const shirt = await db.collection("products").write({
249
+ sku: "SHIRT-001", name: "Classic T-Shirt", price: 29.99, stock: 200,
250
+ });
251
+ const shoes = await db.collection("products").write({
252
+ sku: "SHOE-042", name: "Running Sneakers", price: 89.99, stock: 50,
253
+ });
254
+
255
+ // ── 2. Register a customer ────────────────────────────────────────
256
+ const customer = await db.collection("customers").write({
257
+ name: "Alice Johnson", email: "alice@example.com", tier: "standard",
258
+ });
259
+
260
+ // ── 3. Place an order ─────────────────────────────────────────────
261
+ const order = await db.collection("orders").write({
262
+ customer_id: customer.id,
263
+ items: [
264
+ { product_id: shirt.id, qty: 2, unit_price: 29.99 },
265
+ { product_id: shoes.id, qty: 1, unit_price: 89.99 },
266
+ ],
267
+ total: 149.97,
268
+ status: "placed",
269
+ });
270
+
271
+ // Link order → customer in the graph
272
+ await db.graph.relate(order.id, customer.id, "placed_by");
273
+
274
+ // ── 4. Ship the order (append, never overwrite) ───────────────────
275
+ await db.collection("orders").write({
276
+ ...order, // same logical entity
277
+ status: "shipped",
278
+ tracking: "UPS-1Z999AA10123456784",
279
+ shipped_at: new Date().toISOString(),
280
+ });
281
+
282
+ // ── 5. Audit: what was the order status 10 minutes ago? ───────────
283
+ const tenMinutesAgo = new Date(Date.now() - 10 * 60_000).toISOString();
284
+ const snapshot = await db
285
+ .collection("orders")
286
+ .asOf(tenMinutesAgo)
287
+ .find({ customer_id: customer.id });
288
+ // → returns the "placed" version, before it was shipped
289
+
290
+ // ── 6. Graph: find everything this customer is connected to ───────
291
+ const { nodes } = await db.graph.traverse(customer.id, {
292
+ depth: 2, direction: "inbound",
293
+ });
294
+ // → returns the order records linked to this customer
295
+ ```
@@ -0,0 +1,43 @@
1
+ import { CollectionClient } from "./collection.js";
2
+ import { GraphClient } from "./graph.js";
3
+ import type { SapixClientConfig, HealthResponse, WriteResult } from "./types.js";
4
+ export declare class SapixClient {
5
+ private readonly config;
6
+ /** Graph traversal and edge management. */
7
+ readonly graph: GraphClient;
8
+ constructor(config: SapixClientConfig);
9
+ /**
10
+ * Access a collection. All reads and writes go through this.
11
+ *
12
+ * @example
13
+ * const products = db.collection("products");
14
+ * await products.write({ name: "T-Shirt", price: 29.99 });
15
+ * const all = await products.latest();
16
+ *
17
+ * // With TypeScript generics for full type safety:
18
+ * const products = db.collection<Product>("products");
19
+ */
20
+ collection<T = Record<string, unknown>>(name: string): CollectionClient<T>;
21
+ /**
22
+ * Ingest a record via the agent ingest endpoint.
23
+ * Designed for AI agents, webhooks, and automated pipelines.
24
+ * Supports optional dual-write to Supabase if configured on the server.
25
+ *
26
+ * @example
27
+ * await db.ingest("ai_decisions", {
28
+ * model: "gpt-4o",
29
+ * action: "approve_loan",
30
+ * confidence: 0.94,
31
+ * reasoning: "Credit score 780, DTI 28%",
32
+ * });
33
+ */
34
+ ingest(collection: string, data: Record<string, unknown>): Promise<WriteResult>;
35
+ /** Check that the SapixDB agent is reachable and running. */
36
+ health(): Promise<HealthResponse>;
37
+ /**
38
+ * Ping the agent. Returns true if healthy, false if unreachable.
39
+ * Does not throw.
40
+ */
41
+ ping(): Promise<boolean>;
42
+ }
43
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,KAAK,EACV,iBAAiB,EACjB,cAAc,EACd,WAAW,EACZ,MAAM,YAAY,CAAC;AAEpB,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAoB;IAE3C,2CAA2C;IAC3C,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;gBAEhB,MAAM,EAAE,iBAAiB;IASrC;;;;;;;;;;OAUG;IACH,UAAU,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,gBAAgB,CAAC,CAAC,CAAC;IAI1E;;;;;;;;;;;;OAYG;IACG,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC;IASrF,6DAA6D;IACvD,MAAM,IAAI,OAAO,CAAC,cAAc,CAAC;IAIvC;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC;CAQ/B"}
package/dist/client.js ADDED
@@ -0,0 +1,61 @@
1
+ import { request } from "./http.js";
2
+ import { CollectionClient } from "./collection.js";
3
+ import { GraphClient } from "./graph.js";
4
+ export class SapixClient {
5
+ constructor(config) {
6
+ this.config = {
7
+ timeout: 10000,
8
+ ...config,
9
+ url: config.url.replace(/\/$/, ""),
10
+ };
11
+ this.graph = new GraphClient(this.config);
12
+ }
13
+ /**
14
+ * Access a collection. All reads and writes go through this.
15
+ *
16
+ * @example
17
+ * const products = db.collection("products");
18
+ * await products.write({ name: "T-Shirt", price: 29.99 });
19
+ * const all = await products.latest();
20
+ *
21
+ * // With TypeScript generics for full type safety:
22
+ * const products = db.collection<Product>("products");
23
+ */
24
+ collection(name) {
25
+ return new CollectionClient(this.config, name);
26
+ }
27
+ /**
28
+ * Ingest a record via the agent ingest endpoint.
29
+ * Designed for AI agents, webhooks, and automated pipelines.
30
+ * Supports optional dual-write to Supabase if configured on the server.
31
+ *
32
+ * @example
33
+ * await db.ingest("ai_decisions", {
34
+ * model: "gpt-4o",
35
+ * action: "approve_loan",
36
+ * confidence: 0.94,
37
+ * reasoning: "Credit score 780, DTI 28%",
38
+ * });
39
+ */
40
+ async ingest(collection, data) {
41
+ return request(this.config, "POST", `/v1/${this.config.agent}/ingest`, { collection, data });
42
+ }
43
+ /** Check that the SapixDB agent is reachable and running. */
44
+ async health() {
45
+ return request(this.config, "GET", "/v1/health");
46
+ }
47
+ /**
48
+ * Ping the agent. Returns true if healthy, false if unreachable.
49
+ * Does not throw.
50
+ */
51
+ async ping() {
52
+ try {
53
+ const res = await this.health();
54
+ return res.status === "ok";
55
+ }
56
+ catch {
57
+ return false;
58
+ }
59
+ }
60
+ }
61
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAOzC,MAAM,OAAO,WAAW;IAMtB,YAAY,MAAyB;QACnC,IAAI,CAAC,MAAM,GAAG;YACZ,OAAO,EAAE,KAAM;YACf,GAAG,MAAM;YACT,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;SACnC,CAAC;QACF,IAAI,CAAC,KAAK,GAAG,IAAI,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5C,CAAC;IAED;;;;;;;;;;OAUG;IACH,UAAU,CAA8B,IAAY;QAClD,OAAO,IAAI,gBAAgB,CAAI,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACpD,CAAC;IAED;;;;;;;;;;;;OAYG;IACH,KAAK,CAAC,MAAM,CAAC,UAAkB,EAAE,IAA6B;QAC5D,OAAO,OAAO,CACZ,IAAI,CAAC,MAAM,EACX,MAAM,EACN,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,SAAS,EACjC,EAAE,UAAU,EAAE,IAAI,EAAE,CACrB,CAAC;IACJ,CAAC;IAED,6DAA6D;IAC7D,KAAK,CAAC,MAAM;QACV,OAAO,OAAO,CAAiB,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC;IACnE,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,IAAI;QACR,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;YAChC,OAAO,GAAG,CAAC,MAAM,KAAK,IAAI,CAAC;QAC7B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,41 @@
1
+ import type { SapixClientConfig, WriteResult, NucleotideRecord, QueryOptions } from "./types.js";
2
+ export declare class CollectionQuery<T = Record<string, unknown>> {
3
+ private readonly config;
4
+ 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;
16
+ }
17
+ export declare class CollectionClient<T = Record<string, unknown>> {
18
+ private readonly config;
19
+ private readonly name;
20
+ constructor(config: SapixClientConfig, name: string);
21
+ /**
22
+ * Return a query scoped to a specific point in time.
23
+ * @param timestamp ISO 8601 string, e.g. "2026-05-12T10:00:00Z"
24
+ */
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>;
40
+ }
41
+ //# sourceMappingURL=collection.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,87 @@
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;
6
+ this.name = name;
7
+ this.asOfTimestamp = asOfTimestamp;
8
+ }
9
+ /** Fetch all versions matching filter (full history). */
10
+ async all(options = {}) {
11
+ return this._query({ ...options, latest: false });
12
+ }
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 });
20
+ }
21
+ /** Find one record matching a filter, or null. */
22
+ 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;
35
+ }
36
+ }
37
+ export class CollectionClient {
38
+ constructor(config, name) {
39
+ this.config = config;
40
+ this.name = name;
41
+ }
42
+ /**
43
+ * Return a query scoped to a specific point in time.
44
+ * @param timestamp ISO 8601 string, e.g. "2026-05-12T10:00:00Z"
45
+ */
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);
66
+ }
67
+ throw err;
68
+ }
69
+ }
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);
77
+ }
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);
81
+ }
82
+ /** Find one record or return null. */
83
+ async findOne(filter) {
84
+ return new CollectionQuery(this.config, this.name).findOne(filter);
85
+ }
86
+ }
87
+ //# sourceMappingURL=collection.js.map
@@ -0,0 +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"}
@@ -0,0 +1,12 @@
1
+ export declare class SapixError extends Error {
2
+ readonly status?: number | undefined;
3
+ readonly code?: string | undefined;
4
+ constructor(message: string, status?: number | undefined, code?: string | undefined);
5
+ }
6
+ export declare class SapixNetworkError extends SapixError {
7
+ constructor(cause: unknown);
8
+ }
9
+ export declare class SapixNotFoundError extends SapixError {
10
+ constructor(id: string);
11
+ }
12
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +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"}
package/dist/errors.js ADDED
@@ -0,0 +1,21 @@
1
+ export class SapixError extends Error {
2
+ constructor(message, status, code) {
3
+ super(message);
4
+ this.status = status;
5
+ this.code = code;
6
+ this.name = "SapixError";
7
+ }
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";
13
+ }
14
+ }
15
+ export class SapixNotFoundError extends SapixError {
16
+ constructor(id) {
17
+ super(`Record not found: ${id}`, 404, "NOT_FOUND");
18
+ this.name = "SapixNotFoundError";
19
+ }
20
+ }
21
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +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"}
@@ -0,0 +1,28 @@
1
+ import type { SapixClientConfig, GraphEdgeInput, GraphEdge, TraverseOptions, TraverseResult, NucleotideRecord } from "./types.js";
2
+ export declare class GraphClient {
3
+ private readonly config;
4
+ constructor(config: SapixClientConfig);
5
+ /** Create a directed edge between two records. */
6
+ addEdge(edge: GraphEdgeInput): Promise<void>;
7
+ /** Remove an edge between two records. */
8
+ removeEdge(src: string, dst: string, edge_type: string): Promise<void>;
9
+ /**
10
+ * Traverse the graph from a starting node.
11
+ * Returns all reachable nodes and the edges connecting them.
12
+ */
13
+ traverse(fromId: string, options?: TraverseOptions): Promise<TraverseResult>;
14
+ /** Get all direct neighbours of a node. */
15
+ neighbors(id: string, direction?: "outbound" | "inbound" | "both"): Promise<NucleotideRecord[]>;
16
+ /** Get all outbound edges from a node. */
17
+ edges(id: string): Promise<GraphEdge[]>;
18
+ /**
19
+ * Connect two records with a typed relationship.
20
+ * Convenience wrapper around addEdge.
21
+ *
22
+ * @example
23
+ * await db.graph.relate(orderId, customerId, "placed_by");
24
+ * await db.graph.relate(productId, categoryId, "belongs_to");
25
+ */
26
+ relate(src: string, dst: string, type: string, weight?: number): Promise<void>;
27
+ }
28
+ //# sourceMappingURL=graph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../src/graph.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,iBAAiB,EACjB,cAAc,EACd,SAAS,EACT,eAAe,EACf,cAAc,EACd,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAEpB,qBAAa,WAAW;IACV,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,iBAAiB;IAEtD,kDAAkD;IAC5C,OAAO,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IASlD,0CAA0C;IACpC,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAS5E;;;OAGG;IACG,QAAQ,CACZ,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,cAAc,CAAC;IAS1B,2CAA2C;IACrC,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,GAAE,UAAU,GAAG,SAAS,GAAG,MAAmB,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAKjH,0CAA0C;IACpC,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAK7C;;;;;;;OAOG;IACG,MAAM,CACV,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,MAAM,SAAM,GACX,OAAO,CAAC,IAAI,CAAC;CAGjB"}
package/dist/graph.js ADDED
@@ -0,0 +1,44 @@
1
+ import { request } from "./http.js";
2
+ export class GraphClient {
3
+ constructor(config) {
4
+ this.config = config;
5
+ }
6
+ /** Create a directed edge between two records. */
7
+ async addEdge(edge) {
8
+ await request(this.config, "POST", `/v1/${this.config.agent}/graph/edge`, { ...edge, weight: edge.weight ?? 1.0 });
9
+ }
10
+ /** Remove an edge between two records. */
11
+ async removeEdge(src, dst, edge_type) {
12
+ await request(this.config, "DELETE", `/v1/${this.config.agent}/graph/edge`, { src, dst, edge_type });
13
+ }
14
+ /**
15
+ * Traverse the graph from a starting node.
16
+ * Returns all reachable nodes and the edges connecting them.
17
+ */
18
+ async traverse(fromId, options = {}) {
19
+ const { depth = 1, direction = "outbound" } = options;
20
+ return request(this.config, "GET", `/v1/${this.config.agent}/graph/traverse/${fromId}?depth=${depth}&direction=${direction}`);
21
+ }
22
+ /** Get all direct neighbours of a node. */
23
+ async neighbors(id, direction = "outbound") {
24
+ const result = await this.traverse(id, { depth: 1, direction });
25
+ return result.nodes;
26
+ }
27
+ /** Get all outbound edges from a node. */
28
+ async edges(id) {
29
+ const result = await this.traverse(id, { depth: 1 });
30
+ return result.edges;
31
+ }
32
+ /**
33
+ * Connect two records with a typed relationship.
34
+ * Convenience wrapper around addEdge.
35
+ *
36
+ * @example
37
+ * await db.graph.relate(orderId, customerId, "placed_by");
38
+ * await db.graph.relate(productId, categoryId, "belongs_to");
39
+ */
40
+ async relate(src, dst, type, weight = 1.0) {
41
+ return this.addEdge({ src, dst, edge_type: type, weight });
42
+ }
43
+ }
44
+ //# sourceMappingURL=graph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph.js","sourceRoot":"","sources":["../src/graph.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC,MAAM,OAAO,WAAW;IACtB,YAA6B,MAAyB;QAAzB,WAAM,GAAN,MAAM,CAAmB;IAAG,CAAC;IAE1D,kDAAkD;IAClD,KAAK,CAAC,OAAO,CAAC,IAAoB;QAChC,MAAM,OAAO,CACX,IAAI,CAAC,MAAM,EACX,MAAM,EACN,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,aAAa,EACrC,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,GAAG,EAAE,CACxC,CAAC;IACJ,CAAC;IAED,0CAA0C;IAC1C,KAAK,CAAC,UAAU,CAAC,GAAW,EAAE,GAAW,EAAE,SAAiB;QAC1D,MAAM,OAAO,CACX,IAAI,CAAC,MAAM,EACX,QAAQ,EACR,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,aAAa,EACrC,EAAE,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,CACxB,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,QAAQ,CACZ,MAAc,EACd,UAA2B,EAAE;QAE7B,MAAM,EAAE,KAAK,GAAG,CAAC,EAAE,SAAS,GAAG,UAAU,EAAE,GAAG,OAAO,CAAC;QACtD,OAAO,OAAO,CACZ,IAAI,CAAC,MAAM,EACX,KAAK,EACL,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,mBAAmB,MAAM,UAAU,KAAK,cAAc,SAAS,EAAE,CAC1F,CAAC;IACJ,CAAC;IAED,2CAA2C;IAC3C,KAAK,CAAC,SAAS,CAAC,EAAU,EAAE,YAA6C,UAAU;QACjF,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC;QAChE,OAAO,MAAM,CAAC,KAAK,CAAC;IACtB,CAAC;IAED,0CAA0C;IAC1C,KAAK,CAAC,KAAK,CAAC,EAAU;QACpB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;QACrD,OAAO,MAAM,CAAC,KAAK,CAAC;IACtB,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,MAAM,CACV,GAAW,EACX,GAAW,EACX,IAAY,EACZ,MAAM,GAAG,GAAG;QAEZ,OAAO,IAAI,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IAC7D,CAAC;CACF"}
package/dist/http.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ import type { SapixClientConfig } from "./types.js";
2
+ export declare function request<T>(config: SapixClientConfig, method: string, path: string, body?: unknown): Promise<T>;
3
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpD,wBAAsB,OAAO,CAAC,CAAC,EAC7B,MAAM,EAAE,iBAAiB,EACzB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,OAAO,GACb,OAAO,CAAC,CAAC,CAAC,CAqCZ"}
package/dist/http.js ADDED
@@ -0,0 +1,42 @@
1
+ import { SapixError, SapixNetworkError } from "./errors.js";
2
+ export async function request(config, method, path, body) {
3
+ const url = `${config.url}${path}`;
4
+ const headers = {
5
+ "Content-Type": "application/json",
6
+ ...config.headers,
7
+ };
8
+ let res;
9
+ try {
10
+ const opts = { method, headers };
11
+ if (body !== undefined)
12
+ opts.body = JSON.stringify(body);
13
+ if (config.timeout) {
14
+ const ac = new AbortController();
15
+ const timer = setTimeout(() => ac.abort(), config.timeout);
16
+ opts.signal = ac.signal;
17
+ res = await fetch(url, opts);
18
+ clearTimeout(timer);
19
+ }
20
+ else {
21
+ res = await fetch(url, opts);
22
+ }
23
+ }
24
+ catch (err) {
25
+ throw new SapixNetworkError(err);
26
+ }
27
+ if (!res.ok) {
28
+ let message = `HTTP ${res.status}`;
29
+ let code;
30
+ try {
31
+ const body = await res.json();
32
+ if (body.error)
33
+ message = body.error;
34
+ if (body.code)
35
+ code = body.code;
36
+ }
37
+ catch { /* ignore parse error */ }
38
+ throw new SapixError(message, res.status, code);
39
+ }
40
+ return res.json();
41
+ }
42
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAG5D,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,MAAyB,EACzB,MAAc,EACd,IAAY,EACZ,IAAc;IAEd,MAAM,GAAG,GAAG,GAAG,MAAM,CAAC,GAAG,GAAG,IAAI,EAAE,CAAC;IACnC,MAAM,OAAO,GAA2B;QACtC,cAAc,EAAE,kBAAkB;QAClC,GAAG,MAAM,CAAC,OAAO;KAClB,CAAC;IAEF,IAAI,GAAa,CAAC;IAClB,IAAI,CAAC;QACH,MAAM,IAAI,GAAgB,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;QAC9C,IAAI,IAAI,KAAK,SAAS;YAAE,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAEzD,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,MAAM,EAAE,GAAG,IAAI,eAAe,EAAE,CAAC;YACjC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;YAC3D,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,MAAM,CAAC;YACxB,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YAC7B,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;aAAM,CAAC;YACN,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,iBAAiB,CAAC,GAAG,CAAC,CAAC;IACnC,CAAC;IAED,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,IAAI,OAAO,GAAG,QAAQ,GAAG,CAAC,MAAM,EAAE,CAAC;QACnC,IAAI,IAAwB,CAAC;QAC7B,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAuC,CAAC;YACnE,IAAI,IAAI,CAAC,KAAK;gBAAE,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC;YACrC,IAAI,IAAI,CAAC,IAAI;gBAAE,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QAClC,CAAC;QAAC,MAAM,CAAC,CAAC,wBAAwB,CAAC,CAAC;QACpC,MAAM,IAAI,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAClD,CAAC;IAED,OAAO,GAAG,CAAC,IAAI,EAAgB,CAAC;AAClC,CAAC"}
@@ -0,0 +1,6 @@
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";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +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"}
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
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
+ //# sourceMappingURL=index.js.map
@@ -0,0 +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"}
@@ -0,0 +1,65 @@
1
+ export interface SapixClientConfig {
2
+ /** Base URL of the SapixDB agent, e.g. "http://localhost:7475" */
3
+ url: string;
4
+ /** Agent ID set via SAPIX_AGENT_ID env var */
5
+ agent: string;
6
+ /** Optional extra headers sent with every request */
7
+ headers?: Record<string, string>;
8
+ /** Request timeout in milliseconds (default: 10000) */
9
+ timeout?: number;
10
+ }
11
+ export interface WriteResult {
12
+ id: string;
13
+ hash: string;
14
+ prev_hash: string | null;
15
+ timestamp: string;
16
+ collection: string;
17
+ }
18
+ export interface NucleotideRecord<T = Record<string, unknown>> {
19
+ id: string;
20
+ data: T;
21
+ timestamp: string;
22
+ hash: string;
23
+ prev_hash: string | null;
24
+ collection: string;
25
+ }
26
+ export interface QueryOptions {
27
+ filter?: Record<string, unknown>;
28
+ /** Return only the latest version of each logical entity (default: true) */
29
+ latest?: boolean;
30
+ limit?: number;
31
+ offset?: number;
32
+ }
33
+ export interface TimeTravelQueryOptions extends QueryOptions {
34
+ as_of: string;
35
+ }
36
+ export interface GraphEdgeInput {
37
+ src: string;
38
+ dst: string;
39
+ edge_type: string;
40
+ weight?: number;
41
+ }
42
+ export interface GraphEdge extends GraphEdgeInput {
43
+ timestamp_hlc: number;
44
+ }
45
+ export interface TraverseOptions {
46
+ depth?: number;
47
+ direction?: "outbound" | "inbound" | "both";
48
+ }
49
+ export interface TraverseResult {
50
+ nodes: NucleotideRecord[];
51
+ edges: GraphEdge[];
52
+ }
53
+ export interface HealthResponse {
54
+ status: string;
55
+ agent: string;
56
+ }
57
+ export interface IngestOptions {
58
+ collection: string;
59
+ data: Record<string, unknown>;
60
+ }
61
+ export interface SapixErrorResponse {
62
+ error: string;
63
+ code?: string;
64
+ }
65
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IAChC,kEAAkE;IAClE,GAAG,EAAE,MAAM,CAAC;IACZ,8CAA8C;IAC9C,KAAK,EAAE,MAAM,CAAC;IACd,qDAAqD;IACrD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC3D,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,CAAC,CAAC;IACR,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,4EAA4E;IAC5E,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,sBAAuB,SAAQ,YAAY;IAC1D,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,SAAU,SAAQ,cAAc;IAC/C,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,UAAU,GAAG,SAAS,GAAG,MAAM,CAAC;CAC7C;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,KAAK,EAAE,SAAS,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "sapixdb",
3
+ "version": "0.1.0",
4
+ "description": "Official JavaScript/TypeScript SDK for SapixDB — the agent-native living database",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "scripts": {
15
+ "build": "tsc",
16
+ "dev": "tsc --watch",
17
+ "test": "node --experimental-vm-modules node_modules/.bin/jest"
18
+ },
19
+ "files": [
20
+ "dist",
21
+ "README.md"
22
+ ],
23
+ "keywords": [
24
+ "sapixdb",
25
+ "database",
26
+ "agent-native",
27
+ "ai-database",
28
+ "sdk",
29
+ "typescript"
30
+ ],
31
+ "author": "Sensart Technologies LLC",
32
+ "license": "MIT",
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "https://github.com/sensart/sapixdb"
36
+ },
37
+ "devDependencies": {
38
+ "typescript": "^5.4.0"
39
+ },
40
+ "engines": {
41
+ "node": ">=18.0.0"
42
+ }
43
+ }