alinea 2.0.0-preview.0 → 2.0.0-preview.2

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 (237) hide show
  1. package/dist/.init/content/pages/welcome.json +1 -1
  2. package/dist/LICENSES.md +134 -80
  3. package/dist/adapter/next/DevRemote.d.ts +3 -0
  4. package/dist/adapter/next/DevRemote.js +37 -0
  5. package/dist/adapter/next/ForwardCredentials.d.ts +1 -0
  6. package/dist/adapter/next/ForwardCredentials.js +17 -0
  7. package/dist/adapter/next/cms.js +86 -38
  8. package/dist/adapter/next/context.d.ts +1 -1
  9. package/dist/adapter/next/context.js +11 -3
  10. package/dist/adapter/next/handler.d.ts +2 -0
  11. package/dist/adapter/next/handler.js +23 -16
  12. package/dist/adapter/next/with-alinea.js +18 -16
  13. package/dist/backend/Handler.d.ts +14 -13
  14. package/dist/backend/Handler.js +70 -36
  15. package/dist/backend/resolver/ParsePreview.d.ts +8 -4
  16. package/dist/backend/resolver/ParsePreview.js +40 -43
  17. package/dist/backend/router/Router.d.ts +1 -0
  18. package/dist/backend/router/Router.js +21 -15
  19. package/dist/bundled.d.ts +369 -99
  20. package/dist/chunks/chunk-6UT4N4CO.js +919 -0
  21. package/dist/chunks/{chunk-LUBOGJCG.js → chunk-6V4TAD2N.js} +1 -1
  22. package/dist/chunks/{chunk-TL7ZW6BX.js → chunk-A3XXZBOQ.js} +2535 -2999
  23. package/dist/chunks/chunk-AC5ATYI3.js +1434 -0
  24. package/dist/chunks/{chunk-7ORQ7BYK.js → chunk-KMLLLZ6X.js} +202 -269
  25. package/dist/chunks/{chunk-IWN3T3FL.js → chunk-O7XWTMCB.js} +1 -1
  26. package/dist/chunks/{chunk-53DZYORR.js → chunk-PAYSVIYI.js} +76 -176
  27. package/dist/chunks/{chunk-YK3OSMDM.js → chunk-S4AU6SRS.js} +188 -158
  28. package/dist/chunks/{chunk-EQ3TDHYD.js → chunk-UVOEM4AH.js} +6 -3
  29. package/dist/chunks/{chunk-I7X64JTZ.js → chunk-VXZM6V4P.js} +4 -4
  30. package/dist/cli/Generate.js +3 -13
  31. package/dist/cli/Serve.js +7 -3
  32. package/dist/cli/bin.js +8 -5
  33. package/dist/cli/generate/CompileConfig.js +3 -2
  34. package/dist/cli/generate/CopyStaticFiles.js +2 -3
  35. package/dist/cli/generate/DevDB.d.ts +1 -1
  36. package/dist/cli/generate/DevDB.js +3 -5
  37. package/dist/cli/serve/CreateLocalServer.d.ts +1 -1
  38. package/dist/cli/serve/CreateLocalServer.js +3 -2
  39. package/dist/cli/serve/DevServer.d.ts +3 -2
  40. package/dist/cli/serve/DevServer.js +60 -3
  41. package/dist/cli/serve/ServeContext.d.ts +1 -0
  42. package/dist/cli/serve/StartServer.d.ts +1 -0
  43. package/dist/cli/serve/StartServer.js +6 -1
  44. package/dist/cli/util/EnsureLibs.js +2 -2
  45. package/dist/cli/util/EnsureNode.js +2 -2
  46. package/dist/cloud/CloudRemote.d.ts +2 -1
  47. package/dist/cloud/CloudRemote.js +3 -2
  48. package/dist/components/Breadcrumbs.js +8 -8
  49. package/dist/components/Button.js +6 -6
  50. package/dist/components/Calendar.js +11 -11
  51. package/dist/components/Checkbox.js +7 -7
  52. package/dist/components/CheckboxGroup.js +6 -6
  53. package/dist/components/ColorSwatch.js +6 -6
  54. package/dist/components/ColorSwatchPicker.js +6 -6
  55. package/dist/components/ComboBox.js +17 -17
  56. package/dist/components/DateField.js +9 -9
  57. package/dist/components/DatePicker.js +10 -10
  58. package/dist/components/DateRangePicker.js +14 -14
  59. package/dist/components/Dialog.js +6 -6
  60. package/dist/components/Disclosure.js +13 -13
  61. package/dist/components/DropZone.js +6 -6
  62. package/dist/components/Label.js +16 -16
  63. package/dist/components/Link.js +6 -6
  64. package/dist/components/List.js +34 -34
  65. package/dist/components/Menu.js +10 -10
  66. package/dist/components/Modal.js +8 -8
  67. package/dist/components/MultipleSelect.js +33 -33
  68. package/dist/components/NumberField.d.ts +2 -1
  69. package/dist/components/NumberField.js +21 -11
  70. package/dist/components/Popover.js +6 -6
  71. package/dist/components/ProgressCircle.js +10 -10
  72. package/dist/components/RadioGroup.js +6 -6
  73. package/dist/components/SearchField.js +11 -11
  74. package/dist/components/Select.js +13 -13
  75. package/dist/components/Surface.js +3 -3
  76. package/dist/components/Switch.js +6 -6
  77. package/dist/components/Table.js +13 -13
  78. package/dist/components/Tabs.js +8 -8
  79. package/dist/components/TagGroup.js +7 -7
  80. package/dist/components/TextField.js +10 -10
  81. package/dist/components/TimeField.js +6 -6
  82. package/dist/components/Toggle.js +6 -6
  83. package/dist/components/Toolbar.js +7 -7
  84. package/dist/components/Tooltip.js +10 -10
  85. package/dist/components/Tree.js +9 -9
  86. package/dist/core/BlobTransport.d.ts +5 -0
  87. package/dist/core/BlobTransport.js +79 -0
  88. package/dist/core/Client.d.ts +2 -1
  89. package/dist/core/Client.js +17 -12
  90. package/dist/core/Config.d.ts +4 -0
  91. package/dist/core/Config.js +6 -0
  92. package/dist/core/Connection.d.ts +4 -3
  93. package/dist/core/Connection.js +7 -0
  94. package/dist/core/Graph.d.ts +3 -4
  95. package/dist/core/ListRow.d.ts +2 -0
  96. package/dist/core/OrderBy.d.ts +7 -3
  97. package/dist/core/TextDoc.d.ts +11 -0
  98. package/dist/core/Trace.d.ts +8 -0
  99. package/dist/core/Trace.js +32 -0
  100. package/dist/core/Type.d.ts +7 -1
  101. package/dist/core/db/CommitRequest.d.ts +0 -3
  102. package/dist/core/db/CommitRequest.js +0 -9
  103. package/dist/core/db/EntryDB.js +1 -1
  104. package/dist/core/db/EntryIndex.d.ts +12 -2
  105. package/dist/core/db/EntryIndex.js +131 -22
  106. package/dist/core/db/EntryResolver.js +104 -29
  107. package/dist/core/db/EntryTransaction.d.ts +1 -2
  108. package/dist/core/db/EntryTransaction.js +29 -22
  109. package/dist/core/db/LocalDB.d.ts +5 -5
  110. package/dist/core/db/LocalDB.js +27 -12
  111. package/dist/core/field/RichTextField.d.ts +30 -3
  112. package/dist/core/field/RichTextField.js +124 -56
  113. package/dist/core/media/MediaAltField.d.ts +1 -0
  114. package/dist/core/media/MediaAltField.js +9 -1
  115. package/dist/core/media/MediaLocation.d.ts +5 -2
  116. package/dist/core/media/MediaLocation.js +6 -7
  117. package/dist/core/media/MediaTypes.js +11 -0
  118. package/dist/core/source/CombinedSource.d.ts +2 -2
  119. package/dist/core/source/CombinedSource.js +6 -3
  120. package/dist/core/source/FSSource.d.ts +4 -3
  121. package/dist/core/source/FSSource.js +59 -27
  122. package/dist/core/source/GithubSource.d.ts +2 -2
  123. package/dist/core/source/GithubSource.js +21 -9
  124. package/dist/core/source/IndexedDBSource.d.ts +2 -2
  125. package/dist/core/source/IndexedDBSource.js +3 -1
  126. package/dist/core/source/MemorySource.d.ts +2 -2
  127. package/dist/core/source/MemorySource.js +3 -1
  128. package/dist/core/source/OverlaySource.d.ts +12 -0
  129. package/dist/core/source/OverlaySource.js +50 -0
  130. package/dist/core/source/Source.d.ts +5 -2
  131. package/dist/core/source/Source.js +3 -3
  132. package/dist/core/util/Async.d.ts +8 -2
  133. package/dist/core/util/Async.js +67 -0
  134. package/dist/core/util/EntryFilenames.d.ts +2 -2
  135. package/dist/core/util/EntryFilenames.js +3 -3
  136. package/dist/dashboard/App.css +158 -0
  137. package/dist/dashboard/App.js +2 -2
  138. package/dist/dashboard/app/AccessDenied.js +3 -3
  139. package/dist/dashboard/app/ActivityStatus.js +15 -15
  140. package/dist/dashboard/app/AppShell.js +1 -1
  141. package/dist/dashboard/app/AuthView.js +11 -11
  142. package/dist/dashboard/app/CompactField.js +10 -10
  143. package/dist/dashboard/app/DashboardErrorBoundary.js +5 -5
  144. package/dist/dashboard/app/DashboardLayout.js +22 -19
  145. package/dist/dashboard/app/EntryHeader.js +12 -12
  146. package/dist/dashboard/app/EntryReferences.js +9 -9
  147. package/dist/dashboard/app/EntrySidebar.d.ts +1 -1
  148. package/dist/dashboard/app/EntrySidebar.js +17 -16
  149. package/dist/dashboard/app/EntrySidebarPreview.d.ts +1 -1
  150. package/dist/dashboard/app/EntrySidebarPreview.js +19 -14
  151. package/dist/dashboard/app/EntryTranslationBanner.js +7 -7
  152. package/dist/dashboard/app/Explorer.js +51 -43
  153. package/dist/dashboard/app/ExplorerCards.js +34 -34
  154. package/dist/dashboard/app/ExplorerFileCard.js +18 -18
  155. package/dist/dashboard/app/ExplorerList.js +13 -13
  156. package/dist/dashboard/app/ExplorerModal.js +3 -3
  157. package/dist/dashboard/app/ExplorerTable.js +76 -61
  158. package/dist/dashboard/app/ExternalLinkPicker.js +15 -4
  159. package/dist/dashboard/app/LinkPicker.js +8 -8
  160. package/dist/dashboard/app/LocaleMenu.js +12 -12
  161. package/dist/dashboard/app/SidebarLayout.d.ts +8 -0
  162. package/dist/dashboard/app/SidebarLayout.js +1169 -0
  163. package/dist/dashboard/app/SidebarTree.js +46 -46
  164. package/dist/dashboard/app/WorkspaceMenu.js +17 -17
  165. package/dist/dashboard/app/WorkspaceRoots.js +23 -23
  166. package/dist/dashboard/app/editor/FileEditor.d.ts +2 -1
  167. package/dist/dashboard/app/editor/FileEditor.js +41 -32
  168. package/dist/dashboard/app/editor/FilePreview.js +4 -4
  169. package/dist/dashboard/app/editor/MediaAltField.view.d.ts +1 -1
  170. package/dist/dashboard/app/editor/MediaAltField.view.js +6 -9
  171. package/dist/dashboard/app/modals/CreateEntry.js +4 -4
  172. package/dist/dashboard/app/pages/EntryPage.js +57 -31
  173. package/dist/dashboard/app/pages/UsersPage.js +33 -33
  174. package/dist/dashboard/app/ui/DashboardModal.js +23 -23
  175. package/dist/dashboard/app/ui/Rail.js +3 -3
  176. package/dist/dashboard/app/ui/Sidebar.js +2 -2
  177. package/dist/dashboard/atoms/auth.js +2 -0
  178. package/dist/dashboard/atoms/dashboard.d.ts +9 -0
  179. package/dist/dashboard/atoms/dashboard.js +17 -0
  180. package/dist/dashboard/atoms/editor.d.ts +7 -1
  181. package/dist/dashboard/atoms/editor.js +4 -1
  182. package/dist/dashboard/atoms/entry.d.ts +48 -2
  183. package/dist/dashboard/atoms/entry.js +222 -17
  184. package/dist/dashboard/atoms/explorer.js +4 -9
  185. package/dist/dashboard/atoms/preview.d.ts +3 -0
  186. package/dist/dashboard/atoms/preview.js +18 -1
  187. package/dist/dashboard/atoms/root.d.ts +4 -1
  188. package/dist/dashboard/atoms/root.js +96 -157
  189. package/dist/dashboard/hooks.d.ts +4 -2
  190. package/dist/dashboard/hooks.js +9 -5
  191. package/dist/dashboard/icons.d.ts +1 -0
  192. package/dist/dashboard/icons.js +10 -0
  193. package/dist/field/check/CheckField.view.js +2 -2
  194. package/dist/field/code/CodeField.view.js +12 -12
  195. package/dist/field/date/DateField.view.js +12 -2
  196. package/dist/field/link/FileLink.d.ts +2 -2
  197. package/dist/field/link/FileLink.js +5 -3
  198. package/dist/field/link/ImageLink.d.ts +1 -1
  199. package/dist/field/link/ImageLink.js +1 -1
  200. package/dist/field/link/Link.js +2 -2
  201. package/dist/field/link/LinkField.view.js +155 -128
  202. package/dist/field/list/ListField.view.js +22 -33
  203. package/dist/field/metadata/MetadataField.view.js +19 -19
  204. package/dist/field/number/NumberField.d.ts +2 -0
  205. package/dist/field/number/NumberField.view.js +4 -2
  206. package/dist/field/richtext/PickTextLink.d.ts +7 -0
  207. package/dist/field/richtext/PickTextLink.js +104 -2
  208. package/dist/field/richtext/ReferenceLink.d.ts +4 -1
  209. package/dist/field/richtext/ReferenceLink.js +18 -4
  210. package/dist/field/richtext/RichTextDocument.d.ts +7 -2
  211. package/dist/field/richtext/RichTextDocument.js +34 -5
  212. package/dist/field/richtext/RichTextExtensions.d.ts +3 -1
  213. package/dist/field/richtext/RichTextExtensions.js +2704 -7467
  214. package/dist/field/richtext/RichTextField.d.ts +4 -0
  215. package/dist/field/richtext/RichTextField.story.d.ts +4 -0
  216. package/dist/field/richtext/RichTextField.view.js +43 -20
  217. package/dist/field/richtext/RichTextInsertMenu.js +281 -495
  218. package/dist/field/richtext/RichTextToolbar.d.ts +5 -2
  219. package/dist/field/richtext/RichTextToolbar.js +38 -3
  220. package/dist/field/richtext/Toolbar.d.ts +19 -1
  221. package/dist/field/richtext/Toolbar.js +18 -13
  222. package/dist/field/richtext/extensions/Anchor.js +1 -1
  223. package/dist/field/richtext/extensions/Link.js +1 -1
  224. package/dist/field/richtext/extensions/Small.js +1 -1
  225. package/dist/field/select/SelectField.view.js +8 -6
  226. package/dist/index.css +227 -16
  227. package/dist/next.cjs +18 -16
  228. package/dist/next.d.ts +2 -1
  229. package/dist/next.edge.d.ts +2 -1
  230. package/dist/picker/entry/EntryPicker.js +9 -35
  231. package/dist/preview/PreviewPayload.js +35 -250
  232. package/dist/ui/RichText.d.ts +1 -0
  233. package/dist/ui/RichText.js +29 -2
  234. package/package.json +6 -3
  235. package/dist/cli/util/ExternalPlugin.d.ts +0 -2
  236. package/dist/cli/util/ExternalPlugin.js +0 -919
  237. package/dist/chunks/{chunk-JFROOUG6.js → chunk-NIVGVRDS.js} +17 -17
