@byline/host-tanstack-start 4.15.0 → 4.17.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 (183) hide show
  1. package/dist/admin-shell/chrome/admin-menu-drawer.d.ts +2 -1
  2. package/dist/admin-shell/chrome/admin-menu-drawer.js +17 -5
  3. package/dist/admin-shell/chrome/dashboard.js +41 -5
  4. package/dist/admin-shell/chrome/dashboard.test.d.ts +8 -0
  5. package/dist/admin-shell/collections/api.d.ts +2 -2
  6. package/dist/admin-shell/collections/create.d.ts +2 -2
  7. package/dist/admin-shell/collections/create.js +1 -0
  8. package/dist/admin-shell/collections/edit.d.ts +2 -2
  9. package/dist/admin-shell/collections/edit.js +1 -0
  10. package/dist/admin-shell/collections/history.d.ts +4 -12
  11. package/dist/admin-shell/collections/history.js +112 -303
  12. package/dist/admin-shell/collections/reindex-button.d.ts +1 -1
  13. package/dist/admin-shell/collections/reindex-button.js +5 -1
  14. package/dist/admin-shell/collections/restore-version-modal.d.ts +4 -4
  15. package/dist/admin-shell/collections/restore-version-modal.js +8 -24
  16. package/dist/admin-shell/collections/version-history.d.ts +72 -0
  17. package/dist/admin-shell/collections/version-history.js +259 -0
  18. package/dist/admin-shell/singletons/history.d.ts +19 -0
  19. package/dist/admin-shell/singletons/history.js +170 -0
  20. package/dist/admin-shell/singletons/history.test.d.ts +8 -0
  21. package/dist/admin-shell/singletons/preview-link.d.ts +12 -0
  22. package/dist/admin-shell/singletons/preview-link.js +54 -0
  23. package/dist/admin-shell/singletons/view-menu.d.ts +13 -0
  24. package/dist/admin-shell/singletons/view-menu.js +116 -0
  25. package/dist/admin-shell/singletons/view.d.ts +18 -0
  26. package/dist/admin-shell/singletons/view.js +259 -0
  27. package/dist/admin-shell/singletons/view.test.d.ts +8 -0
  28. package/dist/integrations/analytics-agent.d.ts +20 -0
  29. package/dist/integrations/analytics-agent.js +57 -0
  30. package/dist/integrations/analytics-events.d.ts +51 -0
  31. package/dist/integrations/analytics-events.js +129 -0
  32. package/dist/integrations/api-utils.d.ts +18 -4
  33. package/dist/integrations/api-utils.js +10 -3
  34. package/dist/integrations/serve-analytics-agent.d.ts +8 -0
  35. package/dist/integrations/serve-analytics-agent.js +11 -0
  36. package/dist/routes/analytics-range.d.ts +12 -0
  37. package/dist/routes/analytics-range.js +35 -0
  38. package/dist/routes/create-admin-analytics-route.d.ts +8 -0
  39. package/dist/routes/create-admin-analytics-route.js +108 -0
  40. package/dist/routes/create-admin-dashboard-route.js +2 -2
  41. package/dist/routes/create-admin-layout-route.js +10 -4
  42. package/dist/routes/create-collection-api-route.js +3 -3
  43. package/dist/routes/create-collection-create-route.js +4 -3
  44. package/dist/routes/create-collection-edit-route.js +4 -3
  45. package/dist/routes/create-collection-history-route.js +4 -3
  46. package/dist/routes/create-collection-list-route.js +4 -3
  47. package/dist/routes/create-singleton-history-route.d.ts +8 -0
  48. package/dist/routes/create-singleton-history-route.js +99 -0
  49. package/dist/routes/create-singleton-route.d.ts +35 -0
  50. package/dist/routes/create-singleton-route.js +130 -0
  51. package/dist/routes/get-multi-collection-definition.d.ts +10 -0
  52. package/dist/routes/get-multi-collection-definition.js +6 -0
  53. package/dist/routes/get-singleton-definition.d.ts +10 -0
  54. package/dist/routes/get-singleton-definition.js +6 -0
  55. package/dist/routes/index.d.ts +3 -0
  56. package/dist/routes/index.js +3 -0
  57. package/dist/server-fns/actors.d.ts +16 -0
  58. package/dist/server-fns/actors.js +25 -0
  59. package/dist/server-fns/admin-document-presentation.d.ts +30 -0
  60. package/dist/server-fns/admin-document-presentation.js +32 -0
  61. package/dist/server-fns/analytics/index.d.ts +9 -0
  62. package/dist/server-fns/analytics/index.js +2 -0
  63. package/dist/server-fns/analytics/maintenance.d.ts +22 -0
  64. package/dist/server-fns/analytics/maintenance.js +42 -0
  65. package/dist/server-fns/analytics/queries.d.ts +25 -0
  66. package/dist/server-fns/analytics/queries.js +54 -0
  67. package/dist/server-fns/collections/actors.d.ts +1 -10
  68. package/dist/server-fns/collections/actors.js +1 -25
  69. package/dist/server-fns/collections/get.js +9 -26
  70. package/dist/server-fns/collections/reorder.js +1 -1
  71. package/dist/server-fns/collections/scheduled-publication.js +2 -2
  72. package/dist/server-fns/collections/upload.js +3 -3
  73. package/dist/server-fns/collections/utils.d.ts +1 -7
  74. package/dist/server-fns/collections/utils.js +1 -4
  75. package/dist/server-fns/serialise.d.ts +14 -0
  76. package/dist/server-fns/serialise.js +4 -0
  77. package/dist/server-fns/singleton-document-read.d.ts +20 -0
  78. package/dist/server-fns/singleton-document-read.js +10 -0
  79. package/dist/server-fns/singletons/cancel-scheduled-publish.d.ts +12 -0
  80. package/dist/server-fns/singletons/cancel-scheduled-publish.js +7 -0
  81. package/dist/server-fns/singletons/change-status.d.ts +14 -0
  82. package/dist/server-fns/singletons/change-status.js +7 -0
  83. package/dist/server-fns/singletons/confirm-scheduled-publish.d.ts +14 -0
  84. package/dist/server-fns/singletons/confirm-scheduled-publish.js +9 -0
  85. package/dist/server-fns/singletons/copy-to-locale.d.ts +18 -0
  86. package/dist/server-fns/singletons/copy-to-locale.js +11 -0
  87. package/dist/server-fns/singletons/find-by-version.d.ts +16 -0
  88. package/dist/server-fns/singletons/find-by-version.js +9 -0
  89. package/dist/server-fns/singletons/get-scheduled-publish.d.ts +12 -0
  90. package/dist/server-fns/singletons/get-scheduled-publish.js +7 -0
  91. package/dist/server-fns/singletons/get.d.ts +24 -0
  92. package/dist/server-fns/singletons/get.js +6 -0
  93. package/dist/server-fns/singletons/history.d.ts +31 -0
  94. package/dist/server-fns/singletons/history.js +22 -0
  95. package/dist/server-fns/singletons/index.d.ts +19 -0
  96. package/dist/server-fns/singletons/index.js +12 -0
  97. package/dist/server-fns/singletons/restore-version.d.ts +14 -0
  98. package/dist/server-fns/singletons/restore-version.js +7 -0
  99. package/dist/server-fns/singletons/schedule-publish.d.ts +16 -0
  100. package/dist/server-fns/singletons/schedule-publish.js +10 -0
  101. package/dist/server-fns/singletons/unpublish.d.ts +12 -0
  102. package/dist/server-fns/singletons/unpublish.js +7 -0
  103. package/dist/server-fns/singletons/update.d.ts +14 -0
  104. package/dist/server-fns/singletons/update.js +14 -0
  105. package/dist/vite/analytics-dev.d.ts +22 -0
  106. package/dist/vite/analytics-dev.js +28 -0
  107. package/dist/vite/index.d.ts +1 -0
  108. package/dist/vite/index.js +1 -0
  109. package/dist/vitest-jsdom.test.d.ts +8 -0
  110. package/package.json +28 -16
  111. package/src/admin-shell/chrome/admin-menu-drawer.tsx +19 -5
  112. package/src/admin-shell/chrome/dashboard.test.tsx +199 -0
  113. package/src/admin-shell/chrome/dashboard.tsx +43 -9
  114. package/src/admin-shell/collections/api.tsx +2 -2
  115. package/src/admin-shell/collections/create.tsx +6 -2
  116. package/src/admin-shell/collections/edit.tsx +6 -2
  117. package/src/admin-shell/collections/history.module.css +1 -1
  118. package/src/admin-shell/collections/history.tsx +162 -442
  119. package/src/admin-shell/collections/reindex-button.tsx +4 -2
  120. package/src/admin-shell/collections/restore-version-modal.tsx +19 -25
  121. package/src/admin-shell/collections/version-history.tsx +349 -0
  122. package/src/admin-shell/singletons/history.test.tsx +407 -0
  123. package/src/admin-shell/singletons/history.tsx +185 -0
  124. package/src/admin-shell/singletons/preview-link.tsx +75 -0
  125. package/src/admin-shell/singletons/view-menu.tsx +136 -0
  126. package/src/admin-shell/singletons/view.test.tsx +400 -0
  127. package/src/admin-shell/singletons/view.tsx +351 -0
  128. package/src/integrations/analytics-agent.tsx +91 -0
  129. package/src/integrations/analytics-events.test.node.ts +245 -0
  130. package/src/integrations/analytics-events.ts +224 -0
  131. package/src/integrations/api-utils.ts +34 -9
  132. package/src/integrations/serve-analytics-agent.test.node.ts +20 -0
  133. package/src/integrations/serve-analytics-agent.ts +19 -0
  134. package/src/routes/analytics-range.ts +55 -0
  135. package/src/routes/create-admin-analytics-route.test.node.ts +46 -0
  136. package/src/routes/create-admin-analytics-route.tsx +109 -0
  137. package/src/routes/create-admin-dashboard-route.test.node.ts +70 -0
  138. package/src/routes/create-admin-dashboard-route.tsx +10 -2
  139. package/src/routes/create-admin-layout-route.tsx +15 -8
  140. package/src/routes/create-collection-api-route.tsx +4 -4
  141. package/src/routes/create-collection-create-route.tsx +5 -8
  142. package/src/routes/create-collection-edit-route.tsx +5 -4
  143. package/src/routes/create-collection-history-route.tsx +5 -8
  144. package/src/routes/create-collection-list-route.tsx +5 -8
  145. package/src/routes/create-singleton-history-route.test.node.ts +148 -0
  146. package/src/routes/create-singleton-history-route.tsx +116 -0
  147. package/src/routes/create-singleton-route.test.node.ts +172 -0
  148. package/src/routes/create-singleton-route.tsx +176 -0
  149. package/src/routes/get-multi-collection-definition.ts +16 -0
  150. package/src/routes/get-singleton-definition.ts +16 -0
  151. package/src/routes/index.ts +3 -0
  152. package/src/server-fns/actors.ts +43 -0
  153. package/src/server-fns/admin-document-presentation.ts +78 -0
  154. package/src/server-fns/analytics/index.ts +23 -0
  155. package/src/server-fns/analytics/maintenance.ts +54 -0
  156. package/src/server-fns/analytics/queries.ts +86 -0
  157. package/src/server-fns/collections/actors.ts +1 -52
  158. package/src/server-fns/collections/get.ts +10 -49
  159. package/src/server-fns/collections/reorder.ts +1 -1
  160. package/src/server-fns/collections/scheduled-publication.ts +7 -1
  161. package/src/server-fns/collections/upload-singleton.test.node.ts +164 -0
  162. package/src/server-fns/collections/upload.ts +7 -3
  163. package/src/server-fns/collections/utils.ts +1 -9
  164. package/src/server-fns/serialise.ts +17 -0
  165. package/src/server-fns/singleton-document-read.ts +32 -0
  166. package/src/server-fns/singletons/cancel-scheduled-publish.ts +19 -0
  167. package/src/server-fns/singletons/change-status.ts +19 -0
  168. package/src/server-fns/singletons/confirm-scheduled-publish.ts +23 -0
  169. package/src/server-fns/singletons/copy-to-locale.ts +32 -0
  170. package/src/server-fns/singletons/find-by-version.ts +23 -0
  171. package/src/server-fns/singletons/get-scheduled-publish.ts +19 -0
  172. package/src/server-fns/singletons/get.ts +32 -0
  173. package/src/server-fns/singletons/history.ts +41 -0
  174. package/src/server-fns/singletons/index.ts +20 -0
  175. package/src/server-fns/singletons/restore-version.ts +19 -0
  176. package/src/server-fns/singletons/schedule-publish.ts +24 -0
  177. package/src/server-fns/singletons/singletons.test.node.ts +298 -0
  178. package/src/server-fns/singletons/unpublish.ts +19 -0
  179. package/src/server-fns/singletons/update.ts +31 -0
  180. package/src/vite/analytics-dev.test.node.ts +126 -0
  181. package/src/vite/analytics-dev.ts +56 -0
  182. package/src/vite/index.ts +1 -0
  183. package/src/vitest-jsdom.test.tsx +27 -0
