@infinite-room-labs/claudesync-core 0.4.1 → 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 CHANGED
@@ -24,5 +24,8 @@ export type { ExportFormat, SyncConversationOptions, SyncConversationResult, } f
24
24
  export { syncConversation, isSameByListMetadata, } from "./sync/incremental.js";
25
25
  export type { FetchAndBuildOptions, FetchAndBuildResult, } from "./sync/fetch.js";
26
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";
27
29
  export { slugify, safeSlug, displayName } from "./util/naming.js";
30
+ export { matchGlob, matchAnyGlob, compileGlob } from "./util/glob.js";
28
31
  //# sourceMappingURL=index.d.ts.map
@@ -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;AAC/B,YAAY,EACV,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGhD,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,kBAAkB,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
@@ -16,6 +16,9 @@ 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
18
  export { fetchAndBuild } from "./sync/fetch.js";
19
+ export { replaceWithPreserve, walkRelative } from "./sync/files-mode.js";
19
20
  // Naming helpers
20
21
  export { slugify, safeSlug, displayName } from "./util/naming.js";
22
+ // Glob helpers
23
+ export { matchGlob, matchAnyGlob, compileGlob } from "./util/glob.js";
21
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;AAK/B,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,iBAAiB;AACjB,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,kBAAkB,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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=files-mode.test.d.ts.map
@@ -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,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,6 +12,14 @@ 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";
@@ -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;AAQ5B,OAAO,EAIL,KAAK,SAAS,EACf,MAAM,YAAY,CAAC;AAKpB,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;CACzB;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"}
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"}
@@ -8,6 +8,7 @@ import { readSyncState, writeSyncState, STATE_FILENAME, } from "./state.js";
8
8
  import { buildMessageTree, findLeafMessages } from "../tree/message-tree.js";
9
9
  import { fetchAndBuild } from "./fetch.js";
10
10
  import { displayName as toDisplayName } from "../util/naming.js";
11
+ import { replaceWithPreserve } from "./files-mode.js";
11
12
  /**
12
13
  * Cheap predicate for --skip-same. Returns true when the list-endpoint summary
13
14
  * matches what the sidecar state file recorded on the previous sync. Caller
@@ -97,7 +98,7 @@ export async function syncConversation(client, orgId, summary, outputPath, optio
97
98
  }
98
99
  }
99
100
  else {
100
- await writeFilesMode(bundle, outputPath);
101
+ await writeFilesMode(bundle, outputPath, options.preserve ?? []);
101
102
  }
102
103
  let changelogWritten = false;
103
104
  const section = renderChangelogSection(diff, new Date());
@@ -118,44 +119,24 @@ export async function syncConversation(client, orgId, summary, outputPath, optio
118
119
  /**
119
120
  * Files mode: replay bundle into outputPath via the same tmp+swap pattern as
120
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.
121
128
  */
122
- async function writeFilesMode(bundle, outputPath) {
123
- // Re-use exportToGit then strip .git. We need fresh tmp each time since
124
- // exportToGit refuses to write into an existing path.
125
- const stash = outputPath + ".prev";
126
- const isUpdate = fs.existsSync(outputPath);
127
- if (isUpdate) {
128
- if (fs.existsSync(stash)) {
129
- fs.rmSync(stash, { recursive: true, force: true });
130
- }
131
- fs.renameSync(outputPath, stash);
132
- }
133
- try {
134
- await exportToGit(bundle, outputPath);
135
- rmSync(path.join(outputPath, ".git"), { recursive: true, force: true });
136
- // Preserve CHANGELOG.md from the previous tree (we'll append to it after).
137
- if (isUpdate && fs.existsSync(path.join(stash, CHANGELOG_FILENAME))) {
138
- fs.copyFileSync(path.join(stash, CHANGELOG_FILENAME), path.join(outputPath, CHANGELOG_FILENAME));
139
- }
140
- if (isUpdate && fs.existsSync(path.join(stash, STATE_FILENAME))) {
141
- // State file gets rewritten by caller; nothing to preserve.
142
- }
143
- if (isUpdate) {
144
- fs.rmSync(stash, { recursive: true, force: true });
145
- }
146
- }
147
- catch (error) {
148
- // Restore original on failure.
149
- if (isUpdate) {
150
- if (fs.existsSync(outputPath)) {
151
- fs.rmSync(outputPath, { recursive: true, force: true });
152
- }
153
- if (fs.existsSync(stash)) {
154
- fs.renameSync(stash, outputPath);
155
- }
156
- }
157
- throw error;
158
- }
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
+ });
159
140
  }
160
141
  function ensureGitignore(repoDir) {
161
142
  const gitignorePath = path.join(repoDir, ".gitignore");
@@ -1 +1 @@
1
- {"version":3,"file":"incremental.js","sourceRoot":"","sources":["../../src/sync/incremental.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"incremental.js","sourceRoot":"","sources":["../../src/sync/incremental.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=glob.test.d.ts.map
@@ -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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@infinite-room-labs/claudesync-core",
3
- "version": "0.4.1",
3
+ "version": "0.5.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/InfiniteRoomLabs/claudesync"