@spacelr/sdk 0.2.1 → 0.2.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.
package/dist/index.mjs CHANGED
@@ -1642,6 +1642,68 @@ var StorageModule = class {
1642
1642
  };
1643
1643
 
1644
1644
  // libs/sdk/src/modules/database.module.ts
1645
+ var Paginator = class {
1646
+ constructor(http, basePath, opts) {
1647
+ this.http = http;
1648
+ this.basePath = basePath;
1649
+ this._exhausted = false;
1650
+ /**
1651
+ * Tail of the serialized `next()` chain. Each call appends to this so
1652
+ * concurrent invocations from a UI scroll handler (e.g. user spam-tapping
1653
+ * "load more") don't issue parallel requests with the same cursor — which
1654
+ * would return duplicate pages and clobber the cursor based on whichever
1655
+ * response settles last. Calls execute strictly in invocation order.
1656
+ */
1657
+ this.chain = Promise.resolve({
1658
+ documents: [],
1659
+ hasMore: false
1660
+ });
1661
+ this.cursor = opts.cursor;
1662
+ this.direction = opts.sort?._id ?? -1;
1663
+ this.pageSize = opts.limit ?? 50;
1664
+ this.where = opts.where;
1665
+ }
1666
+ /**
1667
+ * True once a `next()` call has returned an empty page. Subsequent
1668
+ * `next()` calls return an empty page without hitting the server.
1669
+ *
1670
+ * Note: only the empty-page signal flips this flag; a server response
1671
+ * that returns documents but `hasMore: false` does NOT exhaust. This
1672
+ * lets ascending paginators (`sort: { _id: 1 }`) keep polling for
1673
+ * documents inserted after the caller caught up to the current tail —
1674
+ * the next `.after(lastSeen)` call will simply return zero documents
1675
+ * until something new lands.
1676
+ */
1677
+ get exhausted() {
1678
+ return this._exhausted;
1679
+ }
1680
+ next() {
1681
+ const run = this.chain.then(
1682
+ () => this.fetchNextPage(),
1683
+ () => this.fetchNextPage()
1684
+ );
1685
+ this.chain = run;
1686
+ return run;
1687
+ }
1688
+ async fetchNextPage() {
1689
+ if (this._exhausted) return { documents: [], hasMore: false };
1690
+ const builder = new QueryBuilder(this.http, this.basePath, this.where).sort({ _id: this.direction }).limit(this.pageSize);
1691
+ let result;
1692
+ if (this.cursor !== void 0) {
1693
+ const cursorBuilder = this.direction === -1 ? builder.before(this.cursor) : builder.after(this.cursor);
1694
+ result = await cursorBuilder.execute();
1695
+ } else {
1696
+ result = await builder.execute();
1697
+ }
1698
+ if (result.documents.length === 0) {
1699
+ this._exhausted = true;
1700
+ return { documents: [], hasMore: false };
1701
+ }
1702
+ this.cursor = result.documents[result.documents.length - 1]._id;
1703
+ const hasMore = result.mode === "cursor" ? result.hasMore : result.documents.length < result.total;
1704
+ return { documents: result.documents, hasMore };
1705
+ }
1706
+ };
1645
1707
  var QueryBuilder = class {
1646
1708
  constructor(http, basePath, filter) {
1647
1709
  this.http = http;
@@ -1758,6 +1820,20 @@ var CollectionRef = class {
1758
1820
  find(filter) {
1759
1821
  return new QueryBuilder(this.http, this.basePath, filter);
1760
1822
  }
1823
+ /**
1824
+ * Cursor-based scroll-back helper. Returns a `Paginator` whose `.next()`
1825
+ * yields successive pages and tracks the last-seen `_id` internally.
1826
+ * Defaults to descending sort and 50 docs per page (chat scroll-back is
1827
+ * the canonical use case). See `PaginateOptions` for tuning.
1828
+ *
1829
+ * **Cursor constraint:** uses `_id` keyset pagination, which requires
1830
+ * 24-hex ObjectId `_id`s. Collections with custom string `_id` schemes
1831
+ * fall back to comparing strings as ObjectIds — the server's handler
1832
+ * documents this limitation on `before` / `after` directly.
1833
+ */
1834
+ paginate(opts = {}) {
1835
+ return new Paginator(this.http, this.basePath, opts);
1836
+ }
1761
1837
  /**
1762
1838
  * Server-side substring search across the specified fields.
1763
1839
  *