@lobu/connector-sdk 7.2.0 → 9.0.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/dist/connector-runtime.d.ts +23 -11
- package/dist/connector-runtime.d.ts.map +1 -1
- package/dist/connector-runtime.js +32 -8
- package/dist/connector-runtime.js.map +1 -1
- package/dist/connector-types.d.ts +27 -15
- package/dist/connector-types.d.ts.map +1 -1
- package/dist/connector-types.js +0 -7
- package/dist/connector-types.js.map +1 -1
- package/dist/file-source.d.ts +112 -0
- package/dist/file-source.d.ts.map +1 -0
- package/dist/file-source.js +40 -0
- package/dist/file-source.js.map +1 -0
- package/dist/identity-normalize.d.ts +12 -0
- package/dist/identity-normalize.d.ts.map +1 -1
- package/dist/identity-normalize.js +12 -0
- package/dist/identity-normalize.js.map +1 -1
- package/dist/index.d.ts +15 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -5
- package/dist/index.js.map +1 -1
- package/dist/reaction-client-types.d.ts +126 -0
- package/dist/reaction-client-types.d.ts.map +1 -0
- package/dist/reaction-client-types.js +2 -0
- package/dist/reaction-client-types.js.map +1 -0
- package/dist/sources/cache.d.ts +82 -0
- package/dist/sources/cache.d.ts.map +1 -0
- package/dist/sources/cache.js +169 -0
- package/dist/sources/cache.js.map +1 -0
- package/dist/sources/git-file-source.d.ts +33 -0
- package/dist/sources/git-file-source.d.ts.map +1 -0
- package/dist/sources/git-file-source.js +207 -0
- package/dist/sources/git-file-source.js.map +1 -0
- package/dist/sources/git-http.d.ts +48 -0
- package/dist/sources/git-http.d.ts.map +1 -0
- package/dist/sources/git-http.js +179 -0
- package/dist/sources/git-http.js.map +1 -0
- package/dist/sources/git-snapshot.d.ts +14 -0
- package/dist/sources/git-snapshot.d.ts.map +1 -0
- package/dist/sources/git-snapshot.js +96 -0
- package/dist/sources/git-snapshot.js.map +1 -0
- package/dist/sources/glob.d.ts +31 -0
- package/dist/sources/glob.d.ts.map +1 -0
- package/dist/sources/glob.js +129 -0
- package/dist/sources/glob.js.map +1 -0
- package/dist/sources/local-file-source.d.ts +29 -0
- package/dist/sources/local-file-source.d.ts.map +1 -0
- package/dist/sources/local-file-source.js +343 -0
- package/dist/sources/local-file-source.js.map +1 -0
- package/dist/sources/resolver.d.ts +6 -0
- package/dist/sources/resolver.d.ts.map +1 -0
- package/dist/sources/resolver.js +47 -0
- package/dist/sources/resolver.js.map +1 -0
- package/dist/sources/snapshot.d.ts +19 -0
- package/dist/sources/snapshot.d.ts.map +1 -0
- package/dist/sources/snapshot.js +91 -0
- package/dist/sources/snapshot.js.map +1 -0
- package/dist/sources/tarball-file-source.d.ts +28 -0
- package/dist/sources/tarball-file-source.d.ts.map +1 -0
- package/dist/sources/tarball-file-source.js +273 -0
- package/dist/sources/tarball-file-source.js.map +1 -0
- package/dist/types.d.ts +3 -65
- package/dist/types.d.ts.map +1 -1
- package/package.json +10 -3
- package/dist/event-taxonomy.d.ts +0 -3
- package/dist/event-taxonomy.d.ts.map +0 -1
- package/dist/event-taxonomy.js +0 -30
- package/dist/event-taxonomy.js.map +0 -1
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal glob matcher + recursive directory walk.
|
|
3
|
+
*
|
|
4
|
+
* Supports the subset of glob syntax connectors actually need:
|
|
5
|
+
* - `*` matches any run of characters except `/`
|
|
6
|
+
* - `**` matches any run of characters including `/`
|
|
7
|
+
* - `?` matches exactly one character except `/`
|
|
8
|
+
* - Literal `.` `/` `_` `-` segments
|
|
9
|
+
*
|
|
10
|
+
* No brace-expansion, no `!` negation, no `[ ]` character classes. If a
|
|
11
|
+
* connector needs more, it can iterate `walkFiles("**\/*")` and filter in
|
|
12
|
+
* its own code — keeping the SDK surface small.
|
|
13
|
+
*/
|
|
14
|
+
import { readdir } from 'node:fs/promises';
|
|
15
|
+
import { join, posix, sep } from 'node:path';
|
|
16
|
+
/**
|
|
17
|
+
* Recursive walk yielding POSIX-style relative paths (forward-slash).
|
|
18
|
+
* Skips dot-directories of the cache itself (`.lobu-cache`) but otherwise
|
|
19
|
+
* includes hidden files — git's `.git/` is excluded by callers that need
|
|
20
|
+
* to (git source uses a separate snapshot dir without `.git`).
|
|
21
|
+
*/
|
|
22
|
+
export async function* walkDirectoryRelative(root) {
|
|
23
|
+
async function* walk(dir, prefix) {
|
|
24
|
+
let entries;
|
|
25
|
+
try {
|
|
26
|
+
entries = await readdir(dir, { withFileTypes: true });
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
if (err.code === 'ENOENT')
|
|
30
|
+
return;
|
|
31
|
+
throw err;
|
|
32
|
+
}
|
|
33
|
+
// Stable order — deterministic walk for tests + manifests.
|
|
34
|
+
entries.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
|
|
35
|
+
for (const entry of entries) {
|
|
36
|
+
const childPosix = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
37
|
+
const childAbs = join(dir, entry.name);
|
|
38
|
+
if (entry.isDirectory()) {
|
|
39
|
+
yield* walk(childAbs, childPosix);
|
|
40
|
+
}
|
|
41
|
+
else if (entry.isFile()) {
|
|
42
|
+
yield childPosix;
|
|
43
|
+
}
|
|
44
|
+
// Symlinks/sockets/etc. are skipped on purpose — connectors don't
|
|
45
|
+
// need them and they're a common attack vector through extracted tarballs.
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
yield* walk(root, '');
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Compile a glob to a RegExp. Anchored on both ends.
|
|
52
|
+
*
|
|
53
|
+
* Implementation note: we walk the glob char-by-char rather than splitting on
|
|
54
|
+
* `*` so we can distinguish `*` from `**` without ambiguity, and so literal
|
|
55
|
+
* regex metacharacters get escaped exactly once.
|
|
56
|
+
*/
|
|
57
|
+
export function globToRegExp(glob) {
|
|
58
|
+
let re = '^';
|
|
59
|
+
for (let i = 0; i < glob.length; i++) {
|
|
60
|
+
const c = glob[i];
|
|
61
|
+
if (c === '*') {
|
|
62
|
+
if (glob[i + 1] === '*') {
|
|
63
|
+
// `**` — match any run (including `/`). When followed by `/`, the
|
|
64
|
+
// whole `**/` consumes zero or more directory segments so e.g.
|
|
65
|
+
// `**/*.md` matches `foo.md` AND `a/b/foo.md`. Same on the trailing
|
|
66
|
+
// boundary so `foo/**` matches `foo` itself.
|
|
67
|
+
if (glob[i + 2] === '/') {
|
|
68
|
+
re += '(?:.*/)?';
|
|
69
|
+
i += 2; // skip `**` and the slash
|
|
70
|
+
}
|
|
71
|
+
else if (i === 0 && glob[i + 2] === undefined) {
|
|
72
|
+
// bare `**` — match anything (including empty).
|
|
73
|
+
re += '.*';
|
|
74
|
+
i++;
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
re += '.*';
|
|
78
|
+
i++;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
// `*` — match any run not containing `/`.
|
|
83
|
+
re += '[^/]*';
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
else if (c === '?') {
|
|
87
|
+
re += '[^/]';
|
|
88
|
+
}
|
|
89
|
+
else if (c === '/') {
|
|
90
|
+
re += '/';
|
|
91
|
+
}
|
|
92
|
+
else if (c === '.' ||
|
|
93
|
+
c === '(' ||
|
|
94
|
+
c === ')' ||
|
|
95
|
+
c === '+' ||
|
|
96
|
+
c === '|' ||
|
|
97
|
+
c === '^' ||
|
|
98
|
+
c === '$' ||
|
|
99
|
+
c === '{' ||
|
|
100
|
+
c === '}' ||
|
|
101
|
+
c === '[' ||
|
|
102
|
+
c === ']' ||
|
|
103
|
+
c === '\\') {
|
|
104
|
+
re += `\\${c}`;
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
re += c;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
re += '$';
|
|
111
|
+
return new RegExp(re);
|
|
112
|
+
}
|
|
113
|
+
const _globCache = new Map();
|
|
114
|
+
function compileCached(glob) {
|
|
115
|
+
let r = _globCache.get(glob);
|
|
116
|
+
if (!r) {
|
|
117
|
+
r = globToRegExp(glob);
|
|
118
|
+
_globCache.set(glob, r);
|
|
119
|
+
}
|
|
120
|
+
return r;
|
|
121
|
+
}
|
|
122
|
+
/** Test a POSIX-style relative path against `glob`. */
|
|
123
|
+
export function matchesGlob(relativePath, glob) {
|
|
124
|
+
// Normalize windows separators if any leaked in. Callers should pass
|
|
125
|
+
// POSIX already (walkDirectoryRelative emits POSIX) but defensively:
|
|
126
|
+
const norm = sep === posix.sep ? relativePath : relativePath.split(sep).join(posix.sep);
|
|
127
|
+
return compileCached(glob).test(norm);
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=glob.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glob.js","sourceRoot":"","sources":["../../src/sources/glob.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LocalFileSource — adapter over a local directory.
|
|
3
|
+
*
|
|
4
|
+
* URI shape: `file:///absolute/path/`
|
|
5
|
+
*
|
|
6
|
+
* - `fetch()` stream-copies the source tree into a per-ref cache dir
|
|
7
|
+
* (`${WORKSPACE_DIR}/.lobu-cache/sources/<uri-hash>/refs/<ref>/`),
|
|
8
|
+
* sealing each file's sha256 during the copy so the manifest's hashes
|
|
9
|
+
* record exactly the bytes that landed in the cache. The Snapshot
|
|
10
|
+
* reads from that per-ref dir — never the live source — so
|
|
11
|
+
* `snapshot.ref` matches `sha256(snapshot.readFile(path))` for the
|
|
12
|
+
* bytes captured at fetch time, even under concurrent writes against
|
|
13
|
+
* the source. See `Snapshot` in `file-source.ts` for the honest
|
|
14
|
+
* same-UID mutability contract.
|
|
15
|
+
* - `ref` is the canonical manifest hash (sha256 of sorted `(path, sha256)`
|
|
16
|
+
* pairs).
|
|
17
|
+
* - `diffSinceRef(prevRef)`: re-walks the live directory, builds a fresh
|
|
18
|
+
* manifest, and diffs it against the stored per-ref manifest that
|
|
19
|
+
* matches `prevRef`. If no stored manifest matches (cache was cleared
|
|
20
|
+
* between runs), the diff treats every current file as `added`.
|
|
21
|
+
*/
|
|
22
|
+
import type { FileDelta, FileSystemSource, Snapshot } from '../file-source.js';
|
|
23
|
+
export declare class LocalFileSource implements FileSystemSource {
|
|
24
|
+
#private;
|
|
25
|
+
constructor(uri: string);
|
|
26
|
+
fetch(): Promise<Snapshot>;
|
|
27
|
+
diffSinceRef(prevRef: string): Promise<FileDelta>;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=local-file-source.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-file-source.d.ts","sourceRoot":"","sources":["../../src/sources/local-file-source.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAgBH,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAmB/E,qBAAa,eAAgB,YAAW,gBAAgB;;gBAkB1C,GAAG,EAAE,MAAM;IASvB,KAAK,IAAI,OAAO,CAAC,QAAQ,CAAC;IAwF1B,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;CAoBlD"}
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LocalFileSource — adapter over a local directory.
|
|
3
|
+
*
|
|
4
|
+
* URI shape: `file:///absolute/path/`
|
|
5
|
+
*
|
|
6
|
+
* - `fetch()` stream-copies the source tree into a per-ref cache dir
|
|
7
|
+
* (`${WORKSPACE_DIR}/.lobu-cache/sources/<uri-hash>/refs/<ref>/`),
|
|
8
|
+
* sealing each file's sha256 during the copy so the manifest's hashes
|
|
9
|
+
* record exactly the bytes that landed in the cache. The Snapshot
|
|
10
|
+
* reads from that per-ref dir — never the live source — so
|
|
11
|
+
* `snapshot.ref` matches `sha256(snapshot.readFile(path))` for the
|
|
12
|
+
* bytes captured at fetch time, even under concurrent writes against
|
|
13
|
+
* the source. See `Snapshot` in `file-source.ts` for the honest
|
|
14
|
+
* same-UID mutability contract.
|
|
15
|
+
* - `ref` is the canonical manifest hash (sha256 of sorted `(path, sha256)`
|
|
16
|
+
* pairs).
|
|
17
|
+
* - `diffSinceRef(prevRef)`: re-walks the live directory, builds a fresh
|
|
18
|
+
* manifest, and diffs it against the stored per-ref manifest that
|
|
19
|
+
* matches `prevRef`. If no stored manifest matches (cache was cleared
|
|
20
|
+
* between runs), the diff treats every current file as `added`.
|
|
21
|
+
*/
|
|
22
|
+
import { createReadStream, createWriteStream } from 'node:fs';
|
|
23
|
+
import { createHash, randomBytes } from 'node:crypto';
|
|
24
|
+
import { mkdir, readFile, readdir, realpath, rename, rm, stat, } from 'node:fs/promises';
|
|
25
|
+
import { pipeline } from 'node:stream/promises';
|
|
26
|
+
import { fileURLToPath } from 'node:url';
|
|
27
|
+
import { dirname, join, relative, sep } from 'node:path';
|
|
28
|
+
import { canonicalManifestRef, cachePathsFor, defaultCacheRoot, diffManifests, readAndVerifyMeta, readManifest, requireMeta, withSourceLock, writeManifest, writeMeta, } from './cache.js';
|
|
29
|
+
import { walkDirectoryRelative } from './glob.js';
|
|
30
|
+
import { DirectorySnapshot } from './snapshot.js';
|
|
31
|
+
export class LocalFileSource {
|
|
32
|
+
#uri;
|
|
33
|
+
#rootDir;
|
|
34
|
+
#paths;
|
|
35
|
+
/**
|
|
36
|
+
* When the local source root happens to *contain* the SDK cache dir
|
|
37
|
+
* (`${WORKSPACE_DIR}/.lobu-cache`) — typical when the source is the
|
|
38
|
+
* workspace root, OR when WORKSPACE_DIR is nested inside the source —
|
|
39
|
+
* we must NOT ingest our own cache files, or every fetch() would mutate
|
|
40
|
+
* the ref and self-pollute.
|
|
41
|
+
*
|
|
42
|
+
* Resolved at fetch() time using realpath() on both source root and the
|
|
43
|
+
* cache directory, so we exclude exactly the right subtree no matter
|
|
44
|
+
* where the cache lives relative to the source. If the cache is outside
|
|
45
|
+
* the source entirely, the predicate excludes nothing.
|
|
46
|
+
*/
|
|
47
|
+
#exclude = () => false;
|
|
48
|
+
constructor(uri) {
|
|
49
|
+
if (!uri.startsWith('file://')) {
|
|
50
|
+
throw new Error(`LocalFileSource: expected file:// URI, got ${uri}`);
|
|
51
|
+
}
|
|
52
|
+
this.#uri = uri;
|
|
53
|
+
this.#rootDir = fileURLToPath(uri);
|
|
54
|
+
this.#paths = cachePathsFor(uri);
|
|
55
|
+
}
|
|
56
|
+
fetch() {
|
|
57
|
+
return withSourceLock(this.#uri, async () => {
|
|
58
|
+
const s = await stat(this.#rootDir).catch(() => null);
|
|
59
|
+
if (!s || !s.isDirectory()) {
|
|
60
|
+
throw new Error(`LocalFileSource: ${this.#rootDir} is not a directory`);
|
|
61
|
+
}
|
|
62
|
+
await mkdir(this.#paths.root, { recursive: true });
|
|
63
|
+
await readAndVerifyMeta(this.#paths.metaPath, this.#uri);
|
|
64
|
+
// Recompute exclude predicate each fetch(): the cache dir's location
|
|
65
|
+
// relative to the source can shift if WORKSPACE_DIR changes between
|
|
66
|
+
// calls (different process, different cwd).
|
|
67
|
+
this.#exclude = await resolveCacheExclude(this.#rootDir);
|
|
68
|
+
// Race-free pipeline:
|
|
69
|
+
//
|
|
70
|
+
// 1. List the source's relative file paths (no byte reads yet).
|
|
71
|
+
// 2. For each file: stream-pipe the source bytes through a sha256 hash
|
|
72
|
+
// AND into a staging copy in a single pass. The per-file hash is
|
|
73
|
+
// SEALED at copy time — the bytes that landed in staging are
|
|
74
|
+
// identical to the bytes the hash was computed over, and there
|
|
75
|
+
// is no second pass over staging that could observe a post-copy
|
|
76
|
+
// mutation. THIS is the actual mechanism that pins
|
|
77
|
+
// `snapshot.ref` to the bytes the Snapshot will read; an earlier
|
|
78
|
+
// pass also chmod-locked the per-ref dir to 0500/0400, but
|
|
79
|
+
// chmod doesn't bind same-UID writers (the owner can re-mode
|
|
80
|
+
// their own files), so it was theater against the threat model
|
|
81
|
+
// that matters and has been removed.
|
|
82
|
+
// 3. Staging lives INSIDE the cache root at
|
|
83
|
+
// `${root}/refs/<crypto-random-32hex>` — same filesystem as the
|
|
84
|
+
// destination per-ref dir, so `rename()` is atomic.
|
|
85
|
+
// 4. Compute the canonical ref from the sealed per-file hashes.
|
|
86
|
+
// 5. If `refs/<ref>` already exists, drop staging; else rename
|
|
87
|
+
// staging into the per-ref dir.
|
|
88
|
+
//
|
|
89
|
+
// The Snapshot reads from the per-ref dir — never from the live
|
|
90
|
+
// source — so `snapshot.ref` matches the bytes Snapshot.readFile
|
|
91
|
+
// returns at the moment fetch() resolved. Same-UID post-fetch
|
|
92
|
+
// mutation is documented as out-of-scope in the Snapshot contract.
|
|
93
|
+
const relPaths = await listRelativeFiles(this.#rootDir, this.#exclude);
|
|
94
|
+
await mkdir(join(this.#paths.root, 'refs'), { recursive: true });
|
|
95
|
+
const stagingDir = join(this.#paths.root, 'refs', randomBytes(16).toString('hex'));
|
|
96
|
+
await mkdir(stagingDir, { recursive: true, mode: 0o700 });
|
|
97
|
+
let stagingMoved = false;
|
|
98
|
+
let refDir;
|
|
99
|
+
let files;
|
|
100
|
+
let ref;
|
|
101
|
+
try {
|
|
102
|
+
files = await streamCopyAndHash(this.#rootDir, stagingDir, relPaths);
|
|
103
|
+
ref = canonicalManifestRef(files);
|
|
104
|
+
refDir = perRefDir(this.#paths.root, ref);
|
|
105
|
+
if (await dirExists(refDir)) {
|
|
106
|
+
// Same content already installed; throw away the staging copy.
|
|
107
|
+
await rm(stagingDir, { recursive: true, force: true });
|
|
108
|
+
stagingMoved = true;
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
await rename(stagingDir, refDir);
|
|
112
|
+
stagingMoved = true;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
finally {
|
|
116
|
+
if (!stagingMoved) {
|
|
117
|
+
await rm(stagingDir, { recursive: true, force: true }).catch(() => undefined);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
const manifest = {
|
|
121
|
+
ref,
|
|
122
|
+
files,
|
|
123
|
+
fetched_at: new Date().toISOString(),
|
|
124
|
+
};
|
|
125
|
+
await writeManifest(this.#paths.manifestPath, manifest);
|
|
126
|
+
await writeMeta(this.#paths.metaPath, { uri: this.#uri, kind: 'local' });
|
|
127
|
+
// Also persist a per-ref copy so diffSinceRef can look up prior refs.
|
|
128
|
+
await writePerRefManifest(this.#paths.root, manifest);
|
|
129
|
+
// Keep the per-ref cache bounded — `refs/` accumulates a new dir per
|
|
130
|
+
// distinct content state if the source is rewritten. Always preserve
|
|
131
|
+
// the just-returned dir (`refDir`), including the cache-hit branch
|
|
132
|
+
// where its mtime is older than newer entries — pruning it would
|
|
133
|
+
// ENOENT the Snapshot we just handed back. Mirrors the
|
|
134
|
+
// `protectedRefDir` argument tarball-file-source.ts already uses.
|
|
135
|
+
await pruneOldRefDirs(this.#paths.root, MAX_REF_DIRS, refDir);
|
|
136
|
+
return new DirectorySnapshot(refDir, ref);
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
diffSinceRef(prevRef) {
|
|
140
|
+
return withSourceLock(this.#uri, async () => {
|
|
141
|
+
await requireMeta(this.#paths.metaPath, this.#uri);
|
|
142
|
+
this.#exclude = await resolveCacheExclude(this.#rootDir);
|
|
143
|
+
const files = await collectFilesFromLive(this.#rootDir, this.#exclude);
|
|
144
|
+
const curRef = canonicalManifestRef(files);
|
|
145
|
+
if (curRef === prevRef)
|
|
146
|
+
return { added: [], modified: [], removed: [] };
|
|
147
|
+
const prev = await readPerRefManifest(this.#paths.root, prevRef);
|
|
148
|
+
const next = { ref: curRef, files, fetched_at: new Date().toISOString() };
|
|
149
|
+
if (!prev) {
|
|
150
|
+
// No record of the previous ref — caller's checkpoint references a ref
|
|
151
|
+
// we no longer have on disk. Treat as "everything is new" so the
|
|
152
|
+
// connector re-ingests rather than silently dropping data.
|
|
153
|
+
return { added: files.map((f) => f.path), modified: [], removed: [] };
|
|
154
|
+
}
|
|
155
|
+
return diffManifests(prev, next);
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Compute the exclude predicate for `.lobu-cache`. Realpaths both source root
|
|
161
|
+
* and `${cacheRoot}/.lobu-cache`, then:
|
|
162
|
+
* - If the cache dir is contained under the source root, exclude that exact
|
|
163
|
+
* relative subtree (POSIX-separated).
|
|
164
|
+
* - Otherwise return a no-op predicate — no exclusion needed.
|
|
165
|
+
*
|
|
166
|
+
* This handles three layouts correctly:
|
|
167
|
+
* (a) source root === workspace root → exclude `.lobu-cache/`
|
|
168
|
+
* (b) WORKSPACE_DIR is nested inside source (e.g. `source/workspace/`) →
|
|
169
|
+
* exclude `workspace/.lobu-cache/`
|
|
170
|
+
* (c) workspace lives outside source → no exclusion
|
|
171
|
+
*
|
|
172
|
+
* Realpath defends against symlinked workspace dirs.
|
|
173
|
+
*/
|
|
174
|
+
async function resolveCacheExclude(sourceRoot) {
|
|
175
|
+
const cacheBase = join(defaultCacheRoot(), '.lobu-cache');
|
|
176
|
+
const realSource = await realpath(sourceRoot).catch(() => sourceRoot);
|
|
177
|
+
const realCache = await realpath(cacheBase).catch(() => cacheBase);
|
|
178
|
+
const rel = relative(realSource, realCache);
|
|
179
|
+
if (rel === '' || rel.startsWith('..') || rel.split(sep).includes('..')) {
|
|
180
|
+
// cache is outside source (or coincides with the source root, which is
|
|
181
|
+
// degenerate — nothing meaningful to exclude). No-op predicate.
|
|
182
|
+
return () => false;
|
|
183
|
+
}
|
|
184
|
+
const posixRel = sep === '/' ? rel : rel.split(sep).join('/');
|
|
185
|
+
const prefix = `${posixRel}/`;
|
|
186
|
+
return (relPath) => relPath === posixRel || relPath.startsWith(prefix);
|
|
187
|
+
}
|
|
188
|
+
function perRefDir(root, ref) {
|
|
189
|
+
return join(root, 'refs', ref);
|
|
190
|
+
}
|
|
191
|
+
async function dirExists(p) {
|
|
192
|
+
const s = await stat(p).catch(() => null);
|
|
193
|
+
return !!s && s.isDirectory();
|
|
194
|
+
}
|
|
195
|
+
/** Max number of `refs/<hash>` per-ref directories kept on disk. */
|
|
196
|
+
const MAX_REF_DIRS = 3;
|
|
197
|
+
/** List relative paths from the source root, applying the exclude predicate. */
|
|
198
|
+
async function listRelativeFiles(rootDir, exclude) {
|
|
199
|
+
const out = [];
|
|
200
|
+
for await (const rel of walkDirectoryRelative(rootDir)) {
|
|
201
|
+
if (exclude(rel))
|
|
202
|
+
continue;
|
|
203
|
+
out.push(rel);
|
|
204
|
+
}
|
|
205
|
+
return out;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Stream-copy each tracked file from `sourceRoot` into `stagingDir`, feeding
|
|
209
|
+
* the bytes through a sha256 hasher in the same pass. Per-file hash is
|
|
210
|
+
* SEALED at copy time — the manifest entry records exactly the bytes that
|
|
211
|
+
* were written into staging. There is no second pass over staging that
|
|
212
|
+
* could observe a post-copy mutation.
|
|
213
|
+
*
|
|
214
|
+
* Why streaming instead of copy-on-write + post-hash: COW (`COPYFILE_FICLONE`)
|
|
215
|
+
* shares pages with the source until either side writes; a concurrent
|
|
216
|
+
* truncate-and-rewrite on the source breaks the share and may race the
|
|
217
|
+
* hash pass. A read-then-hash-then-write streaming pipe seals the bytes
|
|
218
|
+
* the instant they leave the source.
|
|
219
|
+
*/
|
|
220
|
+
async function streamCopyAndHash(sourceRoot, stagingDir, relPaths) {
|
|
221
|
+
const out = [];
|
|
222
|
+
for (const rel of relPaths) {
|
|
223
|
+
const src = join(sourceRoot, rel);
|
|
224
|
+
const dst = join(stagingDir, rel);
|
|
225
|
+
await mkdir(dirname(dst), { recursive: true });
|
|
226
|
+
const hash = createHash('sha256');
|
|
227
|
+
const reader = createReadStream(src);
|
|
228
|
+
reader.on('data', (chunk) => {
|
|
229
|
+
hash.update(chunk);
|
|
230
|
+
});
|
|
231
|
+
await pipeline(reader, createWriteStream(dst));
|
|
232
|
+
out.push({ path: rel, sha256: hash.digest('hex') });
|
|
233
|
+
}
|
|
234
|
+
return out;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Hash files directly from the live source root — used by `diffSinceRef()`,
|
|
238
|
+
* which doesn't return a Snapshot and only needs a manifest to compare
|
|
239
|
+
* against. Race-tolerant: a mid-walk write just shows up as part of the
|
|
240
|
+
* next diff.
|
|
241
|
+
*/
|
|
242
|
+
async function collectFilesFromLive(rootDir, exclude) {
|
|
243
|
+
const out = [];
|
|
244
|
+
for await (const rel of walkDirectoryRelative(rootDir)) {
|
|
245
|
+
if (exclude(rel))
|
|
246
|
+
continue;
|
|
247
|
+
const abs = join(rootDir, rel);
|
|
248
|
+
const buf = await readFile(abs);
|
|
249
|
+
const sha = createHash('sha256').update(buf).digest('hex');
|
|
250
|
+
out.push({ path: rel, sha256: sha });
|
|
251
|
+
}
|
|
252
|
+
return out;
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Keep at most `keep` per-ref directories under `${root}/refs/`. Sorted by
|
|
256
|
+
* mtime descending; the oldest are rm-rf'd. `protectedRefDir` is always
|
|
257
|
+
* preserved regardless of mtime — the cache-hit branch in fetch() returns
|
|
258
|
+
* an existing dir whose mtime may be older than newer entries, and the
|
|
259
|
+
* Snapshot we just handed back is reading from it. Pre-this-guard, the
|
|
260
|
+
* mtime sort happily pruned exactly the dir the caller was about to read,
|
|
261
|
+
* leaving the Snapshot pointing at an ENOENT. Matches the
|
|
262
|
+
* `protectedRefDir` parameter tarball-file-source.ts already uses
|
|
263
|
+
* (lines 137 + 228-273).
|
|
264
|
+
*
|
|
265
|
+
* Snapshots already handed out keep working as long as their backing
|
|
266
|
+
* dir wasn't pruned — `keep=3` accommodates a fresh fetch plus two
|
|
267
|
+
* in-flight overlapping syncs.
|
|
268
|
+
*
|
|
269
|
+
* Filters by name shape (64-hex sha256). Skips in-flight staging dirs
|
|
270
|
+
* (32-hex random names co-located in `refs/`) AND any legacy `.staging.*`
|
|
271
|
+
* directories from older builds. Per-ref manifest JSON files
|
|
272
|
+
* (`<ref>.json`) are files, not directories, and are kept indefinitely
|
|
273
|
+
* so historical diffs work even after the data dir is gone.
|
|
274
|
+
*
|
|
275
|
+
* v1 limitation: this prune is process-local (`withSourceLock` is an
|
|
276
|
+
* in-memory mutex). Two processes sharing the same
|
|
277
|
+
* `${WORKSPACE_DIR}/.lobu-cache` can race-prune each other's per-ref
|
|
278
|
+
* dirs — including the one a peer's Snapshot is reading. v1 supports
|
|
279
|
+
* one cache owner per workspace; multi-process sharing would need a
|
|
280
|
+
* filesystem advisory lock around fetch+prune.
|
|
281
|
+
*/
|
|
282
|
+
async function pruneOldRefDirs(root, keep, protectedRefDir) {
|
|
283
|
+
const refsRoot = join(root, 'refs');
|
|
284
|
+
let entries;
|
|
285
|
+
try {
|
|
286
|
+
entries = await readdir(refsRoot, { withFileTypes: true });
|
|
287
|
+
}
|
|
288
|
+
catch (err) {
|
|
289
|
+
if (err.code === 'ENOENT')
|
|
290
|
+
return;
|
|
291
|
+
throw err;
|
|
292
|
+
}
|
|
293
|
+
const candidates = [];
|
|
294
|
+
for (const ent of entries) {
|
|
295
|
+
if (!ent.isDirectory())
|
|
296
|
+
continue;
|
|
297
|
+
// Only touch completed per-ref dirs (64-hex sha256). In-flight staging
|
|
298
|
+
// dirs use a 32-hex randomBytes name and must not be pruned.
|
|
299
|
+
if (!/^[a-f0-9]{64}$/.test(ent.name))
|
|
300
|
+
continue;
|
|
301
|
+
const abs = join(refsRoot, ent.name);
|
|
302
|
+
try {
|
|
303
|
+
const s = await stat(abs);
|
|
304
|
+
candidates.push({
|
|
305
|
+
name: ent.name,
|
|
306
|
+
abs,
|
|
307
|
+
mtimeMs: s.mtimeMs,
|
|
308
|
+
protected: abs === protectedRefDir,
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
catch {
|
|
312
|
+
// Skip — concurrent prune from another process is fine.
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
if (candidates.length <= keep)
|
|
316
|
+
return;
|
|
317
|
+
const protectedDirs = candidates.filter((c) => c.protected);
|
|
318
|
+
const others = candidates
|
|
319
|
+
.filter((c) => !c.protected)
|
|
320
|
+
.sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
321
|
+
const keepers = new Set([
|
|
322
|
+
...protectedDirs.map((c) => c.name),
|
|
323
|
+
...others.slice(0, Math.max(0, keep - protectedDirs.length)).map((c) => c.name),
|
|
324
|
+
]);
|
|
325
|
+
for (const c of candidates) {
|
|
326
|
+
if (keepers.has(c.name))
|
|
327
|
+
continue;
|
|
328
|
+
await rm(c.abs, { recursive: true, force: true }).catch(() => undefined);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Per-ref manifest storage under `<root>/refs/<ref>.json`. Lets a connector
|
|
333
|
+
* keep checkpointing arbitrary `prevRef`s without us guessing.
|
|
334
|
+
*/
|
|
335
|
+
async function writePerRefManifest(root, manifest) {
|
|
336
|
+
const { mkdir } = await import('node:fs/promises');
|
|
337
|
+
await mkdir(join(root, 'refs'), { recursive: true });
|
|
338
|
+
await writeManifest(join(root, 'refs', `${manifest.ref}.json`), manifest);
|
|
339
|
+
}
|
|
340
|
+
async function readPerRefManifest(root, ref) {
|
|
341
|
+
return readManifest(join(root, 'refs', `${ref}.json`));
|
|
342
|
+
}
|
|
343
|
+
//# sourceMappingURL=local-file-source.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-file-source.js","sourceRoot":"","sources":["../../src/sources/local-file-source.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../src/sources/resolver.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAK1D,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,gBAAgB,CA8DxD"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { GitFileSource } from './git-file-source.js';
|
|
2
|
+
import { LocalFileSource } from './local-file-source.js';
|
|
3
|
+
import { TarballFileSource } from './tarball-file-source.js';
|
|
4
|
+
export function resolveUri(uri) {
|
|
5
|
+
if (typeof uri !== 'string' || uri.length === 0) {
|
|
6
|
+
throw new Error('fileSystemSourceFromUri: uri must be a non-empty string');
|
|
7
|
+
}
|
|
8
|
+
// git+ssh:// — explicit reject with helpful suggestion.
|
|
9
|
+
if (uri.startsWith('git+ssh://') || uri.startsWith('ssh://')) {
|
|
10
|
+
throw new Error(`Unsupported scheme: ${uri.split('://')[0]}://. SSH auth requires operator keys ` +
|
|
11
|
+
`and is out of scope for v1. Use git+https://github.com/owner/repo.git instead.`);
|
|
12
|
+
}
|
|
13
|
+
// git+http:// — explicit reject (no plaintext clones).
|
|
14
|
+
if (uri.startsWith('git+http://')) {
|
|
15
|
+
throw new Error(`Unsupported scheme: git+http://. Plaintext git fetch is rejected; use git+https://.`);
|
|
16
|
+
}
|
|
17
|
+
if (uri.startsWith('git+https://')) {
|
|
18
|
+
return new GitFileSource(uri);
|
|
19
|
+
}
|
|
20
|
+
if (uri.startsWith('file://')) {
|
|
21
|
+
return new LocalFileSource(uri);
|
|
22
|
+
}
|
|
23
|
+
if (uri.startsWith('https://')) {
|
|
24
|
+
// Tarball schemes: must end in .tar.gz or .tgz (query-stripped).
|
|
25
|
+
const pathPart = uri.split('?')[0]?.split('#')[0] ?? uri;
|
|
26
|
+
if (pathPart.endsWith('.tar.gz') || pathPart.endsWith('.tgz')) {
|
|
27
|
+
return new TarballFileSource(uri);
|
|
28
|
+
}
|
|
29
|
+
throw new Error(`Unsupported HTTPS URL: ${uri}. Only .tar.gz / .tgz are supported in v1 ` +
|
|
30
|
+
`(no .zip, .7z, or raw directories).`);
|
|
31
|
+
}
|
|
32
|
+
if (uri.startsWith('http://')) {
|
|
33
|
+
throw new Error(`Unsupported scheme: http://. Plaintext tarball fetch is rejected; use https://.`);
|
|
34
|
+
}
|
|
35
|
+
// Future schemes — surface them by name so the error tells operators what
|
|
36
|
+
// we know about, not just "unknown".
|
|
37
|
+
const knownFutureSchemes = ['s3://', 'gs://', 'azure://', 'gcs://', 'r2://'];
|
|
38
|
+
for (const scheme of knownFutureSchemes) {
|
|
39
|
+
if (uri.startsWith(scheme)) {
|
|
40
|
+
throw new Error(`Scheme ${scheme} is reserved for a future implementation and not supported ` +
|
|
41
|
+
`in v1 of FileSystemSource.`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
throw new Error(`Unsupported FileSystemSource URI: ${uri}. ` +
|
|
45
|
+
`Expected git+https://…, https://…tar.gz, or file:///…`);
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../src/sources/resolver.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChD,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;IAC7E,CAAC;IAED,wDAAwD;IACxD,IAAI,GAAG,CAAC,UAAU,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7D,MAAM,IAAI,KAAK,CACb,uBAAuB,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,uCAAuC;YAC/E,gFAAgF,CACnF,CAAC;IACJ,CAAC;IAED,uDAAuD;IACvD,IAAI,GAAG,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CACb,qFAAqF,CACtF,CAAC;IACJ,CAAC;IAED,IAAI,GAAG,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;QACnC,OAAO,IAAI,aAAa,CAAC,GAAG,CAAC,CAAC;IAChC,CAAC;IAED,IAAI,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC9B,OAAO,IAAI,eAAe,CAAC,GAAG,CAAC,CAAC;IAClC,CAAC;IAED,IAAI,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,iEAAiE;QACjE,MAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC;QACzD,IAAI,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YAC9D,OAAO,IAAI,iBAAiB,CAAC,GAAG,CAAC,CAAC;QACpC,CAAC;QACD,MAAM,IAAI,KAAK,CACb,0BAA0B,GAAG,4CAA4C;YACvE,qCAAqC,CACxC,CAAC;IACJ,CAAC;IAED,IAAI,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CACb,iFAAiF,CAClF,CAAC;IACJ,CAAC;IAED,0EAA0E;IAC1E,qCAAqC;IACrC,MAAM,kBAAkB,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC7E,KAAK,MAAM,MAAM,IAAI,kBAAkB,EAAE,CAAC;QACxC,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CACb,UAAU,MAAM,6DAA6D;gBAC3E,4BAA4B,CAC/B,CAAC;QACJ,CAAC;IACH,CAAC;IAED,MAAM,IAAI,KAAK,CACb,qCAAqC,GAAG,IAAI;QAC1C,uDAAuD,CAC1D,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Snapshot } from '../file-source.js';
|
|
2
|
+
export interface DirectorySnapshotOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Predicate run against each POSIX-style relative path during walk and
|
|
5
|
+
* read. Returning `true` excludes the path. Used to hide internal dirs
|
|
6
|
+
* (`.git/` for git sources, `.lobu-cache/` for local sources rooted at
|
|
7
|
+
* the workspace).
|
|
8
|
+
*/
|
|
9
|
+
exclude?: (relativePath: string) => boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare class DirectorySnapshot implements Snapshot {
|
|
12
|
+
#private;
|
|
13
|
+
readonly ref: string;
|
|
14
|
+
constructor(rootDir: string, ref: string, options?: DirectorySnapshotOptions);
|
|
15
|
+
walkFiles(glob: string): AsyncIterable<string>;
|
|
16
|
+
readFile(relativePath: string): Promise<Buffer>;
|
|
17
|
+
readText(relativePath: string): Promise<string>;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=snapshot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot.d.ts","sourceRoot":"","sources":["../../src/sources/snapshot.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAGlD,MAAM,WAAW,wBAAwB;IACvC;;;;;OAKG;IACH,OAAO,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC;CAC7C;AAED,qBAAa,iBAAkB,YAAW,QAAQ;;IAChD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;gBAMT,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,wBAA6B;IAUzE,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC;IAO/C,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAI/C,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CA6CtD"}
|