@arkiv-network/sdk 0.6.8 → 0.7.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 +52 -16
- package/dist/chains/index.d.cts +25 -25
- package/dist/consts-AUoL-v42.cjs +18 -0
- package/dist/consts-BV4PR-de.js +7 -0
- package/dist/consts-BV4PR-de.js.map +1 -0
- package/dist/{query-CO6f35AE.d.cts → entity-B6g_EPm1.d.cts} +78 -31
- package/dist/entity-B6g_EPm1.d.cts.map +1 -0
- package/dist/{query-BhdmAzYg.d.ts → entity-qoLMAuuk.d.ts} +78 -31
- package/dist/entity-qoLMAuuk.d.ts.map +1 -0
- package/dist/index-DdspxNAA.d.ts +481 -0
- package/dist/index-DdspxNAA.d.ts.map +1 -0
- package/dist/index-Ds9dwqb5.d.cts +481 -0
- package/dist/index-Ds9dwqb5.d.cts.map +1 -0
- package/dist/index.cjs +63 -28
- package/dist/index.d.cts +90 -5
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +91 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +58 -21
- package/dist/index.js.map +1 -1
- package/dist/{payload-Da9gJMG5.d.ts → payload-B2kFJyah.d.ts} +1 -1
- package/dist/{payload-Da9gJMG5.d.ts.map → payload-B2kFJyah.d.ts.map} +1 -1
- package/dist/payload-Claf2jUO.js +13 -0
- package/dist/payload-Claf2jUO.js.map +1 -0
- package/dist/{payload-vwU3Rc6P.cjs → payload-DpA5PA-w.cjs} +0 -17
- package/dist/query/index.cjs +10 -28
- package/dist/query/index.d.cts +3 -3
- package/dist/query/index.d.ts +3 -3
- package/dist/query/index.js +7 -28
- package/dist/query/index.js.map +1 -1
- package/dist/{queryBuilder-DonAg1aq.js → queryBuilder-D2uwP9jI.js} +209 -89
- package/dist/queryBuilder-D2uwP9jI.js.map +1 -0
- package/dist/{queryBuilder-DM-YO1Y7.cjs → queryBuilder-UW2MCaX4.cjs} +237 -87
- package/dist/types/index.d.cts +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/utils/index.cjs +4 -10
- package/dist/utils/index.d.cts +0 -1
- package/dist/utils/index.d.cts.map +1 -1
- package/dist/utils/index.d.ts +1 -2
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +2 -3
- package/dist/utils/index.js.map +1 -1
- package/package.json +11 -15
- package/src/actions/public/buildQuery.ts +4 -0
- package/src/actions/public/query.ts +10 -0
- package/src/actions/wallet/createEntity.ts +12 -2
- package/src/actions/wallet/extendEntity.ts +6 -1
- package/src/actions/wallet/updateEntity.ts +12 -2
- package/src/clients/createPublicClient.test.ts +2 -0
- package/src/clients/decorators/arkivPublic.ts +67 -2
- package/src/clients/decorators/arkivWallet.ts +18 -0
- package/src/errors.ts +18 -0
- package/src/index.ts +0 -3
- package/src/query/engine.ts +22 -13
- package/src/query/index.ts +1 -0
- package/src/query/predicate.test.ts +43 -0
- package/src/query/predicate.ts +14 -10
- package/src/query/queryBuilder.test.ts +22 -0
- package/src/query/queryBuilder.ts +221 -106
- package/src/query/queryResult.ts +13 -7
- package/src/query/selectQueryBuilder.test.ts +210 -0
- package/src/query/selection.test.ts +120 -0
- package/src/query/selection.ts +116 -0
- package/src/types/attributes.ts +12 -0
- package/src/utils/arkivTransactions.test.ts +62 -0
- package/src/utils/arkivTransactions.ts +36 -27
- package/src/utils/index.ts +0 -1
- package/src/utils/validation.test.ts +60 -0
- package/src/utils/validation.ts +32 -0
- package/dist/accounts/index.cjs +0 -9
- package/dist/accounts/index.d.cts +0 -1
- package/dist/accounts/index.d.ts +0 -1
- package/dist/accounts/index.js +0 -1
- package/dist/payload-DKBYYjeA.js +0 -18
- package/dist/payload-DKBYYjeA.js.map +0 -1
- package/dist/query-BhdmAzYg.d.ts.map +0 -1
- package/dist/query-CO6f35AE.d.cts.map +0 -1
- package/dist/queryBuilder-BvoQXa_u.d.ts +0 -328
- package/dist/queryBuilder-BvoQXa_u.d.ts.map +0 -1
- package/dist/queryBuilder-DonAg1aq.js.map +0 -1
- package/dist/queryBuilder-zTsKXctT.d.cts +0 -328
- package/dist/queryBuilder-zTsKXctT.d.cts.map +0 -1
- package/src/accounts/index.ts +0 -1
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import type { Hex } from "viem"
|
|
2
2
|
import type { ArkivClient } from "../clients/baseClient"
|
|
3
|
-
import type {
|
|
3
|
+
import type { Entity } from "../types/entity"
|
|
4
|
+
import type { RpcEntity, RpcIncludeData, RpcOrderByAttribute } from "../types/rpcSchema"
|
|
4
5
|
import { entityFromRpcResult } from "../utils/entities"
|
|
5
6
|
import { processQuery } from "./engine"
|
|
6
7
|
import type { Predicate } from "./predicate"
|
|
7
8
|
import { QueryResult } from "./queryResult"
|
|
9
|
+
import { type SelectArg, selectionToIncludeData } from "./selection"
|
|
8
10
|
|
|
11
|
+
/**
|
|
12
|
+
* @deprecated Server-side ordering is not supported by the network. Sort the fetched
|
|
13
|
+
* entities in JavaScript instead (e.g. `entities.sort(...)`). This type will be removed
|
|
14
|
+
* in a future release.
|
|
15
|
+
*/
|
|
9
16
|
export type OrderByAttribute = {
|
|
10
17
|
name: string
|
|
11
18
|
type: "string" | "number"
|
|
@@ -18,6 +25,10 @@ export type OrderByAttribute = {
|
|
|
18
25
|
* @param attributeType - The type of the attribute to order by (string or number)
|
|
19
26
|
* @returns Input for orderBy method
|
|
20
27
|
*
|
|
28
|
+
* @deprecated Server-side ordering is not supported by the network, so `orderBy` (and this
|
|
29
|
+
* helper) have no effect on the returned order. Sort the fetched entities in JavaScript
|
|
30
|
+
* instead (e.g. `entities.sort(...)`). This function will be removed in a future release.
|
|
31
|
+
*
|
|
21
32
|
* @example
|
|
22
33
|
* const ascAttribute = asc("name", "string")
|
|
23
34
|
*/
|
|
@@ -35,6 +46,10 @@ export function asc(attributeName: string, attributeType: "string" | "number"):
|
|
|
35
46
|
* @param attributeType - The type of the attribute to order by (string or number)
|
|
36
47
|
* @returns Input for orderBy method
|
|
37
48
|
*
|
|
49
|
+
* @deprecated Server-side ordering is not supported by the network, so `orderBy` (and this
|
|
50
|
+
* helper) have no effect on the returned order. Sort the fetched entities in JavaScript
|
|
51
|
+
* instead (e.g. `entities.sort(...)`). This function will be removed in a future release.
|
|
52
|
+
*
|
|
38
53
|
* @example
|
|
39
54
|
* const descAttribute = desc("name", "string")
|
|
40
55
|
*/
|
|
@@ -45,24 +60,37 @@ export function desc(attributeName: string, attributeType: "string" | "number"):
|
|
|
45
60
|
order: "desc",
|
|
46
61
|
}
|
|
47
62
|
}
|
|
63
|
+
|
|
48
64
|
/**
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
* @param client - The Arkiv client
|
|
52
|
-
* @returns The QueryBuilder instance {@link QueryBuilder}
|
|
65
|
+
* Data-selection parameters forwarded to the query engine on each fetch.
|
|
66
|
+
* Subclasses of {@link BaseQueryBuilder} decide which parts of an entity are fetched.
|
|
53
67
|
*/
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
68
|
+
type SelectionParams = {
|
|
69
|
+
withAttributes?: boolean | undefined
|
|
70
|
+
withMetadata?: boolean | undefined
|
|
71
|
+
withPayload?: boolean | undefined
|
|
72
|
+
includeData?: RpcIncludeData | undefined
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* BaseQueryBuilder holds the query-building logic shared by every query builder
|
|
77
|
+
* (filtering, ordering, pagination, execution). It follows the Builder pattern,
|
|
78
|
+
* allowing methods to be chained. Subclasses decide how data selection is expressed
|
|
79
|
+
* by implementing the protected `selectionParams` method.
|
|
80
|
+
*
|
|
81
|
+
* Use {@link SelectQueryBuilder} via `client.select()` to build and execute queries.
|
|
82
|
+
*
|
|
83
|
+
* @typeParam TEntity - The shape of each entity produced by {@link BaseQueryBuilder.fetch}.
|
|
84
|
+
*/
|
|
85
|
+
export abstract class BaseQueryBuilder<TEntity> {
|
|
86
|
+
protected _client: ArkivClient
|
|
87
|
+
protected _ownedBy: Hex | undefined
|
|
88
|
+
protected _createdBy: Hex | undefined
|
|
89
|
+
protected _orderBy: RpcOrderByAttribute[] | undefined
|
|
90
|
+
protected _validAtBlock: bigint | undefined
|
|
91
|
+
protected _limit: number | undefined
|
|
92
|
+
protected _cursor: string | undefined
|
|
93
|
+
protected _predicates: Predicate[]
|
|
66
94
|
|
|
67
95
|
constructor(client: ArkivClient) {
|
|
68
96
|
this._client = client
|
|
@@ -72,13 +100,13 @@ export class QueryBuilder {
|
|
|
72
100
|
/**
|
|
73
101
|
* Sets the ownedBy filter
|
|
74
102
|
* @param ownedBy - The address of the owner
|
|
75
|
-
* @returns The
|
|
103
|
+
* @returns The query builder instance
|
|
76
104
|
*
|
|
77
105
|
* @example
|
|
78
|
-
* const builder =
|
|
106
|
+
* const builder = client.select()
|
|
79
107
|
* builder.ownedBy("0x1234567890123456789012345678901234567890")
|
|
80
108
|
*/
|
|
81
|
-
ownedBy(ownedBy: Hex) {
|
|
109
|
+
ownedBy(ownedBy: Hex): this {
|
|
82
110
|
this._ownedBy = ownedBy
|
|
83
111
|
return this
|
|
84
112
|
}
|
|
@@ -86,13 +114,13 @@ export class QueryBuilder {
|
|
|
86
114
|
/**
|
|
87
115
|
* Sets the createdBy filter
|
|
88
116
|
* @param createdBy - The address of the creator
|
|
89
|
-
* @returns The
|
|
117
|
+
* @returns The query builder instance
|
|
90
118
|
*
|
|
91
119
|
* @example
|
|
92
|
-
* const builder =
|
|
120
|
+
* const builder = client.select()
|
|
93
121
|
* builder.createdBy("0x1234567890123456789012345678901234567890")
|
|
94
122
|
*/
|
|
95
|
-
createdBy(createdBy: Hex) {
|
|
123
|
+
createdBy(createdBy: Hex): this {
|
|
96
124
|
this._createdBy = createdBy
|
|
97
125
|
return this
|
|
98
126
|
}
|
|
@@ -105,10 +133,14 @@ export class QueryBuilder {
|
|
|
105
133
|
* @param attributeName - The name of the attribute to order by
|
|
106
134
|
* @param attributeType - The type of the attribute to order by (string or number)
|
|
107
135
|
* @param order - The order to set the order by (asc or desc)
|
|
108
|
-
* @returns The
|
|
136
|
+
* @returns The query builder instance
|
|
137
|
+
*
|
|
138
|
+
* @deprecated Server-side ordering is not supported by the network, so this method has no
|
|
139
|
+
* effect on the returned order. Sort the fetched entities in JavaScript instead, e.g.
|
|
140
|
+
* `result.entities.sort((a, b) => ...)`. This method will be removed in a future release.
|
|
109
141
|
*
|
|
110
142
|
* @example
|
|
111
|
-
* const builder = client.
|
|
143
|
+
* const builder = client.select()
|
|
112
144
|
* builder.orderBy("name", "string", "desc")
|
|
113
145
|
* builder.orderBy(asc("name", "string"))
|
|
114
146
|
* builder.orderBy(desc("name", "string"))
|
|
@@ -119,10 +151,14 @@ export class QueryBuilder {
|
|
|
119
151
|
* This method takes the OrderByAttribute object as an argument and is mainly
|
|
120
152
|
* used to use the helper functions asc() and desc() to create the OrderByAttribute instances.
|
|
121
153
|
* @param orderByAttribute - The OrderByAttribute instance to set
|
|
122
|
-
* @returns The
|
|
154
|
+
* @returns The query builder instance
|
|
155
|
+
*
|
|
156
|
+
* @deprecated Server-side ordering is not supported by the network, so this method has no
|
|
157
|
+
* effect on the returned order. Sort the fetched entities in JavaScript instead, e.g.
|
|
158
|
+
* `result.entities.sort((a, b) => ...)`. This method will be removed in a future release.
|
|
123
159
|
*
|
|
124
160
|
* @example
|
|
125
|
-
* const builder =
|
|
161
|
+
* const builder = client.select()
|
|
126
162
|
* builder.orderBy(asc("name", "string"))
|
|
127
163
|
* builder.orderBy(desc("name", "string"))
|
|
128
164
|
*/
|
|
@@ -131,7 +167,7 @@ export class QueryBuilder {
|
|
|
131
167
|
attributeNameOrOrderByAttribute: string | OrderByAttribute,
|
|
132
168
|
attributeType?: "string" | "number",
|
|
133
169
|
order: "asc" | "desc" = "asc",
|
|
134
|
-
) {
|
|
170
|
+
): this {
|
|
135
171
|
if (!this._orderBy) {
|
|
136
172
|
this._orderBy = []
|
|
137
173
|
}
|
|
@@ -160,58 +196,16 @@ export class QueryBuilder {
|
|
|
160
196
|
return this
|
|
161
197
|
}
|
|
162
198
|
|
|
163
|
-
/**
|
|
164
|
-
* Sets the withAttributes flag which will return the attributes for the entities if true
|
|
165
|
-
* @param withAttributes - The boolean value to set
|
|
166
|
-
* @returns The QueryBuilder instance
|
|
167
|
-
*
|
|
168
|
-
* @example
|
|
169
|
-
* const builder = new QueryBuilder(client)
|
|
170
|
-
* builder.withAttributes(true)
|
|
171
|
-
*/
|
|
172
|
-
withAttributes(withAttributes: boolean = true) {
|
|
173
|
-
this._withAttributes = withAttributes
|
|
174
|
-
return this
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* Sets the withMetadata flag which will return the metadata (like owner, expiredAt, etc.) for the entities if true
|
|
179
|
-
* @param withMetadata - The boolean value to set
|
|
180
|
-
* @returns The QueryBuilder instance
|
|
181
|
-
*
|
|
182
|
-
* @example
|
|
183
|
-
* const builder = new QueryBuilder(client)
|
|
184
|
-
* builder.withMetadata(true)
|
|
185
|
-
*/
|
|
186
|
-
withMetadata(withMetadata: boolean = true) {
|
|
187
|
-
this._withMetadata = withMetadata
|
|
188
|
-
return this
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
/**
|
|
192
|
-
* Sets the withPayload flag which will return the payload for the entities if true
|
|
193
|
-
* @param withPayload - The boolean value to set
|
|
194
|
-
* @returns The QueryBuilder instance
|
|
195
|
-
*
|
|
196
|
-
* @example
|
|
197
|
-
* const builder = new QueryBuilder(client)
|
|
198
|
-
* builder.withPayload(true)
|
|
199
|
-
*/
|
|
200
|
-
withPayload(withPayload: boolean = true) {
|
|
201
|
-
this._withPayload = withPayload
|
|
202
|
-
return this
|
|
203
|
-
}
|
|
204
|
-
|
|
205
199
|
/**
|
|
206
200
|
* Sets the limit for the query
|
|
207
201
|
* @param limit - The number of entities to return
|
|
208
|
-
* @returns The
|
|
202
|
+
* @returns The query builder instance
|
|
209
203
|
*
|
|
210
204
|
* @example
|
|
211
|
-
* const builder =
|
|
205
|
+
* const builder = client.select()
|
|
212
206
|
* builder.limit(10)
|
|
213
207
|
*/
|
|
214
|
-
limit(limit: number) {
|
|
208
|
+
limit(limit: number): this {
|
|
215
209
|
this._limit = limit
|
|
216
210
|
return this
|
|
217
211
|
}
|
|
@@ -219,13 +213,13 @@ export class QueryBuilder {
|
|
|
219
213
|
/**
|
|
220
214
|
* Sets the cursor for the query - it is advances setting which rather shouldn't be used manually but it is provided from query result if limit is used (pagination).
|
|
221
215
|
* @param cursor - The cursor to set which tells to RPC Query server where to start or continue the query.
|
|
222
|
-
* @returns The
|
|
216
|
+
* @returns The query builder instance
|
|
223
217
|
*
|
|
224
218
|
* @example
|
|
225
|
-
* const builder =
|
|
226
|
-
* builder.
|
|
219
|
+
* const builder = client.select()
|
|
220
|
+
* builder.cursor("0xABC123")
|
|
227
221
|
*/
|
|
228
|
-
cursor(cursor: string) {
|
|
222
|
+
cursor(cursor: string): this {
|
|
229
223
|
this._cursor = cursor
|
|
230
224
|
return this
|
|
231
225
|
}
|
|
@@ -234,53 +228,64 @@ export class QueryBuilder {
|
|
|
234
228
|
* Sets the validAtBlock for the query which tells at which block height the state we are intested.
|
|
235
229
|
* If not set, the latest block is used.
|
|
236
230
|
* @param validAtBlock - The block number to set
|
|
237
|
-
* @returns The
|
|
231
|
+
* @returns The query builder instance
|
|
238
232
|
*
|
|
239
233
|
* @example
|
|
240
|
-
* const builder =
|
|
234
|
+
* const builder = client.select()
|
|
241
235
|
* builder.validAtBlock(10000)
|
|
242
236
|
*/
|
|
243
|
-
validAtBlock(validAtBlock: bigint) {
|
|
237
|
+
validAtBlock(validAtBlock: bigint): this {
|
|
244
238
|
this._validAtBlock = validAtBlock
|
|
245
239
|
return this
|
|
246
240
|
}
|
|
247
241
|
|
|
248
242
|
/**
|
|
249
|
-
* Sets the predicates for the query limiting the results. It can be a single predicate
|
|
243
|
+
* Sets the predicates for the query limiting the results. It can be a single predicate,
|
|
244
|
+
* multiple predicates passed as separate arguments, or an array of predicates - all combined with 'and'.
|
|
250
245
|
* Predicates can be nested using 'or' and 'and' predicates.
|
|
251
|
-
* @param predicates - The predicates to set
|
|
252
|
-
* @returns The
|
|
246
|
+
* @param predicates - The predicates to set, either as a single array or as separate arguments
|
|
247
|
+
* @returns The query builder instance
|
|
253
248
|
*
|
|
254
249
|
* @example
|
|
255
|
-
* const builder =
|
|
250
|
+
* const builder = client.select()
|
|
256
251
|
* builder.where(eq("name", "John"))
|
|
252
|
+
* builder.where(eq("name", "John"), eq("age", 30))
|
|
257
253
|
* builder.where([eq("name", "John"), eq("age", 30)])
|
|
258
|
-
* builder.where(
|
|
259
|
-
* builder.where(
|
|
260
|
-
* builder.where(
|
|
261
|
-
* builder.where(
|
|
262
|
-
* builder.where([eq("name", "John"), and([eq("age", 30), or([eq("age", 31), and([eq("age", 32), eq("age", 33)])])])])
|
|
254
|
+
* builder.where(eq("name", "John"), or(eq("age", 30), eq("age", 31)))
|
|
255
|
+
* builder.where(eq("name", "John"), and(eq("age", 30), eq("age", 31)))
|
|
256
|
+
* builder.where(eq("name", "John"), or(eq("age", 30), and(eq("age", 31), eq("age", 32))))
|
|
257
|
+
* builder.where(eq("name", "John"), and(eq("age", 30), or(eq("age", 31), eq("age", 32))))
|
|
263
258
|
*/
|
|
264
|
-
where(predicates: Predicate[]
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
this._predicates.push(predicates)
|
|
269
|
-
}
|
|
259
|
+
where(predicates: Predicate[]): this
|
|
260
|
+
where(...predicates: Predicate[]): this
|
|
261
|
+
where(...predicates: (Predicate | Predicate[])[]) {
|
|
262
|
+
this._predicates.push(...predicates.flat())
|
|
270
263
|
return this
|
|
271
264
|
}
|
|
272
265
|
|
|
273
266
|
/**
|
|
274
|
-
*
|
|
267
|
+
* Returns the data-selection parameters forwarded to the query engine.
|
|
268
|
+
* Subclasses decide which parts of an entity are fetched.
|
|
269
|
+
*/
|
|
270
|
+
protected abstract selectionParams(): SelectionParams
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Builds a single result entity from a raw RPC entity. Subclasses decide the produced shape
|
|
274
|
+
* (a full {@link Entity}, or a projected object inferred from the selection).
|
|
275
|
+
*/
|
|
276
|
+
protected abstract projectEntity(rpcEntity: RpcEntity): TEntity | Promise<TEntity>
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Fetches the entities from the query.
|
|
275
280
|
* It will return a QueryResult instance which can be used to fetch the next and previous pages.
|
|
276
281
|
* @returns The QueryResult instance {@link QueryResult}
|
|
277
282
|
*
|
|
278
283
|
* @example
|
|
279
|
-
* const builder =
|
|
284
|
+
* const builder = client.select()
|
|
280
285
|
* const result = await builder.where(eq("name", "John")).fetch()
|
|
281
286
|
* // result = { entities: [Entity, Entity, Entity], next: async () => QueryResult, previous: async () => QueryResult }
|
|
282
287
|
*/
|
|
283
|
-
async fetch() {
|
|
288
|
+
async fetch(): Promise<QueryResult<TEntity>> {
|
|
284
289
|
const queryResult = await processQuery(this._client, {
|
|
285
290
|
predicates: this._predicates,
|
|
286
291
|
limit: this._limit,
|
|
@@ -289,19 +294,15 @@ export class QueryBuilder {
|
|
|
289
294
|
createdBy: this._createdBy,
|
|
290
295
|
orderBy: this._orderBy,
|
|
291
296
|
validAtBlock: this._validAtBlock,
|
|
292
|
-
|
|
293
|
-
withMetadata: this._withMetadata,
|
|
294
|
-
withPayload: this._withPayload,
|
|
297
|
+
...this.selectionParams(),
|
|
295
298
|
})
|
|
296
299
|
|
|
297
|
-
const entities = await Promise.all(
|
|
298
|
-
queryResult.data.map((entity) => entityFromRpcResult(entity)),
|
|
299
|
-
)
|
|
300
|
+
const entities = await Promise.all(queryResult.data.map((entity) => this.projectEntity(entity)))
|
|
300
301
|
|
|
301
302
|
this.cursor(queryResult.cursor)
|
|
302
303
|
this.validAtBlock(BigInt(queryResult.blockNumber ?? 0))
|
|
303
304
|
|
|
304
|
-
return new QueryResult(entities, this, this._cursor, this._limit, this._validAtBlock)
|
|
305
|
+
return new QueryResult<TEntity>(entities, this, this._cursor, this._limit, this._validAtBlock)
|
|
305
306
|
}
|
|
306
307
|
|
|
307
308
|
/**
|
|
@@ -309,7 +310,7 @@ export class QueryBuilder {
|
|
|
309
310
|
* @returns The number of entities
|
|
310
311
|
*
|
|
311
312
|
* @example
|
|
312
|
-
* const builder =
|
|
313
|
+
* const builder = client.select()
|
|
313
314
|
* const result = await builder.where(eq("name", "John")).count()
|
|
314
315
|
* // result = 10
|
|
315
316
|
*/
|
|
@@ -330,3 +331,117 @@ export class QueryBuilder {
|
|
|
330
331
|
return queryResult.data.length ?? 0
|
|
331
332
|
}
|
|
332
333
|
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* QueryBuilder is a helper class to build queries to the Arkiv DBChains.
|
|
337
|
+
* It can be used to fetch entities from the Arkiv DBChains. It follows the Builder pattern allowing chaining of methods.
|
|
338
|
+
*
|
|
339
|
+
* By default the result includes only the entity `key`. Additional data is opt-in through
|
|
340
|
+
* `withAttributes()`, `withMetadata()` and `withPayload()`.
|
|
341
|
+
*
|
|
342
|
+
* @deprecated Use {@link SelectQueryBuilder} via `client.select()` instead. Declaring the
|
|
343
|
+
* selection up front avoids the common mistake of forgetting to opt in to data and getting back
|
|
344
|
+
* entities with only their `key` populated. This class remains for backwards compatibility and
|
|
345
|
+
* will be removed in a future release.
|
|
346
|
+
*
|
|
347
|
+
* @param client - The Arkiv client
|
|
348
|
+
* @returns The QueryBuilder instance {@link QueryBuilder}
|
|
349
|
+
*/
|
|
350
|
+
export class QueryBuilder extends BaseQueryBuilder<Entity> {
|
|
351
|
+
private _withAttributes: boolean | undefined
|
|
352
|
+
private _withMetadata: boolean | undefined
|
|
353
|
+
private _withPayload: boolean | undefined
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Sets the withAttributes flag which will return the attributes for the entities if true
|
|
357
|
+
* @param withAttributes - The boolean value to set
|
|
358
|
+
* @returns The QueryBuilder instance
|
|
359
|
+
*
|
|
360
|
+
* @example
|
|
361
|
+
* const builder = client.buildQuery()
|
|
362
|
+
* builder.withAttributes(true)
|
|
363
|
+
*/
|
|
364
|
+
withAttributes(withAttributes: boolean = true): this {
|
|
365
|
+
this._withAttributes = withAttributes
|
|
366
|
+
return this
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Sets the withMetadata flag which will return the metadata (like owner, expiredAt, etc.) for the entities if true
|
|
371
|
+
* @param withMetadata - The boolean value to set
|
|
372
|
+
* @returns The QueryBuilder instance
|
|
373
|
+
*
|
|
374
|
+
* @example
|
|
375
|
+
* const builder = client.buildQuery()
|
|
376
|
+
* builder.withMetadata(true)
|
|
377
|
+
*/
|
|
378
|
+
withMetadata(withMetadata: boolean = true): this {
|
|
379
|
+
this._withMetadata = withMetadata
|
|
380
|
+
return this
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Sets the withPayload flag which will return the payload for the entities if true
|
|
385
|
+
* @param withPayload - The boolean value to set
|
|
386
|
+
* @returns The QueryBuilder instance
|
|
387
|
+
*
|
|
388
|
+
* @example
|
|
389
|
+
* const builder = client.buildQuery()
|
|
390
|
+
* builder.withPayload(true)
|
|
391
|
+
*/
|
|
392
|
+
withPayload(withPayload: boolean = true): this {
|
|
393
|
+
this._withPayload = withPayload
|
|
394
|
+
return this
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
protected selectionParams(): SelectionParams {
|
|
398
|
+
return {
|
|
399
|
+
withAttributes: this._withAttributes,
|
|
400
|
+
withMetadata: this._withMetadata,
|
|
401
|
+
withPayload: this._withPayload,
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
protected projectEntity(rpcEntity: RpcEntity): Promise<Entity> {
|
|
406
|
+
return entityFromRpcResult(rpcEntity)
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* SelectQueryBuilder is the recommended query builder. It requires the selection to be declared
|
|
412
|
+
* up front, so results always contain exactly the data you asked for — and the type of each
|
|
413
|
+
* returned entity is narrowed to exactly the selected fields.
|
|
414
|
+
*
|
|
415
|
+
* The selection is fixed at construction time and is flat — each field maps to an entity field.
|
|
416
|
+
* Create one via `client.select(...)` rather than constructing it directly, so the result type is
|
|
417
|
+
* inferred from the selection.
|
|
418
|
+
*
|
|
419
|
+
* @typeParam TEntity - The projected entity shape, inferred from the selection by `client.select()`.
|
|
420
|
+
*
|
|
421
|
+
* @example
|
|
422
|
+
* // everything
|
|
423
|
+
* await client.select().where(eq("name", "John")).fetch()
|
|
424
|
+
* await client.select("*").where(eq("name", "John")).fetch()
|
|
425
|
+
* // specific fields
|
|
426
|
+
* await client.select({ owner: true, attributes: true }).fetch()
|
|
427
|
+
* // a single field — result is typed (flat) { owner: Hex }
|
|
428
|
+
* await client.select({ owner: true }).fetch()
|
|
429
|
+
*/
|
|
430
|
+
export class SelectQueryBuilder<TEntity> extends BaseQueryBuilder<TEntity> {
|
|
431
|
+
private _includeData: RpcIncludeData
|
|
432
|
+
|
|
433
|
+
constructor(client: ArkivClient, selection?: SelectArg) {
|
|
434
|
+
super(client)
|
|
435
|
+
this._includeData = selectionToIncludeData(selection)
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
protected selectionParams(): SelectionParams {
|
|
439
|
+
return { includeData: this._includeData }
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
protected async projectEntity(rpcEntity: RpcEntity): Promise<TEntity> {
|
|
443
|
+
// The runtime value is a full Entity (with methods); the static type is narrowed to the
|
|
444
|
+
// selected fields via `client.select()`'s inference.
|
|
445
|
+
return (await entityFromRpcResult(rpcEntity)) as unknown as TEntity
|
|
446
|
+
}
|
|
447
|
+
}
|
package/src/query/queryResult.ts
CHANGED
|
@@ -1,20 +1,26 @@
|
|
|
1
1
|
import { NoCursorOrLimitError, NoMoreResultsError } from "../errors"
|
|
2
2
|
import type { Entity } from "../types/entity"
|
|
3
3
|
import { getLogger } from "../utils/logger"
|
|
4
|
-
import type {
|
|
4
|
+
import type { BaseQueryBuilder } from "./queryBuilder"
|
|
5
5
|
|
|
6
6
|
const logger = getLogger("query:result")
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
/**
|
|
9
|
+
* The result of a query. Holds the fetched entities and supports cursor-based pagination.
|
|
10
|
+
*
|
|
11
|
+
* @typeParam TEntity - The shape of each entity, inferred from the query builder
|
|
12
|
+
* (a full {@link Entity}, or a projected object inferred from a `select()` selection).
|
|
13
|
+
*/
|
|
14
|
+
export class QueryResult<TEntity = Entity> {
|
|
15
|
+
entities: TEntity[]
|
|
10
16
|
private _endOfIteration: boolean
|
|
11
17
|
private _cursor: string | undefined
|
|
12
18
|
private _limit: number | undefined
|
|
13
19
|
private _validAtBlock: bigint | undefined
|
|
14
|
-
private _queryBuilder:
|
|
20
|
+
private _queryBuilder: BaseQueryBuilder<TEntity>
|
|
15
21
|
|
|
16
22
|
// Public getters for internal state
|
|
17
|
-
get queryBuilder():
|
|
23
|
+
get queryBuilder(): BaseQueryBuilder<TEntity> {
|
|
18
24
|
return this._queryBuilder
|
|
19
25
|
}
|
|
20
26
|
|
|
@@ -23,8 +29,8 @@ export class QueryResult {
|
|
|
23
29
|
}
|
|
24
30
|
|
|
25
31
|
constructor(
|
|
26
|
-
entities:
|
|
27
|
-
queryBuilder:
|
|
32
|
+
entities: TEntity[],
|
|
33
|
+
queryBuilder: BaseQueryBuilder<TEntity>,
|
|
28
34
|
cursor: string | undefined,
|
|
29
35
|
limit: number | undefined,
|
|
30
36
|
validAtBlock: bigint | undefined,
|