@arden-hq/revisions 0.0.0-stage → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +84 -2
  3. package/dist/domain/change-set.d.ts +34 -0
  4. package/dist/domain/change-set.d.ts.map +1 -0
  5. package/dist/domain/change-set.js +206 -0
  6. package/dist/domain/change-set.js.map +1 -0
  7. package/dist/domain/codec.d.ts +17 -0
  8. package/dist/domain/codec.d.ts.map +1 -0
  9. package/dist/domain/codec.js +188 -0
  10. package/dist/domain/codec.js.map +1 -0
  11. package/dist/domain/errors.d.ts +61 -0
  12. package/dist/domain/errors.d.ts.map +1 -0
  13. package/dist/domain/errors.js +44 -0
  14. package/dist/domain/errors.js.map +1 -0
  15. package/dist/domain/format.d.ts +72 -0
  16. package/dist/domain/format.d.ts.map +1 -0
  17. package/dist/domain/format.js +93 -0
  18. package/dist/domain/format.js.map +1 -0
  19. package/dist/domain/integrity.d.ts +7 -0
  20. package/dist/domain/integrity.d.ts.map +1 -0
  21. package/dist/domain/integrity.js +100 -0
  22. package/dist/domain/integrity.js.map +1 -0
  23. package/dist/domain/model.d.ts +114 -0
  24. package/dist/domain/model.d.ts.map +1 -0
  25. package/dist/domain/model.js +145 -0
  26. package/dist/domain/model.js.map +1 -0
  27. package/dist/domain/query.d.ts +31 -0
  28. package/dist/domain/query.d.ts.map +1 -0
  29. package/dist/domain/query.js +168 -0
  30. package/dist/domain/query.js.map +1 -0
  31. package/dist/domain/transaction.d.ts +26 -0
  32. package/dist/domain/transaction.d.ts.map +1 -0
  33. package/dist/domain/transaction.js +93 -0
  34. package/dist/domain/transaction.js.map +1 -0
  35. package/dist/domain/tree.d.ts +6 -0
  36. package/dist/domain/tree.d.ts.map +1 -0
  37. package/dist/domain/tree.js +59 -0
  38. package/dist/domain/tree.js.map +1 -0
  39. package/dist/effect/index.d.ts +10 -0
  40. package/dist/effect/index.d.ts.map +1 -0
  41. package/dist/effect/index.js +4 -0
  42. package/dist/effect/index.js.map +1 -0
  43. package/dist/repository/commit.d.ts +12 -0
  44. package/dist/repository/commit.d.ts.map +1 -0
  45. package/dist/repository/commit.js +164 -0
  46. package/dist/repository/commit.js.map +1 -0
  47. package/dist/repository/history.d.ts +21 -0
  48. package/dist/repository/history.d.ts.map +1 -0
  49. package/dist/repository/history.js +152 -0
  50. package/dist/repository/history.js.map +1 -0
  51. package/dist/repository/service.d.ts +114 -0
  52. package/dist/repository/service.d.ts.map +1 -0
  53. package/dist/repository/service.js +374 -0
  54. package/dist/repository/service.js.map +1 -0
  55. package/dist/repository/state.d.ts +27 -0
  56. package/dist/repository/state.d.ts.map +1 -0
  57. package/dist/repository/state.js +72 -0
  58. package/dist/repository/state.js.map +1 -0
  59. package/dist/repository/transaction.d.ts +27 -0
  60. package/dist/repository/transaction.d.ts.map +1 -0
  61. package/dist/repository/transaction.js +372 -0
  62. package/dist/repository/transaction.js.map +1 -0
  63. package/dist/storage/files.d.ts +17 -0
  64. package/dist/storage/files.d.ts.map +1 -0
  65. package/dist/storage/files.js +179 -0
  66. package/dist/storage/files.js.map +1 -0
  67. package/dist/storage/maintenance-adapter.d.ts +5 -0
  68. package/dist/storage/maintenance-adapter.d.ts.map +1 -0
  69. package/dist/storage/maintenance-adapter.js +177 -0
  70. package/dist/storage/maintenance-adapter.js.map +1 -0
  71. package/dist/storage/maintenance-reader.d.ts +17 -0
  72. package/dist/storage/maintenance-reader.d.ts.map +1 -0
  73. package/dist/storage/maintenance-reader.js +82 -0
  74. package/dist/storage/maintenance-reader.js.map +1 -0
  75. package/dist/storage/maintenance.d.ts +113 -0
  76. package/dist/storage/maintenance.d.ts.map +1 -0
  77. package/dist/storage/maintenance.js +445 -0
  78. package/dist/storage/maintenance.js.map +1 -0
  79. package/dist/storage/node.d.ts +7 -0
  80. package/dist/storage/node.d.ts.map +1 -0
  81. package/dist/storage/node.js +53 -0
  82. package/dist/storage/node.js.map +1 -0
  83. package/dist/storage/service.d.ts +88 -0
  84. package/dist/storage/service.d.ts.map +1 -0
  85. package/dist/storage/service.js +506 -0
  86. package/dist/storage/service.js.map +1 -0
  87. package/package.json +63 -4
