@tengx5383/aitool-sync-cli 0.1.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 (153) hide show
  1. package/.claude/settings.local.json +8 -0
  2. package/README.md +203 -0
  3. package/dist/cli.d.ts +2 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +87 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/commands/add.d.ts +2 -0
  8. package/dist/commands/add.d.ts.map +1 -0
  9. package/dist/commands/add.js +24 -0
  10. package/dist/commands/add.js.map +1 -0
  11. package/dist/commands/doctor.d.ts +2 -0
  12. package/dist/commands/doctor.d.ts.map +1 -0
  13. package/dist/commands/doctor.js +89 -0
  14. package/dist/commands/doctor.js.map +1 -0
  15. package/dist/commands/init.d.ts +7 -0
  16. package/dist/commands/init.d.ts.map +1 -0
  17. package/dist/commands/init.js +105 -0
  18. package/dist/commands/init.js.map +1 -0
  19. package/dist/commands/list.d.ts +2 -0
  20. package/dist/commands/list.d.ts.map +1 -0
  21. package/dist/commands/list.js +22 -0
  22. package/dist/commands/list.js.map +1 -0
  23. package/dist/commands/pull.d.ts +6 -0
  24. package/dist/commands/pull.d.ts.map +1 -0
  25. package/dist/commands/pull.js +52 -0
  26. package/dist/commands/pull.js.map +1 -0
  27. package/dist/commands/push.d.ts +6 -0
  28. package/dist/commands/push.d.ts.map +1 -0
  29. package/dist/commands/push.js +60 -0
  30. package/dist/commands/push.js.map +1 -0
  31. package/dist/commands/remove.d.ts +2 -0
  32. package/dist/commands/remove.d.ts.map +1 -0
  33. package/dist/commands/remove.js +20 -0
  34. package/dist/commands/remove.js.map +1 -0
  35. package/dist/commands/status.d.ts +2 -0
  36. package/dist/commands/status.d.ts.map +1 -0
  37. package/dist/commands/status.js +46 -0
  38. package/dist/commands/status.js.map +1 -0
  39. package/dist/config/config-file.d.ts +22 -0
  40. package/dist/config/config-file.d.ts.map +1 -0
  41. package/dist/config/config-file.js +86 -0
  42. package/dist/config/config-file.js.map +1 -0
  43. package/dist/config/schema.d.ts +101 -0
  44. package/dist/config/schema.d.ts.map +1 -0
  45. package/dist/config/schema.js +24 -0
  46. package/dist/config/schema.js.map +1 -0
  47. package/dist/core/backup.d.ts +8 -0
  48. package/dist/core/backup.d.ts.map +1 -0
  49. package/dist/core/backup.js +50 -0
  50. package/dist/core/backup.js.map +1 -0
  51. package/dist/core/checksum.d.ts +14 -0
  52. package/dist/core/checksum.d.ts.map +1 -0
  53. package/dist/core/checksum.js +23 -0
  54. package/dist/core/checksum.js.map +1 -0
  55. package/dist/core/exclusions.d.ts +8 -0
  56. package/dist/core/exclusions.d.ts.map +1 -0
  57. package/dist/core/exclusions.js +29 -0
  58. package/dist/core/exclusions.js.map +1 -0
  59. package/dist/core/file-collector.d.ts +16 -0
  60. package/dist/core/file-collector.d.ts.map +1 -0
  61. package/dist/core/file-collector.js +104 -0
  62. package/dist/core/file-collector.js.map +1 -0
  63. package/dist/core/manifest.d.ts +18 -0
  64. package/dist/core/manifest.d.ts.map +1 -0
  65. package/dist/core/manifest.js +42 -0
  66. package/dist/core/manifest.js.map +1 -0
  67. package/dist/core/path-expander.d.ts +6 -0
  68. package/dist/core/path-expander.d.ts.map +1 -0
  69. package/dist/core/path-expander.js +25 -0
  70. package/dist/core/path-expander.js.map +1 -0
  71. package/dist/core/sync-engine.d.ts +24 -0
  72. package/dist/core/sync-engine.d.ts.map +1 -0
  73. package/dist/core/sync-engine.js +206 -0
  74. package/dist/core/sync-engine.js.map +1 -0
  75. package/dist/core/sync-package.d.ts +12 -0
  76. package/dist/core/sync-package.d.ts.map +1 -0
  77. package/dist/core/sync-package.js +95 -0
  78. package/dist/core/sync-package.js.map +1 -0
  79. package/dist/crypto/encryptor.d.ts +15 -0
  80. package/dist/crypto/encryptor.d.ts.map +1 -0
  81. package/dist/crypto/encryptor.js +77 -0
  82. package/dist/crypto/encryptor.js.map +1 -0
  83. package/dist/crypto/key-resolver.d.ts +28 -0
  84. package/dist/crypto/key-resolver.d.ts.map +1 -0
  85. package/dist/crypto/key-resolver.js +62 -0
  86. package/dist/crypto/key-resolver.js.map +1 -0
  87. package/dist/gist/client.d.ts +18 -0
  88. package/dist/gist/client.d.ts.map +1 -0
  89. package/dist/gist/client.js +58 -0
  90. package/dist/gist/client.js.map +1 -0
  91. package/dist/gist/mock-client.d.ts +19 -0
  92. package/dist/gist/mock-client.d.ts.map +1 -0
  93. package/dist/gist/mock-client.js +61 -0
  94. package/dist/gist/mock-client.js.map +1 -0
  95. package/dist/index.d.ts +3 -0
  96. package/dist/index.d.ts.map +1 -0
  97. package/dist/index.js +3 -0
  98. package/dist/index.js.map +1 -0
  99. package/dist/presets/claude-code.d.ts +3 -0
  100. package/dist/presets/claude-code.d.ts.map +1 -0
  101. package/dist/presets/claude-code.js +27 -0
  102. package/dist/presets/claude-code.js.map +1 -0
  103. package/dist/presets/hermes.d.ts +3 -0
  104. package/dist/presets/hermes.d.ts.map +1 -0
  105. package/dist/presets/hermes.js +27 -0
  106. package/dist/presets/hermes.js.map +1 -0
  107. package/dist/presets/index.d.ts +15 -0
  108. package/dist/presets/index.d.ts.map +1 -0
  109. package/dist/presets/index.js +42 -0
  110. package/dist/presets/index.js.map +1 -0
  111. package/dist/presets/openclaw.d.ts +3 -0
  112. package/dist/presets/openclaw.d.ts.map +1 -0
  113. package/dist/presets/openclaw.js +27 -0
  114. package/dist/presets/openclaw.js.map +1 -0
  115. package/dist/types/config.d.ts +45 -0
  116. package/dist/types/config.d.ts.map +1 -0
  117. package/dist/types/config.js +2 -0
  118. package/dist/types/config.js.map +1 -0
  119. package/dist/types/gist.d.ts +25 -0
  120. package/dist/types/gist.d.ts.map +1 -0
  121. package/dist/types/gist.js +2 -0
  122. package/dist/types/gist.js.map +1 -0
  123. package/dist/types/index.d.ts +4 -0
  124. package/dist/types/index.d.ts.map +1 -0
  125. package/dist/types/index.js +2 -0
  126. package/dist/types/index.js.map +1 -0
  127. package/dist/types/sync.d.ts +78 -0
  128. package/dist/types/sync.d.ts.map +1 -0
  129. package/dist/types/sync.js +2 -0
  130. package/dist/types/sync.js.map +1 -0
  131. package/dist/utils/diff.d.ts +7 -0
  132. package/dist/utils/diff.d.ts.map +1 -0
  133. package/dist/utils/diff.js +99 -0
  134. package/dist/utils/diff.js.map +1 -0
  135. package/dist/utils/env.d.ts +13 -0
  136. package/dist/utils/env.d.ts.map +1 -0
  137. package/dist/utils/env.js +29 -0
  138. package/dist/utils/env.js.map +1 -0
  139. package/dist/utils/logger.d.ts +14 -0
  140. package/dist/utils/logger.d.ts.map +1 -0
  141. package/dist/utils/logger.js +39 -0
  142. package/dist/utils/logger.js.map +1 -0
  143. package/dist/utils/table.d.ts +5 -0
  144. package/dist/utils/table.d.ts.map +1 -0
  145. package/dist/utils/table.js +59 -0
  146. package/dist/utils/table.js.map +1 -0
  147. package/package.json +41 -0
  148. package/tests/integration/encryption-flow.test.ts +142 -0
  149. package/tests/integration/init-flow.test.ts +69 -0
  150. package/tests/integration/push-pull-flow.test.ts +183 -0
  151. package/tests/integration/status-flow.test.ts +149 -0
  152. package/tsconfig.json +19 -0
  153. package/vitest.config.ts +10 -0
