@actuate-media/cms-admin 0.18.0 → 0.20.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.
Files changed (167) hide show
  1. package/dist/AdminRoot.d.ts.map +1 -1
  2. package/dist/AdminRoot.js +9 -5
  3. package/dist/AdminRoot.js.map +1 -1
  4. package/dist/__tests__/lib/post-editor-service.test.js +75 -23
  5. package/dist/__tests__/lib/post-editor-service.test.js.map +1 -1
  6. package/dist/__tests__/lib/posts-service.test.js +132 -142
  7. package/dist/__tests__/lib/posts-service.test.js.map +1 -1
  8. package/dist/__tests__/views/posts-list-view.render.test.d.ts +2 -0
  9. package/dist/__tests__/views/posts-list-view.render.test.d.ts.map +1 -0
  10. package/dist/__tests__/views/posts-list-view.render.test.js +73 -0
  11. package/dist/__tests__/views/posts-list-view.render.test.js.map +1 -0
  12. package/dist/actuate-admin.css +1 -1
  13. package/dist/components/seo/Drawer.d.ts +11 -0
  14. package/dist/components/seo/Drawer.d.ts.map +1 -0
  15. package/dist/components/seo/Drawer.js +13 -0
  16. package/dist/components/seo/Drawer.js.map +1 -0
  17. package/dist/components/seo/RedirectEditorDrawer.d.ts +9 -0
  18. package/dist/components/seo/RedirectEditorDrawer.d.ts.map +1 -0
  19. package/dist/components/seo/RedirectEditorDrawer.js +94 -0
  20. package/dist/components/seo/RedirectEditorDrawer.js.map +1 -0
  21. package/dist/components/seo/SeoCopilotDrawer.d.ts +10 -0
  22. package/dist/components/seo/SeoCopilotDrawer.d.ts.map +1 -0
  23. package/dist/components/seo/SeoCopilotDrawer.js +34 -0
  24. package/dist/components/seo/SeoCopilotDrawer.js.map +1 -0
  25. package/dist/components/seo/SeoEditorDrawer.d.ts +8 -0
  26. package/dist/components/seo/SeoEditorDrawer.d.ts.map +1 -0
  27. package/dist/components/seo/SeoEditorDrawer.js +111 -0
  28. package/dist/components/seo/SeoEditorDrawer.js.map +1 -0
  29. package/dist/components/seo/SeoIssueFixDrawer.d.ts +8 -0
  30. package/dist/components/seo/SeoIssueFixDrawer.d.ts.map +1 -0
  31. package/dist/components/seo/SeoIssueFixDrawer.js +111 -0
  32. package/dist/components/seo/SeoIssueFixDrawer.js.map +1 -0
  33. package/dist/components/seo/primitives.d.ts +53 -0
  34. package/dist/components/seo/primitives.d.ts.map +1 -0
  35. package/dist/components/seo/primitives.js +100 -0
  36. package/dist/components/seo/primitives.js.map +1 -0
  37. package/dist/index.d.ts +0 -2
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js +0 -2
  40. package/dist/index.js.map +1 -1
  41. package/dist/layout/Sidebar.d.ts.map +1 -1
  42. package/dist/layout/Sidebar.js +3 -0
  43. package/dist/layout/Sidebar.js.map +1 -1
  44. package/dist/lib/post-editor-service.d.ts +6 -4
  45. package/dist/lib/post-editor-service.d.ts.map +1 -1
  46. package/dist/lib/post-editor-service.js +32 -37
  47. package/dist/lib/post-editor-service.js.map +1 -1
  48. package/dist/lib/posts-service.d.ts.map +1 -1
  49. package/dist/lib/posts-service.js +91 -160
  50. package/dist/lib/posts-service.js.map +1 -1
  51. package/dist/lib/seo-service.d.ts +322 -0
  52. package/dist/lib/seo-service.d.ts.map +1 -0
  53. package/dist/lib/seo-service.js +295 -0
  54. package/dist/lib/seo-service.js.map +1 -0
  55. package/dist/router/index.d.ts.map +1 -1
  56. package/dist/router/index.js +4 -1
  57. package/dist/router/index.js.map +1 -1
  58. package/dist/views/MediaBrowser.d.ts.map +1 -1
  59. package/dist/views/MediaBrowser.js +36 -25
  60. package/dist/views/MediaBrowser.js.map +1 -1
  61. package/dist/views/Posts/NewPostPicker.d.ts +5 -4
  62. package/dist/views/Posts/NewPostPicker.d.ts.map +1 -1
  63. package/dist/views/Posts/NewPostPicker.js +5 -4
  64. package/dist/views/Posts/NewPostPicker.js.map +1 -1
  65. package/dist/views/Posts/NewPostTypeInstructions.js +2 -2
  66. package/dist/views/Posts/PostTypesView.d.ts +5 -4
  67. package/dist/views/Posts/PostTypesView.d.ts.map +1 -1
  68. package/dist/views/Posts/PostTypesView.js.map +1 -1
  69. package/dist/views/Posts/PostsListView.d.ts.map +1 -1
  70. package/dist/views/Posts/PostsListView.js +8 -0
  71. package/dist/views/Posts/PostsListView.js.map +1 -1
  72. package/dist/views/Posts/post-type-presets.d.ts +5 -0
  73. package/dist/views/Posts/post-type-presets.d.ts.map +1 -1
  74. package/dist/views/Posts/post-type-presets.js +10 -64
  75. package/dist/views/Posts/post-type-presets.js.map +1 -1
  76. package/dist/views/SEO.d.ts.map +1 -1
  77. package/dist/views/SEO.js +89 -132
  78. package/dist/views/SEO.js.map +1 -1
  79. package/dist/views/page-editor/sections/ArticleBodySection.d.ts +6 -2
  80. package/dist/views/page-editor/sections/ArticleBodySection.d.ts.map +1 -1
  81. package/dist/views/page-editor/sections/ArticleBodySection.js +8 -8
  82. package/dist/views/page-editor/sections/ArticleBodySection.js.map +1 -1
  83. package/dist/views/post-editor/PostEditorCanvas.js +7 -1
  84. package/dist/views/post-editor/PostEditorCanvas.js.map +1 -1
  85. package/dist/views/post-editor/PostFieldsModal.d.ts.map +1 -1
  86. package/dist/views/post-editor/PostFieldsModal.js +10 -4
  87. package/dist/views/post-editor/PostFieldsModal.js.map +1 -1
  88. package/dist/views/post-editor/PostHeader.d.ts.map +1 -1
  89. package/dist/views/post-editor/PostHeader.js +4 -3
  90. package/dist/views/post-editor/PostHeader.js.map +1 -1
  91. package/dist/views/post-editor/PostPreview.d.ts.map +1 -1
  92. package/dist/views/post-editor/PostPreview.js +11 -1
  93. package/dist/views/post-editor/PostPreview.js.map +1 -1
  94. package/dist/views/post-editor/PostSectionEditor.d.ts +22 -2
  95. package/dist/views/post-editor/PostSectionEditor.d.ts.map +1 -1
  96. package/dist/views/post-editor/PostSectionEditor.js +4 -1
  97. package/dist/views/post-editor/PostSectionEditor.js.map +1 -1
  98. package/dist/views/seo/AuditTab.d.ts +6 -0
  99. package/dist/views/seo/AuditTab.d.ts.map +1 -0
  100. package/dist/views/seo/AuditTab.js +57 -0
  101. package/dist/views/seo/AuditTab.js.map +1 -0
  102. package/dist/views/seo/ContentTab.d.ts +5 -0
  103. package/dist/views/seo/ContentTab.d.ts.map +1 -0
  104. package/dist/views/seo/ContentTab.js +27 -0
  105. package/dist/views/seo/ContentTab.js.map +1 -0
  106. package/dist/views/seo/OverviewTab.d.ts +8 -0
  107. package/dist/views/seo/OverviewTab.d.ts.map +1 -0
  108. package/dist/views/seo/OverviewTab.js +35 -0
  109. package/dist/views/seo/OverviewTab.js.map +1 -0
  110. package/dist/views/seo/RedirectsTab.d.ts +2 -0
  111. package/dist/views/seo/RedirectsTab.d.ts.map +1 -0
  112. package/dist/views/seo/RedirectsTab.js +124 -0
  113. package/dist/views/seo/RedirectsTab.js.map +1 -0
  114. package/dist/views/seo/TechnicalTab.d.ts +2 -0
  115. package/dist/views/seo/TechnicalTab.d.ts.map +1 -0
  116. package/dist/views/seo/TechnicalTab.js +102 -0
  117. package/dist/views/seo/TechnicalTab.js.map +1 -0
  118. package/dist/views/seo/useSeoResource.d.ts +8 -0
  119. package/dist/views/seo/useSeoResource.d.ts.map +1 -0
  120. package/dist/views/seo/useSeoResource.js +42 -0
  121. package/dist/views/seo/useSeoResource.js.map +1 -0
  122. package/package.json +2 -2
  123. package/src/AdminRoot.tsx +9 -5
  124. package/src/__tests__/lib/post-editor-service.test.ts +78 -23
  125. package/src/__tests__/lib/posts-service.test.ts +134 -163
  126. package/src/__tests__/views/posts-list-view.render.test.tsx +84 -0
  127. package/src/components/seo/Drawer.tsx +61 -0
  128. package/src/components/seo/RedirectEditorDrawer.tsx +235 -0
  129. package/src/components/seo/SeoCopilotDrawer.tsx +76 -0
  130. package/src/components/seo/SeoEditorDrawer.tsx +347 -0
  131. package/src/components/seo/SeoIssueFixDrawer.tsx +244 -0
  132. package/src/components/seo/primitives.tsx +237 -0
  133. package/src/index.ts +0 -2
  134. package/src/layout/Sidebar.tsx +3 -0
  135. package/src/lib/post-editor-service.ts +41 -40
  136. package/src/lib/posts-service.ts +109 -180
  137. package/src/lib/seo-service.ts +623 -0
  138. package/src/router/index.ts +4 -1
  139. package/src/views/MediaBrowser.tsx +89 -67
  140. package/src/views/Posts/NewPostPicker.tsx +5 -4
  141. package/src/views/Posts/NewPostTypeInstructions.tsx +2 -2
  142. package/src/views/Posts/PostTypesView.tsx +5 -4
  143. package/src/views/Posts/PostsListView.tsx +9 -0
  144. package/src/views/Posts/post-type-presets.ts +15 -64
  145. package/src/views/SEO.tsx +186 -863
  146. package/src/views/page-editor/sections/ArticleBodySection.tsx +12 -16
  147. package/src/views/post-editor/PostEditorCanvas.tsx +7 -1
  148. package/src/views/post-editor/PostFieldsModal.tsx +36 -21
  149. package/src/views/post-editor/PostHeader.tsx +4 -4
  150. package/src/views/post-editor/PostPreview.tsx +12 -1
  151. package/src/views/post-editor/PostSectionEditor.tsx +22 -5
  152. package/src/views/seo/AuditTab.tsx +229 -0
  153. package/src/views/seo/ContentTab.tsx +164 -0
  154. package/src/views/seo/OverviewTab.tsx +257 -0
  155. package/src/views/seo/RedirectsTab.tsx +392 -0
  156. package/src/views/seo/TechnicalTab.tsx +303 -0
  157. package/src/views/seo/useSeoResource.ts +52 -0
  158. package/dist/views/PostEditor.d.ts +0 -6
  159. package/dist/views/PostEditor.d.ts.map +0 -1
  160. package/dist/views/PostEditor.js +0 -79
  161. package/dist/views/PostEditor.js.map +0 -1
  162. package/dist/views/Posts.d.ts +0 -5
  163. package/dist/views/Posts.d.ts.map +0 -1
  164. package/dist/views/Posts.js +0 -73
  165. package/dist/views/Posts.js.map +0 -1
  166. package/src/views/PostEditor.tsx +0 -257
  167. package/src/views/Posts.tsx +0 -375
