@tinyrack/devsync 1.1.0 → 1.2.2

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.
Files changed (216) hide show
  1. package/README.md +230 -62
  2. package/dist/cli/base-command.d.ts +14 -0
  3. package/dist/cli/base-command.d.ts.map +1 -0
  4. package/dist/cli/base-command.js +22 -0
  5. package/dist/cli/base-command.js.map +1 -0
  6. package/dist/cli/commands/dir.d.ts +8 -0
  7. package/dist/cli/commands/dir.d.ts.map +1 -0
  8. package/dist/cli/commands/dir.js +16 -0
  9. package/dist/cli/commands/dir.js.map +1 -0
  10. package/dist/cli/commands/doctor.d.ts +8 -0
  11. package/dist/cli/commands/doctor.d.ts.map +1 -0
  12. package/dist/cli/commands/doctor.js +18 -0
  13. package/dist/cli/commands/doctor.js.map +1 -0
  14. package/dist/cli/commands/index.d.ts +23 -0
  15. package/dist/cli/commands/index.d.ts.map +1 -0
  16. package/dist/cli/commands/index.js +23 -0
  17. package/dist/cli/commands/index.js.map +1 -0
  18. package/dist/cli/commands/init.d.ts +15 -0
  19. package/dist/cli/commands/init.d.ts.map +1 -0
  20. package/dist/cli/commands/init.js +43 -0
  21. package/dist/cli/commands/init.js.map +1 -0
  22. package/dist/cli/commands/machine/list.d.ts +7 -0
  23. package/dist/cli/commands/machine/list.d.ts.map +1 -0
  24. package/dist/cli/commands/machine/list.js +12 -0
  25. package/dist/cli/commands/machine/list.js.map +1 -0
  26. package/dist/cli/commands/machine/use.d.ts +11 -0
  27. package/dist/cli/commands/machine/use.d.ts.map +1 -0
  28. package/dist/cli/commands/machine/use.js +28 -0
  29. package/dist/cli/commands/machine/use.js.map +1 -0
  30. package/dist/cli/commands/pull.d.ts +12 -0
  31. package/dist/cli/commands/pull.d.ts.map +1 -0
  32. package/dist/cli/commands/pull.js +34 -0
  33. package/dist/cli/commands/pull.js.map +1 -0
  34. package/dist/cli/commands/push.d.ts +12 -0
  35. package/dist/cli/commands/push.d.ts.map +1 -0
  36. package/dist/cli/commands/push.js +34 -0
  37. package/dist/cli/commands/push.js.map +1 -0
  38. package/dist/cli/commands/status.d.ts +11 -0
  39. package/dist/cli/commands/status.d.ts.map +1 -0
  40. package/dist/cli/commands/status.js +27 -0
  41. package/dist/cli/commands/status.js.map +1 -0
  42. package/dist/cli/commands/track.d.ts +16 -0
  43. package/dist/cli/commands/track.d.ts.map +1 -0
  44. package/dist/cli/commands/track.js +82 -0
  45. package/dist/cli/commands/track.js.map +1 -0
  46. package/dist/cli/commands/untrack.d.ts +11 -0
  47. package/dist/cli/commands/untrack.d.ts.map +1 -0
  48. package/dist/cli/commands/untrack.js +28 -0
  49. package/dist/cli/commands/untrack.js.map +1 -0
  50. package/dist/config/global-config.d.ts +21 -0
  51. package/dist/config/global-config.d.ts.map +1 -0
  52. package/dist/config/global-config.js +106 -0
  53. package/dist/config/global-config.js.map +1 -0
  54. package/dist/config/sync.d.ts +96 -0
  55. package/dist/config/sync.d.ts.map +1 -0
  56. package/dist/config/sync.js +412 -0
  57. package/dist/config/sync.js.map +1 -0
  58. package/dist/config/xdg.d.ts +11 -0
  59. package/dist/config/xdg.d.ts.map +1 -0
  60. package/dist/config/xdg.js +79 -0
  61. package/dist/config/xdg.js.map +1 -0
  62. package/dist/index.d.ts +3 -0
  63. package/dist/index.d.ts.map +1 -0
  64. package/{src/index.ts → dist/index.js} +1 -1
  65. package/dist/index.js.map +1 -0
  66. package/dist/lib/file-mode.d.ts +3 -0
  67. package/dist/lib/file-mode.d.ts.map +1 -0
  68. package/dist/lib/file-mode.js +7 -0
  69. package/dist/lib/file-mode.js.map +1 -0
  70. package/dist/lib/output.d.ts +31 -0
  71. package/dist/lib/output.d.ts.map +1 -0
  72. package/dist/lib/output.js +198 -0
  73. package/dist/lib/output.js.map +1 -0
  74. package/dist/lib/path.d.ts +5 -0
  75. package/dist/lib/path.d.ts.map +1 -0
  76. package/dist/lib/path.js +25 -0
  77. package/dist/lib/path.js.map +1 -0
  78. package/dist/lib/string.d.ts +2 -0
  79. package/dist/lib/string.d.ts.map +1 -0
  80. package/dist/lib/string.js +4 -0
  81. package/dist/lib/string.js.map +1 -0
  82. package/dist/lib/validation.d.ts +3 -0
  83. package/dist/lib/validation.d.ts.map +1 -0
  84. package/dist/lib/validation.js +9 -0
  85. package/dist/lib/validation.js.map +1 -0
  86. package/dist/services/add.d.ts +20 -0
  87. package/dist/services/add.d.ts.map +1 -0
  88. package/dist/services/add.js +161 -0
  89. package/dist/services/add.js.map +1 -0
  90. package/dist/services/config-file.d.ts +30 -0
  91. package/dist/services/config-file.d.ts.map +1 -0
  92. package/dist/services/config-file.js +34 -0
  93. package/dist/services/config-file.js.map +1 -0
  94. package/dist/services/crypto.d.ts +9 -0
  95. package/dist/services/crypto.d.ts.map +1 -0
  96. package/dist/services/crypto.js +75 -0
  97. package/dist/services/crypto.js.map +1 -0
  98. package/dist/services/doctor.d.ts +16 -0
  99. package/dist/services/doctor.d.ts.map +1 -0
  100. package/dist/services/doctor.js +84 -0
  101. package/dist/services/doctor.js.map +1 -0
  102. package/dist/services/error.d.ts +14 -0
  103. package/dist/services/error.d.ts.map +1 -0
  104. package/dist/services/error.js +38 -0
  105. package/dist/services/error.js.map +1 -0
  106. package/dist/services/filesystem.d.ts +15 -0
  107. package/dist/services/filesystem.d.ts.map +1 -0
  108. package/dist/services/filesystem.js +113 -0
  109. package/dist/services/filesystem.js.map +1 -0
  110. package/dist/services/forget.d.ts +14 -0
  111. package/dist/services/forget.d.ts.map +1 -0
  112. package/dist/services/forget.js +124 -0
  113. package/dist/services/forget.js.map +1 -0
  114. package/dist/services/git.d.ts +10 -0
  115. package/dist/services/git.d.ts.map +1 -0
  116. package/dist/services/git.js +57 -0
  117. package/dist/services/git.js.map +1 -0
  118. package/dist/services/init.d.ts +19 -0
  119. package/dist/services/init.d.ts.map +1 -0
  120. package/dist/services/init.js +203 -0
  121. package/dist/services/init.js.map +1 -0
  122. package/dist/services/local-materialization.d.ts +28 -0
  123. package/dist/services/local-materialization.d.ts.map +1 -0
  124. package/dist/services/local-materialization.js +262 -0
  125. package/dist/services/local-materialization.js.map +1 -0
  126. package/dist/services/local-snapshot.d.ts +25 -0
  127. package/dist/services/local-snapshot.d.ts.map +1 -0
  128. package/dist/services/local-snapshot.js +93 -0
  129. package/dist/services/local-snapshot.js.map +1 -0
  130. package/dist/services/machine.d.ts +40 -0
  131. package/dist/services/machine.d.ts.map +1 -0
  132. package/dist/services/machine.js +113 -0
  133. package/dist/services/machine.js.map +1 -0
  134. package/dist/services/paths.d.ts +12 -0
  135. package/dist/services/paths.d.ts.map +1 -0
  136. package/dist/services/paths.js +71 -0
  137. package/dist/services/paths.js.map +1 -0
  138. package/dist/services/pull.d.ts +28 -0
  139. package/dist/services/pull.d.ts.map +1 -0
  140. package/dist/services/pull.js +67 -0
  141. package/dist/services/pull.js.map +1 -0
  142. package/dist/services/push.d.ts +35 -0
  143. package/dist/services/push.d.ts.map +1 -0
  144. package/dist/services/push.js +96 -0
  145. package/dist/services/push.js.map +1 -0
  146. package/dist/services/repo-artifacts.d.ts +52 -0
  147. package/dist/services/repo-artifacts.d.ts.map +1 -0
  148. package/dist/services/repo-artifacts.js +251 -0
  149. package/dist/services/repo-artifacts.js.map +1 -0
  150. package/dist/services/repo-snapshot.d.ts +6 -0
  151. package/dist/services/repo-snapshot.d.ts.map +1 -0
  152. package/dist/services/repo-snapshot.js +163 -0
  153. package/dist/services/repo-snapshot.js.map +1 -0
  154. package/dist/services/runtime.d.ts +40 -0
  155. package/dist/services/runtime.d.ts.map +1 -0
  156. package/dist/services/runtime.js +71 -0
  157. package/dist/services/runtime.js.map +1 -0
  158. package/dist/services/set.d.ts +38 -0
  159. package/dist/services/set.d.ts.map +1 -0
  160. package/dist/services/set.js +184 -0
  161. package/dist/services/set.js.map +1 -0
  162. package/dist/services/status.d.ts +30 -0
  163. package/dist/services/status.d.ts.map +1 -0
  164. package/dist/services/status.js +35 -0
  165. package/dist/services/status.js.map +1 -0
  166. package/package.json +15 -7
  167. package/src/cli/commands/add.ts +0 -40
  168. package/src/cli/commands/cd.ts +0 -80
  169. package/src/cli/commands/doctor.ts +0 -20
  170. package/src/cli/commands/forget.ts +0 -32
  171. package/src/cli/commands/index.ts +0 -23
  172. package/src/cli/commands/init.ts +0 -43
  173. package/src/cli/commands/list.ts +0 -17
  174. package/src/cli/commands/pull.ts +0 -31
  175. package/src/cli/commands/push.ts +0 -31
  176. package/src/cli/commands/set.ts +0 -47
  177. package/src/cli/commands/status.ts +0 -18
  178. package/src/cli/sync-output.test.ts +0 -173
  179. package/src/cli/sync-output.ts +0 -200
  180. package/src/config/sync.test.ts +0 -609
  181. package/src/config/sync.ts +0 -572
  182. package/src/config/xdg.ts +0 -138
  183. package/src/lib/string.test.ts +0 -13
  184. package/src/lib/string.ts +0 -3
  185. package/src/lib/validation.test.ts +0 -32
  186. package/src/lib/validation.ts +0 -11
  187. package/src/services/add.ts +0 -178
  188. package/src/services/config-file.test.ts +0 -161
  189. package/src/services/config-file.ts +0 -101
  190. package/src/services/crypto.test.ts +0 -132
  191. package/src/services/crypto.ts +0 -83
  192. package/src/services/doctor.ts +0 -142
  193. package/src/services/error.ts +0 -6
  194. package/src/services/filesystem.test.ts +0 -171
  195. package/src/services/filesystem.ts +0 -183
  196. package/src/services/forget.ts +0 -261
  197. package/src/services/git.test.ts +0 -83
  198. package/src/services/git.ts +0 -74
  199. package/src/services/init.test.ts +0 -109
  200. package/src/services/init.ts +0 -244
  201. package/src/services/list.ts +0 -63
  202. package/src/services/local-materialization.ts +0 -421
  203. package/src/services/local-snapshot.ts +0 -173
  204. package/src/services/paths.test.ts +0 -74
  205. package/src/services/paths.ts +0 -98
  206. package/src/services/pull.ts +0 -144
  207. package/src/services/push.ts +0 -168
  208. package/src/services/repo-artifacts.ts +0 -262
  209. package/src/services/repo-snapshot.ts +0 -197
  210. package/src/services/runtime.ts +0 -57
  211. package/src/services/set.ts +0 -383
  212. package/src/services/status.ts +0 -57
  213. package/src/services/sync.dry-run.test.ts +0 -179
  214. package/src/services/sync.runtime.test.ts +0 -756
  215. package/src/services/sync.service.test.ts +0 -1169
  216. package/src/test/helpers/sync-fixture.ts +0 -47
