@tinyrack/devsync 1.1.0 → 1.3.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.
Files changed (220) 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/platform.d.ts +11 -0
  55. package/dist/config/platform.d.ts.map +1 -0
  56. package/dist/config/platform.js +19 -0
  57. package/dist/config/platform.js.map +1 -0
  58. package/dist/config/sync.d.ts +107 -0
  59. package/dist/config/sync.d.ts.map +1 -0
  60. package/dist/config/sync.js +424 -0
  61. package/dist/config/sync.js.map +1 -0
  62. package/dist/config/xdg.d.ts +14 -0
  63. package/dist/config/xdg.d.ts.map +1 -0
  64. package/dist/config/xdg.js +102 -0
  65. package/dist/config/xdg.js.map +1 -0
  66. package/dist/index.d.ts +3 -0
  67. package/dist/index.d.ts.map +1 -0
  68. package/{src/index.ts → dist/index.js} +1 -1
  69. package/dist/index.js.map +1 -0
  70. package/dist/lib/file-mode.d.ts +3 -0
  71. package/dist/lib/file-mode.d.ts.map +1 -0
  72. package/dist/lib/file-mode.js +7 -0
  73. package/dist/lib/file-mode.js.map +1 -0
  74. package/dist/lib/output.d.ts +31 -0
  75. package/dist/lib/output.d.ts.map +1 -0
  76. package/dist/lib/output.js +198 -0
  77. package/dist/lib/output.js.map +1 -0
  78. package/dist/lib/path.d.ts +5 -0
  79. package/dist/lib/path.d.ts.map +1 -0
  80. package/dist/lib/path.js +25 -0
  81. package/dist/lib/path.js.map +1 -0
  82. package/dist/lib/string.d.ts +2 -0
  83. package/dist/lib/string.d.ts.map +1 -0
  84. package/dist/lib/string.js +4 -0
  85. package/dist/lib/string.js.map +1 -0
  86. package/dist/lib/validation.d.ts +3 -0
  87. package/dist/lib/validation.d.ts.map +1 -0
  88. package/dist/lib/validation.js +9 -0
  89. package/dist/lib/validation.js.map +1 -0
  90. package/dist/services/add.d.ts +20 -0
  91. package/dist/services/add.d.ts.map +1 -0
  92. package/dist/services/add.js +161 -0
  93. package/dist/services/add.js.map +1 -0
  94. package/dist/services/config-file.d.ts +45 -0
  95. package/dist/services/config-file.d.ts.map +1 -0
  96. package/dist/services/config-file.js +35 -0
  97. package/dist/services/config-file.js.map +1 -0
  98. package/dist/services/crypto.d.ts +9 -0
  99. package/dist/services/crypto.d.ts.map +1 -0
  100. package/dist/services/crypto.js +75 -0
  101. package/dist/services/crypto.js.map +1 -0
  102. package/dist/services/doctor.d.ts +16 -0
  103. package/dist/services/doctor.d.ts.map +1 -0
  104. package/dist/services/doctor.js +84 -0
  105. package/dist/services/doctor.js.map +1 -0
  106. package/dist/services/error.d.ts +14 -0
  107. package/dist/services/error.d.ts.map +1 -0
  108. package/dist/services/error.js +38 -0
  109. package/dist/services/error.js.map +1 -0
  110. package/dist/services/filesystem.d.ts +15 -0
  111. package/dist/services/filesystem.d.ts.map +1 -0
  112. package/dist/services/filesystem.js +113 -0
  113. package/dist/services/filesystem.js.map +1 -0
  114. package/dist/services/forget.d.ts +14 -0
  115. package/dist/services/forget.d.ts.map +1 -0
  116. package/dist/services/forget.js +124 -0
  117. package/dist/services/forget.js.map +1 -0
  118. package/dist/services/git.d.ts +10 -0
  119. package/dist/services/git.d.ts.map +1 -0
  120. package/dist/services/git.js +57 -0
  121. package/dist/services/git.js.map +1 -0
  122. package/dist/services/init.d.ts +19 -0
  123. package/dist/services/init.d.ts.map +1 -0
  124. package/dist/services/init.js +203 -0
  125. package/dist/services/init.js.map +1 -0
  126. package/dist/services/local-materialization.d.ts +28 -0
  127. package/dist/services/local-materialization.d.ts.map +1 -0
  128. package/dist/services/local-materialization.js +262 -0
  129. package/dist/services/local-materialization.js.map +1 -0
  130. package/dist/services/local-snapshot.d.ts +25 -0
  131. package/dist/services/local-snapshot.d.ts.map +1 -0
  132. package/dist/services/local-snapshot.js +93 -0
  133. package/dist/services/local-snapshot.js.map +1 -0
  134. package/dist/services/machine.d.ts +40 -0
  135. package/dist/services/machine.d.ts.map +1 -0
  136. package/dist/services/machine.js +113 -0
  137. package/dist/services/machine.js.map +1 -0
  138. package/dist/services/paths.d.ts +13 -0
  139. package/dist/services/paths.d.ts.map +1 -0
  140. package/dist/services/paths.js +71 -0
  141. package/dist/services/paths.js.map +1 -0
  142. package/dist/services/pull.d.ts +28 -0
  143. package/dist/services/pull.d.ts.map +1 -0
  144. package/dist/services/pull.js +67 -0
  145. package/dist/services/pull.js.map +1 -0
  146. package/dist/services/push.d.ts +35 -0
  147. package/dist/services/push.d.ts.map +1 -0
  148. package/dist/services/push.js +96 -0
  149. package/dist/services/push.js.map +1 -0
  150. package/dist/services/repo-artifacts.d.ts +52 -0
  151. package/dist/services/repo-artifacts.d.ts.map +1 -0
  152. package/dist/services/repo-artifacts.js +251 -0
  153. package/dist/services/repo-artifacts.js.map +1 -0
  154. package/dist/services/repo-snapshot.d.ts +6 -0
  155. package/dist/services/repo-snapshot.d.ts.map +1 -0
  156. package/dist/services/repo-snapshot.js +163 -0
  157. package/dist/services/repo-snapshot.js.map +1 -0
  158. package/dist/services/runtime.d.ts +40 -0
  159. package/dist/services/runtime.d.ts.map +1 -0
  160. package/dist/services/runtime.js +71 -0
  161. package/dist/services/runtime.js.map +1 -0
  162. package/dist/services/set.d.ts +38 -0
  163. package/dist/services/set.d.ts.map +1 -0
  164. package/dist/services/set.js +184 -0
  165. package/dist/services/set.js.map +1 -0
  166. package/dist/services/status.d.ts +30 -0
  167. package/dist/services/status.d.ts.map +1 -0
  168. package/dist/services/status.js +35 -0
  169. package/dist/services/status.js.map +1 -0
  170. package/package.json +15 -7
  171. package/src/cli/commands/add.ts +0 -40
  172. package/src/cli/commands/cd.ts +0 -80
  173. package/src/cli/commands/doctor.ts +0 -20
  174. package/src/cli/commands/forget.ts +0 -32
  175. package/src/cli/commands/index.ts +0 -23
  176. package/src/cli/commands/init.ts +0 -43
  177. package/src/cli/commands/list.ts +0 -17
  178. package/src/cli/commands/pull.ts +0 -31
  179. package/src/cli/commands/push.ts +0 -31
  180. package/src/cli/commands/set.ts +0 -47
  181. package/src/cli/commands/status.ts +0 -18
  182. package/src/cli/sync-output.test.ts +0 -173
  183. package/src/cli/sync-output.ts +0 -200
  184. package/src/config/sync.test.ts +0 -609
  185. package/src/config/sync.ts +0 -572
  186. package/src/config/xdg.ts +0 -138
  187. package/src/lib/string.test.ts +0 -13
  188. package/src/lib/string.ts +0 -3
  189. package/src/lib/validation.test.ts +0 -32
  190. package/src/lib/validation.ts +0 -11
  191. package/src/services/add.ts +0 -178
  192. package/src/services/config-file.test.ts +0 -161
  193. package/src/services/config-file.ts +0 -101
  194. package/src/services/crypto.test.ts +0 -132
  195. package/src/services/crypto.ts +0 -83
  196. package/src/services/doctor.ts +0 -142
  197. package/src/services/error.ts +0 -6
  198. package/src/services/filesystem.test.ts +0 -171
  199. package/src/services/filesystem.ts +0 -183
  200. package/src/services/forget.ts +0 -261
  201. package/src/services/git.test.ts +0 -83
  202. package/src/services/git.ts +0 -74
  203. package/src/services/init.test.ts +0 -109
  204. package/src/services/init.ts +0 -244
  205. package/src/services/list.ts +0 -63
  206. package/src/services/local-materialization.ts +0 -421
  207. package/src/services/local-snapshot.ts +0 -173
  208. package/src/services/paths.test.ts +0 -74
  209. package/src/services/paths.ts +0 -98
  210. package/src/services/pull.ts +0 -144
  211. package/src/services/push.ts +0 -168
  212. package/src/services/repo-artifacts.ts +0 -262
  213. package/src/services/repo-snapshot.ts +0 -197
  214. package/src/services/runtime.ts +0 -57
  215. package/src/services/set.ts +0 -383
  216. package/src/services/status.ts +0 -57
  217. package/src/services/sync.dry-run.test.ts +0 -179
  218. package/src/services/sync.runtime.test.ts +0 -756
  219. package/src/services/sync.service.test.ts +0 -1169
  220. package/src/test/helpers/sync-fixture.ts +0 -47
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/services/status.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,oBAAoB,EACpB,cAAc,GAEf,MAAM,cAAc,CAAC;AA0BtB,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,EAChC,OAAoB,EACpB,UAEK,EAAE,EACoB,EAAE;IAC7B,MAAM,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAEpC,MAAM,EAAE,eAAe,EAAE,UAAU,EAAE,GAAG,MAAM,cAAc,CAC1D,OAAO,EACP,OAAO,CACR,CAAC;IACF,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;IAC/D,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;IAE/D,OAAO;QACL,GAAG,CAAC,eAAe,CAAC,aAAa,KAAK,SAAS;YAC7C,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,EAAE,aAAa,EAAE,eAAe,CAAC,aAAa,EAAE,CAAC;QACrD,UAAU,EAAE,OAAO,CAAC,KAAK,CAAC,UAAU;QACpC,OAAO,EAAE,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YAC1C,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,QAAQ,EAAE,KAAK,CAAC,QAAQ;SACzB,CAAC,CAAC;QACH,UAAU,EAAE,UAAU,CAAC,OAAO,CAAC,MAAM;QACrC,IAAI,EAAE;YACJ,GAAG,uBAAuB,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC;YACnD,OAAO,EAAE,oBAAoB,CAAC,QAAQ,CAAC;SACxC;QACD,IAAI,EAAE;YACJ,GAAG,uBAAuB,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC;YACnD,OAAO,EAAE,oBAAoB,CAAC,QAAQ,CAAC;SACxC;QACD,cAAc,EAAE,eAAe,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM;QACrD,aAAa,EAAE,OAAO,CAAC,KAAK,CAAC,aAAa;KAC3C,CAAC;AACJ,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tinyrack/devsync",
3
- "version": "1.1.0",
3
+ "version": "1.3.0",
4
4
  "description": "A personal CLI tool for git-backed configuration sync.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -24,22 +24,25 @@
24
24
  "devsync"
25
25
  ],
26
26
  "imports": {
27
- "#app/*": "./src/*"
27
+ "#app/*.js": "./dist/*.js"
28
28
  },
29
29
  "bin": {
30
- "devsync": "./src/index.ts"
30
+ "devsync": "./dist/index.js"
31
31
  },
32
32
  "files": [
33
- "src",
33
+ "dist",
34
34
  "README.md",
35
35
  "LICENSE"
36
36
  ],
37
37
  "oclif": {
38
38
  "bin": "devsync",
39
39
  "dirname": "devsync",
40
+ "helpOptions": {
41
+ "flagSortOrder": "none"
42
+ },
40
43
  "commands": {
41
44
  "strategy": "explicit",
42
- "target": "./src/cli/commands/index.ts",
45
+ "target": "./dist/cli/commands/index.js",
43
46
  "identifier": "COMMANDS"
44
47
  },
45
48
  "topicSeparator": " ",
@@ -54,8 +57,12 @@
54
57
  "node": ">=24"
55
58
  },
56
59
  "scripts": {
57
- "dev": "node --watch src/index.ts",
58
- "start": "node src/index.ts",
60
+ "dev": "tsc -p tsconfig.build.json --watch",
61
+ "build": "tsc -p tsconfig.build.json",
62
+ "clean": "rm -rf dist",
63
+ "prebuild": "rm -rf dist",
64
+ "start": "node dist/index.js",
65
+ "prepack": "npm run build",
59
66
  "typecheck": "tsc -p tsconfig.json",
60
67
  "test": "vitest run",
61
68
  "test:watch": "vitest",
@@ -71,6 +78,7 @@
71
78
  "@oclif/core": "^4.9.0",
72
79
  "@oclif/plugin-autocomplete": "^3.2.41",
73
80
  "age-encryption": "^0.3.0",
81
+ "picocolors": "^1.1.1",
74
82
  "zod": "^4.3.6"
75
83
  },
76
84
  "devDependencies": {
@@ -1,40 +0,0 @@
1
- import { Args, Command, Flags } from "@oclif/core";
2
-
3
- import { formatSyncAddResult } from "#app/cli/sync-output.ts";
4
- import { addSyncTarget } from "#app/services/add.ts";
5
- import { createSyncContext } from "#app/services/runtime.ts";
6
-
7
- export default class SyncAdd extends Command {
8
- public static override summary =
9
- "Add a local file or directory under your home directory to sync config.json";
10
-
11
- public static override args = {
12
- target: Args.string({
13
- description:
14
- "Local file or directory under your home directory to track, including cwd-relative paths",
15
- required: true,
16
- }),
17
- };
18
-
19
- public static override flags = {
20
- secret: Flags.boolean({
21
- default: false,
22
- description: "Set the added target mode to secret in sync config.json",
23
- }),
24
- };
25
-
26
- public override async run(): Promise<void> {
27
- const { args, flags } = await this.parse(SyncAdd);
28
- const output = formatSyncAddResult(
29
- await addSyncTarget(
30
- {
31
- secret: flags.secret,
32
- target: args.target,
33
- },
34
- createSyncContext(),
35
- ),
36
- );
37
-
38
- process.stdout.write(output);
39
- }
40
- }
@@ -1,80 +0,0 @@
1
- import { spawn } from "node:child_process";
2
- import { mkdir } from "node:fs/promises";
3
-
4
- import { Command, Flags } from "@oclif/core";
5
-
6
- import { resolveDevsyncSyncDirectory } from "#app/config/xdg.ts";
7
- import { ensureTrailingNewline } from "#app/lib/string.ts";
8
-
9
- const readEnvironmentVariable = (name: "ComSpec" | "SHELL") => {
10
- return process.env[name]?.trim();
11
- };
12
-
13
- const resolveCommandShell = () => {
14
- if (process.platform === "win32") {
15
- return {
16
- args: [] as string[],
17
- command: readEnvironmentVariable("ComSpec") || "cmd.exe",
18
- };
19
- }
20
-
21
- return {
22
- args: ["-i"],
23
- command: readEnvironmentVariable("SHELL") || "/bin/sh",
24
- };
25
- };
26
-
27
- const spawnShellInDirectory = async (directory: string) => {
28
- await mkdir(directory, { recursive: true });
29
-
30
- const shell = resolveCommandShell();
31
-
32
- await new Promise<void>((resolve, reject) => {
33
- const child = spawn(shell.command, shell.args, {
34
- cwd: directory,
35
- stdio: "inherit",
36
- });
37
-
38
- child.once("error", reject);
39
- child.once("exit", (code, signal) => {
40
- if (signal !== null) {
41
- reject(new Error(`Shell exited with signal ${signal}.`));
42
-
43
- return;
44
- }
45
-
46
- if (code === 0) {
47
- resolve();
48
-
49
- return;
50
- }
51
-
52
- reject(new Error(`Shell exited with code ${code ?? 1}.`));
53
- });
54
- });
55
- };
56
-
57
- export default class SyncCd extends Command {
58
- public static override summary =
59
- "Open a shell in the sync directory or print its path";
60
-
61
- public static override flags = {
62
- print: Flags.boolean({
63
- default: false,
64
- description: "Print the sync directory path instead of opening a shell",
65
- }),
66
- };
67
-
68
- public override async run(): Promise<void> {
69
- const { flags } = await this.parse(SyncCd);
70
- const syncDirectory = resolveDevsyncSyncDirectory();
71
-
72
- if (flags.print || !process.stdin.isTTY || !process.stdout.isTTY) {
73
- process.stdout.write(ensureTrailingNewline(syncDirectory));
74
-
75
- return;
76
- }
77
-
78
- await spawnShellInDirectory(syncDirectory);
79
- }
80
- }
@@ -1,20 +0,0 @@
1
- import { Command } from "@oclif/core";
2
-
3
- import { formatSyncDoctorResult } from "#app/cli/sync-output.ts";
4
- import { runSyncDoctor } from "#app/services/doctor.ts";
5
- import { createSyncContext } from "#app/services/runtime.ts";
6
-
7
- export default class SyncDoctor extends Command {
8
- public static override summary =
9
- "Check sync repository, config, age identity, and tracked local paths";
10
-
11
- public override async run(): Promise<void> {
12
- const result = await runSyncDoctor(createSyncContext());
13
-
14
- process.stdout.write(formatSyncDoctorResult(result));
15
-
16
- if (result.hasFailures) {
17
- this.exit(1);
18
- }
19
- }
20
- }
@@ -1,32 +0,0 @@
1
- import { Args, Command } from "@oclif/core";
2
-
3
- import { formatSyncForgetResult } from "#app/cli/sync-output.ts";
4
- import { forgetSyncTarget } from "#app/services/forget.ts";
5
- import { createSyncContext } from "#app/services/runtime.ts";
6
-
7
- export default class SyncForget extends Command {
8
- public static override summary =
9
- "Remove a tracked local path or repository path from sync config.json";
10
-
11
- public static override args = {
12
- target: Args.string({
13
- description:
14
- "Tracked local path (including cwd-relative) or repository path to forget",
15
- required: true,
16
- }),
17
- };
18
-
19
- public override async run(): Promise<void> {
20
- const { args } = await this.parse(SyncForget);
21
- const output = formatSyncForgetResult(
22
- await forgetSyncTarget(
23
- {
24
- target: args.target,
25
- },
26
- createSyncContext(),
27
- ),
28
- );
29
-
30
- process.stdout.write(output);
31
- }
32
- }
@@ -1,23 +0,0 @@
1
- import SyncAdd from "#app/cli/commands/add.ts";
2
- import SyncCd from "#app/cli/commands/cd.ts";
3
- import SyncDoctor from "#app/cli/commands/doctor.ts";
4
- import SyncForget from "#app/cli/commands/forget.ts";
5
- import SyncInit from "#app/cli/commands/init.ts";
6
- import SyncList from "#app/cli/commands/list.ts";
7
- import SyncPull from "#app/cli/commands/pull.ts";
8
- import SyncPush from "#app/cli/commands/push.ts";
9
- import SyncSet from "#app/cli/commands/set.ts";
10
- import SyncStatus from "#app/cli/commands/status.ts";
11
-
12
- export const COMMANDS = {
13
- add: SyncAdd,
14
- cd: SyncCd,
15
- doctor: SyncDoctor,
16
- forget: SyncForget,
17
- init: SyncInit,
18
- list: SyncList,
19
- pull: SyncPull,
20
- push: SyncPush,
21
- status: SyncStatus,
22
- set: SyncSet,
23
- };
@@ -1,43 +0,0 @@
1
- import { Args, Command, Flags } from "@oclif/core";
2
-
3
- import { formatSyncInitResult } from "#app/cli/sync-output.ts";
4
- import { initializeSync } from "#app/services/init.ts";
5
- import { createSyncContext } from "#app/services/runtime.ts";
6
-
7
- export default class SyncInit extends Command {
8
- public static override summary = "Initialize the git-backed sync directory";
9
-
10
- public static override args = {
11
- repository: Args.string({
12
- description: "Remote URL or local git repository path to clone",
13
- required: false,
14
- }),
15
- };
16
-
17
- public static override flags = {
18
- identity: Flags.string({
19
- description:
20
- "Age identity file path to persist in config.json for later pulls",
21
- }),
22
- recipient: Flags.string({
23
- description: "Age recipient public key to persist in config.json",
24
- multiple: true,
25
- }),
26
- };
27
-
28
- public override async run(): Promise<void> {
29
- const { args, flags } = await this.parse(SyncInit);
30
- const output = formatSyncInitResult(
31
- await initializeSync(
32
- {
33
- identityFile: flags.identity,
34
- recipients: flags.recipient ?? [],
35
- repository: args.repository,
36
- },
37
- createSyncContext(),
38
- ),
39
- );
40
-
41
- process.stdout.write(output);
42
- }
43
- }
@@ -1,17 +0,0 @@
1
- import { Command } from "@oclif/core";
2
-
3
- import { formatSyncListResult } from "#app/cli/sync-output.ts";
4
- import { listSyncConfig } from "#app/services/list.ts";
5
- import { createSyncContext } from "#app/services/runtime.ts";
6
-
7
- export default class SyncList extends Command {
8
- public static override summary = "Show tracked sync entries and overrides";
9
-
10
- public override async run(): Promise<void> {
11
- const output = formatSyncListResult(
12
- await listSyncConfig(createSyncContext()),
13
- );
14
-
15
- process.stdout.write(output);
16
- }
17
- }
@@ -1,31 +0,0 @@
1
- import { Command, Flags } from "@oclif/core";
2
-
3
- import { formatSyncPullResult } from "#app/cli/sync-output.ts";
4
- import { pullSync } from "#app/services/pull.ts";
5
- import { createSyncContext } from "#app/services/runtime.ts";
6
-
7
- export default class SyncPull extends Command {
8
- public static override summary =
9
- "Apply the git-backed sync repository to local config paths";
10
-
11
- public static override flags = {
12
- "dry-run": Flags.boolean({
13
- default: false,
14
- description: "Preview local config changes without writing files",
15
- }),
16
- };
17
-
18
- public override async run(): Promise<void> {
19
- const { flags } = await this.parse(SyncPull);
20
- const output = formatSyncPullResult(
21
- await pullSync(
22
- {
23
- dryRun: flags["dry-run"],
24
- },
25
- createSyncContext(),
26
- ),
27
- );
28
-
29
- process.stdout.write(output);
30
- }
31
- }
@@ -1,31 +0,0 @@
1
- import { Command, Flags } from "@oclif/core";
2
-
3
- import { formatSyncPushResult } from "#app/cli/sync-output.ts";
4
- import { pushSync } from "#app/services/push.ts";
5
- import { createSyncContext } from "#app/services/runtime.ts";
6
-
7
- export default class SyncPush extends Command {
8
- public static override summary =
9
- "Mirror local config into the git-backed sync repository";
10
-
11
- public static override flags = {
12
- "dry-run": Flags.boolean({
13
- default: false,
14
- description: "Preview sync repository changes without writing files",
15
- }),
16
- };
17
-
18
- public override async run(): Promise<void> {
19
- const { flags } = await this.parse(SyncPush);
20
- const output = formatSyncPushResult(
21
- await pushSync(
22
- {
23
- dryRun: flags["dry-run"],
24
- },
25
- createSyncContext(),
26
- ),
27
- );
28
-
29
- process.stdout.write(output);
30
- }
31
- }
@@ -1,47 +0,0 @@
1
- import { Args, Command, Flags } from "@oclif/core";
2
-
3
- import { formatSyncSetResult } from "#app/cli/sync-output.ts";
4
- import { createSyncContext } from "#app/services/runtime.ts";
5
- import { setSyncTargetMode } from "#app/services/set.ts";
6
-
7
- export default class SyncSet extends Command {
8
- public static override summary =
9
- "Set sync mode for a tracked directory root, child file, or child subtree";
10
-
11
- public static override args = {
12
- state: Args.string({
13
- description: "Mode to apply: normal, secret, or ignore",
14
- options: ["normal", "secret", "ignore"],
15
- required: true,
16
- }),
17
- target: Args.string({
18
- description:
19
- "Tracked local path (including cwd-relative) or repository path inside a tracked directory",
20
- required: true,
21
- }),
22
- };
23
-
24
- public static override flags = {
25
- recursive: Flags.boolean({
26
- default: false,
27
- description:
28
- "Apply the mode to a directory subtree or update a tracked directory root default",
29
- }),
30
- };
31
-
32
- public override async run(): Promise<void> {
33
- const { args, flags } = await this.parse(SyncSet);
34
- const output = formatSyncSetResult(
35
- await setSyncTargetMode(
36
- {
37
- recursive: flags.recursive,
38
- state: args.state as "ignore" | "normal" | "secret",
39
- target: args.target,
40
- },
41
- createSyncContext(),
42
- ),
43
- );
44
-
45
- process.stdout.write(output);
46
- }
47
- }
@@ -1,18 +0,0 @@
1
- import { Command } from "@oclif/core";
2
-
3
- import { formatSyncStatusResult } from "#app/cli/sync-output.ts";
4
- import { createSyncContext } from "#app/services/runtime.ts";
5
- import { getSyncStatus } from "#app/services/status.ts";
6
-
7
- export default class SyncStatus extends Command {
8
- public static override summary =
9
- "Show planned push and pull changes for the current sync config";
10
-
11
- public override async run(): Promise<void> {
12
- const output = formatSyncStatusResult(
13
- await getSyncStatus(createSyncContext()),
14
- );
15
-
16
- process.stdout.write(output);
17
- }
18
- }
@@ -1,173 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
-
3
- import {
4
- formatSyncAddResult,
5
- formatSyncDoctorResult,
6
- formatSyncForgetResult,
7
- formatSyncInitResult,
8
- formatSyncListResult,
9
- formatSyncPullResult,
10
- formatSyncPushResult,
11
- formatSyncSetResult,
12
- formatSyncStatusResult,
13
- } from "#app/cli/sync-output.ts";
14
-
15
- describe("sync output formatting", () => {
16
- it("formats init results for cloned repositories", () => {
17
- expect(
18
- formatSyncInitResult({
19
- alreadyInitialized: false,
20
- configPath: "/tmp/sync/config.json",
21
- entryCount: 2,
22
- generatedIdentity: true,
23
- gitAction: "cloned",
24
- gitSource: "/tmp/remote",
25
- identityFile: "/tmp/xdg/devsync/age/keys.txt",
26
- recipientCount: 3,
27
- ruleCount: 4,
28
- syncDirectory: "/tmp/sync",
29
- }),
30
- ).toBe(
31
- [
32
- "Initialized sync directory.",
33
- "Sync directory: /tmp/sync",
34
- "Config file: /tmp/sync/config.json",
35
- "Age identity file: /tmp/xdg/devsync/age/keys.txt",
36
- "Git repository: cloned from /tmp/remote",
37
- "Age bootstrap: generated a new local identity.",
38
- "Summary: 3 recipients, 2 entries, 4 rules.",
39
- "",
40
- ].join("\n"),
41
- );
42
- });
43
-
44
- it("formats add, forget, and set results", () => {
45
- expect(
46
- formatSyncAddResult({
47
- alreadyTracked: false,
48
- configPath: "/tmp/sync/config.json",
49
- kind: "file",
50
- localPath: "/tmp/home/.zshrc",
51
- mode: "secret",
52
- repoPath: ".zshrc",
53
- syncDirectory: "/tmp/sync",
54
- }),
55
- ).toContain("Added sync target.\n");
56
- expect(
57
- formatSyncForgetResult({
58
- configPath: "/tmp/sync/config.json",
59
- localPath: "/tmp/home/.zshrc",
60
- plainArtifactCount: 1,
61
- repoPath: ".zshrc",
62
- secretArtifactCount: 2,
63
- syncDirectory: "/tmp/sync",
64
- }),
65
- ).toContain("Removed repo artifacts: 1 plain, 2 secret.\n");
66
- expect(
67
- formatSyncSetResult({
68
- action: "updated",
69
- configPath: "/tmp/sync/config.json",
70
- entryRepoPath: "bundle",
71
- localPath: "/tmp/home/bundle/private.json",
72
- mode: "ignore",
73
- repoPath: "bundle/private.json",
74
- scope: "exact",
75
- syncDirectory: "/tmp/sync",
76
- }),
77
- ).toContain("Scope: exact rule\nAction: updated\n");
78
- });
79
-
80
- it("formats push and pull dry-run summaries", () => {
81
- expect(
82
- formatSyncPushResult({
83
- configPath: "/tmp/sync/config.json",
84
- deletedArtifactCount: 4,
85
- directoryCount: 1,
86
- dryRun: true,
87
- encryptedFileCount: 2,
88
- plainFileCount: 3,
89
- symlinkCount: 1,
90
- syncDirectory: "/tmp/sync",
91
- }),
92
- ).toContain("No filesystem changes were made.\n");
93
- expect(
94
- formatSyncPullResult({
95
- configPath: "/tmp/sync/config.json",
96
- decryptedFileCount: 2,
97
- deletedLocalCount: 5,
98
- directoryCount: 1,
99
- dryRun: true,
100
- plainFileCount: 3,
101
- symlinkCount: 1,
102
- syncDirectory: "/tmp/sync",
103
- }),
104
- ).toContain(
105
- "local paths would be removed.\nNo filesystem changes were made.\n",
106
- );
107
- });
108
-
109
- it("formats list, status, and doctor results", () => {
110
- expect(
111
- formatSyncListResult({
112
- configPath: "/tmp/sync/config.json",
113
- entries: [
114
- {
115
- kind: "directory",
116
- localPath: "/tmp/home/.config/tool",
117
- mode: "normal",
118
- name: ".config/tool",
119
- overrides: [{ mode: "secret", selector: "token.json" }],
120
- repoPath: ".config/tool",
121
- },
122
- ],
123
- recipientCount: 1,
124
- ruleCount: 1,
125
- syncDirectory: "/tmp/sync",
126
- }),
127
- ).toContain("override token.json: secret\n");
128
- expect(
129
- formatSyncStatusResult({
130
- configPath: "/tmp/sync/config.json",
131
- entryCount: 1,
132
- pull: {
133
- configPath: "/tmp/sync/config.json",
134
- decryptedFileCount: 1,
135
- deletedLocalCount: 2,
136
- directoryCount: 1,
137
- dryRun: true,
138
- plainFileCount: 0,
139
- preview: ["bundle", "bundle/token.txt"],
140
- symlinkCount: 0,
141
- syncDirectory: "/tmp/sync",
142
- },
143
- push: {
144
- configPath: "/tmp/sync/config.json",
145
- deletedArtifactCount: 1,
146
- directoryCount: 1,
147
- dryRun: true,
148
- encryptedFileCount: 1,
149
- plainFileCount: 0,
150
- preview: ["bundle", "bundle/token.txt"],
151
- symlinkCount: 0,
152
- syncDirectory: "/tmp/sync",
153
- },
154
- recipientCount: 1,
155
- ruleCount: 0,
156
- syncDirectory: "/tmp/sync",
157
- }),
158
- ).toContain("Push preview: bundle, bundle/token.txt\n");
159
- expect(
160
- formatSyncDoctorResult({
161
- checks: [
162
- { detail: "ok", level: "ok", name: "git" },
163
- { detail: "warn", level: "warn", name: "entries" },
164
- { detail: "fail", level: "fail", name: "age" },
165
- ],
166
- configPath: "/tmp/sync/config.json",
167
- hasFailures: true,
168
- hasWarnings: true,
169
- syncDirectory: "/tmp/sync",
170
- }),
171
- ).toContain("Summary: 1 ok, 1 warnings, 1 failures.\n");
172
- });
173
- });