@arkiv-network/sdk 0.6.8-dev.1 → 0.6.8-dev.2

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.
Files changed (56) hide show
  1. package/README.md +52 -16
  2. package/dist/chains/index.d.cts +25 -25
  3. package/dist/{query-CO6f35AE.d.cts → entity-B3qWIdug.d.cts} +26 -26
  4. package/dist/entity-B3qWIdug.d.cts.map +1 -0
  5. package/dist/{query-BhdmAzYg.d.ts → entity-BOra9GVW.d.ts} +26 -26
  6. package/dist/entity-BOra9GVW.d.ts.map +1 -0
  7. package/dist/{queryBuilder-zTsKXctT.d.cts → index-Dushe05u.d.cts} +202 -74
  8. package/dist/index-Dushe05u.d.cts.map +1 -0
  9. package/dist/{queryBuilder-BvoQXa_u.d.ts → index-t3wvdqvC.d.ts} +202 -74
  10. package/dist/index-t3wvdqvC.d.ts.map +1 -0
  11. package/dist/index.cjs +3 -8
  12. package/dist/index.d.cts +65 -3
  13. package/dist/index.d.cts.map +1 -1
  14. package/dist/index.d.ts +65 -3
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +2 -3
  17. package/dist/index.js.map +1 -1
  18. package/dist/query/index.cjs +5 -2
  19. package/dist/query/index.d.cts +3 -3
  20. package/dist/query/index.d.ts +3 -3
  21. package/dist/query/index.js +2 -2
  22. package/dist/{queryBuilder-DM-YO1Y7.cjs → queryBuilder-BlMPfusd.cjs} +204 -70
  23. package/dist/{queryBuilder-DonAg1aq.js → queryBuilder-D7iYS0vU.js} +188 -72
  24. package/dist/queryBuilder-D7iYS0vU.js.map +1 -0
  25. package/dist/types/index.d.cts +1 -1
  26. package/dist/types/index.d.ts +1 -1
  27. package/dist/utils/index.cjs +1 -8
  28. package/dist/utils/index.d.cts +0 -1
  29. package/dist/utils/index.d.cts.map +1 -1
  30. package/dist/utils/index.d.ts +0 -1
  31. package/dist/utils/index.d.ts.map +1 -1
  32. package/dist/utils/index.js +0 -2
  33. package/dist/utils/index.js.map +1 -1
  34. package/package.json +11 -15
  35. package/src/actions/public/buildQuery.ts +4 -0
  36. package/src/clients/createPublicClient.test.ts +2 -0
  37. package/src/clients/decorators/arkivPublic.ts +67 -1
  38. package/src/index.ts +0 -3
  39. package/src/query/engine.ts +22 -13
  40. package/src/query/index.ts +1 -0
  41. package/src/query/queryBuilder.ts +189 -94
  42. package/src/query/queryResult.ts +13 -7
  43. package/src/query/selectQueryBuilder.test.ts +210 -0
  44. package/src/query/selection.test.ts +120 -0
  45. package/src/query/selection.ts +116 -0
  46. package/src/utils/index.ts +0 -1
  47. package/dist/accounts/index.cjs +0 -9
  48. package/dist/accounts/index.d.cts +0 -1
  49. package/dist/accounts/index.d.ts +0 -1
  50. package/dist/accounts/index.js +0 -1
  51. package/dist/query-BhdmAzYg.d.ts.map +0 -1
  52. package/dist/query-CO6f35AE.d.cts.map +0 -1
  53. package/dist/queryBuilder-BvoQXa_u.d.ts.map +0 -1
  54. package/dist/queryBuilder-DonAg1aq.js.map +0 -1
  55. package/dist/queryBuilder-zTsKXctT.d.cts.map +0 -1
  56. package/src/accounts/index.ts +0 -1
@@ -235,7 +235,7 @@ function processPredicates(predicates) {
235
235
  }).join(" && ");
236
236
  }
