@medicine-wheel/app 0.8.0 → 0.9.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.
@@ -1,4 +1,5 @@
1
1
  import { NextResponse } from "next/server";
2
+ import { parseLimit } from "@/lib/api-paging";
2
3
  import { createProvider, detectProvider } from "@medicine-wheel/storage-provider";
3
4
  import { ceremonyBelongsToEpisode } from "@/lib/ceremony-response";
4
5
 
@@ -9,13 +10,22 @@ export async function GET(request: Request) {
9
10
  const type = searchParams.get("type");
10
11
  const episodePath = searchParams.get("episode_path");
11
12
 
13
+ const limit = parseLimit(searchParams.get("limit"));
14
+ if (limit instanceof NextResponse) return limit;
15
+
12
16
  const store = await createProvider();
13
- // Provider list methods intentionally default to one page (100). A scoped
14
- // episode query must search the complete ceremony store before filtering,
15
- // or an older but valid ceremony silently disappears from its episode.
16
- let ceremonies = await store.getAllCeremonies(
17
- episodePath ? Number.MAX_SAFE_INTEGER : undefined,
18
- );
17
+
18
+ // Always read the whole store, then filter, then page.
19
+ //
20
+ // This used to take the provider's 100-row default unless an episode was
21
+ // named, and filter afterwards — so `?direction=east` searched only the
22
+ // newest 100 ceremonies and every older east ceremony was unreachable
23
+ // through this route. Measured 2026-09-05: an unfiltered read and a
24
+ // direction-filtered read both stopped at the same record, because both were
25
+ // looking at the same 100-row window.
26
+ const all = await store.getAllCeremonies(Number.MAX_SAFE_INTEGER);
27
+ const total = all.length;
28
+ let ceremonies = all;
19
29
 
20
30
  if (direction) {
21
31
  ceremonies = ceremonies.filter((c) => c.direction === direction);
@@ -31,10 +41,20 @@ export async function GET(request: Request) {
31
41
  );
32
42
  }
33
43
 
34
- return NextResponse.json({
35
- ceremonies,
44
+ const matched = ceremonies.length;
45
+ if (limit !== null && ceremonies.length > limit) {
46
+ ceremonies = ceremonies.slice(0, limit);
47
+ }
48
+
49
+ return NextResponse.json({
50
+ ceremonies,
36
51
  provider: detectProvider(),
37
- count: ceremonies.length
52
+ count: ceremonies.length,
53
+ // `total` is the whole store, `matched` what the filters selected. When
54
+ // count < matched the caller holds a page and can now see that it does.
55
+ total,
56
+ ...(direction || type || episodePath ? { matched } : {}),
57
+ truncated: ceremonies.length < matched,
38
58
  });
39
59
  } catch (error: unknown) {
40
60
  const message = error instanceof Error ? error.message : String(error);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@medicine-wheel/app",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "Medicine Wheel — Interactive visual layer for Indigenous relational research with Four Directions, ceremonies, and narrative arcs",
5
5
  "bin": {
6
6
  "mw": "dist/cli/mw.js",
@@ -85,29 +85,29 @@
85
85
  "release:major": "npm run version:major && npm run publish:all && npm run release:commit"
86
86
  },
87
87
  "dependencies": {
88
- "@medicine-wheel/ceremonial-diary": "^0.8.0",
89
- "@medicine-wheel/ceremony-protocol": "^0.8.0",
90
- "@medicine-wheel/community-review": "^0.8.0",
91
- "@medicine-wheel/consent-lifecycle": "^0.8.0",
92
- "@medicine-wheel/creative-orientation": "^0.8.0",
93
- "@medicine-wheel/data-store": "^0.8.0",
94
- "@medicine-wheel/data-store-postgres": "^0.8.0",
95
- "@medicine-wheel/fire-keeper": "^0.8.0",
96
- "@medicine-wheel/github-ceremony": "^0.8.0",
97
- "@medicine-wheel/graph-viz": "^0.8.0",
98
- "@medicine-wheel/importance-unit": "^0.8.0",
99
- "@medicine-wheel/mcp": "^4.8.0",
100
- "@medicine-wheel/narrative-cluster": "^0.8.0",
101
- "@medicine-wheel/narrative-engine": "^0.8.0",
102
- "@medicine-wheel/ontology-core": "^0.8.0",
103
- "@medicine-wheel/perception-layer": "^0.8.0",
104
- "@medicine-wheel/prompt-decomposition": "^0.8.0",
105
- "@medicine-wheel/relational-index": "^0.8.0",
106
- "@medicine-wheel/relational-query": "^0.8.0",
107
- "@medicine-wheel/session-reader": "^0.8.0",
108
- "@medicine-wheel/storage-provider": "^0.8.0",
109
- "@medicine-wheel/transformation-tracker": "^0.8.0",
110
- "@medicine-wheel/ui-components": "^0.8.0",
88
+ "@medicine-wheel/ceremonial-diary": "^0.9.0",
89
+ "@medicine-wheel/ceremony-protocol": "^0.9.0",
90
+ "@medicine-wheel/community-review": "^0.9.0",
91
+ "@medicine-wheel/consent-lifecycle": "^0.9.0",
92
+ "@medicine-wheel/creative-orientation": "^0.9.0",
93
+ "@medicine-wheel/data-store": "^0.9.0",
94
+ "@medicine-wheel/data-store-postgres": "^0.9.0",
95
+ "@medicine-wheel/fire-keeper": "^0.9.0",
96
+ "@medicine-wheel/github-ceremony": "^0.9.0",
97
+ "@medicine-wheel/graph-viz": "^0.9.0",
98
+ "@medicine-wheel/importance-unit": "^0.9.0",
99
+ "@medicine-wheel/mcp": "^4.9.0",
100
+ "@medicine-wheel/narrative-cluster": "^0.9.0",
101
+ "@medicine-wheel/narrative-engine": "^0.9.0",
102
+ "@medicine-wheel/ontology-core": "^0.9.0",
103
+ "@medicine-wheel/perception-layer": "^0.9.0",
104
+ "@medicine-wheel/prompt-decomposition": "^0.9.0",
105
+ "@medicine-wheel/relational-index": "^0.9.0",
106
+ "@medicine-wheel/relational-query": "^0.9.0",
107
+ "@medicine-wheel/session-reader": "^0.9.0",
108
+ "@medicine-wheel/storage-provider": "^0.9.0",
109
+ "@medicine-wheel/transformation-tracker": "^0.9.0",
110
+ "@medicine-wheel/ui-components": "^0.9.0",
111
111
  "@neondatabase/serverless": "^0.10.0",
112
112
  "@xyflow/react": "^12.3.0",
113
113
  "clsx": "^2.1.1",