@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 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
@@ -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,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,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;AAS5B,OAAO,EAIL,KAAK,SAAS,EACf,MAAM,YAAY,CAAC;AAGpB,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;CAC3B;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,CA+GjC"}
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"}
@@ -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
- // Fetch full tree + artifacts.
66
- const conversation = await client.getConversation(orgId, summary.uuid, {
67
- tree: true,
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, artifactContents } = await fetchArtifacts(client, orgId, summary.uuid, !options.skipArtifacts);
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
- // files mode: stage in tmp, swap.
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
- // Re-use exportToGit then strip .git. We need fresh tmp each time since
155
- // exportToGit refuses to write into an existing path.
156
- const stash = outputPath + ".prev";
157
- const isUpdate = fs.existsSync(outputPath);
158
- if (isUpdate) {
159
- if (fs.existsSync(stash)) {
160
- fs.rmSync(stash, { recursive: true, force: true });
161
- }
162
- fs.renameSync(outputPath, stash);
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":"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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":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,SAAS,YAAY,CAAC,OAAe;IACnC,yDAAyD;IACzD,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAE/D,IAAI,EAAE,GAAG,GAAG,CAAC;IACb,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QACvB,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACnB,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YACf,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;gBACxB,oCAAoC;gBACpC,mEAAmE;gBACnE,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;oBACxB,EAAE,IAAI,UAAU,CAAC;oBACjB,CAAC,IAAI,CAAC,CAAC;oBACP,SAAS;gBACX,CAAC;gBACD,EAAE,IAAI,IAAI,CAAC;gBACX,CAAC,IAAI,CAAC,CAAC;gBACP,SAAS;YACX,CAAC;YACD,0CAA0C;YAC1C,EAAE,IAAI,OAAO,CAAC;YACd,CAAC,IAAI,CAAC,CAAC;YACP,SAAS;QACX,CAAC;QACD,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YACf,EAAE,IAAI,MAAM,CAAC;YACb,CAAC,IAAI,CAAC,CAAC;YACP,SAAS;QACX,CAAC;QACD,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YACf,iDAAiD;YACjD,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;YACvC,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC;gBACjB,2CAA2C;gBAC3C,EAAE,IAAI,KAAK,CAAC;gBACZ,CAAC,IAAI,CAAC,CAAC;gBACP,SAAS;YACX,CAAC;YACD,EAAE,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;YAC/B,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;YACd,SAAS;QACX,CAAC;QACD,gDAAgD;QAChD,IAAI,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;YAC7B,EAAE,IAAI,IAAI,GAAG,EAAE,CAAC;QAClB,CAAC;aAAM,CAAC;YACN,EAAE,IAAI,EAAE,CAAC;QACX,CAAC;QACD,CAAC,IAAI,CAAC,CAAC;IACT,CAAC;IACD,EAAE,IAAI,GAAG,CAAC;IACV,OAAO,IAAI,MAAM,CAAC,EAAE,CAAC,CAAC;AACxB,CAAC;AAED,oDAAoD;AACpD,MAAM,UAAU,WAAW,CAAC,OAAe;IACzC,MAAM,EAAE,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;IACjC,OAAO,CAAC,OAAe,EAAE,EAAE;QACzB,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAC9D,OAAO,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvB,CAAC,CAAC;AACJ,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,SAAS,CAAC,OAAe,EAAE,OAAe;IACxD,OAAO,WAAW,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC;AACvC,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,YAAY,CAAC,OAAe,EAAE,QAA2B;IACvE,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAC9D,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,IAAI,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;IAC9C,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@infinite-room-labs/claudesync-core",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/InfiniteRoomLabs/claudesync"