@@ -0,0 +1,52 @@
1
+ import ora from 'ora';
2
+ import { readConfig } from '../config/config-file.js';
3
+ import { pullSync } from '../core/sync-engine.js';
4
+ import { GistClient } from '../gist/client.js';
5
+ import { resolveGithubToken } from '../utils/env.js';
6
+ import { success, error } from '../utils/logger.js';
7
+ import { decryptWithPassword, hasPassword } from '../crypto/key-resolver.js';
8
+ export async function pullCommand(options) {
9
+ const config = readConfig();
10
+ if (!config) {
11
+ error('No configuration found. Run `aitool-sync init` first.');
12
+ return;
13
+ }
14
+ if (!config.gistId) {
15
+ error('No Gist configured. Run `aitool-sync init` first or set up a Gist.');
16
+ return;
17
+ }
18
+ const token = resolveGithubToken(config);
19
+ if (!token) {
20
+ error('GitHub token is required for pull.');
21
+ error('Configure it by running `aitool-sync init` or setting GITHUB_TOKEN environment variable.');
22
+ return;
23
+ }
24
+ const spinner = ora('Pulling from Gist...').start();
25
+ try {
26
+ const gistClient = new GistClient(token);
27
+ const decryptFn = config.encryption.length > 0 && hasPassword()
28
+ ? decryptWithPassword
29
+ : undefined;
30
+ const result = await pullSync(config, gistClient, options.force || false, decryptFn);
31
+ spinner.stop();
32
+ if (result.success) {
33
+ success(`Pull complete — ${result.filesDownloaded} file(s) downloaded.`);
34
+ if (result.errors.length > 0) {
35
+ for (const err of result.errors) {
36
+ error(` ${err}`);
37
+ }
38
+ }
39
+ }
40
+ else {
41
+ error('Pull failed:');
42
+ for (const err of result.errors) {
43
+ error(` ${err}`);
44
+ }
45
+ }
46
+ }
47
+ catch (e) {
48
+ spinner.stop();
49
+ error(`Pull failed: ${e.message}`);
50
+ }
51
+ }
52
+ //# sourceMappingURL=pull.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pull.js","sourceRoot":"","sources":["../../src/commands/pull.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAQ,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAM7E,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAoB;IACpD,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,KAAK,CAAC,uDAAuD,CAAC,CAAC;QAC/D,OAAO;IACT,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACnB,KAAK,CAAC,oEAAoE,CAAC,CAAC;QAC5E,OAAO;IACT,CAAC;IAED,MAAM,KAAK,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;IACzC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,KAAK,CAAC,oCAAoC,CAAC,CAAC;QAC5C,KAAK,CAAC,0FAA0F,CAAC,CAAC;QAClG,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,GAAG,CAAC,sBAAsB,CAAC,CAAC,KAAK,EAAE,CAAC;IAEpD,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;QAEzC,MAAM,SAAS,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,IAAI,WAAW,EAAE;YAC7D,CAAC,CAAC,mBAAmB;YACrB,CAAC,CAAC,SAAS,CAAC;QAEd,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,CAAC,KAAK,IAAI,KAAK,EAAE,SAAS,CAAC,CAAC;QACrF,OAAO,CAAC,IAAI,EAAE,CAAC;QAEf,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,OAAO,CAAC,mBAAmB,MAAM,CAAC,eAAe,sBAAsB,CAAC,CAAC;YACzE,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC7B,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;oBAChC,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;gBACpB,CAAC;YACH,CAAC;QACH,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,cAAc,CAAC,CAAC;YACtB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBAChC,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;YACpB,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,OAAO,CAAC,IAAI,EAAE,CAAC;QACf,KAAK,CAAC,gBAAgB,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;IACrC,CAAC;AACH,CAAC"}
@@ -0,0 +1,6 @@
1
+ interface PushOptions {
2
+ force?: boolean;
3
+ }
4
+ export declare function pushCommand(options: PushOptions): Promise<void>;
5
+ export {};
6
+ //# sourceMappingURL=push.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../../src/commands/push.ts"],"names":[],"mappings":"AAQA,UAAU,WAAW;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAyDrE"}
@@ -0,0 +1,60 @@
1
+ import ora from 'ora';
2
+ import { readConfig, writeConfig } from '../config/config-file.js';
3
+ import { pushSync } from '../core/sync-engine.js';
4
+ import { GistClient } from '../gist/client.js';
5
+ import { resolveGithubToken } from '../utils/env.js';
6
+ import { info, success, error } from '../utils/logger.js';
7
+ import { encryptWithPassword, hasPassword } from '../crypto/key-resolver.js';
8
+ export async function pushCommand(options) {
9
+ const config = readConfig();
10
+ if (!config) {
11
+ error('No configuration found. Run `aitool-sync init` first.');
12
+ return;
13
+ }
14
+ if (config.syncPaths.length === 0) {
15
+ error('No sync paths configured. Use `aitool-sync add` to add paths.');
16
+ return;
17
+ }
18
+ const token = resolveGithubToken(config);
19
+ if (!token) {
20
+ error('GitHub token is required for push.');
21
+ error('Configure it by running `aitool-sync init` or setting GITHUB_TOKEN environment variable.');
22
+ return;
23
+ }
24
+ const spinner = ora('Pushing to Gist...').start();
25
+ try {
26
+ const gistClient = new GistClient(token);
27
+ // Create Gist if not exists
28
+ if (!config.gistId) {
29
+ spinner.text = 'Creating new Gist...';
30
+ // Create an empty package first to get a Gist ID
31
+ const gist = await gistClient.createGist('aitool-sync config sync', {
32
+ 'aitool-sync-package.json': { content: '{}' },
33
+ });
34
+ config.gistId = gist.gistId;
35
+ writeConfig(config);
36
+ info(`Created Gist: ${gist.gistId}`);
37
+ }
38
+ // Pass encryption if configured
39
+ const encryptFn = config.encryption.length > 0 && hasPassword()
40
+ ? encryptWithPassword
41
+ : undefined;
42
+ spinner.text = 'Uploading files...';
43
+ const result = await pushSync(config, gistClient, options.force || false, encryptFn);
44
+ spinner.stop();
45
+ if (result.success) {
46
+ success(`Push complete — ${result.filesUploaded} file(s) uploaded.`);
47
+ }
48
+ else {
49
+ error('Push failed:');
50
+ for (const err of result.errors) {
51
+ error(` ${err}`);
52
+ }
53
+ }
54
+ }
55
+ catch (e) {
56
+ spinner.stop();
57
+ error(`Push failed: ${e.message}`);
58
+ }
59
+ }
60
+ //# sourceMappingURL=push.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"push.js","sourceRoot":"","sources":["../../src/commands/push.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAM7E,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAoB;IACpD,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,KAAK,CAAC,uDAAuD,CAAC,CAAC;QAC/D,OAAO;IACT,CAAC;IAED,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,KAAK,CAAC,+DAA+D,CAAC,CAAC;QACvE,OAAO;IACT,CAAC;IAED,MAAM,KAAK,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;IACzC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,KAAK,CAAC,oCAAoC,CAAC,CAAC;QAC5C,KAAK,CAAC,0FAA0F,CAAC,CAAC;QAClG,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,GAAG,CAAC,oBAAoB,CAAC,CAAC,KAAK,EAAE,CAAC;IAElD,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;QAEzC,4BAA4B;QAC5B,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACnB,OAAO,CAAC,IAAI,GAAG,sBAAsB,CAAC;YACtC,iDAAiD;YACjD,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,UAAU,CAAC,yBAAyB,EAAE;gBAClE,0BAA0B,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;aAC9C,CAAC,CAAC;YACH,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;YAC5B,WAAW,CAAC,MAAM,CAAC,CAAC;YACpB,IAAI,CAAC,iBAAiB,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QACvC,CAAC;QAED,gCAAgC;QAChC,MAAM,SAAS,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,IAAI,WAAW,EAAE;YAC7D,CAAC,CAAC,mBAAmB;YACrB,CAAC,CAAC,SAAS,CAAC;QAEd,OAAO,CAAC,IAAI,GAAG,oBAAoB,CAAC;QACpC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,CAAC,KAAK,IAAI,KAAK,EAAE,SAAS,CAAC,CAAC;QACrF,OAAO,CAAC,IAAI,EAAE,CAAC;QAEf,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,OAAO,CAAC,mBAAmB,MAAM,CAAC,aAAa,oBAAoB,CAAC,CAAC;QACvE,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,cAAc,CAAC,CAAC;YACtB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBAChC,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;YACpB,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,OAAO,CAAC,IAAI,EAAE,CAAC;QACf,KAAK,CAAC,gBAAgB,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;IACrC,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function removeCommand(name: string): Promise<void>;
2
+ //# sourceMappingURL=remove.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remove.d.ts","sourceRoot":"","sources":["../../src/commands/remove.ts"],"names":[],"mappings":"AAGA,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkB/D"}
@@ -0,0 +1,20 @@
1
+ import { readConfig, writeConfig } from '../config/config-file.js';
2
+ import { success, error } from '../utils/logger.js';
3
+ export async function removeCommand(name) {
4
+ const config = readConfig();
5
+ if (!config) {
6
+ error('No configuration found. Run `aitool-sync init` first.');
7
+ return;
8
+ }
9
+ const index = config.syncPaths.findIndex((p) => p.name === name);
10
+ if (index === -1) {
11
+ error(`No path found with name "${name}".`);
12
+ error('Use `aitool-sync list` to see tracked paths.');
13
+ return;
14
+ }
15
+ const removed = config.syncPaths[index];
16
+ config.syncPaths.splice(index, 1);
17
+ writeConfig(config);
18
+ success(`Removed "${removed.name}" (${removed.path})`);
19
+ }
20
+ //# sourceMappingURL=remove.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remove.js","sourceRoot":"","sources":["../../src/commands/remove.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAEpD,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAY;IAC9C,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,KAAK,CAAC,uDAAuD,CAAC,CAAC;QAC/D,OAAO;IACT,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IACjE,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC;QACjB,KAAK,CAAC,4BAA4B,IAAI,IAAI,CAAC,CAAC;QAC5C,KAAK,CAAC,8CAA8C,CAAC,CAAC;QACtD,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAClC,WAAW,CAAC,MAAM,CAAC,CAAC;IACpB,OAAO,CAAC,YAAY,OAAO,CAAC,IAAI,MAAM,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC;AACzD,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function statusCommand(): Promise<void>;
2
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AASA,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CA0CnD"}
@@ -0,0 +1,46 @@
1
+ import { readConfig } from '../config/config-file.js';
2
+ import { buildLocalManifest } from '../core/sync-engine.js';
3
+ import { parseManifest } from '../core/manifest.js';
4
+ import { diffManifests } from '../utils/diff.js';
5
+ import { renderDiffTable } from '../utils/table.js';
6
+ import { info, warn, error } from '../utils/logger.js';
7
+ export async function statusCommand() {
8
+ const config = readConfig();
9
+ if (!config) {
10
+ error('No configuration found. Run `aitool-sync init` first.');
11
+ return;
12
+ }
13
+ if (config.syncPaths.length === 0) {
14
+ warn('No sync paths configured. Use `aitool-sync add` to add paths.');
15
+ return;
16
+ }
17
+ const localManifest = buildLocalManifest(config);
18
+ // For now, when no remote or no Gist is configured, show local state
19
+ if (!config.gistId) {
20
+ info('No Gist configured. Showing local state only.');
21
+ info(`Local files tracked: ${localManifest.entries.length}`);
22
+ for (const entry of localManifest.entries) {
23
+ info(` ${entry.relativePath} (${entry.sourceName})`);
24
+ }
25
+ info('');
26
+ info('Set up a Gist with `aitool-sync init` and run `aitool-sync push` to upload.');
27
+ return;
28
+ }
29
+ // With a real token, we'd fetch the remote Gist here.
30
+ // For the initial implementation, show local state.
31
+ const lastKnown = config.lastKnownManifest ? parseManifest(config.lastKnownManifest) : null;
32
+ if (lastKnown) {
33
+ // Compare local against last known
34
+ const diff = diffManifests(localManifest, lastKnown, localManifest);
35
+ renderDiffTable(diff.added, diff.removed, diff.modified, diff.conflicts);
36
+ }
37
+ else {
38
+ info(`Local files tracked: ${localManifest.entries.length}`);
39
+ for (const entry of localManifest.entries) {
40
+ info(` ${entry.relativePath} (${entry.sourceName})`);
41
+ }
42
+ info('');
43
+ info('No previous sync state. Run `aitool-sync push` to set the baseline.');
44
+ }
45
+ }
46
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAIvD,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,KAAK,CAAC,uDAAuD,CAAC,CAAC;QAC/D,OAAO;IACT,CAAC;IAED,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,IAAI,CAAC,+DAA+D,CAAC,CAAC;QACtE,OAAO;IACT,CAAC;IAED,MAAM,aAAa,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAEjD,qEAAqE;IACrE,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACnB,IAAI,CAAC,+CAA+C,CAAC,CAAC;QACtD,IAAI,CAAC,wBAAwB,aAAa,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QAC7D,KAAK,MAAM,KAAK,IAAI,aAAa,CAAC,OAAO,EAAE,CAAC;YAC1C,IAAI,CAAC,KAAK,KAAK,CAAC,YAAY,KAAK,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC;QACxD,CAAC;QACD,IAAI,CAAC,EAAE,CAAC,CAAC;QACT,IAAI,CAAC,6EAA6E,CAAC,CAAC;QACpF,OAAO;IACT,CAAC;IAED,sDAAsD;IACtD,oDAAoD;IACpD,MAAM,SAAS,GAAG,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAE5F,IAAI,SAAS,EAAE,CAAC;QACd,mCAAmC;QACnC,MAAM,IAAI,GAAG,aAAa,CAAC,aAAa,EAAE,SAAS,EAAE,aAAa,CAAC,CAAC;QACpE,eAAe,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;IAC3E,CAAC;SAAM,CAAC;QACN,IAAI,CAAC,wBAAwB,aAAa,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QAC7D,KAAK,MAAM,KAAK,IAAI,aAAa,CAAC,OAAO,EAAE,CAAC;YAC1C,IAAI,CAAC,KAAK,KAAK,CAAC,YAAY,KAAK,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC;QACxD,CAAC;QACD,IAAI,CAAC,EAAE,CAAC,CAAC;QACT,IAAI,CAAC,qEAAqE,CAAC,CAAC;IAC9E,CAAC;AACH,CAAC"}
@@ -0,0 +1,22 @@
1
+ import type { AppConfig } from '../types/config.js';
2
+ /**
3
+ * Get the full path to the config file in the given directory.
4
+ */
5
+ export declare function configFilePath(dir?: string): string;
6
+ /**
7
+ * Find the config file by walking up from cwd.
8
+ */
9
+ export declare function findConfigFile(): string | null;
10
+ /**
11
+ * Read and validate the config file.
12
+ */
13
+ export declare function readConfig(filePath?: string): AppConfig | null;
14
+ /**
15
+ * Write the config file to disk.
16
+ */
17
+ export declare function writeConfig(config: AppConfig, dir?: string): void;
18
+ /**
19
+ * Create a default AppConfig structure.
20
+ */
21
+ export declare function createDefaultConfig(): AppConfig;
22
+ //# sourceMappingURL=config-file.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-file.d.ts","sourceRoot":"","sources":["../../src/config/config-file.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAKpD;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAGnD;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,MAAM,GAAG,IAAI,CAY9C;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAoB9D;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAKjE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,SAAS,CAkB/C"}
@@ -0,0 +1,86 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { AppConfigSchema } from './schema.js';
4
+ import { debug, error, warn } from '../utils/logger.js';
5
+ const CONFIG_FILENAME = '.aitoolsync.json';
6
+ /**
7
+ * Get the full path to the config file in the given directory.
8
+ */
9
+ export function configFilePath(dir) {
10
+ const cwd = dir || process.cwd();
11
+ return path.resolve(cwd, CONFIG_FILENAME);
12
+ }
13
+ /**
14
+ * Find the config file by walking up from cwd.
15
+ */
16
+ export function findConfigFile() {
17
+ let current = process.cwd();
18
+ for (let i = 0; i < 32; i++) {
19
+ const candidate = configFilePath(current);
20
+ if (fs.existsSync(candidate)) {
21
+ return candidate;
22
+ }
23
+ const parent = path.dirname(current);
24
+ if (parent === current)
25
+ break;
26
+ current = parent;
27
+ }
28
+ return null;
29
+ }
30
+ /**
31
+ * Read and validate the config file.
32
+ */
33
+ export function readConfig(filePath) {
34
+ const target = filePath || findConfigFile();
35
+ if (!target) {
36
+ debug('No .aitoolsync.json found.');
37
+ return null;
38
+ }
39
+ try {
40
+ const raw = fs.readFileSync(target, 'utf-8');
41
+ const parsed = JSON.parse(raw);
42
+ const validated = AppConfigSchema.parse(parsed);
43
+ return validated;
44
+ }
45
+ catch (e) {
46
+ if (e.name === 'ZodError') {
47
+ warn(`Invalid config schema in ${target}: ${e.message}`);
48
+ }
49
+ else {
50
+ error(`Failed to read config at ${target}: ${e.message}`);
51
+ }
52
+ return null;
53
+ }
54
+ }
55
+ /**
56
+ * Write the config file to disk.
57
+ */
58
+ export function writeConfig(config, dir) {
59
+ const target = configFilePath(dir);
60
+ const data = JSON.stringify(config, null, 2);
61
+ fs.writeFileSync(target, data, 'utf-8');
62
+ debug(`Config written to ${target}`);
63
+ }
64
+ /**
65
+ * Create a default AppConfig structure.
66
+ */
67
+ export function createDefaultConfig() {
68
+ return {
69
+ version: 1,
70
+ gistId: null,
71
+ githubToken: null,
72
+ syncPaths: [],
73
+ exclusions: [
74
+ { pattern: '**/node_modules/**' },
75
+ { pattern: '**/.git/**' },
76
+ { pattern: '**/dist/**' },
77
+ { pattern: '**/*.log' },
78
+ { pattern: '**/.DS_Store' },
79
+ ],
80
+ encryption: [],
81
+ lastKnownManifest: null,
82
+ lastPushAt: null,
83
+ lastPullAt: null,
84
+ };
85
+ }
86
+ //# sourceMappingURL=config-file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-file.js","sourceRoot":"","sources":["../../src/config/config-file.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,101 @@
1
+ import { z } from 'zod';
2
+ export declare const SyncPathEntrySchema: z.ZodObject<{
3
+ name: z.ZodString;
4
+ path: z.ZodString;
5
+ enabled: z.ZodDefault<z.ZodBoolean>;
6
+ }, "strip", z.ZodTypeAny, {
7
+ name: string;
8
+ path: string;
9
+ enabled: boolean;
10
+ }, {
11
+ name: string;
12
+ path: string;
13
+ enabled?: boolean | undefined;
14
+ }>;
15
+ export declare const ExclusionRuleSchema: z.ZodObject<{
16
+ pattern: z.ZodString;
17
+ }, "strip", z.ZodTypeAny, {
18
+ pattern: string;
19
+ }, {
20
+ pattern: string;
21
+ }>;
22
+ export declare const EncryptionRuleSchema: z.ZodObject<{
23
+ pattern: z.ZodString;
24
+ }, "strip", z.ZodTypeAny, {
25
+ pattern: string;
26
+ }, {
27
+ pattern: string;
28
+ }>;
29
+ export declare const AppConfigSchema: z.ZodObject<{
30
+ version: z.ZodLiteral<1>;
31
+ gistId: z.ZodDefault<z.ZodNullable<z.ZodString>>;
32
+ githubToken: z.ZodDefault<z.ZodNullable<z.ZodString>>;
33
+ syncPaths: z.ZodDefault<z.ZodArray<z.ZodObject<{
34
+ name: z.ZodString;
35
+ path: z.ZodString;
36
+ enabled: z.ZodDefault<z.ZodBoolean>;
37
+ }, "strip", z.ZodTypeAny, {
38
+ name: string;
39
+ path: string;
40
+ enabled: boolean;
41
+ }, {
42
+ name: string;
43
+ path: string;
44
+ enabled?: boolean | undefined;
45
+ }>, "many">>;
46
+ exclusions: z.ZodDefault<z.ZodArray<z.ZodObject<{
47
+ pattern: z.ZodString;
48
+ }, "strip", z.ZodTypeAny, {
49
+ pattern: string;
50
+ }, {
51
+ pattern: string;
52
+ }>, "many">>;
53
+ encryption: z.ZodDefault<z.ZodArray<z.ZodObject<{
54
+ pattern: z.ZodString;
55
+ }, "strip", z.ZodTypeAny, {
56
+ pattern: string;
57
+ }, {
58
+ pattern: string;
59
+ }>, "many">>;
60
+ lastKnownManifest: z.ZodDefault<z.ZodNullable<z.ZodString>>;
61
+ lastPushAt: z.ZodDefault<z.ZodNullable<z.ZodString>>;
62
+ lastPullAt: z.ZodDefault<z.ZodNullable<z.ZodString>>;
63
+ }, "strip", z.ZodTypeAny, {
64
+ version: 1;
65
+ gistId: string | null;
66
+ githubToken: string | null;
67
+ syncPaths: {
68
+ name: string;
69
+ path: string;
70
+ enabled: boolean;
71
+ }[];
72
+ exclusions: {
73
+ pattern: string;
74
+ }[];
75
+ encryption: {
76
+ pattern: string;
77
+ }[];
78
+ lastKnownManifest: string | null;
79
+ lastPushAt: string | null;
80
+ lastPullAt: string | null;
81
+ }, {
82
+ version: 1;
83
+ gistId?: string | null | undefined;
84
+ githubToken?: string | null | undefined;
85
+ syncPaths?: {
86
+ name: string;
87
+ path: string;
88
+ enabled?: boolean | undefined;
89
+ }[] | undefined;
90
+ exclusions?: {
91
+ pattern: string;
92
+ }[] | undefined;
93
+ encryption?: {
94
+ pattern: string;
95
+ }[] | undefined;
96
+ lastKnownManifest?: string | null | undefined;
97
+ lastPushAt?: string | null | undefined;
98
+ lastPullAt?: string | null | undefined;
99
+ }>;
100
+ export type AppConfigParsed = z.infer<typeof AppConfigSchema>;
101
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,mBAAmB;;;;;;;;;;;;EAI9B,CAAC;AAEH,eAAO,MAAM,mBAAmB;;;;;;EAE9B,CAAC;AAEH,eAAO,MAAM,oBAAoB;;;;;;EAE/B,CAAC;AAEH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAU1B,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC"}
@@ -0,0 +1,24 @@
1
+ import { z } from 'zod';
2
+ export const SyncPathEntrySchema = z.object({
3
+ name: z.string().min(1),
4
+ path: z.string().min(1),
5
+ enabled: z.boolean().default(true),
6
+ });
7
+ export const ExclusionRuleSchema = z.object({
8
+ pattern: z.string().min(1),
9
+ });
10
+ export const EncryptionRuleSchema = z.object({
11
+ pattern: z.string().min(1),
12
+ });
13
+ export const AppConfigSchema = z.object({
14
+ version: z.literal(1),
15
+ gistId: z.string().nullable().default(null),
16
+ githubToken: z.string().nullable().default(null),
17
+ syncPaths: z.array(SyncPathEntrySchema).default([]),
18
+ exclusions: z.array(ExclusionRuleSchema).default([]),
19
+ encryption: z.array(EncryptionRuleSchema).default([]),
20
+ lastKnownManifest: z.string().nullable().default(null),
21
+ lastPushAt: z.string().nullable().default(null),
22
+ lastPullAt: z.string().nullable().default(null),
23
+ });
24
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1C,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;CACnC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1C,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CAC3B,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CAC3B,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC;IACtC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IACrB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAC3C,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAChD,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IACnD,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IACpD,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IACrD,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IACtD,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAC/C,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;CAChD,CAAC,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { AppConfig } from '../types/config.js';
2
+ /**
3
+ * Create a timestamped backup of all currently synced files
4
+ * before a pull operation.
5
+ * Returns the backup directory path.
6
+ */
7
+ export declare function createBackup(config: AppConfig): string;
8
+ //# sourceMappingURL=backup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backup.d.ts","sourceRoot":"","sources":["../../src/core/backup.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAIpD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CA0BtD"}
@@ -0,0 +1,50 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import os from 'node:os';
4
+ import { debug } from '../utils/logger.js';
5
+ import { expandPath } from './path-expander.js';
6
+ /**
7
+ * Create a timestamped backup of all currently synced files
8
+ * before a pull operation.
9
+ * Returns the backup directory path.
10
+ */
11
+ export function createBackup(config) {
12
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
13
+ const backupDir = path.join(os.tmpdir(), `aitool-sync-backup-${timestamp}`);
14
+ fs.mkdirSync(backupDir, { recursive: true });
15
+ debug(`Creating backup in ${backupDir}`);
16
+ for (const syncPath of config.syncPaths) {
17
+ if (!syncPath.enabled)
18
+ continue;
19
+ const expanded = expandPath(syncPath.path);
20
+ const sourceName = syncPath.name;
21
+ if (!fs.existsSync(expanded))
22
+ continue;
23
+ const stat = fs.statSync(expanded);
24
+ if (stat.isDirectory()) {
25
+ copyDirectory(expanded, path.join(backupDir, sourceName));
26
+ }
27
+ else if (stat.isFile()) {
28
+ const destDir = path.join(backupDir, sourceName);
29
+ fs.mkdirSync(destDir, { recursive: true });
30
+ fs.copyFileSync(expanded, path.join(destDir, path.basename(expanded)));
31
+ }
32
+ }
33
+ debug(`Backup created at ${backupDir}`);
34
+ return backupDir;
35
+ }
36
+ function copyDirectory(src, dest) {
37
+ fs.mkdirSync(dest, { recursive: true });
38
+ const entries = fs.readdirSync(src, { withFileTypes: true });
39
+ for (const entry of entries) {
40
+ const srcPath = path.join(src, entry.name);
41
+ const destPath = path.join(dest, entry.name);
42
+ if (entry.isDirectory()) {
43
+ copyDirectory(srcPath, destPath);
44
+ }
45
+ else {
46
+ fs.copyFileSync(srcPath, destPath);
47
+ }
48
+ }
49
+ }
50
+ //# sourceMappingURL=backup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backup.js","sourceRoot":"","sources":["../../src/core/backup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,OAAO,EAAE,KAAK,EAAQ,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEhD;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,MAAiB;IAC5C,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IACjE,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,sBAAsB,SAAS,EAAE,CAAC,CAAC;IAC5E,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,KAAK,CAAC,sBAAsB,SAAS,EAAE,CAAC,CAAC;IAEzC,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;QACxC,IAAI,CAAC,QAAQ,CAAC,OAAO;YAAE,SAAS;QAEhC,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC3C,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAI,CAAC;QAEjC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;YAAE,SAAS;QAEvC,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACnC,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;YACvB,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC;QAC5D,CAAC;aAAM,IAAI,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;YACzB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;YACjD,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC3C,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QACzE,CAAC;IACH,CAAC;IAED,KAAK,CAAC,qBAAqB,SAAS,EAAE,CAAC,CAAC;IACxC,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,aAAa,CAAC,GAAW,EAAE,IAAY;IAC9C,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACxC,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAE7D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAE7C,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,aAAa,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACnC,CAAC;aAAM,CAAC;YACN,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACrC,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Compute SHA-256 checksum of file contents.
3
+ * Returns hex string.
4
+ */
5
+ export declare function computeChecksum(filePath: string): string;
6
+ /**
7
+ * Compute SHA-256 checksum of a string buffer.
8
+ */
9
+ export declare function computeChecksumFromBuffer(buffer: Buffer | string): string;
10
+ /**
11
+ * Compute SHA-256 checksum of a string.
12
+ */
13
+ export declare function computeChecksumFromString(content: string): string;
14
+ //# sourceMappingURL=checksum.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checksum.d.ts","sourceRoot":"","sources":["../../src/core/checksum.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGxD;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAEzE;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEjE"}
@@ -0,0 +1,23 @@
1
+ import crypto from 'node:crypto';
2
+ import fs from 'node:fs';
3
+ /**
4
+ * Compute SHA-256 checksum of file contents.
5
+ * Returns hex string.
6
+ */
7
+ export function computeChecksum(filePath) {
8
+ const content = fs.readFileSync(filePath);
9
+ return crypto.createHash('sha256').update(content).digest('hex');
10
+ }
11
+ /**
12
+ * Compute SHA-256 checksum of a string buffer.
13
+ */
14
+ export function computeChecksumFromBuffer(buffer) {
15
+ return crypto.createHash('sha256').update(buffer).digest('hex');
16
+ }
17
+ /**
18
+ * Compute SHA-256 checksum of a string.
19
+ */
20
+ export function computeChecksumFromString(content) {
21
+ return crypto.createHash('sha256').update(content, 'utf-8').digest('hex');
22
+ }
23
+ //# sourceMappingURL=checksum.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checksum.js","sourceRoot":"","sources":["../../src/core/checksum.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,QAAgB;IAC9C,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;IAC1C,OAAO,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACnE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,yBAAyB,CAAC,MAAuB;IAC/D,OAAO,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAClE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,yBAAyB,CAAC,OAAe;IACvD,OAAO,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC5E,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { ExclusionRule } from '../types/config.js';
2
+ /**
3
+ * Check whether a relative path should be excluded based on exclusion rules.
4
+ * Rules are glob patterns matched against the relative path.
5
+ * A leading ! negates the pattern (include override).
6
+ */
7
+ export declare function isExcluded(relativePath: string, rules: ExclusionRule[]): boolean;
8
+ //# sourceMappingURL=exclusions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exclusions.d.ts","sourceRoot":"","sources":["../../src/core/exclusions.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAUxD;;;;GAIG;AACH,wBAAgB,UAAU,CACxB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,aAAa,EAAE,GACrB,OAAO,CAgBT"}
@@ -0,0 +1,29 @@
1
+ import micromatch from 'micromatch';
2
+ const DEFAULT_EXCLUSIONS = [
3
+ { pattern: '**/node_modules/**' },
4
+ { pattern: '**/.git/**' },
5
+ { pattern: '**/dist/**' },
6
+ { pattern: '**/*.log' },
7
+ { pattern: '**/.DS_Store' },
8
+ ];
9
+ /**
10
+ * Check whether a relative path should be excluded based on exclusion rules.
11
+ * Rules are glob patterns matched against the relative path.
12
+ * A leading ! negates the pattern (include override).
13
+ */
14
+ export function isExcluded(relativePath, rules) {
15
+ const patterns = rules.map((r) => r.pattern);
16
+ if (patterns.length === 0)
17
+ return false;
18
+ // If the path matches a negated pattern, it's included
19
+ const negated = patterns.filter((p) => p.startsWith('!'));
20
+ for (const p of negated) {
21
+ if (micromatch.isMatch(relativePath, p.slice(1))) {
22
+ return false;
23
+ }
24
+ }
25
+ // Check positive patterns
26
+ const positive = patterns.filter((p) => !p.startsWith('!'));
27
+ return micromatch.isMatch(relativePath, positive);
28
+ }
29
+ //# sourceMappingURL=exclusions.js.map