alinea 2.0.0-preview.7 → 2.0.0-preview.8

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 (283) hide show
  1. package/dist/.init/content/pages/welcome.json +1 -1
  2. package/dist/LICENSES.md +120 -120
  3. package/dist/adapter/next/cms.d.ts +18 -4
  4. package/dist/adapter/next/cms.js +125 -36
  5. package/dist/adapter/next/handler.d.ts +5 -1
  6. package/dist/adapter/next/handler.js +14 -7
  7. package/dist/adapter/next/node.d.ts +5 -0
  8. package/dist/adapter/next/node.js +16 -0
  9. package/dist/adapter/next/previews.d.ts +4 -1
  10. package/dist/adapter/next/previews.js +13 -1
  11. package/dist/adapter/next/renderStats.d.ts +24 -0
  12. package/dist/adapter/next/renderStats.js +74 -0
  13. package/dist/adapter/next/syncCheck.d.ts +8 -2
  14. package/dist/adapter/next/syncCheck.js +3 -3
  15. package/dist/adapter/next/with-alinea.js +0 -18
  16. package/dist/backend/Handler.d.ts +2 -2
  17. package/dist/backend/Handler.js +33 -12
  18. package/dist/backend/api/CreateBackend.js +15 -3
  19. package/dist/backend/api/DatabaseApi.js +22 -135
  20. package/dist/backend/api/database.js +15 -3
  21. package/dist/backend/resolver/ParsePreview.d.ts +2 -2
  22. package/dist/backend/router/NodeHandler.js +2 -0
  23. package/dist/backend/store/GeneratedDatabase.d.ts +5 -0
  24. package/dist/backend/store/GeneratedDatabase.js +31 -0
  25. package/dist/backend/store/GeneratedDatabaseNode.d.ts +4 -0
  26. package/dist/backend/store/GeneratedDatabaseNode.js +35 -0
  27. package/dist/backend/util/ORM.js +4 -2
  28. package/dist/bundled.d.ts +1470 -442
  29. package/dist/chunks/bun-sqlite-ZZDB7YQQ.js +18 -0
  30. package/dist/chunks/chunk-2BJ2IFQM.js +1085 -0
  31. package/dist/chunks/chunk-2PIFHEYR.js +364 -0
  32. package/dist/chunks/{chunk-X47OVDF3.js → chunk-2U43BB6P.js} +356 -1000
  33. package/dist/chunks/chunk-76VMZTLN.js +55 -0
  34. package/dist/chunks/chunk-A42DP5T7.js +94 -0
  35. package/dist/chunks/chunk-ATF42T2B.js +35 -0
  36. package/dist/chunks/{chunk-NWQXN4SB.js → chunk-ETBQTP2S.js} +40 -29
  37. package/dist/chunks/chunk-IL7FJQAY.js +94 -0
  38. package/dist/chunks/chunk-K62JP6HR.js +22 -0
  39. package/dist/chunks/chunk-K7LHQXI4.js +103 -0
  40. package/dist/chunks/chunk-M7KDJEGH.js +495 -0
  41. package/dist/chunks/chunk-N47Y62CI.js +396 -0
  42. package/dist/chunks/chunk-NLZLRQ5U.js +100 -0
  43. package/dist/chunks/chunk-QBPYWU6C.js +24 -0
  44. package/dist/chunks/{chunk-6P4UVRPH.js → chunk-RWWYUNVX.js} +2 -1
  45. package/dist/chunks/chunk-TFMUSWGG.js +605 -0
  46. package/dist/chunks/{chunk-I4GC3E65.js → chunk-UPY2RUZF.js} +0 -1
  47. package/dist/chunks/chunk-XCZXR3C2.js +112 -0
  48. package/dist/chunks/chunk-XTWYBWP2.js +81 -0
  49. package/dist/chunks/node-sqlite-7CSGL27V.js +18 -0
  50. package/dist/cli/Generate.js +74 -64
  51. package/dist/cli/Serve.js +1 -1
  52. package/dist/cli/bin.js +2 -1
  53. package/dist/cli/generate/CopyStaticFiles.js +17 -14
  54. package/dist/cli/generate/DevDB.d.ts +22 -5
  55. package/dist/cli/generate/DevDB.js +136 -24
  56. package/dist/cli/serve/CreateLocalServer.js +22 -4
  57. package/dist/cli/serve/LiveReload.d.ts +1 -1
  58. package/dist/cli/serve/LiveReload.js +3 -0
  59. package/dist/cloud/CloudRemote.js +2 -1
  60. package/dist/components/Calendar.js +6 -6
  61. package/dist/components/Checkbox.js +3 -3
  62. package/dist/components/ColorSwatchPicker.js +2 -2
  63. package/dist/components/ComboBox.js +9 -9
  64. package/dist/components/DateField.js +1 -1
  65. package/dist/components/DatePicker.js +6 -6
  66. package/dist/components/DateRangePicker.js +6 -6
  67. package/dist/components/Disclosure.js +9 -9
  68. package/dist/components/Label.js +5 -5
  69. package/dist/components/List.js +33 -33
  70. package/dist/components/Menu.js +3 -3
  71. package/dist/components/Modal.js +3 -3
  72. package/dist/components/MultipleSelect.js +25 -25
  73. package/dist/components/NumberField.js +6 -6
  74. package/dist/components/ProgressCircle.js +3 -3
  75. package/dist/components/RadioGroup.js +2 -2
  76. package/dist/components/SearchField.js +5 -5
  77. package/dist/components/Select.js +7 -7
  78. package/dist/components/Surface.js +2 -2
  79. package/dist/components/Table.js +6 -6
  80. package/dist/components/Tabs.js +2 -2
  81. package/dist/components/TextField.js +6 -6
  82. package/dist/components/Toggle.js +2 -2
  83. package/dist/components/Toolbar.js +2 -2
  84. package/dist/components/Tooltip.js +4 -4
  85. package/dist/components/Tree.d.ts +2 -1
  86. package/dist/components/Tree.js +5 -5
  87. package/dist/core/Document.js +15 -3
  88. package/dist/core/Entry.d.ts +3 -0
  89. package/dist/core/Entry.js +4 -0
  90. package/dist/core/EntrySeed.d.ts +19 -0
  91. package/dist/core/EntrySeed.js +136 -0
  92. package/dist/core/Field.d.ts +7 -0
  93. package/dist/core/Field.js +4 -0
  94. package/dist/core/Filter.d.ts +40 -2
  95. package/dist/core/Filter.js +145 -0
  96. package/dist/core/Graph.d.ts +9 -0
  97. package/dist/core/ListRow.d.ts +1 -0
  98. package/dist/core/ListRow.js +1 -0
  99. package/dist/core/Reference.d.ts +1 -0
  100. package/dist/core/Root.js +1 -1
  101. package/dist/core/Scope.d.ts +2 -0
  102. package/dist/core/Scope.js +16 -1
  103. package/dist/core/Type.d.ts +2 -1
  104. package/dist/core/Type.js +13 -1
  105. package/dist/core/db/EntryAliases.js +1 -11
  106. package/dist/core/db/EntryReference.d.ts +0 -6
  107. package/dist/core/db/IndexEvent.d.ts +2 -1
  108. package/dist/core/db/IndexEvent.js +11 -3
  109. package/dist/core/db/LinkResolver.d.ts +6 -6
  110. package/dist/core/db/LinkResolver.js +0 -52
  111. package/dist/core/db/LocalStore.d.ts +25 -0
  112. package/dist/core/field/ListField.js +19 -0
  113. package/dist/core/field/RecordField.js +8 -0
  114. package/dist/core/field/RichTextField.js +42 -0
  115. package/dist/core/field/UnionField.js +8 -0
  116. package/dist/core/source/FSSource.d.ts +14 -2
  117. package/dist/core/source/FSSource.js +58 -13
  118. package/dist/core/source/GitUtils.d.ts +4 -0
  119. package/dist/core/source/GitUtils.js +9 -10
  120. package/dist/core/source/GithubSource.js +22 -11
  121. package/dist/core/source/IndexedDBSource.d.ts +2 -1
  122. package/dist/core/source/IndexedDBSource.js +67 -53
  123. package/dist/core/source/MemorySource.js +5 -3
  124. package/dist/core/source/OverlaySource.d.ts +5 -2
  125. package/dist/core/source/OverlaySource.js +31 -3
  126. package/dist/core/source/Source.d.ts +3 -0
  127. package/dist/core/source/Source.js +15 -2
  128. package/dist/core/source/Tree.d.ts +10 -7
  129. package/dist/core/source/Tree.js +118 -70
  130. package/dist/core/source/Utils.js +6 -3
  131. package/dist/core/util/Arrays.d.ts +1 -0
  132. package/dist/core/util/Arrays.js +10 -0
  133. package/dist/core/util/Async.d.ts +7 -0
  134. package/dist/core/util/Async.js +15 -0
  135. package/dist/core/util/Checks.js +1 -1
  136. package/dist/core/util/EntryFilenames.d.ts +22 -1
  137. package/dist/core/util/EntryFilenames.js +56 -2
  138. package/dist/core/util/IndexedDB.d.ts +4 -0
  139. package/dist/core/util/IndexedDB.js +20 -0
  140. package/dist/core/util/Paths.js +5 -1
  141. package/dist/dashboard/App.js +3 -3
  142. package/dist/dashboard/ViewKeys.d.ts +1 -0
  143. package/dist/dashboard/ViewKeys.js +1 -0
  144. package/dist/dashboard/app/AccessDenied.js +4 -4
  145. package/dist/dashboard/app/ActivityStatus.js +11 -11
  146. package/dist/dashboard/app/AppShell.js +2 -2
  147. package/dist/dashboard/app/AuthView.js +9 -9
  148. package/dist/dashboard/app/Badge.js +2 -2
  149. package/dist/dashboard/app/CompactField.js +10 -10
  150. package/dist/dashboard/app/DashboardErrorBoundary.js +6 -6
  151. package/dist/dashboard/app/EntryFields.js +2 -2
  152. package/dist/dashboard/app/EntryHeader.js +10 -10
  153. package/dist/dashboard/app/EntryReferences.js +8 -8
  154. package/dist/dashboard/app/EntrySidebar.js +8 -8
  155. package/dist/dashboard/app/EntrySidebarPreview.js +11 -11
  156. package/dist/dashboard/app/EntryTranslationBanner.js +6 -6
  157. package/dist/dashboard/app/Explorer.js +44 -44
  158. package/dist/dashboard/app/ExplorerCards.js +30 -30
  159. package/dist/dashboard/app/ExplorerFileCard.js +17 -17
  160. package/dist/dashboard/app/ExplorerList.js +14 -14
  161. package/dist/dashboard/app/ExplorerModal.js +5 -5
  162. package/dist/dashboard/app/ExplorerTable.js +47 -47
  163. package/dist/dashboard/app/LinkPicker.js +2 -2
  164. package/dist/dashboard/app/LocaleMenu.js +6 -6
  165. package/dist/dashboard/app/SidebarTree.js +76 -40
  166. package/dist/dashboard/app/WorkspaceMenu.js +10 -10
  167. package/dist/dashboard/app/WorkspaceRoots.js +27 -27
  168. package/dist/dashboard/app/editor/FileEditor.js +24 -24
  169. package/dist/dashboard/app/editor/FilePreview.js +6 -6
  170. package/dist/dashboard/app/modals/CreateEntry.js +4 -4
  171. package/dist/dashboard/app/pages/EntryPage.js +15 -15
  172. package/dist/dashboard/app/pages/RootPage.js +3 -3
  173. package/dist/dashboard/app/pages/SplashPage.js +47 -47
  174. package/dist/dashboard/app/pages/UsersPage.js +36 -36
  175. package/dist/dashboard/app/ui/DashboardModal.js +17 -17
  176. package/dist/dashboard/app/ui/Rail.js +4 -4
  177. package/dist/dashboard/atoms/config.d.ts +4 -4
  178. package/dist/dashboard/atoms/entry.d.ts +8 -9
  179. package/dist/dashboard/atoms/entry.js +34 -4
  180. package/dist/dashboard/atoms/explorer.d.ts +2 -0
  181. package/dist/dashboard/atoms/explorer.js +7 -2
  182. package/dist/dashboard/boot/Boot.js +2 -3
  183. package/dist/dashboard/boot/DashboardWorker.d.ts +3 -3
  184. package/dist/dashboard/boot/DashboardWorker.js +78 -27
  185. package/dist/dashboard/boot/LoadWorker.js +2 -3
  186. package/dist/dashboard/icons.d.ts +2 -0
  187. package/dist/dashboard/icons.js +40 -0
  188. package/dist/dashboard/plugins/alineaFixturePlugin.js +14 -3
  189. package/dist/database/BrowserEntryStore.d.ts +30 -0
  190. package/dist/database/BrowserEntryStore.js +168 -0
  191. package/dist/database/DatabaseSource.d.ts +13 -0
  192. package/dist/database/DatabaseSource.js +25 -0
  193. package/dist/database/DatabaseTables.d.ts +38 -0
  194. package/dist/database/DatabaseTables.js +53 -0
  195. package/dist/database/EntryDatabase.d.ts +21 -0
  196. package/dist/database/EntryDatabase.js +138 -0
  197. package/dist/database/EntryLayer.d.ts +93 -0
  198. package/dist/database/EntryLayer.js +459 -0
  199. package/dist/database/EntryStore.d.ts +60 -0
  200. package/dist/database/EntryStore.js +269 -0
  201. package/dist/database/EntryTransaction.d.ts +33 -0
  202. package/dist/database/EntryTransaction.js +889 -0
  203. package/dist/database/EntryUrlAliases.d.ts +2 -0
  204. package/dist/database/EntryUrlAliases.js +69 -0
  205. package/dist/database/LocalDB.d.ts +39 -0
  206. package/dist/database/LocalDB.js +79 -0
  207. package/dist/database/Version.d.ts +9 -0
  208. package/dist/database/Version.js +13 -0
  209. package/dist/database/driver/RuntimeDatabase.d.ts +8 -0
  210. package/dist/database/driver/RuntimeDatabase.js +33 -0
  211. package/dist/database/driver/WasmDatabase.d.ts +8 -0
  212. package/dist/database/driver/WasmDatabase.js +33 -0
  213. package/dist/database/entry/EntryData.d.ts +13 -0
  214. package/dist/database/entry/EntryData.js +51 -0
  215. package/dist/database/entry/EntryTable.d.ts +173 -0
  216. package/dist/database/entry/EntryTable.js +137 -0
  217. package/dist/database/entry/EntryView.d.ts +22 -0
  218. package/dist/database/entry/EntryView.js +106 -0
  219. package/dist/database/query/Condition.d.ts +8 -0
  220. package/dist/database/query/Condition.js +117 -0
  221. package/dist/database/query/EntryQuery.d.ts +43 -0
  222. package/dist/database/query/EntryQuery.js +414 -0
  223. package/dist/database/query/EntryReferences.d.ts +6 -0
  224. package/dist/database/query/EntryReferences.js +68 -0
  225. package/dist/database/query/Relation.d.ts +11 -0
  226. package/dist/database/query/Relation.js +113 -0
  227. package/dist/database/query/ResolveQuery.d.ts +15 -0
  228. package/dist/database/query/ResolveQuery.js +154 -0
  229. package/dist/database/query/Search.d.ts +47 -0
  230. package/dist/database/query/Search.js +169 -0
  231. package/dist/database/sync/Derive.d.ts +8 -0
  232. package/dist/database/sync/Derive.js +270 -0
  233. package/dist/database/sync/EntryParser.d.ts +4 -0
  234. package/dist/database/sync/EntryParser.js +87 -0
  235. package/dist/database/sync/EntrySyncer.d.ts +37 -0
  236. package/dist/database/sync/EntrySyncer.js +117 -0
  237. package/dist/database/sync/Ingest.d.ts +21 -0
  238. package/dist/database/sync/Ingest.js +136 -0
  239. package/dist/database/sync/SyncQueries.d.ts +157 -0
  240. package/dist/database/sync/SyncQueries.js +192 -0
  241. package/dist/field/code/CodeField.view.js +12 -12
  242. package/dist/field/link/LinkField.js +23 -0
  243. package/dist/field/link/LinkField.view.js +41 -40
  244. package/dist/field/list/ListField.view.js +177 -155
  245. package/dist/field/metadata/MetadataField.d.ts +28 -3
  246. package/dist/field/metadata/MetadataField.js +44 -7
  247. package/dist/field/metadata/MetadataField.view.d.ts +5 -0
  248. package/dist/field/metadata/MetadataField.view.js +34 -19
  249. package/dist/field/richtext/RichTextBlock.js +2 -2
  250. package/dist/field/richtext/RichTextDocument.js +4 -3
  251. package/dist/field/richtext/RichTextExtensions.d.ts +1 -1
  252. package/dist/field/richtext/RichTextExtensions.js +32 -28
  253. package/dist/field/richtext/RichTextField.view.js +15 -6
  254. package/dist/field/views.js +2 -0
  255. package/dist/next.cjs +0 -18
  256. package/dist/next.d.ts +4 -3
  257. package/dist/next.edge.d.ts +1 -1
  258. package/dist/next.js +1 -2
  259. package/dist/picker/entry/EntryPicker.js +2 -1
  260. package/dist/picker/url/UrlPicker.js +1 -0
  261. package/dist/preview/widget.d.ts +16 -0
  262. package/dist/preview/widget.js +70 -1
  263. package/dist/query.d.ts +28 -0
  264. package/package.json +2 -1
  265. package/dist/backend/store/GeneratedSource.d.ts +0 -2
  266. package/dist/backend/store/GeneratedSource.js +0 -21
  267. package/dist/chunks/chunk-G6E35DMJ.js +0 -1997
  268. package/dist/core/db/EntryDB.d.ts +0 -19
  269. package/dist/core/db/EntryDB.js +0 -48
  270. package/dist/core/db/EntryIndex.d.ts +0 -143
  271. package/dist/core/db/EntryIndex.js +0 -2773
  272. package/dist/core/db/EntryReferenceIndex.d.ts +0 -21
  273. package/dist/core/db/EntryReferenceIndex.js +0 -131
  274. package/dist/core/db/EntryResolver.d.ts +0 -56
  275. package/dist/core/db/EntryResolver.js +0 -699
  276. package/dist/core/db/EntryTarget.d.ts +0 -5
  277. package/dist/core/db/EntryTransaction.d.ts +0 -31
  278. package/dist/core/db/EntryTransaction.js +0 -956
  279. package/dist/core/db/LocalDB.d.ts +0 -42
  280. package/dist/core/db/LocalDB.js +0 -127
  281. package/dist/core/db/TestDB.d.ts +0 -19
  282. package/dist/core/db/TestDB.js +0 -50
  283. /package/dist/core/db/{EntryTarget.js → LocalStore.js} +0 -0
