@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
|
@@ -9,6 +9,11 @@ export type QueryOptionsIncludeData = {
|
|
|
9
9
|
payload?: boolean
|
|
10
10
|
metadata?: boolean
|
|
11
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* @deprecated Server-side ordering is not supported by the network. Sort the fetched
|
|
14
|
+
* entities in JavaScript instead (e.g. `entities.sort(...)`). This type will be removed
|
|
15
|
+
* in a future release.
|
|
16
|
+
*/
|
|
12
17
|
export type QueryOptionsOrderBy = {
|
|
13
18
|
name: string
|
|
14
19
|
type: "string" | "numeric"
|
|
@@ -18,6 +23,11 @@ export type QueryOptionsOrderBy = {
|
|
|
18
23
|
export type QueryOptions = {
|
|
19
24
|
includeData?: QueryOptionsIncludeData
|
|
20
25
|
atBlock?: bigint
|
|
26
|
+
/**
|
|
27
|
+
* @deprecated Server-side ordering is not supported by the network, so this option has no
|
|
28
|
+
* effect on the returned order. Sort the fetched entities in JavaScript instead
|
|
29
|
+
* (e.g. `entities.sort(...)`). This option will be removed in a future release.
|
|
30
|
+
*/
|
|
21
31
|
orderBy?: QueryOptionsOrderBy[]
|
|
22
32
|
resultsPerPage?: number | undefined
|
|
23
33
|
cursor?: string | undefined
|
|
@@ -9,14 +9,24 @@ const logger = getLogger("actions:wallet:create-entity")
|
|
|
9
9
|
/**
|
|
10
10
|
* Parameters for the createEntity function.
|
|
11
11
|
* - payload: The payload of the entity.
|
|
12
|
-
* - attributes: The attributes of the entity.
|
|
12
|
+
* - attributes: The attributes of the entity. Attribute values may be strings
|
|
13
|
+
* or numbers, but numeric values **must be integers**. To store a non-integer,
|
|
14
|
+
* scale it to an integer (e.g. `1.5` -> `1500`) to preserve numeric ordering,
|
|
15
|
+
* or pass it as a string (e.g. `"1.5"`). A non-integer numeric value throws an
|
|
16
|
+
* {@link InvalidAttributeError}.
|
|
13
17
|
* - contentType: The content type of the entity.
|
|
14
|
-
* - expiresIn:
|
|
18
|
+
* - expiresIn: How long until the entity expires, in seconds. Because Arkiv
|
|
19
|
+
* measures expiration in blocks (1 block = 2 seconds), this **must be a
|
|
20
|
+
* positive integer and a multiple of the block time (2 seconds)**
|
|
21
|
+
* Invalid values throw an {@link InvalidExpirationError}.
|
|
15
22
|
*/
|
|
16
23
|
export type CreateEntityParameters = {
|
|
17
24
|
payload: Uint8Array
|
|
25
|
+
/** Entity attributes. Numeric values must be integers (scale non-integers, e.g. `1.5` -> `1500`, or use a string). Throws {@link InvalidAttributeError} otherwise. */
|
|
18
26
|
attributes: Attribute[]
|
|
19
27
|
contentType: MimeType | string
|
|
28
|
+
/** Seconds until expiry. Must be a positive integer and a multiple of the 2s block time.
|
|
29
|
+
* Throws {@link InvalidExpirationError} otherwise. */
|
|
20
30
|
expiresIn: number
|
|
21
31
|
}
|
|
22
32
|
|
|
@@ -9,10 +9,15 @@ const logger = getLogger("actions:wallet:extend-entity")
|
|
|
9
9
|
/**
|
|
10
10
|
* Parameters for the extendEntity function.
|
|
11
11
|
* - entityKey: The key of the entity to extend.
|
|
12
|
-
* - expiresIn:
|
|
12
|
+
* - expiresIn: How long to extend the entity by, in seconds. Because Arkiv
|
|
13
|
+
* measures expiration in blocks (1 block = 2 seconds), this **must be a
|
|
14
|
+
* positive integer and a multiple of the block time (2 seconds)**.
|
|
15
|
+
* Invalid values throw an {@link InvalidExpirationError}.
|
|
13
16
|
*/
|
|
14
17
|
export type ExtendEntityParameters = {
|
|
15
18
|
entityKey: Hex
|
|
19
|
+
/** Seconds to extend by. Must be a positive integer and a multiple of the 2s block time.
|
|
20
|
+
* Throws {@link InvalidExpirationError} otherwise. */
|
|
16
21
|
expiresIn: number
|
|
17
22
|
}
|
|
18
23
|
|
|
@@ -10,15 +10,25 @@ const logger = getLogger("actions:wallet:update-entity")
|
|
|
10
10
|
* Parameters for the updateEntity function.
|
|
11
11
|
* - entityKey: The key of the entity to update.
|
|
12
12
|
* - payload: The payload of the entity.
|
|
13
|
-
* - attributes: The attributes of the entity.
|
|
13
|
+
* - attributes: The attributes of the entity. Attribute values may be strings
|
|
14
|
+
* or numbers, but numeric values **must be integers**. To store a non-integer,
|
|
15
|
+
* scale it to an integer (e.g. `1.5` -> `1500`) to preserve numeric ordering,
|
|
16
|
+
* or pass it as a string (e.g. `"1.5"`). A non-integer numeric value throws an
|
|
17
|
+
* {@link InvalidAttributeError}.
|
|
14
18
|
* - contentType: The content type of the entity.
|
|
15
|
-
* - expiresIn:
|
|
19
|
+
* - expiresIn: How long until the entity expires, in seconds. Because Arkiv
|
|
20
|
+
* measures expiration in blocks (1 block = 2 seconds), this **must be a
|
|
21
|
+
* positive integer and a multiple of the block time (2 seconds)**.
|
|
22
|
+
* Invalid values throw an {@link InvalidExpirationError}.
|
|
16
23
|
*/
|
|
17
24
|
export type UpdateEntityParameters = {
|
|
18
25
|
entityKey: Hex
|
|
19
26
|
payload: Uint8Array
|
|
27
|
+
/** Entity attributes. Numeric values must be integers (scale non-integers, e.g. `1.5` -> `1500`, or use a string). Throws {@link InvalidAttributeError} otherwise. */
|
|
20
28
|
attributes: Attribute[]
|
|
21
29
|
contentType: MimeType | string
|
|
30
|
+
/** Seconds until expiry. Must be a positive integer and a multiple of the 2s block time.
|
|
31
|
+
* Throws {@link InvalidExpirationError} otherwise. */
|
|
22
32
|
expiresIn: number
|
|
23
33
|
}
|
|
24
34
|
|
|
@@ -20,6 +20,8 @@ test("creates", () => {
|
|
|
20
20
|
expect(typeof client.getEntity).toBe("function")
|
|
21
21
|
expect(client.buildQuery).toBeDefined()
|
|
22
22
|
expect(typeof client.buildQuery).toBe("function")
|
|
23
|
+
expect(client.select).toBeDefined()
|
|
24
|
+
expect(typeof client.select).toBe("function")
|
|
23
25
|
expect(client.query).toBeDefined()
|
|
24
26
|
expect(typeof client.query).toBe("function")
|
|
25
27
|
expect(client.getEntityCount).toBeDefined()
|
|
@@ -4,7 +4,8 @@ import { getEntity } from "../../actions/public/getEntity"
|
|
|
4
4
|
import { getEntityCount } from "../../actions/public/getEntityCount"
|
|
5
5
|
import { type QueryOptions, type QueryReturnType, query } from "../../actions/public/query"
|
|
6
6
|
import { subscribeEntityEvents } from "../../actions/public/subscribeEntityEvents"
|
|
7
|
-
import { QueryBuilder } from "../../query/queryBuilder"
|
|
7
|
+
import { QueryBuilder, SelectQueryBuilder } from "../../query/queryBuilder"
|
|
8
|
+
import type { EntitySelection, FullEntity, ProjectedEntity, SelectArg } from "../../query/selection"
|
|
8
9
|
import type { Entity } from "../../types/entity"
|
|
9
10
|
import type {
|
|
10
11
|
OnEntityCreatedEvent,
|
|
@@ -55,12 +56,76 @@ export type PublicArkivActions<
|
|
|
55
56
|
*/
|
|
56
57
|
getEntity: (key: Hex) => Promise<Entity>
|
|
57
58
|
|
|
59
|
+
/**
|
|
60
|
+
* Returns a SelectQueryBuilder for building and executing queries — the recommended way to
|
|
61
|
+
* read entities. You declare up front which parts of an entity you want returned, so results
|
|
62
|
+
* always contain exactly the data you asked for.
|
|
63
|
+
*
|
|
64
|
+
* - Docs: https://docs.arkiv.network/ts-sdk/actions/public/query
|
|
65
|
+
*
|
|
66
|
+
* @param selection - What to include in the results. Omit it (or pass `"*"`) to select everything,
|
|
67
|
+
* or pass an object to select specific parts (at least one field is required). Every part is
|
|
68
|
+
* opt-in, including the `key`. The selection is flat — each field maps to an entity field.
|
|
69
|
+
* {@link SelectArg}
|
|
70
|
+
* @returns A SelectQueryBuilder instance for building and executing queries. {@link SelectQueryBuilder}
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* import { createPublicClient, http } from 'arkiv'
|
|
74
|
+
* import { braga } from 'arkiv/chains'
|
|
75
|
+
* import { eq } from 'arkiv/query'
|
|
76
|
+
*
|
|
77
|
+
* const client = createPublicClient({
|
|
78
|
+
* chain: braga,
|
|
79
|
+
* transport: http(),
|
|
80
|
+
* })
|
|
81
|
+
* // select everything
|
|
82
|
+
* await client.select().where(eq("category", "docs")).fetch()
|
|
83
|
+
* await client.select("*").where(eq("category", "docs")).fetch()
|
|
84
|
+
* // only the key
|
|
85
|
+
* await client.select({ key: true }).where(eq("category", "docs")).fetch()
|
|
86
|
+
* // select specific fields — result typed { owner: Hex; attributes: Attribute[] }
|
|
87
|
+
* await client.select({ owner: true, attributes: true }).fetch()
|
|
88
|
+
* // a single field — result typed { owner: Hex }
|
|
89
|
+
* await client.select({ owner: true }).fetch()
|
|
90
|
+
*/
|
|
91
|
+
select: {
|
|
92
|
+
/** Select every field. Pass nothing or `"*"`; the returned entities contain all fields. */
|
|
93
|
+
(selection?: "*"): SelectQueryBuilder<FullEntity>
|
|
94
|
+
/**
|
|
95
|
+
* Pick the entity fields to return. Set the ones you want to `true` (at least one is required);
|
|
96
|
+
* the result is typed to exactly those fields, so reading anything else is a compile error.
|
|
97
|
+
*
|
|
98
|
+
* Available fields: `key`, `owner`, `creator`, `contentType`, `payload`, `attributes`,
|
|
99
|
+
* `expiresAtBlock`, `createdAtBlock`, `lastModifiedAtBlock`, `transactionIndexInBlock`,
|
|
100
|
+
* `operationIndexInTransaction`.
|
|
101
|
+
*
|
|
102
|
+
* Pass the selection inline so its fields stay literal `true`. A selection stored in a `let`/
|
|
103
|
+
* `const` variable widens to `boolean` and the result type can no longer be narrowed — annotate
|
|
104
|
+
* it `as const` (e.g. `const sel = { owner: true } as const`) in that case.
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* client.select({ owner: true, attributes: true }) // entities typed { owner, attributes }
|
|
108
|
+
* client.select({ key: true, payload: true }) // includes payload → toText()/toJson() too
|
|
109
|
+
*/
|
|
110
|
+
<const S extends EntitySelection>(selection: S): SelectQueryBuilder<ProjectedEntity<S>>
|
|
111
|
+
/**
|
|
112
|
+
* Dynamic selection: accepts a value typed {@link SelectArg} (e.g. built at runtime). The
|
|
113
|
+
* result cannot be narrowed in this case, so the entities are typed as the full entity.
|
|
114
|
+
*/
|
|
115
|
+
(selection: SelectArg): SelectQueryBuilder<FullEntity>
|
|
116
|
+
}
|
|
117
|
+
|
|
58
118
|
/**
|
|
59
119
|
* Returns a QueryBuilder instance for building and executing queries.
|
|
60
120
|
* The QueryBuilder object follows the Builder pattern, allowing you to chain methods to build a query and then execute it.
|
|
61
121
|
*
|
|
62
122
|
* - Docs: https://docs.arkiv.network/ts-sdk/actions/public/query
|
|
63
123
|
*
|
|
124
|
+
* @deprecated Use {@link select} instead. `buildQuery()` returns only the entity `key` unless
|
|
125
|
+
* you remember to opt in to data with `withAttributes()`/`withMetadata()`/`withPayload()`, which
|
|
126
|
+
* is an easy mistake. `select()` makes the selection explicit. This method remains for backwards
|
|
127
|
+
* compatibility and will be removed in a future release.
|
|
128
|
+
*
|
|
64
129
|
* @returns A QueryBuilder instance for building and executing queries. {@link QueryBuilder}
|
|
65
130
|
*
|
|
66
131
|
* @example
|
|
@@ -100,7 +165,6 @@ export type PublicArkivActions<
|
|
|
100
165
|
* payload: true,
|
|
101
166
|
* metadata: true,
|
|
102
167
|
* },
|
|
103
|
-
* orderBy: [{ name: "key", type: "string", desc: "asc" }],
|
|
104
168
|
* resultsPerPage: 10,
|
|
105
169
|
* cursor: undefined,
|
|
106
170
|
* atBlock: undefined,
|
|
@@ -200,6 +264,7 @@ export function publicArkivActions<
|
|
|
200
264
|
getEntity: (key: Hex) => getEntity(client, key),
|
|
201
265
|
query: (rawQuery: string, queryOptions?: QueryOptions) => query(client, rawQuery, queryOptions),
|
|
202
266
|
buildQuery: () => new QueryBuilder(client),
|
|
267
|
+
select: (selection?: SelectArg) => new SelectQueryBuilder(client, selection),
|
|
203
268
|
getBlockTiming: () => getBlockTiming(client),
|
|
204
269
|
getEntityCount: () => getEntityCount(client),
|
|
205
270
|
subscribeEntityEvents: (
|
|
@@ -56,6 +56,11 @@ export type WalletArkivActions<
|
|
|
56
56
|
* @param txParams - Optional transaction parameters
|
|
57
57
|
* @returns The created entity with transaction hash
|
|
58
58
|
*
|
|
59
|
+
* @throws {InvalidExpirationError} If `expiresIn` is not a positive integer
|
|
60
|
+
* that is a multiple of the block time (2 seconds).
|
|
61
|
+
* @throws {InvalidAttributeError} If a numeric attribute value is not an
|
|
62
|
+
* integer.
|
|
63
|
+
*
|
|
59
64
|
* @example
|
|
60
65
|
* import { createPublicClient, http } from 'arkiv'
|
|
61
66
|
* import { braga } from 'arkiv/chains'
|
|
@@ -91,6 +96,11 @@ export type WalletArkivActions<
|
|
|
91
96
|
* @param txParams - Optional transaction parameters
|
|
92
97
|
* @returns The updated entity with transaction hash
|
|
93
98
|
*
|
|
99
|
+
* @throws {InvalidExpirationError} If `expiresIn` is not a positive integer
|
|
100
|
+
* that is a multiple of the block time (2 seconds).
|
|
101
|
+
* @throws {InvalidAttributeError} If a numeric attribute value is not an
|
|
102
|
+
* integer.
|
|
103
|
+
*
|
|
94
104
|
* @example
|
|
95
105
|
* import { createWalletClient, http } from 'arkiv'
|
|
96
106
|
* import { braga } from 'arkiv/chains'
|
|
@@ -146,6 +156,9 @@ export type WalletArkivActions<
|
|
|
146
156
|
* @param txParams - Optional transaction parameters
|
|
147
157
|
* @returns The updated entity with transaction hash
|
|
148
158
|
*
|
|
159
|
+
* @throws {InvalidExpirationError} If `expiresIn` is not a positive integer
|
|
160
|
+
* that is a multiple of the block time (2 seconds).
|
|
161
|
+
*
|
|
149
162
|
* @example
|
|
150
163
|
* import { createWalletClient, http } from 'arkiv'
|
|
151
164
|
* import { braga } from 'arkiv/chains'
|
|
@@ -194,6 +207,11 @@ export type WalletArkivActions<
|
|
|
194
207
|
* @param txParams - Optional transaction parameters
|
|
195
208
|
* @returns The mutation result with transaction hash
|
|
196
209
|
*
|
|
210
|
+
* @throws {InvalidExpirationError} If any create/update/extension `expiresIn`
|
|
211
|
+
* is not a positive integer that is a multiple of the block time (2 seconds).
|
|
212
|
+
* @throws {InvalidAttributeError} If a numeric attribute value is not an
|
|
213
|
+
* integer.
|
|
214
|
+
*
|
|
197
215
|
* @example
|
|
198
216
|
* import { createWalletClient, http } from 'arkiv'
|
|
199
217
|
* import { braga } from 'arkiv/chains'
|
package/src/errors.ts
CHANGED
|
@@ -1,9 +1,27 @@
|
|
|
1
|
+
import { BLOCK_TIME } from "./consts"
|
|
2
|
+
|
|
1
3
|
export class EntityMutationError extends Error {
|
|
2
4
|
constructor(message: string) {
|
|
3
5
|
super(message)
|
|
4
6
|
this.name = "EntityMutationError"
|
|
5
7
|
}
|
|
6
8
|
}
|
|
9
|
+
export class InvalidExpirationError extends Error {
|
|
10
|
+
constructor(expiresIn: unknown) {
|
|
11
|
+
super(
|
|
12
|
+
`Invalid expiresIn: ${String(expiresIn)}. expiresIn must be a positive integer and a multiple of the Arkiv block time (${BLOCK_TIME} seconds), because expiration is measured in whole blocks (1 block = ${BLOCK_TIME} seconds).`,
|
|
13
|
+
)
|
|
14
|
+
this.name = "InvalidExpirationError"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export class InvalidAttributeError extends Error {
|
|
18
|
+
constructor(key: string, value: number) {
|
|
19
|
+
super(
|
|
20
|
+
`Invalid numeric value for attribute "${key}": ${String(value)}. Numeric attribute values must be integers. To keep numeric ordering/range queries, scale it to an integer (e.g. Math.round(${String(value)} * 1000), dividing by 1000 on read); otherwise store it as a string (e.g. "${String(value)}").`,
|
|
21
|
+
)
|
|
22
|
+
this.name = "InvalidAttributeError"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
7
25
|
|
|
8
26
|
export class NoMoreResultsError extends Error {
|
|
9
27
|
constructor() {
|
package/src/index.ts
CHANGED
package/src/query/engine.ts
CHANGED
|
@@ -55,6 +55,11 @@ export async function processQuery(
|
|
|
55
55
|
withAttributes?: boolean | undefined
|
|
56
56
|
withMetadata?: boolean | undefined
|
|
57
57
|
withPayload?: boolean | undefined
|
|
58
|
+
/**
|
|
59
|
+
* Fully-resolved include-data for fine-grained selection. When provided it takes
|
|
60
|
+
* precedence over the `withAttributes`/`withMetadata`/`withPayload` booleans.
|
|
61
|
+
*/
|
|
62
|
+
includeData?: RpcIncludeData | undefined
|
|
58
63
|
},
|
|
59
64
|
) {
|
|
60
65
|
const {
|
|
@@ -68,6 +73,7 @@ export async function processQuery(
|
|
|
68
73
|
withAttributes,
|
|
69
74
|
withMetadata,
|
|
70
75
|
withPayload,
|
|
76
|
+
includeData,
|
|
71
77
|
} = queryParams
|
|
72
78
|
|
|
73
79
|
logger("Processing query with params %o", {
|
|
@@ -81,6 +87,7 @@ export async function processQuery(
|
|
|
81
87
|
withAttributes,
|
|
82
88
|
withMetadata,
|
|
83
89
|
withPayload,
|
|
90
|
+
includeData,
|
|
84
91
|
})
|
|
85
92
|
|
|
86
93
|
let query = processPredicates(predicates)
|
|
@@ -98,19 +105,21 @@ export async function processQuery(
|
|
|
98
105
|
}
|
|
99
106
|
|
|
100
107
|
const queryOptions: RpcQueryOptions = {
|
|
101
|
-
includeData:
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
108
|
+
includeData:
|
|
109
|
+
includeData ??
|
|
110
|
+
({
|
|
111
|
+
key: true,
|
|
112
|
+
attributes: withAttributes ?? false,
|
|
113
|
+
payload: withPayload ?? false,
|
|
114
|
+
contentType: withMetadata ?? false,
|
|
115
|
+
expiration: withMetadata ?? false,
|
|
116
|
+
owner: withMetadata ?? false,
|
|
117
|
+
creator: withMetadata ?? false,
|
|
118
|
+
createdAtBlock: withMetadata ?? false,
|
|
119
|
+
lastModifiedAtBlock: withMetadata ?? false,
|
|
120
|
+
transactionIndexInBlock: withMetadata ?? false,
|
|
121
|
+
operationIndexInTransaction: withMetadata ?? false,
|
|
122
|
+
} as RpcIncludeData),
|
|
114
123
|
}
|
|
115
124
|
|
|
116
125
|
if (validAtBlock !== undefined) {
|
package/src/query/index.ts
CHANGED
|
@@ -244,6 +244,27 @@ describe("Predicate Factory Functions", () => {
|
|
|
244
244
|
})
|
|
245
245
|
})
|
|
246
246
|
|
|
247
|
+
test("creates or predicate from varargs", () => {
|
|
248
|
+
const result = or(eq("type", "admin"), eq("type", "moderator"))
|
|
249
|
+
|
|
250
|
+
expect(result).toEqual({
|
|
251
|
+
type: "or",
|
|
252
|
+
predicates: [
|
|
253
|
+
{ type: "eq", key: "type", value: "admin" },
|
|
254
|
+
{ type: "eq", key: "type", value: "moderator" },
|
|
255
|
+
],
|
|
256
|
+
})
|
|
257
|
+
})
|
|
258
|
+
|
|
259
|
+
test("creates or predicate with no arguments", () => {
|
|
260
|
+
const result = or()
|
|
261
|
+
|
|
262
|
+
expect(result).toEqual({
|
|
263
|
+
type: "or",
|
|
264
|
+
predicates: [],
|
|
265
|
+
})
|
|
266
|
+
})
|
|
267
|
+
|
|
247
268
|
test("creates or predicate with nested and", () => {
|
|
248
269
|
const nestedAnd = and([eq("verified", 1), gte("age", 18)])
|
|
249
270
|
const predicates = [eq("status", "premium"), nestedAnd]
|
|
@@ -314,6 +335,28 @@ describe("Predicate Factory Functions", () => {
|
|
|
314
335
|
})
|
|
315
336
|
})
|
|
316
337
|
|
|
338
|
+
test("creates and predicate from varargs", () => {
|
|
339
|
+
const result = and(eq("status", "active"), gte("age", 18), not("deleted"))
|
|
340
|
+
|
|
341
|
+
expect(result).toEqual({
|
|
342
|
+
type: "and",
|
|
343
|
+
predicates: [
|
|
344
|
+
{ type: "eq", key: "status", value: "active" },
|
|
345
|
+
{ type: "gte", key: "age", value: 18 },
|
|
346
|
+
{ type: "not", key: "deleted", value: "" },
|
|
347
|
+
],
|
|
348
|
+
})
|
|
349
|
+
})
|
|
350
|
+
|
|
351
|
+
test("creates and predicate with no arguments", () => {
|
|
352
|
+
const result = and()
|
|
353
|
+
|
|
354
|
+
expect(result).toEqual({
|
|
355
|
+
type: "and",
|
|
356
|
+
predicates: [],
|
|
357
|
+
})
|
|
358
|
+
})
|
|
359
|
+
|
|
317
360
|
test("creates and predicate with nested or", () => {
|
|
318
361
|
const nestedOr = or([eq("type", "admin"), eq("type", "moderator")])
|
|
319
362
|
const predicates = [eq("active", 1), nestedOr]
|
package/src/query/predicate.ts
CHANGED
|
@@ -14,32 +14,36 @@ export type Predicate =
|
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* Creates an OR predicate
|
|
17
|
-
* @param predicates - The predicates to combine
|
|
17
|
+
* @param predicates - The predicates to combine, either as a single array or as separate arguments
|
|
18
18
|
* @returns The OR predicate
|
|
19
19
|
*
|
|
20
20
|
* @example
|
|
21
|
-
* const
|
|
22
|
-
*
|
|
21
|
+
* const result = or(eq("name", "John"), eq("age", 30))
|
|
22
|
+
* // or equivalently: or([eq("name", "John"), eq("age", 30)])
|
|
23
23
|
* // result = { type: "or", predicates: [eq("name", "John"), eq("age", 30)] }
|
|
24
24
|
*
|
|
25
25
|
*/
|
|
26
|
-
export function or(predicates: Predicate[]): Predicate
|
|
27
|
-
|
|
26
|
+
export function or(predicates: Predicate[]): Predicate
|
|
27
|
+
export function or(...predicates: Predicate[]): Predicate
|
|
28
|
+
export function or(...predicates: (Predicate | Predicate[])[]): Predicate {
|
|
29
|
+
return { type: "or", predicates: predicates.flat() }
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
/**
|
|
31
33
|
* Creates an AND predicate
|
|
32
|
-
* @param predicates - The predicates to combine
|
|
34
|
+
* @param predicates - The predicates to combine, either as a single array or as separate arguments
|
|
33
35
|
* @returns The AND predicate
|
|
34
36
|
*
|
|
35
37
|
* @example
|
|
36
|
-
* const
|
|
37
|
-
*
|
|
38
|
+
* const result = and(eq("name", "John"), eq("age", 30))
|
|
39
|
+
* // or equivalently: and([eq("name", "John"), eq("age", 30)])
|
|
38
40
|
* // result = { type: "and", predicates: [eq("name", "John"), eq("age", 30)] }
|
|
39
41
|
*
|
|
40
42
|
*/
|
|
41
|
-
export function and(predicates: Predicate[]): Predicate
|
|
42
|
-
|
|
43
|
+
export function and(predicates: Predicate[]): Predicate
|
|
44
|
+
export function and(...predicates: Predicate[]): Predicate
|
|
45
|
+
export function and(...predicates: (Predicate | Predicate[])[]): Predicate {
|
|
46
|
+
return { type: "and", predicates: predicates.flat() }
|
|
43
47
|
}
|
|
44
48
|
|
|
45
49
|
/**
|
|
@@ -78,6 +78,28 @@ describe("QueryBuilder", () => {
|
|
|
78
78
|
})
|
|
79
79
|
})
|
|
80
80
|
|
|
81
|
+
test("adds multiple predicates as varargs", async () => {
|
|
82
|
+
mockProcessQuery.mockResolvedValue({
|
|
83
|
+
data: [],
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
const builder = new QueryBuilder(mockClient)
|
|
87
|
+
await builder.where(eq("name", "test"), gt("age", 18), neq("status", "inactive")).fetch()
|
|
88
|
+
|
|
89
|
+
expect(mockProcessQuery).toHaveBeenCalledWith(mockClient, {
|
|
90
|
+
predicates: [eq("name", "test"), gt("age", 18), neq("status", "inactive")],
|
|
91
|
+
limit: undefined,
|
|
92
|
+
offset: undefined,
|
|
93
|
+
ownedBy: undefined,
|
|
94
|
+
createdBy: undefined,
|
|
95
|
+
orderBy: undefined,
|
|
96
|
+
validBeforeBlock: undefined,
|
|
97
|
+
withAttributes: undefined,
|
|
98
|
+
withMetadata: undefined,
|
|
99
|
+
withPayload: undefined,
|
|
100
|
+
})
|
|
101
|
+
})
|
|
102
|
+
|
|
81
103
|
test("chains multiple where() calls", async () => {
|
|
82
104
|
mockProcessQuery.mockResolvedValue({
|
|
83
105
|
data: [],
|