alinea 2.0.0-preview.8 → 2.0.0-preview.9

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 (165) hide show
  1. package/dist/.init/content/pages/welcome.json +1 -1
  2. package/dist/LICENSES.md +136 -136
  3. package/dist/adapter/next/cms.js +24 -8
  4. package/dist/adapter/next/handler.js +63 -10
  5. package/dist/adapter/next/renderStats.d.ts +25 -4
  6. package/dist/adapter/next/renderStats.js +71 -3
  7. package/dist/adapter/next/syncCheck.js +2 -8
  8. package/dist/adapter/next/with-alinea.js +6 -2
  9. package/dist/backend/HandleAction.d.ts +1 -1
  10. package/dist/backend/HandleAction.js +1 -1
  11. package/dist/backend/Handler.js +12 -35
  12. package/dist/backend/api/CreateBackend.js +6 -6
  13. package/dist/backend/api/DatabaseApi.js +2 -2
  14. package/dist/backend/api/ProxyMedia.d.ts +2 -3
  15. package/dist/backend/api/ProxyMedia.js +7 -22
  16. package/dist/backend/api/database.js +6 -6
  17. package/dist/backend/store/GeneratedDatabase.d.ts +6 -3
  18. package/dist/backend/store/GeneratedDatabase.js +13 -11
  19. package/dist/backend/store/GeneratedDatabaseNode.d.ts +1 -1
  20. package/dist/backend/store/GeneratedDatabaseNode.js +1 -1
  21. package/dist/bundled.d.ts +280 -211
  22. package/dist/chunks/{node-sqlite-7CSGL27V.js → bun-sqlite-5SHXN3AT.js} +3 -3
  23. package/dist/chunks/{chunk-IL7FJQAY.js → chunk-66YZ47TY.js} +1 -1
  24. package/dist/chunks/{chunk-M7KDJEGH.js → chunk-AIU6CMVT.js} +1 -1
  25. package/dist/chunks/{chunk-K7LHQXI4.js → chunk-ASYKC6IE.js} +1 -1
  26. package/dist/chunks/{chunk-RWWYUNVX.js → chunk-DWR5A5KL.js} +6 -2
  27. package/dist/chunks/{chunk-NLZLRQ5U.js → chunk-ETWOY4AL.js} +1 -1
  28. package/dist/chunks/{chunk-TFMUSWGG.js → chunk-MOWR65LM.js} +72 -67
  29. package/dist/chunks/{chunk-2U43BB6P.js → chunk-QJGGYF6E.js} +5 -5
  30. package/dist/chunks/{chunk-A42DP5T7.js → chunk-QSN6RH6X.js} +1 -1
  31. package/dist/chunks/{bun-sqlite-ZZDB7YQQ.js → node-sqlite-XVNTNMCY.js} +3 -3
  32. package/dist/cli/Serve.js +1 -1
  33. package/dist/cli/bin.js +6 -2
  34. package/dist/cli/generate/DevDB.js +4 -2
  35. package/dist/cli/serve/DevServer.d.ts +2 -0
  36. package/dist/cli/serve/DevServer.js +7 -2
  37. package/dist/cloud/CloudRemote.js +1 -1
  38. package/dist/components/Breadcrumbs.js +2 -2
  39. package/dist/components/Calendar.js +7 -7
  40. package/dist/components/Checkbox.js +3 -3
  41. package/dist/components/ComboBox.js +12 -12
  42. package/dist/components/DatePicker.js +3 -3
  43. package/dist/components/DateRangePicker.js +5 -5
  44. package/dist/components/Disclosure.js +7 -7
  45. package/dist/components/Label.js +5 -5
  46. package/dist/components/List.js +37 -37
  47. package/dist/components/Menu.js +2 -2
  48. package/dist/components/Modal.js +3 -3
  49. package/dist/components/MultipleSelect.js +26 -26
  50. package/dist/components/NumberField.js +6 -6
  51. package/dist/components/ProgressCircle.js +3 -3
  52. package/dist/components/RadioGroup.js +2 -2
  53. package/dist/components/SearchField.js +7 -7
  54. package/dist/components/Select.js +7 -7
  55. package/dist/components/Surface.js +2 -2
  56. package/dist/components/Switch.js +2 -2
  57. package/dist/components/Table.js +7 -7
  58. package/dist/components/Tabs.js +3 -3
  59. package/dist/components/TagGroup.js +2 -2
  60. package/dist/components/TextField.js +4 -4
  61. package/dist/components/TimeField.js +3 -3
  62. package/dist/components/Toggle.js +2 -2
  63. package/dist/components/Toolbar.js +3 -3
  64. package/dist/components/Tree.js +7 -7
  65. package/dist/core/Client.d.ts +1 -4
  66. package/dist/core/Client.js +5 -7
  67. package/dist/core/Connection.d.ts +4 -1
  68. package/dist/core/Connection.js +3 -1
  69. package/dist/core/db/LocalStore.d.ts +2 -0
  70. package/dist/core/source/GithubSource.js +39 -11
  71. package/dist/dashboard/App.js +2 -2
  72. package/dist/dashboard/app/AccessDenied.js +4 -4
  73. package/dist/dashboard/app/ActivityStatus.js +15 -15
  74. package/dist/dashboard/app/AuthView.js +13 -13
  75. package/dist/dashboard/app/Badge.js +2 -2
  76. package/dist/dashboard/app/CompactField.js +9 -9
  77. package/dist/dashboard/app/DashboardErrorBoundary.js +7 -7
  78. package/dist/dashboard/app/DashboardLayout.js +3 -3
  79. package/dist/dashboard/app/EntryFields.js +2 -2
  80. package/dist/dashboard/app/EntryHeader.js +10 -10
  81. package/dist/dashboard/app/EntryReferences.js +7 -7
  82. package/dist/dashboard/app/EntrySidebar.js +16 -16
  83. package/dist/dashboard/app/EntrySidebarPreview.js +10 -10
  84. package/dist/dashboard/app/EntryTranslationBanner.js +3 -3
  85. package/dist/dashboard/app/Explorer.js +44 -44
  86. package/dist/dashboard/app/ExplorerCards.js +34 -34
  87. package/dist/dashboard/app/ExplorerFileCard.js +21 -21
  88. package/dist/dashboard/app/ExplorerList.js +10 -10
  89. package/dist/dashboard/app/ExplorerModal.js +4 -4
  90. package/dist/dashboard/app/ExplorerTable.js +49 -49
  91. package/dist/dashboard/app/LinkPicker.js +4 -4
  92. package/dist/dashboard/app/LocaleMenu.js +3 -3
  93. package/dist/dashboard/app/SidebarTree.js +42 -42
  94. package/dist/dashboard/app/WorkspaceMenu.js +12 -12
  95. package/dist/dashboard/app/WorkspaceRoots.js +28 -28
  96. package/dist/dashboard/app/editor/FileEditor.js +27 -27
  97. package/dist/dashboard/app/editor/FilePreview.js +7 -7
  98. package/dist/dashboard/app/modals/CreateEntry.js +3 -3
  99. package/dist/dashboard/app/pages/EntryPage.js +19 -19
  100. package/dist/dashboard/app/pages/SplashPage.js +46 -46
  101. package/dist/dashboard/app/pages/UsersPage.js +36 -36
  102. package/dist/dashboard/app/ui/DashboardModal.js +19 -19
  103. package/dist/dashboard/app/ui/Rail.js +3 -3
  104. package/dist/dashboard/app/ui/Sidebar.js +2 -2
  105. package/dist/dashboard/boot/DashboardWorker.js +6 -2
  106. package/dist/dashboard/boot/WorkerDB.d.ts +2 -2
  107. package/dist/database/BrowserEntryStore.d.ts +18 -6
  108. package/dist/database/BrowserEntryStore.js +95 -81
  109. package/dist/database/DatabaseSource.d.ts +2 -2
  110. package/dist/database/DatabaseTables.js +2 -2
  111. package/dist/database/EntryDatabase.d.ts +83 -7
  112. package/dist/database/EntryDatabase.js +420 -30
  113. package/dist/database/EntryStore.d.ts +10 -12
  114. package/dist/database/EntryStore.js +27 -66
  115. package/dist/database/EntryTransaction.d.ts +3 -3
  116. package/dist/database/EntryTransaction.js +39 -21
  117. package/dist/database/Version.d.ts +2 -2
  118. package/dist/database/Version.js +1 -1
  119. package/dist/database/driver/DatabaseHandle.d.ts +17 -0
  120. package/dist/database/driver/DatabaseHandle.js +0 -0
  121. package/dist/database/driver/OverlayExtension.browser.d.ts +2 -0
  122. package/dist/database/driver/OverlayExtension.browser.js +9 -0
  123. package/dist/database/driver/OverlayExtension.d.ts +1 -0
  124. package/dist/database/driver/OverlayExtension.js +7 -0
  125. package/dist/database/driver/RuntimeDatabase.d.ts +11 -6
  126. package/dist/database/driver/RuntimeDatabase.js +66 -22
  127. package/dist/database/driver/WasmDatabase.d.ts +23 -2
  128. package/dist/database/driver/WasmDatabase.js +22 -9
  129. package/dist/database/entry/EntryTable.d.ts +21 -5
  130. package/dist/database/entry/EntryTable.js +59 -10
  131. package/dist/database/query/EntryQuery.d.ts +3 -2
  132. package/dist/database/query/EntryQuery.js +23 -25
  133. package/dist/database/query/EntryReferences.d.ts +2 -3
  134. package/dist/database/query/EntryReferences.js +43 -41
  135. package/dist/database/query/Relation.js +1 -1
  136. package/dist/database/query/ResolveQuery.d.ts +1 -4
  137. package/dist/database/query/ResolveQuery.js +54 -19
  138. package/dist/database/query/Search.d.ts +8 -17
  139. package/dist/database/query/Search.js +17 -37
  140. package/dist/database/sync/EntryParser.d.ts +5 -1
  141. package/dist/database/sync/EntryParser.js +4 -1
  142. package/dist/database/sync/EntrySyncer.d.ts +7 -19
  143. package/dist/database/sync/EntrySyncer.js +17 -45
  144. package/dist/database/sync/Ingest.js +40 -31
  145. package/dist/database/sync/SyncQueries.d.ts +5 -2
  146. package/dist/database/sync/SyncQueries.js +27 -3
  147. package/dist/field/check/CheckField.view.js +2 -2
  148. package/dist/field/code/CodeField.view.js +11 -11
  149. package/dist/field/link/LinkField.view.js +34 -34
  150. package/dist/field/list/ListField.view.js +17 -17
  151. package/dist/field/metadata/MetadataField.view.js +15 -15
  152. package/dist/field/richtext/RichTextBlock.js +2 -2
  153. package/dist/field/richtext/RichTextExtensions.js +23 -23
  154. package/dist/field/richtext/RichTextField.view.js +2 -2
  155. package/dist/field/richtext/RichTextInsertMenu.js +2 -2
  156. package/dist/next.cjs +6 -2
  157. package/dist/preview/widget.d.ts +29 -0
  158. package/dist/preview/widget.js +31 -5
  159. package/package.json +6 -2
  160. package/dist/adapter/next/DevRemote.d.ts +0 -3
  161. package/dist/adapter/next/DevRemote.js +0 -45
  162. package/dist/database/EntryLayer.d.ts +0 -93
  163. package/dist/database/EntryLayer.js +0 -459
  164. package/dist/database/entry/EntryView.d.ts +0 -22
  165. package/dist/database/entry/EntryView.js +0 -106