@@ -10,8 +10,8 @@
10
10
  * of our API and used only for development.
11
11
  * We'll extract a properly configured API server soon.
12
12
  */
13
- import type { CollectionDefinition } from '@byline/core';
14
- export interface EnsuredCollection {
13
+ import type { CollectionDefinition, MultiCollectionDefinition } from '@byline/core';
14
+ export interface EnsuredDocumentResource {
15
15
  definition: CollectionDefinition;
16
16
  collection: {
17
17
  id: string;
@@ -20,14 +20,28 @@ export interface EnsuredCollection {
20
20
  schemaHash: string;
21
21
  };
22
22
  }
23
+ export interface EnsuredCollection extends EnsuredDocumentResource {
24
+ definition: MultiCollectionDefinition;
25
+ }
23
26
  /**
24
- * Resolve a collection for an admin API request.
27
+ * Resolve either registered document-resource kind against the reconciled
28
+ * collection record.
25
29
  *
26
30
  * Collections are reconciled with the database once at startup by
27
31
  * `initBylineCore()` (see `packages/core/src/services/collection-bootstrap.ts`).
28
32
  * This helper is a per-request cache lookup against the resulting in-memory
29
33
  * registry — no DB I/O, no hash work.
30
34
  *
31
- * Returns `null` when the path is not registered in the client/server config.
35
+ * This broader seam is reserved for operations such as field upload whose core
36
+ * service is explicitly kind-aware; collection route families continue to use
37
+ * `ensureCollection` below.
38
+ */
39
+ export declare function ensureDocumentResource(path: string): Promise<EnsuredDocumentResource | null>;
40
+ /**
41
+ * Narrow the shared document-resource resolution to a multi-document
42
+ * collection for a collection-scoped admin API request.
43
+ *
44
+ * Returns `null` when the path is unregistered or belongs to a singleton, so
45
+ * collection route families cannot accidentally admit the other resource kind.
32
46
  */
33
47
  export declare function ensureCollection(path: string): Promise<EnsuredCollection | null>;
@@ -1,6 +1,6 @@
1
- import { getCollectionDefinition } from "@byline/core";
1
+ import { getCollectionDefinition, isSingleton } from "@byline/core";
2
2
  import { bylineCore } from "./byline-core.js";
3
- async function ensureCollection(path) {
3
+ async function ensureDocumentResource(path) {
4
4
  const definition = getCollectionDefinition(path);
5
5
  if (null == definition) return null;
6
6
  let record;
@@ -19,4 +19,11 @@ async function ensureCollection(path) {
19
19
  }
20
20
  };
21
21
  }
22
- export { ensureCollection };
22
+ async function ensureCollection(path) {
23
+ const resource = await ensureDocumentResource(path);
24
+ return null == resource || isSingleton(resource.definition) ? null : {
25
+ ...resource,
26
+ definition: resource.definition
27
+ };
28
+ }
29
+ export { ensureCollection, ensureDocumentResource };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * This Source Code is subject to the terms of the Mozilla Public
3
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
+ *
6
+ * Copyright (c) Infonomic Company Limited
7
+ */
8
+ export declare function serveAnalyticsAgent(): Response;
@@ -0,0 +1,11 @@
1
+ import { ANALYTICS_AGENT_SOURCE } from "@byline/analytics-agent/source";
2
+ function serveAnalyticsAgent() {
3
+ return new Response(ANALYTICS_AGENT_SOURCE, {
4
+ headers: {
5
+ 'cache-control': 'public, max-age=3600, must-revalidate',
6
+ 'content-type': "text/javascript; charset=utf-8",
7
+ 'x-content-type-options': 'nosniff'
8
+ }
9
+ });
10
+ }
11
+ export { serveAnalyticsAgent };
@@ -0,0 +1,12 @@
1
+ /**
2
+ * This Source Code is subject to the terms of the Mozilla Public
3
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
+ *
6
+ * Copyright (c) Infonomic Company Limited
7
+ */
8
+ import type { AnalyticsDashboardPeriod } from '@byline/admin/analytics';
9
+ export declare function buildAnalyticsDashboardRange(period: AnalyticsDashboardPeriod, now?: Date, earliestReportDay?: string | null): {
10
+ from: string;
11
+ to: string;
12
+ };
@@ -0,0 +1,35 @@
1
+ const UTC_DAY_PATTERN = /^\d{4}-\d{2}-\d{2}$/u;
2
+ function buildAnalyticsDashboardRange(period, now = new Date(), earliestReportDay = null) {
3
+ const to = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()));
4
+ if ('ytd' === period) return {
5
+ from: formatUtcDay(new Date(Date.UTC(to.getUTCFullYear(), 0, 1))),
6
+ to: formatUtcDay(to)
7
+ };
8
+ if ('all' === period) {
9
+ const toDay = formatUtcDay(to);
10
+ const earliest = null == earliestReportDay ? toDay : assertUtcDay(earliestReportDay);
11
+ return {
12
+ from: earliest <= toDay ? earliest : toDay,
13
+ to: toDay
14
+ };
15
+ }
16
+ const from = new Date(to);
17
+ from.setUTCDate(from.getUTCDate() - (period - 1));
18
+ return {
19
+ from: formatUtcDay(from),
20
+ to: formatUtcDay(to)
21
+ };
22
+ }
23
+ function formatUtcDay(value) {
24
+ const year = value.getUTCFullYear().toString().padStart(4, '0');
25
+ const month = (value.getUTCMonth() + 1).toString().padStart(2, '0');
26
+ const day = value.getUTCDate().toString().padStart(2, '0');
27
+ return `${year}-${month}-${day}`;
28
+ }
29
+ function assertUtcDay(value) {
30
+ if (!UTC_DAY_PATTERN.test(value)) throw new Error('analytics report day must use YYYY-MM-DD');
31
+ const date = new Date(`${value}T00:00:00.000Z`);
32
+ if (!Number.isFinite(date.valueOf()) || formatUtcDay(date) !== value) throw new Error('analytics report day must be a real UTC calendar day');
33
+ return value;
34
+ }
35
+ export { buildAnalyticsDashboardRange };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * This Source Code is subject to the terms of the Mozilla Public
3
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
+ *
6
+ * Copyright (c) Infonomic Company Limited
7
+ */
8
+ export declare function createAdminAnalyticsRoute(path: string): any;
@@ -0,0 +1,108 @@
1
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
+ import { createFileRoute, notFound } from "@tanstack/react-router";
3
+ import { AnalyticsDashboard } from "@byline/admin/analytics/components/dashboard";
4
+ import { isAnalyticsDashboardPeriod } from "@byline/analytics/config";
5
+ import { useTranslation } from "@byline/i18n/react";
6
+ import { z } from "zod";
7
+ import { BreadcrumbsClient } from "../admin-shell/chrome/breadcrumbs/breadcrumbs-client.js";
8
+ import { useNavigate } from "../admin-shell/chrome/loose-router.js";
9
+ import { getAnalyticsCountries, getAnalyticsReferrers, getAnalyticsReportCoverage, getAnalyticsRuntime, getAnalyticsSummary, getAnalyticsTop } from "../server-fns/analytics/index.js";
10
+ import { getAdminRoutePath } from "./admin-path.js";
11
+ import { buildAnalyticsDashboardRange } from "./analytics-range.js";
12
+ const periodSchema = z.preprocess((value)=>{
13
+ if (null == value) return;
14
+ if ('ytd' === value || 'all' === value) return value;
15
+ return Number(value);
16
+ }, z.custom((value)=>isAnalyticsDashboardPeriod(value)).optional());
17
+ const searchSchema = z.object({
18
+ period: periodSchema.catch(void 0)
19
+ });
20
+ function createAdminAnalyticsRoute(path) {
21
+ const Route = createFileRoute(path)({
22
+ validateSearch: searchSchema,
23
+ loaderDeps: ({ search })=>({
24
+ period: search.period ?? 30
25
+ }),
26
+ loader: async ({ deps })=>{
27
+ const runtime = await getAnalyticsRuntime();
28
+ if (!runtime.enabled) throw notFound();
29
+ const coverage = await getAnalyticsReportCoverage();
30
+ const range = buildAnalyticsDashboardRange(deps.period, new Date(), coverage.summaryFrom);
31
+ const [summary, pages, downloads, referrers, countries] = await Promise.all([
32
+ getAnalyticsSummary({
33
+ data: range
34
+ }),
35
+ getAnalyticsTop({
36
+ data: {
37
+ ...range,
38
+ kind: 'page',
39
+ limit: 20
40
+ }
41
+ }),
42
+ getAnalyticsTop({
43
+ data: {
44
+ ...range,
45
+ kind: 'download',
46
+ limit: 20
47
+ }
48
+ }),
49
+ getAnalyticsReferrers({
50
+ data: {
51
+ ...range,
52
+ limit: 20
53
+ }
54
+ }),
55
+ getAnalyticsCountries({
56
+ data: range
57
+ })
58
+ ]);
59
+ return {
60
+ data: {
61
+ summary,
62
+ pages,
63
+ downloads,
64
+ referrers,
65
+ countries,
66
+ range,
67
+ coverage
68
+ },
69
+ period: deps.period
70
+ };
71
+ },
72
+ component: function() {
73
+ const { data, period } = Route.useLoaderData();
74
+ const navigate = useNavigate();
75
+ const { t } = useTranslation('byline-admin');
76
+ return /*#__PURE__*/ jsxs(Fragment, {
77
+ children: [
78
+ /*#__PURE__*/ jsx(BreadcrumbsClient, {
79
+ breadcrumbs: [
80
+ {
81
+ label: t('chrome.menu.dashboard'),
82
+ href: getAdminRoutePath()
83
+ },
84
+ {
85
+ label: t('analytics.title'),
86
+ href: getAdminRoutePath('analytics')
87
+ }
88
+ ]
89
+ }),
90
+ /*#__PURE__*/ jsx(AnalyticsDashboard, {
91
+ data: data,
92
+ period: period,
93
+ onPeriodChange: (nextPeriod)=>{
94
+ navigate({
95
+ to: getAdminRoutePath('analytics'),
96
+ search: {
97
+ period: nextPeriod
98
+ }
99
+ });
100
+ }
101
+ })
102
+ ]
103
+ });
104
+ }
105
+ });
106
+ return Route;
107
+ }
108
+ export { createAdminAnalyticsRoute };
@@ -1,6 +1,6 @@
1
1
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
2
  import { createFileRoute } from "@tanstack/react-router";
