@open-mercato/shared 0.6.8-develop.6987.1.02f619470c → 0.6.8-develop.6992.1.00c90fecff

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.
@@ -1,2 +1,2 @@
1
- [build:shared] found 260 entry points
1
+ [build:shared] found 261 entry points
2
2
  [build:shared] built successfully
@@ -0,0 +1,7 @@
1
+ function hasMoreFromPage(servedCount, pageSize) {
2
+ return servedCount >= pageSize;
3
+ }
4
+ export {
5
+ hasMoreFromPage
6
+ };
7
+ //# sourceMappingURL=load-more.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/lib/pagination/load-more.ts"],
4
+ "sourcesContent": ["/**\n * Termination signal for incremental \"load more\" affordances.\n *\n * A page that comes back full is the only reliable \"there may be more\" signal.\n * A server-reported `total` / `totalPages` can under-report \u2014 rows inserted\n * between two requests do it today, and a capped list count will do it by\n * design once `OM_LIST_COUNT_CAP` lands (see\n * `.ai/specs/2026-07-27-list-count-strategies.md`) \u2014 and gating the affordance\n * on one strands every row past the reported end behind a button that has\n * already disappeared.\n *\n * `>=` rather than `===` so an endpoint that serves more than it was asked for\n * still terminates correctly.\n *\n * Two obligations come with this, and both have already caused real defects:\n *\n * 1. **Measure what the server served**, not what survived client-side dedupe\n * or filtering. A deduped length shorter than the served page terminates the\n * sequence early \u2014 reintroducing exactly the bug this replaces.\n *\n * 2. **Only for endpoints whose page past the end comes back short.** That\n * holds for every list built on the query engine, which computes an\n * unclamped offset. An endpoint that instead clamps the requested page to\n * the last page re-serves that page in full, forever; a caller of one must\n * also check it was served the page it asked for before appending. See\n * `AttachmentsSection`, whose endpoint clamps.\n */\nexport function hasMoreFromPage(servedCount: number, pageSize: number): boolean {\n return servedCount >= pageSize\n}\n"],
5
+ "mappings": "AA2BO,SAAS,gBAAgB,aAAqB,UAA2B;AAC9E,SAAO,eAAe;AACxB;",
6
+ "names": []
7
+ }
@@ -1,4 +1,4 @@
1
- const APP_VERSION = "0.6.8-develop.6987.1.02f619470c";
1
+ const APP_VERSION = "0.6.8-develop.6992.1.00c90fecff";
2
2
  const appVersion = APP_VERSION;
3
3
  export {
4
4
  APP_VERSION,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/lib/version.ts"],
4
- "sourcesContent": ["// Build-time generated version\nexport const APP_VERSION = '0.6.8-develop.6987.1.02f619470c';\nexport const appVersion = APP_VERSION;\n"],
4
+ "sourcesContent": ["// Build-time generated version\nexport const APP_VERSION = '0.6.8-develop.6992.1.00c90fecff';\nexport const appVersion = APP_VERSION;\n"],
5
5
  "mappings": "AACO,MAAM,cAAc;AACpB,MAAM,aAAa;",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-mercato/shared",
3
- "version": "0.6.8-develop.6987.1.02f619470c",
3
+ "version": "0.6.8-develop.6992.1.00c90fecff",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -105,7 +105,7 @@
105
105
  "@mikro-orm/core": "^7.1.8",
106
106
  "@mikro-orm/decorators": "^7.1.8",
107
107
  "@mikro-orm/postgresql": "^7.1.8",
108
- "@open-mercato/cache": "0.6.8-develop.6987.1.02f619470c",
108
+ "@open-mercato/cache": "0.6.8-develop.6992.1.00c90fecff",
109
109
  "@types/sanitize-html": "^2.16.1",
110
110
  "dotenv": "^17.4.2",
111
111
  "pino": "^10.3.1",
@@ -0,0 +1,29 @@
1
+ import { hasMoreFromPage } from '../load-more'
2
+
3
+ describe('hasMoreFromPage', () => {
4
+ it('reports more when the page came back full', () => {
5
+ expect(hasMoreFromPage(24, 24)).toBe(true)
6
+ })
7
+
8
+ it('reports more when the endpoint served more than it was asked for', () => {
9
+ // `>=` rather than `===`, so an over-serving endpoint still terminates.
10
+ expect(hasMoreFromPage(25, 24)).toBe(true)
11
+ })
12
+
13
+ it('terminates on a short page', () => {
14
+ expect(hasMoreFromPage(23, 24)).toBe(false)
15
+ })
16
+
17
+ it('terminates on an empty page', () => {
18
+ expect(hasMoreFromPage(0, 24)).toBe(false)
19
+ })
20
+
21
+ // The served count is the contract (obligation 1 in the docstring): callers
22
+ // must not pass a client-deduped length. Nothing here can enforce that, but
23
+ // pinning the boundary keeps the `>=` from drifting to `===` or `>`.
24
+ it('treats one row short of the page size as the end, one row over as more', () => {
25
+ expect(hasMoreFromPage(1, 2)).toBe(false)
26
+ expect(hasMoreFromPage(2, 2)).toBe(true)
27
+ expect(hasMoreFromPage(3, 2)).toBe(true)
28
+ })
29
+ })
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Termination signal for incremental "load more" affordances.
3
+ *
4
+ * A page that comes back full is the only reliable "there may be more" signal.
5
+ * A server-reported `total` / `totalPages` can under-report — rows inserted
6
+ * between two requests do it today, and a capped list count will do it by
7
+ * design once `OM_LIST_COUNT_CAP` lands (see
8
+ * `.ai/specs/2026-07-27-list-count-strategies.md`) — and gating the affordance
9
+ * on one strands every row past the reported end behind a button that has
10
+ * already disappeared.
11
+ *
12
+ * `>=` rather than `===` so an endpoint that serves more than it was asked for
13
+ * still terminates correctly.
14
+ *
15
+ * Two obligations come with this, and both have already caused real defects:
16
+ *
17
+ * 1. **Measure what the server served**, not what survived client-side dedupe
18
+ * or filtering. A deduped length shorter than the served page terminates the
19
+ * sequence early — reintroducing exactly the bug this replaces.
20
+ *
21
+ * 2. **Only for endpoints whose page past the end comes back short.** That
22
+ * holds for every list built on the query engine, which computes an
23
+ * unclamped offset. An endpoint that instead clamps the requested page to
24
+ * the last page re-serves that page in full, forever; a caller of one must
25
+ * also check it was served the page it asked for before appending. See
26
+ * `AttachmentsSection`, whose endpoint clamps.
27
+ */
28
+ export function hasMoreFromPage(servedCount: number, pageSize: number): boolean {
29
+ return servedCount >= pageSize
30
+ }