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.
- package/dist/.init/content/pages/welcome.json +1 -1
- package/dist/LICENSES.md +134 -80
- package/dist/adapter/next/DevRemote.d.ts +3 -0
- package/dist/adapter/next/DevRemote.js +37 -0
- package/dist/adapter/next/ForwardCredentials.d.ts +1 -0
- package/dist/adapter/next/ForwardCredentials.js +17 -0
- package/dist/adapter/next/cms.js +86 -38
- package/dist/adapter/next/context.d.ts +1 -1
- package/dist/adapter/next/context.js +11 -3
- package/dist/adapter/next/handler.d.ts +2 -0
- package/dist/adapter/next/handler.js +23 -16
- package/dist/adapter/next/with-alinea.js +18 -16
- package/dist/backend/Handler.d.ts +14 -13
- package/dist/backend/Handler.js +70 -36
- package/dist/backend/resolver/ParsePreview.d.ts +8 -4
- package/dist/backend/resolver/ParsePreview.js +40 -43
- package/dist/backend/router/Router.d.ts +1 -0
- package/dist/backend/router/Router.js +21 -15
- package/dist/bundled.d.ts +369 -99
- package/dist/chunks/chunk-6UT4N4CO.js +919 -0
- package/dist/chunks/{chunk-LUBOGJCG.js → chunk-6V4TAD2N.js} +1 -1
- package/dist/chunks/{chunk-TL7ZW6BX.js → chunk-A3XXZBOQ.js} +2535 -2999
- package/dist/chunks/chunk-AC5ATYI3.js +1434 -0
- package/dist/chunks/{chunk-7ORQ7BYK.js → chunk-KMLLLZ6X.js} +202 -269
- package/dist/chunks/{chunk-IWN3T3FL.js → chunk-O7XWTMCB.js} +1 -1
- package/dist/chunks/{chunk-53DZYORR.js → chunk-PAYSVIYI.js} +76 -176
- package/dist/chunks/{chunk-YK3OSMDM.js → chunk-S4AU6SRS.js} +188 -158
- package/dist/chunks/{chunk-EQ3TDHYD.js → chunk-UVOEM4AH.js} +6 -3
- package/dist/chunks/{chunk-I7X64JTZ.js → chunk-VXZM6V4P.js} +4 -4
- package/dist/cli/Generate.js +3 -13
- package/dist/cli/Serve.js +7 -3
- package/dist/cli/bin.js +8 -5
- package/dist/cli/generate/CompileConfig.js +3 -2
- package/dist/cli/generate/CopyStaticFiles.js +2 -3
- package/dist/cli/generate/DevDB.d.ts +1 -1
- package/dist/cli/generate/DevDB.js +3 -5
- package/dist/cli/serve/CreateLocalServer.d.ts +1 -1
- package/dist/cli/serve/CreateLocalServer.js +3 -2
- package/dist/cli/serve/DevServer.d.ts +3 -2
- package/dist/cli/serve/DevServer.js +60 -3
- package/dist/cli/serve/ServeContext.d.ts +1 -0
- package/dist/cli/serve/StartServer.d.ts +1 -0
- package/dist/cli/serve/StartServer.js +6 -1
- package/dist/cli/util/EnsureLibs.js +2 -2
- package/dist/cli/util/EnsureNode.js +2 -2
- package/dist/cloud/CloudRemote.d.ts +2 -1
- package/dist/cloud/CloudRemote.js +3 -2
- package/dist/components/Breadcrumbs.js +8 -8
- package/dist/components/Button.js +6 -6
- package/dist/components/Calendar.js +11 -11
- package/dist/components/Checkbox.js +7 -7
- package/dist/components/CheckboxGroup.js +6 -6
- package/dist/components/ColorSwatch.js +6 -6
- package/dist/components/ColorSwatchPicker.js +6 -6
- package/dist/components/ComboBox.js +17 -17
- package/dist/components/DateField.js +9 -9
- package/dist/components/DatePicker.js +10 -10
- package/dist/components/DateRangePicker.js +14 -14
- package/dist/components/Dialog.js +6 -6
- package/dist/components/Disclosure.js +13 -13
- package/dist/components/DropZone.js +6 -6
- package/dist/components/Label.js +16 -16
- package/dist/components/Link.js +6 -6
- package/dist/components/List.js +34 -34
- package/dist/components/Menu.js +10 -10
- package/dist/components/Modal.js +8 -8
- package/dist/components/MultipleSelect.js +33 -33
- package/dist/components/NumberField.d.ts +2 -1
- package/dist/components/NumberField.js +21 -11
- package/dist/components/Popover.js +6 -6
- package/dist/components/ProgressCircle.js +10 -10
- package/dist/components/RadioGroup.js +6 -6
- package/dist/components/SearchField.js +11 -11
- package/dist/components/Select.js +13 -13
- package/dist/components/Surface.js +3 -3
- package/dist/components/Switch.js +6 -6
- package/dist/components/Table.js +13 -13
- package/dist/components/Tabs.js +8 -8
- package/dist/components/TagGroup.js +7 -7
- package/dist/components/TextField.js +10 -10
- package/dist/components/TimeField.js +6 -6
- package/dist/components/Toggle.js +6 -6
- package/dist/components/Toolbar.js +7 -7
- package/dist/components/Tooltip.js +10 -10
- package/dist/components/Tree.js +9 -9
- package/dist/core/BlobTransport.d.ts +5 -0
- package/dist/core/BlobTransport.js +79 -0
- package/dist/core/Client.d.ts +2 -1
- package/dist/core/Client.js +17 -12
- package/dist/core/Config.d.ts +4 -0
- package/dist/core/Config.js +6 -0
- package/dist/core/Connection.d.ts +4 -3
- package/dist/core/Connection.js +7 -0
- package/dist/core/Graph.d.ts +3 -4
- package/dist/core/ListRow.d.ts +2 -0
- package/dist/core/OrderBy.d.ts +7 -3
- package/dist/core/TextDoc.d.ts +11 -0
- package/dist/core/Trace.d.ts +8 -0
- package/dist/core/Trace.js +32 -0
- package/dist/core/Type.d.ts +7 -1
- package/dist/core/db/CommitRequest.d.ts +0 -3
- package/dist/core/db/CommitRequest.js +0 -9
- package/dist/core/db/EntryDB.js +1 -1
- package/dist/core/db/EntryIndex.d.ts +12 -2
- package/dist/core/db/EntryIndex.js +131 -22
- package/dist/core/db/EntryResolver.js +104 -29
- package/dist/core/db/EntryTransaction.d.ts +1 -2
- package/dist/core/db/EntryTransaction.js +29 -22
- package/dist/core/db/LocalDB.d.ts +5 -5
- package/dist/core/db/LocalDB.js +27 -12
- package/dist/core/field/RichTextField.d.ts +30 -3
- package/dist/core/field/RichTextField.js +124 -56
- package/dist/core/media/MediaAltField.d.ts +1 -0
- package/dist/core/media/MediaAltField.js +9 -1
- package/dist/core/media/MediaLocation.d.ts +5 -2
- package/dist/core/media/MediaLocation.js +6 -7
- package/dist/core/media/MediaTypes.js +11 -0
- package/dist/core/source/CombinedSource.d.ts +2 -2
- package/dist/core/source/CombinedSource.js +6 -3
- package/dist/core/source/FSSource.d.ts +4 -3
- package/dist/core/source/FSSource.js +59 -27
- package/dist/core/source/GithubSource.d.ts +2 -2
- package/dist/core/source/GithubSource.js +21 -9
- package/dist/core/source/IndexedDBSource.d.ts +2 -2
- package/dist/core/source/IndexedDBSource.js +3 -1
- package/dist/core/source/MemorySource.d.ts +2 -2
- package/dist/core/source/MemorySource.js +3 -1
- package/dist/core/source/OverlaySource.d.ts +12 -0
- package/dist/core/source/OverlaySource.js +50 -0
- package/dist/core/source/Source.d.ts +5 -2
- package/dist/core/source/Source.js +3 -3
- package/dist/core/util/Async.d.ts +8 -2
- package/dist/core/util/Async.js +67 -0
- package/dist/core/util/EntryFilenames.d.ts +2 -2
- package/dist/core/util/EntryFilenames.js +3 -3
- package/dist/dashboard/App.css +158 -0
- package/dist/dashboard/App.js +2 -2
- package/dist/dashboard/app/AccessDenied.js +3 -3
- package/dist/dashboard/app/ActivityStatus.js +15 -15
- package/dist/dashboard/app/AppShell.js +1 -1
- package/dist/dashboard/app/AuthView.js +11 -11
- package/dist/dashboard/app/CompactField.js +10 -10
- package/dist/dashboard/app/DashboardErrorBoundary.js +5 -5
- package/dist/dashboard/app/DashboardLayout.js +22 -19
- package/dist/dashboard/app/EntryHeader.js +12 -12
- package/dist/dashboard/app/EntryReferences.js +9 -9
- package/dist/dashboard/app/EntrySidebar.d.ts +1 -1
- package/dist/dashboard/app/EntrySidebar.js +17 -16
- package/dist/dashboard/app/EntrySidebarPreview.d.ts +1 -1
- package/dist/dashboard/app/EntrySidebarPreview.js +19 -14
- package/dist/dashboard/app/EntryTranslationBanner.js +7 -7
- package/dist/dashboard/app/Explorer.js +51 -43
- package/dist/dashboard/app/ExplorerCards.js +34 -34
- package/dist/dashboard/app/ExplorerFileCard.js +18 -18
- package/dist/dashboard/app/ExplorerList.js +13 -13
- package/dist/dashboard/app/ExplorerModal.js +3 -3
- package/dist/dashboard/app/ExplorerTable.js +76 -61
- package/dist/dashboard/app/ExternalLinkPicker.js +15 -4
- package/dist/dashboard/app/LinkPicker.js +8 -8
- package/dist/dashboard/app/LocaleMenu.js +12 -12
- package/dist/dashboard/app/SidebarLayout.d.ts +8 -0
- package/dist/dashboard/app/SidebarLayout.js +1169 -0
- package/dist/dashboard/app/SidebarTree.js +46 -46
- package/dist/dashboard/app/WorkspaceMenu.js +17 -17
- package/dist/dashboard/app/WorkspaceRoots.js +23 -23
- package/dist/dashboard/app/editor/FileEditor.d.ts +2 -1
- package/dist/dashboard/app/editor/FileEditor.js +41 -32
- package/dist/dashboard/app/editor/FilePreview.js +4 -4
- package/dist/dashboard/app/editor/MediaAltField.view.d.ts +1 -1
- package/dist/dashboard/app/editor/MediaAltField.view.js +6 -9
- package/dist/dashboard/app/modals/CreateEntry.js +4 -4
- package/dist/dashboard/app/pages/EntryPage.js +57 -31
- package/dist/dashboard/app/pages/UsersPage.js +33 -33
- package/dist/dashboard/app/ui/DashboardModal.js +23 -23
- package/dist/dashboard/app/ui/Rail.js +3 -3
- package/dist/dashboard/app/ui/Sidebar.js +2 -2
- package/dist/dashboard/atoms/auth.js +2 -0
- package/dist/dashboard/atoms/dashboard.d.ts +9 -0
- package/dist/dashboard/atoms/dashboard.js +17 -0
- package/dist/dashboard/atoms/editor.d.ts +7 -1
- package/dist/dashboard/atoms/editor.js +4 -1
- package/dist/dashboard/atoms/entry.d.ts +48 -2
- package/dist/dashboard/atoms/entry.js +222 -17
- package/dist/dashboard/atoms/explorer.js +4 -9
- package/dist/dashboard/atoms/preview.d.ts +3 -0
- package/dist/dashboard/atoms/preview.js +18 -1
- package/dist/dashboard/atoms/root.d.ts +4 -1
- package/dist/dashboard/atoms/root.js +96 -157
- package/dist/dashboard/hooks.d.ts +4 -2
- package/dist/dashboard/hooks.js +9 -5
- package/dist/dashboard/icons.d.ts +1 -0
- package/dist/dashboard/icons.js +10 -0
- package/dist/field/check/CheckField.view.js +2 -2
- package/dist/field/code/CodeField.view.js +12 -12
- package/dist/field/date/DateField.view.js +12 -2
- package/dist/field/link/FileLink.d.ts +2 -2
- package/dist/field/link/FileLink.js +5 -3
- package/dist/field/link/ImageLink.d.ts +1 -1
- package/dist/field/link/ImageLink.js +1 -1
- package/dist/field/link/Link.js +2 -2
- package/dist/field/link/LinkField.view.js +155 -128
- package/dist/field/list/ListField.view.js +22 -33
- package/dist/field/metadata/MetadataField.view.js +19 -19
- package/dist/field/number/NumberField.d.ts +2 -0
- package/dist/field/number/NumberField.view.js +4 -2
- package/dist/field/richtext/PickTextLink.d.ts +7 -0
- package/dist/field/richtext/PickTextLink.js +104 -2
- package/dist/field/richtext/ReferenceLink.d.ts +4 -1
- package/dist/field/richtext/ReferenceLink.js +18 -4
- package/dist/field/richtext/RichTextDocument.d.ts +7 -2
- package/dist/field/richtext/RichTextDocument.js +34 -5
- package/dist/field/richtext/RichTextExtensions.d.ts +3 -1
- package/dist/field/richtext/RichTextExtensions.js +2704 -7467
- package/dist/field/richtext/RichTextField.d.ts +4 -0
- package/dist/field/richtext/RichTextField.story.d.ts +4 -0
- package/dist/field/richtext/RichTextField.view.js +43 -20
- package/dist/field/richtext/RichTextInsertMenu.js +281 -495
- package/dist/field/richtext/RichTextToolbar.d.ts +5 -2
- package/dist/field/richtext/RichTextToolbar.js +38 -3
- package/dist/field/richtext/Toolbar.d.ts +19 -1
- package/dist/field/richtext/Toolbar.js +18 -13
- package/dist/field/richtext/extensions/Anchor.js +1 -1
- package/dist/field/richtext/extensions/Link.js +1 -1
- package/dist/field/richtext/extensions/Small.js +1 -1
- package/dist/field/select/SelectField.view.js +8 -6
- package/dist/index.css +227 -16
- package/dist/next.cjs +18 -16
- package/dist/next.d.ts +2 -1
- package/dist/next.edge.d.ts +2 -1
- package/dist/picker/entry/EntryPicker.js +9 -35
- package/dist/preview/PreviewPayload.js +35 -250
- package/dist/ui/RichText.d.ts +1 -0
- package/dist/ui/RichText.js +29 -2
- package/package.json +6 -3
- package/dist/cli/util/ExternalPlugin.d.ts +0 -2
- package/dist/cli/util/ExternalPlugin.js +0 -919
- package/dist/chunks/{chunk-JFROOUG6.js → chunk-NIVGVRDS.js} +17 -17
|
@@ -10,12 +10,13 @@ function createCMS() {
|
|
|
10
10
|
);
|
|
11
11
|
}
|
|
12
12
|
function withAlinea(config = {}) {
|
|
13
|
-
const
|
|
14
|
-
if (!
|
|
13
|
+
const settings = resolveSettings(config);
|
|
14
|
+
if (!settings) {
|
|
15
15
|
console.warn(
|
|
16
|
-
"Alinea dashboard settings
|
|
16
|
+
"Alinea dashboard settings were not provided; dashboard routing is disabled. Run Next.js through the Alinea CLI."
|
|
17
17
|
);
|
|
18
18
|
}
|
|
19
|
+
const adminPath = settings?.adminPath;
|
|
19
20
|
let nextVersion = 15;
|
|
20
21
|
try {
|
|
21
22
|
const require2 = createRequire(resolve("./index.js"));
|
|
@@ -39,6 +40,10 @@ function withAlinea(config = {}) {
|
|
|
39
40
|
};
|
|
40
41
|
const redirects = adminPath ? createRedirects(config, adminPath) : config.redirects;
|
|
41
42
|
const rewrites = adminPath ? createRewrites(config, adminPath) : config.rewrites;
|
|
43
|
+
const env = settings ? {
|
|
44
|
+
...config.env,
|
|
45
|
+
ALINEA_ADMIN_PATH: settings.adminPath
|
|
46
|
+
} : config.env;
|
|
42
47
|
if (nextVersion < 15)
|
|
43
48
|
return {
|
|
44
49
|
...config,
|
|
@@ -51,7 +56,8 @@ function withAlinea(config = {}) {
|
|
|
51
56
|
},
|
|
52
57
|
images,
|
|
53
58
|
redirects,
|
|
54
|
-
rewrites
|
|
59
|
+
rewrites,
|
|
60
|
+
env
|
|
55
61
|
};
|
|
56
62
|
return {
|
|
57
63
|
...config,
|
|
@@ -61,7 +67,8 @@ function withAlinea(config = {}) {
|
|
|
61
67
|
],
|
|
62
68
|
images,
|
|
63
69
|
redirects,
|
|
64
|
-
rewrites
|
|
70
|
+
rewrites,
|
|
71
|
+
env
|
|
65
72
|
};
|
|
66
73
|
}
|
|
67
74
|
function createRedirects(config, adminPath) {
|
|
@@ -124,17 +131,12 @@ function createRewrites(config, adminPath) {
|
|
|
124
131
|
};
|
|
125
132
|
};
|
|
126
133
|
}
|
|
127
|
-
function
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
);
|
|
134
|
-
if (typeof settings.adminPath === "string" && settings.adminPath)
|
|
135
|
-
return normalizeBasePath(settings.adminPath);
|
|
136
|
-
} catch {
|
|
137
|
-
}
|
|
134
|
+
function resolveSettings(config) {
|
|
135
|
+
const adminPath = config.env?.ALINEA_ADMIN_PATH ?? process.env.ALINEA_ADMIN_PATH;
|
|
136
|
+
if (!adminPath) return;
|
|
137
|
+
return {
|
|
138
|
+
adminPath: normalizeBasePath(adminPath)
|
|
139
|
+
};
|
|
138
140
|
}
|
|
139
141
|
function normalizeBasePath(value) {
|
|
140
142
|
return value.startsWith("/") ? value : `/${value}`;
|
|
@@ -1,24 +1,25 @@
|
|
|
1
|
-
import type { Entry } from 'alinea/core';
|
|
2
1
|
import type { CMS } from 'alinea/core/CMS';
|
|
3
|
-
import type { RemoteConnection, RequestContext } from 'alinea/core/Connection';
|
|
4
|
-
import
|
|
2
|
+
import type { AuthedContext, RemoteConnection, RequestContext } from 'alinea/core/Connection';
|
|
3
|
+
import { LocalDB } from 'alinea/core/db/LocalDB';
|
|
4
|
+
import type { Mutation } from 'alinea/core/db/Mutation';
|
|
5
5
|
export interface Handler {
|
|
6
6
|
(request: Request, context: RequestContext): Promise<Response>;
|
|
7
7
|
}
|
|
8
|
-
export type HookResponse<T = void> = void | T | Promise<
|
|
8
|
+
export type HookResponse<T = void> = void | T | Promise<void | T>;
|
|
9
|
+
export interface BeforeCommitContext {
|
|
10
|
+
mutations: ReadonlyArray<Mutation>;
|
|
11
|
+
}
|
|
12
|
+
export interface AfterCommitContext extends BeforeCommitContext {
|
|
13
|
+
sha: string;
|
|
14
|
+
}
|
|
9
15
|
export interface HandlerHooks {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
beforeUpdate?(entry: Entry): HookResponse<Entry>;
|
|
13
|
-
afterUpdate?(entry: Entry): HookResponse;
|
|
14
|
-
beforeArchive?(entryId: string): HookResponse;
|
|
15
|
-
afterArchive?(entryId: string): HookResponse;
|
|
16
|
-
beforeRemove?(entryId: string): HookResponse;
|
|
17
|
-
afterRemove?(entryId: string): HookResponse;
|
|
16
|
+
beforeCommit?(context: BeforeCommitContext): HookResponse<ReadonlyArray<Mutation>>;
|
|
17
|
+
afterCommit?(context: AfterCommitContext): HookResponse;
|
|
18
18
|
}
|
|
19
19
|
export interface HandlerOptions extends HandlerHooks {
|
|
20
20
|
cms: CMS;
|
|
21
21
|
db: LocalDB | Promise<LocalDB>;
|
|
22
22
|
remote?: (context: RequestContext) => RemoteConnection;
|
|
23
|
+
forwardMutations?(request: Request, context: AuthedContext): Promise<Response | undefined>;
|
|
23
24
|
}
|
|
24
|
-
export declare function createHandler({ cms, remote, db, ...hooks }: HandlerOptions): Handler;
|
|
25
|
+
export declare function createHandler({ cms, remote, db, forwardMutations, ...hooks }: HandlerOptions): Handler;
|
package/dist/backend/Handler.js
CHANGED
|
@@ -13,6 +13,11 @@ import "../chunks/chunk-CQ52GEHY.js";
|
|
|
13
13
|
// src/backend/Handler.ts
|
|
14
14
|
import { JWTPreviews } from "alinea/backend/util/JWTPreviews";
|
|
15
15
|
import { CloudRemote } from "alinea/cloud/CloudRemote";
|
|
16
|
+
import {
|
|
17
|
+
BLOB_SEQUENCE_CONTENT_TYPE,
|
|
18
|
+
encodeBlobSequence
|
|
19
|
+
} from "alinea/core/BlobTransport";
|
|
20
|
+
import { developmentKeyHeader } from "alinea/core/Connection";
|
|
16
21
|
import { ErrorCode, HttpError } from "alinea/core/HttpError";
|
|
17
22
|
import { assertUploadSize } from "alinea/core/media/UploadLimits";
|
|
18
23
|
import { Permission, Policy } from "alinea/core/Role";
|
|
@@ -22,7 +27,8 @@ import { base64 } from "alinea/core/util/Encoding";
|
|
|
22
27
|
import { isRecord } from "alinea/core/util/Objects";
|
|
23
28
|
import { InvalidCredentialsError, MissingCredentialsError } from "./Auth.js";
|
|
24
29
|
import { HandleAction } from "./HandleAction.js";
|
|
25
|
-
import {
|
|
30
|
+
import { applyPreview, decodePreviewRequest } from "./resolver/ParsePreview.js";
|
|
31
|
+
import { compressResponse } from "./router/Router.js";
|
|
26
32
|
import { createThrottledSync } from "./util/Syncable.js";
|
|
27
33
|
var PrepareBody = object({
|
|
28
34
|
filename: string,
|
|
@@ -32,13 +38,10 @@ function createHandler({
|
|
|
32
38
|
cms,
|
|
33
39
|
remote = (context) => new CloudRemote(context, cms.config),
|
|
34
40
|
db,
|
|
41
|
+
forwardMutations,
|
|
35
42
|
...hooks
|
|
36
43
|
}) {
|
|
37
44
|
const throttle = createThrottledSync();
|
|
38
|
-
const previewParser = PLazy.from(async () => {
|
|
39
|
-
const local = await db;
|
|
40
|
-
return createPreviewParser(local);
|
|
41
|
-
});
|
|
42
45
|
return async function handle(request, context) {
|
|
43
46
|
const dev = process.env.ALINEA_DEV_SERVER;
|
|
44
47
|
const local = await db;
|
|
@@ -88,11 +91,10 @@ function createHandler({
|
|
|
88
91
|
};
|
|
89
92
|
} catch (cause) {
|
|
90
93
|
if (cause instanceof MissingCredentialsError) {
|
|
91
|
-
const
|
|
92
|
-
const bearer = authorization?.slice("Bearer ".length);
|
|
94
|
+
const credential = context.isDev ? request.headers.get(developmentKeyHeader) : request.headers.get("authorization")?.slice("Bearer ".length);
|
|
93
95
|
if (!context.apiKey)
|
|
94
96
|
throw new MissingCredentialsError("Missing API key", { cause });
|
|
95
|
-
if (
|
|
97
|
+
if (credential !== context.apiKey)
|
|
96
98
|
throw new InvalidCredentialsError("Expected matching api key", {
|
|
97
99
|
cause
|
|
98
100
|
});
|
|
@@ -159,43 +161,77 @@ function createHandler({
|
|
|
159
161
|
const scope = getScope(cms.config);
|
|
160
162
|
const query = scope.parse(raw);
|
|
161
163
|
if (!query.preview) {
|
|
162
|
-
await periodicSync(
|
|
164
|
+
await periodicSync(
|
|
165
|
+
cnx,
|
|
166
|
+
query.disableSync ? Number.POSITIVE_INFINITY : query.syncInterval ?? cms.config.syncInterval
|
|
167
|
+
);
|
|
163
168
|
} else {
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
|
|
169
|
+
const preview = await decodePreviewRequest(query.preview);
|
|
170
|
+
if ("contentHash" in preview && local.sha !== preview.contentHash)
|
|
171
|
+
await local.syncWith(cnx);
|
|
172
|
+
query.preview = await applyPreview(local, preview);
|
|
167
173
|
}
|
|
168
174
|
return Response.json(await local.resolve(query) ?? null);
|
|
169
175
|
}
|
|
170
176
|
if (action === HandleAction.Mutate && request.method === "POST") {
|
|
177
|
+
if (forwardMutations && userCtx) {
|
|
178
|
+
const forwarded = await forwardMutations(request.clone(), userCtx);
|
|
179
|
+
if (forwarded) return forwarded;
|
|
180
|
+
}
|
|
171
181
|
const user = expectUser();
|
|
172
182
|
expectJson();
|
|
173
183
|
const policy = await user.policy;
|
|
174
|
-
|
|
184
|
+
let mutations = await body;
|
|
185
|
+
await local.syncWith(cnx);
|
|
186
|
+
const adjusted = await hooks.beforeCommit?.({ mutations });
|
|
187
|
+
if (adjusted) mutations = adjusted;
|
|
175
188
|
const attempt = async (retry = 0) => {
|
|
176
|
-
await local.syncWith(cnx);
|
|
189
|
+
if (retry > 0) await local.syncWith(cnx);
|
|
177
190
|
const request2 = {
|
|
178
191
|
...await local.request(mutations, policy),
|
|
179
192
|
user: user.claims
|
|
180
193
|
};
|
|
181
194
|
try {
|
|
182
|
-
let { sha } = await cnx.write(request2);
|
|
183
|
-
if (
|
|
195
|
+
let { sha: sha2 } = await cnx.write(request2);
|
|
196
|
+
if (sha2 === request2.intoSha) {
|
|
184
197
|
await local.write(request2);
|
|
185
198
|
} else {
|
|
186
|
-
|
|
199
|
+
sha2 = await local.syncWith(cnx);
|
|
187
200
|
}
|
|
188
|
-
return
|
|
201
|
+
return sha2;
|
|
189
202
|
} catch (error) {
|
|
190
|
-
|
|
191
|
-
|
|
203
|
+
const isConflict = error instanceof ShaMismatchError || error instanceof HttpError && error.code === 409 || error instanceof Response && error.status === 409;
|
|
204
|
+
if (isConflict && retry < 3) return attempt(retry + 1);
|
|
192
205
|
throw error;
|
|
193
206
|
}
|
|
194
207
|
};
|
|
195
|
-
|
|
208
|
+
const sha = await attempt();
|
|
209
|
+
try {
|
|
210
|
+
await hooks.afterCommit?.({
|
|
211
|
+
mutations,
|
|
212
|
+
sha
|
|
213
|
+
});
|
|
214
|
+
} catch (error) {
|
|
215
|
+
console.error("Alinea afterCommit hook failed", error);
|
|
216
|
+
}
|
|
217
|
+
return Response.json({ sha });
|
|
196
218
|
}
|
|
197
219
|
if (action === HandleAction.Commit && request.method === "POST") {
|
|
198
|
-
|
|
220
|
+
if (!context.isDev)
|
|
221
|
+
throw new HttpError(400, "Commits are only accepted in development");
|
|
222
|
+
const developmentKey = request.headers.get(developmentKeyHeader);
|
|
223
|
+
if (!context.apiKey || developmentKey !== context.apiKey)
|
|
224
|
+
throw new HttpError(401, "Invalid development commit credentials");
|
|
225
|
+
const user = expectUser();
|
|
226
|
+
expectJson();
|
|
227
|
+
const commit = {
|
|
228
|
+
...await body,
|
|
229
|
+
user: user.claims
|
|
230
|
+
};
|
|
231
|
+
let { sha } = await cnx.write(commit);
|
|
232
|
+
if (sha === commit.intoSha) await local.write(commit);
|
|
233
|
+
else sha = await local.syncWith(cnx);
|
|
234
|
+
return Response.json({ sha });
|
|
199
235
|
}
|
|
200
236
|
if (action === HandleAction.History && request.method === "GET") {
|
|
201
237
|
expectUser();
|
|
@@ -210,7 +246,7 @@ function createHandler({
|
|
|
210
246
|
const sha = string(url.searchParams.get("sha"));
|
|
211
247
|
await local.syncWith(cnx);
|
|
212
248
|
const tree = await local.getTreeIfDifferent(sha);
|
|
213
|
-
return Response.json(tree ?? null);
|
|
249
|
+
return compressResponse(request, Response.json(tree ?? null));
|
|
214
250
|
}
|
|
215
251
|
if (action === HandleAction.Blob && request.method === "POST") {
|
|
216
252
|
const { shas } = object({ shas: array(string) })(await body);
|
|
@@ -222,20 +258,18 @@ function createHandler({
|
|
|
222
258
|
if (tree.hasSha(sha)) fromLocal.push(sha);
|
|
223
259
|
else fromRemote.push(sha);
|
|
224
260
|
}
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
}
|
|
261
|
+
async function* blobs() {
|
|
262
|
+
const options = { signal: request.signal };
|
|
263
|
+
if (fromLocal.length > 0)
|
|
264
|
+
yield* local.source.getBlobs(fromLocal, options);
|
|
265
|
+
if (fromRemote.length > 0) yield* cnx.getBlobs(fromRemote, options);
|
|
231
266
|
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
return new Response(formData);
|
|
267
|
+
return compressResponse(
|
|
268
|
+
request,
|
|
269
|
+
new Response(encodeBlobSequence(blobs()), {
|
|
270
|
+
headers: { "content-type": BLOB_SEQUENCE_CONTENT_TYPE }
|
|
271
|
+
})
|
|
272
|
+
);
|
|
239
273
|
}
|
|
240
274
|
if (action === HandleAction.Upload) {
|
|
241
275
|
const user = expectUser();
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import type { LocalDB } from 'alinea/core/db/LocalDB';
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
import { Entry } from 'alinea/core/Entry';
|
|
3
|
+
import type { PreviewRequest, PreviewUpdate } from 'alinea/core/Preview';
|
|
4
|
+
export interface DecodedEntryPreview {
|
|
5
|
+
entry: Entry;
|
|
6
|
+
}
|
|
7
|
+
export type DecodedPreviewRequest = PreviewUpdate | DecodedEntryPreview;
|
|
8
|
+
export declare function decodePreviewRequest(preview: PreviewRequest): Promise<DecodedPreviewRequest>;
|
|
9
|
+
export declare function applyPreview(local: LocalDB, preview: DecodedPreviewRequest): Promise<PreviewRequest | undefined>;
|
|
@@ -5,53 +5,50 @@ import { JsonLoader } from "alinea/backend/loader/JsonLoader";
|
|
|
5
5
|
import { Entry } from "alinea/core/Entry";
|
|
6
6
|
import { createRecord, parseRecord } from "alinea/core/EntryRecord";
|
|
7
7
|
import { applyFilePatch } from "alinea/core/source/FilePatch";
|
|
8
|
+
import { trace } from "alinea/core/Trace";
|
|
8
9
|
import { createEntryRow } from "alinea/core/util/EntryRows";
|
|
9
10
|
import { decodePreviewPayload } from "alinea/preview/PreviewPayload";
|
|
10
11
|
var decoder = new TextDecoder();
|
|
11
|
-
function
|
|
12
|
-
return
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
try {
|
|
35
|
-
updatedText = await applyFilePatch(baseText, payload.patch);
|
|
36
|
-
} catch {
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
const { data } = parseRecord(JSON.parse(updatedText));
|
|
40
|
-
const { rowHash: _rowHash, fileHash: _fileHash, ...withoutHashes } = entry;
|
|
41
|
-
const patched = await createEntryRow(
|
|
42
|
-
local.config,
|
|
43
|
-
{
|
|
44
|
-
...withoutHashes,
|
|
45
|
-
title: data.title,
|
|
46
|
-
data,
|
|
47
|
-
path: entry.path
|
|
48
|
-
},
|
|
49
|
-
entry.status
|
|
50
|
-
);
|
|
51
|
-
return { entry: patched };
|
|
12
|
+
async function decodePreviewRequest(preview) {
|
|
13
|
+
if ("entry" in preview) return preview;
|
|
14
|
+
return decodePreviewPayload(preview.payload);
|
|
15
|
+
}
|
|
16
|
+
async function applyPreview(local, preview) {
|
|
17
|
+
if ("entry" in preview) return preview;
|
|
18
|
+
const span = trace(local.config, "alinea.preview.apply");
|
|
19
|
+
return span(async () => {
|
|
20
|
+
const entry = await local.first({
|
|
21
|
+
select: Entry,
|
|
22
|
+
id: preview.entryId,
|
|
23
|
+
locale: preview.locale,
|
|
24
|
+
status: "preferDraft"
|
|
25
|
+
});
|
|
26
|
+
if (!entry) return;
|
|
27
|
+
const baseText = decoder.decode(
|
|
28
|
+
JsonLoader.format(local.config.schema, createRecord(entry, entry.status))
|
|
29
|
+
);
|
|
30
|
+
let updatedText;
|
|
31
|
+
try {
|
|
32
|
+
updatedText = await applyFilePatch(baseText, preview.patch);
|
|
33
|
+
} catch {
|
|
34
|
+
return;
|
|
52
35
|
}
|
|
53
|
-
|
|
36
|
+
const { data } = parseRecord(JSON.parse(updatedText));
|
|
37
|
+
const { rowHash: _rowHash, fileHash: _fileHash, ...withoutHashes } = entry;
|
|
38
|
+
const patched = await createEntryRow(
|
|
39
|
+
local.config,
|
|
40
|
+
{
|
|
41
|
+
...withoutHashes,
|
|
42
|
+
title: data.title,
|
|
43
|
+
data,
|
|
44
|
+
path: entry.path
|
|
45
|
+
},
|
|
46
|
+
entry.status
|
|
47
|
+
);
|
|
48
|
+
return { entry: patched };
|
|
49
|
+
});
|
|
54
50
|
}
|
|
55
51
|
export {
|
|
56
|
-
|
|
52
|
+
applyPreview,
|
|
53
|
+
decodePreviewRequest
|
|
57
54
|
};
|
|
@@ -144,4 +144,5 @@ export declare namespace router {
|
|
|
144
144
|
function cookie(...cookies: Array<Cookie>): string;
|
|
145
145
|
function compress(...routes: Array<Next<Request, Response | undefined>>): Route<Request, Response | undefined>;
|
|
146
146
|
}
|
|
147
|
+
export declare function compressResponse(request: Request, response: Response): Response;
|
|
147
148
|
export {};
|
|
@@ -186,27 +186,33 @@ function callHandler(handler, input) {
|
|
|
186
186
|
async (request) => {
|
|
187
187
|
const response = await route.handle(request);
|
|
188
188
|
if (response === void 0) return void 0;
|
|
189
|
-
|
|
190
|
-
if (!body) return response;
|
|
191
|
-
const isCompressed = response.headers.get("content-encoding");
|
|
192
|
-
if (isCompressed) return response;
|
|
193
|
-
const accept = request.headers.get("accept-encoding");
|
|
194
|
-
const method = accept?.includes("gzip") ? "gzip" : accept?.includes("deflate") ? "deflate" : void 0;
|
|
195
|
-
if (method === void 0) return response;
|
|
196
|
-
const stream = body.pipeThrough(new CompressionStream(method));
|
|
197
|
-
const headers = new Headers(response.headers);
|
|
198
|
-
headers.set("content-encoding", method);
|
|
199
|
-
headers.delete("content-length");
|
|
200
|
-
return new Response(stream, {
|
|
201
|
-
headers,
|
|
202
|
-
status: response.status
|
|
203
|
-
});
|
|
189
|
+
return compressResponse(request, response);
|
|
204
190
|
}
|
|
205
191
|
);
|
|
206
192
|
}
|
|
207
193
|
router2.compress = compress;
|
|
208
194
|
})(router || (router = {}));
|
|
195
|
+
function compressResponse(request, response) {
|
|
196
|
+
const body = response.body;
|
|
197
|
+
if (!body) return response;
|
|
198
|
+
const isCompressed = response.headers.get("content-encoding");
|
|
199
|
+
if (isCompressed) return response;
|
|
200
|
+
const accept = request.headers.get("accept-encoding");
|
|
201
|
+
const method = accept?.includes("gzip") ? "gzip" : accept?.includes("deflate") ? "deflate" : void 0;
|
|
202
|
+
if (method === void 0) return response;
|
|
203
|
+
const stream = body.pipeThrough(new CompressionStream(method));
|
|
204
|
+
const headers = new Headers(response.headers);
|
|
205
|
+
headers.set("content-encoding", method);
|
|
206
|
+
headers.set("vary", "accept-encoding");
|
|
207
|
+
headers.delete("content-length");
|
|
208
|
+
return new Response(stream, {
|
|
209
|
+
headers,
|
|
210
|
+
status: response.status,
|
|
211
|
+
statusText: response.statusText
|
|
212
|
+
});
|
|
213
|
+
}
|
|
209
214
|
export {
|
|
210
215
|
Route,
|
|
216
|
+
compressResponse,
|
|
211
217
|
router
|
|
212
218
|
};
|