@@ -1,25 +1,16 @@
1
1
  /**
2
- * Posts service — thin client over the existing REST endpoints,
3
- * shaped around the data the Posts admin area needs.
2
+ * Posts service — thin client over the CMS REST endpoints, shaped around the
3
+ * data the Posts admin area needs.
4
4
  *
5
- * V1 strategy: aggregate across post-typed collections client-side
6
- * (one `/collections/:slug` call per type) and join authors via
7
- * `/users`. Each view component pulls from `fetchPosts()` so when
8
- * a server-side `/api/cms/posts` endpoint lands later, only this
9
- * file changes callers consume the same `Post[]` / `PostType[]`
10
- * shapes.
5
+ * `fetchPosts` calls the server-side aggregate endpoint `GET /posts`, which
6
+ * does the cross-collection filter / sort / paginate at the DB level (one
7
+ * query + one count) and returns the post rows alongside dataset-wide type
8
+ * counts and the contributor list. This keeps the Posts list O(page) instead
9
+ * of pulling every document per type into the browser, and lets it scale past
10
+ * the old ~500-row-per-type client cap.
11
11
  *
12
- * Why not a single `/collections/all` call?
13
- * - Each collection has its own access-control check, so listing
14
- * across collections must respect per-collection `read` rules.
15
- * The existing endpoint enforces this per-call; mixing them
16
- * server-side would need a new auth boundary.
17
- * - V1 traffic is small (the seed is 15 rows); a few extra
18
- * parallel requests are well under the rate-limit budget.
19
- *
20
- * Promote to a single endpoint when:
21
- * - Any post-type collection grows past ~5k rows, OR
22
- * - Page-load latency exceeds 300ms in the admin metrics.
12
+ * Access control still lives server-side: the endpoint only returns rows from
13
+ * collections the caller's scope can read.
23
14
  */
