@commonpub/layer 0.43.0 → 0.43.1
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/composables/useContentFeed.ts +32 -15
- package/package.json +6 -6
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Serialized, ContentListItem
|
|
1
|
+
import type { Serialized, ContentListItem } from '@commonpub/server';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Unified content-feed loader with transparent keyset/offset pagination.
|
|
@@ -24,9 +24,15 @@ import type { Serialized, ContentListItem, PaginatedResponse } from '@commonpub/
|
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
26
|
type FeedQuery = Record<string, unknown> & { sort?: string; limit?: number };
|
|
27
|
-
type
|
|
27
|
+
/** Public item type callers consume (for ContentCard). */
|
|
28
|
+
export type FeedItem = Serialized<ContentListItem>;
|
|
28
29
|
|
|
29
|
-
|
|
30
|
+
// Wire response shape for BOTH endpoints (keyset → nextCursor, offset → total). The
|
|
31
|
+
// items are typed `Record<string, unknown>[]`, NOT `Serialized<ContentListItem>[]`, on
|
|
32
|
+
// purpose: feeding the deeply-recursive Serialized<…> mapped type through useFetch's own
|
|
33
|
+
// generic wrapper tripped TS2589 "excessively deep" under the consumer apps' stricter
|
|
34
|
+
// typecheck (deveco). We cast to FeedItem[] once, at the `items` boundary callers read.
|
|
35
|
+
interface FeedResponse { items: Array<Record<string, unknown>>; nextCursor?: string | null; total?: number }
|
|
30
36
|
|
|
31
37
|
export function useContentFeed(query: Ref<FeedQuery> | ComputedRef<FeedQuery>) {
|
|
32
38
|
const toast = useToast();
|
|
@@ -46,17 +52,28 @@ export function useContentFeed(query: Ref<FeedQuery> | ComputedRef<FeedQuery>) {
|
|
|
46
52
|
|
|
47
53
|
// Initial page — SSR-friendly via useFetch. Both endpoints accept the same query;
|
|
48
54
|
// the keyset one returns { items, nextCursor }, the offset one { items, total }.
|
|
55
|
+
//
|
|
56
|
+
// No explicit useFetch<…> generic: parameterising it makes TS instantiate useFetch's
|
|
57
|
+
// own deep transform/pick generic machinery, which trips TS2589 "excessively deep"
|
|
58
|
+
// under the consumer apps' stricter typecheck (deveco already @ts-ignores the same on
|
|
59
|
+
// its own useFetch calls). We let it infer and read `data` through a typed `page`
|
|
60
|
+
// computed cast to the shallow FeedResponse instead.
|
|
49
61
|
const endpoint = computed(() => (isKeyset.value ? '/api/content/feed' : '/api/content'));
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
62
|
+
// @ts-ignore TS2589: a computed endpoint that is a UNION of two typed routes makes
|
|
63
|
+
// Nuxt's useFetch resolve typed route data for both, blowing the instantiation depth
|
|
64
|
+
// under the consumer apps' stricter typecheck (deveco @ts-ignores the same on its own
|
|
65
|
+
// useFetch calls). Runtime is unaffected; `data` is read through the typed `page` below.
|
|
66
|
+
const { data, pending } = useFetch(endpoint, { query, watch: [query] });
|
|
67
|
+
const page = computed<FeedResponse | null>(() => (data.value as FeedResponse | null) ?? null);
|
|
54
68
|
|
|
55
69
|
// Local accumulator: the first page from useFetch, plus any load-more pages. Kept
|
|
56
70
|
// separate from `data` so we never mutate the useFetch payload (which it re-creates
|
|
57
71
|
// on refetch) — and so a tab switch cleanly replaces the list.
|
|
58
|
-
const extra = ref<
|
|
59
|
-
|
|
72
|
+
const extra = ref<Array<Record<string, unknown>>>([]);
|
|
73
|
+
// Single cast from the shallow wire type to the public FeedItem[] callers consume.
|
|
74
|
+
const items = computed<FeedItem[]>(
|
|
75
|
+
() => [...(page.value?.items ?? []), ...extra.value] as FeedItem[],
|
|
76
|
+
);
|
|
60
77
|
|
|
61
78
|
// Reset pagination whenever the underlying query (tab/filter) changes.
|
|
62
79
|
watch(
|
|
@@ -71,10 +88,10 @@ export function useContentFeed(query: Ref<FeedQuery> | ComputedRef<FeedQuery>) {
|
|
|
71
88
|
|
|
72
89
|
// Seed the keyset cursor from the first page once it arrives.
|
|
73
90
|
watch(
|
|
74
|
-
|
|
75
|
-
(
|
|
91
|
+
page,
|
|
92
|
+
(p) => {
|
|
76
93
|
if (isKeyset.value) {
|
|
77
|
-
cursor.value =
|
|
94
|
+
cursor.value = p?.nextCursor ?? null;
|
|
78
95
|
if (cursor.value === null) exhausted.value = true;
|
|
79
96
|
}
|
|
80
97
|
},
|
|
@@ -95,15 +112,15 @@ export function useContentFeed(query: Ref<FeedQuery> | ComputedRef<FeedQuery>) {
|
|
|
95
112
|
try {
|
|
96
113
|
if (isKeyset.value) {
|
|
97
114
|
if (!cursor.value) { exhausted.value = true; return; }
|
|
98
|
-
const res = await $fetch<
|
|
115
|
+
const res = await $fetch<FeedResponse>('/api/content/feed', {
|
|
99
116
|
query: { ...query.value, cursor: cursor.value },
|
|
100
117
|
});
|
|
101
118
|
if (res.items?.length) extra.value.push(...res.items);
|
|
102
|
-
cursor.value = res.nextCursor;
|
|
119
|
+
cursor.value = res.nextCursor ?? null;
|
|
103
120
|
if (!res.nextCursor) exhausted.value = true;
|
|
104
121
|
} else {
|
|
105
122
|
const offset = items.value.length;
|
|
106
|
-
const res = await $fetch<
|
|
123
|
+
const res = await $fetch<FeedResponse>('/api/content', {
|
|
107
124
|
query: { ...query.value, offset },
|
|
108
125
|
});
|
|
109
126
|
if (res.items?.length) extra.value.push(...res.items);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@commonpub/layer",
|
|
3
|
-
"version": "0.43.
|
|
3
|
+
"version": "0.43.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./nuxt.config.ts",
|
|
6
6
|
"files": [
|
|
@@ -53,16 +53,16 @@
|
|
|
53
53
|
"vue": "^3.4.0",
|
|
54
54
|
"vue-router": "^4.3.0",
|
|
55
55
|
"zod": "^4.3.6",
|
|
56
|
-
"@commonpub/docs": "0.6.3",
|
|
57
|
-
"@commonpub/learning": "0.5.2",
|
|
58
56
|
"@commonpub/auth": "0.7.0",
|
|
57
|
+
"@commonpub/config": "0.16.0",
|
|
58
|
+
"@commonpub/docs": "0.6.3",
|
|
59
|
+
"@commonpub/editor": "0.7.11",
|
|
59
60
|
"@commonpub/explainer": "0.7.15",
|
|
60
61
|
"@commonpub/schema": "0.25.0",
|
|
61
62
|
"@commonpub/server": "2.71.0",
|
|
62
|
-
"@commonpub/protocol": "0.12.0",
|
|
63
|
-
"@commonpub/editor": "0.7.11",
|
|
64
63
|
"@commonpub/ui": "0.9.1",
|
|
65
|
-
"@commonpub/
|
|
64
|
+
"@commonpub/protocol": "0.12.0",
|
|
65
|
+
"@commonpub/learning": "0.5.2"
|
|
66
66
|
},
|
|
67
67
|
"devDependencies": {
|
|
68
68
|
"@testing-library/jest-dom": "^6.9.1",
|