@@ -1,27 +1,78 @@
1
1
  import "../../chunks/chunk-CQ52GEHY.js";
2
2
 
3
3
  // src/adapter/next/renderStats.ts
4
+ var slowestCount = 5;
4
5
  var RenderStats = class {
5
6
  rows = [];
6
7
  statements = 0;
7
8
  sqlMs = 0;
9
+ slowest = [];
10
+ /** The bundled database that answered, once a query reached it. */
11
+ database;
12
+ startedAt = Date.now();
8
13
  #pending = 0;
9
14
  #idleSince = Date.now();
15
+ #renderStart = Number.POSITIVE_INFINITY;
16
+ #renderEnd = Number.NEGATIVE_INFINITY;
17
+ #executedUntil = Number.NEGATIVE_INFINITY;
18
+ /** Syncs in progress: their statements run before any query's. */
19
+ #syncing = [];
20
+ /** Queries executing or waiting to, in the order they run. */
21
+ #executing = [];
10
22
  /** Add a row and count it as pending until `run` settles; see `timed`. */
11
23
  async track(stat, run) {
12
24
  const row = { ...stat, durationMs: 0 };
13
25
  this.rows.push(row);
14
26
  this.#pending++;
27
+ this.#renderStart = Math.min(this.#renderStart, performance.now());
28
+ if (row.kind === "sync") this.#syncing.push(row);
15
29
  try {
16
30
  return await run(row);
17
31
  } finally {
32
+ if (row.kind === "sync") remove(this.#syncing, row);
18
33
  this.#pending--;
19
34
  this.#idleSince = Date.now();
35
+ this.#renderEnd = Math.max(this.#renderEnd, performance.now());
20
36
  }
21
37
  }
22
- statement(durationMs) {
38
+ /**
39
+ * Time a database query without the time it waited behind the others:
40
+ * queries of a render run one at a time in the order they were called, so
41
+ * one starts executing once the previous one finished, or when it was
42
+ * called if that is later.
43
+ */
44
+ async executed(row, run) {
45
+ const start = performance.now();
46
+ this.#executing.push(row);
47
+ try {
48
+ return await run();
49
+ } finally {
50
+ remove(this.#executing, row);
51
+ const end = performance.now();
52
+ row.durationMs = end - Math.max(start, this.#executedUntil);
53
+ this.#executedUntil = end;
54
+ }
55
+ }
56
+ /**
57
+ * Count a statement towards the render, and towards the row that ran it:
58
+ * a sync in progress, or else the query executing, which is the earliest
59
+ * one called that has not finished (see `executed`).
60
+ */
61
+ statement(durationMs, sql) {
23
62
  this.statements++;
24
63
  this.sqlMs += durationMs;
64
+ const row = this.#syncing.at(-1) ?? this.#executing[0];
65
+ if (row) {
66
+ row.statements = (row.statements ?? 0) + 1;
67
+ row.sqlMs = (row.sqlMs ?? 0) + durationMs;
68
+ }
69
+ if (sql === void 0) return;
70
+ const { slowest } = this;
71
+ if (slowest.length >= slowestCount && durationMs <= slowest[slowest.length - 1].durationMs)
72
+ return;
73
+ slowest.push({ sql: summarizeSql(sql), durationMs, query: row?.summary });
74
+ slowest.sort((a, b) => b.durationMs - a.durationMs);
75
+ slowest.length = Math.min(slowest.length, slowestCount);
25
76
  }
26
77
  /**
27
78
  * Resolves once nothing ran for `quietMs`, so queries of server components
@@ -36,10 +87,22 @@ var RenderStats = class {
36
87
  (resolve) => setTimeout(resolve, Math.min(wait, deadline - now))
37
88
  );
38
89
  }
39
- const { rows, statements, sqlMs } = this;
40
- return { rows: [...rows], statements, sqlMs };
90
+ const { rows, statements, sqlMs, slowest, database } = this;
91
+ const renderMs = Math.max(0, this.#renderEnd - this.#renderStart);
92
+ return {
93
+ rows: rows.map((row) => ({ ...row })),
94
+ statements,
95
+ sqlMs,
96
+ renderMs,
97
+ slowest: [...slowest],
98
+ database
99
+ };
41
100
  }
42
101
  };
102
+ function summarizeSql(sql, maxLength = 200) {
103
+ const text = sql.replace(/\s+/g, " ").replaceAll('"', "").replace(/^select .*? from /i, "select \u2026 from ").replace(/\b\w+\.(\w+)/g, "$1").trim();
104
+ return text.length > maxLength ? `${text.slice(0, maxLength - 1)}\u2026` : text;
105
+ }
43
106
  async function timed(row, run) {
44
107
  if (!row) return run();
45
108
  const start = performance.now();
@@ -67,8 +130,13 @@ function summarizeQuery(query) {
67
130
  );
68
131
  return `${mode}(${parts.join(", ")})`;
69
132
  }
133
+ function remove(items, item) {
134
+ const index = items.indexOf(item);
135
+ if (index !== -1) items.splice(index, 1);
136
+ }
70
137
  export {
71
138
  RenderStats,
72
139
  summarizeQuery,
140
+ summarizeSql,
73
141
  timed
74
142
  };
@@ -1,10 +1,8 @@
1
1
  import "../../chunks/chunk-CQ52GEHY.js";
2
2
 
3
3
  // src/adapter/next/syncCheck.ts
4
- import { ReadonlyTree } from "alinea/core/source/Tree";
5
4
  var CONTENT_SHA_TAG = "alinea-content-sha";
6
5
  var SHA_REVALIDATE_SECONDS = 60;
7
- var SENTINEL_SHA = ReadonlyTree.EMPTY.sha;
8
6
  var inflight;
9
7
  function latestSha(client) {
10
8
  if (inflight) return inflight;
@@ -17,18 +15,14 @@ async function loadLatestSha(client) {
17
15
  try {
18
16
  const { unstable_cache } = await import("next/cache.js");
19
17
  const getSha = unstable_cache(
20
- async () => {
21
- const tree = await client.getTreeIfDifferent(SENTINEL_SHA);
22
- return tree?.sha;
23
- },
18
+ () => client.getSha(),
24
19
  ["alinea-content-sha"],
25
20
  { revalidate: SHA_REVALIDATE_SECONDS, tags: [CONTENT_SHA_TAG] }
26
21
  );
27
22
  return await getSha();
28
23
  } catch {
29
24
  try {
30
- const tree = await client.getTreeIfDifferent(SENTINEL_SHA);
31
- return tree?.sha;
25
+ return await client.getSha();
32
26
  } catch {
33
27
  return void 0;
34
28
  }
@@ -41,7 +41,8 @@ function withAlinea(config = {}) {
41
41
  ...config.experimental,
42
42
  serverComponentsExternalPackages: [
43
43
  ...config.experimental?.serverComponentsExternalPackages ?? [],
44
- "@alinea/generated"
44
+ "@alinea/generated",
45
+ "@alinea/sqlite-wasm"
45
46
  ]
46
47
  },
47
48
  rewrites,
@@ -52,7 +53,10 @@ function withAlinea(config = {}) {
52
53
  ...config,
53
54
  serverExternalPackages: [
54
55
  ...config.serverExternalPackages ?? [],
55
- "@alinea/generated"
56
+ "@alinea/generated",
57
+ // Loads its native extension from the package directory, which file
58
+ // tracing then includes.
59
+ "@alinea/sqlite-wasm"
56
60
  ],
57
61
  rewrites,
58
62
  images,
@@ -11,6 +11,6 @@ export declare enum HandleAction {
11
11
  Mutate = "mutate",
12
12
  Upload = "upload",
13
13
  Tree = "tree",
14
- Commit = "commit",
14
+ Sha = "sha",
15
15
  Blob = "blob"
16
16
  }
@@ -14,7 +14,7 @@ var HandleAction = /* @__PURE__ */ ((HandleAction2) => {
14
14
  HandleAction2["Mutate"] = "mutate";
15
15
  HandleAction2["Upload"] = "upload";
16
16
  HandleAction2["Tree"] = "tree";
17
- HandleAction2["Commit"] = "commit";
17
+ HandleAction2["Sha"] = "sha";
18
18
  HandleAction2["Blob"] = "blob";
19
19
  return HandleAction2;
20
20
  })(HandleAction || {});
@@ -32,7 +32,7 @@ import { isRecord } from "alinea/core/util/Objects";
32
32
  import { isAbsolute, normalize } from "alinea/core/util/Paths";
33
33
  import { InvalidCredentialsError, MissingCredentialsError } from "./Auth.js";
34
34
  import { HandleAction } from "./HandleAction.js";
35
- import { isRedirectStatus, proxyMediaUrl } from "./api/ProxyMedia.js";
35
+ import { proxyMediaUrl } from "./api/ProxyMedia.js";
36
36
  import { applyPreview, decodePreviewRequest } from "./resolver/ParsePreview.js";
37
37
  import { compressResponse } from "./router/Router.js";
38
38
  import { createThrottledSync } from "./util/Syncable.js";
@@ -124,7 +124,7 @@ function createHandler({
124
124
  if (typeof location !== "string")
125
125
  return new Response("Not found", { status: 404 });
126
126
  const previewSource = typeof previewUrl === "string" && previewUrl ? new URL(previewUrl, request.url).href : void 0;
127
- async function proxyMedia(source2, cacheControl, isAllowed) {
127
+ async function proxyMedia(source2, cacheControl) {
128
128
  const previewEntryId = uploadPreviewEntryId(
129
129
  source2,
130
130
  context.handlerUrl
@@ -135,13 +135,12 @@ function createHandler({
135
135
  } else {
136
136
  response = await proxyMediaUrl(
137
137
  request,
138
- new URL(source2, request.url),
139
- isAllowed
138
+ new URL(source2, request.url)
140
139
  );
141
140
  }
142
141
  return mediaResponse(request, response, cacheControl);
143
142
  }
144
- if (!wasBuilt && previewSource) {
143
+ if (!context.isDev && !wasBuilt && previewSource) {
145
144
  if (proxy) return proxyMedia(previewSource, "private, no-store");
146
145
  return redirectFile(previewSource, "private, no-store");
147
146
  }
@@ -153,18 +152,10 @@ function createHandler({
153
152
  if (!source || source === requestedUrl)
154
153
  return new Response("Not found", { status: 404 });
155
154
  if (!proxy) return redirectFile(source, "public, max-age=60");
156
- const configuredBase = Config.baseUrl(
157
- cms.config,
158
- context.isDev ? "development" : "production"
159
- );
160
- const deliveryBase = configuredBase ?? context.handlerUrl;
161
- const sourceUrl = new URL(source, deliveryBase);
162
- const deliveryOrigin = new URL(deliveryBase).origin;
163
- const handlerPath = context.handlerUrl.pathname;
155
+ const deliveryBase = !context.isDev && Config.baseUrl(cms.config, "production") || context.handlerUrl;
164
156
  return proxyMedia(
165
- sourceUrl.href,
166
- "public, max-age=60",
167
- (url2) => url2.origin === deliveryOrigin && url2.pathname !== handlerPath && !url2.pathname.startsWith(`${handlerPath}/`)
157
+ new URL(source, deliveryBase).href,
158
+ "public, max-age=60"
168
159
  );
169
160
  }
170
161
  const action = params.get("action");
@@ -315,23 +306,6 @@ function createHandler({
315
306
  }
316
307
  return Response.json({ sha });
317
308
  }
318
- if (action === HandleAction.Commit && request.method === "POST") {
319
- if (!context.isDev)
320
- throw new HttpError(400, "Commits are only accepted in development");
321
- const developmentKey = request.headers.get(developmentKeyHeader);
322
- if (!context.apiKey || developmentKey !== context.apiKey)
323
- throw new HttpError(401, "Invalid development commit credentials");
324
- const user = expectUser();
325
- expectJson();
326
- const commit = {
327
- ...await body,
328
- user: user.claims
329
- };
330
- let { sha } = await cnx.write(commit);
331
- if (sha === commit.intoSha) await local.write(commit);
332
- else sha = await local.syncWith(cnx);
333
- return Response.json({ sha });
334
- }
335
309
  if (action === HandleAction.History && request.method === "GET") {
336
310
  expectUser();
337
311
  expectJson();
@@ -347,6 +321,11 @@ function createHandler({
347
321
  const tree = await local.getTreeIfDifferent(sha);
348
322
  return compressResponse(request, Response.json(tree ?? null));
349
323
  }
324
+ if (action === HandleAction.Sha && request.method === "GET") {
325
+ expectJson();
326
+ await syncForRead(cnx);
327
+ return Response.json(await local.sha);
328
+ }
350
329
  if (action === HandleAction.Blob && request.method === "POST") {
351
330
  const { shas } = object({ shas: array(string) })(await body);
352
331
  await periodicSync(cnx);
@@ -452,8 +431,6 @@ function uploadPreviewEntryId(previewSource, handlerUrl) {
452
431
  return previewUrl.searchParams.get("entryId") ?? void 0;
453
432
  }
454
433
  function mediaResponse(request, upstream, cacheControl) {
455
- if (isRedirectStatus(upstream.status))
456
- return new Response("Media backend returned a redirect", { status: 502 });
457
434
  const responseHeaders = new Headers({
458
435
  "cache-control": upstream.ok || upstream.status === 304 ? cacheControl : "no-store"
459
436
  });
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  driver_exports
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";
3
+ } from "../../chunks/chunk-QJGGYF6E.js";
4
+ import "../../chunks/chunk-QSN6RH6X.js";
5
+ import "../../chunks/chunk-ETWOY4AL.js";
6
+ import "../../chunks/chunk-66YZ47TY.js";
7
+ import "../../chunks/chunk-AIU6CMVT.js";
8
8
  import "../../chunks/chunk-N47Y62CI.js";
9
9
  import "../../chunks/chunk-QBPYWU6C.js";
10
10
  import "../../chunks/chunk-2BJ2IFQM.js";
11
11
  import "../../chunks/chunk-XCZXR3C2.js";
12
- import "../../chunks/chunk-TFMUSWGG.js";
12
+ import "../../chunks/chunk-MOWR65LM.js";
13
13
  import "../../chunks/chunk-76VMZTLN.js";
14
14
  import "../../chunks/chunk-2PIFHEYR.js";
15
15
  import "../../chunks/chunk-K62JP6HR.js";
@@ -7,7 +7,7 @@ import {
7
7
  integer,
8
8
  text,
9
9
  varchar
10
- } from "../../chunks/chunk-K7LHQXI4.js";
10
+ } from "../../chunks/chunk-ASYKC6IE.js";
11
11
  import {
12
12
  Builder
13
13
  } from "../../chunks/chunk-2BJ2IFQM.js";
@@ -16,7 +16,7 @@ import {
16
16
  } from "../../chunks/chunk-XCZXR3C2.js";
17
17
  import {
18
18
  table
19
- } from "../../chunks/chunk-TFMUSWGG.js";
19
+ } from "../../chunks/chunk-MOWR65LM.js";
20
20
  import "../../chunks/chunk-76VMZTLN.js";
21
21
  import "../../chunks/chunk-2PIFHEYR.js";
22
22
  import "../../chunks/chunk-K62JP6HR.js";
@@ -1,3 +1,2 @@
1
- import { type Request, Response } from '@alinea/iso';
2
- export declare function proxyMediaUrl(request: Request, source: URL, isAllowed?: (url: URL) => boolean): Promise<Response>;
3
- export declare function isRedirectStatus(status: number): boolean;
1
+ import { type Request } from '@alinea/iso';
2
+ export declare function proxyMediaUrl(request: Request, source: URL): Promise<Response>;
@@ -1,8 +1,8 @@
1
1
  import "../../chunks/chunk-CQ52GEHY.js";
2
2
 
3
3
  // src/backend/api/ProxyMedia.ts
4
- import { Headers, Response } from "@alinea/iso";
5
- async function proxyMediaUrl(request, source, isAllowed = (url) => url.origin === source.origin) {
4
+ import { Headers } from "@alinea/iso";
5
+ function proxyMediaUrl(request, source) {
6
6
  const headers = new Headers();
7
7
  for (const name of [
8
8
  "range",
@@ -13,27 +13,12 @@ async function proxyMediaUrl(request, source, isAllowed = (url) => url.origin ==
13
13
  const value = request.headers.get(name);
14
14
  if (value) headers.set(name, value);
15
15
  }
16
- let current = source;
17
- for (let redirects = 0; ; redirects++) {
18
- if (!isAllowed(current))
19
- return new Response("Invalid media source", { status: 502 });
20
- const response = await fetch(current, {
21
- method: request.method,
22
- headers,
23
- redirect: "manual",
24
- signal: request.signal
25
- });
26
- const location = response.headers.get("location");
27
- if (!isRedirectStatus(response.status) || !location) return response;
28
- if (redirects === 3)
29
- return new Response("Too many media redirects", { status: 502 });
30
- current = new URL(location, current);
31
- }
32
- }
33
- function isRedirectStatus(status) {
34
- return status === 301 || status === 302 || status === 303 || status === 307 || status === 308;
16
+ return fetch(source, {
17
+ method: request.method,
18
+ headers,
19
+ signal: request.signal
20
+ });
35
21
  }
36
22
  export {
37
- isRedirectStatus,
38
23
  proxyMediaUrl
39
24
  };
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  driver_exports
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";
3
+ } from "../../chunks/chunk-QJGGYF6E.js";
4
+ import "../../chunks/chunk-QSN6RH6X.js";
5
+ import "../../chunks/chunk-ETWOY4AL.js";
6
+ import "../../chunks/chunk-66YZ47TY.js";
7
+ import "../../chunks/chunk-AIU6CMVT.js";
8
8
  import "../../chunks/chunk-N47Y62CI.js";
9
9
  import "../../chunks/chunk-QBPYWU6C.js";
10
10
  import "../../chunks/chunk-2BJ2IFQM.js";
11
11
  import "../../chunks/chunk-XCZXR3C2.js";
12
- import "../../chunks/chunk-TFMUSWGG.js";
12
+ import "../../chunks/chunk-MOWR65LM.js";
13
13
  import "../../chunks/chunk-76VMZTLN.js";
14
14
  import "../../chunks/chunk-2PIFHEYR.js";
15
15
  import "../../chunks/chunk-K62JP6HR.js";
@@ -1,5 +1,8 @@
1
1
  import type { Config } from 'alinea/core/Config';
2
+ import type { DatabaseHandle } from 'alinea/database/driver/DatabaseHandle';
2
3
  import { EntryStore } from 'alinea/database/EntryStore';
3
- import type { Database } from 'rado';
4
- /** Add one writable, connection-local layer over a generated database. */
5
- export declare function createGeneratedDatabase(config: Config, db: Database): Promise<EntryStore>;
4
+ /**
5
+ * Serve a generated database from a connection that keeps its writes in
6
+ * memory, so syncs and commits never reach the generated file.
7
+ */
8
+ export declare function createGeneratedDatabase(config: Config, { database: db, fork, driver }: DatabaseHandle): Promise<EntryStore>;
@@ -1,28 +1,30 @@
1
1
  import "../../chunks/chunk-CQ52GEHY.js";
2
2
 
3
3
  // src/backend/store/GeneratedDatabase.ts
4
+ import { DatabaseSource } from "alinea/database/DatabaseSource";
4
5
  import { assertReadableData } from "alinea/database/entry/EntryData";
5
6
  import { EntryDatabase } from "alinea/database/EntryDatabase";
6
7
  import { EntryStore } from "alinea/database/EntryStore";
7
- async function createGeneratedDatabase(config, db) {
8
+ async function createGeneratedDatabase(config, { database: db, fork, driver }) {
8
9
  let initialTree;
9
- const base = new EntryDatabase(config, db, {
10
+ const database = new EntryDatabase(config, db, {
11
+ fork,
10
12
  includedAtBuild(filePath) {
11
13
  return initialTree?.has(filePath) ?? false;
12
- }
14
+ },
15
+ // Nothing reopens the in-memory writes: skip storing the synced tree.
16
+ recordsTree: false
13
17
  });
14
18
  try {
15
19
  await assertReadableData(db);
16
- initialTree = await base.getTree();
17
- const overlay = await base.createOverlay();
18
- return new EntryStore(config, overlay.database, overlay.source, {
19
- close: async () => {
20
- await overlay.close();
21
- await base.close();
22
- }
20
+ initialTree = await database.getTree();
21
+ return new EntryStore(config, database, new DatabaseSource(database), {
22
+ ownsDatabase: true,
23
+ sourceFollowsDatabase: true,
24
+ driver
23
25
  });
24
26
  } catch (error) {
25
- await base.close();
27
+ await database.close();
26
28
  throw error;
27
29
  }
28
30
  }
@@ -1,4 +1,4 @@
1
1
  import type { Config } from 'alinea/core/Config';
2
2
  import type { DatabaseOptions } from 'rado';
3
- /** Open the traced generated file through the native SQLite driver. */
3
+ /** Open the traced generated file as an in-memory overlay. */
4
4
  export declare function generatedDatabase(config: Config, options?: DatabaseOptions): Promise<import("../../database/EntryStore.js").EntryStore>;
@@ -19,7 +19,7 @@ function generatedDatabase(config, options = {}) {
19
19
  store = generatedDatabasePath().then(
20
20
  (path) => runtimeDatabase({
21
21
  path,
22
- readonly: true,
22
+ overlay: true,
23
23
  logQuery: (query, durationMs) => loggers.get(config)?.(query, durationMs)
24
24
  })
25
25
  ).then((db) => createGeneratedDatabase(config, db));