@caretcms/core 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +116 -11
- package/dist/index.d.ts +15 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +78 -5
- package/dist/index.js.map +1 -1
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +8 -0
- package/dist/loader.js.map +1 -1
- package/dist/markdown/paragraphs.d.ts +14 -0
- package/dist/markdown/paragraphs.d.ts.map +1 -0
- package/dist/markdown/paragraphs.js +61 -0
- package/dist/markdown/paragraphs.js.map +1 -0
- package/dist/markdown/remark.d.ts.map +1 -1
- package/dist/markdown/remark.js +1 -0
- package/dist/markdown/remark.js.map +1 -1
- package/dist/markdown/satteri.d.ts.map +1 -1
- package/dist/markdown/satteri.js +3 -1
- package/dist/markdown/satteri.js.map +1 -1
- package/dist/markdown/stamp.d.ts +0 -9
- package/dist/markdown/stamp.d.ts.map +1 -1
- package/dist/markdown/stamp.js +6 -0
- package/dist/markdown/stamp.js.map +1 -1
- package/dist/providers/deployment/github.d.ts +27 -0
- package/dist/providers/deployment/github.d.ts.map +1 -0
- package/dist/providers/deployment/github.js +180 -0
- package/dist/providers/deployment/github.js.map +1 -0
- package/dist/providers/deployment/simulated.d.ts +10 -0
- package/dist/providers/deployment/simulated.d.ts.map +1 -0
- package/dist/providers/deployment/simulated.js +29 -0
- package/dist/providers/deployment/simulated.js.map +1 -0
- package/dist/runtime/authorization.d.ts +11 -0
- package/dist/runtime/authorization.d.ts.map +1 -0
- package/dist/runtime/authorization.js +29 -0
- package/dist/runtime/authorization.js.map +1 -0
- package/dist/runtime/collection-policy.d.ts +11 -0
- package/dist/runtime/collection-policy.d.ts.map +1 -0
- package/dist/runtime/collection-policy.js +44 -0
- package/dist/runtime/collection-policy.js.map +1 -0
- package/dist/runtime/content-errors.d.ts +9 -0
- package/dist/runtime/content-errors.d.ts.map +1 -0
- package/dist/runtime/content-errors.js +17 -0
- package/dist/runtime/content-errors.js.map +1 -0
- package/dist/runtime/content.d.ts.map +1 -1
- package/dist/runtime/content.js +13 -4
- package/dist/runtime/content.js.map +1 -1
- package/dist/runtime/deployment-status.d.ts +14 -0
- package/dist/runtime/deployment-status.d.ts.map +1 -0
- package/dist/runtime/deployment-status.js +57 -0
- package/dist/runtime/deployment-status.js.map +1 -0
- package/dist/runtime/draft-state.d.ts +16 -0
- package/dist/runtime/draft-state.d.ts.map +1 -0
- package/dist/runtime/draft-state.js +29 -0
- package/dist/runtime/draft-state.js.map +1 -0
- package/dist/runtime/i18n.d.ts +13 -2
- package/dist/runtime/i18n.d.ts.map +1 -1
- package/dist/runtime/i18n.js +26 -4
- package/dist/runtime/i18n.js.map +1 -1
- package/dist/runtime/index.d.ts +1 -0
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/index.js +1 -0
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/middleware.d.ts.map +1 -1
- package/dist/runtime/middleware.js +21 -2
- package/dist/runtime/middleware.js.map +1 -1
- package/dist/runtime/mutations/contracts.d.ts +9 -0
- package/dist/runtime/mutations/contracts.d.ts.map +1 -1
- package/dist/runtime/mutations/contracts.js +45 -4
- package/dist/runtime/mutations/contracts.js.map +1 -1
- package/dist/runtime/mutations/engine.d.ts +2 -0
- package/dist/runtime/mutations/engine.d.ts.map +1 -1
- package/dist/runtime/mutations/engine.js +115 -63
- package/dist/runtime/mutations/engine.js.map +1 -1
- package/dist/runtime/providers.d.ts +3 -1
- package/dist/runtime/providers.d.ts.map +1 -1
- package/dist/runtime/providers.js +12 -1
- package/dist/runtime/providers.js.map +1 -1
- package/dist/runtime/publish-recovery.d.ts +32 -0
- package/dist/runtime/publish-recovery.d.ts.map +1 -0
- package/dist/runtime/publish-recovery.js +98 -0
- package/dist/runtime/publish-recovery.js.map +1 -0
- package/dist/runtime/publish.d.ts +10 -4
- package/dist/runtime/publish.d.ts.map +1 -1
- package/dist/runtime/publish.js +104 -67
- package/dist/runtime/publish.js.map +1 -1
- package/dist/runtime/rebuild-webhook.d.ts +4 -0
- package/dist/runtime/rebuild-webhook.d.ts.map +1 -1
- package/dist/runtime/rebuild-webhook.js +12 -2
- package/dist/runtime/rebuild-webhook.js.map +1 -1
- package/dist/runtime/request-context.d.ts +3 -1
- package/dist/runtime/request-context.d.ts.map +1 -1
- package/dist/runtime/request-context.js.map +1 -1
- package/dist/runtime/rewrite.d.ts.map +1 -1
- package/dist/runtime/rewrite.js +28 -2
- package/dist/runtime/rewrite.js.map +1 -1
- package/dist/runtime/rich-allowlist.js +1 -1
- package/dist/runtime/rich-allowlist.js.map +1 -1
- package/dist/runtime/routes/admin-entry.d.ts.map +1 -1
- package/dist/runtime/routes/admin-entry.js +24 -12
- package/dist/runtime/routes/admin-entry.js.map +1 -1
- package/dist/runtime/routes/auth-session.d.ts.map +1 -1
- package/dist/runtime/routes/auth-session.js +6 -0
- package/dist/runtime/routes/auth-session.js.map +1 -1
- package/dist/runtime/routes/collection-list.d.ts.map +1 -1
- package/dist/runtime/routes/collection-list.js +164 -40
- package/dist/runtime/routes/collection-list.js.map +1 -1
- package/dist/runtime/routes/deployment.d.ts +5 -0
- package/dist/runtime/routes/deployment.d.ts.map +1 -0
- package/dist/runtime/routes/deployment.js +38 -0
- package/dist/runtime/routes/deployment.js.map +1 -0
- package/dist/runtime/routes/draft.d.ts.map +1 -1
- package/dist/runtime/routes/draft.js +10 -3
- package/dist/runtime/routes/draft.js.map +1 -1
- package/dist/runtime/routes/entries.d.ts.map +1 -1
- package/dist/runtime/routes/entries.js +74 -39
- package/dist/runtime/routes/entries.js.map +1 -1
- package/dist/runtime/routes/history.d.ts.map +1 -1
- package/dist/runtime/routes/history.js +37 -21
- package/dist/runtime/routes/history.js.map +1 -1
- package/dist/runtime/routes/mutate.d.ts.map +1 -1
- package/dist/runtime/routes/mutate.js +4 -1
- package/dist/runtime/routes/mutate.js.map +1 -1
- package/dist/runtime/routes/publish.d.ts.map +1 -1
- package/dist/runtime/routes/publish.js +127 -33
- package/dist/runtime/routes/publish.js.map +1 -1
- package/dist/runtime/routes/schema.d.ts.map +1 -1
- package/dist/runtime/routes/schema.js +4 -0
- package/dist/runtime/routes/schema.js.map +1 -1
- package/dist/runtime/routes/studio-home.d.ts.map +1 -1
- package/dist/runtime/routes/studio-home.js +3 -1
- package/dist/runtime/routes/studio-home.js.map +1 -1
- package/dist/runtime/routes/upload.d.ts.map +1 -1
- package/dist/runtime/routes/upload.js +3 -0
- package/dist/runtime/routes/upload.js.map +1 -1
- package/dist/runtime/schema-registry.d.ts.map +1 -1
- package/dist/runtime/schema-registry.js +2 -0
- package/dist/runtime/schema-registry.js.map +1 -1
- package/dist/runtime/storage/entry-commit.d.ts +8 -0
- package/dist/runtime/storage/entry-commit.d.ts.map +1 -0
- package/dist/runtime/storage/entry-commit.js +45 -0
- package/dist/runtime/storage/entry-commit.js.map +1 -0
- package/dist/runtime/storage/filesystem-adapter.d.ts +5 -0
- package/dist/runtime/storage/filesystem-adapter.d.ts.map +1 -1
- package/dist/runtime/storage/filesystem-adapter.js +12 -3
- package/dist/runtime/storage/filesystem-adapter.js.map +1 -1
- package/dist/runtime/storage/frontmatter-codec.d.ts +5 -23
- package/dist/runtime/storage/frontmatter-codec.d.ts.map +1 -1
- package/dist/runtime/storage/frontmatter-codec.js +156 -13
- package/dist/runtime/storage/frontmatter-codec.js.map +1 -1
- package/dist/runtime/storage/in-memory-adapter.d.ts +7 -0
- package/dist/runtime/storage/in-memory-adapter.d.ts.map +1 -1
- package/dist/runtime/storage/in-memory-adapter.js +6 -0
- package/dist/runtime/storage/in-memory-adapter.js.map +1 -1
- package/dist/runtime/storage/markdown-adapter.d.ts.map +1 -1
- package/dist/runtime/storage/markdown-adapter.js +18 -20
- package/dist/runtime/storage/markdown-adapter.js.map +1 -1
- package/dist/runtime/storage/session-overlay-adapter.d.ts +12 -4
- package/dist/runtime/storage/session-overlay-adapter.d.ts.map +1 -1
- package/dist/runtime/storage/session-overlay-adapter.js +100 -13
- package/dist/runtime/storage/session-overlay-adapter.js.map +1 -1
- package/dist/runtime/storage/sidecar-meta-store.d.ts +5 -0
- package/dist/runtime/storage/sidecar-meta-store.d.ts.map +1 -1
- package/dist/runtime/storage/sidecar-meta-store.js +48 -5
- package/dist/runtime/storage/sidecar-meta-store.js.map +1 -1
- package/dist/runtime/utils.d.ts.map +1 -1
- package/dist/runtime/utils.js +3 -4
- package/dist/runtime/utils.js.map +1 -1
- package/dist/types.d.ts +123 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +12 -3
- package/static/cms/admin-entry.css +9 -0
- package/static/cms/admin-entry.js +251 -687
- package/static/cms/dev-toolbar/app.js +78 -19
- package/static/cms/editor/config.js +35 -15
- package/static/cms/editor/content-map.css +8 -1
- package/static/cms/editor/content-map.js +62 -23
- package/static/cms/editor/deployment-status.js +66 -0
- package/static/cms/editor/draft-client.js +87 -0
- package/static/cms/editor/guards.js +20 -0
- package/static/cms/editor/helpers.js +30 -1
- package/static/cms/editor/highlight.js +1 -0
- package/static/cms/editor/image-edit.js +43 -1
- package/static/cms/editor/image-utils.js +23 -7
- package/static/cms/editor/link-follow.js +122 -41
- package/static/cms/editor/link-ui.css +10 -1
- package/static/cms/editor/linkify.js +2 -0
- package/static/cms/editor/md-block-edit.js +140 -37
- package/static/cms/editor/md-paragraphs.js +98 -0
- package/static/cms/editor/md-serialize.js +1 -1
- package/static/cms/editor/panel.js +43 -15
- package/static/cms/editor/preview-mode.js +44 -0
- package/static/cms/editor/publish-result.js +100 -0
- package/static/cms/editor/rich-toolbar.js +58 -15
- package/static/cms/editor/sanitize.js +6 -2
- package/static/cms/editor/save-queue.js +75 -17
- package/static/cms/editor/section-controls/activation.js +3 -0
- package/static/cms/editor/section-controls/api.js +25 -7
- package/static/cms/editor/section-controls/index.js +60 -8
- package/static/cms/editor/section-controls/model.js +39 -4
- package/static/cms/editor/section-controls/mutations.js +15 -0
- package/static/cms/editor/section-controls/page-context.js +9 -0
- package/static/cms/editor/section-controls/pickers.js +53 -2
- package/static/cms/editor/section-controls/reorder.js +23 -0
- package/static/cms/editor/section-controls/selection.js +6 -0
- package/static/cms/editor/section-controls/spacing-drag.js +16 -0
- package/static/cms/editor/section-controls/ui-elements.js +7 -0
- package/static/cms/editor/section-controls/utils.js +7 -0
- package/static/cms/editor/section-controls.css +18 -3
- package/static/cms/editor/security.js +13 -2
- package/static/cms/editor/stega-hydrate.js +17 -4
- package/static/cms/editor/sync.js +208 -10
- package/static/cms/editor/text-edit.js +37 -3
- package/static/cms/editor/text-link-interactions.js +59 -17
- package/static/cms/editor/toast.js +23 -9
- package/static/cms/editor/toolbar.css +5 -0
- package/static/cms/editor/toolbar.js +91 -101
- package/static/cms/editor.js +2 -1
- package/static/cms/studio/entry-loader.js +102 -0
- package/static/cms/studio/field-model.js +110 -0
- package/static/cms/studio/fields.js +319 -0
- package/static/cms/studio/history-client.js +74 -0
- package/static/cms/studio/mutation-client.js +74 -0
- package/static/cms/studio/sync-client.js +107 -0
- package/static/cms/studio/upload-client.js +109 -0
|
@@ -31,12 +31,23 @@ async function createIdentityAdapter() {
|
|
|
31
31
|
return testServicesOverride.identityAdapter;
|
|
32
32
|
return await providerModule?.loadConfiguredIdentityAdapter?.() ?? null;
|
|
33
33
|
}
|
|
34
|
+
async function createDeploymentStatusProvider() {
|
|
35
|
+
if (testServicesOverride?.deploymentStatusProvider)
|
|
36
|
+
return testServicesOverride.deploymentStatusProvider;
|
|
37
|
+
return await providerModule?.loadConfiguredDeploymentStatus?.() ?? null;
|
|
38
|
+
}
|
|
34
39
|
export async function getRuntimeServices() {
|
|
35
40
|
if (!runtimeServicesPromise) {
|
|
36
|
-
const inflight = Promise.all([
|
|
41
|
+
const inflight = Promise.all([
|
|
42
|
+
createAdapter(),
|
|
43
|
+
createUploadHandler(),
|
|
44
|
+
createIdentityAdapter(),
|
|
45
|
+
createDeploymentStatusProvider(),
|
|
46
|
+
]).then(([adapter, uploadHandler, identityAdapter, deploymentStatusProvider]) => ({
|
|
37
47
|
adapter,
|
|
38
48
|
uploadHandler,
|
|
39
49
|
identityAdapter,
|
|
50
|
+
deploymentStatusProvider,
|
|
40
51
|
allowedClasses: testServicesOverride?.allowedClasses ?? providerModule?.allowedClasses ?? {},
|
|
41
52
|
delivery: testServicesOverride?.delivery ??
|
|
42
53
|
providerModule?.delivery ?? {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"providers.js","sourceRoot":"","sources":["../../src/runtime/providers.ts"],"names":[],"mappings":"AACA,+EAA+E;AAC/E,8EAA8E;AAC9E,+EAA+E;AAC/E,2EAA2E;AAC3E,OAAO,KAAK,gBAAgB,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"providers.js","sourceRoot":"","sources":["../../src/runtime/providers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { HistoryEntry, StorageAdapter } from "../types.js";
|
|
2
|
+
export interface PublishRecovery {
|
|
3
|
+
version: 1;
|
|
4
|
+
beforeRevision: number;
|
|
5
|
+
beforeData: Record<string, unknown> | null;
|
|
6
|
+
afterData: Record<string, unknown> | null;
|
|
7
|
+
beforeSource?: string;
|
|
8
|
+
afterSource?: string;
|
|
9
|
+
history: HistoryEntry & {
|
|
10
|
+
operationId: string;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export declare class RecoveryConflict extends Error {
|
|
14
|
+
}
|
|
15
|
+
export declare function recoveryState(data: Record<string, unknown>): PublishRecovery | null;
|
|
16
|
+
/** Prepare the entire Markdown file before any source write, preserving untouched YAML. */
|
|
17
|
+
export declare function prepareSource(source: string, before: Record<string, unknown> | null, after: Record<string, unknown>, blocks: ReadonlyArray<{
|
|
18
|
+
md: string;
|
|
19
|
+
src: {
|
|
20
|
+
start: number;
|
|
21
|
+
end: number;
|
|
22
|
+
hash: string;
|
|
23
|
+
};
|
|
24
|
+
}>): string | null;
|
|
25
|
+
/**
|
|
26
|
+
* Forward recovery under the entry lock. The overlay's atomic write persists
|
|
27
|
+
* this plan before touching base content. Each subsequent step is checked so a
|
|
28
|
+
* lost acknowledgement/restart cannot apply the source edit or revision twice.
|
|
29
|
+
* This is recoverability, not atomic visibility or a distributed transaction.
|
|
30
|
+
*/
|
|
31
|
+
export declare function resumePublish(base: StorageAdapter, overlay: StorageAdapter, collection: string, id: string, plan: PublishRecovery): Promise<number>;
|
|
32
|
+
//# sourceMappingURL=publish-recovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publish-recovery.d.ts","sourceRoot":"","sources":["../../src/runtime/publish-recovery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAMhE,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,CAAC,CAAC;IACX,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC3C,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC1C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,YAAY,GAAG;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;CACjD;AAED,qBAAa,gBAAiB,SAAQ,KAAK;CAAG;AAE9C,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,eAAe,GAAG,IAAI,CAcnF;AAED,2FAA2F;AAC3F,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,EACtC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,MAAM,EAAE,aAAa,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAC,GACvF,MAAM,GAAG,IAAI,CAOf;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAC7E,IAAI,EAAE,eAAe,GACpB,OAAO,CAAC,MAAM,CAAC,CAmDjB"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { PUBLISH_RECOVERY_KEY, sameContent } from "./draft-state.js";
|
|
2
|
+
import { rewriteFrontmatter } from "./storage/frontmatter-codec.js";
|
|
3
|
+
import { spliceBodyBlocks } from "../markdown/splice.js";
|
|
4
|
+
import { commitEntryChanges } from "./storage/entry-commit.js";
|
|
5
|
+
export class RecoveryConflict extends Error {
|
|
6
|
+
}
|
|
7
|
+
export function recoveryState(data) {
|
|
8
|
+
const raw = data[PUBLISH_RECOVERY_KEY];
|
|
9
|
+
if (raw === undefined)
|
|
10
|
+
return null;
|
|
11
|
+
const r = raw;
|
|
12
|
+
const recordOrNull = (value) => value === null ||
|
|
13
|
+
(typeof value === "object" && !Array.isArray(value));
|
|
14
|
+
if (!r || r.version !== 1 || !Number.isSafeInteger(r.beforeRevision) || r.beforeRevision < 0 ||
|
|
15
|
+
!recordOrNull(r.beforeData) || !recordOrNull(r.afterData) ||
|
|
16
|
+
!r.history || typeof r.history.operationId !== "string" || !Number.isFinite(r.history.ts) ||
|
|
17
|
+
(r.beforeSource !== undefined && typeof r.beforeSource !== "string") ||
|
|
18
|
+
(r.afterSource !== undefined && typeof r.afterSource !== "string")) {
|
|
19
|
+
throw new RecoveryConflict("Invalid publish recovery record");
|
|
20
|
+
}
|
|
21
|
+
return r;
|
|
22
|
+
}
|
|
23
|
+
/** Prepare the entire Markdown file before any source write, preserving untouched YAML. */
|
|
24
|
+
export function prepareSource(source, before, after, blocks) {
|
|
25
|
+
const spliced = spliceBodyBlocks(source, blocks);
|
|
26
|
+
if (!spliced.ok)
|
|
27
|
+
return null;
|
|
28
|
+
if (sameContent(before, after))
|
|
29
|
+
return spliced.content;
|
|
30
|
+
const rewritten = rewriteFrontmatter(spliced.content, after);
|
|
31
|
+
if (!rewritten.ok)
|
|
32
|
+
throw new Error("Cannot prepare source content");
|
|
33
|
+
return rewritten.content;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Forward recovery under the entry lock. The overlay's atomic write persists
|
|
37
|
+
* this plan before touching base content. Each subsequent step is checked so a
|
|
38
|
+
* lost acknowledgement/restart cannot apply the source edit or revision twice.
|
|
39
|
+
* This is recoverability, not atomic visibility or a distributed transaction.
|
|
40
|
+
*/
|
|
41
|
+
export async function resumePublish(base, overlay, collection, id, plan) {
|
|
42
|
+
const revision = await base.getRevision(collection, id);
|
|
43
|
+
const current = (await base.getEntry(collection, id))?.data ?? null;
|
|
44
|
+
const source = plan.beforeSource !== undefined && base.readBodySource
|
|
45
|
+
? await base.readBodySource(collection, id) : undefined;
|
|
46
|
+
const atBefore = sameContent(current, plan.beforeData) &&
|
|
47
|
+
(plan.beforeSource === undefined || source === plan.beforeSource);
|
|
48
|
+
const atAfter = sameContent(current, plan.afterData) &&
|
|
49
|
+
(plan.afterSource === undefined || source === plan.afterSource);
|
|
50
|
+
if ((!atBefore && !atAfter) || (revision !== plan.beforeRevision && revision !== plan.beforeRevision + 1) ||
|
|
51
|
+
(revision === plan.beforeRevision + 1 && !atAfter)) {
|
|
52
|
+
throw new RecoveryConflict("Published content changed during recovery");
|
|
53
|
+
}
|
|
54
|
+
let committedTransition = false;
|
|
55
|
+
if (!atAfter) {
|
|
56
|
+
if (plan.afterSource === undefined) {
|
|
57
|
+
const committed = await commitEntryChanges(base, [{
|
|
58
|
+
collection,
|
|
59
|
+
id,
|
|
60
|
+
expectedRevision: plan.beforeRevision,
|
|
61
|
+
expectedExists: plan.beforeData !== null,
|
|
62
|
+
data: plan.afterData,
|
|
63
|
+
history: plan.history,
|
|
64
|
+
}]);
|
|
65
|
+
if (!committed.ok)
|
|
66
|
+
throw new RecoveryConflict("Published content changed during recovery");
|
|
67
|
+
committedTransition = true;
|
|
68
|
+
}
|
|
69
|
+
else if (base.writeBodySource) {
|
|
70
|
+
await base.writeBodySource(collection, id, plan.afterSource);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
throw new RecoveryConflict("Source-backed publication is unavailable");
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (!committedTransition && revision === plan.beforeRevision) {
|
|
77
|
+
const next = await base.bumpRevision(collection, id);
|
|
78
|
+
if (next !== plan.beforeRevision + 1)
|
|
79
|
+
throw new RecoveryConflict("Unexpected revision during recovery");
|
|
80
|
+
}
|
|
81
|
+
if (!committedTransition) {
|
|
82
|
+
const history = await base.getHistory(collection, id);
|
|
83
|
+
if (!history.some(entry => entry.operationId === plan.history.operationId)) {
|
|
84
|
+
await base.appendHistory(collection, id, plan.history);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const overlayRevision = await overlay.getRevision(collection, id);
|
|
88
|
+
const overlayEntry = await overlay.getEntry(collection, id);
|
|
89
|
+
if (overlayEntry) {
|
|
90
|
+
const cleared = await commitEntryChanges(overlay, [{
|
|
91
|
+
collection, id, expectedRevision: overlayRevision, expectedExists: true, data: null,
|
|
92
|
+
}]);
|
|
93
|
+
if (!cleared.ok)
|
|
94
|
+
throw new RecoveryConflict("Draft changed during publication cleanup");
|
|
95
|
+
}
|
|
96
|
+
return plan.afterData === null ? 0 : plan.beforeRevision + 1;
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=publish-recovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publish-recovery.js","sourceRoot":"","sources":["../../src/runtime/publish-recovery.ts"],"names":[],"mappings":"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"}
|
|
@@ -22,15 +22,21 @@ export interface PublishedEntry {
|
|
|
22
22
|
export interface PublishConflict {
|
|
23
23
|
collection: string;
|
|
24
24
|
id: string;
|
|
25
|
-
/**
|
|
26
|
-
*
|
|
27
|
-
|
|
28
|
-
reason: "stale_body" | "invalid_body";
|
|
25
|
+
/** Body hashes, structured baselines, or legacy drafts failed validation.
|
|
26
|
+
* The entry was not published and its draft is preserved. */
|
|
27
|
+
reason: "stale_body" | "invalid_body" | "stale_entry" | "legacy_draft";
|
|
29
28
|
}
|
|
30
29
|
export interface PublishOutcome {
|
|
31
30
|
published: PublishedEntry[];
|
|
32
31
|
conflicts: PublishConflict[];
|
|
32
|
+
failed: Array<{
|
|
33
|
+
collection: string;
|
|
34
|
+
id: string;
|
|
35
|
+
reason: "storage_error" | "recovery_conflict";
|
|
36
|
+
}>;
|
|
33
37
|
}
|
|
38
|
+
/** Preflight the entire batch before any source, revision, journal or hook write. */
|
|
39
|
+
export declare function canPublishOverlay(overlay: StorageAdapter, scope?: PublishScope): Promise<boolean>;
|
|
34
40
|
/**
|
|
35
41
|
* Flush the overlay into the base. A tombstoned draft entry deletes from the
|
|
36
42
|
* base; any other draft entry is written, the base revision bumped, and a
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"publish.d.ts","sourceRoot":"","sources":["../../src/runtime/publish.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"publish.d.ts","sourceRoot":"","sources":["../../src/runtime/publish.ts"],"names":[],"mappings":"AACA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AASlD,MAAM,WAAW,YAAY;IAC3B,8EAA8E;IAC9E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mEAAmE;IACnE,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,iEAAiE;IACjE,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IACX;iEAC6D;IAC7D,MAAM,EAAE,YAAY,GAAG,cAAc,GAAG,aAAa,GAAG,cAAc,CAAC;CACxE;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,cAAc,EAAE,CAAC;IAC5B,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,MAAM,EAAE,KAAK,CAAC;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,eAAe,GAAG,mBAAmB,CAAA;KAAE,CAAC,CAAC;CAClG;AAoDD,qFAAqF;AACrF,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,GAAE,YAAiB,GAAG,OAAO,CAAC,OAAO,CAAC,CAW3G;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,cAAc,EACpB,OAAO,EAAE,cAAc,EACvB,KAAK,GAAE,YAAiB,GACvB,OAAO,CAAC,cAAc,CAAC,CA4EzB;AAED,+DAA+D;AAC/D,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,cAAc,EACvB,KAAK,GAAE,YAAiB,GACvB,OAAO,CAAC,MAAM,CAAC,CAEjB;AAED;6CAC6C;AAC7C,wBAAsB,cAAc,CAClC,OAAO,EAAE,cAAc,EACvB,KAAK,GAAE,YAAiB,GACvB,OAAO,CAAC,MAAM,CAAC,CAgBjB"}
|
package/dist/runtime/publish.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
|
+
import { canPerform, PermissionDenied } from "./authorization.js";
|
|
1
2
|
import { BODY_OVERLAY_KEY, parseMdSrc, formatMdSrc } from "../markdown/contracts.js";
|
|
2
3
|
import { withEntryLock } from "./mutations/engine.js";
|
|
3
4
|
import { TOMBSTONE_KEY } from "./storage/session-overlay-adapter.js";
|
|
5
|
+
import { DRAFT_STATE_KEY, PUBLISH_RECOVERY_KEY, readDraftState, sameContent } from "./draft-state.js";
|
|
6
|
+
import { prepareSource, recoveryState, resumePublish, RecoveryConflict } from "./publish-recovery.js";
|
|
4
7
|
import { getRequestContext } from "./request-context.js";
|
|
8
|
+
import { commitEntryChanges } from "./storage/entry-commit.js";
|
|
5
9
|
/** Extract + validate the body-draft map from draft data, or null when absent.
|
|
6
10
|
* `undefined` return = present but malformed (never publish through it). */
|
|
7
11
|
function extractBodyBlocks(data) {
|
|
@@ -48,6 +52,23 @@ async function overlayEntriesInScope(overlay, scope) {
|
|
|
48
52
|
}
|
|
49
53
|
return out;
|
|
50
54
|
}
|
|
55
|
+
/** Preflight the entire batch before any source, revision, journal or hook write. */
|
|
56
|
+
export async function canPublishOverlay(overlay, scope = {}) {
|
|
57
|
+
if (!getRequestContext()?.authorize)
|
|
58
|
+
return true;
|
|
59
|
+
const targets = await overlayEntriesInScope(overlay, scope);
|
|
60
|
+
if (!targets.length)
|
|
61
|
+
return canPerform("publish", scope.collection, scope.id);
|
|
62
|
+
for (const { collection, id } of targets) {
|
|
63
|
+
if (!(await canPerform("publish", collection, id)))
|
|
64
|
+
return false;
|
|
65
|
+
const draft = await overlay.getEntry(collection, id);
|
|
66
|
+
const plan = draft ? recoveryState(draft.data) : null;
|
|
67
|
+
if ((isTombstoneData(draft?.data) || plan?.afterData === null) && !(await canPerform("delete", collection, id)))
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
51
72
|
/**
|
|
52
73
|
* Flush the overlay into the base. A tombstoned draft entry deletes from the
|
|
53
74
|
* base; any other draft entry is written, the base revision bumped, and a
|
|
@@ -61,79 +82,83 @@ async function overlayEntriesInScope(overlay, scope) {
|
|
|
61
82
|
* surface "publish all" should report that list.
|
|
62
83
|
*/
|
|
63
84
|
export async function publishOverlay(base, overlay, scope = {}) {
|
|
85
|
+
if (!(await canPublishOverlay(overlay, scope)))
|
|
86
|
+
throw new PermissionDenied();
|
|
64
87
|
const targets = await overlayEntriesInScope(overlay, scope);
|
|
65
88
|
const published = [];
|
|
66
89
|
const conflicts = [];
|
|
90
|
+
const failed = [];
|
|
67
91
|
for (const { collection, id } of targets) {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
92
|
+
try {
|
|
93
|
+
await withEntryLock(collection, id, async () => {
|
|
94
|
+
const draftRevision = await overlay.getRevision(collection, id);
|
|
95
|
+
const draft = await overlay.getEntry(collection, id);
|
|
96
|
+
if (!draft)
|
|
97
|
+
return;
|
|
98
|
+
let plan = recoveryState(draft.data);
|
|
99
|
+
if (!plan) {
|
|
100
|
+
const state = readDraftState(draft.data);
|
|
101
|
+
const { [BODY_OVERLAY_KEY]: _body, [DRAFT_STATE_KEY]: _state, [PUBLISH_RECOVERY_KEY]: _recovery, [TOMBSTONE_KEY]: _tombstone, ...fields } = draft.data;
|
|
102
|
+
const blocks = extractBodyBlocks(draft.data);
|
|
103
|
+
if (blocks === undefined) {
|
|
104
|
+
conflicts.push({ collection, id, reason: "invalid_body" });
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const deleted = isTombstoneData(draft.data);
|
|
108
|
+
const structured = state?.structured ?? (deleted || Object.keys(fields).length > 0);
|
|
109
|
+
if (!state && structured) {
|
|
110
|
+
conflicts.push({ collection, id, reason: "legacy_draft" });
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const before = (await base.getEntry(collection, id))?.data ?? null;
|
|
114
|
+
const beforeRevision = await base.getRevision(collection, id);
|
|
115
|
+
if (structured && state && (state.baseRevision !== beforeRevision || !sameContent(state.baseData, before))) {
|
|
116
|
+
conflicts.push({ collection, id, reason: "stale_entry" });
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
const after = deleted ? null : structured ? fields : { ...(before ?? {}), ...fields };
|
|
120
|
+
const source = base.readBodySource ? await base.readBodySource(collection, id) : null;
|
|
121
|
+
if (blocks?.length && (!source || !base.writeBodySource)) {
|
|
122
|
+
conflicts.push({ collection, id, reason: "invalid_body" });
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
const afterSource = source !== null && after !== null && base.writeBodySource
|
|
126
|
+
? prepareSource(source, before, after, blocks ?? []) : undefined;
|
|
127
|
+
if (afterSource === null) {
|
|
128
|
+
conflicts.push({ collection, id, reason: "stale_body" });
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
const context = getRequestContext();
|
|
132
|
+
const editor = context?.identity ?? (context?.editorId ? { id: context.editorId } : null);
|
|
133
|
+
plan = {
|
|
134
|
+
version: 1, beforeRevision, beforeData: before, afterData: after,
|
|
135
|
+
...(source !== null ? { beforeSource: source } : {}),
|
|
136
|
+
...(afterSource !== undefined ? { afterSource } : {}),
|
|
137
|
+
history: { operationId: crypto.randomUUID(), ts: Date.now(), action: "publish", data: before,
|
|
138
|
+
...(source !== null ? { bodySource: source } : {}), ...(editor ? { editor } : {}) },
|
|
139
|
+
};
|
|
140
|
+
const persisted = await commitEntryChanges(overlay, [{
|
|
141
|
+
collection,
|
|
142
|
+
id,
|
|
143
|
+
expectedRevision: draftRevision,
|
|
144
|
+
expectedExists: true,
|
|
145
|
+
data: { ...draft.data, [PUBLISH_RECOVERY_KEY]: plan },
|
|
146
|
+
}]);
|
|
147
|
+
if (!persisted.ok) {
|
|
148
|
+
conflicts.push({ collection, id, reason: "stale_entry" });
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
100
151
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
// Merge the draft's frontmatter DELTAS onto the current base rather than
|
|
104
|
-
// replacing it. A body-only draft carries no frontmatter keys, so base
|
|
105
|
-
// fields edited after the draft was staged (e.g. a Studio field save,
|
|
106
|
-
// which writes straight to base in server delivery) survive instead of
|
|
107
|
-
// being clobbered by a stale snapshot. Skip the write entirely when the
|
|
108
|
-
// merge changes nothing — a body-only publish must not re-serialize
|
|
109
|
-
// untouched frontmatter (it re-quotes scalars and pollutes the diff).
|
|
110
|
-
// Same-shape objects come through the same parse path, so stringify
|
|
111
|
-
// comparison is order-stable here.
|
|
112
|
-
const mergedData = { ...(before?.data ?? {}), ...entryData };
|
|
113
|
-
if (JSON.stringify(before?.data ?? null) !== JSON.stringify(mergedData)) {
|
|
114
|
-
await base.writeEntry(collection, id, mergedData);
|
|
115
|
-
}
|
|
116
|
-
const revision = await base.bumpRevision(collection, id);
|
|
117
|
-
const requestContext = getRequestContext();
|
|
118
|
-
const editor = requestContext?.identity
|
|
119
|
-
?? (requestContext?.editorId ? { id: requestContext.editorId } : null);
|
|
120
|
-
await base.appendHistory(collection, id, {
|
|
121
|
-
ts: Date.now(),
|
|
122
|
-
action: "publish",
|
|
123
|
-
data: before?.data ?? null,
|
|
124
|
-
// Pre-publish source file, so a restore can put the prose back.
|
|
125
|
-
...(bodySource !== undefined ? { bodySource } : {}),
|
|
126
|
-
...(editor ? { editor } : {}),
|
|
152
|
+
const revision = await resumePublish(base, overlay, collection, id, plan);
|
|
153
|
+
published.push({ collection, id, revision, deleted: plan.afterData === null });
|
|
127
154
|
});
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
else if (result)
|
|
134
|
-
published.push(result);
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
console.error("[caretcms] Publish requires recovery:", error);
|
|
158
|
+
failed.push({ collection, id, reason: error instanceof RecoveryConflict ? "recovery_conflict" : "storage_error" });
|
|
159
|
+
}
|
|
135
160
|
}
|
|
136
|
-
return { published, conflicts };
|
|
161
|
+
return { published, conflicts, failed };
|
|
137
162
|
}
|
|
138
163
|
/** Count draft entries currently held in an editor overlay. */
|
|
139
164
|
export async function countOverlayDrafts(overlay, scope = {}) {
|
|
@@ -144,7 +169,19 @@ export async function countOverlayDrafts(overlay, scope = {}) {
|
|
|
144
169
|
export async function discardOverlay(overlay, scope = {}) {
|
|
145
170
|
const targets = await overlayEntriesInScope(overlay, scope);
|
|
146
171
|
for (const { collection, id } of targets) {
|
|
147
|
-
await withEntryLock(collection, id, () =>
|
|
172
|
+
await withEntryLock(collection, id, async () => {
|
|
173
|
+
const revision = await overlay.getRevision(collection, id);
|
|
174
|
+
const draft = await overlay.getEntry(collection, id);
|
|
175
|
+
if (draft?.data[PUBLISH_RECOVERY_KEY])
|
|
176
|
+
throw new Error("Finish pending publication before discarding drafts");
|
|
177
|
+
if (draft) {
|
|
178
|
+
const discarded = await commitEntryChanges(overlay, [{
|
|
179
|
+
collection, id, expectedRevision: revision, expectedExists: true, data: null,
|
|
180
|
+
}]);
|
|
181
|
+
if (!discarded.ok)
|
|
182
|
+
throw new Error("Draft changed while it was being discarded");
|
|
183
|
+
}
|
|
184
|
+
});
|
|
148
185
|
}
|
|
149
186
|
return targets.length;
|
|
150
187
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"publish.js","sourceRoot":"","sources":["../../src/runtime/publish.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"publish.js","sourceRoot":"","sources":["../../src/runtime/publish.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,6 +2,8 @@ export interface RebuildWebhookConfig {
|
|
|
2
2
|
webhookUrl: string | null;
|
|
3
3
|
method?: "POST" | "PUT";
|
|
4
4
|
headers?: Record<string, string>;
|
|
5
|
+
/** Defaults to 5 seconds, bounded to 30 seconds. */
|
|
6
|
+
timeoutMs?: number;
|
|
5
7
|
}
|
|
6
8
|
export interface RebuildWebhookPayload {
|
|
7
9
|
published: Array<{
|
|
@@ -11,6 +13,8 @@ export interface RebuildWebhookPayload {
|
|
|
11
13
|
deleted: boolean;
|
|
12
14
|
}>;
|
|
13
15
|
commit: string | null;
|
|
16
|
+
/** Correlates this request with deployment status provider results. */
|
|
17
|
+
deploymentId?: string;
|
|
14
18
|
}
|
|
15
19
|
export type RebuildWebhookResult = {
|
|
16
20
|
triggered: false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rebuild-webhook.d.ts","sourceRoot":"","sources":["../../src/runtime/rebuild-webhook.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"rebuild-webhook.d.ts","sourceRoot":"","sources":["../../src/runtime/rebuild-webhook.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,KAAK,CAAC;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IACzF,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,uEAAuE;IACvE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,MAAM,oBAAoB,GAC5B;IAAE,SAAS,EAAE,KAAK,CAAC;IAAC,EAAE,EAAE,IAAI,CAAA;CAAE,GAC9B;IAAE,SAAS,EAAE,IAAI,CAAC;IAAC,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC7C;IAAE,SAAS,EAAE,IAAI,CAAC;IAAC,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnE,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,oBAAoB,EAC5B,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,oBAAoB,CAAC,CA4C/B"}
|
|
@@ -2,8 +2,12 @@ export async function triggerRebuildWebhook(config, payload) {
|
|
|
2
2
|
const webhookUrl = config.webhookUrl?.trim();
|
|
3
3
|
if (!webhookUrl)
|
|
4
4
|
return { triggered: false, ok: true };
|
|
5
|
+
const controller = new AbortController();
|
|
6
|
+
const timeout = Number.isFinite(config.timeoutMs) ? Math.max(1, Math.min(config.timeoutMs, 30_000)) : 5_000;
|
|
7
|
+
const timer = setTimeout(() => controller.abort(), timeout);
|
|
5
8
|
try {
|
|
6
9
|
const response = await fetch(webhookUrl, {
|
|
10
|
+
signal: controller.signal,
|
|
7
11
|
method: config.method ?? "POST",
|
|
8
12
|
headers: {
|
|
9
13
|
"content-type": "application/json",
|
|
@@ -14,8 +18,11 @@ export async function triggerRebuildWebhook(config, payload) {
|
|
|
14
18
|
event: "publish",
|
|
15
19
|
published: payload.published,
|
|
16
20
|
commit: payload.commit,
|
|
21
|
+
...(payload.deploymentId ? { deploymentId: payload.deploymentId } : {}),
|
|
17
22
|
}),
|
|
18
23
|
});
|
|
24
|
+
// Only acknowledgement headers matter; don't leave a streaming response open.
|
|
25
|
+
void response.body?.cancel().catch(() => { });
|
|
19
26
|
if (!response.ok) {
|
|
20
27
|
return {
|
|
21
28
|
triggered: true,
|
|
@@ -26,12 +33,15 @@ export async function triggerRebuildWebhook(config, payload) {
|
|
|
26
33
|
}
|
|
27
34
|
return { triggered: true, ok: true, status: response.status };
|
|
28
35
|
}
|
|
29
|
-
catch
|
|
36
|
+
catch {
|
|
30
37
|
return {
|
|
31
38
|
triggered: true,
|
|
32
39
|
ok: false,
|
|
33
|
-
error:
|
|
40
|
+
error: controller.signal.aborted ? "Rebuild webhook timed out" : "Could not reach rebuild webhook",
|
|
34
41
|
};
|
|
35
42
|
}
|
|
43
|
+
finally {
|
|
44
|
+
clearTimeout(timer);
|
|
45
|
+
}
|
|
36
46
|
}
|
|
37
47
|
//# sourceMappingURL=rebuild-webhook.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rebuild-webhook.js","sourceRoot":"","sources":["../../src/runtime/rebuild-webhook.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"rebuild-webhook.js","sourceRoot":"","sources":["../../src/runtime/rebuild-webhook.ts"],"names":[],"mappings":"AAoBA,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,MAA4B,EAC5B,OAA8B;IAE9B,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC;IAC7C,IAAI,CAAC,UAAU;QAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IAEvD,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,SAAU,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IAC7G,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,OAAO,CAAC,CAAC;IAC5D,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,UAAU,EAAE;YACvC,MAAM,EAAE,UAAU,CAAC,MAAM;YACzB,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,MAAM;YAC/B,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,GAAG,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC;aAC1B;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,MAAM,EAAE,UAAU;gBAClB,KAAK,EAAE,SAAS;gBAChB,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACxE,CAAC;SACH,CAAC,CAAC;QAEH,8EAA8E;QAC9E,KAAK,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAE7C,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,OAAO;gBACL,SAAS,EAAE,IAAI;gBACf,EAAE,EAAE,KAAK;gBACT,MAAM,EAAE,QAAQ,CAAC,MAAM;gBACvB,KAAK,EAAE,sCAAsC,QAAQ,CAAC,MAAM,EAAE;aAC/D,CAAC;QACJ,CAAC;QAED,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;IAChE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;YACL,SAAS,EAAE,IAAI;YACf,EAAE,EAAE,KAAK;YACT,KAAK,EAAE,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAC,CAAC,iCAAiC;SACnG,CAAC;IACJ,CAAC;YAAS,CAAC;QAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IAAC,CAAC;AACpC,CAAC"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import type { EditorIdentity, StorageAdapter, UploadHandler } from "../types.js";
|
|
1
|
+
import type { AuthorizationAction, EditorIdentity, StorageAdapter, UploadHandler } from "../types.js";
|
|
2
2
|
export interface CaretRequestContext {
|
|
3
3
|
adapter: StorageAdapter;
|
|
4
|
+
/** A request-bound, fail-closed policy. Omitted in legacy full-access mode. */
|
|
5
|
+
authorize?: (action: AuthorizationAction, collection?: string, id?: string) => Promise<boolean>;
|
|
4
6
|
uploadHandler: UploadHandler;
|
|
5
7
|
sessionId: string | null;
|
|
6
8
|
demoMode: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request-context.d.ts","sourceRoot":"","sources":["../../src/runtime/request-context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"request-context.d.ts","sourceRoot":"","sources":["../../src/runtime/request-context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEtG,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,cAAc,CAAC;IACxB,+EAA+E;IAC/E,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,mBAAmB,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAChG,aAAa,EAAE,aAAa,CAAC;IAC7B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;IACjC,8EAA8E;IAC9E,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC;;;;;OAKG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC7C;AAUD,wBAAgB,qBAAqB,CAAC,CAAC,EACrC,OAAO,EAAE,mBAAmB,EAC5B,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACnB,OAAO,CAAC,CAAC,CAAC,CAEZ;AAED,wBAAgB,iBAAiB,IAAI,mBAAmB,GAAG,SAAS,CAEnE;AAED,wBAAgB,qBAAqB,IAAI,mBAAmB,CAQ3D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request-context.js","sourceRoot":"","sources":["../../src/runtime/request-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"request-context.js","sourceRoot":"","sources":["../../src/runtime/request-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AA2CrD,0EAA0E;AAC1E,+EAA+E;AAC/E,yEAAyE;AACzE,MAAM,iBAAiB,GAAG,MAAM,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;AACvE,MAAM,WAAW,GAAG,UAAyD,CAAC;AAC9E,MAAM,OAAO,GAAG,CAAC,WAAW,CAAC,iBAAiB,CAAC;IAC7C,IAAI,iBAAiB,EAAuB,CAA2C,CAAC;AAE1F,MAAM,UAAU,qBAAqB,CACnC,OAA4B,EAC5B,EAAoB;IAEpB,OAAO,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,OAAO,OAAO,CAAC,QAAQ,EAAE,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,qBAAqB;IACnC,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAC/B,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,KAAK,CACb,kIAAkI,CACnI,CAAC;IACJ,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rewrite.d.ts","sourceRoot":"","sources":["../../src/runtime/rewrite.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAa,MAAM,aAAa,CAAC;AAqB7D,KAAK,UAAU,GAAG;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC;AASF;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,uMAKvB,CAAC;AAkJX;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,UAAU,GAAG,IAAI,GACvB;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAY1D;AA2CD,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,cAAc,EACvB,OAAO,CAAC,EAAE;IAAE,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAAA;CAAE,GAC/D,OAAO,CAAC,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"rewrite.d.ts","sourceRoot":"","sources":["../../src/runtime/rewrite.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAa,MAAM,aAAa,CAAC;AAqB7D,KAAK,UAAU,GAAG;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC;AASF;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,uMAKvB,CAAC;AAkJX;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,UAAU,GAAG,IAAI,GACvB;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAY1D;AA2CD,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,cAAc,EACvB,OAAO,CAAC,EAAE;IAAE,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAAA;CAAE,GAC/D,OAAO,CAAC,MAAM,CAAC,CA4MjB"}
|