@rebasepro/common 0.13.0 → 0.13.1-canary.g3660bd5

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.
@@ -45,6 +45,26 @@ export declare class RebasePaginationError extends Error {
45
45
  }
46
46
  /** The one thing a transport has to provide to be paginated. */
47
47
  export type PageFinder<M extends Record<string, unknown> = Record<string, unknown>> = (params: FindParams<M>) => Promise<FindResult<M>>;
48
+ /**
49
+ * Resolve `limit`/`offset`/`page` into the window a read will actually use.
50
+ *
51
+ * Lives here, next to the walk, for the reason at the top of this file: every
52
+ * transport has to mean the same thing by "page two". Four of them did not —
53
+ * the REST layer strode by {@link DEFAULT_LIST_LIMIT}, the local-first
54
+ * evaluator by {@link DEFAULT_PAGE_SIZE}, the in-process accessor by 20, and
55
+ * the published type documented a fourth number. Pages that overlap or skip
56
+ * rows are the mildest of those outcomes.
57
+ *
58
+ * `page` wins over `offset`, as {@link FindParams} documents. `driverOffset`
59
+ * is the value to hand a driver: it stays `undefined` when the caller named no
60
+ * offset, because keyset pagination seeks with a `where` clause and must not
61
+ * look like it is paging by offset.
62
+ */
63
+ export declare function resolveFindWindow(params?: Pick<FindParams, "limit" | "offset" | "page">): {
64
+ limit: number;
65
+ offset: number;
66
+ driverOffset: number | undefined;
67
+ };
48
68
  /**
49
69
  * Walk every row a query matches, yielding one row at a time and fetching the
50
70
  * next page only when the consumer asks for it.
package/dist/index.es.js CHANGED
@@ -1,4 +1,4 @@
1
- import { ANONYMOUS_USER_ID, ANONYMOUS_USER_IDS, CANONICAL_TO_REST, DEFAULT_DATA_SOURCE_KEY, EntityReference, EntityRelation, NULL_OPS, REST_TO_CANONICAL, getDataSourceCapabilities, getDeclaredSubcollections, isAnonymousUid, isManyToMany, isPostgresCollectionConfig, isRelationalCollectionConfig, policy, toCanonicalOp } from "@rebasepro/types";
1
+ import { ANONYMOUS_USER_ID, ANONYMOUS_USER_IDS, CANONICAL_TO_REST, DEFAULT_DATA_SOURCE_KEY, DEFAULT_LIST_LIMIT, EntityReference, EntityRelation, NULL_OPS, REST_TO_CANONICAL, getDataSourceCapabilities, getDeclaredSubcollections, isAnonymousUid, isManyToMany, isPostgresCollectionConfig, isRelationalCollectionConfig, policy, toCanonicalOp } from "@rebasepro/types";
2
2
  import { deepClone, generateForeignKeyName, getIn, getPolicyNamesForRules, getPolicyOperations, isDefaultFieldConfigId, mergeDeep, prettifyIdentifier, randomString, removeFunctions, toSnakeCase } from "@rebasepro/utils";
3
3
  import jsonLogic from "json-logic-js";
4
4
  import { deepEqual } from "fast-equals";
@@ -2861,6 +2861,30 @@ var RebasePaginationError = class RebasePaginationError extends Error {
2861
2861
  Object.setPrototypeOf(this, RebasePaginationError.prototype);
2862
2862
  }
2863
2863
  };
2864
+ /**
2865
+ * Resolve `limit`/`offset`/`page` into the window a read will actually use.
2866
+ *
2867
+ * Lives here, next to the walk, for the reason at the top of this file: every
2868
+ * transport has to mean the same thing by "page two". Four of them did not —
2869
+ * the REST layer strode by {@link DEFAULT_LIST_LIMIT}, the local-first
2870
+ * evaluator by {@link DEFAULT_PAGE_SIZE}, the in-process accessor by 20, and
2871
+ * the published type documented a fourth number. Pages that overlap or skip
2872
+ * rows are the mildest of those outcomes.
2873
+ *
2874
+ * `page` wins over `offset`, as {@link FindParams} documents. `driverOffset`
2875
+ * is the value to hand a driver: it stays `undefined` when the caller named no
2876
+ * offset, because keyset pagination seeks with a `where` clause and must not
2877
+ * look like it is paging by offset.
2878
+ */
2879
+ function resolveFindWindow(params) {
2880
+ const limit = params?.limit ?? DEFAULT_LIST_LIMIT;
2881
+ const offset = params?.page != null ? Math.max(0, (params.page - 1) * limit) : params?.offset ?? 0;
2882
+ return {
2883
+ limit,
2884
+ offset,
2885
+ driverOffset: params?.page != null ? offset : params?.offset
2886
+ };
2887
+ }
2864
2888
  function normalizePageSize(raw) {
2865
2889
  if (raw === void 0 || !Number.isFinite(raw)) return 200;
2866
2890
  return Math.max(1, Math.floor(raw));
@@ -3322,21 +3346,22 @@ function createDriverAccessor(driver, slug, getPks = () => []) {
3322
3346
  const accessor = {
3323
3347
  async find(params) {
3324
3348
  const filter = params?.where ? deserializeFilter(params.where) : void 0;
3325
- const limit = params?.limit ?? 20;
3326
- const offset = params?.offset ?? 0;
3349
+ const { limit, offset, driverOffset } = resolveFindWindow(params);
3327
3350
  const fetchService = driver.restFetchService;
3328
3351
  const rows = fetchService ? await fetchService.fetchCollectionForRest(slug, {
3329
3352
  filter,
3330
- limit: params?.limit,
3331
- offset: params?.offset,
3353
+ logical: params?.logical,
3354
+ limit,
3355
+ offset: driverOffset,
3332
3356
  orderBy: params?.orderBy?.[0],
3333
3357
  order: params?.orderBy?.[1],
3334
3358
  searchString: params?.searchString
3335
3359
  }, params?.include) : await driver.fetchCollection({
3336
3360
  path: slug,
3337
- limit: params?.limit,
3338
- offset: params?.offset,
3361
+ limit,
3362
+ offset: driverOffset,
3339
3363
  filter,
3364
+ logical: params?.logical,
3340
3365
  orderBy: params?.orderBy?.[0],
3341
3366
  order: params?.orderBy?.[1],
3342
3367
  searchString: params?.searchString
@@ -3346,7 +3371,9 @@ function createDriverAccessor(driver, slug, getPks = () => []) {
3346
3371
  if (driver.count) {
3347
3372
  total = await driver.count({
3348
3373
  path: slug,
3349
- filter
3374
+ filter,
3375
+ logical: params?.logical,
3376
+ searchString: params?.searchString
3350
3377
  });
3351
3378
  hasMore = offset + rows.length < total;
3352
3379
  }
@@ -3402,18 +3429,20 @@ function createDriverAccessor(driver, slug, getPks = () => []) {
3402
3429
  const filter = params?.where ? deserializeFilter(params.where) : void 0;
3403
3430
  return driver.count({
3404
3431
  path: slug,
3405
- filter
3432
+ filter,
3433
+ logical: params?.logical,
3434
+ searchString: params?.searchString
3406
3435
  });
3407
3436
  } : void 0,
3408
3437
  listen: driver.listenCollection ? (params, onUpdate, onError) => {
3409
- const limit = params?.limit ?? 20;
3410
- const offset = params?.offset ?? 0;
3438
+ const { limit, offset, driverOffset } = resolveFindWindow(params);
3411
3439
  const normalize = driver.restFetchService ? inlineRelationRefs : (row) => row;
3412
3440
  return driver.listenCollection({
3413
3441
  path: slug,
3414
- limit: params?.limit,
3415
- offset: params?.offset,
3442
+ limit,
3443
+ offset: driverOffset,
3416
3444
  filter: params?.where,
3445
+ logical: params?.logical,
3417
3446
  orderBy: params?.orderBy?.[0],
3418
3447
  order: params?.orderBy?.[1],
3419
3448
  searchString: params?.searchString,
@@ -3421,7 +3450,7 @@ function createDriverAccessor(driver, slug, getPks = () => []) {
3421
3450
  onUpdate({
3422
3451
  data: entities.map((row) => rowToEntity(normalize(row), slug, getPks())),
3423
3452
  meta: {
3424
- total: entities.length,
3453
+ total: offset + entities.length,
3425
3454
  limit,
3426
3455
  offset,
3427
3456
  hasMore: entities.length >= limit
@@ -3906,6 +3935,6 @@ async function detectJunctionTables(executeSql) {
3906
3935
  return junctionTables;
3907
3936
  }
3908
3937
  //#endregion
3909
- export { COLLECTION_PATH_SEPARATOR, COMPOSITE_ID_SEPARATOR, CollectionRegistry, DEFAULT_FIND_ALL_MAX_ROWS, DEFAULT_MAX_PAGES, DEFAULT_ONE_OF_TYPE, DEFAULT_ONE_OF_VALUE, DEFAULT_PAGE_SIZE, DEFAULT_STRING_COLUMN_LENGTH, JUNCTION_TABLES_SQL, QueryBuilder, REBASE_INTERNAL_PREFIXES, REBASE_INTERNAL_SCHEMAS, RebasePaginationError, and, buildCollectionFromTableMetadata, buildCompositeId, buildConditionContext, buildPropertyCallbacks, buildRebaseData, buildRoutedRebaseData, buildSdkData, canCreateEntity, canDeleteEntity, canEditEntity, canReadCollection, checkOperation, classifyTable, collectAllPages, cond, createDataSourceRegistry, createPaginationHelpers, createRelationRef, createRelationRefWithData, defaultUsersCollection, defineCollection, deserializeFilter, deserializeLogicalCondition, deserializeOrderBy, detectJunctionTables, embedParentExpression, enumToObjectEntries, evaluateCondition, evaluatePolicy, findAnonymousGrants, findRelation, fullPathToCollectionSegments, getArrayResolvedProperties, getColumnName, getDeclaredPrimaryKeys, getDefaultValueFor, getDefaultValueFortype, getDefaultValuesFor, getEffectiveSecurityRules, getEntityChildViews, getEnumVarName, getGeneratedPolicyNames, getInjectedSecurityRules, getJunctionCollectionConfig, getJunctionSecurityRules, getLabelOrConfigFrom, getPrimaryKeys, getReferenceFrom, getRelationFrom, getSubcollections, getTableName, getTableVarName, isAddressableId, isJunctionBackedRelation, isPropertyBuilder, isRebaseInternalTable, normalizeEmail, normalizeToEntityRelation, or, paginateFind, parseIdValues, policyToPostgres, registerConditionOperations, resolveArrayProperties, resolveCollectionRelations, resolveDataSource, resolveEnumValues, resolveJunctionSpecs, resolvePrimaryKeys, resolveProperties, resolveProperty, resolvePropertyEnum, resolveRelation, resolveRelationProperty, resolveStorageFilenameString, resolveStoragePathString, resolveStorageSource, resolveStringColumnLength, sanitizeData, securityRuleToConditions, segmentsToStrippedPath, serializeFilter, serializeLogicalCondition, serializeOrderBy, sortProperties, sqlToPolicy, stripCollectionPath, traverseValueProperty, traverseValuesProperties, updateDateAutoValues, wrapAsEntityData, wrapAsSdkData };
3938
+ export { COLLECTION_PATH_SEPARATOR, COMPOSITE_ID_SEPARATOR, CollectionRegistry, DEFAULT_FIND_ALL_MAX_ROWS, DEFAULT_MAX_PAGES, DEFAULT_ONE_OF_TYPE, DEFAULT_ONE_OF_VALUE, DEFAULT_PAGE_SIZE, DEFAULT_STRING_COLUMN_LENGTH, JUNCTION_TABLES_SQL, QueryBuilder, REBASE_INTERNAL_PREFIXES, REBASE_INTERNAL_SCHEMAS, RebasePaginationError, and, buildCollectionFromTableMetadata, buildCompositeId, buildConditionContext, buildPropertyCallbacks, buildRebaseData, buildRoutedRebaseData, buildSdkData, canCreateEntity, canDeleteEntity, canEditEntity, canReadCollection, checkOperation, classifyTable, collectAllPages, cond, createDataSourceRegistry, createPaginationHelpers, createRelationRef, createRelationRefWithData, defaultUsersCollection, defineCollection, deserializeFilter, deserializeLogicalCondition, deserializeOrderBy, detectJunctionTables, embedParentExpression, enumToObjectEntries, evaluateCondition, evaluatePolicy, findAnonymousGrants, findRelation, fullPathToCollectionSegments, getArrayResolvedProperties, getColumnName, getDeclaredPrimaryKeys, getDefaultValueFor, getDefaultValueFortype, getDefaultValuesFor, getEffectiveSecurityRules, getEntityChildViews, getEnumVarName, getGeneratedPolicyNames, getInjectedSecurityRules, getJunctionCollectionConfig, getJunctionSecurityRules, getLabelOrConfigFrom, getPrimaryKeys, getReferenceFrom, getRelationFrom, getSubcollections, getTableName, getTableVarName, isAddressableId, isJunctionBackedRelation, isPropertyBuilder, isRebaseInternalTable, normalizeEmail, normalizeToEntityRelation, or, paginateFind, parseIdValues, policyToPostgres, registerConditionOperations, resolveArrayProperties, resolveCollectionRelations, resolveDataSource, resolveEnumValues, resolveFindWindow, resolveJunctionSpecs, resolvePrimaryKeys, resolveProperties, resolveProperty, resolvePropertyEnum, resolveRelation, resolveRelationProperty, resolveStorageFilenameString, resolveStoragePathString, resolveStorageSource, resolveStringColumnLength, sanitizeData, securityRuleToConditions, segmentsToStrippedPath, serializeFilter, serializeLogicalCondition, serializeOrderBy, sortProperties, sqlToPolicy, stripCollectionPath, traverseValueProperty, traverseValuesProperties, updateDateAutoValues, wrapAsEntityData, wrapAsSdkData };
3910
3939
 
3911
3940
  //# sourceMappingURL=index.es.js.map