24
15
  import { cmsApi } from './api.js';
25
16
  function isPostsCollection(c) {
@@ -54,41 +45,17 @@ function collectionToPostType(c, count = 0) {
54
45
  active: true,
55
46
  };
56
47
  }
57
- function initialsFromName(name, email) {
58
- if (name && name.trim().length > 0) {
59
- const parts = name.trim().split(/\s+/);
60
- const first = parts[0]?.[0] ?? '';
61
- const last = parts.length > 1 ? (parts[parts.length - 1]?.[0] ?? '') : '';
62
- return (first + last).toUpperCase() || (email[0] ?? '?').toUpperCase();
63
- }
64
- return (email[0] ?? '?').toUpperCase();
65
- }
66
- async function fetchAuthorsMap() {
67
- const res = await cmsApi('/users?pageSize=200');
68
- const list = Array.isArray(res.data)
69
- ? res.data
70
- : (res.data?.users ?? []);
71
- const map = new Map();
72
- for (const u of list) {
73
- map.set(u.id, {
74
- id: u.id,
75
- name: u.name?.trim() || u.email,
76
- initials: initialsFromName(u.name, u.email),
77
- });
78
- }
79
- return map;
80
- }
81
- function extractSeoScore(data) {
82
- if (!data)
83
- return null;
84
- const candidates = ['seoScore', 'seo_score', 'metaScore'];
85
- for (const k of candidates) {
86
- const v = data[k];
87
- if (typeof v === 'number' && Number.isFinite(v))
88
- return v;
89
- }
90
- return null;
48
+ // ─── Authors ─────────────────────────────────────────────────────────
49
+ function initialsFromName(name) {
50
+ const trimmed = name?.trim();
51
+ if (!trimmed)
52
+ return '?';
53
+ const parts = trimmed.split(/\s+/);
54
+ const first = parts[0]?.[0] ?? '';
55
+ const last = parts.length > 1 ? (parts[parts.length - 1]?.[0] ?? '') : '';
56
+ return (first + last).toUpperCase() || '?';
91
57
  }
58
+ /** Display date matches the old client behaviour: scheduled/published date when set, else updated. */
92
59
  function pickDisplayDate(d) {
93
60
  if (d.status === 'SCHEDULED' && d.scheduledAt)
94
61
  return d.scheduledAt;
@@ -96,122 +63,86 @@ function pickDisplayDate(d) {
96
63
  return d.publishedAt;
97
64
  return d.updatedAt;
98
65
  }
66
+ function buildPostsQueryString(query) {
67
+ const params = new URLSearchParams();
68
+ if (query.search?.trim())
69
+ params.set('search', query.search.trim());
70
+ if (query.postType && query.postType !== 'all')
71
+ params.set('postType', query.postType);
72
+ if (query.status && query.status !== 'all')
73
+ params.set('status', query.status);
74
+ if (query.author && query.author !== 'all')
75
+ params.set('author', query.author);
76
+ if (query.sortBy)
77
+ params.set('sortBy', query.sortBy);
78
+ if (query.sortDirection)
79
+ params.set('sortDirection', query.sortDirection);
80
+ params.set('page', String(Math.max(1, query.page ?? 1)));
81
+ params.set('pageSize', String(Math.max(1, query.pageSize ?? 10)));
82
+ const qs = params.toString();
83
+ return qs ? `?${qs}` : '';
84
+ }
99
85
  export async function fetchPosts(query = {}) {
100
- const cols = await fetchPostCollections();
101
- const authorsMap = await fetchAuthorsMap();
102
- // Pull every doc for each post type (cap at 500 to avoid runaway
103
- // requests; pagination + filtering still happens client-side over
104
- // this set). When a type grows past 500 docs we'll need the
105
- // server-side aggregate endpoint described in this file's header.
106
- const perTypeRaw = await Promise.all(cols.map(async (c) => {
107
- const res = await cmsApi(`/collections/${encodeURIComponent(c.slug)}?pageSize=500&sort=updatedAt&order=desc`);
108
- const docs = (res.data?.docs ?? []);
109
- return { col: c, docs };
110
- }));
111
- // Map docs → Post objects.
112
- const allPosts = [];
113
- for (const { col, docs } of perTypeRaw) {
114
- for (const d of docs) {
115
- const author = (d.createdById && authorsMap.get(d.createdById)) ||
116
- (d.updatedById && authorsMap.get(d.updatedById)) || {
117
- id: '',
118
- name: 'Unknown',
119
- initials: '??',
120
- };
121
- allPosts.push({
122
- id: d.id,
123
- title: d.title ?? d.data?.title ?? '(untitled)',
124
- slug: d.slug ?? d.data?.slug ?? '',
125
- postTypeId: col.slug,
126
- postTypeName: col.labels.singular,
127
- postTypeAccentColor: col.color ?? null,
128
- authorId: author.id,
129
- authorName: author.name,
130
- authorInitials: author.initials,
131
- status: d.status,
132
- publishDate: d.publishedAt ?? d.scheduledAt ?? null,
133
- updatedDate: pickDisplayDate(d),
134
- seoScore: extractSeoScore(d.data),
135
- createdAt: d.createdAt,
136
- updatedAt: d.updatedAt,
137
- });
138
- }
139
- }
140
- // Compute per-type counts BEFORE filtering — the tabs at the top
141
- // of the page reflect the dataset, not the active query.
142
- const countsBySlug = new Map();
143
- for (const p of allPosts) {
144
- countsBySlug.set(p.postTypeId, (countsBySlug.get(p.postTypeId) ?? 0) + 1);
145
- }
146
- const types = cols.map((c) => collectionToPostType(c, countsBySlug.get(c.slug) ?? 0));
147
- // Apply filters / search.
148
- const search = (query.search ?? '').trim().toLowerCase();
149
- const filtered = allPosts.filter((p) => {
150
- if (query.postType && query.postType !== 'all' && p.postTypeId !== query.postType)
151
- return false;
152
- if (query.status && query.status !== 'all' && p.status !== query.status)
153
- return false;
154
- if (query.author && query.author !== 'all' && p.authorId !== query.author)
155
- return false;
156
- if (search) {
157
- const haystack = `${p.title} ${p.slug} ${p.authorName} ${p.postTypeName}`.toLowerCase();
158
- if (!haystack.includes(search))
159
- return false;
160
- }
161
- return true;
162
- });
163
- // Sort.
164
- const sortBy = query.sortBy ?? 'date';
165
- const dir = query.sortDirection ?? 'desc';
166
- filtered.sort((a, b) => {
167
- const cmp = comparePostsFor(sortBy, a, b);
168
- return dir === 'asc' ? cmp : -cmp;
169
- });
170
- // Paginate.
171
86
  const page = Math.max(1, query.page ?? 1);
172
87
  const pageSize = Math.max(1, query.pageSize ?? 10);
173
- const start = (page - 1) * pageSize;
174
- const paged = filtered.slice(start, start + pageSize);
175
- // Unique authors from the full set (so the dropdown lists every
176
- // contributor, not just the currently visible page).
177
- const authorIds = new Set();
178
- const authors = [];
179
- for (const p of allPosts) {
180
- if (p.authorId && !authorIds.has(p.authorId)) {
181
- authorIds.add(p.authorId);
182
- authors.push({ id: p.authorId, name: p.authorName, initials: p.authorInitials });
183
- }
88
+ const res = await cmsApi(`/posts${buildPostsQueryString(query)}`);
89
+ if (res.error || !res.data) {
90
+ throw new Error(res.error ?? 'Failed to load posts');
184
91
  }
185
- authors.sort((a, b) => a.name.localeCompare(b.name));
92
+ const r = res.data;
93
+ const typeBySlug = new Map();
94
+ for (const t of r.types)
95
+ typeBySlug.set(t.slug, t);
96
+ const types = r.types.map((t) => ({
97
+ id: t.slug,
98
+ slug: t.slug,
99
+ name: t.plural,
100
+ singularName: t.singular,
101
+ description: t.description ?? null,
102
+ urlBase: `/${t.urlPrefix || t.slug}`,
103
+ accentColor: t.color ?? null,
104
+ icon: t.icon ?? null,
105
+ postCount: t.count,
106
+ fieldCount: t.fieldCount,
107
+ active: true,
108
+ }));
109
+ const posts = r.posts.map((d) => {
110
+ const type = typeBySlug.get(d.collection);
111
+ const authorName = d.author?.name?.trim() || 'Unknown';
112
+ return {
113
+ id: d.id,
114
+ title: d.title ?? '(untitled)',
115
+ slug: d.slug ?? '',
116
+ postTypeId: d.collection,
117
+ postTypeName: type?.singular ?? d.collection,
118
+ postTypeAccentColor: type?.color ?? null,
119
+ authorId: d.author?.id ?? '',
120
+ authorName,
121
+ authorInitials: d.author ? initialsFromName(d.author.name) : '??',
122
+ status: d.status,
123
+ publishDate: d.publishedAt ?? d.scheduledAt ?? null,
124
+ updatedDate: pickDisplayDate(d),
125
+ seoScore: d.seoScore,
126
+ createdAt: d.createdAt,
127
+ updatedAt: d.updatedAt,
128
+ };
129
+ });
130
+ const authors = r.authors
131
+ .map((a) => ({
132
+ id: a.id,
133
+ name: a.name?.trim() || 'Unknown',
134
+ initials: initialsFromName(a.name),
135
+ }))
136
+ .sort((a, b) => a.name.localeCompare(b.name));
186
137
  return {
187
- posts: paged,
188
- total: filtered.length,
189
- page,
190
- pageSize,
138
+ posts,
139
+ total: r.total,
140
+ page: r.page ?? page,
141
+ pageSize: r.pageSize ?? pageSize,
191
142
  types,
192
143
  authors,
193
144
  };
194
145
  }
195
- function comparePostsFor(by, a, b) {
196
- switch (by) {
197
- case 'title':
198
- return a.title.localeCompare(b.title);
199
- case 'type':
200
- return a.postTypeName.localeCompare(b.postTypeName);
201
- case 'author':
202
- return a.authorName.localeCompare(b.authorName);
203
- case 'status':
204
- return a.status.localeCompare(b.status);
205
- case 'seo': {
206
- const av = a.seoScore ?? -1;
207
- const bv = b.seoScore ?? -1;
208
- return av - bv;
209
- }
210
- case 'date':
211
- default:
212
- return new Date(a.updatedDate).getTime() - new Date(b.updatedDate).getTime();
213
- }
214
- }
215
146
  // ─── Bulk mutations ──────────────────────────────────────────────────
216
147
  export async function bulkUpdatePosts(ids, payload) {
217
148
  let ok = 0;
@@ -1 +1 @@
1
- {"version":3,"file":"posts-service.js","sourceRoot":"","sources":["../../src/lib/posts-service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"posts-service.js","sourceRoot":"","sources":["../../src/lib/posts-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,322 @@
1
+ export type SeoGrade = 'good' | 'fair' | 'poor' | 'critical';
2
+ export type SeoSeverity = 'critical' | 'warning' | 'info';
3
+ export type SeoIssueStatus = 'open' | 'ignored' | 'resolved' | 'recurring';
4
+ export type SeoIssueCategory = 'content' | 'technical' | 'redirects' | 'media' | 'performance' | 'schema' | 'social' | 'indexing';
5
+ export type RedirectStatusCode = 301 | 302 | 307 | 308 | 410;
6
+ export interface SeoSiteScore {
7
+ score: number;
8
+ grade: SeoGrade;
9
+ /** Change vs the previous audit run, e.g. +6. */
10
+ delta: number | null;
11
+ breakdown: {
12
+ category: string;
13
+ score: number;
14
+ weight: number;
15
+ contribution: number;
16
+ }[];
17
+ }
18
+ export interface SeoMetric {
19
+ label: string;
20
+ value: string;
21
+ helper: string;
22
+ /** Optional trend direction for the helper colour. */
23
+ trend?: 'up' | 'down' | 'flat';
24
+ }
25
+ export interface SeoIssue {
26
+ id: string;
27
+ auditRunId: string | null;
28
+ entityType: string | null;
29
+ entityId: string | null;
30
+ entityTitle: string | null;
31
+ url: string | null;
32
+ severity: SeoSeverity;
33
+ category: SeoIssueCategory;
34
+ type: string;
35
+ title: string;
36
+ description: string | null;
37
+ impact: string | null;
38
+ recommendation: string | null;
39
+ status: SeoIssueStatus;
40
+ fixable: boolean;
41
+ fixActionType: string | null;
42
+ relatedEntityIds: string[];
43
+ source: string;
44
+ firstDetectedAt: string | null;
45
+ lastDetectedAt: string | null;
46
+ resolvedAt: string | null;
47
+ }
48
+ export interface QuickWin {
49
+ id: string;
50
+ title: string;
51
+ explanation: string;
52
+ impact: 'High' | 'Medium' | 'Low';
53
+ issueId: string | null;
54
+ fixActionType: string | null;
55
+ }
56
+ export interface SearchPerformanceRow {
57
+ url: string;
58
+ title: string;
59
+ impressions: number;
60
+ clicks: number;
61
+ ctr: number;
62
+ averagePosition: number;
63
+ }
64
+ export interface SeoOverview {
65
+ siteScore: SeoSiteScore;
66
+ metrics: SeoMetric[];
67
+ issues: SeoIssue[];
68
+ issuesSummary: {
69
+ total: number;
70
+ critical: number;
71
+ warning: number;
72
+ info: number;
73
+ };
74
+ quickWins: QuickWin[];
75
+ searchPerformance: SearchPerformanceRow[];
76
+ searchConsoleConnected: boolean;
77
+ lastAuditRunId: string | null;
78
+ }
79
+ export declare function fetchSeoOverview(): Promise<SeoOverview>;
80
+ export declare function fetchSearchPerformance(params?: {
81
+ limit?: number;
82
+ }): Promise<SearchPerformanceRow[]>;
83
+ export interface SeoContentRecord {
84
+ id: string;
85
+ entityType: 'page' | 'post';
86
+ entityId: string;
87
+ title: string;
88
+ url: string;
89
+ canonicalUrl: string | null;
90
+ metaTitle: string | null;
91
+ metaDescription: string | null;
92
+ focusKeyword: string | null;
93
+ ogTitle: string | null;
94
+ ogDescription: string | null;
95
+ ogImageId: string | null;
96
+ ogImage: string | null;
97
+ twitterTitle: string | null;
98
+ twitterDescription: string | null;
99
+ twitterImageId: string | null;
100
+ noindex: boolean;
101
+ nofollow: boolean;
102
+ structuredDataType: string | null;
103
+ structuredData: Record<string, unknown> | null;
104
+ seoScore: number;
105
+ seoGrade: SeoGrade;
106
+ updatedAt: string | null;
107
+ }
108
+ export type ContentSeoFilter = 'all' | 'pages' | 'posts';
109
+ export declare function fetchSeoContentRecords(): Promise<SeoContentRecord[]>;
110
+ export declare function fetchSeoContentRecord(entityType: string, entityId: string): Promise<SeoContentRecord | null>;
111
+ export interface SeoFieldPayload {
112
+ metaTitle?: string;
113
+ metaDescription?: string;
114
+ canonicalUrl?: string;
115
+ focusKeyword?: string;
116
+ ogTitle?: string;
117
+ ogDescription?: string;
118
+ ogImage?: string;
119
+ twitterTitle?: string;
120
+ twitterDescription?: string;
121
+ twitterImage?: string;
122
+ noindex?: boolean;
123
+ nofollow?: boolean;
124
+ structuredDataType?: string;
125
+ structuredData?: Record<string, unknown>;
126
+ }
127
+ export declare function updateSeoFields(entityType: string, entityId: string, payload: SeoFieldPayload): Promise<{
128
+ error?: string;
129
+ }>;
130
+ /** Pure search/filter over the content records (decoupled from network for tests). */
131
+ export declare function applyContentSeoQuery(records: SeoContentRecord[], query: {
132
+ search?: string;
133
+ filter?: ContentSeoFilter;
134
+ }): SeoContentRecord[];
135
+ export type SeoAuditScope = 'full' | 'content' | 'technical' | 'redirect';
136
+ export interface SeoAuditRun {
137
+ id: string;
138
+ status: 'RUNNING' | 'COMPLETED' | 'FAILED';
139
+ scope: string;
140
+ startedAt: string;
141
+ finishedAt: string | null;
142
+ siteScoreBefore: number | null;
143
+ siteScoreAfter: number | null;
144
+ pagesScanned: number;
145
+ issuesFound: number;
146
+ criticalCount: number;
147
+ warningCount: number;
148
+ infoCount: number;
149
+ errorMessage: string | null;
150
+ }
151
+ export declare function runSeoAudit(scope?: SeoAuditScope): Promise<{
152
+ run?: SeoAuditRun;
153
+ error?: string;
154
+ }>;
155
+ export declare function fetchSeoAuditRuns(): Promise<SeoAuditRun[]>;
156
+ export declare function fetchSeoAuditRun(auditRunId: string): Promise<SeoAuditRun | null>;
157
+ export interface SeoIssueQuery {
158
+ severity?: SeoSeverity | 'all';
159
+ category?: SeoIssueCategory | 'all';
160
+ status?: SeoIssueStatus | 'all';
161
+ auditRunId?: string;
162
+ }
163
+ export declare function fetchSeoIssues(query?: SeoIssueQuery): Promise<SeoIssue[]>;
164
+ export declare function fetchSeoIssue(issueId: string): Promise<SeoIssue | null>;
165
+ export declare function resolveSeoIssue(issueId: string): Promise<{
166
+ error?: string;
167
+ }>;
168
+ export declare function ignoreSeoIssue(issueId: string): Promise<{
169
+ error?: string;
170
+ }>;
171
+ export declare function reopenSeoIssue(issueId: string): Promise<{
172
+ error?: string;
173
+ }>;
174
+ export interface SitemapStatus {
175
+ sitemapUrl: string;
176
+ lastGeneratedAt: string | null;
177
+ pagesIncluded: number;
178
+ pagesExcluded: number;
179
+ autoRegenerateOnPublish: boolean;
180
+ errors: string[];
181
+ warnings: string[];
182
+ }
183
+ export interface CrawlSettings {
184
+ indexEntireSite: boolean;
185
+ includeImagesInSitemap: boolean;
186
+ includePostsInSitemap: boolean;
187
+ noindexPaginatedArchives: boolean;
188
+ noindexTagPages: boolean;
189
+ }
190
+ export declare function fetchSitemapStatus(): Promise<SitemapStatus | null>;
191
+ export declare function regenerateSitemap(): Promise<{
192
+ status?: SitemapStatus;
193
+ error?: string;
194
+ }>;
195
+ export declare function fetchCrawlSettings(): Promise<CrawlSettings | null>;
196
+ export declare function updateCrawlSettings(payload: Partial<CrawlSettings>): Promise<{
197
+ error?: string;
198
+ }>;
199
+ export interface RobotsConfig {
200
+ body: string;
201
+ generated: boolean;
202
+ }
203
+ export interface RobotsValidation {
204
+ valid: boolean;
205
+ blocksEntireSite: boolean;
206
+ errors: string[];
207
+ warnings: string[];
208
+ }
209
+ export declare function fetchRobotsTxt(): Promise<RobotsConfig | null>;
210
+ export declare function updateRobotsTxt(body: string): Promise<{
211
+ error?: string;
212
+ }>;
213
+ /** Client-side robots.txt validation (mirrors server-side checks). */
214
+ export declare function validateRobotsTxt(body: string): RobotsValidation;
215
+ export interface RedirectRule {
216
+ id: string;
217
+ type: RedirectStatusCode;
218
+ fromPath: string;
219
+ toPath: string;
220
+ enabled: boolean;
221
+ priority: number;
222
+ preserveQuery: boolean;
223
+ hits: number;
224
+ lastHitAt: string | null;
225
+ stale: boolean;
226
+ source: string;
227
+ notes: string | null;
228
+ createdAt: string;
229
+ updatedAt: string;
230
+ }
231
+ export interface RedirectOverview {
232
+ activeRedirects: number;
233
+ staleRedirects: number;
234
+ notFoundCount: number;
235
+ notFoundHits: number;
236
+ chainsAndLoops: number;
237
+ trafficRecovered: number;
238
+ }
239
+ export interface Redirect404 {
240
+ id: string;
241
+ path: string;
242
+ hits: number;
243
+ lastSeenAt: string;
244
+ }
245
+ export interface RedirectSuggestion {
246
+ id: string;
247
+ fromPath: string;
248
+ toPath: string;
249
+ confidence: number;
250
+ reason: string | null;
251
+ status: 'open' | 'accepted' | 'dismissed';
252
+ hits: number;
253
+ trend: string | null;
254
+ }
255
+ export interface RedirectChain {
256
+ id: string;
257
+ kind: 'chain' | 'loop';
258
+ hops: string[];
259
+ suggestedFrom: string;
260
+ suggestedTo: string;
261
+ }
262
+ export declare function fetchRedirectOverview(): Promise<RedirectOverview>;
263
+ export declare function fetchRedirectRules(): Promise<RedirectRule[]>;
264
+ export interface RedirectRulePayload {
265
+ type: RedirectStatusCode;
266
+ fromPath: string;
267
+ toPath: string;
268
+ enabled?: boolean;
269
+ preserveQuery?: boolean;
270
+ notes?: string;
271
+ }
272
+ export declare function createRedirectRule(payload: RedirectRulePayload): Promise<{
273
+ error?: string;
274
+ }>;
275
+ export declare function updateRedirectRule(redirectId: string, payload: Partial<RedirectRulePayload>): Promise<{
276
+ error?: string;
277
+ }>;
278
+ export declare function deleteRedirectRule(redirectId: string): Promise<{
279
+ error?: string;
280
+ }>;
281
+ export declare function fetchRedirectChains(): Promise<RedirectChain[]>;
282
+ export declare function flattenRedirectChain(chainId: string): Promise<{
283
+ error?: string;
284
+ }>;
285
+ export declare function fetchRedirectSuggestions(): Promise<RedirectSuggestion[]>;
286
+ export declare function generate404RecoverySuggestions(): Promise<{
287
+ error?: string;
288
+ }>;
289
+ export declare function acceptRedirectSuggestion(suggestionId: string): Promise<{
290
+ error?: string;
291
+ }>;
292
+ export declare function dismissRedirectSuggestion(suggestionId: string): Promise<{
293
+ error?: string;
294
+ }>;
295
+ export declare function exportRedirectsCsv(): Promise<{
296
+ csv?: string;
297
+ error?: string;
298
+ }>;
299
+ export declare function importRedirectsCsv(csv: string): Promise<{
300
+ imported?: number;
301
+ errors?: string[];
302
+ error?: string;
303
+ }>;
304
+ export interface SeoAiResult {
305
+ text?: string;
306
+ alternatives?: string[];
307
+ structuredData?: Record<string, unknown>;
308
+ /** True when the AI provider is not configured (graceful fallback). */
309
+ unavailable?: boolean;
310
+ }
311
+ export declare function generateSeoField(field: 'metaTitle' | 'metaDescription' | 'ogTitle' | 'ogDescription' | 'focusKeyword', context: {
312
+ entityType: string;
313
+ entityId: string;
314
+ }): Promise<SeoAiResult>;
315
+ export declare function explainSeoIssue(issueId: string): Promise<SeoAiResult>;
316
+ export declare function generateStructuredData(context: {
317
+ entityType: string;
318
+ entityId: string;
319
+ schemaType: string;
320
+ }): Promise<SeoAiResult>;
321
+ export declare function summarizeSeoAudit(): Promise<SeoAiResult>;
322
+ //# sourceMappingURL=seo-service.d.ts.map