@@ -0,0 +1,93 @@
1
+ import { lstat, readFile, readlink } from "node:fs/promises";
2
+ import { join, posix } from "node:path";
3
+ import { resolveManagedSyncMode, } from "#app/config/sync.js";
4
+ import { isExecutableMode } from "#app/lib/file-mode.js";
5
+ import { DevsyncError } from "./error.js";
6
+ import { getPathStats, listDirectoryEntries } from "./filesystem.js";
7
+ import { assertStorageSafeRepoPath } from "./repo-artifacts.js";
8
+ export const addSnapshotNode = (snapshot, repoPath, node) => {
9
+ if (snapshot.has(repoPath)) {
10
+ throw new DevsyncError(`Duplicate sync path generated for ${repoPath}`);
11
+ }
12
+ snapshot.set(repoPath, node);
13
+ };
14
+ const addLocalNode = async (snapshot, config, repoPath, path, stats) => {
15
+ assertStorageSafeRepoPath(repoPath);
16
+ const mode = resolveManagedSyncMode(config, repoPath, config.activeMachine);
17
+ if (mode === "ignore") {
18
+ return;
19
+ }
20
+ if (stats.isDirectory()) {
21
+ throw new DevsyncError(`Expected a file-like path but found a directory: ${path}`);
22
+ }
23
+ if (stats.isSymbolicLink()) {
24
+ if (mode === "secret") {
25
+ throw new DevsyncError(`Secret sync paths must be regular files, not symlinks: ${repoPath}`);
26
+ }
27
+ addSnapshotNode(snapshot, repoPath, {
28
+ linkTarget: await readlink(path),
29
+ type: "symlink",
30
+ });
31
+ return;
32
+ }
33
+ if (!stats.isFile()) {
34
+ throw new DevsyncError(`Unsupported filesystem entry: ${path}`);
35
+ }
36
+ addSnapshotNode(snapshot, repoPath, {
37
+ contents: await readFile(path),
38
+ executable: isExecutableMode(stats.mode),
39
+ secret: mode === "secret",
40
+ type: "file",
41
+ });
42
+ };
43
+ const walkLocalDirectory = async (snapshot, config, localDirectory, repoPathPrefix, childEntryPaths) => {
44
+ const entries = await listDirectoryEntries(localDirectory);
45
+ for (const entry of entries) {
46
+ const localPath = join(localDirectory, entry.name);
47
+ const repoPath = posix.join(repoPathPrefix, entry.name);
48
+ if (childEntryPaths.has(repoPath)) {
49
+ continue;
50
+ }
51
+ const stats = await lstat(localPath);
52
+ if (stats.isDirectory()) {
53
+ assertStorageSafeRepoPath(repoPath);
54
+ await walkLocalDirectory(snapshot, config, localPath, repoPath, childEntryPaths);
55
+ continue;
56
+ }
57
+ await addLocalNode(snapshot, config, repoPath, localPath, stats);
58
+ }
59
+ };
60
+ export const buildLocalSnapshot = async (config) => {
61
+ const snapshot = new Map();
62
+ const allEntryPaths = new Set(config.entries.map((e) => e.repoPath));
63
+ for (const entry of config.entries) {
64
+ const stats = await getPathStats(entry.localPath);
65
+ if (stats === undefined) {
66
+ continue;
67
+ }
68
+ const entryMode = resolveManagedSyncMode(config, entry.repoPath, config.activeMachine);
69
+ if (entry.kind === "file") {
70
+ if (entryMode === "ignore") {
71
+ continue;
72
+ }
73
+ if (stats.isDirectory()) {
74
+ throw new DevsyncError(`Sync entry ${entry.name} expects a file, but found a directory: ${entry.localPath}`);
75
+ }
76
+ await addLocalNode(snapshot, config, entry.repoPath, entry.localPath, stats);
77
+ continue;
78
+ }
79
+ if (!stats.isDirectory()) {
80
+ throw new DevsyncError(`Sync entry ${entry.name} expects a directory: ${entry.localPath}`);
81
+ }
82
+ const childEntryPaths = new Set([...allEntryPaths].filter((p) => p !== entry.repoPath && p.startsWith(`${entry.repoPath}/`)));
83
+ const snapshotSizeBeforeWalk = snapshot.size;
84
+ await walkLocalDirectory(snapshot, config, entry.localPath, entry.repoPath, childEntryPaths);
85
+ if (entryMode !== "ignore" || snapshot.size > snapshotSizeBeforeWalk) {
86
+ addSnapshotNode(snapshot, entry.repoPath, {
87
+ type: "directory",
88
+ });
89
+ }
90
+ }
91
+ return snapshot;
92
+ };
93
+ //# sourceMappingURL=local-snapshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-snapshot.js","sourceRoot":"","sources":["../../src/services/local-snapshot.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ import { type SyncContext } from "./runtime.js";
2
+ export type SyncMachineAssignment = Readonly<{
3
+ entryLocalPath: string;
4
+ entryRepoPath: string;
5
+ machines: readonly string[];
6
+ }>;
7
+ export type SyncMachineListResult = Readonly<{
8
+ activeMachine?: string;
9
+ activeMachinesMode: "none" | "single";
10
+ assignments: readonly SyncMachineAssignment[];
11
+ availableMachines: readonly string[];
12
+ globalConfigExists: boolean;
13
+ globalConfigPath: string;
14
+ syncDirectory: string;
15
+ }>;
16
+ export type SyncMachineUpdateResult = Readonly<{
17
+ activeMachine?: string;
18
+ globalConfigPath: string;
19
+ mode: "clear" | "use";
20
+ machine?: string;
21
+ syncDirectory: string;
22
+ warning?: string;
23
+ }>;
24
+ type SyncMachineAssignRequest = Readonly<{
25
+ machines: readonly string[];
26
+ target: string;
27
+ }>;
28
+ type SyncMachineAssignResult = Readonly<{
29
+ action: "assigned" | "unchanged";
30
+ configPath: string;
31
+ entryRepoPath: string;
32
+ machines: readonly string[];
33
+ syncDirectory: string;
34
+ }>;
35
+ export declare const listSyncMachines: (context: SyncContext) => Promise<SyncMachineListResult>;
36
+ export declare const useSyncMachine: (machine: string, context: SyncContext) => Promise<SyncMachineUpdateResult>;
37
+ export declare const clearSyncMachines: (context: SyncContext) => Promise<SyncMachineUpdateResult>;
38
+ export declare const assignSyncMachines: (request: SyncMachineAssignRequest, context: SyncContext) => Promise<SyncMachineAssignResult>;
39
+ export {};
40
+ //# sourceMappingURL=machine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"machine.d.ts","sourceRoot":"","sources":["../../src/services/machine.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAwB,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAEtE,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC;IAC3C,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7B,CAAC,CAAC;AAEH,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC;IAC3C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,GAAG,QAAQ,CAAC;IACtC,WAAW,EAAE,SAAS,qBAAqB,EAAE,CAAC;IAC9C,iBAAiB,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,kBAAkB,EAAE,OAAO,CAAC;IAC5B,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC,CAAC;AAEH,MAAM,MAAM,uBAAuB,GAAG,QAAQ,CAAC;IAC7C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,IAAI,EAAE,OAAO,GAAG,KAAK,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC,CAAC;AAEH,KAAK,wBAAwB,GAAG,QAAQ,CAAC;IACvC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC,CAAC;AAEH,KAAK,uBAAuB,GAAG,QAAQ,CAAC;IACtC,MAAM,EAAE,UAAU,GAAG,WAAW,CAAC;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC,CAAC;AAEH,eAAO,MAAM,gBAAgB,GAC3B,SAAS,WAAW,KACnB,OAAO,CAAC,qBAAqB,CA6B/B,CAAC;AAEF,eAAO,MAAM,cAAc,GACzB,SAAS,MAAM,EACf,SAAS,WAAW,KACnB,OAAO,CAAC,uBAAuB,CA8BjC,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC5B,SAAS,WAAW,KACnB,OAAO,CAAC,uBAAuB,CAajC,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAC7B,SAAS,wBAAwB,EACjC,SAAS,WAAW,KACnB,OAAO,CAAC,uBAAuB,CAsEjC,CAAC"}
@@ -0,0 +1,113 @@
1
+ import { formatGlobalDevsyncConfig, readGlobalDevsyncConfig, } from "#app/config/global-config.js";
2
+ import { collectAllMachineNames, normalizeSyncMachineName, readSyncConfig, } from "#app/config/sync.js";
3
+ import { createSyncConfigDocument, writeValidatedSyncConfig, } from "./config-file.js";
4
+ import { DevsyncError } from "./error.js";
5
+ import { writeTextFileAtomically } from "./filesystem.js";
6
+ import { resolveTrackedEntry } from "./paths.js";
7
+ import { ensureSyncRepository } from "./runtime.js";
8
+ export const listSyncMachines = async (context) => {
9
+ await ensureSyncRepository(context);
10
+ const [globalConfig, syncConfig] = await Promise.all([
11
+ readGlobalDevsyncConfig(context.environment),
12
+ readSyncConfig(context.paths.syncDirectory, context.environment),
13
+ ]);
14
+ return {
15
+ ...(globalConfig?.activeMachine === undefined
16
+ ? {}
17
+ : { activeMachine: globalConfig.activeMachine }),
18
+ activeMachinesMode: globalConfig?.activeMachine === undefined ? "none" : "single",
19
+ assignments: syncConfig.entries
20
+ .filter((entry) => entry.machinesExplicit && entry.machines.length > 0)
21
+ .map((entry) => ({
22
+ entryLocalPath: entry.localPath,
23
+ entryRepoPath: entry.repoPath,
24
+ machines: entry.machines,
25
+ }))
26
+ .sort((left, right) => left.entryRepoPath.localeCompare(right.entryRepoPath)),
27
+ availableMachines: collectAllMachineNames(syncConfig.entries),
28
+ globalConfigExists: globalConfig !== undefined,
29
+ globalConfigPath: context.paths.globalConfigPath,
30
+ syncDirectory: context.paths.syncDirectory,
31
+ };
32
+ };
33
+ export const useSyncMachine = async (machine, context) => {
34
+ const normalizedMachine = normalizeSyncMachineName(machine);
35
+ await ensureSyncRepository(context);
36
+ const syncConfig = await readSyncConfig(context.paths.syncDirectory, context.environment);
37
+ const knownMachines = collectAllMachineNames(syncConfig.entries);
38
+ const warning = knownMachines.includes(normalizedMachine)
39
+ ? undefined
40
+ : `Machine '${normalizedMachine}' is not referenced by any tracked entry.`;
41
+ await writeTextFileAtomically(context.paths.globalConfigPath, formatGlobalDevsyncConfig({
42
+ activeMachine: normalizedMachine,
43
+ version: 3,
44
+ }));
45
+ return {
46
+ activeMachine: normalizedMachine,
47
+ globalConfigPath: context.paths.globalConfigPath,
48
+ mode: "use",
49
+ machine: normalizedMachine,
50
+ syncDirectory: context.paths.syncDirectory,
51
+ ...(warning !== undefined ? { warning } : {}),
52
+ };
53
+ };
54
+ export const clearSyncMachines = async (context) => {
55
+ await ensureSyncRepository(context);
56
+ await writeTextFileAtomically(context.paths.globalConfigPath, formatGlobalDevsyncConfig({ version: 3 }));
57
+ return {
58
+ globalConfigPath: context.paths.globalConfigPath,
59
+ mode: "clear",
60
+ syncDirectory: context.paths.syncDirectory,
61
+ };
62
+ };
63
+ export const assignSyncMachines = async (request, context) => {
64
+ const target = request.target.trim();
65
+ if (target.length === 0) {
66
+ throw new DevsyncError("Target path is required.", {
67
+ code: "TARGET_REQUIRED",
68
+ hint: "Pass a tracked entry path, for example 'devsync track ~/.gitconfig --machine default --machine work'.",
69
+ });
70
+ }
71
+ await ensureSyncRepository(context);
72
+ const config = await readSyncConfig(context.paths.syncDirectory, context.environment);
73
+ const entry = resolveTrackedEntry(target, config.entries, context);
74
+ if (entry === undefined) {
75
+ throw new DevsyncError(`No tracked sync entry matches: ${target}`, {
76
+ code: "TARGET_NOT_TRACKED",
77
+ hint: "Track the root first with 'devsync track'.",
78
+ });
79
+ }
80
+ const normalizedMachines = request.machines.map((m) => normalizeSyncMachineName(m));
81
+ if (entry.machines.length === normalizedMachines.length &&
82
+ normalizedMachines.every((m) => entry.machines.includes(m))) {
83
+ return {
84
+ action: "unchanged",
85
+ configPath: context.paths.configPath,
86
+ entryRepoPath: entry.repoPath,
87
+ machines: normalizedMachines,
88
+ syncDirectory: context.paths.syncDirectory,
89
+ };
90
+ }
91
+ const nextConfig = createSyncConfigDocument({
92
+ ...config,
93
+ entries: config.entries.map((e) => {
94
+ if (e.repoPath !== entry.repoPath) {
95
+ return e;
96
+ }
97
+ return {
98
+ ...e,
99
+ machines: normalizedMachines,
100
+ machinesExplicit: normalizedMachines.length > 0,
101
+ };
102
+ }),
103
+ });
104
+ await writeValidatedSyncConfig(context.paths.syncDirectory, nextConfig, context.environment);
105
+ return {
106
+ action: "assigned",
107
+ configPath: context.paths.configPath,
108
+ entryRepoPath: entry.repoPath,
109
+ machines: normalizedMachines,
110
+ syncDirectory: context.paths.syncDirectory,
111
+ };
112
+ };
113
+ //# sourceMappingURL=machine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"machine.js","sourceRoot":"","sources":["../../src/services/machine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import { type ResolvedSyncConfigEntry } from "#app/config/sync.js";
2
+ export { buildDirectoryKey, doPathsOverlap, isExplicitLocalPath, isPathEqualOrNested, } from "#app/lib/path.js";
3
+ export declare const resolveCommandTargetPath: (target: string, environment: NodeJS.ProcessEnv, cwd: string) => string;
4
+ export declare const buildRepoPathWithinRoot: (absolutePath: string, rootPath: string, description: string) => string;
5
+ export declare const buildConfiguredHomeLocalPath: (repoPath: string) => string;
6
+ export declare const tryBuildRepoPathWithinRoot: (absolutePath: string, rootPath: string, description: string) => string | undefined;
7
+ export declare const tryNormalizeRepoPathInput: (value: string) => string | undefined;
8
+ export declare const resolveTrackedEntry: (target: string, entries: readonly ResolvedSyncConfigEntry[], context: Readonly<{
9
+ cwd: string;
10
+ environment: NodeJS.ProcessEnv;
11
+ }>) => ResolvedSyncConfigEntry | undefined;
12
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/services/paths.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,uBAAuB,EAC7B,MAAM,qBAAqB,CAAC;AAK7B,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,kBAAkB,CAAC;AAI1B,eAAO,MAAM,wBAAwB,GACnC,QAAQ,MAAM,EACd,aAAa,MAAM,CAAC,UAAU,EAC9B,KAAK,MAAM,WAGZ,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAClC,cAAc,MAAM,EACpB,UAAU,MAAM,EAChB,aAAa,MAAM,WA+BpB,CAAC;AAEF,eAAO,MAAM,4BAA4B,GAAI,UAAU,MAAM,WAE5D,CAAC;AAEF,eAAO,MAAM,0BAA0B,GACrC,cAAc,MAAM,EACpB,UAAU,MAAM,EAChB,aAAa,MAAM,uBAOpB,CAAC;AAEF,eAAO,MAAM,yBAAyB,GAAI,OAAO,MAAM,uBAMtD,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAC9B,QAAQ,MAAM,EACd,SAAS,SAAS,uBAAuB,EAAE,EAC3C,SAAS,QAAQ,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC,UAAU,CAAA;CAAE,CAAC,KACjE,uBAAuB,GAAG,SA8B5B,CAAC"}
@@ -0,0 +1,71 @@
1
+ import { isAbsolute, relative, resolve } from "node:path";
2
+ import { normalizeSyncRepoPath, } from "#app/config/sync.js";
3
+ import { expandHomePath } from "#app/config/xdg.js";
4
+ import { isExplicitLocalPath } from "#app/lib/path.js";
5
+ export { buildDirectoryKey, doPathsOverlap, isExplicitLocalPath, isPathEqualOrNested, } from "#app/lib/path.js";
6
+ import { DevsyncError } from "./error.js";
7
+ export const resolveCommandTargetPath = (target, environment, cwd) => {
8
+ return resolve(cwd, expandHomePath(target, environment));
9
+ };
10
+ export const buildRepoPathWithinRoot = (absolutePath, rootPath, description) => {
11
+ const relativePath = relative(rootPath, absolutePath);
12
+ if (relativePath === "") {
13
+ throw new DevsyncError(`${description} resolves to the root directory, which cannot be tracked directly.`, {
14
+ code: "TARGET_ROOT_DISALLOWED",
15
+ details: [`Target: ${absolutePath}`, `Root: ${rootPath}`],
16
+ hint: `Choose a file or subdirectory inside ${rootPath}.`,
17
+ });
18
+ }
19
+ if (isAbsolute(relativePath) ||
20
+ relativePath.startsWith("..") ||
21
+ relativePath === "..") {
22
+ throw new DevsyncError(`${description} must stay inside the configured home root.`, {
23
+ code: "TARGET_OUTSIDE_ROOT",
24
+ details: [`Target: ${absolutePath}`, `Allowed root: ${rootPath}`],
25
+ hint: `Use a path inside ${rootPath}.`,
26
+ });
27
+ }
28
+ return normalizeSyncRepoPath(relativePath);
29
+ };
30
+ export const buildConfiguredHomeLocalPath = (repoPath) => {
31
+ return `~/${repoPath}`;
32
+ };
33
+ export const tryBuildRepoPathWithinRoot = (absolutePath, rootPath, description) => {
34
+ try {
35
+ return buildRepoPathWithinRoot(absolutePath, rootPath, description);
36
+ }
37
+ catch {
38
+ return undefined;
39
+ }
40
+ };
41
+ export const tryNormalizeRepoPathInput = (value) => {
42
+ try {
43
+ return normalizeSyncRepoPath(value);
44
+ }
45
+ catch {
46
+ return undefined;
47
+ }
48
+ };
49
+ export const resolveTrackedEntry = (target, entries, context) => {
50
+ const resolvedTargetPath = resolveCommandTargetPath(target, context.environment, context.cwd);
51
+ const byLocalPath = entries.filter((entry) => entry.localPath === resolvedTargetPath);
52
+ let matches;
53
+ if (byLocalPath.length > 0 || isExplicitLocalPath(target)) {
54
+ matches = byLocalPath;
55
+ }
56
+ else {
57
+ const normalizedRepoPath = tryNormalizeRepoPathInput(target);
58
+ matches =
59
+ normalizedRepoPath === undefined
60
+ ? []
61
+ : entries.filter((entry) => entry.repoPath === normalizedRepoPath);
62
+ }
63
+ if (matches.length > 1) {
64
+ throw new DevsyncError(`Multiple tracked sync entries match: ${target}`, {
65
+ code: "TARGET_CONFLICT",
66
+ hint: "Use an explicit local path to choose the tracked entry.",
67
+ });
68
+ }
69
+ return matches[0];
70
+ };
71
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/services/paths.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import { buildEntryMaterialization, buildPullCounts } from "./local-materialization.js";
2
+ import { type EffectiveSyncConfig, type SyncContext } from "./runtime.js";
3
+ export type SyncPullRequest = Readonly<{
4
+ dryRun: boolean;
5
+ machine?: string;
6
+ }>;
7
+ export type SyncPullResult = Readonly<{
8
+ configPath: string;
9
+ decryptedFileCount: number;
10
+ deletedLocalCount: number;
11
+ directoryCount: number;
12
+ dryRun: boolean;
13
+ plainFileCount: number;
14
+ symlinkCount: number;
15
+ syncDirectory: string;
16
+ }>;
17
+ export type PullPlan = Readonly<{
18
+ counts: ReturnType<typeof buildPullCounts>;
19
+ deletedLocalCount: number;
20
+ desiredKeys: ReadonlySet<string>;
21
+ existingKeys: ReadonlySet<string>;
22
+ materializations: readonly ReturnType<typeof buildEntryMaterialization>[];
23
+ }>;
24
+ export declare const buildPullPlan: (config: EffectiveSyncConfig, context: SyncContext) => Promise<PullPlan>;
25
+ export declare const buildPullPlanPreview: (plan: PullPlan) => string[];
26
+ export declare const buildPullResultFromPlan: (plan: PullPlan, context: SyncContext, dryRun: boolean) => SyncPullResult;
27
+ export declare const pullSync: (request: SyncPullRequest, context: SyncContext) => Promise<SyncPullResult>;
28
+ //# sourceMappingURL=pull.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../src/services/pull.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,yBAAyB,EACzB,eAAe,EAEhB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACL,KAAK,mBAAmB,EAGxB,KAAK,WAAW,EACjB,MAAM,cAAc,CAAC;AAEtB,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC;IACrC,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,OAAO,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC,CAAC;AAEH,MAAM,MAAM,QAAQ,GAAG,QAAQ,CAAC;IAC9B,MAAM,EAAE,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;IAC3C,iBAAiB,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACjC,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAClC,gBAAgB,EAAE,SAAS,UAAU,CAAC,OAAO,yBAAyB,CAAC,EAAE,CAAC;CAC3E,CAAC,CAAC;AAEH,eAAO,MAAM,aAAa,GACxB,QAAQ,mBAAmB,EAC3B,SAAS,WAAW,KACnB,OAAO,CAAC,QAAQ,CAmClB,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,MAAM,QAAQ,aAalD,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAClC,MAAM,QAAQ,EACd,SAAS,WAAW,EACpB,QAAQ,OAAO,KACd,cAQF,CAAC;AAEF,eAAO,MAAM,QAAQ,GACnB,SAAS,eAAe,EACxB,SAAS,WAAW,KACnB,OAAO,CAAC,cAAc,CAsBxB,CAAC"}
@@ -0,0 +1,67 @@
1
+ import { applyEntryMaterialization, buildEntryMaterialization, buildPullCounts, countDeletedLocalNodes, } from "./local-materialization.js";
2
+ import { buildRepositorySnapshot } from "./repo-snapshot.js";
3
+ import { ensureSyncRepository, loadSyncConfig, } from "./runtime.js";
4
+ export const buildPullPlan = async (config, context) => {
5
+ const snapshot = await buildRepositorySnapshot(context.paths.syncDirectory, config);
6
+ const materializations = config.entries.map((entry) => {
7
+ return buildEntryMaterialization(entry, snapshot);
8
+ });
9
+ let deletedLocalCount = 0;
10
+ const existingKeys = new Set();
11
+ for (let index = 0; index < config.entries.length; index += 1) {
12
+ const entry = config.entries[index];
13
+ const materialization = materializations[index];
14
+ if (entry === undefined || materialization === undefined) {
15
+ continue;
16
+ }
17
+ deletedLocalCount += await countDeletedLocalNodes(entry, materialization.desiredKeys, config, existingKeys);
18
+ }
19
+ return {
20
+ counts: buildPullCounts(materializations),
21
+ deletedLocalCount,
22
+ desiredKeys: new Set(materializations.flatMap((m) => [...m.desiredKeys])),
23
+ existingKeys,
24
+ materializations,
25
+ };
26
+ };
27
+ export const buildPullPlanPreview = (plan) => {
28
+ const desired = [...plan.desiredKeys].sort((left, right) => {
29
+ return left.localeCompare(right);
30
+ });
31
+ const deleted = [...plan.existingKeys]
32
+ .filter((key) => {
33
+ return !plan.desiredKeys.has(key);
34
+ })
35
+ .sort((left, right) => {
36
+ return left.localeCompare(right);
37
+ });
38
+ return [...desired.slice(0, 4), ...deleted.slice(0, 4)].slice(0, 6);
39
+ };
40
+ export const buildPullResultFromPlan = (plan, context, dryRun) => {
41
+ return {
42
+ configPath: context.paths.configPath,
43
+ deletedLocalCount: plan.deletedLocalCount,
44
+ dryRun,
45
+ syncDirectory: context.paths.syncDirectory,
46
+ ...plan.counts,
47
+ };
48
+ };
49
+ export const pullSync = async (request, context) => {
50
+ await ensureSyncRepository(context);
51
+ const { effectiveConfig: config } = await loadSyncConfig(context, {
52
+ ...(request.machine === undefined ? {} : { machine: request.machine }),
53
+ });
54
+ const plan = await buildPullPlan(config, context);
55
+ for (let index = 0; index < config.entries.length; index += 1) {
56
+ const entry = config.entries[index];
57
+ const materialization = plan.materializations[index];
58
+ if (entry === undefined || materialization === undefined) {
59
+ continue;
60
+ }
61
+ if (!request.dryRun) {
62
+ await applyEntryMaterialization(entry, materialization, config);
63
+ }
64
+ }
65
+ return buildPullResultFromPlan(plan, context, request.dryRun);
66
+ };
67
+ //# sourceMappingURL=pull.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pull.js","sourceRoot":"","sources":["../../src/services/pull.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import { type SnapshotNode } from "./local-snapshot.js";
2
+ import { type EffectiveSyncConfig, type SyncContext } from "./runtime.js";
3
+ export type SyncPushRequest = Readonly<{
4
+ dryRun: boolean;
5
+ machine?: string;
6
+ }>;
7
+ export type SyncPushResult = Readonly<{
8
+ configPath: string;
9
+ deletedArtifactCount: number;
10
+ directoryCount: number;
11
+ dryRun: boolean;
12
+ encryptedFileCount: number;
13
+ plainFileCount: number;
14
+ symlinkCount: number;
15
+ syncDirectory: string;
16
+ }>;
17
+ export type PushPlan = Readonly<{
18
+ counts: ReturnType<typeof buildPushCounts>;
19
+ deletedArtifactCount: number;
20
+ desiredArtifactKeys: ReadonlySet<string>;
21
+ existingArtifactKeys: ReadonlySet<string>;
22
+ snapshot: ReadonlyMap<string, SnapshotNode>;
23
+ }>;
24
+ declare const buildPushCounts: (snapshot: ReadonlyMap<string, SnapshotNode>) => {
25
+ directoryCount: number;
26
+ encryptedFileCount: number;
27
+ plainFileCount: number;
28
+ symlinkCount: number;
29
+ };
30
+ export declare const buildPushPlan: (config: EffectiveSyncConfig, context: SyncContext) => Promise<PushPlan>;
31
+ export declare const buildPushPlanPreview: (plan: PushPlan) => string[];
32
+ export declare const buildPushResultFromPlan: (plan: PushPlan, context: SyncContext, dryRun: boolean) => SyncPushResult;
33
+ export declare const pushSync: (request: SyncPushRequest, context: SyncContext) => Promise<SyncPushResult>;
34
+ export {};
35
+ //# sourceMappingURL=push.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../../src/services/push.ts"],"names":[],"mappings":"AAKA,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAO5E,OAAO,EACL,KAAK,mBAAmB,EAGxB,KAAK,WAAW,EACjB,MAAM,cAAc,CAAC;AAEtB,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC;IACrC,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,OAAO,CAAC;IAChB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC,CAAC;AAEH,MAAM,MAAM,QAAQ,GAAG,QAAQ,CAAC;IAC9B,MAAM,EAAE,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;IAC3C,oBAAoB,EAAE,MAAM,CAAC;IAC7B,mBAAmB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACzC,oBAAoB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC1C,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;CAC7C,CAAC,CAAC;AAEH,QAAA,MAAM,eAAe,GAAI,UAAU,WAAW,CAAC,MAAM,EAAE,YAAY,CAAC;;;;;CA8BnE,CAAC;AAEF,eAAO,MAAM,aAAa,GACxB,QAAQ,mBAAmB,EAC3B,SAAS,WAAW,KACnB,OAAO,CAAC,QAAQ,CAuBlB,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,MAAM,QAAQ,aAalD,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAClC,MAAM,QAAQ,EACd,SAAS,WAAW,EACpB,QAAQ,OAAO,KACd,cAQF,CAAC;AAEF,eAAO,MAAM,QAAQ,GACnB,SAAS,eAAe,EACxB,SAAS,WAAW,KACnB,OAAO,CAAC,cAAc,CA8BxB,CAAC"}
@@ -0,0 +1,96 @@
1
+ import { join } from "node:path";
2
+ import { resolveSyncArtifactsDirectoryPath } from "#app/config/sync.js";
3
+ import { removePathAtomically } from "./filesystem.js";
4
+ import { buildLocalSnapshot } from "./local-snapshot.js";
5
+ import { buildArtifactKey, buildRepoArtifacts, collectExistingArtifactKeys, writeArtifactsToDirectory, } from "./repo-artifacts.js";
6
+ import { ensureSyncRepository, loadSyncConfig, } from "./runtime.js";
7
+ const buildPushCounts = (snapshot) => {
8
+ let directoryCount = 0;
9
+ let encryptedFileCount = 0;
10
+ let plainFileCount = 0;
11
+ let symlinkCount = 0;
12
+ for (const node of snapshot.values()) {
13
+ if (node.type === "directory") {
14
+ directoryCount += 1;
15
+ continue;
16
+ }
17
+ if (node.type === "symlink") {
18
+ symlinkCount += 1;
19
+ continue;
20
+ }
21
+ if (node.secret) {
22
+ encryptedFileCount += 1;
23
+ }
24
+ else {
25
+ plainFileCount += 1;
26
+ }
27
+ }
28
+ return {
29
+ directoryCount,
30
+ encryptedFileCount,
31
+ plainFileCount,
32
+ symlinkCount,
33
+ };
34
+ };
35
+ export const buildPushPlan = async (config, context) => {
36
+ const snapshot = await buildLocalSnapshot(config);
37
+ const artifacts = await buildRepoArtifacts(snapshot, config);
38
+ const desiredArtifactKeys = new Set(artifacts.map((artifact) => {
39
+ return buildArtifactKey(artifact);
40
+ }));
41
+ const existingArtifactKeys = await collectExistingArtifactKeys(context.paths.syncDirectory, config);
42
+ const deletedArtifactCount = [...existingArtifactKeys].filter((key) => {
43
+ return !desiredArtifactKeys.has(key);
44
+ }).length;
45
+ return {
46
+ counts: buildPushCounts(snapshot),
47
+ deletedArtifactCount,
48
+ desiredArtifactKeys,
49
+ existingArtifactKeys,
50
+ snapshot,
51
+ };
52
+ };
53
+ export const buildPushPlanPreview = (plan) => {
54
+ const createdOrUpdated = [...plan.snapshot.keys()].sort((left, right) => {
55
+ return left.localeCompare(right);
56
+ });
57
+ const deleted = [...plan.existingArtifactKeys]
58
+ .filter((key) => {
59
+ return !plan.desiredArtifactKeys.has(key);
60
+ })
61
+ .sort((left, right) => {
62
+ return left.localeCompare(right);
63
+ });
64
+ return [...createdOrUpdated.slice(0, 4), ...deleted.slice(0, 4)].slice(0, 6);
65
+ };
66
+ export const buildPushResultFromPlan = (plan, context, dryRun) => {
67
+ return {
68
+ configPath: context.paths.configPath,
69
+ deletedArtifactCount: plan.deletedArtifactCount,
70
+ dryRun,
71
+ syncDirectory: context.paths.syncDirectory,
72
+ ...plan.counts,
73
+ };
74
+ };
75
+ export const pushSync = async (request, context) => {
76
+ await ensureSyncRepository(context);
77
+ const { effectiveConfig: config } = await loadSyncConfig(context, {
78
+ ...(request.machine === undefined ? {} : { machine: request.machine }),
79
+ });
80
+ const plan = await buildPushPlan(config, context);
81
+ if (!request.dryRun) {
82
+ const artifactsDirectory = resolveSyncArtifactsDirectoryPath(context.paths.syncDirectory);
83
+ const artifacts = await buildRepoArtifacts(plan.snapshot, config);
84
+ for (const staleKey of [...plan.existingArtifactKeys].filter((key) => {
85
+ return !plan.desiredArtifactKeys.has(key);
86
+ })) {
87
+ const relativePath = staleKey.endsWith("/")
88
+ ? staleKey.slice(0, -1)
89
+ : staleKey;
90
+ await removePathAtomically(join(artifactsDirectory, ...relativePath.split("/")));
91
+ }
92
+ await writeArtifactsToDirectory(artifactsDirectory, artifacts, config.age);
93
+ }
94
+ return buildPushResultFromPlan(plan, context, request.dryRun);
95
+ };
96
+ //# sourceMappingURL=push.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"push.js","sourceRoot":"","sources":["../../src/services/push.ts"],"names":[],"mappings":"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"}