@codebyplan/cli 3.3.0 → 3.4.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/cli.js +50 -17
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -37,7 +37,7 @@ var VERSION, PACKAGE_NAME;
|
|
|
37
37
|
var init_version = __esm({
|
|
38
38
|
"src/lib/version.ts"() {
|
|
39
39
|
"use strict";
|
|
40
|
-
VERSION = "3.
|
|
40
|
+
VERSION = "3.4.0";
|
|
41
41
|
PACKAGE_NAME = "@codebyplan/cli";
|
|
42
42
|
}
|
|
43
43
|
});
|
|
@@ -1751,8 +1751,12 @@ var sync_exports = {};
|
|
|
1751
1751
|
__export(sync_exports, {
|
|
1752
1752
|
runSync: () => runSync
|
|
1753
1753
|
});
|
|
1754
|
+
import { createHash } from "node:crypto";
|
|
1754
1755
|
import { readFile as readFile7, writeFile as writeFile3, mkdir as mkdir2, chmod as chmod2, unlink as unlink2 } from "node:fs/promises";
|
|
1755
1756
|
import { join as join7, dirname as dirname2 } from "node:path";
|
|
1757
|
+
function contentHash(content) {
|
|
1758
|
+
return createHash("sha256").update(content).digest("hex");
|
|
1759
|
+
}
|
|
1756
1760
|
async function runSync() {
|
|
1757
1761
|
const flags = parseFlags(3);
|
|
1758
1762
|
const dryRun = hasFlag("dry-run", 3);
|
|
@@ -1817,17 +1821,27 @@ async function runSyncInner(repoId, projectPath, dryRun, force) {
|
|
|
1817
1821
|
localFiles = await scanLocalFiles(claudeDir, projectPath);
|
|
1818
1822
|
} catch {
|
|
1819
1823
|
}
|
|
1820
|
-
const [defaultsRes, repoSyncRes, repoRes, syncStateRes] = await Promise.all([
|
|
1824
|
+
const [defaultsRes, repoSyncRes, repoRes, syncStateRes, fileReposRes] = await Promise.all([
|
|
1821
1825
|
apiGet("/sync/defaults"),
|
|
1822
1826
|
apiGet("/sync/files", { repo_id: repoId }),
|
|
1823
1827
|
apiGet(`/repos/${repoId}`),
|
|
1824
|
-
apiGet("/sync/state", { repo_id: repoId })
|
|
1828
|
+
apiGet("/sync/state", { repo_id: repoId }),
|
|
1829
|
+
apiGet("/sync/file-repos", { repo_id: repoId })
|
|
1825
1830
|
]);
|
|
1826
1831
|
const syncStartTime = Date.now();
|
|
1827
1832
|
const repoData = repoRes.data;
|
|
1828
1833
|
const remoteDefaults = flattenSyncData(defaultsRes.data);
|
|
1829
1834
|
const remoteRepoFiles = flattenSyncData(repoSyncRes.data);
|
|
1830
1835
|
const syncState = syncStateRes.data;
|
|
1836
|
+
const fileRepoHashes = /* @__PURE__ */ new Map();
|
|
1837
|
+
const fileRepoByClaudeFileId = /* @__PURE__ */ new Map();
|
|
1838
|
+
for (const entry of fileReposRes.data ?? []) {
|
|
1839
|
+
if (entry.claude_files) {
|
|
1840
|
+
const key = compositeKey(entry.claude_files.type, entry.claude_files.name, entry.claude_files.category);
|
|
1841
|
+
fileRepoHashes.set(key, entry.last_synced_content_hash);
|
|
1842
|
+
}
|
|
1843
|
+
fileRepoByClaudeFileId.set(entry.claude_file_id, entry.last_synced_content_hash);
|
|
1844
|
+
}
|
|
1831
1845
|
const remoteFiles = new Map([...remoteDefaults, ...remoteRepoFiles]);
|
|
1832
1846
|
console.log(` Local: ${localFiles.size} files, Remote: ${remoteFiles.size} files
|
|
1833
1847
|
`);
|
|
@@ -1854,9 +1868,8 @@ async function runSyncInner(repoId, projectPath, dryRun, force) {
|
|
|
1854
1868
|
});
|
|
1855
1869
|
} else if (!local && remote) {
|
|
1856
1870
|
const resolvedContent = substituteVariables(remote.content, repoData);
|
|
1857
|
-
const
|
|
1858
|
-
const
|
|
1859
|
-
const recommended = !isDefaultOnly && hasSyncedBefore ? "delete" : "pull";
|
|
1871
|
+
const hadSyncedThisFile = remote.id ? fileRepoByClaudeFileId.has(remote.id) : fileRepoHashes.has(key);
|
|
1872
|
+
const recommended = hadSyncedThisFile ? "delete" : "pull";
|
|
1860
1873
|
plan.push({
|
|
1861
1874
|
key,
|
|
1862
1875
|
displayPath: `${remote.type}/${remote.category ? remote.category + "/" : ""}${remote.name}`,
|
|
@@ -1877,16 +1890,24 @@ async function runSyncInner(repoId, projectPath, dryRun, force) {
|
|
|
1877
1890
|
if (local.content === resolvedRemote) {
|
|
1878
1891
|
continue;
|
|
1879
1892
|
}
|
|
1880
|
-
const
|
|
1881
|
-
const
|
|
1882
|
-
const
|
|
1893
|
+
const localHash = contentHash(local.content);
|
|
1894
|
+
const lastSyncedHash = fileRepoHashes.get(key) ?? null;
|
|
1895
|
+
const localChanged = lastSyncedHash ? localHash !== lastSyncedHash : true;
|
|
1883
1896
|
let action;
|
|
1884
|
-
if (
|
|
1897
|
+
if (force) {
|
|
1885
1898
|
action = "pull";
|
|
1886
|
-
} else if (!
|
|
1887
|
-
action = "
|
|
1888
|
-
} else {
|
|
1899
|
+
} else if (!localChanged) {
|
|
1900
|
+
action = "pull";
|
|
1901
|
+
} else if (lastSyncedHash === null) {
|
|
1889
1902
|
action = "conflict";
|
|
1903
|
+
} else {
|
|
1904
|
+
const remoteDbHash = remote.content_hash ?? null;
|
|
1905
|
+
const remoteChanged = remoteDbHash ? remoteDbHash !== lastSyncedHash : true;
|
|
1906
|
+
if (remoteChanged) {
|
|
1907
|
+
action = "conflict";
|
|
1908
|
+
} else {
|
|
1909
|
+
action = "push";
|
|
1910
|
+
}
|
|
1890
1911
|
}
|
|
1891
1912
|
plan.push({
|
|
1892
1913
|
key,
|
|
@@ -2062,11 +2083,22 @@ async function runSyncInner(repoId, projectPath, dryRun, force) {
|
|
|
2062
2083
|
});
|
|
2063
2084
|
const syncTimestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
2064
2085
|
const fileRepoUpdates = [];
|
|
2065
|
-
for (const p of
|
|
2066
|
-
if (p.claudeFileId) {
|
|
2086
|
+
for (const p of toPull) {
|
|
2087
|
+
if (p.claudeFileId && p.remoteContent !== null) {
|
|
2088
|
+
fileRepoUpdates.push({
|
|
2089
|
+
claude_file_id: p.claudeFileId,
|
|
2090
|
+
last_synced_at: syncTimestamp,
|
|
2091
|
+
last_synced_content_hash: contentHash(p.remoteContent),
|
|
2092
|
+
sync_status: "synced"
|
|
2093
|
+
});
|
|
2094
|
+
}
|
|
2095
|
+
}
|
|
2096
|
+
for (const p of toPush) {
|
|
2097
|
+
if (p.claudeFileId && p.localContent !== null) {
|
|
2067
2098
|
fileRepoUpdates.push({
|
|
2068
2099
|
claude_file_id: p.claudeFileId,
|
|
2069
2100
|
last_synced_at: syncTimestamp,
|
|
2101
|
+
last_synced_content_hash: contentHash(p.localContent),
|
|
2070
2102
|
sync_status: "synced"
|
|
2071
2103
|
});
|
|
2072
2104
|
}
|
|
@@ -2263,7 +2295,7 @@ function getLocalFilePath(claudeDir, projectPath, remote) {
|
|
|
2263
2295
|
}
|
|
2264
2296
|
function getSyncVersion() {
|
|
2265
2297
|
try {
|
|
2266
|
-
return "3.
|
|
2298
|
+
return "3.4.0";
|
|
2267
2299
|
} catch {
|
|
2268
2300
|
return "unknown";
|
|
2269
2301
|
}
|
|
@@ -2289,7 +2321,8 @@ function flattenSyncData(data) {
|
|
|
2289
2321
|
name: file.name,
|
|
2290
2322
|
content: file.content,
|
|
2291
2323
|
category: file.category,
|
|
2292
|
-
updated_at: file.updated_at
|
|
2324
|
+
updated_at: file.updated_at,
|
|
2325
|
+
content_hash: file.content_hash
|
|
2293
2326
|
});
|
|
2294
2327
|
}
|
|
2295
2328
|
}
|