package/dist/bundled.d.ts CHANGED
@@ -75,7 +75,21 @@ declare module 'alinea/adapter/next/context' {
75
75
 
76
76
  import { Config } from 'alinea/core/Config';
77
77
  import type { RequestContext } from 'alinea/core/Connection';
78
- export function requestContext(config: Config): Promise<RequestContext>;
78
+ export function requestContext(config: Config, request?: Request): Promise<RequestContext>;
79
+
80
+ }
81
+
82
+ declare module 'alinea/adapter/next/DevRemote' {
83
+
84
+ import type { RemoteConnection, RequestContext } from 'alinea/core/Connection';
85
+ import type { Config } from 'alinea/core/Config';
86
+ export function createDevRemote(context: RequestContext, config: Config): RemoteConnection;
87
+
88
+ }
89
+
90
+ declare module 'alinea/adapter/next/ForwardCredentials' {
91
+
92
+ export function forwardDevelopmentCredentials(request: Request | undefined, apiKey: string, init?: RequestInit): RequestInit;
79
93
 
80
94
  }
81
95
 
@@ -83,6 +97,7 @@ declare module 'alinea/adapter/next/handler' {
83
97
 
84
98
  import { type BackendFactory, type BackendOptions } from 'alinea/backend/api/CreateBackend';
85
99
  import { type HandlerHooks } from 'alinea/backend/Handler';
100
+ import { Config } from 'alinea/core/Config';
86
101
  import { NextCMS } from 'alinea/adapter/next/cms';
87
102
  type Handler = (request: Request) => Promise<Response>;
88
103
  export interface NextHandlerOptions extends HandlerHooks {
@@ -90,6 +105,7 @@ declare module 'alinea/adapter/next/handler' {
90
105
  backend?: BackendFactory | BackendOptions;
91
106
  }
92
107
  export function createHandler(input: NextCMS | NextHandlerOptions): Handler;
108
+ export function handlerPathname(config: Config, requestUrl: URL): string;
93
109
  export {};
94
110
 
95
111
  }
@@ -465,30 +481,31 @@ declare module 'alinea/backend/HandleAction' {
465
481
 
466
482
  declare module 'alinea/backend/Handler' {
467
483
 
468
- import type { Entry } from 'alinea/core';
469
484
  import type { CMS } from 'alinea/core/CMS';
470
- import type { RemoteConnection, RequestContext } from 'alinea/core/Connection';
471
- import type { LocalDB } from 'alinea/core/db/LocalDB';
485
+ import type { AuthedContext, RemoteConnection, RequestContext } from 'alinea/core/Connection';
486
+ import { LocalDB } from 'alinea/core/db/LocalDB';
487
+ import type { Mutation } from 'alinea/core/db/Mutation';
472
488
  export interface Handler {
473
489
  (request: Request, context: RequestContext): Promise<Response>;
474
490
  }
475
- export type HookResponse<T = void> = void | T | Promise<T> | Promise<void>;
491
+ export type HookResponse<T = void> = void | T | Promise<void | T>;
492
+ export interface BeforeCommitContext {
493
+ mutations: ReadonlyArray<Mutation>;
494
+ }
495
+ export interface AfterCommitContext extends BeforeCommitContext {
496
+ sha: string;
497
+ }
476
498
  export interface HandlerHooks {
477
- beforeCreate?(entry: Entry): HookResponse<Entry>;
478
- afterCreate?(entry: Entry): HookResponse;
479
- beforeUpdate?(entry: Entry): HookResponse<Entry>;
480
- afterUpdate?(entry: Entry): HookResponse;
481
- beforeArchive?(entryId: string): HookResponse;
482
- afterArchive?(entryId: string): HookResponse;
483
- beforeRemove?(entryId: string): HookResponse;
484
- afterRemove?(entryId: string): HookResponse;
499
+ beforeCommit?(context: BeforeCommitContext): HookResponse<ReadonlyArray<Mutation>>;
500
+ afterCommit?(context: AfterCommitContext): HookResponse;
485
501
  }
486
502
  export interface HandlerOptions extends HandlerHooks {
487
503
  cms: CMS;
488
504
  db: LocalDB | Promise<LocalDB>;
489
505
  remote?: (context: RequestContext) => RemoteConnection;
506
+ forwardMutations?(request: Request, context: AuthedContext): Promise<Response | undefined>;
490
507
  }
491
- export function createHandler({ cms, remote, db, ...hooks }: HandlerOptions): Handler;
508
+ export function createHandler({ cms, remote, db, forwardMutations, ...hooks }: HandlerOptions): Handler;
492
509
 
493
510
  }
494
511
 
@@ -523,10 +540,14 @@ declare module 'alinea/backend/Previews' {
523
540
  declare module 'alinea/backend/resolver/ParsePreview' {
524
541
 
525
542
  import type { LocalDB } from 'alinea/core/db/LocalDB';
526
- import type { PreviewRequest } from 'alinea/core/Preview';
527
- export function createPreviewParser(local: LocalDB): {
528
- parse(preview: PreviewRequest, sync: () => Promise<unknown>): Promise<PreviewRequest | undefined>;
529
- };
543
+ import { Entry } from 'alinea/core/Entry';
544
+ import type { PreviewRequest, PreviewUpdate } from 'alinea/core/Preview';
545
+ export interface DecodedEntryPreview {
546
+ entry: Entry;
547
+ }
548
+ export type DecodedPreviewRequest = PreviewUpdate | DecodedEntryPreview;
549
+ export function decodePreviewRequest(preview: PreviewRequest): Promise<DecodedPreviewRequest>;
550
+ export function applyPreview(local: LocalDB, preview: DecodedPreviewRequest): Promise<PreviewRequest | undefined>;
530
551
 
531
552
  }
532
553
 
@@ -688,6 +709,7 @@ declare module 'alinea/backend/router/Router' {
688
709
  function cookie(...cookies: Array<Cookie>): string;
689
710
  function compress(...routes: Array<Next<Request, Response | undefined>>): Route<Request, Response | undefined>;
690
711
  }
712
+ export function compressResponse(request: Request, response: Response): Response;
691
713
  export {};
692
714
 
693
715
  }
@@ -827,7 +849,7 @@ declare module 'alinea/cli/generate/DevDB' {
827
849
 
828
850
  import { Config } from 'alinea/core/Config';
829
851
  import type { UploadResponse } from 'alinea/core/Connection';
830
- import { type CommitRequest } from 'alinea/core/db/CommitRequest';
852
+ import type { CommitRequest } from 'alinea/core/db/CommitRequest';
831
853
  import { LocalDB } from 'alinea/core/db/LocalDB';
832
854
  import { CachedFSSource } from 'alinea/core/source/FSSource';
833
855
  export interface DevDBOptions {
@@ -931,7 +953,7 @@ declare module 'alinea/cli/serve/CreateLocalServer' {
931
953
  import type { User } from 'alinea/core/User';
932
954
  import { type Request, Response } from '@alinea/iso';
933
955
  import type { ServeContext } from 'alinea/cli/serve/ServeContext';
934
- export function createLocalServer({ cmd, configLocation, rootDir, staticDir, alineaDev, buildOptions, production, liveReload, buildId }: ServeContext, cms: CMS, handleApi: Handler, user: User): {
956
+ export function createLocalServer({ cmd, configLocation, rootDir, staticDir, alineaDev, buildOptions, production, liveReload, buildId, apiKey }: ServeContext, cms: CMS, handleApi: Handler, user: User): {
935
957
  close(): void;
936
958
  handle(input: Request): Promise<Response>;
937
959
  };
@@ -940,8 +962,8 @@ declare module 'alinea/cli/serve/CreateLocalServer' {
940
962
 
941
963
  declare module 'alinea/cli/serve/DevServer' {
942
964
 
943
- import type { Request, Response } from '@alinea/iso';
944
- import type { Config } from 'alinea/core/Config';
965
+ import { Config } from 'alinea/core/Config';
966
+ import { Request, type Response } from '@alinea/iso';
945
967
  import type { BuildOptions } from 'esbuild';
946
968
  export interface CreateDevServerOptions {
947
969
  cmd: 'dev' | 'build';
@@ -951,6 +973,7 @@ declare module 'alinea/cli/serve/DevServer' {
951
973
  buildOptions?: BuildOptions;
952
974
  alineaDev?: boolean;
953
975
  production?: boolean;
976
+ apiKey?: string;
954
977
  dashboardUrl: Promise<string>;
955
978
  onAfterGenerate?: (message: string, config: Config) => void;
956
979
  }
@@ -1032,6 +1055,7 @@ declare module 'alinea/cli/serve/ServeContext' {
1032
1055
  production: boolean;
1033
1056
  liveReload: LiveReload;
1034
1057
  buildId: string;
1058
+ apiKey: string;
1035
1059
  }
1036
1060
 
1037
1061
  }
@@ -1044,6 +1068,7 @@ declare module 'alinea/cli/serve/StartServer' {
1044
1068
  respondWith(response: Response): Promise<void>;
1045
1069
  }
1046
1070
  export interface Server {
1071
+ hostname: string;
1047
1072
  port: number;
1048
1073
  serve(abortController?: AbortController): AsyncIterable<RequestEvent>;
1049
1074
  close(): void;
@@ -1109,13 +1134,6 @@ declare module 'alinea/cli/util/EnsureNode' {
1109
1134
 
1110
1135
  }
1111
1136
 
1112
- declare module 'alinea/cli/util/ExternalPlugin' {
1113
-
1114
- import type { Plugin } from 'esbuild';
1115
- export function externalPlugin(cwd: string): Plugin;
1116
-
1117
- }
1118
-
1119
1137
  declare module 'alinea/cli/util/FindConfigFile' {
1120
1138
 
1121
1139
  export function findConfigFile(cwd: string): string | undefined;
@@ -1255,12 +1273,13 @@ declare module 'alinea/cloud/CloudRemote' {
1255
1273
  import { type Draft, type DraftKey } from 'alinea/core/Draft';
1256
1274
  import type { EntryRecord } from 'alinea/core/EntryRecord';
1257
1275
  import { ReadonlyTree } from 'alinea/core/source/Tree';
1276
+ import type { GetBlobsOptions } from 'alinea/core/source/Source';
1258
1277
  import type { User, UserInput } from 'alinea/core/User';
1259
1278
  export class CloudRemote extends OAuth2 implements RemoteConnection {
1260
1279
  #private;
1261
1280
  constructor(context: RequestContext, config: Config);
1262
1281
  getTreeIfDifferent(sha: string): Promise<ReadonlyTree | undefined>;
1263
- getBlobs(shas: Array<string>): AsyncGenerator<[sha: string, blob: Uint8Array]>;
1282
+ getBlobs(shas: ReadonlyArray<string>, options?: GetBlobsOptions): AsyncGenerator<[sha: string, blob: Uint8Array]>;
1264
1283
  write(request: CommitRequest): Promise<{
1265
1284
  sha: string;
1266
1285
  }>;
@@ -1734,8 +1753,9 @@ declare module 'alinea/components/NumberField' {
1734
1753
  import { type LabelSharedProps } from 'alinea/components/Label';
1735
1754
  export interface NumberFieldProps extends Omit<NumberFieldPrimitiveProps, 'children'>, LabelSharedProps {
1736
1755
  steppers?: boolean;
1756
+ placeholder?: string;
1737
1757
  }
1738
- export function NumberField({ steppers, ...props }: NumberFieldProps): import("react").JSX.Element;
1758
+ export function NumberField({ steppers, placeholder, ...props }: NumberFieldProps): import("react").JSX.Element;
1739
1759
 
1740
1760
  }
1741
1761
 
@@ -2024,6 +2044,16 @@ declare module 'alinea/core/Auth' {
2024
2044
 
2025
2045
  }
2026
2046
 
2047
+ declare module 'alinea/core/BlobTransport' {
2048
+
2049
+ import { ReadableStream } from '@alinea/iso';
2050
+ import type { GetBlobsOptions } from 'alinea/core/source/Source';
2051
+ export const BLOB_SEQUENCE_CONTENT_TYPE = "application/cbor-seq";
2052
+ export function encodeBlobSequence(blobs: AsyncIterable<[sha: string, blob: Uint8Array]>): ReadableStream<Uint8Array>;
2053
+ export function decodeBlobSequence(stream: ReadableStream<Uint8Array>, options?: GetBlobsOptions): AsyncGenerator<[sha: string, blob: Uint8Array]>;
2054
+
2055
+ }
2056
+
2027
2057
  declare module 'alinea/core/Client' {
2028
2058
 
2029
2059
  import { type AuthResult } from 'alinea/cloud/AuthResult';
@@ -2035,6 +2065,7 @@ declare module 'alinea/core/Client' {
2035
2065
  import type { EntryRecord } from 'alinea/core/EntryRecord';
2036
2066
  import type { AnyQueryResult, GraphQuery } from 'alinea/core/Graph';
2037
2067
  import { ReadonlyTree } from 'alinea/core/source/Tree';
2068
+ import type { GetBlobsOptions } from 'alinea/core/source/Source';
2038
2069
  import type { User, UserInput } from 'alinea/core/User';
2039
2070
  export type AuthenticateRequest = (request?: RequestInit) => RequestInit | undefined;
2040
2071
  export interface ClientOptions {
@@ -2065,7 +2096,7 @@ declare module 'alinea/core/Client' {
2065
2096
  revisions(file: string): Promise<Array<Revision>>;
2066
2097
  revisionData(file: string, revisionId: string): Promise<EntryRecord | undefined>;
2067
2098
  getTreeIfDifferent(sha: string): Promise<ReadonlyTree | undefined>;
2068
- getBlobs(shas: Array<string>): AsyncGenerator<[sha: string, blob: Uint8Array]>;
2099
+ getBlobs(shas: ReadonlyArray<string>, options?: GetBlobsOptions): AsyncGenerator<[sha: string, blob: Uint8Array]>;
2069
2100
  write(request: CommitRequest): Promise<{
2070
2101
  sha: string;
2071
2102
  }>;
@@ -2101,6 +2132,7 @@ declare module 'alinea/core/Config' {
2101
2132
  import { type Role } from 'alinea/core/Role';
2102
2133
  import { Root } from 'alinea/core/Root';
2103
2134
  import { Schema } from 'alinea/core/Schema';
2135
+ import type { Tracer } from 'alinea/core/Trace';
2104
2136
  import { Type } from 'alinea/core/Type';
2105
2137
  import { Workspace, type WorkspaceInternal } from 'alinea/core/Workspace';
2106
2138
  /** Configuration options */
@@ -2130,10 +2162,13 @@ declare module 'alinea/core/Config' {
2130
2162
  publicDir?: string;
2131
2163
  /** Filename of the generated dashboard, defaults to admin.html */
2132
2164
  dashboardFile?: string;
2165
+ /** Optional application-owned instrumentation for Alinea operations. */
2166
+ tracer?: Tracer;
2133
2167
  auth?: Auth.View;
2134
2168
  }
2135
2169
  export namespace Config {
2136
2170
  function baseUrl(config: Config, env?: string): string | undefined;
2171
+ function handlerUrl(config: Config): string;
2137
2172
  function adminPath(config: Config): string;
2138
2173
  function mainWorkspace(config: Config): WorkspaceInternal;
2139
2174
  function type(config: Config, name: string): Type | undefined;
@@ -2159,6 +2194,7 @@ declare module 'alinea/core/Connection' {
2159
2194
  import type { Draft, DraftKey } from 'alinea/core/Draft';
2160
2195
  import type { EntryRecord } from 'alinea/core/EntryRecord';
2161
2196
  import type { AnyQueryResult, GraphQuery } from 'alinea/core/Graph';
2197
+ import type { GetBlobsOptions } from 'alinea/core/source/Source';
2162
2198
  import type { ReadonlyTree } from 'alinea/core/source/Tree';
2163
2199
  import type { User, UserInput } from 'alinea/core/User';
2164
2200
  export interface AuthApi {
@@ -2197,7 +2233,7 @@ declare module 'alinea/core/Connection' {
2197
2233
  }
2198
2234
  export interface SyncApi {
2199
2235
  getTreeIfDifferent(sha: string): Promise<ReadonlyTree | undefined>;
2200
- getBlobs(shas: Array<string>): AsyncGenerator<[sha: string, blob: Uint8Array]>;
2236
+ getBlobs(shas: ReadonlyArray<string>, options?: GetBlobsOptions): AsyncIterable<[sha: string, blob: Uint8Array]>;
2201
2237
  }
2202
2238
  export interface CommitApi {
2203
2239
  write(request: CommitRequest): Promise<{
@@ -2223,9 +2259,9 @@ declare module 'alinea/core/Connection' {
2223
2259
  isDev: boolean;
2224
2260
  handlerUrl: URL;
2225
2261
  apiKey: string;
2226
- user?: User;
2227
- token?: string;
2262
+ applyAuth?(init?: RequestInit): RequestInit;
2228
2263
  }
2264
+ export const developmentKeyHeader = "x-alinea-dev-key";
2229
2265
  export interface AuthedContext extends RequestContext {
2230
2266
  user: User;
2231
2267
  token: string;
@@ -2265,7 +2301,6 @@ declare module 'alinea/core/Connection' {
2265
2301
  declare module 'alinea/core/db/CommitRequest' {
2266
2302
 
2267
2303
  import type { Change, ChangeFile, ChangesBatch } from 'alinea/core/source/Change';
2268
- import type { ReadonlyTree } from 'alinea/core/source/Tree';
2269
2304
  import type { User } from 'alinea/core/User';
2270
2305
  import type { RemoveFileMutation, UploadFileMutation } from 'alinea/core/db/Mutation';
2271
2306
  export interface AddContent extends ChangeFile {
@@ -2283,10 +2318,8 @@ declare module 'alinea/core/db/CommitRequest' {
2283
2318
  user?: User;
2284
2319
  fromSha: string;
2285
2320
  intoSha: string;
2286
- checks: Array<[path: string, sha: string]>;
2287
2321
  changes: Array<CommitChange>;
2288
2322
  }
2289
- export function checkCommit(tree: ReadonlyTree, request: CommitRequest): void;
2290
2323
 
2291
2324
  }
2292
2325
 
@@ -2344,12 +2377,20 @@ declare module 'alinea/core/db/EntryIndex' {
2344
2377
  language?(language: EntryLanguageNode): boolean;
2345
2378
  entry?(entry: Entry): boolean;
2346
2379
  }
2380
+ interface EntryNodeQuery {
2381
+ ids?: ReadonlyArray<string>;
2382
+ parentIds?: ReadonlyArray<string | null>;
2383
+ urls?: ReadonlyArray<string>;
2384
+ workspaces?: ReadonlyArray<string>;
2385
+ roots?: ReadonlyArray<string>;
2386
+ types?: ReadonlyArray<string>;
2387
+ }
2347
2388
  export function combineConditions(a: EntryCondition, b: EntryCondition): EntryCondition;
2348
2389
  interface EntryVersionData {
2349
2390
  id: string;
2350
2391
  type: string;
2351
2392
  index: string;
2352
- searchableText: string;
2393
+ searchableText?: string;
2353
2394
  title: string;
2354
2395
  data: Record<string, unknown>;
2355
2396
  seeded: string | null;
@@ -2417,6 +2458,7 @@ declare module 'alinea/core/db/EntryIndex' {
2417
2458
  nodes: Array<EntryNode>;
2418
2459
  constructor(config: Config, versionData: Map<string, EntryVersionData>, seeds: Map<string, Seed>);
2419
2460
  byId(id: string): EntryNode | undefined;
2461
+ candidateNodes(query: EntryNodeQuery): Array<EntryNode> | undefined;
2420
2462
  get config(): Config;
2421
2463
  byDir(dir: string): EntryNode | undefined;
2422
2464
  entryByFilePath(filePath: string): Entry | undefined;
@@ -2429,6 +2471,7 @@ declare module 'alinea/core/db/EntryIndex' {
2429
2471
  initialSync: ReadonlyTree | undefined;
2430
2472
  graph: EntryGraph;
2431
2473
  constructor(config: Config);
2474
+ clone(): EntryIndex;
2432
2475
  get sha(): string;
2433
2476
  filter(filter: EntryCondition): Iterable<Entry>;
2434
2477
  findFirst<T extends Record<string, unknown>>(filter: (entry: Entry) => boolean): Entry<T> | undefined;
@@ -2438,7 +2481,7 @@ declare module 'alinea/core/db/EntryIndex' {
2438
2481
  get references(): Promise<EntryReferenceIndex>;
2439
2482
  sync(source: Source): Promise<string>;
2440
2483
  syncWith(source: Source): Promise<string>;
2441
- indexChanges(batch: ChangesBatch): Promise<string>;
2484
+ indexChanges(batch: ChangesBatch, targetTree?: ReadonlyTree): Promise<string>;
2442
2485
  seed(source: Source): Promise<void>;
2443
2486
  byId(id: string): EntryNode | undefined;
2444
2487
  fix(source: Source): Promise<void>;
@@ -2626,12 +2669,11 @@ declare module 'alinea/core/db/EntryTransaction' {
2626
2669
  removeFile(mutation: Op<RemoveFileMutation>): this;
2627
2670
  uploadFile(mutation: Op<UploadFileMutation>): this;
2628
2671
  description(): string;
2629
- apply(mutations: Array<Mutation>): void;
2672
+ apply(mutations: ReadonlyArray<Mutation>): Promise<void>;
2630
2673
  toRequest(): Promise<{
2631
2674
  fromSha: string;
2632
2675
  intoSha: string;
2633
2676
  description: string;
2634
- checks: [path: string, sha: string][];
2635
2677
  changes: CommitChange[];
2636
2678
  }>;
2637
2679
  }
@@ -2702,7 +2744,8 @@ declare module 'alinea/core/db/LocalDB' {
2702
2744
  import type { AnyQueryResult, GraphQuery } from 'alinea/core/Graph';
2703
2745
  import type { Policy } from 'alinea/core/Role';
2704
2746
  import type { ChangesBatch } from 'alinea/core/source/Change';
2705
- import type { Source } from 'alinea/core/source/Source';
2747
+ import type { GetBlobsOptions } from 'alinea/core/source/Source';
2748
+ import { type Source } from 'alinea/core/source/Source';
2706
2749
  import { type CommitRequest } from 'alinea/core/db/CommitRequest';
2707
2750
  import { EntryIndex } from 'alinea/core/db/EntryIndex';
2708
2751
  import type { EntryReferenceQuery, EntryReferenceResult } from 'alinea/core/db/EntryReference';
@@ -2713,22 +2756,21 @@ declare module 'alinea/core/db/LocalDB' {
2713
2756
  config: Config;
2714
2757
  index: EntryIndex;
2715
2758
  source: Source;
2716
- constructor(config: Config, source?: Source);
2759
+ constructor(config: Config, source?: Source, index?: EntryIndex);
2717
2760
  resolve<Query extends GraphQuery>(query: Query): Promise<AnyQueryResult<Query>>;
2718
2761
  referencesTo(query: EntryReferenceQuery): Promise<EntryReferenceResult>;
2719
2762
  get sha(): string;
2720
2763
  indexChanges(batch: ChangesBatch): Promise<string>;
2721
2764
  applyChanges(batch: ChangesBatch): Promise<void>;
2722
2765
  getTreeIfDifferent(sha: string): Promise<import("alinea/core/source/Tree").ReadonlyTree | undefined>;
2723
- getBlobs(shas: Array<string>): AsyncGenerator<[sha: string, blob: Uint8Array<ArrayBufferLike>], any, any>;
2766
+ getBlobs(shas: ReadonlyArray<string>, options?: GetBlobsOptions): AsyncIterable<[sha: string, blob: Uint8Array<ArrayBufferLike>]>;
2724
2767
  sync(): Promise<string>;
2725
2768
  syncWith(remote: SyncApi): Promise<string>;
2726
2769
  logEntries(): Promise<void>;
2727
- request(mutations: Array<Mutation>, policy?: Policy): Promise<{
2770
+ request(mutations: ReadonlyArray<Mutation>, policy?: Policy): Promise<{
2728
2771
  fromSha: string;
2729
2772
  intoSha: string;
2730
2773
  description: string;
2731
- checks: [path: string, sha: string][];
2732
2774
  changes: import("alinea/core/db/CommitRequest").CommitChange[];
2733
2775
  }>;
2734
2776
  mutate(mutations: Array<Mutation>): Promise<{
@@ -3406,7 +3448,7 @@ declare module 'alinea/core/field/RichTextField' {
3406
3448
  import { Field, type FieldMeta, type FieldOptions } from 'alinea/core/Field';
3407
3449
  import type { InferStoredValue } from 'alinea/core/Infer';
3408
3450
  import { Schema } from 'alinea/core/Schema';
3409
- import { type TextDoc } from 'alinea/core/TextDoc';
3451
+ import { Mark, type ElementNode, type TextDoc } from 'alinea/core/TextDoc';
3410
3452
  export type RichTextMutator<R> = {
3411
3453
  insert: (id: string, block: string) => void;
3412
3454
  };
@@ -3420,10 +3462,37 @@ declare module 'alinea/core/field/RichTextField' {
3420
3462
  private doc;
3421
3463
  constructor(doc?: TextDoc<Blocks>);
3422
3464
  add<Key extends keyof Blocks>(type: Key, block: RichTextBlockInput<Blocks, Key>): this;
3423
- addHtml(html: string): this;
3465
+ addHtml(html: string, options?: ParseHTMLSyncOptions): this;
3466
+ addHtmlAsync(html: string, options?: ParseHTMLAsyncOptions): Promise<this>;
3424
3467
  value(): TextDoc<Blocks>;
3425
3468
  }
3426
- export function parseHTML(html: string): TextDoc<any>;
3469
+ export interface ParseHTMLTagHandler {
3470
+ (attributes: Record<string, string>): ElementNode | undefined;
3471
+ }
3472
+ export interface ParseHTMLMarkHandler {
3473
+ (attributes: Record<string, string>): Mark | undefined;
3474
+ }
3475
+ export interface ParseHTMLAsyncTagHandler {
3476
+ (attributes: Record<string, string>): ElementNode | undefined | PromiseLike<ElementNode | undefined>;
3477
+ }
3478
+ export interface ParseHTMLAsyncMarkHandler {
3479
+ (attributes: Record<string, string>): Mark | undefined | PromiseLike<Mark | undefined>;
3480
+ }
3481
+ export interface ParseHTMLSyncOptions {
3482
+ tags?: Record<string, ParseHTMLTagHandler>;
3483
+ marks?: Record<string, ParseHTMLMarkHandler>;
3484
+ }
3485
+ export interface ParseHTMLAsyncOptions {
3486
+ tags?: Record<string, ParseHTMLAsyncTagHandler>;
3487
+ marks?: Record<string, ParseHTMLAsyncMarkHandler>;
3488
+ }
3489
+ /**
3490
+ * Parse HTML using handlers that may perform asynchronous work, such as
3491
+ * importing remote images into a media directory.
3492
+ */
3493
+ export function parseHTMLAsync(html: string, options?: ParseHTMLAsyncOptions): Promise<TextDoc>;
3494
+ /** Parse HTML synchronously. Async handlers are only supported by parseHTMLAsync. */
3495
+ export function parseHTML(html: string, options?: ParseHTMLSyncOptions): TextDoc;
3427
3496
 
3428
3497
  }
3429
3498
 
@@ -3494,6 +3563,7 @@ declare module 'alinea/core/Graph' {
3494
3563
  import type { Condition, Filter } from 'alinea/core/Filter';
3495
3564
  import type { Infer, StoredRow } from 'alinea/core/Infer';
3496
3565
  import type { HasField } from 'alinea/core/Internal';
3566
+ import type { OrderBy } from 'alinea/core/OrderBy';
3497
3567
  import type { Page } from 'alinea/core/Page';
3498
3568
  import type { PreviewRequest } from 'alinea/core/Preview';
3499
3569
  import type { Type } from 'alinea/core/Type';
@@ -3541,11 +3611,9 @@ declare module 'alinea/core/Graph' {
3541
3611
  }
3542
3612
  export type Projection = SelectContent | SelectObject;
3543
3613
  export type InferProjection<Selection> = InferSelection<Selection>;
3544
- export interface Order {
3545
- asc?: Expr<any>;
3546
- desc?: Expr<any>;
3614
+ export type Order = OrderBy & {
3547
3615
  caseSensitive?: boolean;
3548
- }
3616
+ };
3549
3617
  type InferSelection<Selection> = Selection extends GraphQuery & Edge ? Expand<AnyQueryResult<Selection>> : Selection extends Expr<infer V> ? V : {
3550
3618
  [K in keyof Selection]: Selection[K] extends Type<infer V> ? Type.Infer<V> : InferSelection<Selection[K]>;
3551
3619
  };
@@ -3807,6 +3875,8 @@ declare module 'alinea/core/ListRow' {
3807
3875
  _id: string;
3808
3876
  _type: string;
3809
3877
  _index: string;
3878
+ _anchor?: string;
3879
+ _label?: string;
3810
3880
  }
3811
3881
  export namespace ListRow {
3812
3882
  const id = "_id";
@@ -3859,6 +3929,7 @@ declare module 'alinea/core/media/MediaAltField' {
3859
3929
  export class MediaAltField extends ScalarField<MediaAltValue, MediaAltOptions> {
3860
3930
  }
3861
3931
  export function mediaAlt(label: string, options?: WithoutLabel<MediaAltOptions>): MediaAltField;
3932
+ export function mediaAltText(value: MediaAltValue, locale?: string): string;
3862
3933
 
3863
3934
  }
3864
3935
 
@@ -3882,10 +3953,13 @@ declare module 'alinea/core/media/MediaLocation' {
3882
3953
  (meta: MediaUrlMeta): string;
3883
3954
  }
3884
3955
  export interface MediaPublicUrlMeta extends Omit<MediaUrlMeta, 'parentPaths'> {
3885
- entryUrl: string;
3956
+ /** @deprecated Pass parentPaths directly when available. */
3957
+ entryUrl?: string;
3958
+ parentPaths?: Array<string>;
3886
3959
  }
3887
3960
  export interface MediaEntryUrlMeta {
3888
- entryUrl: string;
3961
+ defaultUrl: string;
3962
+ parentPaths: Array<string>;
3889
3963
  path: string;
3890
3964
  workspace: string;
3891
3965
  root: string;
@@ -4024,11 +4098,15 @@ declare module 'alinea/core/media/UploadLimits' {
4024
4098
  declare module 'alinea/core/OrderBy' {
4025
4099
 
4026
4100
  import type { Expr } from 'alinea/core/Expr';
4027
- export type OrderBy = {
4101
+ export interface AscendingOrder {
4028
4102
  asc: Expr<any>;
4029
- } | {
4103
+ desc?: never;
4104
+ }
4105
+ export interface DescendingOrder {
4106
+ asc?: never;
4030
4107
  desc: Expr<any>;
4031
- };
4108
+ }
4109
+ export type OrderBy = AscendingOrder | DescendingOrder;
4032
4110
 
4033
4111
  }
4034
4112
 
@@ -4525,14 +4603,14 @@ declare module 'alinea/core/source/Change' {
4525
4603
  declare module 'alinea/core/source/CombinedSource' {
4526
4604
 
4527
4605
  import type { ChangesBatch } from 'alinea/core/source/Change';
4528
- import type { Source } from 'alinea/core/source/Source';
4606
+ import type { GetBlobsOptions, Source } from 'alinea/core/source/Source';
4529
4607
  import { ReadonlyTree } from 'alinea/core/source/Tree';
4530
4608
  export class CombinedSource implements Source {
4531
4609
  #private;
4532
4610
  constructor(sources: Record<string, Source>);
4533
4611
  getTree(): Promise<ReadonlyTree>;
4534
4612
  getTreeIfDifferent(sha: string): Promise<ReadonlyTree | undefined>;
4535
- getBlobs(shas: Array<string>): AsyncGenerator<[sha: string, blob: Uint8Array]>;
4613
+ getBlobs(shas: ReadonlyArray<string>, options?: GetBlobsOptions): AsyncGenerator<[sha: string, blob: Uint8Array]>;
4536
4614
  applyChanges(batch: ChangesBatch): Promise<void>;
4537
4615
  }
4538
4616
 
@@ -4558,7 +4636,7 @@ declare module 'alinea/core/source/FilePatch' {
4558
4636
  declare module 'alinea/core/source/FSSource' {
4559
4637
 
4560
4638
  import type { ChangesBatch } from 'alinea/core/source/Change';
4561
- import type { Source } from 'alinea/core/source/Source';
4639
+ import type { GetBlobsOptions, Source } from 'alinea/core/source/Source';
4562
4640
  import { ReadonlyTree, WriteableTree } from 'alinea/core/source/Tree';
4563
4641
  export class FSSource implements Source {
4564
4642
  #private;
@@ -4566,7 +4644,8 @@ declare module 'alinea/core/source/FSSource' {
4566
4644
  getTree(): Promise<ReadonlyTree>;
4567
4645
  getFile(current: ReadonlyTree, builder: WriteableTree, file: string): Promise<readonly [string, Uint8Array<ArrayBufferLike>] | undefined>;
4568
4646
  getTreeIfDifferent(sha: string): Promise<ReadonlyTree | undefined>;
4569
- getBlobs(shas: Array<string>): AsyncGenerator<[sha: string, blob: Uint8Array]>;
4647
+ getBlobs(shas: ReadonlyArray<string>, options?: GetBlobsOptions): AsyncGenerator<[sha: string, blob: Uint8Array]>;
4648
+ readBlob(sha: string, file: string, signal?: AbortSignal): Promise<[sha: string, blob: Uint8Array]>;
4570
4649
  applyChanges(batch: ChangesBatch): Promise<void>;
4571
4650
  }
4572
4651
  export class CachedFSSource extends FSSource {
@@ -4576,7 +4655,7 @@ declare module 'alinea/core/source/FSSource' {
4576
4655
  getTree(): Promise<ReadonlyTree>;
4577
4656
  applyChanges(batch: ChangesBatch): Promise<void>;
4578
4657
  getFile(current: ReadonlyTree, builder: WriteableTree, file: string): Promise<readonly [string, Uint8Array<ArrayBufferLike>] | undefined>;
4579
- getBlobs(shas: Array<string>): AsyncGenerator<[sha: string, blob: Uint8Array]>;
4658
+ getBlobs(shas: ReadonlyArray<string>, options?: GetBlobsOptions): AsyncGenerator<[sha: string, blob: Uint8Array]>;
4580
4659
  }
4581
4660
 
4582
4661
  }
@@ -4599,7 +4678,7 @@ declare module 'alinea/core/source/GitDelta' {
4599
4678
  declare module 'alinea/core/source/GithubSource' {
4600
4679
 
4601
4680
  import type { ChangesBatch } from 'alinea/core/source/Change';
4602
- import type { Source } from 'alinea/core/source/Source';
4681
+ import type { GetBlobsOptions, Source } from 'alinea/core/source/Source';
4603
4682
  import { ReadonlyTree } from 'alinea/core/source/Tree';
4604
4683
  export interface GithubSourceOptions {
4605
4684
  authToken: string;
@@ -4617,7 +4696,7 @@ declare module 'alinea/core/source/GithubSource' {
4617
4696
  getTree(): Promise<ReadonlyTree>;
4618
4697
  shaAt(ref: string): Promise<string>;
4619
4698
  getTreeIfDifferent(sha: string): Promise<ReadonlyTree | undefined>;
4620
- getBlobs(shas: Array<string>): AsyncGenerator<[sha: string, blob: Uint8Array]>;
4699
+ getBlobs(shas: ReadonlyArray<string>, options?: GetBlobsOptions): AsyncGenerator<[sha: string, blob: Uint8Array]>;
4621
4700
  applyChanges(batch: ChangesBatch): Promise<void>;
4622
4701
  }
4623
4702
 
@@ -4652,14 +4731,14 @@ declare module 'alinea/core/source/GitUtils' {
4652
4731
  declare module 'alinea/core/source/IndexedDBSource' {
4653
4732
 
4654
4733
  import type { ChangesBatch } from 'alinea/core/source/Change';
4655
- import type { Source } from 'alinea/core/source/Source';
4734
+ import type { GetBlobsOptions, Source } from 'alinea/core/source/Source';
4656
4735
  import { ReadonlyTree } from 'alinea/core/source/Tree';
4657
4736
  export class IndexedDBSource implements Source {
4658
4737
  #private;
4659
4738
  constructor(indexedDB: IDBFactory, name: string);
4660
4739
  getTree(): Promise<ReadonlyTree>;
4661
4740
  getTreeIfDifferent(sha: string): Promise<ReadonlyTree | undefined>;
4662
- getBlobs(shas: Array<string>): AsyncGenerator<[sha: string, blob: Uint8Array]>;
4741
+ getBlobs(shas: ReadonlyArray<string>, options?: GetBlobsOptions): AsyncGenerator<[sha: string, blob: Uint8Array]>;
4663
4742
  applyChanges(batch: ChangesBatch): Promise<void>;
4664
4743
  }
4665
4744
 
@@ -4668,20 +4747,37 @@ declare module 'alinea/core/source/IndexedDBSource' {
4668
4747
  declare module 'alinea/core/source/MemorySource' {
4669
4748
 
4670
4749
  import type { ChangesBatch } from 'alinea/core/source/Change';
4671
- import type { Source } from 'alinea/core/source/Source';
4750
+ import type { GetBlobsOptions, Source } from 'alinea/core/source/Source';
4672
4751
  import { ReadonlyTree } from 'alinea/core/source/Tree';
4673
4752
  export class MemorySource implements Source {
4674
4753
  #private;
4675
4754
  constructor(tree?: ReadonlyTree, blobs?: Map<string, Uint8Array>);
4676
4755
  getTree(): Promise<ReadonlyTree>;
4677
4756
  getTreeIfDifferent(sha: string): Promise<ReadonlyTree | undefined>;
4678
- getBlobs(shas: Array<string>): AsyncGenerator<[sha: string, blob: Uint8Array]>;
4757
+ getBlobs(shas: ReadonlyArray<string>, options?: GetBlobsOptions): AsyncGenerator<[sha: string, blob: Uint8Array]>;
4679
4758
  addBlob(contents: Uint8Array): Promise<string>;
4680
4759
  applyChanges(batch: ChangesBatch): Promise<void>;
4681
4760
  }
4682
4761
 
4683
4762
  }
4684
4763
 
4764
+ declare module 'alinea/core/source/OverlaySource' {
4765
+
4766
+ import type { ChangesBatch } from 'alinea/core/source/Change';
4767
+ import type { GetBlobsOptions, Source } from 'alinea/core/source/Source';
4768
+ import type { ReadonlyTree } from 'alinea/core/source/Tree';
4769
+ export class OverlaySource implements Source {
4770
+ #private;
4771
+ constructor(source: Source, tree: ReadonlyTree);
4772
+ static create(source: Source): Promise<OverlaySource>;
4773
+ getTree(): Promise<ReadonlyTree>;
4774
+ getTreeIfDifferent(sha: string): Promise<ReadonlyTree | undefined>;
4775
+ getBlobs(shas: ReadonlyArray<string>, options?: GetBlobsOptions): AsyncGenerator<[sha: string, blob: Uint8Array]>;
4776
+ applyChanges(batch: ChangesBatch): Promise<void>;
4777
+ }
4778
+
4779
+ }
4780
+
4685
4781
  declare module 'alinea/core/source/ShaMismatchError' {
4686
4782
 
4687
4783
  import { HttpError } from 'alinea/core/HttpError';
@@ -4697,9 +4793,12 @@ declare module 'alinea/core/source/Source' {
4697
4793
 
4698
4794
  import type { ChangesBatch } from 'alinea/core/source/Change';
4699
4795
  import type { ReadonlyTree } from 'alinea/core/source/Tree';
4796
+ export interface GetBlobsOptions {
4797
+ signal?: AbortSignal;
4798
+ }
4700
4799
  export interface RemoteSource {
4701
4800
  getTreeIfDifferent(sha: string): Promise<ReadonlyTree | undefined>;
4702
- getBlobs(shas: Array<string>): AsyncGenerator<[sha: string, blob: Uint8Array]>;
4801
+ getBlobs(shas: ReadonlyArray<string>, options?: GetBlobsOptions): AsyncIterable<[sha: string, blob: Uint8Array]>;
4703
4802
  }
4704
4803
  export interface Source extends RemoteSource {
4705
4804
  getTree(): Promise<ReadonlyTree>;
@@ -4715,7 +4814,7 @@ declare module 'alinea/core/source/Source' {
4715
4814
  add(path: string, contents: Uint8Array): this;
4716
4815
  remove(path: string): this;
4717
4816
  rename(from: string, to: string): this;
4718
- compile(): Promise<{
4817
+ compile(previous?: ReadonlyTree): Promise<{
4719
4818
  from: ReadonlyTree;
4720
4819
  into: ReadonlyTree;
4721
4820
  changes: (import("alinea/core/source/Change").DeleteChange | {
@@ -4910,6 +5009,17 @@ declare module 'alinea/core/TextDoc' {
4910
5009
  export namespace ElementNode {
4911
5010
  const content = "content";
4912
5011
  }
5012
+ export interface ImageNode extends ElementNode {
5013
+ _type: 'image';
5014
+ _id?: string;
5015
+ _link?: 'image';
5016
+ _entry?: string;
5017
+ src?: string;
5018
+ alt?: string;
5019
+ title?: string;
5020
+ width?: number | string;
5021
+ height?: number | string;
5022
+ }
4913
5023
  export interface BlockNode {
4914
5024
  _id: string;
4915
5025
  _type: string;
@@ -4920,6 +5030,19 @@ declare module 'alinea/core/TextDoc' {
4920
5030
 
4921
5031
  }
4922
5032
 
5033
+ declare module 'alinea/core/Trace' {
5034
+
5035
+ import type { Config } from 'alinea/core/Config';
5036
+ export interface Tracer {
5037
+ <Result>(name: string, run: () => Promise<Result>): Promise<Result>;
5038
+ }
5039
+ export interface TraceSpan {
5040
+ <Result>(operation: () => Promise<Result>): Promise<Result>;
5041
+ }
5042
+ export function trace(config: Config, name: string): TraceSpan;
5043
+
5044
+ }
5045
+
4923
5046
  declare module 'alinea/core/Tracker' {
4924
5047
 
4925
5048
  import { Field, type FieldOptions } from 'alinea/core/Field';
@@ -4949,6 +5072,7 @@ declare module 'alinea/core/Trigger' {
4949
5072
  declare module 'alinea/core/Type' {
4950
5073
 
4951
5074
  import type { ComponentType } from 'react';
5075
+ import type { Config } from 'alinea/core/Config';
4952
5076
  import type { EntryStatus } from 'alinea/core/Entry';
4953
5077
  import type { Expr } from 'alinea/core/Expr';
4954
5078
  import { Field, type EntryAnchorTarget, type FieldAnchorContext, type FieldBeforeSaveContext } from 'alinea/core/Field';
@@ -4961,7 +5085,9 @@ declare module 'alinea/core/Type' {
4961
5085
  import type { EntryReferenceTarget } from 'alinea/core/db/EntryReference';
4962
5086
  import type { SummaryProps } from 'alinea/core/media/Summary';
4963
5087
  import type { Expand } from 'alinea/core/util/Types';
4964
- export interface EntryUrlMeta {
5088
+ export interface EntryUrlInput {
5089
+ config: Config;
5090
+ data: Record<string, unknown>;
4965
5091
  status: EntryStatus;
4966
5092
  path: string;
4967
5093
  parentPaths: Array<string>;
@@ -4969,6 +5095,9 @@ declare module 'alinea/core/Type' {
4969
5095
  workspace: string;
4970
5096
  root: string;
4971
5097
  }
5098
+ export interface EntryUrlMeta extends EntryUrlInput {
5099
+ defaultUrl: string;
5100
+ }
4972
5101
  export type EntryDefaultView = 'edit' | 'overview';
4973
5102
  export type Type<Definition = object> = Definition & HasType;
4974
5103
  type TypeRow<Definition> = Expand<{
@@ -5101,9 +5230,15 @@ declare module 'alinea/core/util/Assert' {
5101
5230
 
5102
5231
  declare module 'alinea/core/util/Async' {
5103
5232
 
5104
- /** Accumulate all entries of an AsyncGenerator into an array */
5105
- export function accumulate<T>(gen: AsyncGenerator<T>): Promise<Array<T>>;
5233
+ /** Accumulate all entries of an AsyncIterable into an array */
5234
+ export function accumulate<T>(gen: AsyncIterable<T>): Promise<Array<T>>;
5106
5235
  export function toGenerator<T>(iterable: Iterable<T>): AsyncGenerator<T>;
5236
+ export interface MapConcurrentOptions {
5237
+ concurrency: number;
5238
+ signal?: AbortSignal;
5239
+ }
5240
+ /** Map concurrently while yielding results as they complete. */
5241
+ export function mapConcurrent<T, TResult>(iterable: Iterable<T>, mapper: (item: T, signal?: AbortSignal) => Promise<TResult>, options: MapConcurrentOptions): AsyncGenerator<TResult>;
5107
5242
  export function genEffect<T, TReturn>(gen: AsyncIterable<T, TReturn>, effect: (result: T) => void): AsyncIterable<T>;
5108
5243
 
5109
5244
  }
@@ -5266,7 +5401,7 @@ declare module 'alinea/core/util/EntryFilenames' {
5266
5401
 
5267
5402
  import type { Config } from 'alinea/core/Config';
5268
5403
  import { type Entry, type EntryStatus } from 'alinea/core/Entry';
5269
- import type { EntryUrlMeta, Type } from 'alinea/core/Type';
5404
+ import type { EntryUrlInput, Type } from 'alinea/core/Type';
5270
5405
  export function entryInfo(fileName: string): [name: string, status: EntryStatus];
5271
5406
  export function entryChildrenDir(config: Config, entry: {
5272
5407
  workspace: string;
@@ -5290,7 +5425,7 @@ declare module 'alinea/core/util/EntryFilenames' {
5290
5425
  status: EntryStatus;
5291
5426
  }, parentPaths: Array<string>): string;
5292
5427
  export function entryFile(config: Config, entry: Entry): string;
5293
- export function entryUrl(type: Type, meta: EntryUrlMeta): string;
5428
+ export function entryUrl(type: Type, meta: EntryUrlInput): string;
5294
5429
  export function pathSuffix(path: string, conflictingPaths: Array<string>): number | undefined;
5295
5430
  export function applySuffix(path: string, suffix: number): string;
5296
5431
  export function fileVersions(file: string): string[];
@@ -5890,8 +6025,9 @@ declare module 'alinea/dashboard/app/editor/FileEditor' {
5890
6025
  import type { Entry } from 'alinea/core/Entry';
5891
6026
  export interface FileEditorProps {
5892
6027
  entry: Pick<Entry, 'root' | 'url' | 'workspace'>;
6028
+ parentPaths: Array<string>;
5893
6029
  }
5894
- export function FileEditor({ entry }: FileEditorProps): import("react").JSX.Element;
6030
+ export function FileEditor({ entry, parentPaths }: FileEditorProps): import("react").JSX.Element;
5895
6031
 
5896
6032
  }
5897
6033
 
@@ -5915,7 +6051,7 @@ declare module 'alinea/dashboard/app/editor/FilePreview' {
5915
6051
 
5916
6052
  declare module 'alinea/dashboard/app/editor/MediaAltField.view' {
5917
6053
 
5918
- import type { MediaAltField } from 'alinea/core/media/MediaAltField';
6054
+ import { type MediaAltField } from 'alinea/core/media/MediaAltField';
5919
6055
  export interface MediaAltFieldViewProps {
5920
6056
  field: MediaAltField;
5921
6057
  }
@@ -6046,7 +6182,7 @@ declare module 'alinea/dashboard/app/EntrySidebar' {
6046
6182
  onOpenChange?: (isOpen: boolean) => void;
6047
6183
  }
6048
6184
  export type EntrySidebarTab = 'preview' | 'history' | 'references';
6049
- export function entrySidebar(get: Getter, entry: EntryAtoms, localeData: EntryLocaleAtoms): Promise<EntrySidebarProps | undefined>;
6185
+ export function entrySidebar(get: Getter, entry: EntryAtoms, localeData: EntryLocaleAtoms, isOpen?: boolean): Promise<EntrySidebarProps | undefined>;
6050
6186
  export function EntrySidebar({ entry, localeData, selectedTab, previousVersionsOpen, onOpenChange }: EntrySidebarProps): import("react").JSX.Element;
6051
6187
  export type EntrySidebarVersionStatus = EntryStatus | 'unpublished' | 'none';
6052
6188
  export interface EntrySidebarVersionRowProps {
@@ -6071,7 +6207,7 @@ declare module 'alinea/dashboard/app/EntrySidebarPreview' {
6071
6207
  }
6072
6208
  export function EntrySidebarPreview({ entry, localeData }: EntrySidebarPreviewProps): import("react").JSX.Element;
6073
6209
  export interface EntrySidebarBrowserPreviewProps {
6074
- localeData: Pick<EntryLocaleAtoms, 'previewUrl' | 'retryPreviewUrl'> & Partial<Pick<EntryLocaleAtoms, 'previewPayloadSignal' | 'updatePreviewPayload'>>;
6210
+ localeData: Pick<EntryLocaleAtoms, 'previewUrlState' | 'retryPreviewUrl'> & Partial<Pick<EntryLocaleAtoms, 'previewPayloadSignal' | 'updatePreviewPayload'>>;
6075
6211
  }
6076
6212
  export function EntrySidebarBrowserPreview({ localeData }: EntrySidebarBrowserPreviewProps): import("react").JSX.Element;
6077
6213
 
@@ -6378,6 +6514,19 @@ declare module 'alinea/dashboard/app/pages/UsersPage' {
6378
6514
 
6379
6515
  }
6380
6516
 
6517
+ declare module 'alinea/dashboard/app/SidebarLayout' {
6518
+
6519
+ import { type ReactNode } from 'react';
6520
+ export interface SidebarLayoutProps {
6521
+ children: ReactNode;
6522
+ sidebar: ReactNode;
6523
+ side: 'left' | 'right';
6524
+ visible?: boolean;
6525
+ }
6526
+ export function SidebarLayout({ children, sidebar, side, visible }: SidebarLayoutProps): import("react").JSX.Element;
6527
+
6528
+ }
6529
+
6381
6530
  declare module 'alinea/dashboard/app/SidebarTree' {
6382
6531
 
6383
6532
  import { type Page } from 'alinea/dashboard/atoms/nav';
@@ -6751,6 +6900,15 @@ declare module 'alinea/dashboard/atoms/dashboard' {
6751
6900
 
6752
6901
  import type { SetStateAction } from 'react';
6753
6902
  export type DashboardTheme = 'system' | 'light' | 'dark';
6903
+ export const dashboardMobileAtom: import("jotai").PrimitiveAtom<boolean> & {
6904
+ init: boolean;
6905
+ };
6906
+ export const navigationSidebarWidthAtom: import("jotai").PrimitiveAtom<number> & {
6907
+ init: number;
6908
+ };
6909
+ export const entrySidebarWidthAtom: import("jotai").PrimitiveAtom<number> & {
6910
+ init: number;
6911
+ };
6754
6912
  export const entrySidebarOpenAtom: import("jotai").PrimitiveAtom<boolean> & {
6755
6913
  init: boolean;
6756
6914
  };
@@ -6773,6 +6931,10 @@ declare module 'alinea/dashboard/atoms/editor' {
6773
6931
  import { Type } from 'alinea/core/Type';
6774
6932
  import type { Atom, WritableAtom } from 'jotai';
6775
6933
  import type { ComponentType, ReactNode } from 'react';
6934
+ export interface ResolvedEditorImage {
6935
+ src: string;
6936
+ alt: string;
6937
+ }
6776
6938
  export interface EditorNode {
6777
6939
  readOnly: boolean;
6778
6940
  nodes: WritableAtom<unknown, [unknown], void>;
@@ -6783,6 +6945,7 @@ declare module 'alinea/dashboard/atoms/editor' {
6783
6945
  anchors: Atom<Array<EntryAnchorTarget>>;
6784
6946
  node: EditorNode;
6785
6947
  parent?: EditorModel;
6948
+ resolvedImages: ReadonlyMap<string, ResolvedEditorImage>;
6786
6949
  sections: Array<EditorSection>;
6787
6950
  type: Type;
6788
6951
  field(key: string): EditorField | undefined;
@@ -6813,10 +6976,11 @@ declare module 'alinea/dashboard/atoms/editor' {
6813
6976
  parent?: EntryEditor | undefined;
6814
6977
  resource?: Resource | undefined;
6815
6978
  policy?: Policy | undefined;
6979
+ resolvedImages: ReadonlyMap<string, ResolvedEditorImage>;
6816
6980
  anchors: Atom<Array<EntryAnchorTarget>>;
6817
6981
  value: Atom<object>;
6818
6982
  sections: Array<EntryEditorSection>;
6819
- constructor(type: Type, node: EditorNode, parent?: EntryEditor | undefined, resource?: Resource | undefined, policy?: Policy | undefined);
6983
+ constructor(type: Type, node: EditorNode, parent?: EntryEditor | undefined, resource?: Resource | undefined, policy?: Policy | undefined, resolvedImages?: ReadonlyMap<string, ResolvedEditorImage>);
6820
6984
  field: (key: string) => EntryEditorField | undefined;
6821
6985
  get(field: Field): EntryEditorField | undefined;
6822
6986
  }
@@ -6853,8 +7017,10 @@ declare module 'alinea/dashboard/atoms/entry' {
6853
7017
 
6854
7018
  import type { EntryReference, EntryReferenceScan } from 'alinea/core/db/EntryReference';
6855
7019
  import { Entry, EntryStatus } from 'alinea/core/Entry';
7020
+ import type { Order } from 'alinea/core/Graph';
6856
7021
  import { type EntryDefaultView } from 'alinea/core/Type';
6857
- import { Atom } from 'jotai';
7022
+ import { Atom, Getter } from 'jotai';
7023
+ import type { ResolvedEditorImage } from 'alinea/dashboard/atoms/editor';
6858
7024
  import { ReactiveNode } from 'alinea/dashboard/atoms/ReactiveNode';
6859
7025
  interface EntryData {
6860
7026
  id: string;
@@ -6920,6 +7086,7 @@ declare module 'alinea/dashboard/atoms/entry' {
6920
7086
  historyReady: Atom<Promise<import("alinea/core/Connection").Revision[]>>;
6921
7087
  history: Atom<import("alinea/core/Connection").Revision[]>;
6922
7088
  selectedNode: Atom<Promise<ReactiveNode<object>>>;
7089
+ richTextImages: Atom<Promise<Map<string, ResolvedEditorImage>>>;
6923
7090
  anchors: Atom<Promise<import("alinea/core/Field").EntryAnchorTarget[]>>;
6924
7091
  retryPreviewUrl: import("jotai").WritableAtom<null, [], void> & {
6925
7092
  init: null;
@@ -6975,7 +7142,7 @@ declare module 'alinea/dashboard/atoms/entry' {
6975
7142
  searchableText: string;
6976
7143
  } | undefined>;
6977
7144
  previewUrlReady: Atom<Promise<string | undefined>>;
6978
- previewUrl: Atom<string | undefined>;
7145
+ previewUrlState: Atom<readonly [false, string | undefined] | readonly [true, string | undefined]>;
6979
7146
  previewPayloadSignal: Atom<(object | null | undefined)[]>;
6980
7147
  updatePreviewPayload: import("jotai").WritableAtom<null, [], Promise<string | undefined>> & {
6981
7148
  init: null;
@@ -7059,6 +7226,7 @@ declare module 'alinea/dashboard/atoms/entry' {
7059
7226
  parentId: Atom<string | null>;
7060
7227
  workspace: Atom<string>;
7061
7228
  root: Atom<string>;
7229
+ parentPaths: Atom<string[]>;
7062
7230
  hasChildren: Atom<boolean>;
7063
7231
  canPublishParents: Atom<boolean>;
7064
7232
  parentUnpublished: Atom<boolean>;
@@ -7073,6 +7241,48 @@ declare module 'alinea/dashboard/atoms/entry' {
7073
7241
  id: string;
7074
7242
  constructor(id: string);
7075
7243
  }
7244
+ export interface TreeEntrySummary {
7245
+ id: string;
7246
+ title: string;
7247
+ type: string;
7248
+ status: EntryStatus;
7249
+ main: boolean;
7250
+ locale: string | null;
7251
+ parentId: string | null;
7252
+ parents: Array<string>;
7253
+ workspace: string;
7254
+ root: string;
7255
+ hasChildren: boolean;
7256
+ }
7257
+ interface TreeChildrenLocation {
7258
+ workspace: string;
7259
+ root: string;
7260
+ parentId: string | null;
7261
+ }
7262
+ export function loadTreeChildren(get: Getter, location: TreeChildrenLocation, locale: string | null, orderBy?: Order | Array<Order>): Promise<Array<TreeEntryAtoms>>;
7263
+ export class TreeEntryAtoms {
7264
+ #private;
7265
+ readonly id: string;
7266
+ constructor(id: string);
7267
+ ready: Atom<Promise<this>>;
7268
+ raw: (locale: string | null) => Atom<Promise<Omit<TreeEntrySummary, "hasChildren">>>;
7269
+ summary: (locale: string | null) => Atom<Promise<{
7270
+ id: string;
7271
+ title: string;
7272
+ type: string;
7273
+ status: EntryStatus;
7274
+ main: boolean;
7275
+ locale: string | null;
7276
+ parentId: string | null;
7277
+ parents: Array<string>;
7278
+ workspace: string;
7279
+ root: string;
7280
+ hasChildren: boolean;
7281
+ }>>;
7282
+ parents: Atom<Promise<TreeEntryAtoms[]>>;
7283
+ children: (locale: string | null) => Atom<Promise<TreeEntryAtoms[]>>;
7284
+ }
7285
+ export const treeEntryAtoms: (id: string) => TreeEntryAtoms;
7076
7286
  export {};
7077
7287
 
7078
7288
  }
@@ -7432,7 +7642,10 @@ declare module 'alinea/dashboard/atoms/nav' {
7432
7642
 
7433
7643
  declare module 'alinea/dashboard/atoms/preview' {
7434
7644
 
7645
+ import type { LocalConnection } from 'alinea/core/Connection';
7435
7646
  import type { PreviewMetadata } from 'alinea/core/Preview';
7647
+ export function getPreviewToken(client: LocalConnection): Promise<string | undefined>;
7648
+ export function retryPreviewToken(client: LocalConnection): void;
7436
7649
  export const previewMetadataAtom: import("jotai").PrimitiveAtom<PreviewMetadata | undefined> & {
7437
7650
  init: PreviewMetadata | undefined;
7438
7651
  };
@@ -7487,7 +7700,7 @@ declare module 'alinea/dashboard/atoms/ReactiveNode' {
7487
7700
 
7488
7701
  declare module 'alinea/dashboard/atoms/root' {
7489
7702
 
7490
- import { type EntryStatus } from 'alinea/core/Entry';
7703
+ import type { EntryStatus } from 'alinea/core/Entry';
7491
7704
  import type { RootData, RootI18n } from 'alinea/core/Root';
7492
7705
  import type { DragItem, DragTypes, DropOperation, DropTarget } from '@react-types/shared';
7493
7706
  import { type ExplorerAtoms } from 'alinea/dashboard/atoms/explorer';
@@ -7495,6 +7708,7 @@ declare module 'alinea/dashboard/atoms/root' {
7495
7708
  import type { ComponentType } from 'react';
7496
7709
  import type { DroppableCollectionInsertDropEvent, DroppableCollectionOnItemDropEvent, DroppableCollectionReorderEvent, Key } from 'react-aria-components';
7497
7710
  import { LucideFile } from 'alinea/dashboard/icons';
7711
+ import { type TreeEntryAtoms } from 'alinea/dashboard/atoms/entry';
7498
7712
  export interface RootViewProps {
7499
7713
  root: RootData;
7500
7714
  }
@@ -7534,6 +7748,7 @@ declare module 'alinea/dashboard/atoms/root' {
7534
7748
  constructor(root: RootAtoms, locale: string | null, selectedKeys: Atom<Set<Key>>, viewState?: TreeViewState);
7535
7749
  snapshot: Atom<TreeSnapshot>;
7536
7750
  items: Atom<RootTreeItem[]>;
7751
+ children: (id: string) => Atom<Promise<TreeEntryAtoms[]>>;
7537
7752
  item: (id: string) => Atom<RootTreeItem>;
7538
7753
  selectedItem: Atom<RootTreeItem | undefined>;
7539
7754
  ready: Atom<Promise<{
@@ -7551,6 +7766,7 @@ declare module 'alinea/dashboard/atoms/root' {
7551
7766
  explorer: ExplorerAtoms;
7552
7767
  constructor(workspace: string, key: string);
7553
7768
  createTree(locale: string | null, selectedKeys: Atom<Set<Key>>, expandedKeys?: PrimitiveAtom<Set<string>>): TreeAtoms;
7769
+ treeEntries: (locale: string | null) => Atom<Promise<TreeEntryAtoms[]>>;
7554
7770
  children: (parentId: string | null) => ExplorerAtoms;
7555
7771
  label: Atom<string>;
7556
7772
  icon: Atom<typeof LucideFile | ComponentType>;
@@ -8021,7 +8237,7 @@ declare module 'alinea/dashboard/hooks' {
8021
8237
  import type { WorkspaceInternal } from 'alinea/core/Workspace';
8022
8238
  import { Type } from 'alinea';
8023
8239
  import type { ComponentType, Dispatch, PropsWithChildren, SetStateAction } from 'react';
8024
- import { type EditorModel, type EditorNode, EntryEditor } from 'alinea/dashboard/atoms/editor';
8240
+ import { type EditorModel, type EditorNode, EntryEditor, type ResolvedEditorImage } from 'alinea/dashboard/atoms/editor';
8025
8241
  import type { EntryAtoms, EntryLocaleAtoms } from 'alinea/dashboard/atoms/entry';
8026
8242
  import type { Page } from 'alinea/dashboard/atoms/nav';
8027
8243
  import type { RootAtoms } from 'alinea/dashboard/atoms/root';
@@ -8029,6 +8245,7 @@ declare module 'alinea/dashboard/hooks' {
8029
8245
  interface EntryContextValue {
8030
8246
  entry: EntryAtoms;
8031
8247
  localeData: EntryLocaleAtoms;
8248
+ richTextImages: ReadonlyMap<string, ResolvedEditorImage>;
8032
8249
  selectedEntry: EntryRecord<Record<string, unknown>>;
8033
8250
  }
8034
8251
  export interface DashboardOptions {
@@ -8096,9 +8313,10 @@ declare module 'alinea/dashboard/hooks' {
8096
8313
  export interface EntryScopeProps {
8097
8314
  entry: EntryAtoms;
8098
8315
  localeData: EntryLocaleAtoms;
8316
+ richTextImages: ReadonlyMap<string, ResolvedEditorImage>;
8099
8317
  selectedEntry: EntryRecord<Record<string, unknown>>;
8100
8318
  }
8101
- export function EntryScope({ children, entry, localeData, selectedEntry }: PropsWithChildren<EntryScopeProps>): import("react").FunctionComponentElement<import("react").ProviderProps<EntryContextValue | null>>;
8319
+ export function EntryScope({ children, entry, localeData, richTextImages, selectedEntry }: PropsWithChildren<EntryScopeProps>): import("react").FunctionComponentElement<import("react").ProviderProps<EntryContextValue | null>>;
8102
8320
  export function useEntryAtoms(): EntryContextValue;
8103
8321
  export function useOptionalEntryAtoms(): EntryContextValue | null;
8104
8322
  /**
@@ -8281,6 +8499,7 @@ declare module 'alinea/dashboard/icons' {
8281
8499
  export function IcRoundMoreVert(props: SVGProps<SVGSVGElement>): import("react").JSX.Element;
8282
8500
  export function IcRoundNorthEast(props: SVGProps<SVGSVGElement>): import("react").JSX.Element;
8283
8501
  export function IcRoundNumbers(props: SVGProps<SVGSVGElement>): import("react").JSX.Element;
8502
+ export function IcRoundOpenInFull(props: SVGProps<SVGSVGElement>): import("react").JSX.Element;
8284
8503
  export function IcRoundOpenInNew(props: SVGProps<SVGSVGElement>): import("react").JSX.Element;
8285
8504
  export function IcRoundPanorama(props: SVGProps<SVGSVGElement>): import("react").JSX.Element;
8286
8505
  export function IcRoundPermMedia(props: SVGProps<SVGSVGElement>): import("react").JSX.Element;
@@ -8766,8 +8985,8 @@ declare module 'alinea/field/link/FileLink' {
8766
8985
  }
8767
8986
  export namespace FileLink {
8768
8987
  const title: import("alinea/core/Expr").Expr<string>;
8769
- const url: import("alinea/field/hidden").HiddenField<string>;
8770
- const href: import("alinea/field/hidden").HiddenField<string>;
8988
+ const url: import("alinea/core/Expr").Expr<string>;
8989
+ const href: import("alinea/core/Expr").Expr<string>;
8771
8990
  const extension: import("alinea/field/hidden").HiddenField<string>;
8772
8991
  const size: import("alinea/field/hidden").HiddenField<number>;
8773
8992
  }
@@ -8814,7 +9033,7 @@ declare module 'alinea/field/link/ImageLink' {
8814
9033
  export namespace ImageLink {
8815
9034
  const title: import("alinea/core/Expr").Expr<string>;
8816
9035
  const alt: import("alinea/core/media/MediaAltField").MediaAltField;
8817
- const src: import("alinea/field/hidden").HiddenField<string>;
9036
+ const src: import("alinea/core/Expr").Expr<string>;
8818
9037
  const extension: import("alinea/field/hidden").HiddenField<string>;
8819
9038
  const size: import("alinea/field/hidden").HiddenField<number>;
8820
9039
  const hash: import("alinea/field/hidden").HiddenField<string>;
@@ -9277,6 +9496,8 @@ declare module 'alinea/field/number/NumberField' {
9277
9496
  help?: ReactNode;
9278
9497
  /** Display a minimal version */
9279
9498
  inline?: boolean;
9499
+ /** Text displayed when the field is empty */
9500
+ placeholder?: string;
9280
9501
  /** A minimum value */
9281
9502
  minValue?: number;
9282
9503
  /** A maximum value */
@@ -9509,7 +9730,9 @@ declare module 'alinea/field/richtext/PickTextLink' {
9509
9730
  import { Reference } from 'alinea/core/Reference';
9510
9731
  export interface PickerValue {
9511
9732
  link?: Reference;
9733
+ alt?: string;
9512
9734
  description?: string;
9735
+ src?: string;
9513
9736
  title?: string;
9514
9737
  blank?: boolean;
9515
9738
  }
@@ -9520,9 +9743,14 @@ declare module 'alinea/field/richtext/PickTextLink' {
9520
9743
  export interface PickTextLinkFunc {
9521
9744
  (options: Partial<PickerOptions>): Promise<PickerValue | undefined>;
9522
9745
  }
9746
+ export interface PickRichTextImageFunc {
9747
+ (options: Partial<PickerOptions>): Promise<PickerValue | undefined>;
9748
+ }
9523
9749
  export interface PickTextLinkState {
9524
9750
  isOpen: boolean;
9751
+ kind: 'image' | 'link';
9525
9752
  options: Partial<PickerOptions>;
9753
+ pickImage: PickRichTextImageFunc;
9526
9754
  pickLink: PickTextLinkFunc;
9527
9755
  cancel: () => void;
9528
9756
  confirm: (value: PickerValue | undefined) => void;
@@ -9540,10 +9768,13 @@ declare module 'alinea/field/richtext/ReferenceLink' {
9540
9768
  import { Reference } from 'alinea/core/Reference';
9541
9769
  import type { HTMLProps } from 'react';
9542
9770
  interface Anchor extends HTMLProps<HTMLAnchorElement> {
9771
+ _id?: string;
9772
+ _entry?: string;
9773
+ _link?: 'entry' | 'file' | 'image' | 'url';
9543
9774
  'data-id'?: string;
9544
9775
  'data-entry'?: string;
9545
9776
  'data-anchor'?: string;
9546
- 'data-link'?: 'entry' | 'file' | 'url';
9777
+ 'data-link'?: 'entry' | 'file' | 'image' | 'url';
9547
9778
  'data-suffix'?: string;
9548
9779
  }
9549
9780
  export function referenceToAttributes(reference: Reference): Anchor;
@@ -9620,8 +9851,13 @@ declare module 'alinea/field/richtext/RichTextBlockValue' {
9620
9851
  declare module 'alinea/field/richtext/RichTextDocument' {
9621
9852
 
9622
9853
  import { BlockNode, type TextDoc } from 'alinea/core/TextDoc';
9623
- import type { JSONContent } from '@tiptap/core';
9624
- export function editorContent(nodes: TextDoc): JSONContent;
9854
+ import { type Editor, type JSONContent } from '@tiptap/core';
9855
+ /** Include data attributes produced by custom extensions in the stored document. */
9856
+ export function editorDocument(editor: Editor): JSONContent;
9857
+ export function editorContent(nodes: TextDoc, images?: ReadonlyMap<string, {
9858
+ src: string;
9859
+ alt: string;
9860
+ }>): JSONContent;
9625
9861
  export function editorNodes(content: JSONContent, resolveBlock?: (id: string, typeName: string, snapshot: BlockNode | undefined) => BlockNode | undefined): TextDoc;
9626
9862
 
9627
9863
  }
@@ -9643,6 +9879,7 @@ declare module 'alinea/field/richtext/RichTextExtensions' {
9643
9879
  Italic: import("@tiptap/core").Mark<import("@tiptap/extension-italic").ItalicOptions, any>;
9644
9880
  Strike: import("@tiptap/core").Mark<import("@tiptap/extension-strike").StrikeOptions, any>;
9645
9881
  HorizontalRule: TipTapNode<import("@tiptap/extension-horizontal-rule").HorizontalRuleOptions, any>;
9882
+ Image: TipTapNode<import("@tiptap/extension-image").ImageOptions, any>;
9646
9883
  BulletList: TipTapNode<import("@tiptap/extension-list").BulletListOptions, any>;
9647
9884
  OrderedList: TipTapNode<import("@tiptap/extension-list").OrderedListOptions, any>;
9648
9885
  ListItem: TipTapNode<import("@tiptap/extension-list").ListItemOptions, any>;
@@ -9663,7 +9900,7 @@ declare module 'alinea/field/richtext/RichTextExtensions' {
9663
9900
  Highlight: import("@tiptap/core").Mark<import("@tiptap/extension-highlight").HighlightOptions, any>;
9664
9901
  UndoRedo: Extension<import("@tiptap/extensions").UndoRedoOptions, any>;
9665
9902
  };
9666
- export function defaultExtensionConfig(getEntryAnchors?: () => Iterable<string>): {
9903
+ export function defaultExtensionConfig(getEntryAnchors?: () => Iterable<string>, enableImageResize?: boolean): {
9667
9904
  Document: TipTapNode<any, any>;
9668
9905
  Text: TipTapNode<any, any>;
9669
9906
  Paragraph: TipTapNode<import("@tiptap/extension-paragraph").ParagraphOptions, any>;
@@ -9673,6 +9910,7 @@ declare module 'alinea/field/richtext/RichTextExtensions' {
9673
9910
  Italic: import("@tiptap/core").Mark<import("@tiptap/extension-italic").ItalicOptions, any>;
9674
9911
  Strike: import("@tiptap/core").Mark<import("@tiptap/extension-strike").StrikeOptions, any>;
9675
9912
  HorizontalRule: TipTapNode<import("@tiptap/extension-horizontal-rule").HorizontalRuleOptions, any>;
9913
+ Image: TipTapNode<import("@tiptap/extension-image").ImageOptions, any>;
9676
9914
  BulletList: TipTapNode<import("@tiptap/extension-list").BulletListOptions, any>;
9677
9915
  OrderedList: TipTapNode<import("@tiptap/extension-list").OrderedListOptions, any>;
9678
9916
  ListItem: TipTapNode<import("@tiptap/extension-list").ListItemOptions, any>;
@@ -9724,10 +9962,14 @@ declare module 'alinea/field/richtext/RichTextField' {
9724
9962
  help?: ReactNode;
9725
9963
  /** Display a minimal version */
9726
9964
  inline?: boolean;
9965
+ /** Text shown when the editor is empty */
9966
+ placeholder?: string;
9727
9967
  /** Index the text value of this field */
9728
9968
  searchable?: boolean;
9729
9969
  /** Enable inserting and editing tables */
9730
9970
  enableTables?: boolean;
9971
+ /** Enable inserting and editing images */
9972
+ enableImages?: boolean;
9731
9973
  /** Configure the toolbar layout and items */
9732
9974
  toolbar?: ToolbarConfig;
9733
9975
  /** Configure tiptap extensions */
@@ -9748,12 +9990,16 @@ declare module 'alinea/field/richtext/RichTextField.story' {
9748
9990
 
9749
9991
  export function RichTextStory(): import("react").JSX.Element;
9750
9992
  export function RichTextPlainStory(): import("react").JSX.Element;
9993
+ export function RichTextImageStory(): import("react").JSX.Element;
9994
+ export function RichTextImageDisabledStory(): import("react").JSX.Element;
9995
+ export function RichTextReadOnlyImageStory(): import("react").JSX.Element;
9751
9996
  export function RichTextLargeStory(): import("react").JSX.Element;
9752
9997
  export function RichTextImportedListStory(): import("react").JSX.Element;
9753
9998
  export function RichTextCustomToolbarStory(): import("react").JSX.Element;
9754
9999
  export function RichTextEmptyStory(): import("react").JSX.Element;
9755
10000
  export function RichTextLegacyEmptyStory(): import("react").JSX.Element;
9756
10001
  export function RichTextReadOnlyStory(): import("react").JSX.Element;
10002
+ export function RichTextInlineStory(): import("react").JSX.Element;
9757
10003
 
9758
10004
  }
9759
10005
 
@@ -9803,20 +10049,23 @@ declare module 'alinea/field/richtext/RichTextState' {
9803
10049
  declare module 'alinea/field/richtext/RichTextToolbar' {
9804
10050
 
9805
10051
  import type { Editor } from '@tiptap/core';
9806
- import type { PickTextLinkFunc } from 'alinea/field/richtext/PickTextLink';
10052
+ import type { PickRichTextImageFunc, PickTextLinkFunc } from 'alinea/field/richtext/PickTextLink';
9807
10053
  import { type ToolbarConfig } from 'alinea/field/richtext/Toolbar';
9808
10054
  import type { PickTextAnchorFunc } from 'alinea/field/richtext/PickTextAnchor';
9809
10055
  export interface RichTextToolbarProps {
9810
10056
  editor: Editor;
10057
+ enableImages?: boolean;
9811
10058
  enableTables?: boolean;
9812
10059
  ownerId: string;
10060
+ pickImage?: PickRichTextImageFunc;
9813
10061
  pickLink?: PickTextLinkFunc;
9814
10062
  pickAnchor?: PickTextAnchorFunc;
9815
10063
  getEntryAnchors: () => Array<string>;
9816
10064
  toolbar?: ToolbarConfig;
9817
10065
  onFocusChange: (focused: boolean, nextTarget?: EventTarget | null) => void;
9818
10066
  }
9819
- export function RichTextToolbar({ editor, enableTables, ownerId, pickLink, pickAnchor, getEntryAnchors, toolbar, onFocusChange }: RichTextToolbarProps): import("react").JSX.Element;
10067
+ export function RichTextToolbar({ editor, enableImages, enableTables, ownerId, pickImage, pickLink, pickAnchor, getEntryAnchors, toolbar, onFocusChange }: RichTextToolbarProps): import("react").JSX.Element;
10068
+ export function createImageHandler(editor: Editor, pickImage: PickRichTextImageFunc | undefined, exec: () => ReturnType<Editor['chain']>): () => void;
9820
10069
 
9821
10070
  }
9822
10071
 
@@ -9825,6 +10074,7 @@ declare module 'alinea/field/richtext/Toolbar' {
9825
10074
  import type { Editor } from '@tiptap/react';
9826
10075
  import type { ComponentType, ReactElement, ReactNode } from 'react';
9827
10076
  import type { PickTextLinkFunc } from 'alinea/field/richtext/PickTextLink';
10077
+ import type { PickRichTextImageFunc } from 'alinea/field/richtext/PickTextLink';
9828
10078
  export interface RichTextCommand {
9829
10079
  (): ReturnType<Editor['chain']>;
9830
10080
  }
@@ -9851,9 +10101,12 @@ declare module 'alinea/field/richtext/Toolbar' {
9851
10101
  export interface RichTextToolbarContext {
9852
10102
  editor: Editor;
9853
10103
  focusToggle: (target: EventTarget | null) => void;
10104
+ pickImage: PickRichTextImageFunc;
9854
10105
  pickLink: PickTextLinkFunc;
10106
+ enableImages?: boolean;
9855
10107
  enableTables?: boolean;
9856
10108
  exec: RichTextCommand;
10109
+ handleImage: () => void;
9857
10110
  handleLink: () => void;
9858
10111
  handleAnchor: () => void;
9859
10112
  toolbar: ToolbarConfig;
@@ -10003,6 +10256,16 @@ declare module 'alinea/field/richtext/Toolbar' {
10003
10256
  };
10004
10257
  };
10005
10258
  };
10259
+ export const images: {
10260
+ group: {
10261
+ image: {
10262
+ icon: () => import("react").JSX.Element;
10263
+ title: string;
10264
+ active: ({ editor }: RichTextToolbarContext) => boolean;
10265
+ onSelect: ({ handleImage }: RichTextToolbarContext) => void;
10266
+ };
10267
+ };
10268
+ };
10006
10269
  export const anchors: {
10007
10270
  group: {
10008
10271
  anchor: {
@@ -10024,7 +10287,11 @@ declare module 'alinea/field/richtext/Toolbar' {
10024
10287
  title: string;
10025
10288
  onSelect: ({ exec }: RichTextToolbarContext) => boolean;
10026
10289
  };
10027
- export function defaultToolbar(enableTables: boolean): ToolbarConfig;
10290
+ export interface DefaultToolbarOptions {
10291
+ enableImages?: boolean;
10292
+ enableTables?: boolean;
10293
+ }
10294
+ export function defaultToolbar({ enableImages, enableTables }?: DefaultToolbarOptions): ToolbarConfig;
10028
10295
  export {};
10029
10296
 
10030
10297
  }
@@ -10277,7 +10544,8 @@ declare module 'alinea' {
10277
10544
  declare module 'alinea/next' {
10278
10545
 
10279
10546
  export { createCMS } from 'alinea/adapter/next/cms';
10280
- export { createHandler } from 'alinea/adapter/next/handler';
10547
+ export { createHandler, type NextHandlerOptions } from 'alinea/adapter/next/handler';
10548
+ export type { AfterCommitContext, BeforeCommitContext } from 'alinea/backend/Handler';
10281
10549
  export { withAlinea } from 'alinea/adapter/next/with-alinea';
10282
10550
 
10283
10551
  }
@@ -10285,7 +10553,8 @@ declare module 'alinea/next' {
10285
10553
  declare module 'alinea/next.edge' {
10286
10554
 
10287
10555
  export { createCMS } from 'alinea/adapter/next/cms';
10288
- export { createHandler } from 'alinea/adapter/next/handler';
10556
+ export { createHandler, type NextHandlerOptions } from 'alinea/adapter/next/handler';
10557
+ export type { AfterCommitContext, BeforeCommitContext } from 'alinea/backend/Handler';
10289
10558
 
10290
10559
  }
10291
10560
 
@@ -11008,6 +11277,7 @@ declare module 'alinea/ui/RichText' {
11008
11277
  li?: ComponentType<JSX.IntrinsicElements['li']> | ReactElement;
11009
11278
  blockquote?: ComponentType<JSX.IntrinsicElements['blockquote']> | ReactElement;
11010
11279
  hr?: ComponentType<JSX.IntrinsicElements['hr']> | ReactElement;
11280
+ img?: ComponentType<JSX.IntrinsicElements['img']> | ReactElement;
11011
11281
  br?: ComponentType<JSX.IntrinsicElements['br']> | ReactElement;
11012
11282
  small?: ComponentType<JSX.IntrinsicElements['small']> | ReactElement;
11013
11283
  sub?: ComponentType<JSX.IntrinsicElements['sub']> | ReactElement;