@anysoftinc/anydb-sdk 0.1.2 → 0.4.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 +100 -163
- package/dist/anydb.datascript.core.js +336 -0
- package/dist/anydb.datascript.rules.js +29 -0
- package/dist/anydb.datascript.schema.js +35 -0
- package/dist/client.d.ts +46 -96
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +332 -305
- package/dist/cljs.core.js +38752 -0
- package/dist/cljs.reader.js +450 -0
- package/dist/cljs.tools.reader.edn.js +945 -0
- package/dist/cljs.tools.reader.impl.commons.js +205 -0
- package/dist/cljs.tools.reader.impl.errors.js +429 -0
- package/dist/cljs.tools.reader.impl.inspect.js +170 -0
- package/dist/cljs.tools.reader.impl.utils.js +413 -0
- package/dist/cljs.tools.reader.js +1815 -0
- package/dist/cljs.tools.reader.reader_types.js +826 -0
- package/dist/cljs_env.js +7672 -0
- package/dist/clojure.data.js +307 -0
- package/dist/clojure.edn.js +107 -0
- package/dist/clojure.set.js +394 -0
- package/dist/clojure.string.js +490 -0
- package/dist/clojure.walk.js +144 -0
- package/dist/datascript-backend.d.ts +26 -0
- package/dist/datascript-backend.d.ts.map +1 -0
- package/dist/datascript-backend.js +113 -0
- package/dist/datascript.built_ins.js +680 -0
- package/dist/datascript.conn.js +814 -0
- package/dist/datascript.core.js +1285 -0
- package/dist/datascript.db.js +4058 -0
- package/dist/datascript.impl.entity.js +588 -0
- package/dist/datascript.lru.js +213 -0
- package/dist/datascript.parser.js +8598 -0
- package/dist/datascript.pull_api.js +2287 -0
- package/dist/datascript.pull_parser.js +865 -0
- package/dist/datascript.query.js +2785 -0
- package/dist/datascript.serialize.js +352 -0
- package/dist/datascript.storage.js +50 -0
- package/dist/datascript.util.js +82 -0
- package/dist/extend_clj.core.js +134 -0
- package/dist/me.tonsky.persistent_sorted_set.arrays.js +54 -0
- package/dist/me.tonsky.persistent_sorted_set.js +2485 -0
- package/dist/nextauth-adapter.d.ts +7 -2
- package/dist/nextauth-adapter.d.ts.map +1 -1
- package/dist/nextauth-adapter.js +251 -149
- package/package.json +9 -5
- package/dist/query-builder.d.ts +0 -126
- package/dist/query-builder.d.ts.map +0 -1
- package/dist/query-builder.js +0 -207
package/README.md
CHANGED
|
@@ -11,35 +11,43 @@ npm install @anysoftinc/anydb-sdk
|
|
|
11
11
|
## Quick Start
|
|
12
12
|
|
|
13
13
|
```typescript
|
|
14
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
DatomicClient,
|
|
16
|
+
createAnyDBClient,
|
|
17
|
+
kw,
|
|
18
|
+
sym,
|
|
19
|
+
uuid,
|
|
20
|
+
} from "@anysoftinc/anydb-sdk";
|
|
15
21
|
|
|
16
22
|
// Create a client
|
|
17
23
|
const client = new DatomicClient({
|
|
18
|
-
baseUrl:
|
|
24
|
+
baseUrl: "http://localhost:4000",
|
|
25
|
+
getAuthToken: () => process.env.ANYDB_TOKEN!,
|
|
19
26
|
});
|
|
20
27
|
|
|
21
28
|
// Create a database wrapper for convenience
|
|
22
|
-
const db =
|
|
29
|
+
const db = createAnyDBClient(client, "sql", "db-name");
|
|
23
30
|
|
|
24
|
-
//
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
31
|
+
// Symbolic query
|
|
32
|
+
const query = {
|
|
33
|
+
find: [[sym("pull"), sym("?e"), [kw("db/id"), kw("person/name")]]],
|
|
34
|
+
where: [[sym("?e"), kw("person/name"), "John Doe"]],
|
|
35
|
+
};
|
|
36
|
+
const rows = await db.query(query);
|
|
29
37
|
|
|
30
|
-
// Execute a transaction
|
|
31
|
-
|
|
38
|
+
// Execute a transaction (keywordized keys, kw()/uuid() for values)
|
|
39
|
+
await db.transact([
|
|
32
40
|
{
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
41
|
+
["person/id"]: uuid("550e8400-e29b-41d4-a716-446655440000"),
|
|
42
|
+
["person/name"]: "John Doe",
|
|
43
|
+
},
|
|
37
44
|
]);
|
|
38
45
|
```
|
|
39
46
|
|
|
40
47
|
## Core Features
|
|
41
48
|
|
|
42
49
|
### Database Operations
|
|
50
|
+
|
|
43
51
|
- **Database Management** - Create, list, and delete databases
|
|
44
52
|
- **Transactions** - Execute database transactions
|
|
45
53
|
- **Queries** - Execute Datalog queries with full EDN support
|
|
@@ -48,176 +56,109 @@ const txResult = await db.transact([
|
|
|
48
56
|
|
|
49
57
|
### Query Types
|
|
50
58
|
|
|
51
|
-
|
|
52
|
-
```typescript
|
|
53
|
-
const query = [
|
|
54
|
-
':find', '?e', '?name',
|
|
55
|
-
':where', ['?e', ':person/name', '?name']
|
|
56
|
-
];
|
|
57
|
-
const results = await db.query(query);
|
|
58
|
-
```
|
|
59
|
+
Traditional array-based queries are not supported in v2.
|
|
59
60
|
|
|
60
61
|
#### Symbolic Queries (Type-safe)
|
|
62
|
+
|
|
61
63
|
```typescript
|
|
62
|
-
import { sym, kw } from
|
|
64
|
+
import { sym, kw } from "@anysoftinc/anydb-sdk";
|
|
63
65
|
|
|
64
66
|
const query = {
|
|
65
|
-
find: [sym(
|
|
66
|
-
where: [
|
|
67
|
-
[sym('?e'), kw(':person/name'), sym('?name')]
|
|
68
|
-
]
|
|
67
|
+
find: [sym("?e"), sym("?name")],
|
|
68
|
+
where: [[sym("?e"), kw("person/name"), sym("?name")]],
|
|
69
69
|
};
|
|
70
|
-
const results = await db.
|
|
70
|
+
const results = await db.query(query);
|
|
71
71
|
```
|
|
72
72
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
The QueryBuilder provides a type-safe, fluent API for constructing Datalog queries:
|
|
76
|
-
|
|
77
|
-
```typescript
|
|
78
|
-
import { QueryBuilder, kw } from '@anysoftinc/anydb-sdk';
|
|
79
|
-
|
|
80
|
-
// Basic entity-attribute-value query
|
|
81
|
-
const basicQuery = new QueryBuilder()
|
|
82
|
-
.find('?e', '?name')
|
|
83
|
-
.where({ entity: '?e', attribute: kw(':person/name'), value: '?name' })
|
|
84
|
-
.build();
|
|
85
|
-
|
|
86
|
-
// Fluent entity-based building
|
|
87
|
-
const fluentQuery = new QueryBuilder()
|
|
88
|
-
.find('?e', '?name')
|
|
89
|
-
.entity('?e').hasAttribute(kw(':person/name')).withValue('?name')
|
|
90
|
-
.build();
|
|
91
|
-
|
|
92
|
-
// Helper methods for common patterns
|
|
93
|
-
const entitiesWithName = new QueryBuilder()
|
|
94
|
-
.findEntitiesWith(kw(':person/name'))
|
|
95
|
-
.build();
|
|
96
|
-
|
|
97
|
-
// Aggregation queries
|
|
98
|
-
const personCount = new QueryBuilder()
|
|
99
|
-
.count('?e')
|
|
100
|
-
.where({ entity: '?e', attribute: kw(':person/name'), value: '?name' })
|
|
101
|
-
.build();
|
|
102
|
-
|
|
103
|
-
// Multiple aggregations
|
|
104
|
-
const stats = new QueryBuilder()
|
|
105
|
-
.count('?e')
|
|
106
|
-
.avg('?age')
|
|
107
|
-
.where({ entity: '?e', attribute: kw(':person/name'), value: '?name' })
|
|
108
|
-
.where({ entity: '?e', attribute: kw(':person/age'), value: '?age' })
|
|
109
|
-
.build();
|
|
110
|
-
|
|
111
|
-
// Input parameters and with clauses
|
|
112
|
-
const parameterizedQuery = new QueryBuilder()
|
|
113
|
-
.find('?e')
|
|
114
|
-
.in('$', '?minAge')
|
|
115
|
-
.with('?tx')
|
|
116
|
-
.where({ entity: '?e', attribute: kw(':person/age'), value: '?age' })
|
|
117
|
-
.build();
|
|
118
|
-
|
|
119
|
-
// Direct execution
|
|
120
|
-
const results = await new QueryBuilder()
|
|
121
|
-
.find('?e', '?name')
|
|
122
|
-
.entity('?e').hasAttribute(kw(':person/name')).withValue('?name')
|
|
123
|
-
.execute(db);
|
|
124
|
-
```
|
|
73
|
+
QueryBuilder has been removed in v2.
|
|
125
74
|
|
|
126
75
|
**QueryBuilder Benefits:**
|
|
76
|
+
|
|
127
77
|
- **Type Safety**: All attributes use proper `Keyword` objects with `kw()`
|
|
128
|
-
- **IntelliSense**: Full autocomplete for methods and parameters
|
|
78
|
+
- **IntelliSense**: Full autocomplete for methods and parameters
|
|
129
79
|
- **Structured Queries**: No string concatenation or EDN parsing errors
|
|
130
80
|
- **Fluent API**: Chain methods for readable query construction
|
|
131
81
|
- **Aggregations**: Built-in support for count, sum, avg, min, max
|
|
132
82
|
- **Direct Execution**: Execute queries directly from the builder
|
|
133
83
|
|
|
134
84
|
### Temporal Queries
|
|
85
|
+
|
|
135
86
|
```typescript
|
|
136
87
|
// As-of queries
|
|
137
|
-
const pastResults = await client.query(query, [
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
88
|
+
const pastResults = await client.query(query, [
|
|
89
|
+
{
|
|
90
|
+
"db/alias": "storage/db",
|
|
91
|
+
"as-of": 1000,
|
|
92
|
+
},
|
|
93
|
+
]);
|
|
141
94
|
|
|
142
|
-
// Since queries
|
|
143
|
-
const recentResults = await client.query(query, [
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
95
|
+
// Since queries
|
|
96
|
+
const recentResults = await client.query(query, [
|
|
97
|
+
{
|
|
98
|
+
"db/alias": "storage/db",
|
|
99
|
+
since: 1000,
|
|
100
|
+
},
|
|
101
|
+
]);
|
|
147
102
|
|
|
148
103
|
// History queries
|
|
149
|
-
const allHistory = await client.query(query, [
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
104
|
+
const allHistory = await client.query(query, [
|
|
105
|
+
{
|
|
106
|
+
"db/alias": "storage/db",
|
|
107
|
+
history: true,
|
|
108
|
+
},
|
|
109
|
+
]);
|
|
153
110
|
```
|
|
154
111
|
|
|
155
|
-
|
|
156
|
-
```typescript
|
|
157
|
-
import { SchemaBuilder, DatomicUtils } from '@anysoftinc/anydb-sdk';
|
|
158
|
-
|
|
159
|
-
// Define attributes
|
|
160
|
-
const personNameAttr = SchemaBuilder.attribute({
|
|
161
|
-
':db/ident': ':person/name',
|
|
162
|
-
':db/valueType': ':db.type/string',
|
|
163
|
-
':db/cardinality': ':db.cardinality/one',
|
|
164
|
-
':db/index': true,
|
|
165
|
-
':db/doc': 'Person name'
|
|
166
|
-
});
|
|
112
|
+
SchemaBuilder and DatomicUtils have been removed in v2. Use plain tx maps with keywordized keys and kw()/uuid() for values.
|
|
167
113
|
|
|
168
|
-
|
|
169
|
-
const genderEnum = SchemaBuilder.enum(':person.gender/male');
|
|
114
|
+
### Utility Functions
|
|
170
115
|
|
|
171
|
-
|
|
172
|
-
await db.transact([personNameAttr, genderEnum]);
|
|
173
|
-
```
|
|
116
|
+
Utility helpers for tempids and entity builders were removed in v2.
|
|
174
117
|
|
|
175
|
-
###
|
|
176
|
-
```typescript
|
|
177
|
-
import { DatomicUtils } from '@anysoftinc/anydb-sdk';
|
|
118
|
+
### Idempotent Schema Install
|
|
178
119
|
|
|
179
|
-
|
|
180
|
-
const tempId = DatomicUtils.tempId();
|
|
120
|
+
Use `ensureAttributes(db, schemaEntities)` to install attribute idents exactly once per database alias. It checks which idents already exist and only transacts the missing ones.
|
|
181
121
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
':person/name': 'Jane Doe',
|
|
185
|
-
':person/email': 'jane@example.com'
|
|
186
|
-
});
|
|
122
|
+
```ts
|
|
123
|
+
import { ensureAttributes, kw } from "@anysoftinc/anydb-sdk";
|
|
187
124
|
|
|
188
|
-
|
|
189
|
-
|
|
125
|
+
await ensureAttributes(db, [
|
|
126
|
+
{ "db/ident": kw("person/name"), "db/valueType": kw("db.type/string"), "db/cardinality": kw("db.cardinality/one") },
|
|
127
|
+
{ "db/ident": kw("person/age"), "db/valueType": kw("db.type/long"), "db/cardinality": kw("db.cardinality/one") },
|
|
128
|
+
]);
|
|
190
129
|
```
|
|
191
130
|
|
|
192
131
|
## Advanced Features
|
|
193
132
|
|
|
194
133
|
### EDN Data Types
|
|
134
|
+
|
|
195
135
|
The SDK provides full support for Datomic's EDN data types:
|
|
196
136
|
|
|
197
137
|
```typescript
|
|
198
|
-
import { sym, kw, uuid } from
|
|
138
|
+
import { sym, kw, uuid } from "@anysoftinc/anydb-sdk";
|
|
199
139
|
|
|
200
140
|
// Symbols for query variables
|
|
201
|
-
const entityVar = sym(
|
|
141
|
+
const entityVar = sym("?e");
|
|
202
142
|
|
|
203
143
|
// Keywords for attributes
|
|
204
|
-
const nameAttr = kw(
|
|
144
|
+
const nameAttr = kw("person/name");
|
|
205
145
|
|
|
206
146
|
// UUIDs
|
|
207
|
-
const entityId = uuid(
|
|
147
|
+
const entityId = uuid("550e8400-e29b-41d4-a716-446655440000");
|
|
208
148
|
```
|
|
209
149
|
|
|
210
150
|
### Event Streaming
|
|
151
|
+
|
|
211
152
|
Subscribe to transaction reports via Server-Sent Events:
|
|
212
153
|
|
|
213
154
|
```typescript
|
|
214
155
|
const eventSource = db.subscribeToEvents(
|
|
215
156
|
(event) => {
|
|
216
157
|
const txData = JSON.parse(event.data);
|
|
217
|
-
console.log(
|
|
158
|
+
console.log("Transaction:", txData);
|
|
218
159
|
},
|
|
219
160
|
(error) => {
|
|
220
|
-
console.error(
|
|
161
|
+
console.error("Connection error:", error);
|
|
221
162
|
}
|
|
222
163
|
);
|
|
223
164
|
|
|
@@ -226,41 +167,44 @@ eventSource.close();
|
|
|
226
167
|
```
|
|
227
168
|
|
|
228
169
|
### Raw Datom Queries
|
|
170
|
+
|
|
229
171
|
Access the raw datom index for high-performance queries:
|
|
230
172
|
|
|
231
173
|
```typescript
|
|
232
174
|
// Query EAVT index
|
|
233
|
-
const datoms = await db.datoms(
|
|
175
|
+
const datoms = await db.datoms("eavt", "-", {
|
|
234
176
|
e: 12345,
|
|
235
|
-
limit: 100
|
|
177
|
+
limit: 100,
|
|
236
178
|
});
|
|
237
179
|
|
|
238
180
|
// Query AVET index for attribute values
|
|
239
|
-
const attributeValues = await db.datoms(
|
|
240
|
-
a:
|
|
241
|
-
start:
|
|
242
|
-
end:
|
|
181
|
+
const attributeValues = await db.datoms("avet", "-", {
|
|
182
|
+
a: ":person/name",
|
|
183
|
+
start: "A",
|
|
184
|
+
end: "B",
|
|
243
185
|
});
|
|
244
186
|
```
|
|
245
187
|
|
|
246
188
|
### Custom HTTP Configuration
|
|
189
|
+
|
|
247
190
|
```typescript
|
|
248
191
|
const client = new DatomicClient({
|
|
249
|
-
baseUrl:
|
|
192
|
+
baseUrl: "https://api.example.com",
|
|
250
193
|
timeout: 30000,
|
|
251
194
|
headers: {
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
}
|
|
195
|
+
Authorization: "Bearer token",
|
|
196
|
+
"X-Custom-Header": "value",
|
|
197
|
+
},
|
|
255
198
|
});
|
|
256
199
|
```
|
|
257
200
|
|
|
258
201
|
### NextAuth.js Integration
|
|
202
|
+
|
|
259
203
|
The SDK includes a NextAuth.js adapter for authentication:
|
|
260
204
|
|
|
261
205
|
```typescript
|
|
262
|
-
import { AnyDBAdapter } from
|
|
263
|
-
import NextAuth from
|
|
206
|
+
import { AnyDBAdapter } from "@anysoftinc/anydb-sdk/nextauth-adapter";
|
|
207
|
+
import NextAuth from "next-auth";
|
|
264
208
|
|
|
265
209
|
export default NextAuth({
|
|
266
210
|
adapter: AnyDBAdapter(db),
|
|
@@ -278,10 +222,10 @@ The SDK provides detailed error information:
|
|
|
278
222
|
try {
|
|
279
223
|
const results = await db.query(invalidQuery);
|
|
280
224
|
} catch (error) {
|
|
281
|
-
if (error.message.includes(
|
|
282
|
-
console.error(
|
|
225
|
+
if (error.message.includes("Datomic API error")) {
|
|
226
|
+
console.error("Server error:", error.message);
|
|
283
227
|
} else {
|
|
284
|
-
console.error(
|
|
228
|
+
console.error("Client error:", error);
|
|
285
229
|
}
|
|
286
230
|
}
|
|
287
231
|
```
|
|
@@ -291,17 +235,17 @@ try {
|
|
|
291
235
|
Full TypeScript definitions are included:
|
|
292
236
|
|
|
293
237
|
```typescript
|
|
294
|
-
import type {
|
|
295
|
-
QueryResult,
|
|
296
|
-
Transaction,
|
|
297
|
-
Entity,
|
|
238
|
+
import type {
|
|
239
|
+
QueryResult,
|
|
240
|
+
Transaction,
|
|
241
|
+
Entity,
|
|
298
242
|
Datom,
|
|
299
|
-
DatabaseDescriptor
|
|
300
|
-
} from
|
|
243
|
+
DatabaseDescriptor,
|
|
244
|
+
} from "@anysoftinc/anydb-sdk";
|
|
301
245
|
|
|
302
246
|
const processResults = (results: QueryResult): void => {
|
|
303
|
-
results.forEach(row => {
|
|
304
|
-
console.log(
|
|
247
|
+
results.forEach((row) => {
|
|
248
|
+
console.log("Row:", row);
|
|
305
249
|
});
|
|
306
250
|
};
|
|
307
251
|
```
|
|
@@ -316,21 +260,14 @@ See the [examples directory](./examples/) for complete working examples:
|
|
|
316
260
|
## API Reference
|
|
317
261
|
|
|
318
262
|
### DatomicClient
|
|
319
|
-
The main client class for interacting with the AnyDB server.
|
|
320
|
-
|
|
321
|
-
### DatomicDatabase
|
|
322
|
-
Convenience wrapper for working with a specific database.
|
|
323
263
|
|
|
324
|
-
|
|
325
|
-
Static utility methods for common Datomic operations.
|
|
264
|
+
The main client class for interacting with the AnyDB server.
|
|
326
265
|
|
|
327
|
-
###
|
|
328
|
-
Helper for building schema definitions.
|
|
266
|
+
### AnyDBClient
|
|
329
267
|
|
|
330
|
-
|
|
331
|
-
Fluent API for constructing queries programmatically.
|
|
268
|
+
Convenience wrapper for working with a specific database.
|
|
332
269
|
|
|
333
270
|
## Related
|
|
334
271
|
|
|
335
272
|
- [AnyDB Server](../../..) - Backend Clojure implementation
|
|
336
|
-
- [Datomic Documentation](https://docs.datomic.com/) - Official Datomic docs
|
|
273
|
+
- [Datomic Documentation](https://docs.datomic.com/) - Official Datomic docs
|