@sapixdb/sdk 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.
- package/dist/admin.d.ts +78 -0
- package/dist/admin.d.ts.map +1 -0
- package/dist/admin.js +89 -0
- package/dist/admin.js.map +1 -0
- package/dist/client.d.ts +99 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +210 -0
- package/dist/client.js.map +1 -0
- package/dist/collection.d.ts +124 -0
- package/dist/collection.d.ts.map +1 -0
- package/dist/collection.js +190 -0
- package/dist/collection.js.map +1 -0
- package/dist/errors.d.ts +30 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +60 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/stream.d.ts +42 -0
- package/dist/stream.d.ts.map +1 -0
- package/dist/stream.js +60 -0
- package/dist/stream.js.map +1 -0
- package/dist/types.d.ts +195 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +33 -0
package/dist/admin.d.ts
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { ApiKeyPatch, ApiKeyUsage, ApiKeyView, CreateApiKeyRequest, CreateApiKeyResponse, ListApiKeysResponse } from "./types.js";
|
|
2
|
+
type Requester = <T>(method: string, path: string, body?: unknown) => Promise<T>;
|
|
3
|
+
/**
|
|
4
|
+
* Programmatic API key management.
|
|
5
|
+
* Requires a root key or a key with ``admin:api-keys`` scope.
|
|
6
|
+
*
|
|
7
|
+
* Obtain via ``SapixClient.admin``.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* const db = new SapixClient({ baseUrl: "http://localhost:7475",
|
|
11
|
+
* apiKey: process.env.SAPIX_ROOT_KEY });
|
|
12
|
+
*
|
|
13
|
+
* // Create a scoped key for an orders service
|
|
14
|
+
* const result = await db.admin.createKey({
|
|
15
|
+
* label: "orders-service-prod",
|
|
16
|
+
* scopes: ["write:agents/orders/records", "read:agents/orders/query"],
|
|
17
|
+
* rate_limit_rps: 500,
|
|
18
|
+
* });
|
|
19
|
+
* console.log(result.key); // save immediately — shown once
|
|
20
|
+
*
|
|
21
|
+
* // List all keys
|
|
22
|
+
* const { keys } = await db.admin.listKeys();
|
|
23
|
+
*
|
|
24
|
+
* // Update expiry
|
|
25
|
+
* await db.admin.updateKey(result.key_id, { expires_at_ms: Date.now() + 90 * 86_400_000 });
|
|
26
|
+
*
|
|
27
|
+
* // Remove rate limit
|
|
28
|
+
* await db.admin.updateKey(result.key_id, { rate_limit_rps: null });
|
|
29
|
+
*
|
|
30
|
+
* // Check usage
|
|
31
|
+
* const usage = await db.admin.keyUsage(result.key_id);
|
|
32
|
+
* console.log(usage.request_count_since_restart);
|
|
33
|
+
*
|
|
34
|
+
* // Revoke
|
|
35
|
+
* await db.admin.revokeKey(result.key_id);
|
|
36
|
+
*/
|
|
37
|
+
export declare class AdminClient {
|
|
38
|
+
private readonly req;
|
|
39
|
+
constructor(req: Requester);
|
|
40
|
+
/** Return all API keys. Secrets are never included. */
|
|
41
|
+
listKeys(): Promise<ListApiKeysResponse>;
|
|
42
|
+
/**
|
|
43
|
+
* Create a new scoped API key.
|
|
44
|
+
*
|
|
45
|
+
* ``result.key`` contains the full secret and is returned **exactly once**.
|
|
46
|
+
*
|
|
47
|
+
* **Scope examples**
|
|
48
|
+
* ```
|
|
49
|
+
* ["admin:*"] // full operator access
|
|
50
|
+
* ["admin:api-keys"] // can manage keys only
|
|
51
|
+
* ["write:agents/orders/records",
|
|
52
|
+
* "read:agents/orders/query"] // scoped to one agent
|
|
53
|
+
* ["write:*", "read:*"] // all reads + writes
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
createKey(req: CreateApiKeyRequest): Promise<CreateApiKeyResponse>;
|
|
57
|
+
/** Fetch a single key by ID. Throws ``SapixError`` with status 404 if missing. */
|
|
58
|
+
getKey(keyId: string): Promise<ApiKeyView>;
|
|
59
|
+
/**
|
|
60
|
+
* Partially update a key. Only provided fields are changed.
|
|
61
|
+
*
|
|
62
|
+
* Set a nullable field to ``null`` to remove it:
|
|
63
|
+
* ```ts
|
|
64
|
+
* // Make key permanent (remove expiry)
|
|
65
|
+
* await db.admin.updateKey(id, { expires_at_ms: null });
|
|
66
|
+
*
|
|
67
|
+
* // Remove rate limit
|
|
68
|
+
* await db.admin.updateKey(id, { rate_limit_rps: null });
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
updateKey(keyId: string, patch: ApiKeyPatch): Promise<ApiKeyView>;
|
|
72
|
+
/** Revoke a key permanently. Immediately blocks all requests from it. */
|
|
73
|
+
revokeKey(keyId: string): Promise<void>;
|
|
74
|
+
/** Request count and last-used timestamp since the last agent restart. */
|
|
75
|
+
keyUsage(keyId: string): Promise<ApiKeyUsage>;
|
|
76
|
+
}
|
|
77
|
+
export {};
|
|
78
|
+
//# sourceMappingURL=admin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin.d.ts","sourceRoot":"","sources":["../src/admin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,WAAW,EACX,UAAU,EACV,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACpB,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;AAEjF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,qBAAa,WAAW;IACV,OAAO,CAAC,QAAQ,CAAC,GAAG;gBAAH,GAAG,EAAE,SAAS;IAE3C,uDAAuD;IACvD,QAAQ,IAAI,OAAO,CAAC,mBAAmB,CAAC;IAIxC;;;;;;;;;;;;;OAaG;IACH,SAAS,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAIlE,kFAAkF;IAClF,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAI1C;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;IAIjE,yEAAyE;IACzE,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvC,0EAA0E;IAC1E,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;CAG9C"}
|
package/dist/admin.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Programmatic API key management.
|
|
3
|
+
* Requires a root key or a key with ``admin:api-keys`` scope.
|
|
4
|
+
*
|
|
5
|
+
* Obtain via ``SapixClient.admin``.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* const db = new SapixClient({ baseUrl: "http://localhost:7475",
|
|
9
|
+
* apiKey: process.env.SAPIX_ROOT_KEY });
|
|
10
|
+
*
|
|
11
|
+
* // Create a scoped key for an orders service
|
|
12
|
+
* const result = await db.admin.createKey({
|
|
13
|
+
* label: "orders-service-prod",
|
|
14
|
+
* scopes: ["write:agents/orders/records", "read:agents/orders/query"],
|
|
15
|
+
* rate_limit_rps: 500,
|
|
16
|
+
* });
|
|
17
|
+
* console.log(result.key); // save immediately — shown once
|
|
18
|
+
*
|
|
19
|
+
* // List all keys
|
|
20
|
+
* const { keys } = await db.admin.listKeys();
|
|
21
|
+
*
|
|
22
|
+
* // Update expiry
|
|
23
|
+
* await db.admin.updateKey(result.key_id, { expires_at_ms: Date.now() + 90 * 86_400_000 });
|
|
24
|
+
*
|
|
25
|
+
* // Remove rate limit
|
|
26
|
+
* await db.admin.updateKey(result.key_id, { rate_limit_rps: null });
|
|
27
|
+
*
|
|
28
|
+
* // Check usage
|
|
29
|
+
* const usage = await db.admin.keyUsage(result.key_id);
|
|
30
|
+
* console.log(usage.request_count_since_restart);
|
|
31
|
+
*
|
|
32
|
+
* // Revoke
|
|
33
|
+
* await db.admin.revokeKey(result.key_id);
|
|
34
|
+
*/
|
|
35
|
+
export class AdminClient {
|
|
36
|
+
req;
|
|
37
|
+
constructor(req) {
|
|
38
|
+
this.req = req;
|
|
39
|
+
}
|
|
40
|
+
/** Return all API keys. Secrets are never included. */
|
|
41
|
+
listKeys() {
|
|
42
|
+
return this.req("GET", "/v1/admin/api-keys");
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Create a new scoped API key.
|
|
46
|
+
*
|
|
47
|
+
* ``result.key`` contains the full secret and is returned **exactly once**.
|
|
48
|
+
*
|
|
49
|
+
* **Scope examples**
|
|
50
|
+
* ```
|
|
51
|
+
* ["admin:*"] // full operator access
|
|
52
|
+
* ["admin:api-keys"] // can manage keys only
|
|
53
|
+
* ["write:agents/orders/records",
|
|
54
|
+
* "read:agents/orders/query"] // scoped to one agent
|
|
55
|
+
* ["write:*", "read:*"] // all reads + writes
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
createKey(req) {
|
|
59
|
+
return this.req("POST", "/v1/admin/api-keys", req);
|
|
60
|
+
}
|
|
61
|
+
/** Fetch a single key by ID. Throws ``SapixError`` with status 404 if missing. */
|
|
62
|
+
getKey(keyId) {
|
|
63
|
+
return this.req("GET", `/v1/admin/api-keys/${keyId}`);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Partially update a key. Only provided fields are changed.
|
|
67
|
+
*
|
|
68
|
+
* Set a nullable field to ``null`` to remove it:
|
|
69
|
+
* ```ts
|
|
70
|
+
* // Make key permanent (remove expiry)
|
|
71
|
+
* await db.admin.updateKey(id, { expires_at_ms: null });
|
|
72
|
+
*
|
|
73
|
+
* // Remove rate limit
|
|
74
|
+
* await db.admin.updateKey(id, { rate_limit_rps: null });
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
updateKey(keyId, patch) {
|
|
78
|
+
return this.req("PATCH", `/v1/admin/api-keys/${keyId}`, patch);
|
|
79
|
+
}
|
|
80
|
+
/** Revoke a key permanently. Immediately blocks all requests from it. */
|
|
81
|
+
revokeKey(keyId) {
|
|
82
|
+
return this.req("DELETE", `/v1/admin/api-keys/${keyId}`);
|
|
83
|
+
}
|
|
84
|
+
/** Request count and last-used timestamp since the last agent restart. */
|
|
85
|
+
keyUsage(keyId) {
|
|
86
|
+
return this.req("GET", `/v1/admin/api-keys/${keyId}/usage`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=admin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin.js","sourceRoot":"","sources":["../src/admin.ts"],"names":[],"mappings":"AAWA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,MAAM,OAAO,WAAW;IACO;IAA7B,YAA6B,GAAc;QAAd,QAAG,GAAH,GAAG,CAAW;IAAG,CAAC;IAE/C,uDAAuD;IACvD,QAAQ;QACN,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,oBAAoB,CAAC,CAAC;IAC/C,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,SAAS,CAAC,GAAwB;QAChC,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,oBAAoB,EAAE,GAAG,CAAC,CAAC;IACrD,CAAC;IAED,kFAAkF;IAClF,MAAM,CAAC,KAAa;QAClB,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,sBAAsB,KAAK,EAAE,CAAC,CAAC;IACxD,CAAC;IAED;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,KAAa,EAAE,KAAkB;QACzC,OAAO,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,sBAAsB,KAAK,EAAE,EAAE,KAAK,CAAC,CAAC;IACjE,CAAC;IAED,yEAAyE;IACzE,SAAS,CAAC,KAAa;QACrB,OAAO,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,sBAAsB,KAAK,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED,0EAA0E;IAC1E,QAAQ,CAAC,KAAa;QACpB,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,sBAAsB,KAAK,QAAQ,CAAC,CAAC;IAC9D,CAAC;CACF"}
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { AdminClient } from "./admin.js";
|
|
2
|
+
import { CollectionClient } from "./collection.js";
|
|
3
|
+
import type { StreamEvent, SubscribeOptions } from "./stream.js";
|
|
4
|
+
import type { AddEdgeRequest, AddRecordRefRequest, ChainHeadResponse, EdgeView, GenesisRequest, GenesisResponse, HealthResponse, QueryResult, RecordRefView, RecordView, SapixClientOptions, SaqlQuery, WriteResponse } from "./types.js";
|
|
5
|
+
export declare class SapixClient {
|
|
6
|
+
private readonly baseUrl;
|
|
7
|
+
private readonly timeoutMs;
|
|
8
|
+
private readonly _fetch;
|
|
9
|
+
private readonly authHeaders;
|
|
10
|
+
constructor(options: SapixClientOptions);
|
|
11
|
+
private request;
|
|
12
|
+
private toB64;
|
|
13
|
+
fromB64(b64: string): Uint8Array;
|
|
14
|
+
/**
|
|
15
|
+
* API key management — create, list, update, revoke, and inspect usage.
|
|
16
|
+
* Requires a root key or a key with ``admin:api-keys`` scope.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* const result = await db.admin.createKey({
|
|
20
|
+
* label: "orders-service-prod",
|
|
21
|
+
* scopes: ["write:agents/orders/records", "read:agents/orders/query"],
|
|
22
|
+
* rate_limit_rps: 500,
|
|
23
|
+
* });
|
|
24
|
+
* console.log(result.key); // save immediately — shown once
|
|
25
|
+
*/
|
|
26
|
+
get admin(): AdminClient;
|
|
27
|
+
/**
|
|
28
|
+
* Return a `CollectionClient` for a named SapixDB agent.
|
|
29
|
+
*
|
|
30
|
+
* Every named agent is an independent strand — a logical "table" scoped to
|
|
31
|
+
* its own keypair and access policy. Operations route to `/v1/agents/{name}/...`.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* const orders = db.collection("orders");
|
|
35
|
+
* const record = await orders.write({ total: 99.99 });
|
|
36
|
+
* const latest = await orders.latest({ limit: 20 });
|
|
37
|
+
* const one = await orders.findOne({ status: "pending" });
|
|
38
|
+
* const byHash = await orders.get(record.content_hash);
|
|
39
|
+
* const hist = await orders.history({ limit: 100 });
|
|
40
|
+
* const snap = await orders.asOf(record.timestamp_hlc).latest();
|
|
41
|
+
*/
|
|
42
|
+
collection(name: string): CollectionClient;
|
|
43
|
+
/**
|
|
44
|
+
* Alias for `collection(name)` — preferred when thinking in SapixDB terms
|
|
45
|
+
* where each "table" is an agent.
|
|
46
|
+
*/
|
|
47
|
+
agent(name: string): CollectionClient;
|
|
48
|
+
health(): Promise<HealthResponse>;
|
|
49
|
+
genesis(req?: GenesisRequest): Promise<GenesisResponse>;
|
|
50
|
+
/**
|
|
51
|
+
* Append a raw byte payload to the agent's strand.
|
|
52
|
+
* Encode your domain object before calling (e.g. with msgpackr or JSON.stringify).
|
|
53
|
+
*/
|
|
54
|
+
write(payload: Uint8Array | string, flags?: number): Promise<WriteResponse>;
|
|
55
|
+
/**
|
|
56
|
+
* Convenience: JSON-encode `obj` and write it.
|
|
57
|
+
* Use `client.fromB64(record.payload_b64)` → `JSON.parse(...)` to decode on read.
|
|
58
|
+
*/
|
|
59
|
+
writeJson(obj: unknown, flags?: number): Promise<WriteResponse>;
|
|
60
|
+
readByHash(contentHash: string): Promise<RecordView>;
|
|
61
|
+
chainHead(): Promise<ChainHeadResponse>;
|
|
62
|
+
query(q: SaqlQuery): Promise<QueryResult>;
|
|
63
|
+
queryLatest(limit?: number): Promise<QueryResult>;
|
|
64
|
+
queryTimeRange(fromTs: number, toTs: number): Promise<QueryResult>;
|
|
65
|
+
queryByHash(contentHash: string): Promise<QueryResult>;
|
|
66
|
+
queryChainHead(): Promise<QueryResult>;
|
|
67
|
+
addEdge(req: AddEdgeRequest): Promise<void>;
|
|
68
|
+
getEdges(agentId: string, opts?: {
|
|
69
|
+
direction?: "in" | "out";
|
|
70
|
+
edge_type?: string;
|
|
71
|
+
}): Promise<EdgeView[]>;
|
|
72
|
+
deleteEdge(src: string, edgeType: string, dst: string): Promise<void>;
|
|
73
|
+
addRecordRef(req: AddRecordRefRequest): Promise<void>;
|
|
74
|
+
getRecordRefs(agentId: string, contentHash: string): Promise<RecordRefView[]>;
|
|
75
|
+
/**
|
|
76
|
+
* Subscribe to realtime writes on a named agent via SSE.
|
|
77
|
+
* Returns an `EventSource` — call `.close()` to unsubscribe.
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* const es = client.subscribeAgent("orders", (ev) => {
|
|
81
|
+
* console.log(ev.record_id, ev.payload);
|
|
82
|
+
* });
|
|
83
|
+
* es.close();
|
|
84
|
+
*/
|
|
85
|
+
subscribeAgent(agentId: string, onEvent: (event: StreamEvent) => void, opts?: SubscribeOptions): EventSource;
|
|
86
|
+
/**
|
|
87
|
+
* Subscribe to realtime writes on all agents via SSE.
|
|
88
|
+
* Returns an `EventSource` — call `.close()` to unsubscribe.
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* const es = client.subscribeGlobal((ev) => {
|
|
92
|
+
* console.log(ev.agent_id, ev.record_id);
|
|
93
|
+
* }, { agents: ["orders", "payments"] });
|
|
94
|
+
*/
|
|
95
|
+
subscribeGlobal(onEvent: (event: StreamEvent) => void, opts?: SubscribeOptions & {
|
|
96
|
+
agents?: string[];
|
|
97
|
+
}): EventSource;
|
|
98
|
+
}
|
|
99
|
+
//# 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,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnD,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,KAAK,EACV,cAAc,EACd,mBAAmB,EACnB,iBAAiB,EACjB,QAAQ,EACR,cAAc,EACd,eAAe,EACf,cAAc,EACd,WAAW,EACX,aAAa,EACb,UAAU,EACV,kBAAkB,EAClB,SAAS,EACT,aAAa,EACd,MAAM,YAAY,CAAC;AAIpB,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0B;IACjD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAyB;gBAEzC,OAAO,EAAE,kBAAkB;YAezB,OAAO;IAkCrB,OAAO,CAAC,KAAK;IAWb,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU;IAWhC;;;;;;;;;;;OAWG;IACH,IAAI,KAAK,IAAI,WAAW,CAEvB;IAID;;;;;;;;;;;;;;OAcG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB;IAI1C;;;OAGG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB;IAMrC,MAAM,IAAI,OAAO,CAAC,cAAc,CAAC;IAMjC,OAAO,CAAC,GAAG,GAAE,cAAmB,GAAG,OAAO,CAAC,eAAe,CAAC;IAM3D;;;OAGG;IACH,KAAK,CAAC,OAAO,EAAE,UAAU,GAAG,MAAM,EAAE,KAAK,SAAI,GAAG,OAAO,CAAC,aAAa,CAAC;IAOtE;;;OAGG;IACH,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,SAAI,GAAG,OAAO,CAAC,aAAa,CAAC;IAI1D,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAIpD,SAAS,IAAI,OAAO,CAAC,iBAAiB,CAAC;IAMvC,KAAK,CAAC,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;IAIzC,WAAW,CAAC,KAAK,SAAK,GAAG,OAAO,CAAC,WAAW,CAAC;IAI7C,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAIlE,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAItD,cAAc,IAAI,OAAO,CAAC,WAAW,CAAC;IAMtC,OAAO,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3C,QAAQ,CACN,OAAO,EAAE,MAAM,EACf,IAAI,GAAE;QAAE,SAAS,CAAC,EAAE,IAAI,GAAG,KAAK,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAO,GAC1D,OAAO,CAAC,QAAQ,EAAE,CAAC;IAQtB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMrE,YAAY,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAIrD,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAM7E;;;;;;;;;OASG;IACH,cAAc,CACZ,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,EACrC,IAAI,CAAC,EAAE,gBAAgB,GACtB,WAAW;IAId;;;;;;;;OAQG;IACH,eAAe,CACb,OAAO,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,EACrC,IAAI,CAAC,EAAE,gBAAgB,GAAG;QAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,GAC9C,WAAW;CAGf"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { SapixError } from "./errors.js";
|
|
2
|
+
import { AdminClient } from "./admin.js";
|
|
3
|
+
import { CollectionClient } from "./collection.js";
|
|
4
|
+
import { openAgentStream, openGlobalStream } from "./stream.js";
|
|
5
|
+
const DEFAULT_TIMEOUT_MS = 10_000;
|
|
6
|
+
export class SapixClient {
|
|
7
|
+
baseUrl;
|
|
8
|
+
timeoutMs;
|
|
9
|
+
_fetch;
|
|
10
|
+
authHeaders;
|
|
11
|
+
constructor(options) {
|
|
12
|
+
this.baseUrl = options.baseUrl.replace(/\/$/, "");
|
|
13
|
+
this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
14
|
+
this._fetch = options.fetch ?? globalThis.fetch.bind(globalThis);
|
|
15
|
+
this.authHeaders = {};
|
|
16
|
+
if (options.apiKey) {
|
|
17
|
+
this.authHeaders["Authorization"] = `Bearer ${options.apiKey}`;
|
|
18
|
+
}
|
|
19
|
+
if (options.callerId) {
|
|
20
|
+
this.authHeaders["X-Sapix-Caller"] = options.callerId;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
// ── Internal helpers ──────────────────────────────────────────────────────
|
|
24
|
+
async request(method, path, body) {
|
|
25
|
+
const controller = new AbortController();
|
|
26
|
+
const timer = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
27
|
+
let resp;
|
|
28
|
+
try {
|
|
29
|
+
const baseHeaders = { ...this.authHeaders };
|
|
30
|
+
if (body !== undefined)
|
|
31
|
+
baseHeaders["content-type"] = "application/json";
|
|
32
|
+
const init = {
|
|
33
|
+
method,
|
|
34
|
+
headers: baseHeaders,
|
|
35
|
+
signal: controller.signal,
|
|
36
|
+
};
|
|
37
|
+
if (body !== undefined)
|
|
38
|
+
init.body = JSON.stringify(body);
|
|
39
|
+
resp = await this._fetch(`${this.baseUrl}${path}`, init);
|
|
40
|
+
}
|
|
41
|
+
finally {
|
|
42
|
+
clearTimeout(timer);
|
|
43
|
+
}
|
|
44
|
+
if (!resp.ok) {
|
|
45
|
+
throw await SapixError.fromResponse(resp);
|
|
46
|
+
}
|
|
47
|
+
if (resp.status === 204 || resp.headers.get("content-length") === "0") {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
return resp.json();
|
|
51
|
+
}
|
|
52
|
+
toB64(payload) {
|
|
53
|
+
if (typeof payload === "string") {
|
|
54
|
+
return btoa(payload);
|
|
55
|
+
}
|
|
56
|
+
let binary = "";
|
|
57
|
+
for (let i = 0; i < payload.length; i++) {
|
|
58
|
+
binary += String.fromCharCode(payload[i]);
|
|
59
|
+
}
|
|
60
|
+
return btoa(binary);
|
|
61
|
+
}
|
|
62
|
+
fromB64(b64) {
|
|
63
|
+
const binary = atob(b64);
|
|
64
|
+
const bytes = new Uint8Array(binary.length);
|
|
65
|
+
for (let i = 0; i < binary.length; i++) {
|
|
66
|
+
bytes[i] = binary.charCodeAt(i);
|
|
67
|
+
}
|
|
68
|
+
return bytes;
|
|
69
|
+
}
|
|
70
|
+
// ── Admin ─────────────────────────────────────────────────────────────────
|
|
71
|
+
/**
|
|
72
|
+
* API key management — create, list, update, revoke, and inspect usage.
|
|
73
|
+
* Requires a root key or a key with ``admin:api-keys`` scope.
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* const result = await db.admin.createKey({
|
|
77
|
+
* label: "orders-service-prod",
|
|
78
|
+
* scopes: ["write:agents/orders/records", "read:agents/orders/query"],
|
|
79
|
+
* rate_limit_rps: 500,
|
|
80
|
+
* });
|
|
81
|
+
* console.log(result.key); // save immediately — shown once
|
|
82
|
+
*/
|
|
83
|
+
get admin() {
|
|
84
|
+
return new AdminClient(this.request.bind(this));
|
|
85
|
+
}
|
|
86
|
+
// ── Named agents (collections) ────────────────────────────────────────────
|
|
87
|
+
/**
|
|
88
|
+
* Return a `CollectionClient` for a named SapixDB agent.
|
|
89
|
+
*
|
|
90
|
+
* Every named agent is an independent strand — a logical "table" scoped to
|
|
91
|
+
* its own keypair and access policy. Operations route to `/v1/agents/{name}/...`.
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* const orders = db.collection("orders");
|
|
95
|
+
* const record = await orders.write({ total: 99.99 });
|
|
96
|
+
* const latest = await orders.latest({ limit: 20 });
|
|
97
|
+
* const one = await orders.findOne({ status: "pending" });
|
|
98
|
+
* const byHash = await orders.get(record.content_hash);
|
|
99
|
+
* const hist = await orders.history({ limit: 100 });
|
|
100
|
+
* const snap = await orders.asOf(record.timestamp_hlc).latest();
|
|
101
|
+
*/
|
|
102
|
+
collection(name) {
|
|
103
|
+
return new CollectionClient(name, this.request.bind(this));
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Alias for `collection(name)` — preferred when thinking in SapixDB terms
|
|
107
|
+
* where each "table" is an agent.
|
|
108
|
+
*/
|
|
109
|
+
agent(name) {
|
|
110
|
+
return this.collection(name);
|
|
111
|
+
}
|
|
112
|
+
// ── Health ────────────────────────────────────────────────────────────────
|
|
113
|
+
health() {
|
|
114
|
+
return this.request("GET", "/v1/health");
|
|
115
|
+
}
|
|
116
|
+
// ── Genesis ───────────────────────────────────────────────────────────────
|
|
117
|
+
genesis(req = {}) {
|
|
118
|
+
return this.request("POST", "/v1/genesis", { zone: req.zone ?? "governed" });
|
|
119
|
+
}
|
|
120
|
+
// ── Records ───────────────────────────────────────────────────────────────
|
|
121
|
+
/**
|
|
122
|
+
* Append a raw byte payload to the agent's strand.
|
|
123
|
+
* Encode your domain object before calling (e.g. with msgpackr or JSON.stringify).
|
|
124
|
+
*/
|
|
125
|
+
write(payload, flags = 0) {
|
|
126
|
+
return this.request("POST", "/v1/records", {
|
|
127
|
+
payload_b64: this.toB64(payload),
|
|
128
|
+
flags,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Convenience: JSON-encode `obj` and write it.
|
|
133
|
+
* Use `client.fromB64(record.payload_b64)` → `JSON.parse(...)` to decode on read.
|
|
134
|
+
*/
|
|
135
|
+
writeJson(obj, flags = 0) {
|
|
136
|
+
return this.write(new TextEncoder().encode(JSON.stringify(obj)), flags);
|
|
137
|
+
}
|
|
138
|
+
readByHash(contentHash) {
|
|
139
|
+
return this.request("GET", `/v1/records/${contentHash}`);
|
|
140
|
+
}
|
|
141
|
+
chainHead() {
|
|
142
|
+
return this.request("GET", "/v1/strand/head");
|
|
143
|
+
}
|
|
144
|
+
// ── SaQL ─────────────────────────────────────────────────────────────────
|
|
145
|
+
query(q) {
|
|
146
|
+
return this.request("POST", "/v1/query", q);
|
|
147
|
+
}
|
|
148
|
+
queryLatest(limit = 10) {
|
|
149
|
+
return this.query({ type: "latest", limit });
|
|
150
|
+
}
|
|
151
|
+
queryTimeRange(fromTs, toTs) {
|
|
152
|
+
return this.query({ type: "time_range", from_ts: fromTs, to_ts: toTs });
|
|
153
|
+
}
|
|
154
|
+
queryByHash(contentHash) {
|
|
155
|
+
return this.query({ type: "hash", content_hash: contentHash });
|
|
156
|
+
}
|
|
157
|
+
queryChainHead() {
|
|
158
|
+
return this.query({ type: "chain_head" });
|
|
159
|
+
}
|
|
160
|
+
// ── Graph — edges ─────────────────────────────────────────────────────────
|
|
161
|
+
addEdge(req) {
|
|
162
|
+
return this.request("POST", "/v1/graph/edges", req);
|
|
163
|
+
}
|
|
164
|
+
getEdges(agentId, opts = {}) {
|
|
165
|
+
const params = new URLSearchParams();
|
|
166
|
+
if (opts.direction)
|
|
167
|
+
params.set("direction", opts.direction);
|
|
168
|
+
if (opts.edge_type)
|
|
169
|
+
params.set("edge_type", opts.edge_type);
|
|
170
|
+
const qs = params.size > 0 ? `?${params}` : "";
|
|
171
|
+
return this.request("GET", `/v1/graph/edges/${agentId}${qs}`);
|
|
172
|
+
}
|
|
173
|
+
deleteEdge(src, edgeType, dst) {
|
|
174
|
+
return this.request("DELETE", `/v1/graph/edges/${src}/${edgeType}/${dst}`);
|
|
175
|
+
}
|
|
176
|
+
// ── Graph — record refs ───────────────────────────────────────────────────
|
|
177
|
+
addRecordRef(req) {
|
|
178
|
+
return this.request("POST", "/v1/graph/refs", req);
|
|
179
|
+
}
|
|
180
|
+
getRecordRefs(agentId, contentHash) {
|
|
181
|
+
return this.request("GET", `/v1/graph/refs/${agentId}/${contentHash}`);
|
|
182
|
+
}
|
|
183
|
+
// ── Realtime SSE ──────────────────────────────────────────────────────────
|
|
184
|
+
/**
|
|
185
|
+
* Subscribe to realtime writes on a named agent via SSE.
|
|
186
|
+
* Returns an `EventSource` — call `.close()` to unsubscribe.
|
|
187
|
+
*
|
|
188
|
+
* @example
|
|
189
|
+
* const es = client.subscribeAgent("orders", (ev) => {
|
|
190
|
+
* console.log(ev.record_id, ev.payload);
|
|
191
|
+
* });
|
|
192
|
+
* es.close();
|
|
193
|
+
*/
|
|
194
|
+
subscribeAgent(agentId, onEvent, opts) {
|
|
195
|
+
return openAgentStream(this.baseUrl, agentId, onEvent, opts);
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Subscribe to realtime writes on all agents via SSE.
|
|
199
|
+
* Returns an `EventSource` — call `.close()` to unsubscribe.
|
|
200
|
+
*
|
|
201
|
+
* @example
|
|
202
|
+
* const es = client.subscribeGlobal((ev) => {
|
|
203
|
+
* console.log(ev.agent_id, ev.record_id);
|
|
204
|
+
* }, { agents: ["orders", "payments"] });
|
|
205
|
+
*/
|
|
206
|
+
subscribeGlobal(onEvent, opts) {
|
|
207
|
+
return openGlobalStream(this.baseUrl, onEvent, opts);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,124 @@
|
|
|
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 {
|
|
12
|
+
private readonly name;
|
|
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>;
|
|
28
|
+
}
|
|
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>;
|
|
111
|
+
/**
|
|
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 });
|
|
120
|
+
*/
|
|
121
|
+
asOf(timestampHlc: number): CollectionSnapshot;
|
|
122
|
+
}
|
|
123
|
+
export {};
|
|
124
|
+
//# sourceMappingURL=collection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|