chain-db-ts 1.0.0-rc.2 → 1.0.0-rc.4
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/.nvmrc +1 -0
- package/CHANGELOG.md +6 -0
- package/dist/cjs/features/chain-db.d.ts +8 -2
- package/dist/cjs/features/chain-db.js +40 -35
- package/dist/cjs/features/table-doc.js +5 -7
- package/dist/cjs/features/table.d.ts +49 -19
- package/dist/cjs/features/table.js +131 -65
- package/dist/cjs/features/types.d.ts +5 -0
- package/dist/cjs/features/utils.d.ts +2 -1
- package/dist/cjs/features/utils.js +9 -1
- package/dist/cjs/index.d.ts +2 -1
- package/dist/cjs/index.js +4 -1
- package/features/chain-db.d.ts +8 -2
- package/features/chain-db.js +38 -34
- package/features/table-doc.js +6 -5
- package/features/table.d.ts +49 -19
- package/features/table.js +132 -63
- package/features/types.d.ts +5 -0
- package/features/utils.d.ts +2 -1
- package/features/utils.js +7 -0
- package/index.d.ts +2 -1
- package/index.js +2 -1
- package/package.json +1 -1
- package/readme.md +66 -162
package/readme.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# Chain DB
|
|
1
|
+
# Chain DB TS / JS Client (Node)
|
|
2
2
|
|
|
3
|
-
A TypeScript client for [Chain DB](https://github.com/wpdas/chain-db), a
|
|
3
|
+
A TypeScript / JavaScript client for [Chain DB](https://github.com/wpdas/chain-db), a secure database system with built-in history tracking, offering AES-256-GCM encryption, atomic operations with rollback capability, and automatic backups.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -14,10 +14,12 @@ yarn add chain-db-ts
|
|
|
14
14
|
|
|
15
15
|
### Connecting to Chain DB
|
|
16
16
|
|
|
17
|
+
#### Asynchronously
|
|
18
|
+
|
|
17
19
|
```typescript
|
|
18
20
|
import { connect } from 'chain-db-ts'
|
|
19
21
|
|
|
20
|
-
// Connect to Chain DB
|
|
22
|
+
// Connect to Chain DB async
|
|
21
23
|
// Parameters: server | database | user | password
|
|
22
24
|
// If the server parameter is null, "http://localhost:2818" will be used as default
|
|
23
25
|
const db = await connect({
|
|
@@ -28,107 +30,99 @@ const db = await connect({
|
|
|
28
30
|
})
|
|
29
31
|
```
|
|
30
32
|
|
|
33
|
+
#### Synchronously
|
|
34
|
+
|
|
35
|
+
This is better if you don't want to configure a connection using Promise, which can block the initialization of the application.
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
import { connectWithToken } from 'chain-db-ts'
|
|
39
|
+
|
|
40
|
+
// Connect to Chain DB sync
|
|
41
|
+
// Parameters: server | database | token
|
|
42
|
+
// If the server parameter is null, "http://localhost:2818" will be used as default
|
|
43
|
+
const db = connectWithToken({
|
|
44
|
+
server: 'http://localhost:2818',
|
|
45
|
+
database: 'my-database',
|
|
46
|
+
// Go to https://github.com/wpdas/chain-db?tab=readme-ov-file#authentication to understand how to get this token
|
|
47
|
+
token: 'dGVzdF9kYjpyb290OjEyMzQ=',
|
|
48
|
+
})
|
|
49
|
+
```
|
|
50
|
+
|
|
31
51
|
### Working with Tables
|
|
32
52
|
|
|
33
|
-
Define your table structure using TypeScript interfaces:
|
|
53
|
+
Define your table structure using TypeScript interfaces or types:
|
|
34
54
|
|
|
35
55
|
```typescript
|
|
36
|
-
// Define your table
|
|
56
|
+
// Define your table schema
|
|
37
57
|
interface GreetingTable {
|
|
38
58
|
greeting: string
|
|
39
59
|
}
|
|
40
60
|
|
|
41
|
-
// Define a more complex table
|
|
61
|
+
// Define a more complex table schema
|
|
42
62
|
interface UserTable {
|
|
43
63
|
id: number
|
|
44
64
|
name: string
|
|
45
65
|
email: string
|
|
46
66
|
active: boolean
|
|
47
67
|
createdAt: string
|
|
68
|
+
address: {...}
|
|
48
69
|
}
|
|
49
70
|
```
|
|
50
71
|
|
|
51
|
-
###
|
|
72
|
+
### Create
|
|
52
73
|
|
|
53
74
|
```typescript
|
|
54
|
-
//
|
|
55
|
-
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
//
|
|
59
|
-
|
|
75
|
+
// Table Instances
|
|
76
|
+
const Greeting = db.getTable<GreetingTable>('greetings') // where "greetings" is the table name
|
|
77
|
+
const User = db.getTable<UserTable>('users') // where "users" is the table name
|
|
78
|
+
|
|
79
|
+
// Creates and stores new data into greetings table and returns its content
|
|
80
|
+
const newGreeting = await Greeting.new({ greeting: "Hello" })
|
|
81
|
+
// newGreeting.doc => { doc_id: "xyz123", greeting: "Hello" }
|
|
82
|
+
// newGreeting.getTableName() => "greetings"
|
|
83
|
+
// newGreeting.isEmpty() => true / false
|
|
84
|
+
// await newGreeting.refetch() => Fetch updated content. This is useful when the data has been changed elsewhere.
|
|
85
|
+
// await newGreeting.update() => Should be called when you change the newGreeting.doc body
|
|
60
86
|
```
|
|
61
87
|
|
|
62
|
-
###
|
|
88
|
+
### Get
|
|
63
89
|
|
|
64
90
|
```typescript
|
|
65
|
-
//
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
// Persist changes to database (creates a new record with a new doc_id)
|
|
69
|
-
const result = await greetingTable.persist()
|
|
70
|
-
|
|
71
|
-
// The persist method returns the created document with its doc_id
|
|
72
|
-
console.log(result.doc_id) // e.g., '550e8400-e29b-41d4-a716-446655440000'
|
|
73
|
-
|
|
74
|
-
// You can also access the current document's ID directly
|
|
75
|
-
const currentDocId = greetingTable.getCurrentDocId()
|
|
76
|
-
console.log(currentDocId) // Same as result.doc_id
|
|
77
|
-
```
|
|
91
|
+
// Get the last register
|
|
92
|
+
const greeting = await Greeting.last();
|
|
93
|
+
console.log(greeting.doc) // e.g., { doc_id: "550e8400-e29b-41d4-a716-446655440000", greeting: "Hello" }
|
|
78
94
|
|
|
79
|
-
|
|
95
|
+
// OR
|
|
80
96
|
|
|
81
|
-
|
|
82
|
-
// To update a specific document, first get it by ID
|
|
97
|
+
// Get by doc id
|
|
83
98
|
const docId = '550e8400-e29b-41d4-a716-446655440000'
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
// Then update its data
|
|
87
|
-
specificDoc.doc.greeting = 'Updated greeting'
|
|
88
|
-
await specificDoc.update()
|
|
99
|
+
const specificGreeting = await Greeting.getByDocId(docId)
|
|
100
|
+
console.log(specificGreeting.doc) // e.g., { doc_id: "550e8400-e29b-41d4-a716-446655440000", greeting: "Hello" }
|
|
89
101
|
```
|
|
90
102
|
|
|
91
|
-
###
|
|
103
|
+
### Updating Item
|
|
92
104
|
|
|
93
105
|
```typescript
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
const docId = '550e8400-e29b-41d4-a716-446655440000' // Example ID
|
|
97
|
-
const specificDoc = await greetingTable.getDoc(docId)
|
|
98
|
-
|
|
99
|
-
// Access the document data
|
|
100
|
-
console.log(specificDoc.doc) // e.g., { greeting: 'Hello from specific doc', doc_id: '550e8400-e29b-41d4-a716-446655440000' }
|
|
101
|
-
|
|
102
|
-
// The doc_id is also available directly in the document object
|
|
103
|
-
console.log(specificDoc.doc.doc_id) // '550e8400-e29b-41d4-a716-446655440000'
|
|
104
|
-
|
|
105
|
-
// Update the specific document
|
|
106
|
-
specificDoc.doc.greeting = 'Updated greeting for specific doc'
|
|
107
|
-
await specificDoc.update() // Updates only this specific document
|
|
108
|
-
|
|
109
|
-
// Refetch the document data if it might have been updated elsewhere
|
|
110
|
-
await specificDoc.refetch()
|
|
111
|
-
console.log(specificDoc.doc) // Updated data from the database
|
|
112
|
-
|
|
113
|
-
// Get the table name this document belongs to
|
|
114
|
-
const tableName = specificDoc.getTableName() // 'greeting'
|
|
106
|
+
greeting.doc = { greeting: "Olá Mundo!" }; // OR greeting.doc.greeting = "Olá Mundo!"
|
|
107
|
+
await greeting.update()
|
|
115
108
|
```
|
|
116
109
|
|
|
117
|
-
Note: The `TableDoc` instance returned by `
|
|
110
|
+
<!-- Note: The `TableDoc` instance returned by `getByDocId()` is a simplified version of a table that only allows updating the specific document. -->
|
|
118
111
|
|
|
119
112
|
### Getting Table History
|
|
120
113
|
|
|
121
114
|
```typescript
|
|
122
115
|
// Get the last 100 changes to the table
|
|
123
|
-
const history = await
|
|
124
|
-
|
|
116
|
+
const history = await Greeting.getHistory(100)
|
|
117
|
+
history.forEach(item => {
|
|
118
|
+
// Table data instance
|
|
119
|
+
console.log(item.doc);
|
|
120
|
+
});
|
|
125
121
|
// Example output:
|
|
126
|
-
//
|
|
127
|
-
//
|
|
128
|
-
//
|
|
129
|
-
//
|
|
130
|
-
// ...
|
|
131
|
-
// ]
|
|
122
|
+
// { greeting: 'Hello, Chain DB!' },
|
|
123
|
+
// { greeting: 'Hello' },
|
|
124
|
+
// { greeting: 'Hi there' },
|
|
125
|
+
// ...
|
|
132
126
|
```
|
|
133
127
|
|
|
134
128
|
### Real-time Events with WebSockets
|
|
@@ -140,14 +134,14 @@ import { EventTypes, EventData } from 'chain-db-ts'
|
|
|
140
134
|
|
|
141
135
|
// Subscribe to table update events
|
|
142
136
|
db.events().subscribe(EventTypes.TABLE_UPDATE, (eventData: EventData) => {
|
|
143
|
-
console.log('Table updated:', eventData.table)
|
|
144
|
-
console.log('New data:', eventData.data)
|
|
137
|
+
console.log('Table updated:', eventData.table) // e.g. greetings
|
|
138
|
+
console.log('New data:', eventData.data) // e.g. { greeting: "Hello World!" }
|
|
145
139
|
})
|
|
146
140
|
|
|
147
141
|
// Subscribe to new data persistence events
|
|
148
142
|
db.events().subscribe(EventTypes.TABLE_PERSIST, (eventData: EventData) => {
|
|
149
|
-
console.log('New data added to table:', eventData.table)
|
|
150
|
-
console.log('Data:', eventData.data)
|
|
143
|
+
console.log('New data added to table:', eventData.table) // e.g. greetings
|
|
144
|
+
console.log('Data:', eventData.data) // e.g. { greeting: "Hello World!" }
|
|
151
145
|
})
|
|
152
146
|
|
|
153
147
|
// Unsubscribe from an event
|
|
@@ -176,7 +170,7 @@ The `EventData` object contains:
|
|
|
176
170
|
|
|
177
171
|
```typescript
|
|
178
172
|
// Find items with exact matches
|
|
179
|
-
const users = await
|
|
173
|
+
const users = await User.findWhere(
|
|
180
174
|
{ active: true, name: 'John' }, // criteria
|
|
181
175
|
10, // limit (default: 1000)
|
|
182
176
|
true // reverse order (default: true)
|
|
@@ -189,7 +183,7 @@ const users = await userTable.findWhere(
|
|
|
189
183
|
import { Operators } from 'chain-db-ts'
|
|
190
184
|
|
|
191
185
|
// Find items with advanced criteria
|
|
192
|
-
const users = await
|
|
186
|
+
const users = await User.findWhereAdvanced(
|
|
193
187
|
[
|
|
194
188
|
{
|
|
195
189
|
field: 'name',
|
|
@@ -219,96 +213,6 @@ Available operators:
|
|
|
219
213
|
- `STARTS_WITH` (for strings)
|
|
220
214
|
- `ENDS_WITH` (for strings)
|
|
221
215
|
|
|
222
|
-
### Other Table Methods
|
|
223
|
-
|
|
224
|
-
```typescript
|
|
225
|
-
// Check if a table is empty
|
|
226
|
-
const isEmpty = greetingTable.isEmpty()
|
|
227
|
-
|
|
228
|
-
// Get the table name
|
|
229
|
-
const tableName = greetingTable.getName()
|
|
230
|
-
|
|
231
|
-
// Refetch the table data from the database
|
|
232
|
-
await greetingTable.refetch()
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
## Complete Example
|
|
236
|
-
|
|
237
|
-
```typescript
|
|
238
|
-
import { connect, EventTypes, EventData } from 'chain-db-ts'
|
|
239
|
-
|
|
240
|
-
// Define table structure
|
|
241
|
-
interface GreetingTable {
|
|
242
|
-
greeting: string
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
async function main() {
|
|
246
|
-
// Connect to Chain DB
|
|
247
|
-
const db = await connect({
|
|
248
|
-
server: 'http://localhost:2818',
|
|
249
|
-
database: 'test-db',
|
|
250
|
-
user: 'root',
|
|
251
|
-
password: '1234',
|
|
252
|
-
})
|
|
253
|
-
|
|
254
|
-
// Get the "greeting" table
|
|
255
|
-
const greetingTable = await db.getTable<GreetingTable>('greeting')
|
|
256
|
-
console.log(greetingTable.currentDoc) // e.g., { greeting: 'Hi' }
|
|
257
|
-
|
|
258
|
-
// Subscribe to table update events
|
|
259
|
-
db.events().subscribe(EventTypes.TABLE_UPDATE, (eventData: EventData) => {
|
|
260
|
-
if (eventData.table === 'greeting') {
|
|
261
|
-
console.log('Greeting table updated:', eventData.data)
|
|
262
|
-
}
|
|
263
|
-
})
|
|
264
|
-
|
|
265
|
-
// Modify and persist data
|
|
266
|
-
greetingTable.currentDoc.greeting = 'Hello my dear!'
|
|
267
|
-
const persistResult = await greetingTable.persist() // Data is persisted on database
|
|
268
|
-
|
|
269
|
-
// Get the doc_id of the newly created document
|
|
270
|
-
console.log('New document ID:', persistResult.doc_id)
|
|
271
|
-
|
|
272
|
-
// You can also get the current document ID directly from the table
|
|
273
|
-
const currentDocId = greetingTable.getCurrentDocId()
|
|
274
|
-
console.log('Current document ID:', currentDocId)
|
|
275
|
-
|
|
276
|
-
// See the updated values
|
|
277
|
-
console.log(greetingTable.currentDoc) // { greeting: 'Hello my dear!', doc_id: '...' }
|
|
278
|
-
|
|
279
|
-
// Get a specific document by its ID
|
|
280
|
-
// We can use the ID we just got from the persist operation
|
|
281
|
-
const specificDoc = await greetingTable.getDoc(currentDocId)
|
|
282
|
-
|
|
283
|
-
// Access the document data and ID
|
|
284
|
-
console.log(specificDoc.doc) // { greeting: 'Hello my dear!', doc_id: '...' }
|
|
285
|
-
console.log(specificDoc.doc.doc_id) // Same as currentDocId
|
|
286
|
-
|
|
287
|
-
// Update a specific document
|
|
288
|
-
specificDoc.doc.greeting = 'Updated specific document'
|
|
289
|
-
await specificDoc.update() // Updates only this specific document
|
|
290
|
-
|
|
291
|
-
// Refetch the document to get the latest data
|
|
292
|
-
await specificDoc.refetch()
|
|
293
|
-
console.log(specificDoc.doc) // Latest data from the database
|
|
294
|
-
|
|
295
|
-
// Get the last 100 changes
|
|
296
|
-
const greetingHistory = await greetingTable.getHistory(100)
|
|
297
|
-
console.log(greetingHistory)
|
|
298
|
-
// [
|
|
299
|
-
// { greeting: 'Updated specific document' },
|
|
300
|
-
// { greeting: 'Hello my dear!' },
|
|
301
|
-
// { greeting: 'Hi' },
|
|
302
|
-
// ...
|
|
303
|
-
// ]
|
|
304
|
-
|
|
305
|
-
// Close WebSocket connection when done
|
|
306
|
-
db.events().closeEvents()
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
main().catch(console.error)
|
|
310
|
-
```
|
|
311
|
-
|
|
312
216
|
## License
|
|
313
217
|
|
|
314
218
|
MIT
|