@scolladon/tsgit 0.9.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 (125) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +169 -0
  3. package/dist/cjs/adapters/browser/index.cjs +2 -0
  4. package/dist/cjs/adapters/browser/index.cjs.map +1 -0
  5. package/dist/cjs/adapters/memory/index.cjs +2 -0
  6. package/dist/cjs/adapters/memory/index.cjs.map +1 -0
  7. package/dist/cjs/adapters/node/index.cjs +2 -0
  8. package/dist/cjs/adapters/node/index.cjs.map +1 -0
  9. package/dist/cjs/chunks/browser-http-transport-BBF8uw-f.cjs +2 -0
  10. package/dist/cjs/chunks/browser-http-transport-BBF8uw-f.cjs.map +1 -0
  11. package/dist/cjs/chunks/context-BcoAzPuU.cjs +2 -0
  12. package/dist/cjs/chunks/context-BcoAzPuU.cjs.map +1 -0
  13. package/dist/cjs/chunks/error-DL4SHCBJ.cjs +2 -0
  14. package/dist/cjs/chunks/error-DL4SHCBJ.cjs.map +1 -0
  15. package/dist/cjs/chunks/error-DN8Vnwr4.cjs +2 -0
  16. package/dist/cjs/chunks/error-DN8Vnwr4.cjs.map +1 -0
  17. package/dist/cjs/chunks/index-iUd-bwwm.cjs +2 -0
  18. package/dist/cjs/chunks/index-iUd-bwwm.cjs.map +1 -0
  19. package/dist/cjs/chunks/logger-Cz9r6yt5.cjs +2 -0
  20. package/dist/cjs/chunks/logger-Cz9r6yt5.cjs.map +1 -0
  21. package/dist/cjs/chunks/lru-cache-1OU7JhD8.cjs +2 -0
  22. package/dist/cjs/chunks/lru-cache-1OU7JhD8.cjs.map +1 -0
  23. package/dist/cjs/chunks/memory-http-transport-DGll7Af4.cjs +2 -0
  24. package/dist/cjs/chunks/memory-http-transport-DGll7Af4.cjs.map +1 -0
  25. package/dist/cjs/chunks/merge-base-DlGWnkxP.cjs +2 -0
  26. package/dist/cjs/chunks/merge-base-DlGWnkxP.cjs.map +1 -0
  27. package/dist/cjs/chunks/node-http-transport-CuOgJlws.cjs +2 -0
  28. package/dist/cjs/chunks/node-http-transport-CuOgJlws.cjs.map +1 -0
  29. package/dist/cjs/chunks/progress-CK7CT9vU.cjs +2 -0
  30. package/dist/cjs/chunks/progress-CK7CT9vU.cjs.map +1 -0
  31. package/dist/cjs/chunks/repository-Cbzk-Qwz.cjs +2 -0
  32. package/dist/cjs/chunks/repository-Cbzk-Qwz.cjs.map +1 -0
  33. package/dist/cjs/commands/index.cjs +2 -0
  34. package/dist/cjs/commands/index.cjs.map +1 -0
  35. package/dist/cjs/index.browser.cjs +2 -0
  36. package/dist/cjs/index.browser.cjs.map +1 -0
  37. package/dist/cjs/index.cjs +2 -0
  38. package/dist/cjs/index.cjs.map +1 -0
  39. package/dist/cjs/index.default.cjs +2 -0
  40. package/dist/cjs/index.default.cjs.map +1 -0
  41. package/dist/cjs/index.node.cjs +2 -0
  42. package/dist/cjs/index.node.cjs.map +1 -0
  43. package/dist/cjs/operators/index.cjs +2 -0
  44. package/dist/cjs/operators/index.cjs.map +1 -0
  45. package/dist/cjs/primitives/index.cjs +2 -0
  46. package/dist/cjs/primitives/index.cjs.map +1 -0
  47. package/dist/cjs/transport/index.cjs +2 -0
  48. package/dist/cjs/transport/index.cjs.map +1 -0
  49. package/dist/esm/adapters/browser/index.js +2 -0
  50. package/dist/esm/adapters/browser/index.js.map +1 -0
  51. package/dist/esm/adapters/memory/index.js +2 -0
  52. package/dist/esm/adapters/memory/index.js.map +1 -0
  53. package/dist/esm/adapters/node/index.js +2 -0
  54. package/dist/esm/adapters/node/index.js.map +1 -0
  55. package/dist/esm/chunks/browser-http-transport-CRPPmib5.js +2 -0
  56. package/dist/esm/chunks/browser-http-transport-CRPPmib5.js.map +1 -0
  57. package/dist/esm/chunks/context-CumKOV7K.js +2 -0
  58. package/dist/esm/chunks/context-CumKOV7K.js.map +1 -0
  59. package/dist/esm/chunks/error-CAlAXhN3.js +2 -0
  60. package/dist/esm/chunks/error-CAlAXhN3.js.map +1 -0
  61. package/dist/esm/chunks/error-DVZkS_ub.js +2 -0
  62. package/dist/esm/chunks/error-DVZkS_ub.js.map +1 -0
  63. package/dist/esm/chunks/index-gUdap5AF.js +2 -0
  64. package/dist/esm/chunks/index-gUdap5AF.js.map +1 -0
  65. package/dist/esm/chunks/logger-Cg7fUh8D.js +2 -0
  66. package/dist/esm/chunks/logger-Cg7fUh8D.js.map +1 -0
  67. package/dist/esm/chunks/lru-cache-Cy7C7Lx2.js +2 -0
  68. package/dist/esm/chunks/lru-cache-Cy7C7Lx2.js.map +1 -0
  69. package/dist/esm/chunks/memory-http-transport-Cv1sbkCX.js +2 -0
  70. package/dist/esm/chunks/memory-http-transport-Cv1sbkCX.js.map +1 -0
  71. package/dist/esm/chunks/merge-base-opORz-S1.js +2 -0
  72. package/dist/esm/chunks/merge-base-opORz-S1.js.map +1 -0
  73. package/dist/esm/chunks/node-http-transport-CuXVJf0s.js +2 -0
  74. package/dist/esm/chunks/node-http-transport-CuXVJf0s.js.map +1 -0
  75. package/dist/esm/chunks/progress-OxUHmDV4.js +2 -0
  76. package/dist/esm/chunks/progress-OxUHmDV4.js.map +1 -0
  77. package/dist/esm/chunks/repository-BaEhU6zt.js +2 -0
  78. package/dist/esm/chunks/repository-BaEhU6zt.js.map +1 -0
  79. package/dist/esm/commands/index.js +2 -0
  80. package/dist/esm/commands/index.js.map +1 -0
  81. package/dist/esm/index.browser.js +2 -0
  82. package/dist/esm/index.browser.js.map +1 -0
  83. package/dist/esm/index.default.js +2 -0
  84. package/dist/esm/index.default.js.map +1 -0
  85. package/dist/esm/index.js +2 -0
  86. package/dist/esm/index.js.map +1 -0
  87. package/dist/esm/index.node.js +2 -0
  88. package/dist/esm/index.node.js.map +1 -0
  89. package/dist/esm/operators/index.js +2 -0
  90. package/dist/esm/operators/index.js.map +1 -0
  91. package/dist/esm/primitives/index.js +2 -0
  92. package/dist/esm/primitives/index.js.map +1 -0
  93. package/dist/esm/transport/index.js +2 -0
  94. package/dist/esm/transport/index.js.map +1 -0
  95. package/dist/types/adapters/browser/index.d.cts +67 -0
  96. package/dist/types/adapters/browser/index.d.ts +67 -0
  97. package/dist/types/adapters/memory/index.d.cts +95 -0
  98. package/dist/types/adapters/memory/index.d.ts +95 -0
  99. package/dist/types/adapters/node/index.d.cts +75 -0
  100. package/dist/types/adapters/node/index.d.ts +75 -0
  101. package/dist/types/chunks/context-C6df52Qs.d.ts +354 -0
  102. package/dist/types/chunks/context-Ku1aP8Ie.d.cts +354 -0
  103. package/dist/types/chunks/diff-change-BwO75AgS.d.cts +59 -0
  104. package/dist/types/chunks/diff-change-CUWN3OSK.d.ts +59 -0
  105. package/dist/types/chunks/http-transport--_NdQOiw.d.cts +20 -0
  106. package/dist/types/chunks/http-transport--_NdQOiw.d.ts +20 -0
  107. package/dist/types/chunks/repository-BBKJnr8a.d.ts +89 -0
  108. package/dist/types/chunks/repository-Cv4Y0T9t.d.cts +89 -0
  109. package/dist/types/commands/index.d.cts +336 -0
  110. package/dist/types/commands/index.d.ts +336 -0
  111. package/dist/types/index.browser.d.cts +26 -0
  112. package/dist/types/index.browser.d.ts +26 -0
  113. package/dist/types/index.d.cts +68 -0
  114. package/dist/types/index.d.ts +68 -0
  115. package/dist/types/index.default.d.cts +35 -0
  116. package/dist/types/index.default.d.ts +35 -0
  117. package/dist/types/index.node.d.cts +23 -0
  118. package/dist/types/index.node.d.ts +23 -0
  119. package/dist/types/operators/index.d.cts +36 -0
  120. package/dist/types/operators/index.d.ts +36 -0
  121. package/dist/types/primitives/index.d.cts +217 -0
  122. package/dist/types/primitives/index.d.ts +217 -0
  123. package/dist/types/transport/index.d.cts +62 -0
  124. package/dist/types/transport/index.d.ts +62 -0
  125. package/package.json +524 -0