@@ -0,0 +1,177 @@
1
+ import { Effect, Exit } from "effect";
2
+ import { parseIdempotencyRecord, parseTransaction } from "../domain/transaction.js";
3
+ import { normalizeRelativePath } from "../domain/model.js";
4
+ import { CorruptRepositoryError, RevisionStorageError, UnsafePathError } from "../domain/errors.js";
5
+ import { compareCodePoints } from "@arden-hq/std/json";
6
+ const transactionDirectories = ["publish", "backups", "displaced", "rejected", "markers"];
7
+ const isHash = (value) => typeof value === "string" &&
8
+ value.length === 64 &&
9
+ [...value].every((character) => "0123456789abcdef".includes(character));
10
+ const corrupt = (message) => Effect.fail(new CorruptRepositoryError({ message }));
11
+ const storageErrorMessage = (error) => `${error._tag}: ${error.message}`;
12
+ const adaptStorageError = (error) => {
13
+ switch (error._tag) {
14
+ case "RevisionStorageError":
15
+ return error;
16
+ case "UnsafePathError":
17
+ return error;
18
+ case "RevisionConflictError":
19
+ return new RevisionStorageError({ message: storageErrorMessage(error), cause: error });
20
+ }
21
+ };
22
+ const fromStorage = (effect) => effect.pipe(Effect.mapError(adaptStorageError));
23
+ const objectFilename = (kind, id) => kind === "blob" ? id : `${id}.jsonl`;
24
+ const objectPath = (kind, id) => `${kind === "commit" ? "commits" : `objects/${kind === "blob" ? "blobs" : "trees"}`}/${objectFilename(kind, id)}`;
25
+ const checkedStat = (target, stat) => {
26
+ if (stat === null)
27
+ return corrupt(`metadata entry disappeared: ${target}`);
28
+ if (!Number.isSafeInteger(stat.size) || stat.size < 0) {
29
+ return corrupt(`metadata entry has an invalid byte size: ${target}`);
30
+ }
31
+ if (stat.mtimeMillis === null || !Number.isSafeInteger(stat.mtimeMillis)) {
32
+ return corrupt(`metadata entry has an invalid modification time: ${target}`);
33
+ }
34
+ return Effect.succeed({ byteSize: stat.size, modifiedAtMillis: stat.mtimeMillis });
35
+ };
36
+ const metadataBytes = Effect.fn("maintenanceAdapter.metadataBytes")(function* (storage, target) {
37
+ const listed = yield* Effect.exit(fromStorage(storage.listMetadata(target)));
38
+ if (Exit.isSuccess(listed)) {
39
+ let total = 0;
40
+ for (const name of [...listed.value].sort(compareCodePoints)) {
41
+ total += yield* metadataBytes(storage, `${target}/${name}`);
42
+ }
43
+ return total;
44
+ }
45
+ const content = yield* fromStorage(storage.readMetadata(target, true));
46
+ if (content === null)
47
+ return yield* corrupt(`metadata entry disappeared: ${target}`);
48
+ const stat = yield* fromStorage(storage.metadataStat(target));
49
+ const measured = yield* checkedStat(target, stat);
50
+ if (measured.byteSize !== content.length) {
51
+ return yield* corrupt(`metadata entry changed during accounting: ${target}`);
52
+ }
53
+ return measured.byteSize;
54
+ });
55
+ const optionalMetadataBytes = Effect.fn("maintenanceAdapter.optionalMetadataBytes")(function* (storage, target) {
56
+ if (!(yield* fromStorage(storage.metadataExists(target))))
57
+ return null;
58
+ return yield* metadataBytes(storage, target);
59
+ });
60
+ const readProtectedTransaction = Effect.fn("maintenanceAdapter.readProtectedTransaction")(function* (storage, parent, transactionId) {
61
+ const prefix = `${parent}/${transactionId}`;
62
+ const prepared = yield* fromStorage(storage.readMetadata(`${prefix}/PREPARED`, true));
63
+ if (prepared === null)
64
+ return null;
65
+ if (prepared.length !== 0)
66
+ return yield* corrupt(`transaction ${transactionId} PREPARED marker is not empty`);
67
+ for (const directory of transactionDirectories) {
68
+ yield* fromStorage(storage.listMetadata(`${prefix}/${directory}`));
69
+ }
70
+ const content = yield* fromStorage(storage.readMetadata(`${prefix}/manifest.jsonl`));
71
+ if (content === null)
72
+ return yield* corrupt(`transaction manifest is missing: ${transactionId}`);
73
+ return {
74
+ ...(yield* parseTransaction(transactionId, content)),
75
+ conflicted: parent === "conflicts"
76
+ };
77
+ });
78
+ const listProtectedTransactions = Effect.fn("maintenanceAdapter.listProtectedTransactions")(function* (storage, parent) {
79
+ const names = yield* fromStorage(storage.listMetadata(parent));
80
+ const output = [];
81
+ for (const name of [...names].sort(compareCodePoints)) {
82
+ if (!isHash(name))
83
+ return yield* corrupt(`invalid ${parent} transaction directory: ${name}`);
84
+ const transaction = yield* readProtectedTransaction(storage, parent, name);
85
+ if (transaction !== null)
86
+ output.push(transaction);
87
+ }
88
+ return output;
89
+ });
90
+ /** Adapt the repository's low-level storage contract to maintenance operations. */
91
+ export const maintenanceStorageFromRevisionStorage = (storage) => {
92
+ const listObjects = Effect.fn("maintenanceAdapter.listObjects")(function* (kind) {
93
+ const ids = yield* fromStorage(storage.listObjectIds(kind));
94
+ const entries = [];
95
+ for (const id of [...ids].sort(compareCodePoints)) {
96
+ if (!isHash(id))
97
+ return yield* corrupt(`invalid ${kind} object identifier: ${id}`);
98
+ const target = objectPath(kind, id);
99
+ const measured = yield* checkedStat(target, yield* fromStorage(storage.metadataStat(target)));
100
+ entries.push({ name: objectFilename(kind, id), ...measured });
101
+ }
102
+ return entries;
103
+ });
104
+ const readObject = (kind, id) => {
105
+ if (!isHash(id))
106
+ return Effect.fail(new UnsafePathError({ message: `${kind} identifier is invalid: ${id}` }));
107
+ switch (kind) {
108
+ case "blob":
109
+ return fromStorage(storage.readBlob(id));
110
+ case "tree":
111
+ return fromStorage(storage.readTree(id));
112
+ case "commit":
113
+ return fromStorage(storage.readCommit(id));
114
+ }
115
+ };
116
+ const listIdempotency = Effect.gen(function* () {
117
+ const names = yield* fromStorage(storage.listMetadata("idempotency"));
118
+ const output = [];
119
+ for (const name of [...names].sort(compareCodePoints)) {
120
+ if (!name.endsWith(".jsonl"))
121
+ return yield* corrupt(`invalid idempotency filename: ${name}`);
122
+ const keyHash = name.slice(0, -".jsonl".length);
123
+ if (!isHash(keyHash))
124
+ return yield* corrupt(`invalid idempotency filename: ${name}`);
125
+ const content = yield* fromStorage(storage.readIdempotency(keyHash));
126
+ if (content === null)
127
+ return yield* corrupt(`idempotency record disappeared: ${keyHash}`);
128
+ output.push(yield* parseIdempotencyRecord(content, keyHash));
129
+ }
130
+ return output;
131
+ });
132
+ const listProtected = Effect.gen(function* () {
133
+ const transactions = yield* listProtectedTransactions(storage, "transactions");
134
+ const conflicts = yield* listProtectedTransactions(storage, "conflicts");
135
+ return [...transactions, ...conflicts];
136
+ });
137
+ const metadataStats = Effect.gen(function* () {
138
+ const transactionBytes = yield* metadataBytes(storage, "transactions");
139
+ const conflictBytes = yield* metadataBytes(storage, "conflicts");
140
+ const idempotencyBytes = yield* metadataBytes(storage, "idempotency");
141
+ const publicationBytes = yield* metadataBytes(storage, "published");
142
+ const refBytes = yield* metadataBytes(storage, "refs");
143
+ const lockBytes = yield* optionalMetadataBytes(storage, "repository.lock");
144
+ return {
145
+ transactionBytes,
146
+ conflictBytes,
147
+ idempotencyBytes,
148
+ publicationBytes,
149
+ refBytes,
150
+ lockBytes
151
+ };
152
+ });
153
+ return {
154
+ readRef: fromStorage(storage.readRef),
155
+ listObjects,
156
+ readObject,
157
+ readWorking: (path) => normalizeRelativePath(path).pipe(Effect.flatMap((normalized) => fromStorage(storage.readWorking(normalized, true, true)))),
158
+ listPublished: fromStorage(storage.listPublished).pipe(Effect.flatMap(Effect.fn("maintenanceAdapter.listPublished.ids")(function* (ids) {
159
+ const output = [];
160
+ for (const id of [...ids].sort(compareCodePoints)) {
161
+ if (!isHash(id))
162
+ return yield* corrupt(`invalid publication marker: ${id}`);
163
+ output.push({ commitId: id });
164
+ }
165
+ return output;
166
+ }))),
167
+ listIdempotency,
168
+ listProtectedTransactions: listProtected,
169
+ metadataStats,
170
+ removeObject: (kind, id) => {
171
+ if (!isHash(id))
172
+ return Effect.fail(new UnsafePathError({ message: `${kind} identifier is invalid: ${id}` }));
173
+ return fromStorage(storage.removeObject(kind, id));
174
+ }
175
+ };
176
+ };
177
+ //# sourceMappingURL=maintenance-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"maintenance-adapter.js","sourceRoot":"","sources":["../../src/storage/maintenance-adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { Effect } from "effect";
2
+ import { Commit, ResourceVersion } from "../domain/model.js";
3
+ import { CorruptRepositoryError } from "../domain/errors.js";
4
+ import { type TreeRecord } from "../domain/format.js";
5
+ import type { MaintenanceError, MaintenanceStorage } from "./maintenance.js";
6
+ export declare const validHash: (value: unknown) => value is string;
7
+ export declare const corrupt: (message: string) => Effect.Effect<never, CorruptRepositoryError>;
8
+ export interface MaintenanceReader {
9
+ readonly commit: (id: string) => Effect.Effect<Commit, MaintenanceError>;
10
+ readonly tree: (id: string) => Effect.Effect<TreeRecord, MaintenanceError>;
11
+ readonly materialize: (id: string) => Effect.Effect<ReadonlyMap<string, ResourceVersion>, MaintenanceError>;
12
+ readonly treeClosure: (id: string) => Effect.Effect<ReadonlySet<string>, MaintenanceError>;
13
+ readonly transition: (commit: Commit) => Effect.Effect<ReadonlyMap<string, ResourceVersion>, MaintenanceError>;
14
+ readonly verifyBlob: (id: string) => Effect.Effect<void, MaintenanceError>;
15
+ }
16
+ export declare const makeReader: (storage: MaintenanceStorage) => MaintenanceReader;
17
+ //# sourceMappingURL=maintenance-reader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"maintenance-reader.d.ts","sourceRoot":"","sources":["../../src/storage/maintenance-reader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAG/B,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAC5D,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AAC5D,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAGrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AAG5E,eAAO,MAAM,SAAS,UAAW,OAAO,KAAG,KAAK,IAAI,MACO,CAAA;AAE3D,eAAO,MAAM,OAAO,YAAa,MAAM,KAAG,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,sBAAsB,CAC/B,CAAA;AAEtD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;IACxE,QAAQ,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,gBAAgB,CAAC,CAAA;IAC1E,QAAQ,CAAC,WAAW,EAAE,CACpB,EAAE,EAAE,MAAM,KACP,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,eAAe,CAAC,EAAE,gBAAgB,CAAC,CAAA;IAC1E,QAAQ,CAAC,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,gBAAgB,CAAC,CAAA;IAC1F,QAAQ,CAAC,UAAU,EAAE,CACnB,MAAM,EAAE,MAAM,KACX,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,eAAe,CAAC,EAAE,gBAAgB,CAAC,CAAA;IAC1E,QAAQ,CAAC,UAAU,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAA;CAC3E;AAED,eAAO,MAAM,UAAU,YAAa,kBAAkB,KAAG,iBAqFxD,CAAA"}
@@ -0,0 +1,82 @@
1
+ import { Effect } from "effect";
2
+ import { decodeCanonicalJsonl, parseCommitObject, parseTreeRecord } from "../domain/codec.js";
3
+ import { Commit, ResourceVersion } from "../domain/model.js";
4
+ import { CorruptRepositoryError } from "../domain/errors.js";
5
+ import {} from "../domain/format.js";
6
+ import { validateSnapshotTransition } from "../domain/integrity.js";
7
+ import { materializeSnapshot } from "../domain/tree.js";
8
+ import { sha256Hex } from "@arden-hq/std/hash";
9
+ export const validHash = (value) => typeof value === "string" && /^[0-9a-f]{64}$/.test(value);
10
+ export const corrupt = (message) => Effect.fail(new CorruptRepositoryError({ message }));
11
+ export const makeReader = (storage) => {
12
+ const commits = new Map();
13
+ const trees = new Map();
14
+ const snapshots = new Map();
15
+ const blobs = new Set();
16
+ const commit = Effect.fn("maintenance.readCommit")(function* (id) {
17
+ if (!validHash(id))
18
+ return yield* corrupt(`commit identifier is invalid: ${id}`);
19
+ const cached = commits.get(id);
20
+ if (cached !== undefined)
21
+ return cached;
22
+ const bytes = yield* storage.readObject("commit", id);
23
+ const parsed = yield* parseCommitObject(id, bytes);
24
+ commits.set(id, parsed);
25
+ return parsed;
26
+ });
27
+ const tree = Effect.fn("maintenance.readTree")(function* (id) {
28
+ if (!validHash(id))
29
+ return yield* corrupt(`tree identifier is invalid: ${id}`);
30
+ const cached = trees.get(id);
31
+ if (cached !== undefined)
32
+ return cached;
33
+ const bytes = yield* storage.readObject("tree", id);
34
+ const record = yield* decodeCanonicalJsonl(bytes);
35
+ const parsed = yield* parseTreeRecord(record);
36
+ trees.set(id, parsed);
37
+ return parsed;
38
+ });
39
+ const materialize = (id) => materializeSnapshot(tree, id, snapshots);
40
+ const treeClosure = Effect.fn("maintenance.treeClosure")(function* (id) {
41
+ const result = new Set();
42
+ const active = new Set();
43
+ const visit = Effect.fn("maintenance.treeClosure.visit")(function* (treeId) {
44
+ if (active.has(treeId))
45
+ return yield* corrupt(`tree ${id} contains a cycle at ${treeId}`);
46
+ if (result.has(treeId))
47
+ return;
48
+ active.add(treeId);
49
+ const node = yield* tree(treeId);
50
+ result.add(treeId);
51
+ for (const entry of node.entries) {
52
+ if (entry.kind === "subtree")
53
+ yield* visit(entry.tree_id);
54
+ }
55
+ active.delete(treeId);
56
+ });
57
+ yield* visit(id);
58
+ return result;
59
+ });
60
+ const verifyBlob = Effect.fn("maintenance.verifyBlob")(function* (id) {
61
+ if (!validHash(id))
62
+ return yield* corrupt(`blob identifier is invalid: ${id}`);
63
+ if (blobs.has(id))
64
+ return;
65
+ const bytes = yield* storage.readObject("blob", id);
66
+ if (sha256Hex(bytes) !== id)
67
+ return yield* corrupt(`blob hash mismatch: ${id}`);
68
+ blobs.add(id);
69
+ });
70
+ const transition = Effect.fn("maintenance.transition")(function* (current) {
71
+ const after = yield* materialize(current.treeId);
72
+ const before = current.parentId === null
73
+ ? new Map()
74
+ : yield* materialize((yield* commit(current.parentId)).treeId);
75
+ yield* validateSnapshotTransition(current, before, after);
76
+ for (const resource of after.values())
77
+ yield* verifyBlob(resource.blobId);
78
+ return after;
79
+ });
80
+ return { commit, tree, materialize, treeClosure, transition, verifyBlob };
81
+ };
82
+ //# sourceMappingURL=maintenance-reader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"maintenance-reader.js","sourceRoot":"","sources":["../../src/storage/maintenance-reader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,113 @@
1
+ import { Effect } from "effect";
2
+ import { ResourceVersion } from "../domain/model.js";
3
+ import { CorruptRepositoryError, InvalidRevisionInputError, RevisionStorageError, UnsafePathError } from "../domain/errors.js";
4
+ /** Object families owned by the revisions store. */
5
+ export type MaintenanceObjectKind = "blob" | "tree" | "commit";
6
+ /** One object-directory entry as observed by a storage adapter. */
7
+ export interface MaintenanceObjectEntry {
8
+ readonly name: string;
9
+ readonly byteSize: number;
10
+ readonly modifiedAtMillis: number;
11
+ }
12
+ interface MaintenancePublishedEntry {
13
+ readonly commitId: string;
14
+ }
15
+ /** A validated idempotency record used as a collection root. */
16
+ export interface MaintenanceIdempotencyRecord {
17
+ readonly keyHash: string;
18
+ readonly requestHash: string;
19
+ readonly commitId: string;
20
+ }
21
+ interface MaintenanceTransactionRow {
22
+ readonly path: string;
23
+ readonly oldBlob: string | null;
24
+ readonly newBlob: string | null;
25
+ }
26
+ /** A validated pending or conflict transaction supplied by the repository adapter. */
27
+ export interface MaintenanceProtectedTransaction {
28
+ readonly transactionId: string;
29
+ readonly oldHead: string | null;
30
+ readonly newHead: string;
31
+ readonly treeId: string;
32
+ readonly rows: ReadonlyArray<MaintenanceTransactionRow>;
33
+ /** True when the manifest came from conflicts/ after an external-write conflict. */
34
+ readonly conflicted?: boolean;
35
+ }
36
+ /** Byte counts for metadata outside immutable object directories. */
37
+ export interface MaintenanceMetadataStats {
38
+ readonly transactionBytes: number;
39
+ readonly conflictBytes: number;
40
+ readonly idempotencyBytes: number;
41
+ readonly publicationBytes: number;
42
+ readonly refBytes: number;
43
+ readonly lockBytes: number | null;
44
+ }
45
+ /** Errors an adapter may return while maintenance is reading or sweeping. */
46
+ export type MaintenanceStorageError = CorruptRepositoryError | RevisionStorageError | UnsafePathError;
47
+ /** Small adapter boundary for integrity checks, accounting, and collection. */
48
+ export interface MaintenanceStorage {
49
+ readonly readRef: Effect.Effect<string | null, MaintenanceStorageError>;
50
+ readonly listObjects: (kind: MaintenanceObjectKind) => Effect.Effect<ReadonlyArray<MaintenanceObjectEntry>, MaintenanceStorageError>;
51
+ readonly readObject: (kind: MaintenanceObjectKind, id: string) => Effect.Effect<Uint8Array, MaintenanceStorageError>;
52
+ readonly readWorking: (path: string) => Effect.Effect<Uint8Array | null, MaintenanceStorageError>;
53
+ readonly listPublished: Effect.Effect<ReadonlyArray<MaintenancePublishedEntry>, MaintenanceStorageError>;
54
+ readonly listIdempotency: Effect.Effect<ReadonlyArray<MaintenanceIdempotencyRecord>, MaintenanceStorageError>;
55
+ readonly listProtectedTransactions: Effect.Effect<ReadonlyArray<MaintenanceProtectedTransaction>, MaintenanceStorageError>;
56
+ readonly metadataStats: Effect.Effect<MaintenanceMetadataStats, MaintenanceStorageError>;
57
+ readonly removeObject: (kind: MaintenanceObjectKind, id: string) => Effect.Effect<void, MaintenanceStorageError>;
58
+ }
59
+ /** One issue found by an integrity pass. */
60
+ export interface IntegrityIssue {
61
+ readonly code: string;
62
+ readonly target: string;
63
+ readonly detail: string;
64
+ }
65
+ /** Canonical integrity summary. */
66
+ export interface IntegrityReport {
67
+ readonly ok: boolean;
68
+ readonly headCommit: string | null;
69
+ readonly resources: number;
70
+ readonly objects: number;
71
+ readonly issues: ReadonlyArray<IntegrityIssue>;
72
+ }
73
+ /** Canonical storage accounting summary. */
74
+ export interface StorageReport {
75
+ readonly totalBytes: number;
76
+ readonly blobBytes: number;
77
+ readonly treeBytes: number;
78
+ readonly commitBytes: number;
79
+ readonly recoveryBytes: number;
80
+ readonly metadataBytes: number;
81
+ readonly resourceCount: number;
82
+ readonly commitCount: number;
83
+ readonly objectCount: number;
84
+ }
85
+ /** Canonical collection summary. */
86
+ export interface CollectionReport {
87
+ readonly scanned: number;
88
+ readonly removed: number;
89
+ readonly retained: number;
90
+ readonly bytesRemoved: number;
91
+ }
92
+ /** Content-addressed roots retained by collection. */
93
+ export interface CollectionRoots {
94
+ readonly commits: ReadonlySet<string>;
95
+ readonly trees: ReadonlySet<string>;
96
+ readonly blobs: ReadonlySet<string>;
97
+ }
98
+ /** Optional clock/grace controls for collection. */
99
+ export interface CollectionOptions {
100
+ readonly roots?: CollectionRoots;
101
+ readonly nowMillis?: number;
102
+ readonly gracePeriodMs?: number;
103
+ readonly cutoffMillis?: number;
104
+ }
105
+ export type MaintenanceError = MaintenanceStorageError | InvalidRevisionInputError;
106
+ /** Validate all immutable objects, reachable history, indexes, and materialized files. */
107
+ export declare const integrityReport: (storage: MaintenanceStorage) => Effect.Effect<IntegrityReport, never, never>;
108
+ /** Account immutable objects and metadata bytes without reading object contents. */
109
+ export declare const storageReport: (storage: MaintenanceStorage, resources?: number | readonly ResourceVersion[] | ReadonlyMap<string, ResourceVersion> | undefined) => Effect.Effect<StorageReport, MaintenanceError, never>;
110
+ /** Collect unreachable immutable objects after the configured grace period. */
111
+ export declare const collect: (storage: MaintenanceStorage, input?: CollectionRoots | CollectionOptions, cutoffMillis?: number) => Effect.Effect<CollectionReport, MaintenanceError>;
112
+ export {};
113
+ //# sourceMappingURL=maintenance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"maintenance.d.ts","sourceRoot":"","sources":["../../src/storage/maintenance.ts"],"names":[],"mappings":"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"}