237
237
  async function processQuery(client, queryParams) {
238
- const { predicates, limit, cursor, ownedBy, createdBy, orderBy, validAtBlock, withAttributes, withMetadata, withPayload } = queryParams;
238
+ const { predicates, limit, cursor, ownedBy, createdBy, orderBy, validAtBlock, withAttributes, withMetadata, withPayload, includeData } = queryParams;
239
239
  logger$1("Processing query with params %o", {
240
240
  predicates,
241
241
  cursor,
@@ -246,14 +246,15 @@ async function processQuery(client, queryParams) {
246
246
  validAtBlock,
247
247
  withAttributes,
248
248
  withMetadata,
249
- withPayload
249
+ withPayload,
250
+ includeData
250
251
  });
251
252
  let query = processPredicates(predicates);
252
253
  if (ownedBy) query += ` && $owner=${ownedBy}`;
253
254
  if (createdBy) query += ` && $creator=${createdBy}`;
254
255
  query = query.trim();
255
256
  if (query.startsWith("&& ")) query = query.slice(3);
256
- const queryOptions = { includeData: {
257
+ const queryOptions = { includeData: includeData ?? {
257
258
  key: true,
258
259
  attributes: withAttributes ?? false,
259
260
  payload: withPayload ?? false,
@@ -288,6 +289,12 @@ async function processQuery(client, queryParams) {
288
289
  //#endregion
289
290
  //#region src/query/queryResult.ts
290
291
  const logger = getLogger("query:result");
292
+ /**
293
+ * The result of a query. Holds the fetched entities and supports cursor-based pagination.
294
+ *
295
+ * @typeParam TEntity - The shape of each entity, inferred from the query builder
296
+ * (a full {@link Entity}, or a projected object inferred from a `select()` selection).
297
+ */
291
298
  var QueryResult = class {
292
299
  entities;
293
300
  _endOfIteration;
@@ -325,6 +332,53 @@ var QueryResult = class {
325
332
  }
326
333
  };
327
334
 
335
+ //#endregion
336
+ //#region src/query/selection.ts
337
+ /**
338
+ * Converts a {@link SelectArg} into the {@link RpcIncludeData} understood by the query engine.
339
+ * Every field is opt-in — anything not explicitly selected defaults to `false`, including the key.
340
+ * `undefined` or `"*"` selects everything.
341
+ *
342
+ * @param selection - The selection to convert
343
+ * @returns The fully-resolved include-data object for the RPC query
344
+ * @throws If an empty selection object is provided
345
+ *
346
+ * @example
347
+ * selectionToIncludeData() // everything
348
+ * selectionToIncludeData("*") // everything
349
+ * selectionToIncludeData({ key: true }) // only the key
350
+ * selectionToIncludeData({ owner: true }) // only the owner
351
+ */
352
+ function selectionToIncludeData(selection) {
353
+ if (selection === void 0 || selection === "*") return {
354
+ key: true,
355
+ attributes: true,
356
+ payload: true,
357
+ contentType: true,
358
+ expiration: true,
359
+ owner: true,
360
+ creator: true,
361
+ createdAtBlock: true,
362
+ lastModifiedAtBlock: true,
363
+ transactionIndexInBlock: true,
364
+ operationIndexInTransaction: true
365
+ };
366
+ if (!Object.values(selection).some((selected) => selected === true)) throw new Error("select() requires at least one field to be selected. Pass select() or select(\"*\") to select everything.");
367
+ return {
368
+ key: selection.key ?? false,
369
+ attributes: selection.attributes ?? false,
370
+ payload: selection.payload ?? false,
371
+ contentType: selection.contentType ?? false,
372
+ expiration: selection.expiresAtBlock ?? false,
373
+ owner: selection.owner ?? false,
374
+ creator: selection.creator ?? false,
375
+ createdAtBlock: selection.createdAtBlock ?? false,
376
+ lastModifiedAtBlock: selection.lastModifiedAtBlock ?? false,
377
+ transactionIndexInBlock: selection.transactionIndexInBlock ?? false,
378
+ operationIndexInTransaction: selection.operationIndexInTransaction ?? false
379
+ };
380
+ }
381
+
328
382
  //#endregion
329
383
  //#region src/query/queryBuilder.ts
330
384
  /**
@@ -360,20 +414,21 @@ function desc(attributeName, attributeType) {
360
414
  };
361
415
  }
362
416
  /**
363
- * QueryBuilder is a helper class to build queries to the Arkiv DBChains.
364
- * It can be used to fetch entities from the Arkiv DBChains. It follows the Builder pattern allowing chaining of methods.
365
- * @param client - The Arkiv client
366
- * @returns The QueryBuilder instance {@link QueryBuilder}
417
+ * BaseQueryBuilder holds the query-building logic shared by every query builder
418
+ * (filtering, ordering, pagination, execution). It follows the Builder pattern,
419
+ * allowing methods to be chained. Subclasses decide how data selection is expressed
420
+ * by implementing the protected `selectionParams` method.
421
+ *
422
+ * Use {@link SelectQueryBuilder} via `client.select()` to build and execute queries.
423
+ *
424
+ * @typeParam TEntity - The shape of each entity produced by {@link BaseQueryBuilder.fetch}.
367
425
  */
368
- var QueryBuilder = class {
426
+ var BaseQueryBuilder = class {
369
427
  _client;
370
428
  _ownedBy;
371
429
  _createdBy;
372
430
  _orderBy;
373
431
  _validAtBlock;
374
- _withAttributes;
375
- _withMetadata;
376
- _withPayload;
377
432
  _limit;
378
433
  _cursor;
379
434
  _predicates;
@@ -384,10 +439,10 @@ var QueryBuilder = class {
384
439
  /**
385
440
  * Sets the ownedBy filter
386
441
  * @param ownedBy - The address of the owner
387
- * @returns The QueryBuilder instance
442
+ * @returns The query builder instance
388
443
  *
389
444
  * @example
390
- * const builder = new QueryBuilder(client)
445
+ * const builder = client.select()
391
446
  * builder.ownedBy("0x1234567890123456789012345678901234567890")
392
447
  */
393
448
  ownedBy(ownedBy) {
@@ -397,10 +452,10 @@ var QueryBuilder = class {
397
452
  /**
398
453
  * Sets the createdBy filter
399
454
  * @param createdBy - The address of the creator
400
- * @returns The QueryBuilder instance
455
+ * @returns The query builder instance
401
456
  *
402
457
  * @example
403
- * const builder = new QueryBuilder(client)
458
+ * const builder = client.select()
404
459
  * builder.createdBy("0x1234567890123456789012345678901234567890")
405
460
  */
406
461
  createdBy(createdBy) {
@@ -427,51 +482,12 @@ var QueryBuilder = class {
427
482
  return this;
428
483
  }
429
484
  /**
430
- * Sets the withAttributes flag which will return the attributes for the entities if true
431
- * @param withAttributes - The boolean value to set
432
- * @returns The QueryBuilder instance
433
- *
434
- * @example
435
- * const builder = new QueryBuilder(client)
436
- * builder.withAttributes(true)
437
- */
438
- withAttributes(withAttributes = true) {
439
- this._withAttributes = withAttributes;
440
- return this;
441
- }
442
- /**
443
- * Sets the withMetadata flag which will return the metadata (like owner, expiredAt, etc.) for the entities if true
444
- * @param withMetadata - The boolean value to set
445
- * @returns The QueryBuilder instance
446
- *
447
- * @example
448
- * const builder = new QueryBuilder(client)
449
- * builder.withMetadata(true)
450
- */
451
- withMetadata(withMetadata = true) {
452
- this._withMetadata = withMetadata;
453
- return this;
454
- }
455
- /**
456
- * Sets the withPayload flag which will return the payload for the entities if true
457
- * @param withPayload - The boolean value to set
458
- * @returns The QueryBuilder instance
459
- *
460
- * @example
461
- * const builder = new QueryBuilder(client)
462
- * builder.withPayload(true)
463
- */
464
- withPayload(withPayload = true) {
465
- this._withPayload = withPayload;
466
- return this;
467
- }
468
- /**
469
485
  * Sets the limit for the query
470
486
  * @param limit - The number of entities to return
471
- * @returns The QueryBuilder instance
487
+ * @returns The query builder instance
472
488
  *
473
489
  * @example
474
- * const builder = new QueryBuilder(client)
490
+ * const builder = client.select()
475
491
  * builder.limit(10)
476
492
  */
477
493
  limit(limit) {
@@ -481,11 +497,11 @@ var QueryBuilder = class {
481
497
  /**
482
498
  * 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).
483
499
  * @param cursor - The cursor to set which tells to RPC Query server where to start or continue the query.
484
- * @returns The QueryBuilder instance
500
+ * @returns The query builder instance
485
501
  *
486
502
  * @example
487
- * const builder = new QueryBuilder(client)
488
- * builder.offset(10)
503
+ * const builder = client.select()
504
+ * builder.cursor("0xABC123")
489
505
  */
490
506
  cursor(cursor) {
491
507
  this._cursor = cursor;
@@ -495,10 +511,10 @@ var QueryBuilder = class {
495
511
  * Sets the validAtBlock for the query which tells at which block height the state we are intested.
496
512
  * If not set, the latest block is used.
497
513
  * @param validAtBlock - The block number to set
498
- * @returns The QueryBuilder instance
514
+ * @returns The query builder instance
499
515
  *
500
516
  * @example
501
- * const builder = new QueryBuilder(client)
517
+ * const builder = client.select()
502
518
  * builder.validAtBlock(10000)
503
519
  */
504
520
  validAtBlock(validAtBlock) {
@@ -509,10 +525,10 @@ var QueryBuilder = class {
509
525
  * Sets the predicates for the query limiting the results. It can be a single predicate or an array of predicates combined with 'and'.
510
526
  * Predicates can be nested using 'or' and 'and' predicates.
511
527
  * @param predicates - The predicates to set
512
- * @returns The QueryBuilder instance
528
+ * @returns The query builder instance
513
529
  *
514
530
  * @example
515
- * const builder = new QueryBuilder(client)
531
+ * const builder = client.select()
516
532
  * builder.where(eq("name", "John"))
517
533
  * builder.where([eq("name", "John"), eq("age", 30)])
518
534
  * builder.where([eq("name", "John"), or([eq("age", 30), eq("age", 31)])])
@@ -527,12 +543,12 @@ var QueryBuilder = class {
527
543
  return this;
528
544
  }
529
545
  /**
530
- * Fetches the entities from the query. Re
546
+ * Fetches the entities from the query.
531
547
  * It will return a QueryResult instance which can be used to fetch the next and previous pages.
532
548
  * @returns The QueryResult instance {@link QueryResult}
533
549
  *
534
550
  * @example
535
- * const builder = new QueryBuilder(client)
551
+ * const builder = client.select()
536
552
  * const result = await builder.where(eq("name", "John")).fetch()
537
553
  * // result = { entities: [Entity, Entity, Entity], next: async () => QueryResult, previous: async () => QueryResult }
538
554
  */
@@ -545,11 +561,9 @@ var QueryBuilder = class {
545
561
  createdBy: this._createdBy,
546
562
  orderBy: this._orderBy,
547
563
  validAtBlock: this._validAtBlock,
548
- withAttributes: this._withAttributes,
549
- withMetadata: this._withMetadata,
550
- withPayload: this._withPayload
564
+ ...this.selectionParams()
551
565
  });
552
- const entities = await Promise.all(queryResult.data.map((entity) => entityFromRpcResult(entity)));
566
+ const entities = await Promise.all(queryResult.data.map((entity) => this.projectEntity(entity)));
553
567
  this.cursor(queryResult.cursor);
554
568
  this.validAtBlock(BigInt(queryResult.blockNumber ?? 0));
555
569
  return new QueryResult(entities, this, this._cursor, this._limit, this._validAtBlock);
@@ -559,7 +573,7 @@ var QueryBuilder = class {
559
573
  * @returns The number of entities
560
574
  *
561
575
  * @example
562
- * const builder = new QueryBuilder(client)
576
+ * const builder = client.select()
563
577
  * const result = await builder.where(eq("name", "John")).count()
564
578
  * // result = 10
565
579
  */
@@ -578,8 +592,116 @@ var QueryBuilder = class {
578
592
  })).data.length ?? 0;
579
593
  }
580
594
  };
595
+ /**
596
+ * QueryBuilder is a helper class to build queries to the Arkiv DBChains.
597
+ * It can be used to fetch entities from the Arkiv DBChains. It follows the Builder pattern allowing chaining of methods.
598
+ *
599
+ * By default the result includes only the entity `key`. Additional data is opt-in through
600
+ * `withAttributes()`, `withMetadata()` and `withPayload()`.
601
+ *
602
+ * @deprecated Use {@link SelectQueryBuilder} via `client.select()` instead. Declaring the
603
+ * selection up front avoids the common mistake of forgetting to opt in to data and getting back
604
+ * entities with only their `key` populated. This class remains for backwards compatibility and
605
+ * will be removed in a future release.
606
+ *
607
+ * @param client - The Arkiv client
608
+ * @returns The QueryBuilder instance {@link QueryBuilder}
609
+ */
610
+ var QueryBuilder = class extends BaseQueryBuilder {
611
+ _withAttributes;
612
+ _withMetadata;
613
+ _withPayload;
614
+ /**
615
+ * Sets the withAttributes flag which will return the attributes for the entities if true
616
+ * @param withAttributes - The boolean value to set
617
+ * @returns The QueryBuilder instance
618
+ *
619
+ * @example
620
+ * const builder = client.buildQuery()
621
+ * builder.withAttributes(true)
622
+ */
623
+ withAttributes(withAttributes = true) {
624
+ this._withAttributes = withAttributes;
625
+ return this;
626
+ }
627
+ /**
628
+ * Sets the withMetadata flag which will return the metadata (like owner, expiredAt, etc.) for the entities if true
629
+ * @param withMetadata - The boolean value to set
630
+ * @returns The QueryBuilder instance
631
+ *
632
+ * @example
633
+ * const builder = client.buildQuery()
634
+ * builder.withMetadata(true)
635
+ */
636
+ withMetadata(withMetadata = true) {
637
+ this._withMetadata = withMetadata;
638
+ return this;
639
+ }
640
+ /**
641
+ * Sets the withPayload flag which will return the payload for the entities if true
642
+ * @param withPayload - The boolean value to set
643
+ * @returns The QueryBuilder instance
644
+ *
645
+ * @example
646
+ * const builder = client.buildQuery()
647
+ * builder.withPayload(true)
648
+ */
649
+ withPayload(withPayload = true) {
650
+ this._withPayload = withPayload;
651
+ return this;
652
+ }
653
+ selectionParams() {
654
+ return {
655
+ withAttributes: this._withAttributes,
656
+ withMetadata: this._withMetadata,
657
+ withPayload: this._withPayload
658
+ };
659
+ }
660
+ projectEntity(rpcEntity) {
661
+ return entityFromRpcResult(rpcEntity);
662
+ }
663
+ };
664
+ /**
665
+ * SelectQueryBuilder is the recommended query builder. It requires the selection to be declared
666
+ * up front, so results always contain exactly the data you asked for — and the type of each
667
+ * returned entity is narrowed to exactly the selected fields.
668
+ *
669
+ * The selection is fixed at construction time and is flat — each field maps to an entity field.
670
+ * Create one via `client.select(...)` rather than constructing it directly, so the result type is
671
+ * inferred from the selection.
672
+ *
673
+ * @typeParam TEntity - The projected entity shape, inferred from the selection by `client.select()`.
674
+ *
675
+ * @example
676
+ * // everything
677
+ * await client.select().where(eq("name", "John")).fetch()
678
+ * await client.select("*").where(eq("name", "John")).fetch()
679
+ * // specific fields
680
+ * await client.select({ owner: true, attributes: true }).fetch()
681
+ * // a single field — result is typed (flat) { owner: Hex }
682
+ * await client.select({ owner: true }).fetch()
683
+ */
684
+ var SelectQueryBuilder = class extends BaseQueryBuilder {
685
+ _includeData;
686
+ constructor(client, selection) {
687
+ super(client);
688
+ this._includeData = selectionToIncludeData(selection);
689
+ }
690
+ selectionParams() {
691
+ return { includeData: this._includeData };
692
+ }
693
+ async projectEntity(rpcEntity) {
694
+ return await entityFromRpcResult(rpcEntity);
695
+ }
696
+ };
581
697
 
582
698
  //#endregion
699
+ Object.defineProperty(exports, 'BaseQueryBuilder', {
700
+ enumerable: true,
701
+ get: function () {
702
+ return BaseQueryBuilder;
703
+ }
704
+ });
583
705
  Object.defineProperty(exports, 'EntityMutationError', {
584
706
  enumerable: true,
585
707
  get: function () {
@@ -616,6 +738,12 @@ Object.defineProperty(exports, 'QueryResult', {
616
738
  return QueryResult;
617
739
  }
618
740
  });
741
+ Object.defineProperty(exports, 'SelectQueryBuilder', {
742
+ enumerable: true,
743
+ get: function () {
744
+ return SelectQueryBuilder;
745
+ }
746
+ });
619
747
  Object.defineProperty(exports, 'asc', {
620
748
  enumerable: true,
621
749
  get: function () {
@@ -639,4 +767,10 @@ Object.defineProperty(exports, 'getLogger', {
639
767
  get: function () {
640
768
  return getLogger;
641
769
  }
770
+ });
771
+ Object.defineProperty(exports, 'selectionToIncludeData', {
772
+ enumerable: true,
773
+ get: function () {
774
+ return selectionToIncludeData;
775
+ }
642
776
  });