3
- import { filterReadableCollections, getAdminConfig } from "@byline/core";
3
+ import { filterReadableCollections, getAdminConfig, isSingleton } from "@byline/core";
4
4
  import { useTranslation } from "@byline/i18n/react";
5
5
  import { BreadcrumbsClient } from "../admin-shell/chrome/breadcrumbs/breadcrumbs-client.js";
6
6
  import { AdminDashboard } from "../admin-shell/chrome/dashboard.js";
@@ -15,7 +15,7 @@ function createAdminDashboardRoute(path) {
15
15
  abilities: context.user.abilities
16
16
  });
17
17
  const statsMap = {};
18
- await Promise.all(visible.filter((c)=>true === c.showStats).map(async (c)=>{
18
+ await Promise.all(visible.filter((resource)=>!isSingleton(resource) && true === resource.showStats).map(async (c)=>{
19
19
  try {
20
20
  statsMap[c.path] = await getCollectionStats(c.path);
21
21
  } catch {
@@ -18,6 +18,7 @@ import { buildLocaleDefinitions } from "../i18n/locale-definitions.js";
18
18
  import { bylineAdminServices } from "../integrations/byline-admin-services.js";
19
19
  import { BylineAiAdminProvider } from "../integrations/byline-ai.js";
20
20
  import { bylineFieldServices } from "../integrations/byline-field-services.js";
21
+ import { getAnalyticsRuntime } from "../server-fns/analytics/index.js";
21
22
  import { getCurrentAdminUser } from "../server-fns/auth/index.js";
22
23
  import { getScheduledPublicationRuntime } from "../server-fns/collections/index.js";
23
24
  import { getActiveLocaleFn, setAdminLocaleFn } from "../server-fns/i18n/index.js";
@@ -28,12 +29,16 @@ function createAdminLayoutRoute(path) {
28
29
  const signInPath = getSignInRoutePath();
29
30
  try {
30
31
  const user = await getCurrentAdminUser();
31
- const activeLocale = await getActiveLocaleFn();
32
- const scheduledPublicationRuntime = await getScheduledPublicationRuntime();
32
+ const [activeLocale, scheduledPublicationRuntime, analyticsRuntime] = await Promise.all([
33
+ getActiveLocaleFn(),
34
+ getScheduledPublicationRuntime(),
35
+ getAnalyticsRuntime()
36
+ ]);
33
37
  return {
34
38
  user,
35
39
  activeLocale,
36
- scheduledPublicationRuntime
40
+ scheduledPublicationRuntime,
41
+ analyticsRuntime
37
42
  };
38
43
  } catch {
39
44
  throw redirect({
@@ -45,7 +50,7 @@ function createAdminLayoutRoute(path) {
45
50
  }
46
51
  },
47
52
  component: function() {
48
- const { user, activeLocale, scheduledPublicationRuntime } = Route.useRouteContext();
53
+ const { user, activeLocale, scheduledPublicationRuntime, analyticsRuntime } = Route.useRouteContext();
49
54
  const { i18n } = getAdminConfig();
50
55
  const localeDefinitions = buildLocaleDefinitions(i18n.admin.locales, i18n.admin.localeDefinitions);
51
56
  useEffect(()=>{
@@ -80,6 +85,7 @@ function createAdminLayoutRoute(path) {
80
85
  className: clsx('byline-admin-layout-main', admin_layout_module.main),
81
86
  children: [
82
87
  /*#__PURE__*/ jsx(AdminMenuDrawer, {
88
+ analyticsEnabled: analyticsRuntime.enabled,
83
89
  scheduledPublicationEnabled: scheduledPublicationRuntime.enabled
84
90
  }),
85
91
  /*#__PURE__*/ jsx(Content, {
@@ -1,6 +1,5 @@
1
1
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
2
  import { createFileRoute, notFound } from "@tanstack/react-router";
3
- import { getCollectionDefinition } from "@byline/core";
4
3
  import { useTranslation } from "@byline/i18n/react";
5
4
  import { z } from "zod";
6
5
  import { BreadcrumbsClient } from "../admin-shell/chrome/breadcrumbs/breadcrumbs-client.js";
@@ -8,6 +7,7 @@ import { ApiView } from "../admin-shell/collections/api.js";
8
7
  import { getCollectionDocument } from "../server-fns/collections/index.js";
9
8
  import { getAdminRoutePath } from "./admin-path.js";
10
9
  import { getContentLocaleRouteConfig } from "./get-content-locale-route-config.js";
10
+ import { getMultiCollectionDefinition } from "./get-multi-collection-definition.js";
11
11
  const searchSchema = z.object({
12
12
  locale: z.string().optional(),
13
13
  depth: z.coerce.number().int().min(0).max(3).optional()
@@ -20,7 +20,7 @@ function createCollectionApiRoute(path) {
20
20
  depth: search.depth
21
21
  }),
22
22
  loader: async ({ params, deps })=>{
23
- const collectionDef = getCollectionDefinition(params.collection);
23
+ const collectionDef = getMultiCollectionDefinition(params.collection);
24
24
  if (!collectionDef) throw notFound();
25
25
  const { defaultContentLocale } = getContentLocaleRouteConfig();
26
26
  const resolvedLocale = deps.locale ?? defaultContentLocale;
@@ -35,7 +35,7 @@ function createCollectionApiRoute(path) {
35
35
  const data = Route.useLoaderData();
36
36
  const { collection, id } = Route.useParams();
37
37
  const { locale, depth } = Route.useSearch();
38
- const collectionDef = getCollectionDefinition(collection);
38
+ const collectionDef = getMultiCollectionDefinition(collection);
39
39
  const { t } = useTranslation('byline-admin');
40
40
  const { contentLocales, defaultContentLocale } = getContentLocaleRouteConfig();
41
41
  return /*#__PURE__*/ jsxs(Fragment, {
@@ -1,11 +1,12 @@
1
1
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
2
  import { createFileRoute, notFound } from "@tanstack/react-router";
3
- import { buildInitialDataFromFields, getCollectionAdminConfig, getCollectionDefinition } from "@byline/core";
3
+ import { buildInitialDataFromFields, getCollectionAdminConfig } from "@byline/core";
4
4
  import { useTranslation } from "@byline/i18n/react";
5
5
  import { z } from "zod";
6
6
  import { BreadcrumbsClient } from "../admin-shell/chrome/breadcrumbs/breadcrumbs-client.js";
7
7
  import { CreateView } from "../admin-shell/collections/create.js";
8
8
  import { getAdminRoutePath } from "./admin-path.js";
9
+ import { getMultiCollectionDefinition } from "./get-multi-collection-definition.js";
9
10
  const searchSchema = z.object({
10
11
  from: z.string().optional()
11
12
  });
@@ -13,7 +14,7 @@ function createCollectionCreateRoute(path) {
13
14
  const Route = createFileRoute(path)({
14
15
  validateSearch: searchSchema,
15
16
  loader: async ({ params })=>{
16
- const collectionDef = getCollectionDefinition(params.collection);
17
+ const collectionDef = getMultiCollectionDefinition(params.collection);
17
18
  if (!collectionDef) throw notFound();
18
19
  const initialData = await buildInitialDataFromFields(collectionDef.fields, {
19
20
  data: {},
@@ -26,7 +27,7 @@ function createCollectionCreateRoute(path) {
26
27
  component: function() {
27
28
  const { collection } = Route.useParams();
28
29
  const { initialData } = Route.useLoaderData();
29
- const collectionDef = getCollectionDefinition(collection);
30
+ const collectionDef = getMultiCollectionDefinition(collection);
30
31
  const adminConfig = getCollectionAdminConfig(collection);
31
32
  const { t } = useTranslation('byline-admin');
32
33
  const search = Route.useSearch();
@@ -1,7 +1,7 @@
1
1
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
2
  import { useEffect, useRef, useState } from "react";
3
3
  import { createFileRoute, notFound } from "@tanstack/react-router";
4
- import { getCollectionAdminConfig, getCollectionDefinition } from "@byline/core";
4
+ import { getCollectionAdminConfig } from "@byline/core";
5
5
  import { useTranslation } from "@byline/i18n/react";
6
6
  import { useToastManager } from "@byline/ui/react";
7
7
  import { z } from "zod";
@@ -11,6 +11,7 @@ import { EditView } from "../admin-shell/collections/edit.js";
11
11
  import { getCollectionDocument } from "../server-fns/collections/index.js";
12
12
  import { getAdminRoutePath } from "./admin-path.js";
13
13
  import { getContentLocaleRouteConfig } from "./get-content-locale-route-config.js";
14
+ import { getMultiCollectionDefinition } from "./get-multi-collection-definition.js";
14
15
  import { decodeListReturnState } from "./list-return-state.js";
15
16
  import { persistListReturnState, readListReturnState } from "./list-return-storage.js";
16
17
  const searchSchema = z.object({
@@ -27,7 +28,7 @@ function createCollectionEditRoute(path) {
27
28
  locale: search.locale
28
29
  }),
29
30
  loader: async ({ params, deps })=>{
30
- const collectionDef = getCollectionDefinition(params.collection);
31
+ const collectionDef = getMultiCollectionDefinition(params.collection);
31
32
  if (!collectionDef) throw notFound();
32
33
  const data = await getCollectionDocument(params.collection, params.id, deps.locale, void 0, true);
33
34
  if (!data) throw notFound();
@@ -41,7 +42,7 @@ function createCollectionEditRoute(path) {
41
42
  const { collection, id } = Route.useParams();
42
43
  const search = Route.useSearch();
43
44
  const { locale } = search;
44
- const collectionDef = getCollectionDefinition(collection);
45
+ const collectionDef = getMultiCollectionDefinition(collection);
45
46
  const adminConfig = getCollectionAdminConfig(collection);
46
47
  const { t } = useTranslation('byline-admin');
47
48
  const toastManager = useToastManager();
@@ -1,6 +1,6 @@
1
1
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
2
  import { createFileRoute, notFound } from "@tanstack/react-router";
3
- import { getCollectionAdminConfig, getCollectionDefinition, getWorkflowStatuses } from "@byline/core";
3
+ import { getCollectionAdminConfig, getWorkflowStatuses } from "@byline/core";
4
4
  import { useTranslation } from "@byline/i18n/react";
5
5
  import { z } from "zod";
6
6
  import { BreadcrumbsClient } from "../admin-shell/chrome/breadcrumbs/breadcrumbs-client.js";
@@ -8,6 +8,7 @@ import { HistoryView } from "../admin-shell/collections/history.js";
8
8
  import { getCollectionDocument, getCollectionDocumentAuditLog, getCollectionDocumentHistory } from "../server-fns/collections/index.js";
9
9
  import { getAdminRoutePath } from "./admin-path.js";
10
10
  import { getContentLocaleRouteConfig } from "./get-content-locale-route-config.js";
11
+ import { getMultiCollectionDefinition } from "./get-multi-collection-definition.js";
11
12
  const searchSchema = z.object({
12
13
  page: z.coerce.number().min(1).optional(),
13
14
  page_size: z.coerce.number().max(100).optional(),
@@ -31,7 +32,7 @@ function createCollectionHistoryRoute(path) {
31
32
  locale: search.locale
32
33
  }),
33
34
  loader: async ({ params, deps })=>{
34
- const collectionDef = getCollectionDefinition(params.collection);
35
+ const collectionDef = getMultiCollectionDefinition(params.collection);
35
36
  if (!collectionDef) throw notFound();
36
37
  const [history, currentDocument, auditLog] = await Promise.all([
37
38
  getCollectionDocumentHistory({
@@ -71,7 +72,7 @@ function createCollectionHistoryRoute(path) {
71
72
  component: function() {
72
73
  const { history, currentDocument, auditLog } = Route.useLoaderData();
73
74
  const { collection } = Route.useParams();
74
- const collectionDef = getCollectionDefinition(collection);
75
+ const collectionDef = getMultiCollectionDefinition(collection);
75
76
  const adminConfig = getCollectionAdminConfig(collection);
76
77
  const { t } = useTranslation('byline-admin');
77
78
  const { contentLocales, defaultContentLocale } = getContentLocaleRouteConfig();
@@ -2,7 +2,7 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
2
  import { useEffect, useRef } from "react";
3
3
  import { createFileRoute, notFound } from "@tanstack/react-router";
4
4
  import { applyRelationColumnFormatters } from "@byline/admin/react";
5
- import { getCollectionAdminConfig, getCollectionDefinition, getWorkflowStatuses } from "@byline/core";
5
+ import { getCollectionAdminConfig, getWorkflowStatuses } from "@byline/core";
6
6
  import { useTranslation } from "@byline/i18n/react";
7
7
  import { useToastManager } from "@byline/ui/react";
8
8
  import { BreadcrumbsClient } from "../admin-shell/chrome/breadcrumbs/breadcrumbs-client.js";
@@ -11,6 +11,7 @@ import { ListView } from "../admin-shell/collections/list.js";
11
11
  import { TreeListView } from "../admin-shell/collections/tree-list.js";
12
12
  import { getCollectionDocuments, getCollectionTree, placeTreeNode, reorderCollectionDocument } from "../server-fns/collections/index.js";
13
13
  import { getAdminRoutePath } from "./admin-path.js";
14
+ import { getMultiCollectionDefinition } from "./get-multi-collection-definition.js";
14
15
  import { collectionListSearchSchema } from "./list-return-state.js";
15
16
  function createCollectionListRoute(path) {
16
17
  const Route = createFileRoute(path)({
@@ -25,7 +26,7 @@ function createCollectionListRoute(path) {
25
26
  status: search.status
26
27
  }),
27
28
  loader: async ({ params, deps })=>{
28
- const collectionDef = getCollectionDefinition(params.collection);
29
+ const collectionDef = getMultiCollectionDefinition(params.collection);
29
30
  if (!collectionDef) throw notFound();
30
31
  if (true === collectionDef.tree) return await getCollectionTree({
31
32
  data: {
@@ -59,7 +60,7 @@ function createCollectionListRoute(path) {
59
60
  const { collection } = Route.useParams();
60
61
  const search = Route.useSearch();
61
62
  const navigate = useNavigate();
62
- const collectionDef = getCollectionDefinition(collection);
63
+ const collectionDef = getMultiCollectionDefinition(collection);
63
64
  const adminConfig = getCollectionAdminConfig(collection);
64
65
  const columns = applyRelationColumnFormatters(adminConfig?.columns || [], collectionDef);
65
66
  const workflowStatuses = getWorkflowStatuses(collectionDef);
@@ -0,0 +1,8 @@
1
+ /**
2
+ * This Source Code is subject to the terms of the Mozilla Public
3
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
+ *
6
+ * Copyright (c) Infonomic Company Limited
7
+ */
8
+ export declare function createSingletonHistoryRoute(path: string): any;
@@ -0,0 +1,99 @@
1
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
+ import { createFileRoute, notFound } from "@tanstack/react-router";
3
+ import { getSingletonAdminConfig, getWorkflowStatuses } from "@byline/core";
4
+ import { useTranslation } from "@byline/i18n/react";
5
+ import { z } from "zod";
6
+ import { BreadcrumbsClient } from "../admin-shell/chrome/breadcrumbs/breadcrumbs-client.js";
7
+ import { SingletonHistoryView } from "../admin-shell/singletons/history.js";
8
+ import { getSingleton, getSingletonHistory } from "../server-fns/singletons/index.js";
9
+ import { getAdminRoutePath } from "./admin-path.js";
10
+ import { getContentLocaleRouteConfig } from "./get-content-locale-route-config.js";
11
+ import { getSingletonDefinition } from "./get-singleton-definition.js";
12
+ const searchSchema = z.object({
13
+ page: z.coerce.number().min(1).optional(),
14
+ page_size: z.coerce.number().max(100).optional(),
15
+ order: z.string().optional(),
16
+ desc: z.coerce.boolean().optional(),
17
+ locale: z.string().optional()
18
+ });
19
+ function createSingletonHistoryRoute(path) {
20
+ const Route = createFileRoute(path)({
21
+ validateSearch: searchSchema,
22
+ loaderDeps: ({ search })=>({
23
+ page: search.page,
24
+ page_size: search.page_size,
25
+ order: search.order,
26
+ desc: search.desc,
27
+ locale: search.locale
28
+ }),
29
+ loader: async ({ params, deps })=>{
30
+ if (null == getSingletonDefinition(params.singleton)) throw notFound();
31
+ const [history, currentDocument] = await Promise.all([
32
+ getSingletonHistory({
33
+ data: {
34
+ singleton: params.singleton,
35
+ params: {
36
+ page: deps.page,
37
+ page_size: deps.page_size,
38
+ order: deps.order,
39
+ desc: deps.desc,
40
+ locale: deps.locale
41
+ }
42
+ }
43
+ }),
44
+ getSingleton({
45
+ data: {
46
+ singleton: params.singleton,
47
+ locale: deps.locale ?? 'all'
48
+ }
49
+ })
50
+ ]);
51
+ return {
52
+ history,
53
+ currentDocument
54
+ };
55
+ },
56
+ staleTime: 0,
57
+ gcTime: 0,
58
+ shouldReload: true,
59
+ component: function() {
60
+ const { history, currentDocument } = Route.useLoaderData();
61
+ const { singleton } = Route.useParams();
62
+ const definition = getSingletonDefinition(singleton);
63
+ if (null == definition) throw notFound();
64
+ const { t } = useTranslation('byline-admin');
65
+ const { contentLocales, defaultContentLocale } = getContentLocaleRouteConfig();
66
+ return /*#__PURE__*/ jsxs(Fragment, {
67
+ children: [
68
+ /*#__PURE__*/ jsx(BreadcrumbsClient, {
69
+ breadcrumbs: [
70
+ {
71
+ label: t('chrome.menu.dashboard'),
72
+ href: getAdminRoutePath()
73
+ },
74
+ {
75
+ label: definition.label,
76
+ href: getAdminRoutePath('singletons', singleton)
77
+ },
78
+ {
79
+ label: t('collections.breadcrumbs.history'),
80
+ href: getAdminRoutePath('singletons', singleton, 'history')
81
+ }
82
+ ]
83
+ }),
84
+ /*#__PURE__*/ jsx(SingletonHistoryView, {
85
+ singletonDefinition: definition,
86
+ adminConfig: getSingletonAdminConfig(singleton) ?? void 0,
87
+ data: history,
88
+ currentDocument: currentDocument,
89
+ contentLocales: contentLocales,
90
+ defaultContentLocale: defaultContentLocale,
91
+ workflowStatuses: getWorkflowStatuses(definition)
92
+ })
93
+ ]
94
+ });
95
+ }
96
+ });
97
+ return Route;
98
+ }
99
+ export { createSingletonHistoryRoute };
@@ -0,0 +1,35 @@
1
+ /**
2
+ * This Source Code is subject to the terms of the Mozilla Public
3
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
+ *
6
+ * Copyright (c) Infonomic Company Limited
7
+ */
8
+ import type { DocumentPublishScheduleInfo } from '@byline/client';
9
+ /**
10
+ * Load the mapped singleton document and attach the admin-only lifecycle
11
+ * metadata consumed by the editor. Keeping this composition in the route
12
+ * layer leaves ordinary singleton reads free of publication timing and actor
13
+ * capability details.
14
+ */
15
+ export declare const getSingletonRouteDocument: import("@tanstack/react-start").RequiredFetcher<undefined, (input: {
16
+ singleton: string;
17
+ locale?: string;
18
+ }) => {
19
+ singleton: string;
20
+ locale?: string;
21
+ }, Promise<{
22
+ document: null;
23
+ initialData: Record<string, any>;
24
+ } | {
25
+ document: {
26
+ _publishedVersion: Record<string, any> | null;
27
+ _scheduledPublicationEnabled: boolean;
28
+ _canSchedulePublication: boolean;
29
+ _scheduledPublish: DocumentPublishScheduleInfo | null;
30
+ scheduledPublishAt?: Date | undefined;
31
+ scheduledPublishVersionId?: string | undefined;
32
+ };
33
+ initialData: undefined;
34
+ } | null>>;
35
+ export declare function createSingletonRoute(path: string): any;