@@ -10,17 +10,15 @@ import {
10
10
  import {
11
11
  createHandler as createCoreHandler
12
12
  } from "alinea/backend/Handler";
13
- import { generatedSource } from "alinea/backend/store/GeneratedSource";
14
13
  import { JWTPreviews } from "alinea/backend/util/JWTPreviews";
15
14
  import { CloudRemote } from "alinea/cloud/CloudRemote";
16
15
  import { Config } from "alinea/core/Config";
17
- import { LocalDB } from "alinea/core/db/LocalDB";
18
16
  import { trace } from "alinea/core/Trace";
19
17
  import { NextCMS } from "./cms.js";
20
18
  import { requestContext } from "./context.js";
21
19
  import { createDevRemote } from "./DevRemote.js";
22
20
  import { revalidateContentSha } from "./syncCheck.js";
23
- function createHandler(input) {
21
+ function createHandlerWithDatabase(input, openGeneratedDatabase) {
24
22
  const options = input instanceof NextCMS ? { cms: input } : input;
25
23
  const config = options.cms.config;
26
24
  const backend = typeof options.backend === "function" ? options.backend : options.backend ? backendFromOptions(options.backend) : (context) => new CloudRemote(context, config);
@@ -28,10 +26,15 @@ function createHandler(input) {
28
26
  const span = trace(config, "alinea.next.handler.db");
29
27
  const db = PLazy.from(
30
28
  () => span(async () => {
31
- const source = await generatedSource;
32
- const db2 = new LocalDB(config, source);
33
- await db2.sync();
34
- return db2;
29
+ if (process.env.NEXT_RUNTIME === "edge")
30
+ throw new Error(
31
+ "The Alinea handler is not supported in Edge runtime environments."
32
+ );
33
+ if (!openGeneratedDatabase)
34
+ throw new Error(
35
+ "A generated database loader is required. Import createHandler from 'alinea/next'."
36
+ );
37
+ return openGeneratedDatabase(config);
35
38
  })
36
39
  );
37
40
  const handleBackend = createCoreHandler({
@@ -108,7 +111,11 @@ function rewrittenFilePath(config, request) {
108
111
  return;
109
112
  }
110
113
  }
114
+ function createHandler(input) {
115
+ return createHandlerWithDatabase(input);
116
+ }
111
117
  export {
112
118
  createHandler,
119
+ createHandlerWithDatabase,
113
120
  handlerPathname
114
121
  };
@@ -0,0 +1,5 @@
1
+ import type { Config } from 'alinea/core/Config';
2
+ import { NextCMS } from './cms.js';
3
+ import { type NextHandlerOptions } from './handler.js';
4
+ export declare function createCMS<Definition extends Config>(config: Definition): NextCMS<Definition>;
5
+ export declare function createHandler(input: NextCMS | NextHandlerOptions): (request: Request) => Promise<Response>;
@@ -0,0 +1,16 @@
1
+ import "../../chunks/chunk-CQ52GEHY.js";
2
+
3
+ // src/adapter/next/node.ts
4
+ import { generatedDatabase } from "alinea/backend/store/GeneratedDatabaseNode";
5
+ import { NextCMS } from "./cms.js";
6
+ import { createHandlerWithDatabase } from "./handler.js";
7
+ function createCMS(config) {
8
+ return new NextCMS(config, generatedDatabase);
9
+ }
10
+ function createHandler(input) {
11
+ return createHandlerWithDatabase(input, generatedDatabase);
12
+ }
13
+ export {
14
+ createCMS,
15
+ createHandler
16
+ };
@@ -1,10 +1,13 @@
1
+ import { type PreviewStats } from 'alinea/preview/widget';
1
2
  export interface NextPreviewsProps {
2
3
  dashboardUrl: string;
3
4
  widget?: boolean;
5
+ /** Resolves once the render's CMS queries settled. */
6
+ stats?: Promise<PreviewStats>;
4
7
  root?: string;
5
8
  workspace?: string;
6
9
  }
7
- export default function NextPreviews({ dashboardUrl, widget, root, workspace }: NextPreviewsProps): import("react").JSX.Element | null;
10
+ export default function NextPreviews({ dashboardUrl, widget, stats, root, workspace }: NextPreviewsProps): import("react").JSX.Element | null;
8
11
  /**
9
12
  * Wrapper around `router.refresh()` from `next/navigation` `useRouter()` to return Promise, and resolve after refresh completed
10
13
  * @returns Refresh function
@@ -11,12 +11,14 @@ import { jsx } from "react/jsx-runtime";
11
11
  function NextPreviews({
12
12
  dashboardUrl,
13
13
  widget,
14
+ stats,
14
15
  root,
15
16
  workspace
16
17
  }) {
17
18
  const refresh = useRouterRefresh();
18
19
  const [isLoading, setIsLoading] = useState(false);
19
20
  const [previewDisabled, setPreviewDisabled] = useState(false);
21
+ const [renderStats, setRenderStats] = useState();
20
22
  const pathname = usePathname();
21
23
  const adminUrl = new URL(dashboardUrl, location.origin);
22
24
  const host = window.parent !== window ? window.parent : window.opener;
@@ -43,13 +45,23 @@ function NextPreviews({
43
45
  useEffect(() => {
44
46
  if (widget) registerPreviewWidget();
45
47
  }, [widget]);
48
+ useEffect(() => {
49
+ let current = true;
50
+ stats?.then((value) => {
51
+ if (current) setRenderStats(JSON.stringify(value));
52
+ });
53
+ return () => {
54
+ current = false;
55
+ };
56
+ }, [stats]);
46
57
  if (!widget) return null;
47
58
  return /* @__PURE__ */ jsx(
48
59
  "alinea-preview",
49
60
  {
50
61
  adminUrl: String(adminUrl),
51
62
  editUrl: String(editUrl),
52
- livePreview: isPreviewing ? isLoading ? "loading" : previewDisabled ? "warning" : "connected" : void 0
63
+ livePreview: isPreviewing ? isLoading ? "loading" : previewDisabled ? "warning" : "connected" : void 0,
64
+ stats: renderStats
53
65
  }
54
66
  );
55
67
  }
@@ -0,0 +1,24 @@
1
+ import type { GraphQuery } from 'alinea/core/Graph';
2
+ import type { PreviewStat, PreviewStats } from 'alinea/preview/widget';
3
+ /** Collects the CMS queries and syncs of one draft render. */
4
+ export declare class RenderStats {
5
+ #private;
6
+ rows: Array<PreviewStat>;
7
+ statements: number;
8
+ sqlMs: number;
9
+ /** Add a row and count it as pending until `run` settles; see `timed`. */
10
+ track<T>(stat: Omit<PreviewStat, 'durationMs'>, run: (row: PreviewStat) => Promise<T>): Promise<T>;
11
+ statement(durationMs: number): void;
12
+ /**
13
+ * Resolves once nothing ran for `quietMs`, so queries of server components
14
+ * that render after the caller are counted, or after `maxMs` regardless.
15
+ */
16
+ settled(quietMs?: number, maxMs?: number): Promise<PreviewStats>;
17
+ }
18
+ /**
19
+ * Time the work a row stands for, such as answering a query without the sync
20
+ * it waited for.
21
+ */
22
+ export declare function timed<T>(row: PreviewStat | undefined, run: () => Promise<T>): Promise<T>;
23
+ /** A short description such as `first(type, url=/about)`. */
24
+ export declare function summarizeQuery(query: GraphQuery): string;
@@ -0,0 +1,74 @@
1
+ import "../../chunks/chunk-CQ52GEHY.js";
2
+
3
+ // src/adapter/next/renderStats.ts
4
+ var RenderStats = class {
5
+ rows = [];
6
+ statements = 0;
7
+ sqlMs = 0;
8
+ #pending = 0;
9
+ #idleSince = Date.now();
10
+ /** Add a row and count it as pending until `run` settles; see `timed`. */
11
+ async track(stat, run) {
12
+ const row = { ...stat, durationMs: 0 };
13
+ this.rows.push(row);
14
+ this.#pending++;
15
+ try {
16
+ return await run(row);
17
+ } finally {
18
+ this.#pending--;
19
+ this.#idleSince = Date.now();
20
+ }
21
+ }
22
+ statement(durationMs) {
23
+ this.statements++;
24
+ this.sqlMs += durationMs;
25
+ }
26
+ /**
27
+ * Resolves once nothing ran for `quietMs`, so queries of server components
28
+ * that render after the caller are counted, or after `maxMs` regardless.
29
+ */
30
+ async settled(quietMs = 50, maxMs = 5e3) {
31
+ const deadline = Date.now() + maxMs;
32
+ for (let now = Date.now(); now < deadline; now = Date.now()) {
33
+ const wait = this.#pending > 0 ? quietMs : this.#idleSince + quietMs - now;
34
+ if (wait <= 0) break;
35
+ await new Promise(
36
+ (resolve) => setTimeout(resolve, Math.min(wait, deadline - now))
37
+ );
38
+ }
39
+ const { rows, statements, sqlMs } = this;
40
+ return { rows: [...rows], statements, sqlMs };
41
+ }
42
+ };
43
+ async function timed(row, run) {
44
+ if (!row) return run();
45
+ const start = performance.now();
46
+ try {
47
+ return await run();
48
+ } finally {
49
+ row.durationMs += performance.now() - start;
50
+ }
51
+ }
52
+ var unlisted = /* @__PURE__ */ new Set([
53
+ "first",
54
+ "get",
55
+ "count",
56
+ "select",
57
+ "include",
58
+ "status",
59
+ "preview",
60
+ "syncInterval",
61
+ "disableSync"
62
+ ]);
63
+ function summarizeQuery(query) {
64
+ const mode = query.count ? "count" : query.get ? "get" : query.first ? "first" : "find";
65
+ const parts = Object.entries(query).filter(([key, value]) => !unlisted.has(key) && value !== void 0).map(
66
+ ([key, value]) => typeof value === "string" || typeof value === "number" ? `${key}=${value}` : key
67
+ );
68
+ return `${mode}(${parts.join(", ")})`;
69
+ }
70
+ export {
71
+ RenderStats,
72
+ summarizeQuery,
73
+ timed
74
+ };
@@ -1,5 +1,10 @@
1
1
  import type { Client } from 'alinea/core/Client';
2
- import type { LocalDB } from 'alinea/core/db/LocalDB';
2
+ import type { SyncOptions } from 'alinea/core/db/LocalStore';
3
+ import type { RemoteSource } from 'alinea/core/source/Source';
4
+ interface SyncableDB {
5
+ readonly sha: string | Promise<string>;
6
+ syncWith(source: RemoteSource, options?: SyncOptions): Promise<string>;
7
+ }
3
8
  export declare const CONTENT_SHA_TAG = "alinea-content-sha";
4
9
  export declare function revalidateContentSha(): Promise<void>;
5
10
  /**
@@ -9,4 +14,5 @@ export declare function revalidateContentSha(): Promise<void>;
9
14
  * Returns false when the sha could not be determined, so the caller falls
10
15
  * back to its existing throttle behavior.
11
16
  */
12
- export declare function syncIfStale(db: LocalDB, client: Client, syncInterval?: number): Promise<boolean>;
17
+ export declare function syncIfStale(db: SyncableDB, client: Client, syncInterval?: number, options?: SyncOptions): Promise<boolean>;
18
+ export {};
@@ -41,15 +41,15 @@ async function revalidateContentSha() {
41
41
  } catch {
42
42
  }
43
43
  }
44
- async function syncIfStale(db, client, syncInterval) {
44
+ async function syncIfStale(db, client, syncInterval, options) {
45
45
  if (syncInterval === Number.POSITIVE_INFINITY) return true;
46
46
  if (syncInterval === 0) {
47
- await db.syncWith(client);
47
+ await db.syncWith(client, options);
48
48
  return true;
49
49
  }
50
50
  const expected = await latestSha(client);
51
51
  if (!expected) return false;
52
- if (expected !== db.sha) await db.syncWith(client);
52
+ if (expected !== await db.sha) await db.syncWith(client, options);
53
53
  return true;
54
54
  }
55
55
  export {
@@ -27,7 +27,6 @@ function withAlinea(config = {}) {
27
27
  } catch {
28
28
  console.warn("Alinea could not determine Next.js version, assuming 15+");
29
29
  }
30
- const redirects = adminPath ? createRedirects(config, adminPath) : config.redirects;
31
30
  const rewrites = adminPath ? createRewrites(config, adminPath, settings.handlerUrl) : config.rewrites;
32
31
  const images = adminPath ? createImages(config, adminPath) : config.images;
33
32
  const env = settings ? {
@@ -45,7 +44,6 @@ function withAlinea(config = {}) {
45
44
  "@alinea/generated"
46
45
  ]
47
46
  },
48
- redirects,
49
47
  rewrites,
50
48
  images,
51
49
  env
@@ -56,7 +54,6 @@ function withAlinea(config = {}) {
56
54
  ...config.serverExternalPackages ?? [],
57
55
  "@alinea/generated"
58
56
  ],
59
- redirects,
60
57
  rewrites,
61
58
  images,
62
59
  env
@@ -82,21 +79,6 @@ function createImages(config, adminPath) {
82
79
  ]
83
80
  };
84
81
  }
85
- function createRedirects(config, adminPath) {
86
- const dev = process.env.ALINEA_DEV_SERVER;
87
- if (!dev) return config.redirects;
88
- return async () => {
89
- const existing = config.redirects ? await config.redirects() : [];
90
- return [
91
- ...existing,
92
- {
93
- permanent: true,
94
- source: `${adminPath}/~dev`,
95
- destination: `${dev}/~dev`
96
- }
97
- ];
98
- };
99
- }
100
82
  var emptyRewrites = {
101
83
  beforeFiles: [],
102
84
  afterFiles: [],
@@ -1,6 +1,6 @@
1
1
  import type { CMS } from 'alinea/core/CMS';
2
2
  import type { AuthedContext, RemoteConnection, RequestContext } from 'alinea/core/Connection';
3
- import { LocalDB } from 'alinea/core/db/LocalDB';
3
+ import type { LocalStore } from 'alinea/core/db/LocalStore';
4
4
  import type { Mutation } from 'alinea/core/db/Mutation';
5
5
  export interface Handler {
6
6
  (request: Request, context: RequestContext): Promise<Response>;
@@ -18,7 +18,7 @@ export interface HandlerHooks {
18
18
  }
19
19
  export interface HandlerOptions extends HandlerHooks {
20
20
  cms: CMS;
21
- db: LocalDB | Promise<LocalDB>;
21
+ db: LocalStore | Promise<LocalStore>;
22
22
  remote?: (context: RequestContext) => RemoteConnection;
23
23
  forwardMutations?(request: Request, context: AuthedContext): Promise<Response | undefined>;
24
24
  }
@@ -4,7 +4,7 @@ import {
4
4
  object,
5
5
  optional,
6
6
  string
7
- } from "../chunks/chunk-I4GC3E65.js";
7
+ } from "../chunks/chunk-UPY2RUZF.js";
8
8
  import {
9
9
  PLazy
10
10
  } from "../chunks/chunk-IKINPSS5.js";
@@ -19,8 +19,10 @@ import {
19
19
  } from "alinea/core/BlobTransport";
20
20
  import { Config } from "alinea/core/Config";
21
21
  import { developmentKeyHeader } from "alinea/core/Connection";
22
+ import { Entry } from "alinea/core/Entry";
22
23
  import { ErrorCode, HttpError } from "alinea/core/HttpError";
23
24
  import { MediaLocation } from "alinea/core/media/MediaLocation";
25
+ import { MediaFile } from "alinea/core/media/MediaTypes";
24
26
  import { assertUploadSize } from "alinea/core/media/UploadLimits";
25
27
  import { Permission, Policy } from "alinea/core/Role";
26
28
  import { getScope } from "alinea/core/Scope";
@@ -51,9 +53,18 @@ function createHandler({
51
53
  const local = await db;
52
54
  const simulateLatency = process.env.ALINEA_LATENCY;
53
55
  if (simulateLatency) await new Promise((resolve) => setTimeout(resolve, 2e3));
56
+ async function syncForRead(cnx) {
57
+ try {
58
+ await local.syncWith(cnx);
59
+ } catch (error) {
60
+ console.warn(
61
+ `Alinea could not sync with the remote, serving current content: ${error instanceof Error ? error.message : String(error)}`
62
+ );
63
+ }
64
+ }
54
65
  async function periodicSync(cnx, syncInterval) {
55
66
  if (dev) return;
56
- return throttle(() => local.syncWith(cnx), syncInterval);
67
+ return throttle(() => syncForRead(cnx), syncInterval);
57
68
  }
58
69
  try {
59
70
  const previews = new JWTPreviews(context.apiKey);
@@ -87,19 +98,29 @@ function createHandler({
87
98
  throw new HttpError(400, "Invalid file path");
88
99
  await periodicSync(cnx);
89
100
  const requestedUrl = Config.filePathname(cms.config, normalized);
90
- const entry = local.index.findByUrl(
91
- requestedUrl,
92
- (entry2) => entry2.type === "MediaFile" && entry2.status === "published" && entry2.main
93
- );
101
+ const select = {
102
+ url: Entry.url,
103
+ filePath: Entry.filePath,
104
+ workspace: Entry.workspace,
105
+ location: MediaFile.location,
106
+ previewUrl: MediaFile.previewUrl
107
+ };
108
+ const query = {
109
+ type: MediaFile,
110
+ status: "published",
111
+ main: true,
112
+ select
113
+ };
114
+ const entry = await local.first({ ...query, url: requestedUrl }) ?? await local.first({ ...query, alias: requestedUrl });
94
115
  if (!entry) return new Response("Not found", { status: 404 });
95
116
  if (entry.url !== requestedUrl && !proxy)
96
117
  return new Response(null, {
97
118
  status: 308,
98
119
  headers: { location: entry.url }
99
120
  });
100
- const wasBuilt = local.index.initialSync?.has(entry.filePath) ?? false;
101
- const previewUrl = entry.data.previewUrl;
102
- const location = entry.data.location;
121
+ const wasBuilt = await local.includedAtBuild(entry.filePath);
122
+ const previewUrl = entry.previewUrl;
123
+ const location = entry.location;
103
124
  if (typeof location !== "string")
104
125
  return new Response("Not found", { status: 404 });
105
126
  const previewSource = typeof previewUrl === "string" && previewUrl ? new URL(previewUrl, request.url).href : void 0;
@@ -245,8 +266,8 @@ function createHandler({
245
266
  );
246
267
  } else {
247
268
  const preview = await decodePreviewRequest(query.preview);
248
- if ("contentHash" in preview && local.sha !== preview.contentHash)
249
- await local.syncWith(cnx);
269
+ if ("contentHash" in preview && await local.sha !== preview.contentHash)
270
+ await syncForRead(cnx);
250
271
  query.preview = await applyPreview(local, preview);
251
272
  }
252
273
  return Response.json(await local.resolve(query) ?? null);
@@ -322,7 +343,7 @@ function createHandler({
322
343
  if (action === HandleAction.Tree && request.method === "GET") {
323
344
  expectJson();
324
345
  const sha = string(url.searchParams.get("sha"));
325
- await local.syncWith(cnx);
346
+ await syncForRead(cnx);
326
347
  const tree = await local.getTreeIfDifferent(sha);
327
348
  return compressResponse(request, Response.json(tree ?? null));
328
349
  }
@@ -1,8 +1,20 @@
1
1
  import {
2
2
  driver_exports
3
- } from "../../chunks/chunk-X47OVDF3.js";
4
- import "../../chunks/chunk-G6E35DMJ.js";
5
- import "../../chunks/chunk-NWQXN4SB.js";
3
+ } from "../../chunks/chunk-2U43BB6P.js";
4
+ import "../../chunks/chunk-A42DP5T7.js";
5
+ import "../../chunks/chunk-NLZLRQ5U.js";
6
+ import "../../chunks/chunk-IL7FJQAY.js";
7
+ import "../../chunks/chunk-M7KDJEGH.js";
8
+ import "../../chunks/chunk-N47Y62CI.js";
9
+ import "../../chunks/chunk-QBPYWU6C.js";
10
+ import "../../chunks/chunk-2BJ2IFQM.js";
11
+ import "../../chunks/chunk-XCZXR3C2.js";
12
+ import "../../chunks/chunk-TFMUSWGG.js";
13
+ import "../../chunks/chunk-76VMZTLN.js";
14
+ import "../../chunks/chunk-2PIFHEYR.js";
15
+ import "../../chunks/chunk-K62JP6HR.js";
16
+ import "../../chunks/chunk-ATF42T2B.js";
17
+ import "../../chunks/chunk-ETBQTP2S.js";
6
18
  import "../../chunks/chunk-CQ52GEHY.js";
7
19
 
8
20
  // src/backend/api/CreateBackend.ts
@@ -1,21 +1,29 @@
1
1
  import {
2
- Builder,
3
- Column,
4
- ColumnType,
5
- column,
6
- eq,
7
- jsonAggregateArray,
8
- jsonArray,
9
- querySelection,
10
- selectQuery,
2
+ include
3
+ } from "../../chunks/chunk-XTWYBWP2.js";
4
+ import {
5
+ blob,
6
+ id,
7
+ integer,
8
+ text,
9
+ varchar
10
+ } from "../../chunks/chunk-K7LHQXI4.js";
11
+ import {
12
+ Builder
13
+ } from "../../chunks/chunk-2BJ2IFQM.js";
14
+ import {
15
+ eq
16
+ } from "../../chunks/chunk-XCZXR3C2.js";
17
+ import {
11
18
  table
12
- } from "../../chunks/chunk-G6E35DMJ.js";
19
+ } from "../../chunks/chunk-TFMUSWGG.js";
20
+ import "../../chunks/chunk-76VMZTLN.js";
21
+ import "../../chunks/chunk-2PIFHEYR.js";
22
+ import "../../chunks/chunk-K62JP6HR.js";
23
+ import "../../chunks/chunk-ATF42T2B.js";
13
24
  import {
14
- getData,
15
- internalData,
16
- internalSql,
17
25
  sql
18
- } from "../../chunks/chunk-NWQXN4SB.js";
26
+ } from "../../chunks/chunk-ETBQTP2S.js";
19
27
  import {
20
28
  PLazy
21
29
  } from "../../chunks/chunk-IKINPSS5.js";
@@ -26,127 +34,6 @@ import { createId } from "alinea/core/Id";
26
34
  import { assert } from "alinea/core/util/Assert";
27
35
  import { basename, extname } from "alinea/core/util/Paths";
28
36
  import { slugify } from "alinea/core/util/Slugs";
29
-
30
- // node_modules/rado/dist/universal/columns.js
31
- var idType = new ColumnType(
32
- "id",
33
- [],
34
- sql.universal({
35
- sqlite: sql`integer`,
36
- postgres: sql`integer generated always as identity`,
37
- mysql: sql`int not null auto_increment`
38
- })
39
- );
40
- var blobType = new ColumnType(
41
- "blob",
42
- [],
43
- sql.universal({
44
- postgres: sql`bytea`,
45
- default: sql`blob`
46
- })
47
- );
48
- var numberType = new ColumnType(
49
- "number",
50
- [],
51
- sql.universal({
52
- mysql: sql`double`,
53
- default: sql`numeric`
54
- })
55
- );
56
- var jsonbType = new ColumnType(
57
- "json",
58
- [],
59
- sql.universal({
60
- mysql: sql`json`,
61
- default: sql`jsonb`
62
- })
63
- );
64
- function id(name) {
65
- return new Column({
66
- name,
67
- type: idType,
68
- primary: true,
69
- notNull: true
70
- });
71
- }
72
- function text(name) {
73
- return new Column({ name, type: column.text() });
74
- }
75
- function varchar(name, options) {
76
- return new Column({ name, type: column.varchar(options?.length) });
77
- }
78
- function integer(name) {
79
- return new Column({ name, type: column.integer() });
80
- }
81
- function blob(name) {
82
- return new Column({
83
- name,
84
- type: blobType,
85
- mapFromDriverValue(value) {
86
- return new Uint8Array(value);
87
- }
88
- });
89
- }
90
-
91
- // node_modules/rado/dist/core/expr/Include.js
92
- var Include = class {
93
- [internalData];
94
- constructor(data) {
95
- this[internalData] = data;
96
- }
97
- #mapFromDriverValue = (value, specs) => {
98
- const query = getData(this);
99
- const parsed = specs.parsesJson ? value : JSON.parse(value);
100
- const selected = querySelection(query);
101
- if (query.first) {
102
- const result = parsed ? selected.mapRow({ values: parsed, index: 0, specs }) : null;
103
- return result;
104
- }
105
- if (!parsed) return [];
106
- const rows = parsed;
107
- const ctx = {
108
- values: void 0,
109
- index: 0,
110
- specs
111
- };
112
- for (let i = 0; i < rows.length; i++) {
113
- ctx.values = rows[i];
114
- ctx.index = 0;
115
- rows[i] = selected.mapRow(ctx);
116
- }
117
- return rows ?? [];
118
- };
119
- get [internalSql]() {
120
- return includeQuery(getData(this)).mapWith({
121
- mapFromDriverValue: this.#mapFromDriverValue
122
- });
123
- }
124
- };
125
- function include(select) {
126
- return new Include({ ...getData(select), first: false });
127
- }
128
- ((include2) => {
129
- function one(select) {
130
- return new Include({
131
- ...getData(select),
132
- first: true
133
- });
134
- }
135
- include2.one = one;
136
- })(include || (include = {}));
137
- function includeQuery(query) {
138
- const { first, limit, offset, orderBy } = query;
139
- const wrapQuery = Boolean(limit || offset || orderBy);
140
- const innerQuery = selectQuery(query);
141
- const inner = wrapQuery ? sql`select * from (${innerQuery}) as __` : innerQuery;
142
- const fields = querySelection(query).fieldNames();
143
- const subject = jsonArray(
144
- ...fields.map((name) => sql`_.${sql.identifier(name)}`)
145
- );
146
- return sql`(select ${first ? subject : jsonAggregateArray(subject)} from (${inner}) as _)`;
147
- }
148
-
149
- // src/backend/api/DatabaseApi.ts
150
37
  import { HandleAction } from "../HandleAction.js";
151
38
  var UploadTable = table("alinea_upload", {
152
39
  entryId: varchar(void 0, { length: 27 }).primaryKey(),
@@ -1,8 +1,20 @@
1
1
  import {
2
2
  driver_exports
3
- } from "../../chunks/chunk-X47OVDF3.js";
4
- import "../../chunks/chunk-G6E35DMJ.js";
5
- import "../../chunks/chunk-NWQXN4SB.js";
3
+ } from "../../chunks/chunk-2U43BB6P.js";
4
+ import "../../chunks/chunk-A42DP5T7.js";
5
+ import "../../chunks/chunk-NLZLRQ5U.js";
6
+ import "../../chunks/chunk-IL7FJQAY.js";
7
+ import "../../chunks/chunk-M7KDJEGH.js";
8
+ import "../../chunks/chunk-N47Y62CI.js";
9
+ import "../../chunks/chunk-QBPYWU6C.js";
10
+ import "../../chunks/chunk-2BJ2IFQM.js";
11
+ import "../../chunks/chunk-XCZXR3C2.js";
12
+ import "../../chunks/chunk-TFMUSWGG.js";
13
+ import "../../chunks/chunk-76VMZTLN.js";
14
+ import "../../chunks/chunk-2PIFHEYR.js";
15
+ import "../../chunks/chunk-K62JP6HR.js";
16
+ import "../../chunks/chunk-ATF42T2B.js";
17
+ import "../../chunks/chunk-ETBQTP2S.js";
6
18
  import "../../chunks/chunk-CQ52GEHY.js";
7
19
 
8
20
  // src/backend/api/database.ts
@@ -1,9 +1,9 @@
1
- import type { LocalDB } from 'alinea/core/db/LocalDB';
2
1
  import { Entry } from 'alinea/core/Entry';
3
2
  import type { PreviewRequest, PreviewUpdate } from 'alinea/core/Preview';
3
+ import type { Graph } from 'alinea/core/Graph';
4
4
  export interface DecodedEntryPreview {
5
5
  entry: Entry;
6
6
  }
7
7
  export type DecodedPreviewRequest = PreviewUpdate | DecodedEntryPreview;
8
8
  export declare function decodePreviewRequest(preview: PreviewRequest): Promise<DecodedPreviewRequest>;
9
- export declare function applyPreview(local: LocalDB, preview: DecodedPreviewRequest): Promise<PreviewRequest | undefined>;
9
+ export declare function applyPreview(local: Graph, preview: DecodedPreviewRequest): Promise<PreviewRequest | undefined>;
@@ -5,6 +5,8 @@ import { Headers, Request } from "@alinea/iso";
5
5
  import { TLSSocket } from "node:tls";
6
6
  async function writeReadableStreamToWritable(stream, writable) {
7
7
  const reader = stream.getReader();
8
+ writable.once("close", () => reader.cancel().catch(() => {
9
+ }));
8
10
  async function read() {
9
11
  const { done, value } = await reader.read();
10
12
  if (done) return writable.end();