boundlessdb 0.11.0 → 0.12.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/CHANGELOG.md +65 -0
- package/dist/event-store.d.ts +2 -2
- package/dist/event-store.js +2 -2
- package/dist/query-builder.d.ts +38 -60
- package/dist/query-builder.d.ts.map +1 -1
- package/dist/query-builder.js +61 -102
- package/dist/query-builder.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,71 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to BoundlessDB will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.12.0] - 2026-03-05
|
|
6
|
+
|
|
7
|
+
### Changed (Breaking)
|
|
8
|
+
|
|
9
|
+
#### Flat query API — `matchKeys()` and `matchTypeAndKeys()`
|
|
10
|
+
|
|
11
|
+
The nested `.andKey()` chaining is replaced by flat top-level methods where AND-keys are passed as an object. Each top-level call now represents exactly one DCB QueryItem.
|
|
12
|
+
|
|
13
|
+
**Before:**
|
|
14
|
+
```typescript
|
|
15
|
+
store.query()
|
|
16
|
+
.matchType('StudentSubscribed')
|
|
17
|
+
.andKey('course', 'cs101')
|
|
18
|
+
.andKey('student', 'alice')
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
**After:**
|
|
22
|
+
```typescript
|
|
23
|
+
store.query()
|
|
24
|
+
.matchTypeAndKeys('StudentSubscribed', { course: 'cs101', student: 'alice' })
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**New API:**
|
|
28
|
+
```typescript
|
|
29
|
+
// Key-only query
|
|
30
|
+
.matchKeys({ course: 'cs101' })
|
|
31
|
+
.matchKeys({ course: 'cs101', student: 'alice' }) // AND within
|
|
32
|
+
|
|
33
|
+
// Type + keys
|
|
34
|
+
.matchTypeAndKeys('StudentSubscribed', { course: 'cs101' })
|
|
35
|
+
.matchTypeAndKeys('StudentSubscribed', { course: 'cs101', student: 'alice' })
|
|
36
|
+
|
|
37
|
+
// Type-only (unchanged)
|
|
38
|
+
.matchType('CourseCreated')
|
|
39
|
+
.matchType('CourseCreated', 'CourseCancelled')
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
#### Removed
|
|
43
|
+
- `matchKey(key, value)` — use `matchKeys({ key: value })` instead
|
|
44
|
+
- `andKey(key, value)` — no longer needed
|
|
45
|
+
|
|
46
|
+
#### Deprecated
|
|
47
|
+
- `matchTypeAndKey(type, key, value)` — kept as alias, use `matchTypeAndKeys()` instead
|
|
48
|
+
|
|
49
|
+
## [0.11.0] - 2026-03-02
|
|
50
|
+
|
|
51
|
+
### Added
|
|
52
|
+
|
|
53
|
+
#### `backwards()` query
|
|
54
|
+
|
|
55
|
+
Read events in reverse order (newest first). Useful with `.limit()` to get the last N events efficiently:
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
const result = await store.all().backwards().limit(100).read();
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
All 4 storage engines supported: SQLite, PostgreSQL, SqlJs, InMemory.
|
|
62
|
+
|
|
63
|
+
#### Demo UI improvements
|
|
64
|
+
|
|
65
|
+
- **Config editor:** Edit consistency config and reindex live
|
|
66
|
+
- **Live Query builder:** Mirrors the fluent API with `matchType` and `matchKey` blocks, plus AND-key chaining
|
|
67
|
+
- **Key-only queries** in Live Query (leave Type empty)
|
|
68
|
+
- Debug panel hidden by default (accessible via `showDebug()` in console)
|
|
69
|
+
|
|
5
70
|
## [0.10.0] - 2026-03-01
|
|
6
71
|
|
|
7
72
|
### Added
|
package/dist/event-store.d.ts
CHANGED
|
@@ -34,7 +34,7 @@ export declare class EventStore {
|
|
|
34
34
|
* ```typescript
|
|
35
35
|
* const result = await store.query<CourseEvent>()
|
|
36
36
|
* .matchType('CourseCreated')
|
|
37
|
-
* .
|
|
37
|
+
* .matchTypeAndKeys('StudentSubscribed', { course: 'cs101' })
|
|
38
38
|
* .fromPosition(100n)
|
|
39
39
|
* .limit(50)
|
|
40
40
|
* .read();
|
|
@@ -45,7 +45,7 @@ export declare class EventStore {
|
|
|
45
45
|
* Create a fluent query builder that reads all events (no type filter required).
|
|
46
46
|
*
|
|
47
47
|
* Returns the same QueryBuilder as `query()`, but does not require any
|
|
48
|
-
* `.matchType()` or `.
|
|
48
|
+
* `.matchType()` or `.matchTypeAndKeys()` calls before `.read()`.
|
|
49
49
|
* You can still use `.fromPosition()` and `.limit()` for pagination.
|
|
50
50
|
*
|
|
51
51
|
* @typeParam E - Event union type for typed results
|
package/dist/event-store.js
CHANGED
|
@@ -116,7 +116,7 @@ export class EventStore {
|
|
|
116
116
|
* ```typescript
|
|
117
117
|
* const result = await store.query<CourseEvent>()
|
|
118
118
|
* .matchType('CourseCreated')
|
|
119
|
-
* .
|
|
119
|
+
* .matchTypeAndKeys('StudentSubscribed', { course: 'cs101' })
|
|
120
120
|
* .fromPosition(100n)
|
|
121
121
|
* .limit(50)
|
|
122
122
|
* .read();
|
|
@@ -129,7 +129,7 @@ export class EventStore {
|
|
|
129
129
|
* Create a fluent query builder that reads all events (no type filter required).
|
|
130
130
|
*
|
|
131
131
|
* Returns the same QueryBuilder as `query()`, but does not require any
|
|
132
|
-
* `.matchType()` or `.
|
|
132
|
+
* `.matchType()` or `.matchTypeAndKeys()` calls before `.read()`.
|
|
133
133
|
* You can still use `.fromPosition()` and `.limit()` for pagination.
|
|
134
134
|
*
|
|
135
135
|
* @typeParam E - Event union type for typed results
|
package/dist/query-builder.d.ts
CHANGED
|
@@ -13,27 +13,29 @@ export interface QueryExecutor<E extends Event> {
|
|
|
13
13
|
/**
|
|
14
14
|
* Fluent API for building queries.
|
|
15
15
|
*
|
|
16
|
+
* Each top-level call adds one QueryItem (OR between items).
|
|
17
|
+
* Keys within a single call are AND-combined.
|
|
18
|
+
*
|
|
16
19
|
* @example
|
|
17
20
|
* ```typescript
|
|
18
|
-
* //
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
21
|
+
* // Key-only query
|
|
22
|
+
* .matchKeys({ course: 'cs101' })
|
|
23
|
+
*
|
|
24
|
+
* // Key-only AND query
|
|
25
|
+
* .matchKeys({ course: 'cs101', student: 'alice' })
|
|
26
|
+
*
|
|
27
|
+
* // Type-only query
|
|
28
|
+
* .matchType('CourseCreated')
|
|
22
29
|
*
|
|
23
|
-
* //
|
|
24
|
-
*
|
|
25
|
-
* .matchType('StudentSubscribed')
|
|
26
|
-
* .andKey('course', 'cs101')
|
|
27
|
-
* .andKey('student', 'alice')
|
|
28
|
-
* .read();
|
|
30
|
+
* // Multiple types (OR within item)
|
|
31
|
+
* .matchType('CourseCreated', 'CourseCancelled')
|
|
29
32
|
*
|
|
30
|
-
* //
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
* .read();
|
|
33
|
+
* // Type + keys (AND within item)
|
|
34
|
+
* .matchTypeAndKeys('StudentSubscribed', { course: 'cs101' })
|
|
35
|
+
*
|
|
36
|
+
* // OR between items
|
|
37
|
+
* .matchTypeAndKeys('StudentSubscribed', { course: 'cs101' })
|
|
38
|
+
* .matchKeys({ student: 'alice' })
|
|
37
39
|
* ```
|
|
38
40
|
*/
|
|
39
41
|
export declare class QueryBuilder<E extends Event> {
|
|
@@ -44,81 +46,57 @@ export declare class QueryBuilder<E extends Event> {
|
|
|
44
46
|
private _backwards;
|
|
45
47
|
constructor(executor: QueryExecutor<E>);
|
|
46
48
|
/**
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
+
* Match events by key(s). All keys must match (AND).
|
|
50
|
+
* Starts a new query item (OR with previous items).
|
|
49
51
|
*
|
|
50
52
|
* @example
|
|
51
53
|
* ```typescript
|
|
52
|
-
* .
|
|
53
|
-
* .
|
|
54
|
-
* .matchType('StudentSubscribed').andKey('course', 'cs101') // type + key
|
|
54
|
+
* .matchKeys({ course: 'cs101' })
|
|
55
|
+
* .matchKeys({ course: 'cs101', student: 'alice' }) // AND
|
|
55
56
|
* ```
|
|
56
57
|
*/
|
|
57
|
-
|
|
58
|
+
matchKeys(keys: Record<string, string>): this;
|
|
58
59
|
/**
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
* Use `.andKey()` after to add more key constraints (AND).
|
|
60
|
+
* Match events of one or more types (OR within item).
|
|
61
|
+
* Starts a new query item (OR with previous items).
|
|
62
62
|
*
|
|
63
63
|
* @example
|
|
64
64
|
* ```typescript
|
|
65
|
-
* .
|
|
66
|
-
* .
|
|
65
|
+
* .matchType('CourseCreated')
|
|
66
|
+
* .matchType('CourseCreated', 'CourseCancelled')
|
|
67
67
|
* ```
|
|
68
68
|
*/
|
|
69
|
-
|
|
69
|
+
matchType(...types: string[]): this;
|
|
70
70
|
/**
|
|
71
|
-
*
|
|
72
|
-
* Starts a new
|
|
73
|
-
* Use `.andKey()` after to add more key constraints (AND).
|
|
71
|
+
* Match events of a given type where all keys match (AND).
|
|
72
|
+
* Starts a new query item (OR with previous items).
|
|
74
73
|
*
|
|
75
74
|
* @example
|
|
76
75
|
* ```typescript
|
|
77
|
-
* .
|
|
78
|
-
* .
|
|
76
|
+
* .matchTypeAndKeys('StudentSubscribed', { course: 'cs101' })
|
|
77
|
+
* .matchTypeAndKeys('StudentSubscribed', { course: 'cs101', student: 'alice' })
|
|
79
78
|
* ```
|
|
80
79
|
*/
|
|
81
|
-
|
|
80
|
+
matchTypeAndKeys(type: string, keys: Record<string, string>): this;
|
|
82
81
|
/**
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
* @throws Error if no preceding condition exists
|
|
87
|
-
*
|
|
88
|
-
* @example
|
|
89
|
-
* ```typescript
|
|
90
|
-
* .matchType('StudentSubscribed')
|
|
91
|
-
* .andKey('course', 'cs101')
|
|
92
|
-
* .andKey('student', 'alice') // AND: both keys must match
|
|
93
|
-
* ```
|
|
82
|
+
* Shorthand for `.matchTypeAndKeys(type, { key: value })`.
|
|
83
|
+
* @deprecated Use `.matchTypeAndKeys(type, { key: value })` instead.
|
|
94
84
|
*/
|
|
95
|
-
|
|
85
|
+
matchTypeAndKey(type: string, key: string, value: string): this;
|
|
96
86
|
/**
|
|
97
87
|
* Start reading from a specific position.
|
|
98
|
-
*
|
|
99
|
-
* @example
|
|
100
|
-
* ```typescript
|
|
101
|
-
* .fromPosition(100n) // skip events before position 100
|
|
102
|
-
* ```
|
|
103
88
|
*/
|
|
104
89
|
fromPosition(position: bigint): this;
|
|
105
90
|
/**
|
|
106
91
|
* Limit the number of events returned.
|
|
107
|
-
*
|
|
108
|
-
* @example
|
|
109
|
-
* ```typescript
|
|
110
|
-
* .limit(50) // return at most 50 events
|
|
111
|
-
* ```
|
|
112
92
|
*/
|
|
113
93
|
limit(count: number): this;
|
|
114
94
|
/**
|
|
115
95
|
* Read events in reverse order (newest first).
|
|
116
|
-
* Useful with `.limit()` to get the last N events.
|
|
117
96
|
*
|
|
118
97
|
* @example
|
|
119
98
|
* ```typescript
|
|
120
|
-
*
|
|
121
|
-
* const result = await store.all().backwards().limit(100).read();
|
|
99
|
+
* await store.all().backwards().limit(100).read();
|
|
122
100
|
* ```
|
|
123
101
|
*/
|
|
124
102
|
backwards(): this;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query-builder.d.ts","sourceRoot":"","sources":["../src/query-builder.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,WAAW,EAAsE,MAAM,YAAY,CAAC;AAEzI,MAAM,WAAW,aAAa,CAAC,CAAC,SAAS,KAAK;IAC5C,IAAI,CAAC,KAAK,EAAE;QACV,UAAU,EAAE,cAAc,EAAE,CAAC;QAC7B,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,SAAS,CAAC,EAAE,OAAO,CAAC;KACrB,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;CAC7B;AAED
|
|
1
|
+
{"version":3,"file":"query-builder.d.ts","sourceRoot":"","sources":["../src/query-builder.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,WAAW,EAAsE,MAAM,YAAY,CAAC;AAEzI,MAAM,WAAW,aAAa,CAAC,CAAC,SAAS,KAAK;IAC5C,IAAI,CAAC,KAAK,EAAE;QACV,UAAU,EAAE,cAAc,EAAE,CAAC;QAC7B,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,SAAS,CAAC,EAAE,OAAO,CAAC;KACrB,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,qBAAa,YAAY,CAAC,CAAC,SAAS,KAAK;IAM3B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IALrC,OAAO,CAAC,UAAU,CAAwB;IAC1C,OAAO,CAAC,aAAa,CAAC,CAAS;IAC/B,OAAO,CAAC,MAAM,CAAC,CAAS;IACxB,OAAO,CAAC,UAAU,CAAS;gBAEE,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC;IAEvD;;;;;;;;;OASG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAW7C;;;;;;;;;OASG;IACH,SAAS,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI;IAYnC;;;;;;;;;OASG;IACH,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAYlE;;;OAGG;IACH,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAI/D;;OAEG;IACH,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAKpC;;OAEG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAK1B;;;;;;;OAOG;IACH,SAAS,IAAI,IAAI;IAKjB;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;CAQtC"}
|
package/dist/query-builder.js
CHANGED
|
@@ -4,27 +4,29 @@
|
|
|
4
4
|
/**
|
|
5
5
|
* Fluent API for building queries.
|
|
6
6
|
*
|
|
7
|
+
* Each top-level call adds one QueryItem (OR between items).
|
|
8
|
+
* Keys within a single call are AND-combined.
|
|
9
|
+
*
|
|
7
10
|
* @example
|
|
8
11
|
* ```typescript
|
|
9
|
-
* //
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
12
|
+
* // Key-only query
|
|
13
|
+
* .matchKeys({ course: 'cs101' })
|
|
14
|
+
*
|
|
15
|
+
* // Key-only AND query
|
|
16
|
+
* .matchKeys({ course: 'cs101', student: 'alice' })
|
|
17
|
+
*
|
|
18
|
+
* // Type-only query
|
|
19
|
+
* .matchType('CourseCreated')
|
|
13
20
|
*
|
|
14
|
-
* //
|
|
15
|
-
*
|
|
16
|
-
* .matchType('StudentSubscribed')
|
|
17
|
-
* .andKey('course', 'cs101')
|
|
18
|
-
* .andKey('student', 'alice')
|
|
19
|
-
* .read();
|
|
21
|
+
* // Multiple types (OR within item)
|
|
22
|
+
* .matchType('CourseCreated', 'CourseCancelled')
|
|
20
23
|
*
|
|
21
|
-
* //
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* .read();
|
|
24
|
+
* // Type + keys (AND within item)
|
|
25
|
+
* .matchTypeAndKeys('StudentSubscribed', { course: 'cs101' })
|
|
26
|
+
*
|
|
27
|
+
* // OR between items
|
|
28
|
+
* .matchTypeAndKeys('StudentSubscribed', { course: 'cs101' })
|
|
29
|
+
* .matchKeys({ student: 'alice' })
|
|
28
30
|
* ```
|
|
29
31
|
*/
|
|
30
32
|
export class QueryBuilder {
|
|
@@ -37,14 +39,33 @@ export class QueryBuilder {
|
|
|
37
39
|
this.executor = executor;
|
|
38
40
|
}
|
|
39
41
|
/**
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
+
* Match events by key(s). All keys must match (AND).
|
|
43
|
+
* Starts a new query item (OR with previous items).
|
|
42
44
|
*
|
|
43
45
|
* @example
|
|
44
46
|
* ```typescript
|
|
45
|
-
* .
|
|
46
|
-
* .
|
|
47
|
-
*
|
|
47
|
+
* .matchKeys({ course: 'cs101' })
|
|
48
|
+
* .matchKeys({ course: 'cs101', student: 'alice' }) // AND
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
matchKeys(keys) {
|
|
52
|
+
const entries = Object.entries(keys);
|
|
53
|
+
if (entries.length === 0) {
|
|
54
|
+
throw new Error('.matchKeys() requires at least one key');
|
|
55
|
+
}
|
|
56
|
+
this.conditions.push({
|
|
57
|
+
keys: entries.map(([name, value]) => ({ name, value })),
|
|
58
|
+
});
|
|
59
|
+
return this;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Match events of one or more types (OR within item).
|
|
63
|
+
* Starts a new query item (OR with previous items).
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```typescript
|
|
67
|
+
* .matchType('CourseCreated')
|
|
68
|
+
* .matchType('CourseCreated', 'CourseCancelled')
|
|
48
69
|
* ```
|
|
49
70
|
*/
|
|
50
71
|
matchType(...types) {
|
|
@@ -60,90 +81,35 @@ export class QueryBuilder {
|
|
|
60
81
|
return this;
|
|
61
82
|
}
|
|
62
83
|
/**
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
* Use `.andKey()` after to add more key constraints (AND).
|
|
66
|
-
*
|
|
67
|
-
* @example
|
|
68
|
-
* ```typescript
|
|
69
|
-
* .matchTypeAndKey('StudentSubscribed', 'course', 'cs101')
|
|
70
|
-
* .matchTypeAndKey('StudentSubscribed', 'course', 'cs101').andKey('student', 'alice')
|
|
71
|
-
* ```
|
|
72
|
-
*/
|
|
73
|
-
matchTypeAndKey(type, key, value) {
|
|
74
|
-
this.conditions.push({ type, keys: [{ name: key, value }] });
|
|
75
|
-
return this;
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Key-only query: match events by key, regardless of event type.
|
|
79
|
-
* Starts a new condition (OR with previous conditions).
|
|
80
|
-
* Use `.andKey()` after to add more key constraints (AND).
|
|
84
|
+
* Match events of a given type where all keys match (AND).
|
|
85
|
+
* Starts a new query item (OR with previous items).
|
|
81
86
|
*
|
|
82
87
|
* @example
|
|
83
88
|
* ```typescript
|
|
84
|
-
* .
|
|
85
|
-
* .
|
|
89
|
+
* .matchTypeAndKeys('StudentSubscribed', { course: 'cs101' })
|
|
90
|
+
* .matchTypeAndKeys('StudentSubscribed', { course: 'cs101', student: 'alice' })
|
|
86
91
|
* ```
|
|
87
92
|
*/
|
|
88
|
-
|
|
89
|
-
|
|
93
|
+
matchTypeAndKeys(type, keys) {
|
|
94
|
+
const entries = Object.entries(keys);
|
|
95
|
+
if (entries.length === 0) {
|
|
96
|
+
throw new Error('.matchTypeAndKeys() requires at least one key');
|
|
97
|
+
}
|
|
98
|
+
this.conditions.push({
|
|
99
|
+
type,
|
|
100
|
+
keys: entries.map(([name, value]) => ({ name, value })),
|
|
101
|
+
});
|
|
90
102
|
return this;
|
|
91
103
|
}
|
|
92
104
|
/**
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
* @throws Error if no preceding condition exists
|
|
97
|
-
*
|
|
98
|
-
* @example
|
|
99
|
-
* ```typescript
|
|
100
|
-
* .matchType('StudentSubscribed')
|
|
101
|
-
* .andKey('course', 'cs101')
|
|
102
|
-
* .andKey('student', 'alice') // AND: both keys must match
|
|
103
|
-
* ```
|
|
105
|
+
* Shorthand for `.matchTypeAndKeys(type, { key: value })`.
|
|
106
|
+
* @deprecated Use `.matchTypeAndKeys(type, { key: value })` instead.
|
|
104
107
|
*/
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
throw new Error('.andKey() requires a preceding .matchType(), .matchTypeAndKey(), or .matchKey()');
|
|
108
|
-
}
|
|
109
|
-
const lastIdx = this.conditions.length - 1;
|
|
110
|
-
const last = this.conditions[lastIdx];
|
|
111
|
-
// Convert the last condition to multi-key format if needed
|
|
112
|
-
if ('keys' in last && Array.isArray(last.keys)) {
|
|
113
|
-
// Already multi-key format — add to it
|
|
114
|
-
last.keys.push({ name: key, value });
|
|
115
|
-
}
|
|
116
|
-
else if ('key' in last && 'value' in last) {
|
|
117
|
-
// Legacy single-key format — convert to multi-key
|
|
118
|
-
const legacy = last;
|
|
119
|
-
this.conditions[lastIdx] = {
|
|
120
|
-
type: legacy.type,
|
|
121
|
-
keys: [{ name: legacy.key, value: legacy.value }, { name: key, value }],
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
else if ('types' in last) {
|
|
125
|
-
// Multi-type unconstrained — convert to multi-type constrained
|
|
126
|
-
this.conditions[lastIdx] = {
|
|
127
|
-
types: last.types,
|
|
128
|
-
keys: [{ name: key, value }],
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
else {
|
|
132
|
-
// Unconstrained (type only) — convert to multi-key
|
|
133
|
-
this.conditions[lastIdx] = {
|
|
134
|
-
type: last.type,
|
|
135
|
-
keys: [{ name: key, value }],
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
return this;
|
|
108
|
+
matchTypeAndKey(type, key, value) {
|
|
109
|
+
return this.matchTypeAndKeys(type, { [key]: value });
|
|
139
110
|
}
|
|
140
111
|
/**
|
|
141
112
|
* Start reading from a specific position.
|
|
142
|
-
*
|
|
143
|
-
* @example
|
|
144
|
-
* ```typescript
|
|
145
|
-
* .fromPosition(100n) // skip events before position 100
|
|
146
|
-
* ```
|
|
147
113
|
*/
|
|
148
114
|
fromPosition(position) {
|
|
149
115
|
this._fromPosition = position;
|
|
@@ -151,11 +117,6 @@ export class QueryBuilder {
|
|
|
151
117
|
}
|
|
152
118
|
/**
|
|
153
119
|
* Limit the number of events returned.
|
|
154
|
-
*
|
|
155
|
-
* @example
|
|
156
|
-
* ```typescript
|
|
157
|
-
* .limit(50) // return at most 50 events
|
|
158
|
-
* ```
|
|
159
120
|
*/
|
|
160
121
|
limit(count) {
|
|
161
122
|
this._limit = count;
|
|
@@ -163,12 +124,10 @@ export class QueryBuilder {
|
|
|
163
124
|
}
|
|
164
125
|
/**
|
|
165
126
|
* Read events in reverse order (newest first).
|
|
166
|
-
* Useful with `.limit()` to get the last N events.
|
|
167
127
|
*
|
|
168
128
|
* @example
|
|
169
129
|
* ```typescript
|
|
170
|
-
*
|
|
171
|
-
* const result = await store.all().backwards().limit(100).read();
|
|
130
|
+
* await store.all().backwards().limit(100).read();
|
|
172
131
|
* ```
|
|
173
132
|
*/
|
|
174
133
|
backwards() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query-builder.js","sourceRoot":"","sources":["../src/query-builder.ts"],"names":[],"mappings":"AAAA;;GAEG;AAaH
|
|
1
|
+
{"version":3,"file":"query-builder.js","sourceRoot":"","sources":["../src/query-builder.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED