@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,34 @@
1
+ import { formatSyncConfig, parseSyncConfig, resolveSyncConfigFilePath, } from "#app/config/sync.js";
2
+ import { writeTextFileAtomically } from "./filesystem.js";
3
+ export const sortSyncConfigEntries = (entries) => {
4
+ return [...entries].sort((left, right) => {
5
+ return left.localPath.localeCompare(right.localPath);
6
+ });
7
+ };
8
+ export const createSyncConfigDocument = (config) => {
9
+ const entries = sortSyncConfigEntries(config.entries.map((entry) => ({
10
+ kind: entry.kind,
11
+ localPath: entry.configuredLocalPath,
12
+ ...(entry.modeExplicit ? { mode: entry.mode } : {}),
13
+ ...(entry.machinesExplicit ? { machines: [...entry.machines] } : {}),
14
+ })));
15
+ return {
16
+ version: 6,
17
+ ...(config.age === undefined
18
+ ? {}
19
+ : {
20
+ age: {
21
+ identityFile: config.age.identityFile,
22
+ recipients: [...config.age.recipients],
23
+ },
24
+ }),
25
+ entries,
26
+ };
27
+ };
28
+ export const writeValidatedSyncConfig = async (syncDirectory, config, environment) => {
29
+ const resolvedConfig = parseSyncConfig(config, environment);
30
+ const nextConfig = createSyncConfigDocument(resolvedConfig);
31
+ await writeTextFileAtomically(resolveSyncConfigFilePath(syncDirectory), formatSyncConfig(nextConfig));
32
+ return nextConfig;
33
+ };
34
+ //# sourceMappingURL=config-file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-file.js","sourceRoot":"","sources":["../../src/services/config-file.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,eAAe,EAEf,yBAAyB,GAE1B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAE1D,MAAM,CAAC,MAAM,qBAAqB,GAAG,CACnC,OAAiD,EACjD,EAAE;IACF,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QACvC,OAAO,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,wBAAwB,GAAG,CACtC,MAA0B,EACd,EAAE;IACd,MAAM,OAAO,GAAG,qBAAqB,CACnC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAiC,EAAE,CAAC,CAAC;QAC5D,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,SAAS,EAAE,KAAK,CAAC,mBAAmB;QACpC,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnD,GAAG,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACrE,CAAC,CAAC,CACJ,CAAC;IAEF,OAAO;QACL,OAAO,EAAE,CAAC;QACV,GAAG,CAAC,MAAM,CAAC,GAAG,KAAK,SAAS;YAC1B,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC;gBACE,GAAG,EAAE;oBACH,YAAY,EAAE,MAAM,CAAC,GAAG,CAAC,YAAY;oBACrC,UAAU,EAAE,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC;iBACvC;aACF,CAAC;QACN,OAAO;KACM,CAAC;AAClB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,wBAAwB,GAAG,KAAK,EAC3C,aAAqB,EACrB,MAAkB,EAClB,WAA8B,EAC9B,EAAE;IACF,MAAM,cAAc,GAAG,eAAe,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC5D,MAAM,UAAU,GAAG,wBAAwB,CAAC,cAAc,CAAC,CAAC;IAE5D,MAAM,uBAAuB,CAC3B,yBAAyB,CAAC,aAAa,CAAC,EACxC,gBAAgB,CAAC,UAAU,CAAC,CAC7B,CAAC;IAEF,OAAO,UAAU,CAAC;AACpB,CAAC,CAAC"}
@@ -0,0 +1,9 @@
1
+ export declare const readAgeIdentityLines: (identityFile: string) => Promise<string[]>;
2
+ export declare const readAgeRecipientsFromIdentityFile: (identityFile: string) => Promise<string[]>;
3
+ export declare const createAgeIdentityFile: (identityFile: string) => Promise<{
4
+ identity: string;
5
+ recipient: string;
6
+ }>;
7
+ export declare const encryptSecretFile: (contents: Uint8Array, recipients: readonly string[]) => Promise<string>;
8
+ export declare const decryptSecretFile: (armoredCiphertext: string, identityFile: string) => Promise<Uint8Array<ArrayBufferLike>>;
9
+ //# sourceMappingURL=crypto.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../../src/services/crypto.ts"],"names":[],"mappings":"AAcA,eAAO,MAAM,oBAAoB,GAAU,cAAc,MAAM,sBAqB9D,CAAC;AAEF,eAAO,MAAM,iCAAiC,GAC5C,cAAc,MAAM,sBAwBrB,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAU,cAAc,MAAM;;;EAW/D,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC5B,UAAU,UAAU,EACpB,YAAY,SAAS,MAAM,EAAE,oBAW9B,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC5B,mBAAmB,MAAM,EACzB,cAAc,MAAM,yCAkBrB,CAAC"}
@@ -0,0 +1,75 @@
1
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
2
+ import { dirname } from "node:path";
3
+ import { armor, Decrypter, Encrypter, generateIdentity, identityToRecipient, } from "age-encryption";
4
+ import { ensureTrailingNewline } from "#app/lib/string.js";
5
+ import { DevsyncError, wrapUnknownError } from "#app/services/error.js";
6
+ export const readAgeIdentityLines = async (identityFile) => {
7
+ const contents = await readFile(identityFile, "utf8");
8
+ const identities = contents
9
+ .split(/\r?\n/u)
10
+ .map((line) => line.trim())
11
+ .filter((line) => {
12
+ return line !== "" && !line.startsWith("#");
13
+ });
14
+ if (identities.length === 0) {
15
+ throw new DevsyncError("No age identities were found in the configured identity file.", {
16
+ code: "AGE_IDENTITY_EMPTY",
17
+ details: [`Identity file: ${identityFile}`],
18
+ hint: "Add at least one age private key to the identity file, or run 'devsync init' to generate one.",
19
+ });
20
+ }
21
+ return identities;
22
+ };
23
+ export const readAgeRecipientsFromIdentityFile = async (identityFile) => {
24
+ const identities = await readAgeIdentityLines(identityFile);
25
+ let recipients;
26
+ try {
27
+ recipients = await Promise.all(identities.map(async (identity) => {
28
+ return await identityToRecipient(identity);
29
+ }));
30
+ }
31
+ catch (error) {
32
+ throw wrapUnknownError("Failed to read age recipients from the configured identity file.", error, {
33
+ code: "AGE_RECIPIENT_READ_FAILED",
34
+ details: [`Identity file: ${identityFile}`],
35
+ hint: "Check that the identity file contains valid age private keys.",
36
+ });
37
+ }
38
+ return [...new Set(recipients)];
39
+ };
40
+ export const createAgeIdentityFile = async (identityFile) => {
41
+ const identity = await generateIdentity();
42
+ const recipient = await identityToRecipient(identity);
43
+ await mkdir(dirname(identityFile), { recursive: true });
44
+ await writeFile(identityFile, ensureTrailingNewline(identity), "utf8");
45
+ return {
46
+ identity,
47
+ recipient,
48
+ };
49
+ };
50
+ export const encryptSecretFile = async (contents, recipients) => {
51
+ const encrypter = new Encrypter();
52
+ for (const recipient of recipients) {
53
+ encrypter.addRecipient(recipient);
54
+ }
55
+ const ciphertext = await encrypter.encrypt(contents);
56
+ return armor.encode(ciphertext);
57
+ };
58
+ export const decryptSecretFile = async (armoredCiphertext, identityFile) => {
59
+ const decrypter = new Decrypter();
60
+ const identities = await readAgeIdentityLines(identityFile);
61
+ for (const identity of identities) {
62
+ decrypter.addIdentity(identity);
63
+ }
64
+ try {
65
+ return await decrypter.decrypt(armor.decode(armoredCiphertext));
66
+ }
67
+ catch (error) {
68
+ throw wrapUnknownError("Failed to decrypt a secret artifact.", error, {
69
+ code: "AGE_DECRYPT_FAILED",
70
+ details: [`Identity file: ${identityFile}`],
71
+ hint: "Check that the artifact is valid age data and that the configured identity file matches one of its recipients.",
72
+ });
73
+ }
74
+ };
75
+ //# sourceMappingURL=crypto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.js","sourceRoot":"","sources":["../../src/services/crypto.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { type SyncContext } from "./runtime.js";
2
+ export type DoctorCheckLevel = "fail" | "ok" | "warn";
3
+ export type DoctorCheck = Readonly<{
4
+ detail: string;
5
+ level: DoctorCheckLevel;
6
+ name: string;
7
+ }>;
8
+ export type SyncDoctorResult = Readonly<{
9
+ checks: readonly DoctorCheck[];
10
+ configPath: string;
11
+ hasFailures: boolean;
12
+ hasWarnings: boolean;
13
+ syncDirectory: string;
14
+ }>;
15
+ export declare const runSyncDoctor: (context: SyncContext) => Promise<SyncDoctorResult>;
16
+ //# sourceMappingURL=doctor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/services/doctor.ts"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,WAAW,EACjB,MAAM,cAAc,CAAC;AAEtB,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,CAAC;AAEtD,MAAM,MAAM,WAAW,GAAG,QAAQ,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,gBAAgB,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC;IACtC,MAAM,EAAE,SAAS,WAAW,EAAE,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC,CAAC;AAoBH,eAAO,MAAM,aAAa,GACxB,SAAS,WAAW,KACnB,OAAO,CAAC,gBAAgB,CAyG1B,CAAC"}
@@ -0,0 +1,84 @@
1
+ import { pathExists } from "./filesystem.js";
2
+ import { ensureRepository } from "./git.js";
3
+ import { loadSyncConfig, } from "./runtime.js";
4
+ const ok = (name, detail) => ({
5
+ detail,
6
+ level: "ok",
7
+ name,
8
+ });
9
+ const warn = (name, detail) => ({
10
+ detail,
11
+ level: "warn",
12
+ name,
13
+ });
14
+ const fail = (name, detail) => ({
15
+ detail,
16
+ level: "fail",
17
+ name,
18
+ });
19
+ export const runSyncDoctor = async (context) => {
20
+ const checks = [];
21
+ try {
22
+ await ensureRepository(context.paths.syncDirectory);
23
+ checks.push(ok("git", "Sync directory is a git repository."));
24
+ }
25
+ catch (error) {
26
+ checks.push(fail("git", error instanceof Error ? error.message : "Git repository check failed."));
27
+ return {
28
+ checks,
29
+ configPath: context.paths.configPath,
30
+ hasFailures: true,
31
+ hasWarnings: false,
32
+ syncDirectory: context.paths.syncDirectory,
33
+ };
34
+ }
35
+ let config;
36
+ try {
37
+ const { effectiveConfig, fullConfig } = await loadSyncConfig(context);
38
+ config = effectiveConfig;
39
+ checks.push(ok("config", `Loaded config with ${fullConfig.entries.length} entries and ${effectiveConfig.age.recipients.length} recipients.`));
40
+ checks.push(ok("machines", effectiveConfig.activeMachine === undefined
41
+ ? "No active machine configured."
42
+ : `Active machine: ${effectiveConfig.activeMachine}.`));
43
+ }
44
+ catch (error) {
45
+ checks.push(fail("config", error instanceof Error
46
+ ? error.message
47
+ : "Sync configuration could not be read."));
48
+ return {
49
+ checks,
50
+ configPath: context.paths.configPath,
51
+ hasFailures: true,
52
+ hasWarnings: false,
53
+ syncDirectory: context.paths.syncDirectory,
54
+ };
55
+ }
56
+ checks.push((await pathExists(config.age.identityFile))
57
+ ? ok("age", `Age identity file exists at ${config.age.identityFile}.`)
58
+ : fail("age", `Age identity file is missing: ${config.age.identityFile}`));
59
+ checks.push(config.entries.length === 0
60
+ ? warn("entries", "No sync entries are configured yet.")
61
+ : ok("entries", `Tracked ${config.entries.length} sync entries.`));
62
+ const missingEntries = config.entries.filter((entry) => {
63
+ return !context.environment || entry.localPath.length > 0;
64
+ });
65
+ let missingCount = 0;
66
+ for (const entry of missingEntries) {
67
+ if (!(await pathExists(entry.localPath))) {
68
+ missingCount += 1;
69
+ }
70
+ }
71
+ checks.push(missingCount === 0
72
+ ? ok("local-paths", "All tracked local paths currently exist.")
73
+ : warn("local-paths", `${missingCount} tracked local path${missingCount === 1 ? " is" : "s are"} missing.`));
74
+ const hasFailures = checks.some((check) => check.level === "fail");
75
+ const hasWarnings = checks.some((check) => check.level === "warn");
76
+ return {
77
+ checks,
78
+ configPath: context.paths.configPath,
79
+ hasFailures,
80
+ hasWarnings,
81
+ syncDirectory: context.paths.syncDirectory,
82
+ };
83
+ };
84
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/services/doctor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ export type DevsyncErrorOptions = Readonly<{
2
+ code?: string;
3
+ details?: readonly string[];
4
+ hint?: string;
5
+ }>;
6
+ export declare class DevsyncError extends Error {
7
+ readonly code?: string;
8
+ readonly details: readonly string[];
9
+ readonly hint?: string;
10
+ constructor(message: string, options?: DevsyncErrorOptions);
11
+ }
12
+ export declare const formatDevsyncError: (error: DevsyncError | Error | string) => string;
13
+ export declare const wrapUnknownError: (message: string, error: unknown, options?: DevsyncErrorOptions) => DevsyncError;
14
+ //# sourceMappingURL=error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../src/services/error.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,mBAAmB,GAAG,QAAQ,CAAC;IACzC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC,CAAC;AAQH,qBAAa,YAAa,SAAQ,KAAK;IACrC,SAAgB,IAAI,CAAC,EAAE,MAAM,CAAC;IAC9B,SAAgB,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C,SAAgB,IAAI,CAAC,EAAE,MAAM,CAAC;gBAEX,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,mBAAwB;CAOtE;AAED,eAAO,MAAM,kBAAkB,GAAI,OAAO,YAAY,GAAG,KAAK,GAAG,MAAM,WActE,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAC3B,SAAS,MAAM,EACf,OAAO,OAAO,EACd,UAAS,mBAAwB,iBAQlC,CAAC"}
@@ -0,0 +1,38 @@
1
+ const compactLines = (lines) => {
2
+ return lines.filter((line) => {
3
+ return typeof line === "string" && line.trim().length > 0;
4
+ });
5
+ };
6
+ export class DevsyncError extends Error {
7
+ code;
8
+ details;
9
+ hint;
10
+ constructor(message, options = {}) {
11
+ super(message);
12
+ this.name = "DevsyncError";
13
+ this.code = options.code;
14
+ this.details = options.details ?? [];
15
+ this.hint = options.hint;
16
+ }
17
+ }
18
+ export const formatDevsyncError = (error) => {
19
+ if (typeof error === "string") {
20
+ return error;
21
+ }
22
+ if (!(error instanceof DevsyncError)) {
23
+ return error.message;
24
+ }
25
+ return compactLines([
26
+ error.message,
27
+ ...error.details,
28
+ error.hint === undefined ? undefined : `Hint: ${error.hint}`,
29
+ ]).join("\n");
30
+ };
31
+ export const wrapUnknownError = (message, error, options = {}) => {
32
+ const detail = error instanceof Error ? error.message.trim() : String(error);
33
+ return new DevsyncError(message, {
34
+ ...options,
35
+ details: compactLines([...(options.details ?? []), detail]),
36
+ });
37
+ };
38
+ //# sourceMappingURL=error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error.js","sourceRoot":"","sources":["../../src/services/error.ts"],"names":[],"mappings":"AAMA,MAAM,YAAY,GAAG,CAAC,KAAsC,EAAE,EAAE;IAC9D,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAkB,EAAE;QAC3C,OAAO,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,OAAO,YAAa,SAAQ,KAAK;IACrB,IAAI,CAAU;IACd,OAAO,CAAoB;IAC3B,IAAI,CAAU;IAE9B,YAAmB,OAAe,EAAE,UAA+B,EAAE;QACnE,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;QAC3B,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QACzB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC;QACrC,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAC3B,CAAC;CACF;AAED,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,KAAoC,EAAE,EAAE;IACzE,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,CAAC,CAAC,KAAK,YAAY,YAAY,CAAC,EAAE,CAAC;QACrC,OAAO,KAAK,CAAC,OAAO,CAAC;IACvB,CAAC;IAED,OAAO,YAAY,CAAC;QAClB,KAAK,CAAC,OAAO;QACb,GAAG,KAAK,CAAC,OAAO;QAChB,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,KAAK,CAAC,IAAI,EAAE;KAC7D,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,OAAe,EACf,KAAc,EACd,UAA+B,EAAE,EACjC,EAAE;IACF,MAAM,MAAM,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAE7E,OAAO,IAAI,YAAY,CAAC,OAAO,EAAE;QAC/B,GAAG,OAAO;QACV,OAAO,EAAE,YAAY,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;KAC5D,CAAC,CAAC;AACL,CAAC,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { lstat } from "node:fs/promises";
2
+ export { buildExecutableMode, isExecutableMode } from "#app/lib/file-mode.js";
3
+ export declare const pathExists: (path: string) => Promise<boolean>;
4
+ export declare const getPathStats: (path: string) => Promise<import("node:fs").Stats | undefined>;
5
+ export declare const listDirectoryEntries: (path: string) => Promise<import("node:fs").Dirent<string>[]>;
6
+ export declare const writeFileNode: (path: string, node: Readonly<{
7
+ contents: string | Uint8Array;
8
+ executable: boolean;
9
+ }>) => Promise<void>;
10
+ export declare const writeSymlinkNode: (path: string, linkTarget: string) => Promise<void>;
11
+ export declare const copyFilesystemNode: (sourcePath: string, targetPath: string, stats?: Awaited<ReturnType<typeof lstat>>) => Promise<void>;
12
+ export declare const replacePathAtomically: (targetPath: string, nextPath: string) => Promise<void>;
13
+ export declare const removePathAtomically: (targetPath: string) => Promise<void>;
14
+ export declare const writeTextFileAtomically: (targetPath: string, contents: string) => Promise<void>;
15
+ //# sourceMappingURL=filesystem.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filesystem.d.ts","sourceRoot":"","sources":["../../src/services/filesystem.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,EAUN,MAAM,kBAAkB,CAAC;AAK1B,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAI9E,eAAO,MAAM,UAAU,GAAU,MAAM,MAAM,qBAY5C,CAAC;AAEF,eAAO,MAAM,YAAY,GAAU,MAAM,MAAM,iDAU9C,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAU,MAAM,MAAM,gDAMtD,CAAC;AAEF,eAAO,MAAM,aAAa,GACxB,MAAM,MAAM,EACZ,MAAM,QAAQ,CAAC;IACb,QAAQ,EAAE,MAAM,GAAG,UAAU,CAAC;IAC9B,UAAU,EAAE,OAAO,CAAC;CACrB,CAAC,kBAKH,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAU,MAAM,MAAM,EAAE,YAAY,MAAM,kBAItE,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAC7B,YAAY,MAAM,EAClB,YAAY,MAAM,EAClB,QAAQ,OAAO,CAAC,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC,kBAiC1C,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAChC,YAAY,MAAM,EAClB,UAAU,MAAM,kBA6BjB,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAU,YAAY,MAAM,kBAc5D,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAClC,YAAY,MAAM,EAClB,UAAU,MAAM,kBAcjB,CAAC"}
@@ -0,0 +1,113 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { access, chmod, lstat, mkdir, mkdtemp, readdir, readFile, readlink, rename, rm, symlink, writeFile, } from "node:fs/promises";
3
+ import { basename, dirname, join } from "node:path";
4
+ import { buildExecutableMode, isExecutableMode } from "#app/lib/file-mode.js";
5
+ export { buildExecutableMode, isExecutableMode } from "#app/lib/file-mode.js";
6
+ import { DevsyncError } from "./error.js";
7
+ export const pathExists = async (path) => {
8
+ try {
9
+ await access(path);
10
+ return true;
11
+ }
12
+ catch (error) {
13
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") {
14
+ return false;
15
+ }
16
+ throw error;
17
+ }
18
+ };
19
+ export const getPathStats = async (path) => {
20
+ try {
21
+ return await lstat(path);
22
+ }
23
+ catch (error) {
24
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") {
25
+ return undefined;
26
+ }
27
+ throw error;
28
+ }
29
+ };
30
+ export const listDirectoryEntries = async (path) => {
31
+ const entries = await readdir(path, { withFileTypes: true });
32
+ return entries.sort((left, right) => {
33
+ return left.name.localeCompare(right.name);
34
+ });
35
+ };
36
+ export const writeFileNode = async (path, node) => {
37
+ await mkdir(dirname(path), { recursive: true });
38
+ await writeFile(path, node.contents);
39
+ await chmod(path, buildExecutableMode(node.executable));
40
+ };
41
+ export const writeSymlinkNode = async (path, linkTarget) => {
42
+ await mkdir(dirname(path), { recursive: true });
43
+ await rm(path, { force: true, recursive: true });
44
+ await symlink(linkTarget, path);
45
+ };
46
+ export const copyFilesystemNode = async (sourcePath, targetPath, stats) => {
47
+ const sourceStats = stats ?? (await lstat(sourcePath));
48
+ if (sourceStats.isDirectory()) {
49
+ await mkdir(targetPath, { recursive: true });
50
+ const entries = await listDirectoryEntries(sourcePath);
51
+ for (const entry of entries) {
52
+ await copyFilesystemNode(join(sourcePath, entry.name), join(targetPath, entry.name));
53
+ }
54
+ return;
55
+ }
56
+ if (sourceStats.isSymbolicLink()) {
57
+ await writeSymlinkNode(targetPath, await readlink(sourcePath));
58
+ return;
59
+ }
60
+ if (!sourceStats.isFile()) {
61
+ throw new DevsyncError(`Unsupported filesystem entry: ${sourcePath}`);
62
+ }
63
+ await writeFileNode(targetPath, {
64
+ contents: await readFile(sourcePath),
65
+ executable: isExecutableMode(sourceStats.mode),
66
+ });
67
+ };
68
+ export const replacePathAtomically = async (targetPath, nextPath) => {
69
+ const backupPath = join(dirname(targetPath), `.${basename(targetPath)}.devsync-sync-backup-${randomUUID()}`);
70
+ const existingStats = await getPathStats(targetPath);
71
+ let targetMoved = false;
72
+ try {
73
+ if (existingStats !== undefined) {
74
+ await rename(targetPath, backupPath);
75
+ targetMoved = true;
76
+ }
77
+ await rename(nextPath, targetPath);
78
+ if (targetMoved) {
79
+ await rm(backupPath, { force: true, recursive: true });
80
+ }
81
+ }
82
+ catch (error) {
83
+ if (targetMoved && !(await pathExists(targetPath))) {
84
+ await rename(backupPath, targetPath).catch(() => { });
85
+ }
86
+ throw error;
87
+ }
88
+ finally {
89
+ await rm(backupPath, { force: true, recursive: true }).catch(() => { });
90
+ }
91
+ };
92
+ export const removePathAtomically = async (targetPath) => {
93
+ const stats = await getPathStats(targetPath);
94
+ if (stats === undefined) {
95
+ return;
96
+ }
97
+ const backupPath = join(dirname(targetPath), `.${basename(targetPath)}.devsync-sync-remove-${randomUUID()}`);
98
+ await rename(targetPath, backupPath);
99
+ await rm(backupPath, { force: true, recursive: true });
100
+ };
101
+ export const writeTextFileAtomically = async (targetPath, contents) => {
102
+ await mkdir(dirname(targetPath), { recursive: true });
103
+ const stagingDirectory = await mkdtemp(join(dirname(targetPath), `.${basename(targetPath)}.devsync-sync-`));
104
+ const stagedPath = join(stagingDirectory, basename(targetPath));
105
+ try {
106
+ await writeFile(stagedPath, contents, "utf8");
107
+ await replacePathAtomically(targetPath, stagedPath);
108
+ }
109
+ finally {
110
+ await rm(stagingDirectory, { force: true, recursive: true });
111
+ }
112
+ };
113
+ //# sourceMappingURL=filesystem.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filesystem.js","sourceRoot":"","sources":["../../src/services/filesystem.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { type SyncContext } from "./runtime.js";
2
+ export type SyncForgetRequest = Readonly<{
3
+ target: string;
4
+ }>;
5
+ export type SyncForgetResult = Readonly<{
6
+ configPath: string;
7
+ localPath: string;
8
+ plainArtifactCount: number;
9
+ repoPath: string;
10
+ secretArtifactCount: number;
11
+ syncDirectory: string;
12
+ }>;
13
+ export declare const forgetSyncTarget: (request: SyncForgetRequest, context: SyncContext) => Promise<SyncForgetResult>;
14
+ //# sourceMappingURL=forget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forget.d.ts","sourceRoot":"","sources":["../../src/services/forget.ts"],"names":[],"mappings":"AA0BA,OAAO,EAAwB,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAEtE,MAAM,MAAM,iBAAiB,GAAG,QAAQ,CAAC;IACvC,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC,CAAC;AA+IH,eAAO,MAAM,gBAAgB,GAC3B,SAAS,iBAAiB,EAC1B,SAAS,WAAW,KACnB,OAAO,CAAC,gBAAgB,CA2C1B,CAAC"}
@@ -0,0 +1,124 @@
1
+ import { readdir, rm } from "node:fs/promises";
2
+ import { dirname, join, posix } from "node:path";
3
+ import { readSyncConfig, resolveSyncArtifactsDirectoryPath, } from "#app/config/sync.js";
4
+ import { createSyncConfigDocument, writeValidatedSyncConfig, } from "./config-file.js";
5
+ import { DevsyncError } from "./error.js";
6
+ import { getPathStats, listDirectoryEntries, removePathAtomically, } from "./filesystem.js";
7
+ import { isPathEqualOrNested, resolveTrackedEntry } from "./paths.js";
8
+ import { collectArtifactNamespaces, isSecretArtifactPath, resolveArtifactRelativePath, resolveEntryArtifactPath, } from "./repo-artifacts.js";
9
+ import { ensureSyncRepository } from "./runtime.js";
10
+ const collectRepoArtifactCounts = async (targetPath, counts, relativePath) => {
11
+ const stats = await getPathStats(targetPath);
12
+ if (stats === undefined) {
13
+ return;
14
+ }
15
+ if (stats.isDirectory()) {
16
+ counts.plain += 1;
17
+ const entries = await listDirectoryEntries(targetPath);
18
+ for (const entry of entries) {
19
+ await collectRepoArtifactCounts(join(targetPath, entry.name), counts, posix.join(relativePath, entry.name));
20
+ }
21
+ return;
22
+ }
23
+ if (isSecretArtifactPath(relativePath)) {
24
+ counts.secret += 1;
25
+ }
26
+ else {
27
+ counts.plain += 1;
28
+ }
29
+ };
30
+ const collectEntryArtifactCounts = async (syncDirectory, entry) => {
31
+ const artifactsRoot = resolveSyncArtifactsDirectoryPath(syncDirectory);
32
+ const counts = {
33
+ plain: 0,
34
+ secret: 0,
35
+ };
36
+ const namespaces = collectArtifactNamespaces([entry]);
37
+ for (const machine of namespaces) {
38
+ await collectRepoArtifactCounts(resolveEntryArtifactPath(artifactsRoot, entry, machine), counts, resolveArtifactRelativePath({
39
+ category: "plain",
40
+ machine,
41
+ repoPath: entry.repoPath,
42
+ }));
43
+ if (entry.kind !== "directory") {
44
+ const secretRelativePath = resolveArtifactRelativePath({
45
+ category: "secret",
46
+ machine,
47
+ repoPath: entry.repoPath,
48
+ });
49
+ await collectRepoArtifactCounts(join(artifactsRoot, ...secretRelativePath.split("/")), counts, secretRelativePath);
50
+ }
51
+ }
52
+ return {
53
+ plainArtifactCount: counts.plain,
54
+ secretArtifactCount: counts.secret,
55
+ };
56
+ };
57
+ const pruneEmptyParentDirectories = async (startPath, rootPath) => {
58
+ let currentPath = startPath;
59
+ while (isPathEqualOrNested(currentPath, rootPath) &&
60
+ currentPath !== rootPath) {
61
+ const stats = await getPathStats(currentPath);
62
+ if (stats === undefined) {
63
+ currentPath = dirname(currentPath);
64
+ continue;
65
+ }
66
+ if (!stats.isDirectory()) {
67
+ break;
68
+ }
69
+ const entries = await readdir(currentPath);
70
+ if (entries.length > 0) {
71
+ break;
72
+ }
73
+ await rm(currentPath, { force: true, recursive: true });
74
+ currentPath = dirname(currentPath);
75
+ }
76
+ };
77
+ const removeTrackedEntryArtifacts = async (syncDirectory, entry) => {
78
+ const artifactsRoot = resolveSyncArtifactsDirectoryPath(syncDirectory);
79
+ const namespaces = collectArtifactNamespaces([entry]);
80
+ for (const machine of namespaces) {
81
+ const plainPath = resolveEntryArtifactPath(artifactsRoot, entry, machine);
82
+ await removePathAtomically(plainPath);
83
+ await pruneEmptyParentDirectories(dirname(plainPath), artifactsRoot);
84
+ if (entry.kind !== "directory") {
85
+ const secretPath = join(artifactsRoot, ...resolveArtifactRelativePath({
86
+ category: "secret",
87
+ machine,
88
+ repoPath: entry.repoPath,
89
+ }).split("/"));
90
+ await removePathAtomically(secretPath);
91
+ await pruneEmptyParentDirectories(dirname(secretPath), artifactsRoot);
92
+ }
93
+ }
94
+ };
95
+ export const forgetSyncTarget = async (request, context) => {
96
+ const target = request.target.trim();
97
+ if (target.length === 0) {
98
+ throw new DevsyncError("Target path is required.");
99
+ }
100
+ await ensureSyncRepository(context);
101
+ const config = await readSyncConfig(context.paths.syncDirectory, context.environment);
102
+ const entry = resolveTrackedEntry(target, config.entries, context);
103
+ if (entry === undefined) {
104
+ throw new DevsyncError(`No tracked sync entry matches: ${target}`);
105
+ }
106
+ const { plainArtifactCount, secretArtifactCount } = await collectEntryArtifactCounts(context.paths.syncDirectory, entry);
107
+ const nextConfig = createSyncConfigDocument({
108
+ ...config,
109
+ entries: config.entries.filter((configEntry) => {
110
+ return configEntry.repoPath !== entry.repoPath;
111
+ }),
112
+ });
113
+ await writeValidatedSyncConfig(context.paths.syncDirectory, nextConfig, context.environment);
114
+ await removeTrackedEntryArtifacts(context.paths.syncDirectory, entry);
115
+ return {
116
+ configPath: context.paths.configPath,
117
+ localPath: entry.localPath,
118
+ plainArtifactCount,
119
+ repoPath: entry.repoPath,
120
+ secretArtifactCount,
121
+ syncDirectory: context.paths.syncDirectory,
122
+ };
123
+ };
124
+ //# sourceMappingURL=forget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forget.js","sourceRoot":"","sources":["../../src/services/forget.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export declare const ensureRepository: (directory: string) => Promise<void>;
2
+ export declare const initializeRepository: (directory: string, source?: string) => Promise<{
3
+ action: "initialized";
4
+ source?: undefined;
5
+ } | {
6
+ action: "cloned";
7
+ source: string;
8
+ }>;
9
+ export declare const ensureGitRepository: (syncDirectory: string) => Promise<void>;
10
+ //# sourceMappingURL=git.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/services/git.ts"],"names":[],"mappings":"AAuCA,eAAO,MAAM,gBAAgB,GAAU,WAAW,MAAM,kBAEvD,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAC/B,WAAW,MAAM,EACjB,SAAS,MAAM;;;;;;EAgBhB,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAU,eAAe,MAAM,kBAU9D,CAAC"}