@@ -0,0 +1,75 @@
1
+ import { a as Context, C as Compressor, I as InflateStreamResult, F as FileSystem, c as FileStat, D as DirEntry, d as FileHandle, H as HashService, e as Hasher } from '../../chunks/context-Ku1aP8Ie.cjs';
2
+ import { H as HttpTransport, a as HttpRequest, b as HttpResponse } from '../../chunks/http-transport--_NdQOiw.cjs';
3
+
4
+ interface NodeAdapterOptions {
5
+ readonly workDir: string;
6
+ readonly gitDir?: string;
7
+ readonly bare?: boolean;
8
+ readonly allowInsecureHttp?: boolean;
9
+ readonly signal?: AbortSignal;
10
+ readonly deltaCacheMaxBytes?: number;
11
+ readonly deltaCacheMaxEntries?: number;
12
+ }
13
+ declare function createNodeContext(options: NodeAdapterOptions): Context;
14
+
15
+ interface NodeCompressorOptions {
16
+ /** Override the inflated-output cap. Tests use a small value to exercise the overflow branch. */
17
+ readonly maxInflatedBytes?: number;
18
+ }
19
+ declare class NodeCompressor implements Compressor {
20
+ private readonly maxInflatedBytes;
21
+ constructor(options?: NodeCompressorOptions);
22
+ deflate: (data: Uint8Array) => Promise<Uint8Array>;
23
+ inflate: (data: Uint8Array) => Promise<Uint8Array>;
24
+ streamInflate: (bytes: Uint8Array, offset: number) => Promise<InflateStreamResult>;
25
+ createInflateStream: () => TransformStream<Uint8Array, Uint8Array>;
26
+ }
27
+
28
+ declare class NodeFileSystem implements FileSystem {
29
+ private readonly rootDir;
30
+ constructor(rootDir: string);
31
+ read: (path: string) => Promise<Uint8Array>;
32
+ readSlice: (path: string, offset: number, length: number) => Promise<Uint8Array>;
33
+ readUtf8: (path: string) => Promise<string>;
34
+ write: (path: string, data: Uint8Array) => Promise<void>;
35
+ writeExclusive: (path: string, data: Uint8Array) => Promise<void>;
36
+ writeUtf8: (path: string, content: string) => Promise<void>;
37
+ exists: (path: string) => Promise<boolean>;
38
+ stat: (path: string) => Promise<FileStat>;
39
+ lstat: (path: string) => Promise<FileStat>;
40
+ readdir: (path: string) => Promise<ReadonlyArray<DirEntry>>;
41
+ mkdir: (path: string) => Promise<void>;
42
+ rm: (path: string) => Promise<void>;
43
+ rename: (src: string, dst: string) => Promise<void>;
44
+ readlink: (path: string) => Promise<string>;
45
+ symlink: (target: string, path: string) => Promise<void>;
46
+ chmod: (path: string, mode: number) => Promise<void>;
47
+ rmRecursive: (path: string) => Promise<void>;
48
+ openWithNoFollow: (path: string, mode: "read" | "write") => Promise<FileHandle>;
49
+ private removeTree;
50
+ private resolveForCreation;
51
+ private resolveForMode;
52
+ private checkContainment;
53
+ }
54
+
55
+ type Algorithm = 'sha1' | 'sha256';
56
+ declare class NodeHashService implements HashService {
57
+ readonly algorithm: Algorithm;
58
+ readonly digestLength: 20 | 32;
59
+ constructor(algorithm?: Algorithm);
60
+ hash: (data: Uint8Array) => Promise<Uint8Array>;
61
+ hashHex: (data: Uint8Array) => Promise<string>;
62
+ createHasher: () => Hasher;
63
+ }
64
+
65
+ interface NodeHttpTransportOptions {
66
+ readonly allowInsecureHttp?: boolean;
67
+ }
68
+ declare class NodeHttpTransport implements HttpTransport {
69
+ private readonly allowInsecureHttp;
70
+ constructor(options?: NodeHttpTransportOptions);
71
+ request: (req: HttpRequest) => Promise<HttpResponse>;
72
+ }
73
+
74
+ export { NodeCompressor, NodeFileSystem, NodeHashService, NodeHttpTransport, createNodeContext };
75
+ export type { NodeAdapterOptions, NodeHttpTransportOptions };
@@ -0,0 +1,75 @@
1
+ import { a as Context, C as Compressor, I as InflateStreamResult, F as FileSystem, c as FileStat, D as DirEntry, d as FileHandle, H as HashService, e as Hasher } from '../../chunks/context-C6df52Qs.js';
2
+ import { H as HttpTransport, a as HttpRequest, b as HttpResponse } from '../../chunks/http-transport--_NdQOiw.js';
3
+
4
+ interface NodeAdapterOptions {
5
+ readonly workDir: string;
6
+ readonly gitDir?: string;
7
+ readonly bare?: boolean;
8
+ readonly allowInsecureHttp?: boolean;
9
+ readonly signal?: AbortSignal;
10
+ readonly deltaCacheMaxBytes?: number;
11
+ readonly deltaCacheMaxEntries?: number;
12
+ }
13
+ declare function createNodeContext(options: NodeAdapterOptions): Context;
14
+
15
+ interface NodeCompressorOptions {
16
+ /** Override the inflated-output cap. Tests use a small value to exercise the overflow branch. */
17
+ readonly maxInflatedBytes?: number;
18
+ }
19
+ declare class NodeCompressor implements Compressor {
20
+ private readonly maxInflatedBytes;
21
+ constructor(options?: NodeCompressorOptions);
22
+ deflate: (data: Uint8Array) => Promise<Uint8Array>;
23
+ inflate: (data: Uint8Array) => Promise<Uint8Array>;
24
+ streamInflate: (bytes: Uint8Array, offset: number) => Promise<InflateStreamResult>;
25
+ createInflateStream: () => TransformStream<Uint8Array, Uint8Array>;
26
+ }
27
+
28
+ declare class NodeFileSystem implements FileSystem {
29
+ private readonly rootDir;
30
+ constructor(rootDir: string);
31
+ read: (path: string) => Promise<Uint8Array>;
32
+ readSlice: (path: string, offset: number, length: number) => Promise<Uint8Array>;
33
+ readUtf8: (path: string) => Promise<string>;
34
+ write: (path: string, data: Uint8Array) => Promise<void>;
35
+ writeExclusive: (path: string, data: Uint8Array) => Promise<void>;
36
+ writeUtf8: (path: string, content: string) => Promise<void>;
37
+ exists: (path: string) => Promise<boolean>;
38
+ stat: (path: string) => Promise<FileStat>;
39
+ lstat: (path: string) => Promise<FileStat>;
40
+ readdir: (path: string) => Promise<ReadonlyArray<DirEntry>>;
41
+ mkdir: (path: string) => Promise<void>;
42
+ rm: (path: string) => Promise<void>;
43
+ rename: (src: string, dst: string) => Promise<void>;
44
+ readlink: (path: string) => Promise<string>;
45
+ symlink: (target: string, path: string) => Promise<void>;
46
+ chmod: (path: string, mode: number) => Promise<void>;
47
+ rmRecursive: (path: string) => Promise<void>;
48
+ openWithNoFollow: (path: string, mode: "read" | "write") => Promise<FileHandle>;
49
+ private removeTree;
50
+ private resolveForCreation;
51
+ private resolveForMode;
52
+ private checkContainment;
53
+ }
54
+
55
+ type Algorithm = 'sha1' | 'sha256';
56
+ declare class NodeHashService implements HashService {
57
+ readonly algorithm: Algorithm;
58
+ readonly digestLength: 20 | 32;
59
+ constructor(algorithm?: Algorithm);
60
+ hash: (data: Uint8Array) => Promise<Uint8Array>;
61
+ hashHex: (data: Uint8Array) => Promise<string>;
62
+ createHasher: () => Hasher;
63
+ }
64
+
65
+ interface NodeHttpTransportOptions {
66
+ readonly allowInsecureHttp?: boolean;
67
+ }
68
+ declare class NodeHttpTransport implements HttpTransport {
69
+ private readonly allowInsecureHttp;
70
+ constructor(options?: NodeHttpTransportOptions);
71
+ request: (req: HttpRequest) => Promise<HttpResponse>;
72
+ }
73
+
74
+ export { NodeCompressor, NodeFileSystem, NodeHashService, NodeHttpTransport, createNodeContext };
75
+ export type { NodeAdapterOptions, NodeHttpTransportOptions };
@@ -0,0 +1,354 @@
1
+ import { H as HttpTransport } from './http-transport--_NdQOiw.js';
2
+
3
+ interface InflateStreamResult {
4
+ /** The fully-inflated output bytes. */
5
+ readonly output: Uint8Array;
6
+ /** The number of input bytes consumed, counted from `offset`. */
7
+ readonly bytesConsumed: number;
8
+ }
9
+ interface Compressor {
10
+ /** Deflate (compress) data using zlib deflate format (RFC 1950). */
11
+ readonly deflate: (data: Uint8Array) => Promise<Uint8Array>;
12
+ /** Inflate (decompress) zlib-compressed data. */
13
+ readonly inflate: (data: Uint8Array) => Promise<Uint8Array>;
14
+ /**
15
+ * Inflate one zlib stream starting at `offset` in `bytes`, stopping at the
16
+ * zlib terminator. Used by the pack-file resolver, where each entry is a
17
+ * separate zlib stream concatenated with other entries; the resolver does
18
+ * not know the compressed length of a single entry a priori.
19
+ *
20
+ * Returns the inflated output and the number of input bytes consumed
21
+ * (measured from `offset`). Throws DECOMPRESS_FAILED when the input at
22
+ * `offset` is not a valid zlib stream.
23
+ */
24
+ readonly streamInflate: (bytes: Uint8Array, offset: number) => Promise<InflateStreamResult>;
25
+ /**
26
+ * Create a streaming inflate transform.
27
+ * Returns a TransformStream that inflates chunks incrementally.
28
+ * Used for large packfile entries to avoid buffering entire objects.
29
+ */
30
+ readonly createInflateStream: () => TransformStream<Uint8Array, Uint8Array>;
31
+ }
32
+
33
+ /** Metadata returned by stat operations. */
34
+ interface FileStat {
35
+ readonly ctimeMs: number;
36
+ readonly mtimeMs: number;
37
+ readonly dev: number;
38
+ readonly ino: number;
39
+ readonly mode: number;
40
+ readonly uid: number;
41
+ readonly gid: number;
42
+ readonly size: number;
43
+ readonly isFile: boolean;
44
+ readonly isDirectory: boolean;
45
+ readonly isSymbolicLink: boolean;
46
+ /** Nanosecond-precision ctime. Populated by Node adapter (fs.stat({ bigint: true })). Undefined on platforms without ns support. */
47
+ readonly ctimeNs?: bigint;
48
+ /** Nanosecond-precision mtime. Populated by Node adapter. Undefined on platforms without ns support. */
49
+ readonly mtimeNs?: bigint;
50
+ }
51
+ /** A single entry from a directory listing. */
52
+ interface DirEntry {
53
+ readonly name: string;
54
+ readonly isFile: boolean;
55
+ readonly isDirectory: boolean;
56
+ readonly isSymbolicLink: boolean;
57
+ }
58
+ /**
59
+ * Minimal subset of Node's `fs/promises` FileHandle. Returned by `openWithNoFollow`.
60
+ *
61
+ * Lifetime: callers MUST `close()` the handle in a `finally` block. Holding handles open
62
+ * across async boundaries can leak file descriptors on Node — keep usage tight.
63
+ */
64
+ interface FileHandle {
65
+ /** Read up to `length` bytes into `buffer` at `offset` (in the buffer). */
66
+ readonly read: (buffer: Uint8Array, offset: number, length: number, position?: number) => Promise<number>;
67
+ /** Write the buffer to the file. */
68
+ readonly write: (buffer: Uint8Array) => Promise<void>;
69
+ /** Stat the open file (cheap — uses fstat on Node). */
70
+ readonly stat: () => Promise<FileStat>;
71
+ /** Release the underlying file descriptor. Idempotent — safe to call twice. */
72
+ readonly close: () => Promise<void>;
73
+ }
74
+ interface FileSystem {
75
+ /** Read entire file as bytes. Throws FILE_NOT_FOUND if not found. */
76
+ readonly read: (path: string) => Promise<Uint8Array>;
77
+ /** Read a byte slice from a file at the given offset. Throws FILE_NOT_FOUND if not found. */
78
+ readonly readSlice: (path: string, offset: number, length: number) => Promise<Uint8Array>;
79
+ /** Read entire file as UTF-8 string. Throws FILE_NOT_FOUND if not found. */
80
+ readonly readUtf8: (path: string) => Promise<string>;
81
+ /** Write bytes to file, creating parent directories as needed. Overwrites if exists. */
82
+ readonly write: (path: string, data: Uint8Array) => Promise<void>;
83
+ /**
84
+ * Write bytes to file. Fails with FILE_EXISTS if the file already exists (exclusive create).
85
+ *
86
+ * Contract obligations (Phase 7 §14.17):
87
+ * - **Parent-directory creation:** the adapter MUST ensure parent directories exist before the
88
+ * exclusive write. Equivalent to `mkdir -p dirname(path)` before `open(path, O_EXCL)`. If the
89
+ * parent is removed between the implicit mkdir and the open (e.g. concurrent `git gc` prunes
90
+ * the fanout), the adapter retries once: re-create the parent, re-attempt the open. On a second
91
+ * ENOENT the error propagates as FILE_NOT_FOUND.
92
+ * - **Symlink-safe ancestor check:** the adapter MUST reject writes where any ancestor directory
93
+ * of `path` is a symbolic link whose resolved target is outside the containment root. This
94
+ * closes the attack where an attacker replaces `objects/xx/` with a symlink pointing elsewhere.
95
+ * Implementation: lstat-walk the ancestor chain, or use `openat`-style relative opens.
96
+ */
97
+ readonly writeExclusive: (path: string, data: Uint8Array) => Promise<void>;
98
+ /** Write UTF-8 string to file, creating parent directories as needed. */
99
+ readonly writeUtf8: (path: string, content: string) => Promise<void>;
100
+ /** Check if path exists. */
101
+ readonly exists: (path: string) => Promise<boolean>;
102
+ /** Get file/directory metadata. Throws FILE_NOT_FOUND if not found. Follows symlinks. */
103
+ readonly stat: (path: string) => Promise<FileStat>;
104
+ /** Get file/directory metadata. Throws FILE_NOT_FOUND if not found. Does NOT follow symlinks. */
105
+ readonly lstat: (path: string) => Promise<FileStat>;
106
+ /** List directory entries. Throws NOT_A_DIRECTORY if not a directory. */
107
+ readonly readdir: (path: string) => Promise<ReadonlyArray<DirEntry>>;
108
+ /** Create directory and all parents. No-op if already exists. */
109
+ readonly mkdir: (path: string) => Promise<void>;
110
+ /** Remove file or empty directory. Throws FILE_NOT_FOUND if not found. */
111
+ readonly rm: (path: string) => Promise<void>;
112
+ /**
113
+ * Rename `src` to `dst`. Atomic where the platform supports it (Node: yes on POSIX;
114
+ * Browser OPFS: no — emulated as read + write + rm, caller must tolerate partial
115
+ * failure between steps). Both paths must be on the same logical root.
116
+ */
117
+ readonly rename: (src: string, dst: string) => Promise<void>;
118
+ /** Read the target of a symbolic link. Throws FILE_NOT_FOUND if not a symlink. */
119
+ readonly readlink: (path: string) => Promise<string>;
120
+ /** Create a symbolic link. Creates parent directories as needed. */
121
+ readonly symlink: (target: string, path: string) => Promise<void>;
122
+ /** Set file permissions. No-op on platforms without permission support (OPFS). */
123
+ readonly chmod: (path: string, mode: number) => Promise<void>;
124
+ /**
125
+ * Recursively remove a file or directory tree.
126
+ *
127
+ * Idempotent: a missing path returns void (no error).
128
+ *
129
+ * Symlink-safe: does NOT follow symlinks during traversal. When a directory entry is a
130
+ * symlink, the symlink itself is removed (the link, not its target), and the walk does
131
+ * not descend into it. This prevents an attacker who plants a symlink under a doomed
132
+ * directory from having `rmRecursive` reach outside the containment root.
133
+ */
134
+ readonly rmRecursive: (path: string) => Promise<void>;
135
+ /**
136
+ * Open a file with the platform equivalent of `O_NOFOLLOW` — refuses to open the path
137
+ * if its leaf is a symbolic link. Used by callers that must read/write a regular file
138
+ * without crossing a symlink hop (e.g., lockfile creation under the git dir).
139
+ *
140
+ * - Node: `fs.open(path, O_NOFOLLOW | (mode === 'write' ? O_WRONLY : O_RDONLY))`.
141
+ * - Memory: rejects with `PERMISSION_DENIED` when the leaf is a memory symlink entry.
142
+ * - Browser OPFS: throws `UNSUPPORTED_OPERATION` (OPFS has no symlinks; callers can
143
+ * fall back to a plain `read`/`write` because the no-follow guarantee holds vacuously).
144
+ *
145
+ * Throws `FILE_NOT_FOUND` if the leaf does not exist (in `read` mode).
146
+ * Throws `PERMISSION_DENIED` if the leaf is a symlink.
147
+ */
148
+ readonly openWithNoFollow: (path: string, mode: 'read' | 'write') => Promise<FileHandle>;
149
+ }
150
+
151
+ /** Incremental hash computation context. Single-use: consumed after digest. */
152
+ interface Hasher {
153
+ /** Feed data into the hash. Can be called multiple times before digest. Throws HASH_FAILED if called after digest/digestHex. */
154
+ readonly update: (data: Uint8Array) => void;
155
+ /** Finalize and return the raw digest bytes. Consumes the hasher — no further update/digest calls allowed. */
156
+ readonly digest: () => Promise<Uint8Array>;
157
+ /** Finalize and return the hex-encoded digest. Consumes the hasher — no further update/digest calls allowed. */
158
+ readonly digestHex: () => Promise<string>;
159
+ }
160
+ interface HashService {
161
+ /** Compute the digest of data in one shot. Returns raw bytes (20 for SHA-1, 32 for SHA-256). */
162
+ readonly hash: (data: Uint8Array) => Promise<Uint8Array>;
163
+ /** Compute the hex-encoded digest of data in one shot. */
164
+ readonly hashHex: (data: Uint8Array) => Promise<string>;
165
+ /** Create an incremental hasher for streaming hash computation. */
166
+ readonly createHasher: () => Hasher;
167
+ /** The hash algorithm name. */
168
+ readonly algorithm: 'sha1' | 'sha256';
169
+ /** Digest length in bytes (20 for SHA-1, 32 for SHA-256). */
170
+ readonly digestLength: 20 | 32;
171
+ }
172
+
173
+ type ObjectId = string & {
174
+ readonly __brand: unique symbol;
175
+ };
176
+ declare const ObjectId: {
177
+ readonly from: (hex: string) => ObjectId;
178
+ readonly fromRaw: (bytes: Uint8Array) => ObjectId;
179
+ };
180
+ type RefName = string & {
181
+ readonly __brand: unique symbol;
182
+ };
183
+ declare const RefName: {
184
+ readonly from: (name: string) => RefName;
185
+ };
186
+ type FilePath = string & {
187
+ readonly __brand: unique symbol;
188
+ };
189
+ declare const FilePath: {
190
+ readonly from: (path: string) => FilePath;
191
+ };
192
+
193
+ interface HashConfig {
194
+ readonly digestLength: 20 | 32;
195
+ readonly hexLength: 40 | 64;
196
+ }
197
+
198
+ interface LruCache<V> {
199
+ get(key: string): V | undefined;
200
+ set(key: string, value: V, byteSize: number): void;
201
+ has(key: string): boolean;
202
+ delete(key: string): boolean;
203
+ clear(): void;
204
+ readonly currentSize: number;
205
+ readonly maxSize: number;
206
+ readonly entryCount: number;
207
+ }
208
+
209
+ /**
210
+ * General-purpose level-based logger consumed by the facade and any cross-cutting
211
+ * concern (dispose, validation, lifecycle). Independent from the transport-tier
212
+ * `Logger` in `transport/types.ts`, which is event-based and HTTP-shaped.
213
+ *
214
+ * The facade wraps user-supplied loggers with sanitization at construction time
215
+ * (see Phase 10 design §8.5). Implementations should be tolerant of high call
216
+ * frequency and MUST NOT throw — a throwing logger crashes nothing.
217
+ */
218
+ interface Logger {
219
+ readonly debug?: (message: string, context?: Readonly<Record<string, unknown>>) => void;
220
+ readonly info?: (message: string, context?: Readonly<Record<string, unknown>>) => void;
221
+ readonly warn?: (message: string, context?: Readonly<Record<string, unknown>>) => void;
222
+ readonly error?: (message: string, context?: Readonly<Record<string, unknown>>) => void;
223
+ }
224
+ /** No-op Logger — every level method is absent (callers use optional chaining). */
225
+ declare const noopLogger: Logger;
226
+ /**
227
+ * Wrap a user-supplied logger so every `message` + every string value in the
228
+ * `context` object passes through `sanitize()` (Phase 9 §4.7) before reaching
229
+ * the sink. Per design §8.5 the facade applies this at construction time so no
230
+ * downstream caller ever feeds raw control bytes to a user-controlled sink.
231
+ *
232
+ * Methods that the user did not supply are absent on the wrapper (preserves
233
+ * the optional-method contract). Throws from the underlying sink are caught
234
+ * and dropped — a faulty logger must not crash the operation.
235
+ */
236
+ declare const wrapLoggerSanitizer: (logger: Logger) => Logger;
237
+
238
+ /**
239
+ * Progress reporter shape consumed by long-running commands. The facade
240
+ * (Phase 10) accepts a user-supplied implementation via
241
+ * `OpenRepositoryOptions.progress` and plumbs it onto `Context.progress`.
242
+ *
243
+ * Reporters are synchronous and fire-and-forget. The facade wraps every call
244
+ * site in try/catch; a throwing reporter never crashes the operation.
245
+ */
246
+ interface ProgressReporter {
247
+ /**
248
+ * Called once before the first work unit of a sub-task. `op` is a stable
249
+ * internal identifier (e.g., 'clone:write-objects'). `total`, when known,
250
+ * lets consumers render a percentage; absent for indeterminate work.
251
+ */
252
+ readonly start: (op: string, total?: number) => void;
253
+ /**
254
+ * Called periodically during the sub-task. `current` is the count of items
255
+ * processed so far; `total` may be undefined when not known. `text`, when
256
+ * provided, is sideband-style auxiliary text (sanitized by built-in reporters).
257
+ */
258
+ readonly update: (op: string, current: number, total?: number, text?: string) => void;
259
+ /** Called when the sub-task completes (success OR failure). */
260
+ readonly end: (op: string) => void;
261
+ }
262
+
263
+ /**
264
+ * Repository physical layout — where the working tree and .git directory live.
265
+ * Renamed in Phase 10 from the previous `RepositoryConfig` (port-tier) to free that
266
+ * name for the facade-tier `RepositoryConfig` shape (auth/parallelism/etc.).
267
+ */
268
+ interface RepositoryLayout {
269
+ /** Absolute path to the repository root (working tree). */
270
+ readonly workDir: string;
271
+ /** Absolute path to the .git directory (usually `${workDir}/.git`, but may differ for bare repos or worktrees). */
272
+ readonly gitDir: string;
273
+ /** Whether this is a bare repository. */
274
+ readonly bare: boolean;
275
+ }
276
+ /**
277
+ * Author / committer identity — Phase 9 §4.7 shape.
278
+ */
279
+ interface AuthorIdentity {
280
+ readonly name: string;
281
+ readonly email: string;
282
+ }
283
+ /**
284
+ * Authentication strategy for transport — narrowed shape consumed by withAuth.
285
+ */
286
+ type AuthStrategy = {
287
+ readonly type: 'bearer';
288
+ readonly token: string;
289
+ } | {
290
+ readonly type: 'basic';
291
+ readonly username: string;
292
+ readonly password: string;
293
+ };
294
+ /**
295
+ * Facade-tier configuration. Phase 10 introduces this shape; it carries the
296
+ * auth/parallelism/SSRF/network options the facade plumbs into network-pipeline.
297
+ * All fields are optional — primitives and commands consult only the keys they need.
298
+ */
299
+ interface RepositoryConfig {
300
+ readonly user?: AuthorIdentity;
301
+ readonly auth?: AuthStrategy;
302
+ /** Bounded parallelism for fan-out work. 1..32, default 8 (enforced by facade validation). */
303
+ readonly parallelism?: number;
304
+ readonly upstreamRef?: RefName;
305
+ readonly allowInsecure?: boolean;
306
+ readonly allowPrivateNetworks?: boolean;
307
+ readonly maxResponseBytes?: number;
308
+ readonly maxObjectsPerPack?: number;
309
+ readonly detectRenames?: boolean;
310
+ readonly breakStaleLockMs?: number;
311
+ readonly dnsResolver?: (host: string) => Promise<ReadonlyArray<string>>;
312
+ /** Hard cap on `dnsResolver` return-array length to bound resolver-amplification DoS. Default 64. */
313
+ readonly maxDnsResults?: number;
314
+ }
315
+ interface Context {
316
+ readonly fs: FileSystem;
317
+ readonly hash: HashService;
318
+ readonly compressor: Compressor;
319
+ readonly transport: HttpTransport;
320
+ readonly progress: ProgressReporter;
321
+ /** Repository physical layout. Required — every primitive needs gitDir/workDir. */
322
+ readonly layout: RepositoryLayout;
323
+ /** User-supplied working directory (may be a sub-path of layout.workDir). Defaults to layout.workDir when not set by the facade. */
324
+ readonly cwd: string;
325
+ /** Object serialization parameters (sha1 vs sha256 digest+hex sizes). */
326
+ readonly hashConfig: HashConfig;
327
+ /** Shared delta-base LRU cache; consumed by primitives' iterative delta walker. */
328
+ readonly deltaCache: LruCache<Uint8Array>;
329
+ /** Optional facade-tier configuration (auth, parallelism, SSRF, …). Populated by openRepository. */
330
+ readonly config?: RepositoryConfig;
331
+ /** Optional sanitized logger. Populated by openRepository. */
332
+ readonly logger?: Logger;
333
+ /** Optional abort signal for cancelling long-running operations. */
334
+ readonly signal?: AbortSignal;
335
+ }
336
+ interface CreateContextParts {
337
+ readonly fs: FileSystem;
338
+ readonly hash: HashService;
339
+ readonly compressor: Compressor;
340
+ readonly transport: HttpTransport;
341
+ readonly progress: ProgressReporter;
342
+ readonly layout: RepositoryLayout;
343
+ readonly cwd?: string;
344
+ readonly hashConfig: HashConfig;
345
+ readonly deltaCache: LruCache<Uint8Array>;
346
+ readonly config?: RepositoryConfig;
347
+ readonly logger?: Logger;
348
+ readonly signal?: AbortSignal;
349
+ }
350
+ /** Assemble a frozen Context from its constituent ports + layout. */
351
+ declare function createContext(parts: CreateContextParts): Context;
352
+
353
+ export { ObjectId as O, FilePath as b, createContext as i, RefName as j, noopLogger as n, wrapLoggerSanitizer as w };
354
+ export type { AuthStrategy as A, Compressor as C, DirEntry as D, FileSystem as F, HashService as H, InflateStreamResult as I, Logger as L, ProgressReporter as P, RepositoryConfig as R, Context as a, FileStat as c, FileHandle as d, Hasher as e, AuthorIdentity as f, CreateContextParts as g, RepositoryLayout as h };