@infinite-room-labs/claudesync-core 0.4.0 → 0.5.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/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/sync/__tests__/files-mode.test.d.ts +2 -0
- package/dist/sync/__tests__/files-mode.test.d.ts.map +1 -0
- package/dist/sync/__tests__/files-mode.test.js +156 -0
- package/dist/sync/__tests__/files-mode.test.js.map +1 -0
- package/dist/sync/fetch.d.ts +34 -0
- package/dist/sync/fetch.d.ts.map +1 -0
- package/dist/sync/fetch.js +55 -0
- package/dist/sync/fetch.js.map +1 -0
- package/dist/sync/files-mode.d.ts +47 -0
- package/dist/sync/files-mode.d.ts.map +1 -0
- package/dist/sync/files-mode.js +94 -0
- package/dist/sync/files-mode.js.map +1 -0
- package/dist/sync/incremental.d.ts +10 -0
- package/dist/sync/incremental.d.ts.map +1 -1
- package/dist/sync/incremental.js +34 -84
- package/dist/sync/incremental.js.map +1 -1
- package/dist/util/__tests__/glob.test.d.ts +2 -0
- package/dist/util/__tests__/glob.test.d.ts.map +1 -0
- package/dist/util/__tests__/glob.test.js +57 -0
- package/dist/util/__tests__/glob.test.js.map +1 -0
- package/dist/util/glob.d.ts +24 -0
- package/dist/util/glob.d.ts.map +1 -0
- package/dist/util/glob.js +94 -0
- package/dist/util/glob.js.map +1 -0
- package/dist/util/naming.d.ts +19 -0
- package/dist/util/naming.d.ts.map +1 -0
- package/dist/util/naming.js +30 -0
- package/dist/util/naming.js.map +1 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -22,4 +22,10 @@ export { diffConversation } from "./sync/diff.js";
|
|
|
22
22
|
export { CHANGELOG_FILENAME, renderChangelogSection, appendChangelog, } from "./sync/changelog.js";
|
|
23
23
|
export type { ExportFormat, SyncConversationOptions, SyncConversationResult, } from "./sync/incremental.js";
|
|
24
24
|
export { syncConversation, isSameByListMetadata, } from "./sync/incremental.js";
|
|
25
|
+
export type { FetchAndBuildOptions, FetchAndBuildResult, } from "./sync/fetch.js";
|
|
26
|
+
export { fetchAndBuild } from "./sync/fetch.js";
|
|
27
|
+
export type { ReplaceWithPreserveOptions } from "./sync/files-mode.js";
|
|
28
|
+
export { replaceWithPreserve, walkRelative } from "./sync/files-mode.js";
|
|
29
|
+
export { slugify, safeSlug, displayName } from "./util/naming.js";
|
|
30
|
+
export { matchGlob, matchAnyGlob, compileGlob } from "./util/glob.js";
|
|
25
31
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAG7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACrE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAG5D,OAAO,EACL,kBAAkB,EAClB,0BAA0B,EAC1B,gBAAgB,EAChB,iBAAiB,EACjB,yBAAyB,EACzB,kBAAkB,EAClB,iBAAiB,EACjB,oBAAoB,EACpB,0BAA0B,EAC1B,0BAA0B,EAC1B,aAAa,EACb,gBAAgB,GACjB,MAAM,qBAAqB,CAAC;AAG7B,YAAY,EACV,YAAY,EACZ,oBAAoB,EACpB,UAAU,EACV,WAAW,EACX,mBAAmB,EACnB,YAAY,EACZ,WAAW,EACX,cAAc,EACd,oBAAoB,EACpB,oBAAoB,EACpB,OAAO,EACP,UAAU,GACX,MAAM,mBAAmB,CAAC;AAG3B,YAAY,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,mBAAmB,EACnB,cAAc,GACf,MAAM,wBAAwB,CAAC;AAGhC,YAAY,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpE,YAAY,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAGxE,YAAY,EACV,SAAS,EACT,aAAa,EACb,iBAAiB,GAClB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,cAAc,EACd,eAAe,EACf,aAAa,EACb,cAAc,GACf,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACV,gBAAgB,EAChB,UAAU,EACV,YAAY,EACZ,YAAY,GACb,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EACL,kBAAkB,EAClB,sBAAsB,EACtB,eAAe,GAChB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EACV,YAAY,EACZ,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAG7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACrE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAG5D,OAAO,EACL,kBAAkB,EAClB,0BAA0B,EAC1B,gBAAgB,EAChB,iBAAiB,EACjB,yBAAyB,EACzB,kBAAkB,EAClB,iBAAiB,EACjB,oBAAoB,EACpB,0BAA0B,EAC1B,0BAA0B,EAC1B,aAAa,EACb,gBAAgB,GACjB,MAAM,qBAAqB,CAAC;AAG7B,YAAY,EACV,YAAY,EACZ,oBAAoB,EACpB,UAAU,EACV,WAAW,EACX,mBAAmB,EACnB,YAAY,EACZ,WAAW,EACX,cAAc,EACd,oBAAoB,EACpB,oBAAoB,EACpB,OAAO,EACP,UAAU,GACX,MAAM,mBAAmB,CAAC;AAG3B,YAAY,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,mBAAmB,EACnB,cAAc,GACf,MAAM,wBAAwB,CAAC;AAGhC,YAAY,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpE,YAAY,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAGxE,YAAY,EACV,SAAS,EACT,aAAa,EACb,iBAAiB,GAClB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,cAAc,EACd,eAAe,EACf,aAAa,EACb,cAAc,GACf,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACV,gBAAgB,EAChB,UAAU,EACV,YAAY,EACZ,YAAY,GACb,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EACL,kBAAkB,EAClB,sBAAsB,EACtB,eAAe,GAChB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EACV,YAAY,EACZ,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EACV,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,YAAY,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AACvE,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAGzE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAGlE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -15,4 +15,10 @@ export { STATE_FILENAME, SyncStateSchema, readSyncState, writeSyncState, } from
|
|
|
15
15
|
export { diffConversation } from "./sync/diff.js";
|
|
16
16
|
export { CHANGELOG_FILENAME, renderChangelogSection, appendChangelog, } from "./sync/changelog.js";
|
|
17
17
|
export { syncConversation, isSameByListMetadata, } from "./sync/incremental.js";
|
|
18
|
+
export { fetchAndBuild } from "./sync/fetch.js";
|
|
19
|
+
export { replaceWithPreserve, walkRelative } from "./sync/files-mode.js";
|
|
20
|
+
// Naming helpers
|
|
21
|
+
export { slugify, safeSlug, displayName } from "./util/naming.js";
|
|
22
|
+
// Glob helpers
|
|
23
|
+
export { matchGlob, matchAnyGlob, compileGlob } from "./util/glob.js";
|
|
18
24
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,SAAS;AACT,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACrE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAE5D,oBAAoB;AACpB,OAAO,EACL,kBAAkB,EAClB,0BAA0B,EAC1B,gBAAgB,EAChB,iBAAiB,EACjB,yBAAyB,EACzB,kBAAkB,EAClB,iBAAiB,EACjB,oBAAoB,EACpB,0BAA0B,EAC1B,0BAA0B,EAC1B,aAAa,EACb,gBAAgB,GACjB,MAAM,qBAAqB,CAAC;AAoB7B,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,mBAAmB,EACnB,cAAc,GACf,MAAM,wBAAwB,CAAC;AAKhC,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAQxE,OAAO,EACL,cAAc,EACd,eAAe,EACf,aAAa,EACb,cAAc,GACf,MAAM,iBAAiB,CAAC;AAOzB,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EACL,kBAAkB,EAClB,sBAAsB,EACtB,eAAe,GAChB,MAAM,qBAAqB,CAAC;AAM7B,OAAO,EACL,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,SAAS;AACT,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACrE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAE5D,oBAAoB;AACpB,OAAO,EACL,kBAAkB,EAClB,0BAA0B,EAC1B,gBAAgB,EAChB,iBAAiB,EACjB,yBAAyB,EACzB,kBAAkB,EAClB,iBAAiB,EACjB,oBAAoB,EACpB,0BAA0B,EAC1B,0BAA0B,EAC1B,aAAa,EACb,gBAAgB,GACjB,MAAM,qBAAqB,CAAC;AAoB7B,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,mBAAmB,EACnB,cAAc,GACf,MAAM,wBAAwB,CAAC;AAKhC,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAQxE,OAAO,EACL,cAAc,EACd,eAAe,EACf,aAAa,EACb,cAAc,GACf,MAAM,iBAAiB,CAAC;AAOzB,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EACL,kBAAkB,EAClB,sBAAsB,EACtB,eAAe,GAChB,MAAM,qBAAqB,CAAC;AAM7B,OAAO,EACL,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,uBAAuB,CAAC;AAK/B,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzE,iBAAiB;AACjB,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAElE,eAAe;AACf,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"files-mode.test.d.ts","sourceRoot":"","sources":["../../../src/sync/__tests__/files-mode.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { describe, expect, it, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import { mkdtempSync, rmSync, writeFileSync, existsSync, readFileSync, mkdirSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { replaceWithPreserve, walkRelative } from "../files-mode.js";
|
|
6
|
+
let workdir;
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
workdir = mkdtempSync(join(tmpdir(), "claudesync-files-mode-"));
|
|
9
|
+
});
|
|
10
|
+
afterEach(() => {
|
|
11
|
+
rmSync(workdir, { recursive: true, force: true });
|
|
12
|
+
});
|
|
13
|
+
function writeFile(p, content) {
|
|
14
|
+
mkdirSync(join(workdir, p, ".."), { recursive: true });
|
|
15
|
+
writeFileSync(join(workdir, p), content, "utf-8");
|
|
16
|
+
}
|
|
17
|
+
describe("replaceWithPreserve", () => {
|
|
18
|
+
it("creates outputPath on first run (no stash to merge from)", async () => {
|
|
19
|
+
const outputPath = join(workdir, "convo");
|
|
20
|
+
await replaceWithPreserve({
|
|
21
|
+
outputPath,
|
|
22
|
+
writeFresh: async () => {
|
|
23
|
+
mkdirSync(outputPath, { recursive: true });
|
|
24
|
+
writeFileSync(join(outputPath, "conversation.md"), "fresh body", "utf-8");
|
|
25
|
+
},
|
|
26
|
+
alwaysPreserve: ["CHANGELOG.md"],
|
|
27
|
+
preserveGlobs: ["INDEX.md"],
|
|
28
|
+
});
|
|
29
|
+
expect(readFileSync(join(outputPath, "conversation.md"), "utf-8")).toBe("fresh body");
|
|
30
|
+
});
|
|
31
|
+
it("preserves alwaysPreserve files across re-sync", async () => {
|
|
32
|
+
const outputPath = join(workdir, "convo");
|
|
33
|
+
// Initial state.
|
|
34
|
+
mkdirSync(outputPath, { recursive: true });
|
|
35
|
+
writeFileSync(join(outputPath, "conversation.md"), "v1 body", "utf-8");
|
|
36
|
+
writeFileSync(join(outputPath, "CHANGELOG.md"), "## changelog v1\n", "utf-8");
|
|
37
|
+
// Re-sync rewrites the dir.
|
|
38
|
+
await replaceWithPreserve({
|
|
39
|
+
outputPath,
|
|
40
|
+
writeFresh: async () => {
|
|
41
|
+
mkdirSync(outputPath, { recursive: true });
|
|
42
|
+
writeFileSync(join(outputPath, "conversation.md"), "v2 body", "utf-8");
|
|
43
|
+
},
|
|
44
|
+
alwaysPreserve: ["CHANGELOG.md"],
|
|
45
|
+
});
|
|
46
|
+
expect(readFileSync(join(outputPath, "conversation.md"), "utf-8")).toBe("v2 body");
|
|
47
|
+
expect(readFileSync(join(outputPath, "CHANGELOG.md"), "utf-8")).toBe("## changelog v1\n");
|
|
48
|
+
});
|
|
49
|
+
it("preserves files matching preserveGlobs", async () => {
|
|
50
|
+
const outputPath = join(workdir, "convo");
|
|
51
|
+
mkdirSync(outputPath, { recursive: true });
|
|
52
|
+
writeFileSync(join(outputPath, "INDEX.md"), "indexer output\n", "utf-8");
|
|
53
|
+
writeFileSync(join(outputPath, "conversation.md"), "v1", "utf-8");
|
|
54
|
+
await replaceWithPreserve({
|
|
55
|
+
outputPath,
|
|
56
|
+
writeFresh: async () => {
|
|
57
|
+
mkdirSync(outputPath, { recursive: true });
|
|
58
|
+
writeFileSync(join(outputPath, "conversation.md"), "v2", "utf-8");
|
|
59
|
+
},
|
|
60
|
+
preserveGlobs: ["INDEX.md"],
|
|
61
|
+
});
|
|
62
|
+
expect(readFileSync(join(outputPath, "INDEX.md"), "utf-8")).toBe("indexer output\n");
|
|
63
|
+
expect(readFileSync(join(outputPath, "conversation.md"), "utf-8")).toBe("v2");
|
|
64
|
+
});
|
|
65
|
+
it("drops files matching alwaysDrop even if they match preserveGlobs", async () => {
|
|
66
|
+
const outputPath = join(workdir, "convo");
|
|
67
|
+
mkdirSync(outputPath, { recursive: true });
|
|
68
|
+
writeFileSync(join(outputPath, ".claudesync-state.json"), "{\"old\":true}", "utf-8");
|
|
69
|
+
writeFileSync(join(outputPath, "conversation.md"), "v1", "utf-8");
|
|
70
|
+
await replaceWithPreserve({
|
|
71
|
+
outputPath,
|
|
72
|
+
writeFresh: async () => {
|
|
73
|
+
mkdirSync(outputPath, { recursive: true });
|
|
74
|
+
writeFileSync(join(outputPath, "conversation.md"), "v2", "utf-8");
|
|
75
|
+
},
|
|
76
|
+
alwaysDrop: [".claudesync-state.json"],
|
|
77
|
+
preserveGlobs: ["**"], // even with greedy preserve, alwaysDrop wins
|
|
78
|
+
});
|
|
79
|
+
expect(existsSync(join(outputPath, ".claudesync-state.json"))).toBe(false);
|
|
80
|
+
});
|
|
81
|
+
it("preserves nested files matching ** globs", async () => {
|
|
82
|
+
const outputPath = join(workdir, "project");
|
|
83
|
+
mkdirSync(join(outputPath, "conversations/foo"), { recursive: true });
|
|
84
|
+
writeFileSync(join(outputPath, "conversations/foo/INDEX.md"), "nested index\n", "utf-8");
|
|
85
|
+
writeFileSync(join(outputPath, "README.md"), "v1", "utf-8");
|
|
86
|
+
await replaceWithPreserve({
|
|
87
|
+
outputPath,
|
|
88
|
+
writeFresh: async () => {
|
|
89
|
+
mkdirSync(join(outputPath, "conversations/foo"), { recursive: true });
|
|
90
|
+
writeFileSync(join(outputPath, "README.md"), "v2", "utf-8");
|
|
91
|
+
writeFileSync(join(outputPath, "conversations/foo/conversation.md"), "v2", "utf-8");
|
|
92
|
+
},
|
|
93
|
+
preserveGlobs: ["**/INDEX.md"],
|
|
94
|
+
});
|
|
95
|
+
expect(readFileSync(join(outputPath, "conversations/foo/INDEX.md"), "utf-8")).toBe("nested index\n");
|
|
96
|
+
expect(readFileSync(join(outputPath, "README.md"), "utf-8")).toBe("v2");
|
|
97
|
+
});
|
|
98
|
+
it("does not clobber when the bundle wrote the same relative path", async () => {
|
|
99
|
+
const outputPath = join(workdir, "convo");
|
|
100
|
+
mkdirSync(outputPath, { recursive: true });
|
|
101
|
+
writeFileSync(join(outputPath, "conversation.md"), "stash version", "utf-8");
|
|
102
|
+
await replaceWithPreserve({
|
|
103
|
+
outputPath,
|
|
104
|
+
writeFresh: async () => {
|
|
105
|
+
mkdirSync(outputPath, { recursive: true });
|
|
106
|
+
writeFileSync(join(outputPath, "conversation.md"), "bundle version", "utf-8");
|
|
107
|
+
},
|
|
108
|
+
preserveGlobs: ["conversation.md"], // user mis-glob; bundle should win
|
|
109
|
+
});
|
|
110
|
+
expect(readFileSync(join(outputPath, "conversation.md"), "utf-8")).toBe("bundle version");
|
|
111
|
+
});
|
|
112
|
+
it("restores the stash on writeFresh failure", async () => {
|
|
113
|
+
const outputPath = join(workdir, "convo");
|
|
114
|
+
mkdirSync(outputPath, { recursive: true });
|
|
115
|
+
writeFileSync(join(outputPath, "conversation.md"), "original", "utf-8");
|
|
116
|
+
await expect(replaceWithPreserve({
|
|
117
|
+
outputPath,
|
|
118
|
+
writeFresh: async () => {
|
|
119
|
+
throw new Error("boom");
|
|
120
|
+
},
|
|
121
|
+
})).rejects.toThrow("boom");
|
|
122
|
+
expect(readFileSync(join(outputPath, "conversation.md"), "utf-8")).toBe("original");
|
|
123
|
+
expect(existsSync(outputPath + ".prev")).toBe(false);
|
|
124
|
+
});
|
|
125
|
+
it("removes stale stash directory before renaming", async () => {
|
|
126
|
+
const outputPath = join(workdir, "convo");
|
|
127
|
+
mkdirSync(outputPath, { recursive: true });
|
|
128
|
+
writeFileSync(join(outputPath, "conversation.md"), "v1", "utf-8");
|
|
129
|
+
// Pre-existing stash from a previously-crashed run.
|
|
130
|
+
const staleStash = outputPath + ".prev";
|
|
131
|
+
mkdirSync(staleStash, { recursive: true });
|
|
132
|
+
writeFileSync(join(staleStash, "junk.md"), "leftover", "utf-8");
|
|
133
|
+
await replaceWithPreserve({
|
|
134
|
+
outputPath,
|
|
135
|
+
writeFresh: async () => {
|
|
136
|
+
mkdirSync(outputPath, { recursive: true });
|
|
137
|
+
writeFileSync(join(outputPath, "conversation.md"), "v2", "utf-8");
|
|
138
|
+
},
|
|
139
|
+
});
|
|
140
|
+
expect(readFileSync(join(outputPath, "conversation.md"), "utf-8")).toBe("v2");
|
|
141
|
+
expect(existsSync(staleStash)).toBe(false);
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
describe("walkRelative", () => {
|
|
145
|
+
it("yields all file paths with POSIX separators", () => {
|
|
146
|
+
writeFile("a.md", "1");
|
|
147
|
+
writeFile("nested/b.md", "2");
|
|
148
|
+
writeFile("nested/deep/c.md", "3");
|
|
149
|
+
const paths = [...walkRelative(workdir)].sort();
|
|
150
|
+
expect(paths).toEqual(["a.md", "nested/b.md", "nested/deep/c.md"]);
|
|
151
|
+
});
|
|
152
|
+
it("returns empty for nonexistent root", () => {
|
|
153
|
+
expect([...walkRelative(join(workdir, "missing"))]).toEqual([]);
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
//# sourceMappingURL=files-mode.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"files-mode.test.js","sourceRoot":"","sources":["../../../src/sync/__tests__/files-mode.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { ClaudeSyncClient } from "../client/client.js";
|
|
2
|
+
import type { ArtifactListResponse, Conversation, ConversationSummary } from "../models/types.js";
|
|
3
|
+
import type { GitBundle } from "../export/types.js";
|
|
4
|
+
export interface FetchAndBuildOptions {
|
|
5
|
+
authorName: string;
|
|
6
|
+
authorEmail: string;
|
|
7
|
+
/** Don't fetch artifacts (faster). */
|
|
8
|
+
skipArtifacts?: boolean;
|
|
9
|
+
/** Pass-through to buildGitBundle. Default true so all sync paths preserve
|
|
10
|
+
* branches uniformly. */
|
|
11
|
+
multiBranch?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface FetchAndBuildResult {
|
|
14
|
+
conversation: Conversation;
|
|
15
|
+
artifacts: ArtifactListResponse;
|
|
16
|
+
artifactContents: Map<string, string | Uint8Array>;
|
|
17
|
+
bundle: GitBundle;
|
|
18
|
+
/** Human-readable label for log lines. Falls back to `<unnamed <uuid>>`. */
|
|
19
|
+
displayName: string;
|
|
20
|
+
/** Filesystem-safe slug. Falls back to `unnamed-<uuid>`. */
|
|
21
|
+
slug: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Single source of truth for "fetch a conversation, fetch its artifacts, and
|
|
25
|
+
* build the bundle". Both the standalone-conversation orchestrator and the
|
|
26
|
+
* project-export loop go through this so name/slug fallbacks, tree fetching,
|
|
27
|
+
* and artifact handling stay consistent.
|
|
28
|
+
*
|
|
29
|
+
* This function does no I/O against the local filesystem -- it is a pure
|
|
30
|
+
* fetch+build. Persistence (state file, changelog, swap, ref management) is
|
|
31
|
+
* the caller's job.
|
|
32
|
+
*/
|
|
33
|
+
export declare function fetchAndBuild(client: ClaudeSyncClient, orgId: string, summary: ConversationSummary, options: FetchAndBuildOptions): Promise<FetchAndBuildResult>;
|
|
34
|
+
//# sourceMappingURL=fetch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/sync/fetch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,KAAK,EACV,oBAAoB,EACpB,YAAY,EACZ,mBAAmB,EACpB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAGpD,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,sCAAsC;IACtC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;8BAC0B;IAC1B,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,mBAAmB;IAClC,YAAY,EAAE,YAAY,CAAC;IAC3B,SAAS,EAAE,oBAAoB,CAAC;IAChC,gBAAgB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAAC,CAAC;IACnD,MAAM,EAAE,SAAS,CAAC;IAClB,4EAA4E;IAC5E,WAAW,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;GASG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,gBAAgB,EACxB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,mBAAmB,EAC5B,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,mBAAmB,CAAC,CA+C9B"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { buildGitBundle } from "../export/bundle-builder.js";
|
|
2
|
+
import { safeSlug, displayName } from "../util/naming.js";
|
|
3
|
+
/**
|
|
4
|
+
* Single source of truth for "fetch a conversation, fetch its artifacts, and
|
|
5
|
+
* build the bundle". Both the standalone-conversation orchestrator and the
|
|
6
|
+
* project-export loop go through this so name/slug fallbacks, tree fetching,
|
|
7
|
+
* and artifact handling stay consistent.
|
|
8
|
+
*
|
|
9
|
+
* This function does no I/O against the local filesystem -- it is a pure
|
|
10
|
+
* fetch+build. Persistence (state file, changelog, swap, ref management) is
|
|
11
|
+
* the caller's job.
|
|
12
|
+
*/
|
|
13
|
+
export async function fetchAndBuild(client, orgId, summary, options) {
|
|
14
|
+
const conversation = await client.getConversation(orgId, summary.uuid, {
|
|
15
|
+
tree: true,
|
|
16
|
+
});
|
|
17
|
+
const empty = {
|
|
18
|
+
success: true,
|
|
19
|
+
files: [],
|
|
20
|
+
files_metadata: [],
|
|
21
|
+
};
|
|
22
|
+
let artifacts = empty;
|
|
23
|
+
const artifactContents = new Map();
|
|
24
|
+
if (!options.skipArtifacts) {
|
|
25
|
+
try {
|
|
26
|
+
artifacts = await client.listArtifacts(orgId, summary.uuid);
|
|
27
|
+
for (const meta of artifacts.files_metadata) {
|
|
28
|
+
try {
|
|
29
|
+
const content = await client.downloadArtifact(orgId, summary.uuid, meta.path);
|
|
30
|
+
artifactContents.set(meta.path, content);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
// Per-artifact failure is non-fatal: keep going with what we have.
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
// Some conversations don't support the wiggle filesystem at all.
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const bundle = buildGitBundle(conversation, artifacts, artifactContents, {
|
|
42
|
+
authorName: options.authorName,
|
|
43
|
+
authorEmail: options.authorEmail,
|
|
44
|
+
multiBranch: options.multiBranch ?? true,
|
|
45
|
+
});
|
|
46
|
+
return {
|
|
47
|
+
conversation,
|
|
48
|
+
artifacts,
|
|
49
|
+
artifactContents,
|
|
50
|
+
bundle,
|
|
51
|
+
displayName: displayName(summary.name, summary.uuid),
|
|
52
|
+
slug: safeSlug(summary.name, summary.uuid),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=fetch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch.js","sourceRoot":"","sources":["../../src/sync/fetch.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAE7D,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAuB1D;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,MAAwB,EACxB,KAAa,EACb,OAA4B,EAC5B,OAA6B;IAE7B,MAAM,YAAY,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,EAAE;QACrE,IAAI,EAAE,IAAI;KACX,CAAC,CAAC;IAEH,MAAM,KAAK,GAAyB;QAClC,OAAO,EAAE,IAAI;QACb,KAAK,EAAE,EAAE;QACT,cAAc,EAAE,EAAE;KACnB,CAAC;IACF,IAAI,SAAS,GAAyB,KAAK,CAAC;IAC5C,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAA+B,CAAC;IAEhE,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;QAC3B,IAAI,CAAC;YACH,SAAS,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;YAC5D,KAAK,MAAM,IAAI,IAAI,SAAS,CAAC,cAAc,EAAE,CAAC;gBAC5C,IAAI,CAAC;oBACH,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAC3C,KAAK,EACL,OAAO,CAAC,IAAI,EACZ,IAAI,CAAC,IAAI,CACV,CAAC;oBACF,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;gBAC3C,CAAC;gBAAC,MAAM,CAAC;oBACP,mEAAmE;gBACrE,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,iEAAiE;QACnE,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,cAAc,CAAC,YAAY,EAAE,SAAS,EAAE,gBAAgB,EAAE;QACvE,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,IAAI;KACzC,CAAC,CAAC;IAEH,OAAO;QACL,YAAY;QACZ,SAAS;QACT,gBAAgB;QAChB,MAAM;QACN,WAAW,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC;QACpD,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC;KAC3C,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stash-and-rebuild file-writing primitive shared between conversation and
|
|
3
|
+
* project export paths.
|
|
4
|
+
*
|
|
5
|
+
* Both code paths produce a fresh, claudesync-canonical directory tree on
|
|
6
|
+
* every re-sync. Without explicit rescue, anything the user added locally
|
|
7
|
+
* (INDEX.md from a downstream indexer, hand-written notes, etc.) would be
|
|
8
|
+
* wiped on every run.
|
|
9
|
+
*
|
|
10
|
+
* This helper:
|
|
11
|
+
* 1. Renames the existing outputPath to a `<outputPath>.prev` stash.
|
|
12
|
+
* 2. Runs the caller-supplied `writeFresh` to populate a clean outputPath.
|
|
13
|
+
* 3. Walks the stash and copies back files that either equal an entry in
|
|
14
|
+
* `alwaysPreserve` or match any glob in `preserveGlobs`.
|
|
15
|
+
* 4. Removes the stash on success, restores it on failure.
|
|
16
|
+
*
|
|
17
|
+
* Copies are non-destructive: if writeFresh already produced a file at the
|
|
18
|
+
* same relative path, the bundle wins and the stash copy is skipped. This
|
|
19
|
+
* protects against a user pattern accidentally clobbering conversation.md
|
|
20
|
+
* or README.md.
|
|
21
|
+
*/
|
|
22
|
+
export interface ReplaceWithPreserveOptions {
|
|
23
|
+
/** Final destination directory. May or may not exist. */
|
|
24
|
+
outputPath: string;
|
|
25
|
+
/** Callback that populates `outputPath` from scratch. Must create the dir. */
|
|
26
|
+
writeFresh: () => Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
* Files preserved by exact relative-path match. CHANGELOG.md is the
|
|
29
|
+
* canonical example; the changelog is appended to by the sync.
|
|
30
|
+
*/
|
|
31
|
+
alwaysPreserve?: readonly string[];
|
|
32
|
+
/**
|
|
33
|
+
* Files dropped by exact relative-path match, even if they would otherwise
|
|
34
|
+
* match `preserveGlobs`. `.claudesync-state.json` is the canonical example;
|
|
35
|
+
* the caller rewrites it after this returns.
|
|
36
|
+
*/
|
|
37
|
+
alwaysDrop?: readonly string[];
|
|
38
|
+
/**
|
|
39
|
+
* Glob patterns (POSIX) of locally-added files to preserve. Matched against
|
|
40
|
+
* paths relative to `outputPath`. See `util/glob.ts` for syntax.
|
|
41
|
+
*/
|
|
42
|
+
preserveGlobs?: readonly string[];
|
|
43
|
+
}
|
|
44
|
+
export declare function replaceWithPreserve(opts: ReplaceWithPreserveOptions): Promise<void>;
|
|
45
|
+
/** Yield every file path under root, as POSIX-separated paths relative to root. */
|
|
46
|
+
export declare function walkRelative(root: string): Generator<string>;
|
|
47
|
+
//# sourceMappingURL=files-mode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"files-mode.d.ts","sourceRoot":"","sources":["../../src/sync/files-mode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAMH,MAAM,WAAW,0BAA0B;IACzC,yDAAyD;IACzD,UAAU,EAAE,MAAM,CAAC;IACnB,8EAA8E;IAC9E,UAAU,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAChC;;;OAGG;IACH,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC;;;;OAIG;IACH,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B;;;OAGG;IACH,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAED,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,0BAA0B,GAC/B,OAAO,CAAC,IAAI,CAAC,CAmCf;AAyBD,mFAAmF;AACnF,wBAAiB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,CAoB7D"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stash-and-rebuild file-writing primitive shared between conversation and
|
|
3
|
+
* project export paths.
|
|
4
|
+
*
|
|
5
|
+
* Both code paths produce a fresh, claudesync-canonical directory tree on
|
|
6
|
+
* every re-sync. Without explicit rescue, anything the user added locally
|
|
7
|
+
* (INDEX.md from a downstream indexer, hand-written notes, etc.) would be
|
|
8
|
+
* wiped on every run.
|
|
9
|
+
*
|
|
10
|
+
* This helper:
|
|
11
|
+
* 1. Renames the existing outputPath to a `<outputPath>.prev` stash.
|
|
12
|
+
* 2. Runs the caller-supplied `writeFresh` to populate a clean outputPath.
|
|
13
|
+
* 3. Walks the stash and copies back files that either equal an entry in
|
|
14
|
+
* `alwaysPreserve` or match any glob in `preserveGlobs`.
|
|
15
|
+
* 4. Removes the stash on success, restores it on failure.
|
|
16
|
+
*
|
|
17
|
+
* Copies are non-destructive: if writeFresh already produced a file at the
|
|
18
|
+
* same relative path, the bundle wins and the stash copy is skipped. This
|
|
19
|
+
* protects against a user pattern accidentally clobbering conversation.md
|
|
20
|
+
* or README.md.
|
|
21
|
+
*/
|
|
22
|
+
import fs from "node:fs";
|
|
23
|
+
import path from "node:path";
|
|
24
|
+
import { matchAnyGlob } from "../util/glob.js";
|
|
25
|
+
export async function replaceWithPreserve(opts) {
|
|
26
|
+
const { outputPath, writeFresh, alwaysPreserve = [], alwaysDrop = [], preserveGlobs = [], } = opts;
|
|
27
|
+
const stash = outputPath + ".prev";
|
|
28
|
+
const isUpdate = fs.existsSync(outputPath);
|
|
29
|
+
if (isUpdate) {
|
|
30
|
+
if (fs.existsSync(stash)) {
|
|
31
|
+
fs.rmSync(stash, { recursive: true, force: true });
|
|
32
|
+
}
|
|
33
|
+
fs.renameSync(outputPath, stash);
|
|
34
|
+
}
|
|
35
|
+
try {
|
|
36
|
+
await writeFresh();
|
|
37
|
+
if (isUpdate) {
|
|
38
|
+
restoreFromStash(stash, outputPath, alwaysPreserve, alwaysDrop, preserveGlobs);
|
|
39
|
+
fs.rmSync(stash, { recursive: true, force: true });
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
if (isUpdate) {
|
|
44
|
+
if (fs.existsSync(outputPath)) {
|
|
45
|
+
fs.rmSync(outputPath, { recursive: true, force: true });
|
|
46
|
+
}
|
|
47
|
+
if (fs.existsSync(stash)) {
|
|
48
|
+
fs.renameSync(stash, outputPath);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
throw error;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function restoreFromStash(stash, outputPath, alwaysPreserve, alwaysDrop, preserveGlobs) {
|
|
55
|
+
const dropSet = new Set(alwaysDrop);
|
|
56
|
+
const preserveSet = new Set(alwaysPreserve);
|
|
57
|
+
for (const rel of walkRelative(stash)) {
|
|
58
|
+
if (dropSet.has(rel))
|
|
59
|
+
continue;
|
|
60
|
+
const shouldPreserve = preserveSet.has(rel) || matchAnyGlob(rel, preserveGlobs);
|
|
61
|
+
if (!shouldPreserve)
|
|
62
|
+
continue;
|
|
63
|
+
const dest = path.join(outputPath, rel);
|
|
64
|
+
if (fs.existsSync(dest))
|
|
65
|
+
continue; // bundle wins
|
|
66
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
67
|
+
fs.copyFileSync(path.join(stash, rel), dest);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/** Yield every file path under root, as POSIX-separated paths relative to root. */
|
|
71
|
+
export function* walkRelative(root) {
|
|
72
|
+
const stack = [""];
|
|
73
|
+
while (stack.length > 0) {
|
|
74
|
+
const rel = stack.pop();
|
|
75
|
+
const abs = rel === "" ? root : path.join(root, rel);
|
|
76
|
+
let entries;
|
|
77
|
+
try {
|
|
78
|
+
entries = fs.readdirSync(abs, { withFileTypes: true });
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
for (const entry of entries) {
|
|
84
|
+
const childRel = rel === "" ? entry.name : `${rel}/${entry.name}`;
|
|
85
|
+
if (entry.isDirectory()) {
|
|
86
|
+
stack.push(childRel);
|
|
87
|
+
}
|
|
88
|
+
else if (entry.isFile() || entry.isSymbolicLink()) {
|
|
89
|
+
yield childRel;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=files-mode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"files-mode.js","sourceRoot":"","sources":["../../src/sync/files-mode.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,11 +12,21 @@ export interface SyncConversationOptions {
|
|
|
12
12
|
skipExisting?: boolean;
|
|
13
13
|
/** Don't fetch artifacts. */
|
|
14
14
|
skipArtifacts?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Glob patterns (POSIX-style) of locally-added files inside the
|
|
17
|
+
* conversation directory that must survive a re-sync in `files` mode.
|
|
18
|
+
* Matched against paths relative to the conversation directory. The
|
|
19
|
+
* CHANGELOG.md sidecar is always preserved regardless of this list.
|
|
20
|
+
* Examples: ["INDEX.md", "notes/**", "*.local.md"].
|
|
21
|
+
*/
|
|
22
|
+
preserve?: string[];
|
|
15
23
|
}
|
|
16
24
|
export interface SyncConversationResult {
|
|
17
25
|
action: "skipped" | "skipped-existing" | "full" | "incremental";
|
|
18
26
|
reason?: string;
|
|
19
27
|
changelogWritten: boolean;
|
|
28
|
+
/** Human-readable label (falls back to `<unnamed <uuid>>` for nameless conversations). */
|
|
29
|
+
displayName: string;
|
|
20
30
|
}
|
|
21
31
|
/**
|
|
22
32
|
* Cheap predicate for --skip-same. Returns true when the list-endpoint summary
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"incremental.d.ts","sourceRoot":"","sources":["../../src/sync/incremental.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,KAAK,EAGV,mBAAmB,EACpB,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"incremental.d.ts","sourceRoot":"","sources":["../../src/sync/incremental.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,KAAK,EAGV,mBAAmB,EACpB,MAAM,oBAAoB,CAAC;AAQ5B,OAAO,EAIL,KAAK,SAAS,EACf,MAAM,YAAY,CAAC;AAMpB,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,OAAO,GAAG,MAAM,CAAC;AAEpD,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,YAAY,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,oEAAoE;IACpE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,iEAAiE;IACjE,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,6BAA6B;IAC7B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,SAAS,GAAG,kBAAkB,GAAG,MAAM,GAAG,aAAa,CAAC;IAChE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,0FAA0F;IAC1F,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,IAAI,CAAC,mBAAmB,EAAE,YAAY,GAAG,2BAA2B,CAAC,EAC9E,SAAS,EAAE,SAAS,GAAG,SAAS,GAC/B,OAAO,CAMT;AAED;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,gBAAgB,EACxB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,mBAAmB,EAC5B,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,uBAAuB,GAC/B,OAAO,CAAC,sBAAsB,CAAC,CAmGjC"}
|
package/dist/sync/incremental.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { rmSync } from "node:fs";
|
|
4
|
-
import { buildGitBundle } from "../export/bundle-builder.js";
|
|
5
4
|
import { exportToGit, appendToGit } from "../export/git-exporter.js";
|
|
6
5
|
import { diffConversation } from "./diff.js";
|
|
7
6
|
import { appendChangelog, renderChangelogSection, CHANGELOG_FILENAME, } from "./changelog.js";
|
|
8
7
|
import { readSyncState, writeSyncState, STATE_FILENAME, } from "./state.js";
|
|
9
8
|
import { buildMessageTree, findLeafMessages } from "../tree/message-tree.js";
|
|
9
|
+
import { fetchAndBuild } from "./fetch.js";
|
|
10
|
+
import { displayName as toDisplayName } from "../util/naming.js";
|
|
11
|
+
import { replaceWithPreserve } from "./files-mode.js";
|
|
10
12
|
/**
|
|
11
13
|
* Cheap predicate for --skip-same. Returns true when the list-endpoint summary
|
|
12
14
|
* matches what the sidecar state file recorded on the previous sync. Caller
|
|
@@ -33,6 +35,8 @@ export async function syncConversation(client, orgId, summary, outputPath, optio
|
|
|
33
35
|
const stateDir = options.format === "json"
|
|
34
36
|
? path.dirname(outputPath)
|
|
35
37
|
: outputPath;
|
|
38
|
+
// Pre-compute display label so even early-return code paths can include it.
|
|
39
|
+
const prelimDisplayName = toDisplayName(summary.name, summary.uuid);
|
|
36
40
|
// --skip-existing: legacy, dumb existence check.
|
|
37
41
|
if (options.skipExisting) {
|
|
38
42
|
const target = options.format === "json" ? outputPath + ".json" : outputPath;
|
|
@@ -41,6 +45,7 @@ export async function syncConversation(client, orgId, summary, outputPath, optio
|
|
|
41
45
|
action: "skipped-existing",
|
|
42
46
|
reason: "output exists",
|
|
43
47
|
changelogWritten: false,
|
|
48
|
+
displayName: prelimDisplayName,
|
|
44
49
|
};
|
|
45
50
|
}
|
|
46
51
|
}
|
|
@@ -60,36 +65,29 @@ export async function syncConversation(client, orgId, summary, outputPath, optio
|
|
|
60
65
|
action: "skipped",
|
|
61
66
|
reason: "unchanged since last sync",
|
|
62
67
|
changelogWritten: false,
|
|
68
|
+
displayName: prelimDisplayName,
|
|
63
69
|
};
|
|
64
70
|
}
|
|
65
|
-
//
|
|
66
|
-
const
|
|
67
|
-
|
|
71
|
+
// Single source of truth for fetch + build.
|
|
72
|
+
const built = await fetchAndBuild(client, orgId, summary, {
|
|
73
|
+
authorName: options.authorName,
|
|
74
|
+
authorEmail: options.authorEmail,
|
|
75
|
+
skipArtifacts: options.skipArtifacts,
|
|
76
|
+
multiBranch: true,
|
|
68
77
|
});
|
|
69
|
-
const { artifacts,
|
|
78
|
+
const { conversation, artifacts, bundle } = built;
|
|
70
79
|
const diff = diffConversation(prevState, conversation, artifacts);
|
|
71
80
|
// For json mode: bundle is the full snapshot, written as a single JSON file.
|
|
72
81
|
if (options.format === "json") {
|
|
73
|
-
const bundle = buildGitBundle(conversation, artifacts, artifactContents, {
|
|
74
|
-
authorName: options.authorName,
|
|
75
|
-
authorEmail: options.authorEmail,
|
|
76
|
-
multiBranch: true,
|
|
77
|
-
});
|
|
78
82
|
fs.mkdirSync(path.dirname(outputPath), { recursive: true });
|
|
79
83
|
fs.writeFileSync(outputPath + ".json", JSON.stringify(bundle, null, 2), "utf-8");
|
|
80
|
-
// For json mode, write state file to the directory containing the json file.
|
|
81
84
|
writeStateFile(stateDir, summary, conversation, artifacts, prevState ? "incremental" : "full");
|
|
82
85
|
return {
|
|
83
86
|
action: prevState ? "incremental" : "full",
|
|
84
87
|
changelogWritten: false,
|
|
88
|
+
displayName: built.displayName,
|
|
85
89
|
};
|
|
86
90
|
}
|
|
87
|
-
// For files / git mode: build a multi-branch bundle.
|
|
88
|
-
const bundle = buildGitBundle(conversation, artifacts, artifactContents, {
|
|
89
|
-
authorName: options.authorName,
|
|
90
|
-
authorEmail: options.authorEmail,
|
|
91
|
-
multiBranch: true,
|
|
92
|
-
});
|
|
93
91
|
const isFresh = !fs.existsSync(outputPath);
|
|
94
92
|
if (options.format === "git") {
|
|
95
93
|
if (isFresh) {
|
|
@@ -100,10 +98,8 @@ export async function syncConversation(client, orgId, summary, outputPath, optio
|
|
|
100
98
|
}
|
|
101
99
|
}
|
|
102
100
|
else {
|
|
103
|
-
|
|
104
|
-
await writeFilesMode(bundle, outputPath);
|
|
101
|
+
await writeFilesMode(bundle, outputPath, options.preserve ?? []);
|
|
105
102
|
}
|
|
106
|
-
// After successful swap: write CHANGELOG, .gitignore (git only), state file.
|
|
107
103
|
let changelogWritten = false;
|
|
108
104
|
const section = renderChangelogSection(diff, new Date());
|
|
109
105
|
if (section) {
|
|
@@ -117,76 +113,30 @@ export async function syncConversation(client, orgId, summary, outputPath, optio
|
|
|
117
113
|
return {
|
|
118
114
|
action: prevState ? "incremental" : "full",
|
|
119
115
|
changelogWritten,
|
|
116
|
+
displayName: built.displayName,
|
|
120
117
|
};
|
|
121
118
|
}
|
|
122
|
-
async function fetchArtifacts(client, orgId, convId, enabled) {
|
|
123
|
-
const empty = {
|
|
124
|
-
success: true,
|
|
125
|
-
files: [],
|
|
126
|
-
files_metadata: [],
|
|
127
|
-
};
|
|
128
|
-
if (!enabled)
|
|
129
|
-
return { artifacts: empty, artifactContents: new Map() };
|
|
130
|
-
let artifacts = empty;
|
|
131
|
-
const artifactContents = new Map();
|
|
132
|
-
try {
|
|
133
|
-
artifacts = await client.listArtifacts(orgId, convId);
|
|
134
|
-
for (const meta of artifacts.files_metadata) {
|
|
135
|
-
try {
|
|
136
|
-
const content = await client.downloadArtifact(orgId, convId, meta.path);
|
|
137
|
-
artifactContents.set(meta.path, content);
|
|
138
|
-
}
|
|
139
|
-
catch {
|
|
140
|
-
// Skip failed artifact downloads.
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
catch {
|
|
145
|
-
// Some conversations don't support artifacts.
|
|
146
|
-
}
|
|
147
|
-
return { artifacts, artifactContents };
|
|
148
|
-
}
|
|
149
119
|
/**
|
|
150
120
|
* Files mode: replay bundle into outputPath via the same tmp+swap pattern as
|
|
151
121
|
* exportToGit, but strip .git at the end.
|
|
122
|
+
*
|
|
123
|
+
* Preservation: every re-sync rebuilds the directory from scratch. Files that
|
|
124
|
+
* the user (or a downstream tool) added locally would be wiped without
|
|
125
|
+
* explicit rescue. We always preserve `CHANGELOG.md` (appended to by the
|
|
126
|
+
* sync), drop the prior `.claudesync-state.json` (rewritten by the caller),
|
|
127
|
+
* and copy back anything else in the stash matching the `preserve` glob list.
|
|
152
128
|
*/
|
|
153
|
-
async function writeFilesMode(bundle, outputPath) {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
}
|
|
164
|
-
try {
|
|
165
|
-
await exportToGit(bundle, outputPath);
|
|
166
|
-
rmSync(path.join(outputPath, ".git"), { recursive: true, force: true });
|
|
167
|
-
// Preserve CHANGELOG.md from the previous tree (we'll append to it after).
|
|
168
|
-
if (isUpdate && fs.existsSync(path.join(stash, CHANGELOG_FILENAME))) {
|
|
169
|
-
fs.copyFileSync(path.join(stash, CHANGELOG_FILENAME), path.join(outputPath, CHANGELOG_FILENAME));
|
|
170
|
-
}
|
|
171
|
-
if (isUpdate && fs.existsSync(path.join(stash, STATE_FILENAME))) {
|
|
172
|
-
// State file gets rewritten by caller; nothing to preserve.
|
|
173
|
-
}
|
|
174
|
-
if (isUpdate) {
|
|
175
|
-
fs.rmSync(stash, { recursive: true, force: true });
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
catch (error) {
|
|
179
|
-
// Restore original on failure.
|
|
180
|
-
if (isUpdate) {
|
|
181
|
-
if (fs.existsSync(outputPath)) {
|
|
182
|
-
fs.rmSync(outputPath, { recursive: true, force: true });
|
|
183
|
-
}
|
|
184
|
-
if (fs.existsSync(stash)) {
|
|
185
|
-
fs.renameSync(stash, outputPath);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
throw error;
|
|
189
|
-
}
|
|
129
|
+
async function writeFilesMode(bundle, outputPath, preserve) {
|
|
130
|
+
await replaceWithPreserve({
|
|
131
|
+
outputPath,
|
|
132
|
+
writeFresh: async () => {
|
|
133
|
+
await exportToGit(bundle, outputPath);
|
|
134
|
+
rmSync(path.join(outputPath, ".git"), { recursive: true, force: true });
|
|
135
|
+
},
|
|
136
|
+
alwaysPreserve: [CHANGELOG_FILENAME],
|
|
137
|
+
alwaysDrop: [STATE_FILENAME],
|
|
138
|
+
preserveGlobs: preserve,
|
|
139
|
+
});
|
|
190
140
|
}
|
|
191
141
|
function ensureGitignore(repoDir) {
|
|
192
142
|
const gitignorePath = path.join(repoDir, ".gitignore");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"incremental.js","sourceRoot":"","sources":["../../src/sync/incremental.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAOjC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"incremental.js","sourceRoot":"","sources":["../../src/sync/incremental.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glob.test.d.ts","sourceRoot":"","sources":["../../../src/util/__tests__/glob.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { matchGlob, matchAnyGlob } from "../glob.js";
|
|
3
|
+
describe("matchGlob", () => {
|
|
4
|
+
it("matches literal filenames", () => {
|
|
5
|
+
expect(matchGlob("INDEX.md", "INDEX.md")).toBe(true);
|
|
6
|
+
expect(matchGlob("README.md", "INDEX.md")).toBe(false);
|
|
7
|
+
});
|
|
8
|
+
it("matches single * within a segment", () => {
|
|
9
|
+
expect(matchGlob("foo.md", "*.md")).toBe(true);
|
|
10
|
+
expect(matchGlob("foo.txt", "*.md")).toBe(false);
|
|
11
|
+
expect(matchGlob("notes/foo.md", "*.md")).toBe(false); // * does not cross /
|
|
12
|
+
});
|
|
13
|
+
it("matches ** across path segments", () => {
|
|
14
|
+
expect(matchGlob("notes/foo.md", "notes/**")).toBe(true);
|
|
15
|
+
expect(matchGlob("notes/nested/deep.md", "notes/**")).toBe(true);
|
|
16
|
+
expect(matchGlob("notes/", "notes/**")).toBe(true);
|
|
17
|
+
expect(matchGlob("other/foo.md", "notes/**")).toBe(false);
|
|
18
|
+
});
|
|
19
|
+
it("**/ collapses zero or more path segments", () => {
|
|
20
|
+
expect(matchGlob("INDEX.md", "**/INDEX.md")).toBe(true);
|
|
21
|
+
expect(matchGlob("a/INDEX.md", "**/INDEX.md")).toBe(true);
|
|
22
|
+
expect(matchGlob("a/b/c/INDEX.md", "**/INDEX.md")).toBe(true);
|
|
23
|
+
expect(matchGlob("INDEX.txt", "**/INDEX.md")).toBe(false);
|
|
24
|
+
});
|
|
25
|
+
it("? matches exactly one non-slash char", () => {
|
|
26
|
+
expect(matchGlob("foo.md", "fo?.md")).toBe(true);
|
|
27
|
+
expect(matchGlob("foo.md", "f??.md")).toBe(true);
|
|
28
|
+
expect(matchGlob("fo.md", "fo?.md")).toBe(false);
|
|
29
|
+
expect(matchGlob("fo/o.md", "fo?o.md")).toBe(false);
|
|
30
|
+
});
|
|
31
|
+
it("character classes work", () => {
|
|
32
|
+
expect(matchGlob("a.md", "[ab].md")).toBe(true);
|
|
33
|
+
expect(matchGlob("b.md", "[ab].md")).toBe(true);
|
|
34
|
+
expect(matchGlob("c.md", "[ab].md")).toBe(false);
|
|
35
|
+
});
|
|
36
|
+
it("normalizes leading ./ and backslashes", () => {
|
|
37
|
+
expect(matchGlob("./INDEX.md", "INDEX.md")).toBe(true);
|
|
38
|
+
expect(matchGlob("notes\\foo.md", "notes/foo.md")).toBe(true);
|
|
39
|
+
});
|
|
40
|
+
it("escapes regex metacharacters in literal segments", () => {
|
|
41
|
+
expect(matchGlob("a.b+c.md", "a.b+c.md")).toBe(true);
|
|
42
|
+
expect(matchGlob("axb+c.md", "a.b+c.md")).toBe(false); // . is literal, not regex any-char
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
describe("matchAnyGlob", () => {
|
|
46
|
+
it("returns true when any pattern matches", () => {
|
|
47
|
+
expect(matchAnyGlob("INDEX.md", ["README.md", "INDEX.md"])).toBe(true);
|
|
48
|
+
expect(matchAnyGlob("notes/x.md", ["INDEX.md", "notes/**"])).toBe(true);
|
|
49
|
+
});
|
|
50
|
+
it("returns false when no pattern matches", () => {
|
|
51
|
+
expect(matchAnyGlob("foo.txt", ["INDEX.md", "*.md"])).toBe(false);
|
|
52
|
+
});
|
|
53
|
+
it("returns false on empty pattern list", () => {
|
|
54
|
+
expect(matchAnyGlob("INDEX.md", [])).toBe(false);
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
//# sourceMappingURL=glob.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glob.test.js","sourceRoot":"","sources":["../../../src/util/__tests__/glob.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal POSIX-style glob matcher for relative paths.
|
|
3
|
+
*
|
|
4
|
+
* Supports:
|
|
5
|
+
* * -- any sequence of non-slash chars
|
|
6
|
+
* ** -- any sequence including slashes
|
|
7
|
+
* ? -- single non-slash char
|
|
8
|
+
* [abc] -- character class
|
|
9
|
+
* literal segments
|
|
10
|
+
*
|
|
11
|
+
* Paths are normalized to forward slashes before matching. Patterns must use
|
|
12
|
+
* forward slashes regardless of platform. Leading `./` is stripped.
|
|
13
|
+
*
|
|
14
|
+
* No brace expansion ({a,b}) and no extglob -- if you need those, swap in
|
|
15
|
+
* minimatch. This helper exists so core can ship zero-dep glob matching for
|
|
16
|
+
* the --preserve flag without dragging in a 30KB dependency.
|
|
17
|
+
*/
|
|
18
|
+
/** Compile a pattern once for repeated matching. */
|
|
19
|
+
export declare function compileGlob(pattern: string): (subject: string) => boolean;
|
|
20
|
+
/** Match a relative path against a single pattern. Convenience wrapper. */
|
|
21
|
+
export declare function matchGlob(subject: string, pattern: string): boolean;
|
|
22
|
+
/** True if any pattern matches. Compiles each pattern once per call. */
|
|
23
|
+
export declare function matchAnyGlob(subject: string, patterns: readonly string[]): boolean;
|
|
24
|
+
//# sourceMappingURL=glob.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glob.d.ts","sourceRoot":"","sources":["../../src/util/glob.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AA0DH,oDAAoD;AACpD,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAMzE;AAED,2EAA2E;AAC3E,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAEnE;AAED,wEAAwE;AACxE,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAMlF"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal POSIX-style glob matcher for relative paths.
|
|
3
|
+
*
|
|
4
|
+
* Supports:
|
|
5
|
+
* * -- any sequence of non-slash chars
|
|
6
|
+
* ** -- any sequence including slashes
|
|
7
|
+
* ? -- single non-slash char
|
|
8
|
+
* [abc] -- character class
|
|
9
|
+
* literal segments
|
|
10
|
+
*
|
|
11
|
+
* Paths are normalized to forward slashes before matching. Patterns must use
|
|
12
|
+
* forward slashes regardless of platform. Leading `./` is stripped.
|
|
13
|
+
*
|
|
14
|
+
* No brace expansion ({a,b}) and no extglob -- if you need those, swap in
|
|
15
|
+
* minimatch. This helper exists so core can ship zero-dep glob matching for
|
|
16
|
+
* the --preserve flag without dragging in a 30KB dependency.
|
|
17
|
+
*/
|
|
18
|
+
function globToRegExp(pattern) {
|
|
19
|
+
// Normalize: strip leading ./ and any duplicate slashes.
|
|
20
|
+
const norm = pattern.replace(/^\.\//, "").replace(/\/+/g, "/");
|
|
21
|
+
let re = "^";
|
|
22
|
+
let i = 0;
|
|
23
|
+
while (i < norm.length) {
|
|
24
|
+
const ch = norm[i];
|
|
25
|
+
if (ch === "*") {
|
|
26
|
+
if (norm[i + 1] === "*") {
|
|
27
|
+
// ** -> match anything including /
|
|
28
|
+
// **/ -> match zero or more path segments (consume the trailing /)
|
|
29
|
+
if (norm[i + 2] === "/") {
|
|
30
|
+
re += "(?:.*/)?";
|
|
31
|
+
i += 3;
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
re += ".*";
|
|
35
|
+
i += 2;
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
// single * -> any sequence of non-/ chars
|
|
39
|
+
re += "[^/]*";
|
|
40
|
+
i += 1;
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
if (ch === "?") {
|
|
44
|
+
re += "[^/]";
|
|
45
|
+
i += 1;
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
if (ch === "[") {
|
|
49
|
+
// copy character class verbatim until matching ]
|
|
50
|
+
const close = norm.indexOf("]", i + 1);
|
|
51
|
+
if (close === -1) {
|
|
52
|
+
// unterminated class -- treat as literal [
|
|
53
|
+
re += "\\[";
|
|
54
|
+
i += 1;
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
re += norm.slice(i, close + 1);
|
|
58
|
+
i = close + 1;
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
// Escape regex metachars; keep slashes literal.
|
|
62
|
+
if (/[.+^${}()|\\]/.test(ch)) {
|
|
63
|
+
re += "\\" + ch;
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
re += ch;
|
|
67
|
+
}
|
|
68
|
+
i += 1;
|
|
69
|
+
}
|
|
70
|
+
re += "$";
|
|
71
|
+
return new RegExp(re);
|
|
72
|
+
}
|
|
73
|
+
/** Compile a pattern once for repeated matching. */
|
|
74
|
+
export function compileGlob(pattern) {
|
|
75
|
+
const rx = globToRegExp(pattern);
|
|
76
|
+
return (subject) => {
|
|
77
|
+
const norm = subject.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
78
|
+
return rx.test(norm);
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
/** Match a relative path against a single pattern. Convenience wrapper. */
|
|
82
|
+
export function matchGlob(subject, pattern) {
|
|
83
|
+
return compileGlob(pattern)(subject);
|
|
84
|
+
}
|
|
85
|
+
/** True if any pattern matches. Compiles each pattern once per call. */
|
|
86
|
+
export function matchAnyGlob(subject, patterns) {
|
|
87
|
+
const norm = subject.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
88
|
+
for (const p of patterns) {
|
|
89
|
+
if (globToRegExp(p).test(norm))
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=glob.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glob.js","sourceRoot":"","sources":["../../src/util/glob.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Filesystem-safe slug from a free-text name. Lowercases, strips anything
|
|
3
|
+
* non-alphanumeric to dashes, trims edges, caps at 60 chars. Returns "" for
|
|
4
|
+
* empty/null input -- callers should pair with `safeSlug()` if they need a
|
|
5
|
+
* fallback.
|
|
6
|
+
*/
|
|
7
|
+
export declare function slugify(name: string | null | undefined): string;
|
|
8
|
+
/**
|
|
9
|
+
* Slug guaranteed non-empty. If `name` slugifies to "", returns
|
|
10
|
+
* `unnamed-<uuid>`. Use this anywhere a path segment must be unique even when
|
|
11
|
+
* the source object has no name.
|
|
12
|
+
*/
|
|
13
|
+
export declare function safeSlug(name: string | null | undefined, uuid: string): string;
|
|
14
|
+
/**
|
|
15
|
+
* Human-readable label. Returns the trimmed name when present, else
|
|
16
|
+
* `<unnamed <uuid>>`. For log lines and progress output.
|
|
17
|
+
*/
|
|
18
|
+
export declare function displayName(name: string | null | undefined, uuid: string): string;
|
|
19
|
+
//# sourceMappingURL=naming.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"naming.d.ts","sourceRoot":"","sources":["../../src/util/naming.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAM/D;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9E;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAGjF"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Filesystem-safe slug from a free-text name. Lowercases, strips anything
|
|
3
|
+
* non-alphanumeric to dashes, trims edges, caps at 60 chars. Returns "" for
|
|
4
|
+
* empty/null input -- callers should pair with `safeSlug()` if they need a
|
|
5
|
+
* fallback.
|
|
6
|
+
*/
|
|
7
|
+
export function slugify(name) {
|
|
8
|
+
return (name ?? "")
|
|
9
|
+
.toLowerCase()
|
|
10
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
11
|
+
.replace(/^-|-$/g, "")
|
|
12
|
+
.slice(0, 60);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Slug guaranteed non-empty. If `name` slugifies to "", returns
|
|
16
|
+
* `unnamed-<uuid>`. Use this anywhere a path segment must be unique even when
|
|
17
|
+
* the source object has no name.
|
|
18
|
+
*/
|
|
19
|
+
export function safeSlug(name, uuid) {
|
|
20
|
+
return slugify(name) || `unnamed-${uuid}`;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Human-readable label. Returns the trimmed name when present, else
|
|
24
|
+
* `<unnamed <uuid>>`. For log lines and progress output.
|
|
25
|
+
*/
|
|
26
|
+
export function displayName(name, uuid) {
|
|
27
|
+
const trimmed = (name ?? "").trim();
|
|
28
|
+
return trimmed || `<unnamed ${uuid}>`;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=naming.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"naming.js","sourceRoot":"","sources":["../../src/util/naming.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,UAAU,OAAO,CAAC,IAA+B;IACrD,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC;SAChB,WAAW,EAAE;SACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC;SACrB,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAClB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAC,IAA+B,EAAE,IAAY;IACpE,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,WAAW,IAAI,EAAE,CAAC;AAC5C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,IAA+B,EAAE,IAAY;IACvE,MAAM,OAAO,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACpC,OAAO,OAAO,IAAI,YAAY,IAAI,GAAG,CAAC;AACxC,CAAC"}
|