@commonpub/layer 0.15.2 → 0.15.3

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.
@@ -12,7 +12,8 @@ interface Comment {
12
12
  createdAt: string;
13
13
  parentId: string | null;
14
14
  author: CommentAuthor | null;
15
- replies?: Comment[];
15
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
16
+ replies?: any[];
16
17
  }
17
18
 
18
19
  const props = defineProps<{
@@ -38,6 +39,8 @@ const queryParams = computed(() =>
38
39
  isFederated.value ? undefined : { targetType: props.targetType, targetId: props.targetId, limit: commentLimit },
39
40
  );
40
41
 
42
+ // @ts-ignore TS2589: useFetch<Comment[]> with this query shape hits deep
43
+ // type instantiation in some consumer apps (notably shell). Runtime is fine.
41
44
  const { data: comments, refresh } = await useFetch<Comment[]>(commentUrl, { query: queryParams, lazy: true });
42
45
 
43
46
  const allCommentsLoaded = ref(false);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@commonpub/layer",
3
- "version": "0.15.2",
3
+ "version": "0.15.3",
4
4
  "type": "module",
5
5
  "main": "./nuxt.config.ts",
6
6
  "files": [
@@ -30,7 +30,7 @@
30
30
  "@aws-sdk/client-s3": "^3.1010.0",
31
31
  "@commonpub/explainer": "^0.7.11",
32
32
  "@commonpub/schema": "^0.13.0",
33
- "@commonpub/server": "^2.42.0",
33
+ "@commonpub/server": "^2.43.0",
34
34
  "@tiptap/core": "^2.11.0",
35
35
  "@tiptap/extension-bold": "^2.11.0",
36
36
  "@tiptap/extension-bullet-list": "^2.11.0",
@@ -53,13 +53,13 @@
53
53
  "vue": "^3.4.0",
54
54
  "vue-router": "^4.3.0",
55
55
  "zod": "^4.3.6",
56
- "@commonpub/auth": "0.5.1",
57
- "@commonpub/config": "0.10.0",
58
56
  "@commonpub/docs": "0.6.2",
59
- "@commonpub/editor": "0.7.9",
60
- "@commonpub/learning": "0.5.0",
57
+ "@commonpub/config": "0.10.0",
61
58
  "@commonpub/protocol": "0.9.9",
62
- "@commonpub/ui": "0.8.5"
59
+ "@commonpub/learning": "0.5.0",
60
+ "@commonpub/ui": "0.8.5",
61
+ "@commonpub/auth": "0.5.1",
62
+ "@commonpub/editor": "0.7.9"
63
63
  },
64
64
  "devDependencies": {
65
65
  "@testing-library/jest-dom": "^6.9.1",
@@ -12,7 +12,22 @@ interface Category {
12
12
  icon: string | null;
13
13
  }
14
14
 
15
- const { data, refresh } = await useFetch('/api/content', {
15
+ interface AdminContentItem {
16
+ id: string;
17
+ source?: string;
18
+ title: string;
19
+ slug: string;
20
+ type: string;
21
+ status: string;
22
+ isEditorial?: boolean;
23
+ isFeatured?: boolean;
24
+ categoryId?: string | null;
25
+ viewCount?: number;
26
+ createdAt: string;
27
+ author?: { id: string; username: string; displayName: string | null } | null;
28
+ }
29
+
30
+ const { data, refresh } = await useFetch<{ items: AdminContentItem[] }>('/api/content', {
16
31
  query: { limit: 50, sort: 'recent' },
17
32
  });
18
33
  const { data: categories } = await useFetch<Category[]>('/api/categories');
@@ -22,7 +37,11 @@ const selectAll = ref(false);
22
37
 
23
38
  watch(selectAll, (val) => {
24
39
  if (val && data.value?.items) {
25
- selectedIds.value = new Set(data.value.items.filter(i => i.source !== 'federated').map(i => i.id));
40
+ selectedIds.value = new Set(
41
+ data.value.items
42
+ .filter((i: AdminContentItem) => i.source !== 'federated')
43
+ .map((i: AdminContentItem) => i.id),
44
+ );
26
45
  } else {
27
46
  selectedIds.value = new Set();
28
47
  }
@@ -15,8 +15,19 @@ const activeTab = ref<'content' | 'bookmarks' | 'learning'>('content');
15
15
  const contentSort = ref<'newest' | 'oldest' | 'popular'>('newest');
16
16
  const contentTypeFilter = ref('');
17
17
 
18
+ interface DashContentItem {
19
+ id: string;
20
+ type: string;
21
+ slug: string;
22
+ title: string;
23
+ status: string;
24
+ createdAt: string;
25
+ viewCount?: number;
26
+ likeCount?: number;
27
+ }
28
+
18
29
  // My content (all statuses)
19
- const { data: myContent, status: contentStatus } = await useFetch('/api/content', {
30
+ const { data: myContent, status: contentStatus } = await useFetch<{ items: DashContentItem[] }>('/api/content', {
20
31
  query: { authorId: user.value?.id },
21
32
  headers: reqHeaders,
22
33
  });
@@ -65,19 +76,27 @@ function sortItems<T extends { createdAt: string; viewCount?: number; likeCount?
65
76
  return sorted;
66
77
  }
67
78
 
68
- const drafts = computed(() =>
69
- sortItems(filterByType((myContent.value?.items ?? []).filter((i: { status: string }) => i.status === 'draft'))),
79
+ const drafts = computed<DashContentItem[]>(() =>
80
+ sortItems<DashContentItem>(
81
+ filterByType<DashContentItem>(
82
+ (myContent.value?.items ?? []).filter((i: DashContentItem) => i.status === 'draft'),
83
+ ),
84
+ ),
70
85
  );
71
- const published = computed(() =>
72
- sortItems(filterByType((myContent.value?.items ?? []).filter((i: { status: string }) => i.status === 'published'))),
86
+ const published = computed<DashContentItem[]>(() =>
87
+ sortItems<DashContentItem>(
88
+ filterByType<DashContentItem>(
89
+ (myContent.value?.items ?? []).filter((i: DashContentItem) => i.status === 'published'),
90
+ ),
91
+ ),
73
92
  );
74
93
 
75
94
  // Stats use ALL items (unfiltered) so totals don't change with filter selection
76
- const allPublished = computed(() =>
77
- (myContent.value?.items ?? []).filter((i: { status: string }) => i.status === 'published'),
95
+ const allPublished = computed<DashContentItem[]>(() =>
96
+ (myContent.value?.items ?? []).filter((i: DashContentItem) => i.status === 'published'),
78
97
  );
79
- const allDrafts = computed(() =>
80
- (myContent.value?.items ?? []).filter((i: { status: string }) => i.status === 'draft'),
98
+ const allDrafts = computed<DashContentItem[]>(() =>
99
+ (myContent.value?.items ?? []).filter((i: DashContentItem) => i.status === 'draft'),
81
100
  );
82
101
  const totalViews = computed(() =>
83
102
  allPublished.value.reduce((sum, item) => sum + (item.viewCount ?? 0), 0),
@@ -24,9 +24,10 @@ const { data: site, refresh: refreshSite } = await useFetch<{ id: string; name:
24
24
 
25
25
  // Version selector
26
26
  const selectedVersion = ref('');
27
+ type SiteVersion = { id: string; version: string; isDefault: boolean };
27
28
  watch(site, (s) => {
28
29
  if (s?.versions?.length && !selectedVersion.value) {
29
- const def = s.versions.find((v) => v.isDefault) ?? s.versions[0];
30
+ const def = s.versions.find((v: SiteVersion) => v.isDefault) ?? s.versions[0];
30
31
  if (def) selectedVersion.value = def.version;
31
32
  }
32
33
  }, { immediate: true });
@@ -34,7 +35,7 @@ watch(site, (s) => {
34
35
  // Resolve selected version string → version UUID for write operations
35
36
  const selectedVersionId = computed(() => {
36
37
  if (!site.value?.versions?.length || !selectedVersion.value) return undefined;
37
- return site.value.versions.find((v) => v.version === selectedVersion.value)?.id;
38
+ return site.value.versions.find((v: SiteVersion) => v.version === selectedVersion.value)?.id;
38
39
  });
39
40
 
40
41
  const { data: rawPages, refresh: refreshPages } = await useFetch<Array<{ id: string; title: string; slug: string; sortOrder: number; parentId: string | null; content: string | BlockTuple[] | null; format?: string }>>(() => {
package/pages/index.vue CHANGED
@@ -58,7 +58,19 @@ const { data: communities, pending: communitiesPending } = await useFetch('/api/
58
58
  query: { limit: 4 },
59
59
  });
60
60
 
61
- const { data: contests, pending: contestsPending } = await useFetch('/api/contests', {
61
+ interface ContestListItem {
62
+ id: string;
63
+ slug: string;
64
+ title: string;
65
+ status: string;
66
+ description?: string | null;
67
+ bannerUrl?: string | null;
68
+ startDate?: string | null;
69
+ endDate?: string | null;
70
+ entryCount?: number;
71
+ }
72
+
73
+ const { data: contests, pending: contestsPending } = await useFetch<{ items: ContestListItem[] }>('/api/contests', {
62
74
  query: { limit: 3 },
63
75
  });
64
76
 
@@ -66,9 +78,9 @@ const heroDismissed = ref(false);
66
78
  const joinedHubs = ref(new Set<string>());
67
79
 
68
80
  // Active contest for hero banner
69
- const activeContest = computed(() => {
81
+ const activeContest = computed<ContestListItem | null>(() => {
70
82
  const items = contests.value?.items;
71
- return items?.find((c) => c.status === 'active') ?? null;
83
+ return items?.find((c: ContestListItem) => c.status === 'active') ?? null;
72
84
  });
73
85
 
74
86
  const isAuthenticated = computed(() => !!user.value);
@@ -79,7 +79,7 @@ if (profile.value) {
79
79
  form.value.bannerUrl = p.bannerUrl || '';
80
80
 
81
81
  if (Array.isArray(p.skills)) {
82
- skills.value = p.skills.filter((s): s is string => typeof s === 'string');
82
+ skills.value = (p.skills as unknown[]).filter((s): s is string => typeof s === 'string');
83
83
  }
84
84
  pronouns.value = p.pronouns || '';
85
85
  if (p.socialLinks) {