@contentrail/publisher 0.0.0-stage → 0.2.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.
Files changed (55) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +137 -2
  3. package/dist/engine.d.ts +34 -0
  4. package/dist/engine.d.ts.map +1 -0
  5. package/dist/engine.js +196 -0
  6. package/dist/engine.js.map +1 -0
  7. package/dist/errors.d.ts +28 -0
  8. package/dist/errors.d.ts.map +1 -0
  9. package/dist/errors.js +35 -0
  10. package/dist/errors.js.map +1 -0
  11. package/dist/fakes/memory-git.d.ts +12 -0
  12. package/dist/fakes/memory-git.d.ts.map +1 -0
  13. package/dist/fakes/memory-git.js +56 -0
  14. package/dist/fakes/memory-git.js.map +1 -0
  15. package/dist/fakes/memory-r2.d.ts +12 -0
  16. package/dist/fakes/memory-r2.d.ts.map +1 -0
  17. package/dist/fakes/memory-r2.js +59 -0
  18. package/dist/fakes/memory-r2.js.map +1 -0
  19. package/dist/index.d.ts +15 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +12 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/paths.d.ts +4 -0
  24. package/dist/paths.d.ts.map +1 -0
  25. package/dist/paths.js +43 -0
  26. package/dist/paths.js.map +1 -0
  27. package/dist/providers/git-client.d.ts +31 -0
  28. package/dist/providers/git-client.d.ts.map +1 -0
  29. package/dist/providers/git-client.js +2 -0
  30. package/dist/providers/git-client.js.map +1 -0
  31. package/dist/providers/git.d.ts +10 -0
  32. package/dist/providers/git.d.ts.map +1 -0
  33. package/dist/providers/git.js +311 -0
  34. package/dist/providers/git.js.map +1 -0
  35. package/dist/providers/r2-client.d.ts +19 -0
  36. package/dist/providers/r2-client.d.ts.map +1 -0
  37. package/dist/providers/r2-client.js +2 -0
  38. package/dist/providers/r2-client.js.map +1 -0
  39. package/dist/providers/r2.d.ts +14 -0
  40. package/dist/providers/r2.d.ts.map +1 -0
  41. package/dist/providers/r2.js +305 -0
  42. package/dist/providers/r2.js.map +1 -0
  43. package/dist/rebuild.d.ts +34 -0
  44. package/dist/rebuild.d.ts.map +1 -0
  45. package/dist/rebuild.js +51 -0
  46. package/dist/rebuild.js.map +1 -0
  47. package/dist/types.d.ts +111 -0
  48. package/dist/types.d.ts.map +1 -0
  49. package/dist/types.js +2 -0
  50. package/dist/types.js.map +1 -0
  51. package/dist/version.d.ts +13 -0
  52. package/dist/version.d.ts.map +1 -0
  53. package/dist/version.js +26 -0
  54. package/dist/version.js.map +1 -0
  55. package/package.json +47 -3
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @contentrail/publisher — server-only publishing engine.
3
+ * Do not import from browser bundles. Credentials stay in the host process.
4
+ */
5
+ export { createPublisher, type ContentPublisher, type CreatePublisherOptions, } from "./engine.js";
6
+ export { PublishConflictError, PublishError, type PublishErrorCode, } from "./errors.js";
7
+ export { createRebuildHook, type RebuildHookClient, type RebuildHookOptions, } from "./rebuild.js";
8
+ export { createGitPublishProvider, type GitPublishProviderOptions, } from "./providers/git.js";
9
+ export type { GitRepositoryClient, GitCommitResult, } from "./providers/git-client.js";
10
+ export { createR2PublishProvider, type R2PublishProviderOptions, } from "./providers/r2.js";
11
+ export type { ObjectStorageClient, ObjectStorageObject, } from "./providers/r2-client.js";
12
+ export { createMemoryGitClient } from "./fakes/memory-git.js";
13
+ export { createMemoryR2Client } from "./fakes/memory-r2.js";
14
+ export type { ActiveContentSnapshot, PublicationManifest, PublicationSummary, PublishEntryInput, PublishProvider, PublishRequest, PublishResult, PublishSuccess, RebuildState, RebuildStatus, } from "./types.js";
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,eAAe,EACf,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,GAC5B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,oBAAoB,EACpB,YAAY,EACZ,KAAK,gBAAgB,GACtB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,iBAAiB,EACjB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,GACxB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,wBAAwB,EACxB,KAAK,yBAAyB,GAC/B,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,mBAAmB,EACnB,eAAe,GAChB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,uBAAuB,EACvB,KAAK,wBAAwB,GAC9B,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,YAAY,EACV,qBAAqB,EACrB,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,eAAe,EACf,cAAc,EACd,aAAa,EACb,cAAc,EACd,YAAY,EACZ,aAAa,GACd,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @contentrail/publisher — server-only publishing engine.
3
+ * Do not import from browser bundles. Credentials stay in the host process.
4
+ */
5
+ export { createPublisher, } from "./engine.js";
6
+ export { PublishConflictError, PublishError, } from "./errors.js";
7
+ export { createRebuildHook, } from "./rebuild.js";
8
+ export { createGitPublishProvider, } from "./providers/git.js";
9
+ export { createR2PublishProvider, } from "./providers/r2.js";
10
+ export { createMemoryGitClient } from "./fakes/memory-git.js";
11
+ export { createMemoryR2Client } from "./fakes/memory-r2.js";
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,eAAe,GAGhB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,oBAAoB,EACpB,YAAY,GAEb,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,iBAAiB,GAGlB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,wBAAwB,GAEzB,MAAM,oBAAoB,CAAC;AAK5B,OAAO,EACL,uBAAuB,GAExB,MAAM,mBAAmB,CAAC;AAK3B,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function assertSafeSegment(segment: string, label: string): void;
2
+ export declare function assertSafeRelativePath(relativePath: string, allowedPrefix: string): string;
3
+ export declare function joinContentPath(contentRoot: string, collectionName: string, entryId: string): string;
4
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAIA,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAetE;AAED,wBAAgB,sBAAsB,CACpC,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,GACpB,MAAM,CAgCR;AAED,wBAAgB,eAAe,CAC7B,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,MAAM,GACd,MAAM,CASR"}
package/dist/paths.js ADDED
@@ -0,0 +1,43 @@
1
+ import { PublishError } from "./errors.js";
2
+ const SEGMENT_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
3
+ export function assertSafeSegment(segment, label) {
4
+ if (segment === "" ||
5
+ segment === "." ||
6
+ segment === ".." ||
7
+ segment.includes("/") ||
8
+ segment.includes("\\") ||
9
+ segment.includes("\0") ||
10
+ !SEGMENT_PATTERN.test(segment)) {
11
+ throw new PublishError("PATH_ESCAPE", `Unsafe ${label} segment rejected: ${JSON.stringify(segment)}`);
12
+ }
13
+ }
14
+ export function assertSafeRelativePath(relativePath, allowedPrefix) {
15
+ const normalized = relativePath.replaceAll("\\", "/");
16
+ if (normalized.startsWith("/") ||
17
+ normalized.includes("\0") ||
18
+ normalized
19
+ .split("/")
20
+ .some((part) => part === "" || part === "." || part === "..")) {
21
+ throw new PublishError("PATH_ESCAPE", `Unsafe destination path rejected: ${JSON.stringify(relativePath)}`);
22
+ }
23
+ const prefix = allowedPrefix.replaceAll(/\/+$/g, "");
24
+ if (prefix !== "" &&
25
+ !normalized.startsWith(`${prefix}/`) &&
26
+ normalized !== prefix) {
27
+ throw new PublishError("PATH_ESCAPE", `Destination path escapes configured content root "${prefix}": ${normalized}`);
28
+ }
29
+ for (const part of normalized.split("/")) {
30
+ assertSafeSegment(part, "path");
31
+ }
32
+ return normalized;
33
+ }
34
+ export function joinContentPath(contentRoot, collectionName, entryId) {
35
+ assertSafeSegment(collectionName, "collection name");
36
+ assertSafeSegment(entryId, "entry id");
37
+ const root = contentRoot.replaceAll(/\/+$/g, "");
38
+ const relative = root === "" || root === "."
39
+ ? `${collectionName}/${entryId}.json`
40
+ : `${root}/${collectionName}/${entryId}.json`;
41
+ return assertSafeRelativePath(relative, root === "." ? "" : root);
42
+ }
43
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,eAAe,GAAG,8BAA8B,CAAC;AAEvD,MAAM,UAAU,iBAAiB,CAAC,OAAe,EAAE,KAAa;IAC9D,IACE,OAAO,KAAK,EAAE;QACd,OAAO,KAAK,GAAG;QACf,OAAO,KAAK,IAAI;QAChB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;QACrB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;QACtB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;QACtB,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,EAC9B,CAAC;QACD,MAAM,IAAI,YAAY,CACpB,aAAa,EACb,UAAU,KAAK,sBAAsB,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAC/D,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,YAAoB,EACpB,aAAqB;IAErB,MAAM,UAAU,GAAG,YAAY,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACtD,IACE,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC;QAC1B,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC;QACzB,UAAU;aACP,KAAK,CAAC,GAAG,CAAC;aACV,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,EAAE,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,IAAI,CAAC,EAC/D,CAAC;QACD,MAAM,IAAI,YAAY,CACpB,aAAa,EACb,qCAAqC,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,EAAE,CACpE,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,aAAa,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IACrD,IACE,MAAM,KAAK,EAAE;QACb,CAAC,UAAU,CAAC,UAAU,CAAC,GAAG,MAAM,GAAG,CAAC;QACpC,UAAU,KAAK,MAAM,EACrB,CAAC;QACD,MAAM,IAAI,YAAY,CACpB,aAAa,EACb,qDAAqD,MAAM,MAAM,UAAU,EAAE,CAC9E,CAAC;IACJ,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACzC,iBAAiB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAClC,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,WAAmB,EACnB,cAAsB,EACtB,OAAe;IAEf,iBAAiB,CAAC,cAAc,EAAE,iBAAiB,CAAC,CAAC;IACrD,iBAAiB,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IACvC,MAAM,IAAI,GAAG,WAAW,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IACjD,MAAM,QAAQ,GACZ,IAAI,KAAK,EAAE,IAAI,IAAI,KAAK,GAAG;QACzB,CAAC,CAAC,GAAG,cAAc,IAAI,OAAO,OAAO;QACrC,CAAC,CAAC,GAAG,IAAI,IAAI,cAAc,IAAI,OAAO,OAAO,CAAC;IAClD,OAAO,sBAAsB,CAAC,QAAQ,EAAE,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACpE,CAAC"}
@@ -0,0 +1,31 @@
1
+ export interface GitFileSnapshot {
2
+ readonly path: string;
3
+ readonly content: string;
4
+ readonly sha: string;
5
+ }
6
+ export interface GitCommitResult {
7
+ readonly commitSha: string;
8
+ readonly branch: string;
9
+ }
10
+ /**
11
+ * Injected Git API surface. Production adapters wrap GitHub/GitLab HTTP APIs.
12
+ * Tests use an in-memory fake — no live credentials required.
13
+ */
14
+ export interface GitRepositoryClient {
15
+ getBranchTip(branch: string): Promise<string>;
16
+ /**
17
+ * Creates a commit on `branch` only when `expectedParentSha` matches the tip.
18
+ * Throws with code-like message `CONFLICT` when the tip moved.
19
+ */
20
+ commitFiles(input: {
21
+ branch: string;
22
+ expectedParentSha: string;
23
+ message: string;
24
+ files: ReadonlyArray<{
25
+ path: string;
26
+ content: string;
27
+ }>;
28
+ }): Promise<GitCommitResult>;
29
+ readFile(path: string, ref: string): Promise<string | null>;
30
+ }
31
+ //# sourceMappingURL=git-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-client.d.ts","sourceRoot":"","sources":["../../src/providers/git-client.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9C;;;OAGG;IACH,WAAW,CAAC,KAAK,EAAE;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,iBAAiB,EAAE,MAAM,CAAC;QAC1B,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,aAAa,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KACzD,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CAC7D"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=git-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-client.js","sourceRoot":"","sources":["../../src/providers/git-client.ts"],"names":[],"mappings":""}
@@ -0,0 +1,10 @@
1
+ import type { PublishProvider } from "../types.js";
2
+ import type { GitRepositoryClient } from "./git-client.js";
3
+ export interface GitPublishProviderOptions {
4
+ readonly client: GitRepositoryClient;
5
+ readonly branch: string;
6
+ readonly contentRoot: string;
7
+ readonly hasCredential?: boolean;
8
+ }
9
+ export declare function createGitPublishProvider(options: GitPublishProviderOptions): PublishProvider;
10
+ //# sourceMappingURL=git.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/providers/git.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAIV,eAAe,EAEhB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAE3D,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,MAAM,EAAE,mBAAmB,CAAC;IACrC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;CAClC;AAqDD,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,yBAAyB,GACjC,eAAe,CA6WjB"}
@@ -0,0 +1,311 @@
1
+ import { PublishConflictError, PublishError } from "../errors.js";
2
+ import { assertSafeRelativePath, joinContentPath } from "../paths.js";
3
+ function metaPath(contentRoot, siteId, collection) {
4
+ const root = contentRoot.replaceAll(/\/+$/g, "");
5
+ const relative = root === "" || root === "."
6
+ ? `contentrail-meta/${siteId}/${collection}/meta.json`
7
+ : `${root}/contentrail-meta/${siteId}/${collection}/meta.json`;
8
+ return assertSafeRelativePath(relative, root === "." ? "" : root);
9
+ }
10
+ function emptyMeta() {
11
+ return { activeVersion: null, versions: {}, idempotency: {} };
12
+ }
13
+ async function readMeta(client, ref, path) {
14
+ const raw = await client.readFile(path, ref);
15
+ if (raw === null) {
16
+ return emptyMeta();
17
+ }
18
+ return JSON.parse(raw);
19
+ }
20
+ function isConflict(error) {
21
+ return (error instanceof Error &&
22
+ (error.message === "CONFLICT" || /conflict/i.test(error.message)));
23
+ }
24
+ function isTimeout(error) {
25
+ return error instanceof Error && /timeout|timed out/i.test(error.message);
26
+ }
27
+ export function createGitPublishProvider(options) {
28
+ if (options.hasCredential === false) {
29
+ throw new PublishError("CREDENTIALS", "Git publish provider requires a configured server-side credential.");
30
+ }
31
+ const { client, branch, contentRoot } = options;
32
+ return {
33
+ kind: "git",
34
+ async getActiveVersion(siteId, collection) {
35
+ const tip = await client.getBranchTip(branch);
36
+ return (await readMeta(client, tip, metaPath(contentRoot, siteId, collection))).activeVersion;
37
+ },
38
+ async readActiveContent(siteId, collection) {
39
+ const tip = await client.getBranchTip(branch);
40
+ const meta = await readMeta(client, tip, metaPath(contentRoot, siteId, collection));
41
+ if (meta.activeVersion === null) {
42
+ return null;
43
+ }
44
+ const stored = meta.versions[meta.activeVersion];
45
+ if (stored === undefined) {
46
+ throw new PublishError("NOT_FOUND", `Active version "${meta.activeVersion}" is missing from Git metadata.`, { siteId, collection });
47
+ }
48
+ const entries = stored.entryIds.map((entryId) => {
49
+ const data = stored.bodies[entryId];
50
+ if (data === undefined) {
51
+ throw new PublishError("NOT_FOUND", `Active version "${meta.activeVersion}" is missing entry "${entryId}".`, { siteId, collection });
52
+ }
53
+ return { id: entryId, data };
54
+ });
55
+ const snapshot = {
56
+ version: stored.version,
57
+ publicationId: stored.publicationId,
58
+ createdAt: stored.createdAt,
59
+ entries,
60
+ };
61
+ return snapshot;
62
+ },
63
+ async readIdempotentResult(siteId, collection, idempotencyKey) {
64
+ const tip = await client.getBranchTip(branch);
65
+ const meta = await readMeta(client, tip, metaPath(contentRoot, siteId, collection));
66
+ return meta.idempotency[idempotencyKey] ?? null;
67
+ },
68
+ async recoverIdempotentPublish(input) {
69
+ const tip = await client.getBranchTip(branch);
70
+ const meta = await readMeta(client, tip, metaPath(contentRoot, input.siteId, input.collection));
71
+ const prior = meta.idempotency[input.idempotencyKey];
72
+ if (prior !== undefined) {
73
+ return prior;
74
+ }
75
+ if (meta.activeVersion !== input.version) {
76
+ return null;
77
+ }
78
+ const stored = meta.versions[input.version];
79
+ if (stored === undefined) {
80
+ return null;
81
+ }
82
+ return {
83
+ success: true,
84
+ publicationId: input.publicationId,
85
+ version: input.version,
86
+ previousVersion: stored.previousVersion,
87
+ manifest: {
88
+ siteId: stored.siteId,
89
+ collection: stored.collection,
90
+ publicationId: stored.publicationId,
91
+ version: stored.version,
92
+ previousVersion: stored.previousVersion,
93
+ createdAt: stored.createdAt,
94
+ entryIds: [...stored.entryIds],
95
+ },
96
+ provider: { kind: "git", revision: tip },
97
+ rebuild: { state: "not_requested" },
98
+ idempotentReplay: true,
99
+ };
100
+ },
101
+ async publishSnapshot(input) {
102
+ const tip = await client.getBranchTip(branch);
103
+ const metaFile = metaPath(contentRoot, input.siteId, input.collection);
104
+ const meta = await readMeta(client, tip, metaFile);
105
+ if (meta.activeVersion !== input.expectedVersion) {
106
+ throw new PublishConflictError("Git active version changed before commit.", {
107
+ siteId: input.siteId,
108
+ collection: input.collection,
109
+ publicationId: input.publicationId,
110
+ currentVersion: meta.activeVersion,
111
+ expectedVersion: input.expectedVersion,
112
+ });
113
+ }
114
+ const createdAt = new Date().toISOString();
115
+ const bodies = {};
116
+ const files = input.entries.map((entry) => {
117
+ bodies[entry.id] = entry.data;
118
+ return {
119
+ path: joinContentPath(contentRoot, input.collection, entry.id),
120
+ content: `${JSON.stringify(entry.data, null, 2)}\n`,
121
+ };
122
+ });
123
+ const stored = {
124
+ siteId: input.siteId,
125
+ collection: input.collection,
126
+ publicationId: input.publicationId,
127
+ version: input.version,
128
+ previousVersion: input.previousVersion,
129
+ createdAt,
130
+ entryIds: input.entries.map((entry) => entry.id),
131
+ baseTip: tip,
132
+ bodies,
133
+ };
134
+ const provisionalResult = {
135
+ success: true,
136
+ publicationId: input.publicationId,
137
+ version: input.version,
138
+ previousVersion: input.previousVersion,
139
+ manifest: {
140
+ siteId: input.siteId,
141
+ collection: input.collection,
142
+ publicationId: input.publicationId,
143
+ version: input.version,
144
+ previousVersion: input.previousVersion,
145
+ createdAt,
146
+ entryIds: [...stored.entryIds],
147
+ },
148
+ provider: { kind: "git", revision: tip },
149
+ rebuild: { state: "not_requested" },
150
+ idempotentReplay: false,
151
+ };
152
+ const nextMeta = {
153
+ activeVersion: input.version,
154
+ versions: {
155
+ ...meta.versions,
156
+ [input.version]: stored,
157
+ },
158
+ idempotency: {
159
+ ...meta.idempotency,
160
+ ...(input.idempotencyKey !== undefined
161
+ ? { [input.idempotencyKey]: provisionalResult }
162
+ : {}),
163
+ },
164
+ };
165
+ try {
166
+ const commit = await client.commitFiles({
167
+ branch,
168
+ expectedParentSha: tip,
169
+ message: input.message ??
170
+ `contentrail publish ${input.collection} ${input.version}`,
171
+ files: [
172
+ ...files,
173
+ {
174
+ path: metaFile,
175
+ content: `${JSON.stringify(nextMeta, null, 2)}\n`,
176
+ },
177
+ ],
178
+ });
179
+ const result = {
180
+ ...provisionalResult,
181
+ provider: { kind: "git", revision: commit.commitSha },
182
+ };
183
+ if (input.idempotencyKey !== undefined) {
184
+ // Best-effort: idempotent record in the committed meta used tip as revision;
185
+ // engine returns the commit SHA result to the caller. Replays read meta and
186
+ // still return success payload; revision may show the tip used at write time.
187
+ nextMeta.idempotency[input.idempotencyKey] = result;
188
+ }
189
+ return result;
190
+ }
191
+ catch (error) {
192
+ if (isConflict(error)) {
193
+ throw new PublishConflictError("Concurrent Git update detected; publication was not activated.", {
194
+ siteId: input.siteId,
195
+ collection: input.collection,
196
+ publicationId: input.publicationId,
197
+ cause: error,
198
+ });
199
+ }
200
+ if (isTimeout(error)) {
201
+ throw new PublishError("PARTIAL_FAILURE", "Git provider timed out during publication. Active version was not confirmed.", {
202
+ siteId: input.siteId,
203
+ collection: input.collection,
204
+ publicationId: input.publicationId,
205
+ cause: error,
206
+ });
207
+ }
208
+ throw new PublishError("PROVIDER", "Git provider failed during publication.", {
209
+ siteId: input.siteId,
210
+ collection: input.collection,
211
+ publicationId: input.publicationId,
212
+ cause: error,
213
+ });
214
+ }
215
+ },
216
+ async listVersions(siteId, collection) {
217
+ const tip = await client.getBranchTip(branch);
218
+ const meta = await readMeta(client, tip, metaPath(contentRoot, siteId, collection));
219
+ return Object.values(meta.versions)
220
+ .map((version) => ({
221
+ version: version.version,
222
+ publicationId: version.publicationId,
223
+ createdAt: version.createdAt,
224
+ active: version.version === meta.activeVersion,
225
+ }))
226
+ .sort((a, b) => a.createdAt.localeCompare(b.createdAt));
227
+ },
228
+ async rollback(input) {
229
+ const tip = await client.getBranchTip(branch);
230
+ const metaFile = metaPath(contentRoot, input.siteId, input.collection);
231
+ const meta = await readMeta(client, tip, metaFile);
232
+ if (meta.activeVersion !== input.expectedVersion) {
233
+ throw new PublishConflictError("Rollback expectedVersion does not match active Git publication.", {
234
+ siteId: input.siteId,
235
+ collection: input.collection,
236
+ currentVersion: meta.activeVersion,
237
+ expectedVersion: input.expectedVersion,
238
+ });
239
+ }
240
+ const target = meta.versions[input.targetVersion];
241
+ if (target === undefined) {
242
+ throw new PublishError("NOT_FOUND", `Unknown publication version "${input.targetVersion}".`, { siteId: input.siteId, collection: input.collection });
243
+ }
244
+ const publicationId = input.publicationId ?? target.publicationId;
245
+ const createdAt = new Date().toISOString();
246
+ const files = target.entryIds.map((entryId) => {
247
+ const body = target.bodies[entryId];
248
+ if (body === undefined) {
249
+ throw new PublishError("NOT_FOUND", `Missing snapshot body for entry "${entryId}" in version "${input.targetVersion}".`, { siteId: input.siteId, collection: input.collection });
250
+ }
251
+ return {
252
+ path: joinContentPath(contentRoot, input.collection, entryId),
253
+ content: `${JSON.stringify(body, null, 2)}\n`,
254
+ };
255
+ });
256
+ const nextMeta = {
257
+ ...meta,
258
+ activeVersion: input.targetVersion,
259
+ };
260
+ try {
261
+ const commit = await client.commitFiles({
262
+ branch,
263
+ expectedParentSha: tip,
264
+ message: `contentrail rollback ${input.collection} -> ${input.targetVersion}`,
265
+ files: [
266
+ ...files,
267
+ {
268
+ path: metaFile,
269
+ content: `${JSON.stringify(nextMeta, null, 2)}\n`,
270
+ },
271
+ ],
272
+ });
273
+ return {
274
+ success: true,
275
+ publicationId,
276
+ version: input.targetVersion,
277
+ previousVersion: meta.activeVersion,
278
+ manifest: {
279
+ siteId: input.siteId,
280
+ collection: input.collection,
281
+ publicationId,
282
+ version: input.targetVersion,
283
+ previousVersion: meta.activeVersion,
284
+ createdAt,
285
+ entryIds: [...target.entryIds],
286
+ },
287
+ provider: { kind: "git", revision: commit.commitSha },
288
+ rebuild: { state: "not_requested" },
289
+ idempotentReplay: false,
290
+ };
291
+ }
292
+ catch (error) {
293
+ if (isConflict(error)) {
294
+ throw new PublishConflictError("Concurrent Git update detected during rollback.", {
295
+ siteId: input.siteId,
296
+ collection: input.collection,
297
+ publicationId,
298
+ cause: error,
299
+ });
300
+ }
301
+ throw new PublishError("PROVIDER", "Git rollback failed.", {
302
+ siteId: input.siteId,
303
+ collection: input.collection,
304
+ publicationId,
305
+ cause: error,
306
+ });
307
+ }
308
+ },
309
+ };
310
+ }
311
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/providers/git.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ export interface ObjectStorageObject {
2
+ readonly body: string;
3
+ readonly etag: string;
4
+ }
5
+ /**
6
+ * Injected object-storage surface for R2 / S3-compatible APIs.
7
+ * Conditional writes implement activation compare-and-swap.
8
+ */
9
+ export interface ObjectStorageClient {
10
+ getObject(key: string): Promise<ObjectStorageObject | null>;
11
+ putObject(key: string, body: string, options?: {
12
+ ifMatch?: string;
13
+ ifNoneMatch?: "*";
14
+ }): Promise<{
15
+ etag: string;
16
+ }>;
17
+ listKeys(prefix: string): Promise<string[]>;
18
+ }
19
+ //# sourceMappingURL=r2-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"r2-client.d.ts","sourceRoot":"","sources":["../../src/providers/r2-client.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAAC;IAC5D,SAAS,CACP,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;QACR,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,WAAW,CAAC,EAAE,GAAG,CAAC;KACnB,GACA,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;CAC7C"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=r2-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"r2-client.js","sourceRoot":"","sources":["../../src/providers/r2-client.ts"],"names":[],"mappings":""}
@@ -0,0 +1,14 @@
1
+ import type { PublishProvider } from "../types.js";
2
+ import type { ObjectStorageClient } from "./r2-client.js";
3
+ export interface R2PublishProviderOptions {
4
+ readonly client: ObjectStorageClient;
5
+ /** Allowed key prefix, e.g. `sites/demo`. */
6
+ readonly keyPrefix: string;
7
+ readonly hasCredential?: boolean;
8
+ }
9
+ /**
10
+ * R2 / object-storage provider.
11
+ * Writes immutable version snapshots, then conditionally updates `current.json`.
12
+ */
13
+ export declare function createR2PublishProvider(options: R2PublishProviderOptions): PublishProvider;
14
+ //# sourceMappingURL=r2.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"r2.d.ts","sourceRoot":"","sources":["../../src/providers/r2.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAIV,eAAe,EAEhB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAM1D,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,MAAM,EAAE,mBAAmB,CAAC;IACrC,6CAA6C;IAC7C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;CAClC;AAgBD;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,wBAAwB,GAChC,eAAe,CA6ajB"}