ctx-sync 1.0.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 (145) hide show
  1. package/dist/commands/audit.d.ts +76 -0
  2. package/dist/commands/audit.d.ts.map +1 -0
  3. package/dist/commands/audit.js +367 -0
  4. package/dist/commands/audit.js.map +1 -0
  5. package/dist/commands/config.d.ts +58 -0
  6. package/dist/commands/config.d.ts.map +1 -0
  7. package/dist/commands/config.js +114 -0
  8. package/dist/commands/config.js.map +1 -0
  9. package/dist/commands/dir.d.ts +56 -0
  10. package/dist/commands/dir.d.ts.map +1 -0
  11. package/dist/commands/dir.js +172 -0
  12. package/dist/commands/dir.js.map +1 -0
  13. package/dist/commands/docker.d.ts +140 -0
  14. package/dist/commands/docker.d.ts.map +1 -0
  15. package/dist/commands/docker.js +380 -0
  16. package/dist/commands/docker.js.map +1 -0
  17. package/dist/commands/env.d.ts +96 -0
  18. package/dist/commands/env.d.ts.map +1 -0
  19. package/dist/commands/env.js +352 -0
  20. package/dist/commands/env.js.map +1 -0
  21. package/dist/commands/init.d.ts +89 -0
  22. package/dist/commands/init.d.ts.map +1 -0
  23. package/dist/commands/init.js +272 -0
  24. package/dist/commands/init.js.map +1 -0
  25. package/dist/commands/key.d.ts +92 -0
  26. package/dist/commands/key.d.ts.map +1 -0
  27. package/dist/commands/key.js +274 -0
  28. package/dist/commands/key.js.map +1 -0
  29. package/dist/commands/list.d.ts +38 -0
  30. package/dist/commands/list.d.ts.map +1 -0
  31. package/dist/commands/list.js +84 -0
  32. package/dist/commands/list.js.map +1 -0
  33. package/dist/commands/note.d.ts +151 -0
  34. package/dist/commands/note.d.ts.map +1 -0
  35. package/dist/commands/note.js +411 -0
  36. package/dist/commands/note.js.map +1 -0
  37. package/dist/commands/pull.d.ts +47 -0
  38. package/dist/commands/pull.d.ts.map +1 -0
  39. package/dist/commands/pull.js +94 -0
  40. package/dist/commands/pull.js.map +1 -0
  41. package/dist/commands/push.d.ts +40 -0
  42. package/dist/commands/push.d.ts.map +1 -0
  43. package/dist/commands/push.js +94 -0
  44. package/dist/commands/push.js.map +1 -0
  45. package/dist/commands/restore.d.ts +116 -0
  46. package/dist/commands/restore.d.ts.map +1 -0
  47. package/dist/commands/restore.js +336 -0
  48. package/dist/commands/restore.js.map +1 -0
  49. package/dist/commands/service.d.ts +83 -0
  50. package/dist/commands/service.d.ts.map +1 -0
  51. package/dist/commands/service.js +259 -0
  52. package/dist/commands/service.js.map +1 -0
  53. package/dist/commands/show.d.ts +63 -0
  54. package/dist/commands/show.d.ts.map +1 -0
  55. package/dist/commands/show.js +243 -0
  56. package/dist/commands/show.js.map +1 -0
  57. package/dist/commands/status.d.ts +53 -0
  58. package/dist/commands/status.d.ts.map +1 -0
  59. package/dist/commands/status.js +150 -0
  60. package/dist/commands/status.js.map +1 -0
  61. package/dist/commands/sync.d.ts +105 -0
  62. package/dist/commands/sync.d.ts.map +1 -0
  63. package/dist/commands/sync.js +243 -0
  64. package/dist/commands/sync.js.map +1 -0
  65. package/dist/commands/team.d.ts +79 -0
  66. package/dist/commands/team.d.ts.map +1 -0
  67. package/dist/commands/team.js +233 -0
  68. package/dist/commands/team.js.map +1 -0
  69. package/dist/commands/track.d.ts +109 -0
  70. package/dist/commands/track.d.ts.map +1 -0
  71. package/dist/commands/track.js +406 -0
  72. package/dist/commands/track.js.map +1 -0
  73. package/dist/core/command-validator.d.ts +100 -0
  74. package/dist/core/command-validator.d.ts.map +1 -0
  75. package/dist/core/command-validator.js +299 -0
  76. package/dist/core/command-validator.js.map +1 -0
  77. package/dist/core/config-store.d.ts +76 -0
  78. package/dist/core/config-store.d.ts.map +1 -0
  79. package/dist/core/config-store.js +148 -0
  80. package/dist/core/config-store.js.map +1 -0
  81. package/dist/core/directories-handler.d.ts +116 -0
  82. package/dist/core/directories-handler.d.ts.map +1 -0
  83. package/dist/core/directories-handler.js +199 -0
  84. package/dist/core/directories-handler.js.map +1 -0
  85. package/dist/core/docker-handler.d.ts +183 -0
  86. package/dist/core/docker-handler.d.ts.map +1 -0
  87. package/dist/core/docker-handler.js +515 -0
  88. package/dist/core/docker-handler.js.map +1 -0
  89. package/dist/core/encryption.d.ts +79 -0
  90. package/dist/core/encryption.d.ts.map +1 -0
  91. package/dist/core/encryption.js +111 -0
  92. package/dist/core/encryption.js.map +1 -0
  93. package/dist/core/env-handler.d.ts +128 -0
  94. package/dist/core/env-handler.d.ts.map +1 -0
  95. package/dist/core/env-handler.js +272 -0
  96. package/dist/core/env-handler.js.map +1 -0
  97. package/dist/core/git-sync.d.ts +88 -0
  98. package/dist/core/git-sync.d.ts.map +1 -0
  99. package/dist/core/git-sync.js +143 -0
  100. package/dist/core/git-sync.js.map +1 -0
  101. package/dist/core/key-store.d.ts +51 -0
  102. package/dist/core/key-store.d.ts.map +1 -0
  103. package/dist/core/key-store.js +108 -0
  104. package/dist/core/key-store.js.map +1 -0
  105. package/dist/core/log-sanitizer.d.ts +72 -0
  106. package/dist/core/log-sanitizer.d.ts.map +1 -0
  107. package/dist/core/log-sanitizer.js +202 -0
  108. package/dist/core/log-sanitizer.js.map +1 -0
  109. package/dist/core/path-validator.d.ts +37 -0
  110. package/dist/core/path-validator.d.ts.map +1 -0
  111. package/dist/core/path-validator.js +127 -0
  112. package/dist/core/path-validator.js.map +1 -0
  113. package/dist/core/recipients.d.ts +99 -0
  114. package/dist/core/recipients.d.ts.map +1 -0
  115. package/dist/core/recipients.js +206 -0
  116. package/dist/core/recipients.js.map +1 -0
  117. package/dist/core/services-handler.d.ts +113 -0
  118. package/dist/core/services-handler.d.ts.map +1 -0
  119. package/dist/core/services-handler.js +176 -0
  120. package/dist/core/services-handler.js.map +1 -0
  121. package/dist/core/state-manager.d.ts +96 -0
  122. package/dist/core/state-manager.d.ts.map +1 -0
  123. package/dist/core/state-manager.js +165 -0
  124. package/dist/core/state-manager.js.map +1 -0
  125. package/dist/core/transport.d.ts +28 -0
  126. package/dist/core/transport.d.ts.map +1 -0
  127. package/dist/core/transport.js +79 -0
  128. package/dist/core/transport.js.map +1 -0
  129. package/dist/index.d.ts +20 -0
  130. package/dist/index.d.ts.map +1 -0
  131. package/dist/index.js +80 -0
  132. package/dist/index.js.map +1 -0
  133. package/dist/types/index.d.ts +5 -0
  134. package/dist/types/index.d.ts.map +1 -0
  135. package/dist/types/index.js +2 -0
  136. package/dist/types/index.js.map +1 -0
  137. package/dist/utils/errors.d.ts +81 -0
  138. package/dist/utils/errors.d.ts.map +1 -0
  139. package/dist/utils/errors.js +191 -0
  140. package/dist/utils/errors.js.map +1 -0
  141. package/dist/utils/secure-memory.d.ts +65 -0
  142. package/dist/utils/secure-memory.d.ts.map +1 -0
  143. package/dist/utils/secure-memory.js +86 -0
  144. package/dist/utils/secure-memory.js.map +1 -0
  145. package/package.json +58 -0
package/dist/index.js ADDED
@@ -0,0 +1,80 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * ctx-sync — Sync your complete development context across machines.
4
+ *
5
+ * CLI entry point. Uses Commander.js for command parsing and routing.
6
+ *
7
+ * @module ctx-sync
8
+ */
9
+ import { Command } from 'commander';
10
+ import { VERSION } from '@ctx-sync/shared';
11
+ import { formatError } from './utils/errors.js';
12
+ import { registerInitCommand } from './commands/init.js';
13
+ import { registerTrackCommand } from './commands/track.js';
14
+ import { registerListCommand } from './commands/list.js';
15
+ import { registerStatusCommand } from './commands/status.js';
16
+ import { registerEnvCommand } from './commands/env.js';
17
+ import { registerSyncCommand } from './commands/sync.js';
18
+ import { registerPushCommand } from './commands/push.js';
19
+ import { registerPullCommand } from './commands/pull.js';
20
+ import { registerRestoreCommand } from './commands/restore.js';
21
+ import { registerNoteCommand } from './commands/note.js';
22
+ import { registerShowCommand } from './commands/show.js';
23
+ import { registerDockerCommand } from './commands/docker.js';
24
+ import { registerServiceCommand } from './commands/service.js';
25
+ import { registerDirCommand } from './commands/dir.js';
26
+ import { registerKeyCommand } from './commands/key.js';
27
+ import { registerAuditCommand } from './commands/audit.js';
28
+ import { registerTeamCommand } from './commands/team.js';
29
+ import { registerConfigCommand } from './commands/config.js';
30
+ /**
31
+ * Create and configure the root CLI program.
32
+ *
33
+ * @returns The configured Commander program instance.
34
+ */
35
+ export function createProgram() {
36
+ const program = new Command();
37
+ program
38
+ .name('ctx-sync')
39
+ .description('Sync your complete development context across machines')
40
+ .version(VERSION, '-V, --version');
41
+ // Register subcommands
42
+ registerInitCommand(program);
43
+ registerTrackCommand(program);
44
+ registerListCommand(program);
45
+ registerStatusCommand(program);
46
+ registerEnvCommand(program);
47
+ registerSyncCommand(program);
48
+ registerPushCommand(program);
49
+ registerPullCommand(program);
50
+ registerRestoreCommand(program);
51
+ registerNoteCommand(program);
52
+ registerShowCommand(program);
53
+ registerDockerCommand(program);
54
+ registerServiceCommand(program);
55
+ registerDirCommand(program);
56
+ registerKeyCommand(program);
57
+ registerAuditCommand(program);
58
+ registerTeamCommand(program);
59
+ registerConfigCommand(program);
60
+ return program;
61
+ }
62
+ /**
63
+ * Main entry point — parse CLI arguments and execute the matched command.
64
+ */
65
+ export async function main(argv) {
66
+ const program = createProgram();
67
+ await program.parseAsync(argv ?? process.argv);
68
+ }
69
+ // Run when executed directly (not imported as a module in tests)
70
+ const isDirectExecution = process.argv[1] &&
71
+ (process.argv[1].endsWith('/index.ts') ||
72
+ process.argv[1].endsWith('/index.js') ||
73
+ process.argv[1].endsWith('ctx-sync'));
74
+ if (isDirectExecution) {
75
+ main().catch((err) => {
76
+ console.error(formatError(err));
77
+ process.exit(1);
78
+ });
79
+ }
80
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Re-export shared types for convenience.
3
+ */
4
+ export type { Project, EnvVars, DockerState, MentalContext, ServiceState, DirectoryState, Manifest, } from '@ctx-sync/shared';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,YAAY,EACV,OAAO,EACP,OAAO,EACP,WAAW,EACX,aAAa,EACb,YAAY,EACZ,cAAc,EACd,QAAQ,GACT,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Custom error classes for ctx-sync.
3
+ *
4
+ * Each error class provides:
5
+ * - A user-friendly message with suggested fix.
6
+ * - An error code for programmatic handling.
7
+ * - Stack traces only shown with `--verbose` or `DEBUG=*`.
8
+ *
9
+ * @module utils/errors
10
+ */
11
+ /** Base class for all ctx-sync errors with user-friendly messaging. */
12
+ export declare class CtxSyncError extends Error {
13
+ /** Machine-readable error code (e.g. 'ENCRYPTION_FAILED'). */
14
+ readonly code: string;
15
+ /** Suggested fix for the user. */
16
+ readonly suggestion: string;
17
+ constructor(message: string, code: string, suggestion: string);
18
+ /** Format a user-friendly error message (no stack trace). */
19
+ toFriendlyString(): string;
20
+ }
21
+ /** Encryption/decryption failures. */
22
+ export declare class EncryptionError extends CtxSyncError {
23
+ constructor(message: string, suggestion?: string);
24
+ }
25
+ /** Git sync failures. */
26
+ export declare class SyncError extends CtxSyncError {
27
+ constructor(message: string, suggestion?: string);
28
+ }
29
+ /** Configuration errors (missing config, invalid values). */
30
+ export declare class ConfigError extends CtxSyncError {
31
+ constructor(message: string, suggestion?: string);
32
+ }
33
+ /** Security violations (bad permissions, insecure transport, etc.). */
34
+ export declare class SecurityError extends CtxSyncError {
35
+ constructor(message: string, suggestion?: string);
36
+ }
37
+ /** Project not found or invalid project state. */
38
+ export declare class ProjectError extends CtxSyncError {
39
+ constructor(message: string, suggestion?: string);
40
+ }
41
+ /** Edge-case errors (disk full, permission denied, corrupted data). */
42
+ export declare class EdgeCaseError extends CtxSyncError {
43
+ constructor(message: string, suggestion?: string);
44
+ }
45
+ /**
46
+ * Determine whether verbose/debug output should be shown.
47
+ *
48
+ * Returns `true` if `--verbose` was passed or `DEBUG` env is set.
49
+ */
50
+ export declare function isVerbose(): boolean;
51
+ /**
52
+ * Map common raw errors to ctx-sync error classes.
53
+ *
54
+ * Takes an unknown thrown value and wraps it in the most appropriate
55
+ * CtxSyncError subclass when possible.
56
+ *
57
+ * @param err - The raw thrown value.
58
+ * @returns A CtxSyncError (or the original if already one).
59
+ */
60
+ export declare function classifyError(err: unknown): CtxSyncError;
61
+ /**
62
+ * Format an error for user-facing output.
63
+ *
64
+ * In normal mode: shows only the friendly message + suggestion.
65
+ * In verbose mode: also shows the full stack trace.
66
+ *
67
+ * @param err - The error to format.
68
+ * @returns Formatted string for console output.
69
+ */
70
+ export declare function formatError(err: unknown): string;
71
+ /**
72
+ * Wrap a command handler with user-friendly error handling.
73
+ *
74
+ * Catches any thrown error, classifies it, and prints a friendly message.
75
+ * Sets `process.exitCode = 1` on failure.
76
+ *
77
+ * @param fn - The async command handler function.
78
+ * @returns A wrapped function safe for use as a Commander action.
79
+ */
80
+ export declare function withErrorHandler<T extends unknown[]>(fn: (...args: T) => Promise<void>): (...args: T) => Promise<void>;
81
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,uEAAuE;AACvE,qBAAa,YAAa,SAAQ,KAAK;IACrC,8DAA8D;IAC9D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB,kCAAkC;IAClC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;gBAEhB,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM;IAO7D,6DAA6D;IAC7D,gBAAgB,IAAI,MAAM;CAS3B;AAED,sCAAsC;AACtC,qBAAa,eAAgB,SAAQ,YAAY;gBACnC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM;CAQjD;AAED,yBAAyB;AACzB,qBAAa,SAAU,SAAQ,YAAY;gBAC7B,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM;CAQjD;AAED,6DAA6D;AAC7D,qBAAa,WAAY,SAAQ,YAAY;gBAC/B,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM;CASjD;AAED,uEAAuE;AACvE,qBAAa,aAAc,SAAQ,YAAY;gBACjC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM;CAQjD;AAED,kDAAkD;AAClD,qBAAa,YAAa,SAAQ,YAAY;gBAChC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM;CAQjD;AAED,uEAAuE;AACvE,qBAAa,aAAc,SAAQ,YAAY;gBACjC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM;CAQjD;AAED;;;;GAIG;AACH,wBAAgB,SAAS,IAAI,OAAO,CAOnC;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,YAAY,CAiGxD;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAahD;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,OAAO,EAAE,EAClD,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,GAChC,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAS/B"}
@@ -0,0 +1,191 @@
1
+ /**
2
+ * Custom error classes for ctx-sync.
3
+ *
4
+ * Each error class provides:
5
+ * - A user-friendly message with suggested fix.
6
+ * - An error code for programmatic handling.
7
+ * - Stack traces only shown with `--verbose` or `DEBUG=*`.
8
+ *
9
+ * @module utils/errors
10
+ */
11
+ /** Base class for all ctx-sync errors with user-friendly messaging. */
12
+ export class CtxSyncError extends Error {
13
+ /** Machine-readable error code (e.g. 'ENCRYPTION_FAILED'). */
14
+ code;
15
+ /** Suggested fix for the user. */
16
+ suggestion;
17
+ constructor(message, code, suggestion) {
18
+ super(message);
19
+ this.name = 'CtxSyncError';
20
+ this.code = code;
21
+ this.suggestion = suggestion;
22
+ }
23
+ /** Format a user-friendly error message (no stack trace). */
24
+ toFriendlyString() {
25
+ const lines = [];
26
+ lines.push(`Error: ${this.message}`);
27
+ if (this.suggestion) {
28
+ lines.push('');
29
+ lines.push(` Suggested fix: ${this.suggestion}`);
30
+ }
31
+ return lines.join('\n');
32
+ }
33
+ }
34
+ /** Encryption/decryption failures. */
35
+ export class EncryptionError extends CtxSyncError {
36
+ constructor(message, suggestion) {
37
+ super(message, 'ENCRYPTION_FAILED', suggestion ?? 'Check your encryption key with `ctx-sync key verify`.');
38
+ this.name = 'EncryptionError';
39
+ }
40
+ }
41
+ /** Git sync failures. */
42
+ export class SyncError extends CtxSyncError {
43
+ constructor(message, suggestion) {
44
+ super(message, 'SYNC_FAILED', suggestion ?? 'Run `ctx-sync init` to set up the sync repository.');
45
+ this.name = 'SyncError';
46
+ }
47
+ }
48
+ /** Configuration errors (missing config, invalid values). */
49
+ export class ConfigError extends CtxSyncError {
50
+ constructor(message, suggestion) {
51
+ super(message, 'CONFIG_ERROR', suggestion ??
52
+ 'Run `ctx-sync init` to create a fresh configuration, or check ~/.config/ctx-sync/.');
53
+ this.name = 'ConfigError';
54
+ }
55
+ }
56
+ /** Security violations (bad permissions, insecure transport, etc.). */
57
+ export class SecurityError extends CtxSyncError {
58
+ constructor(message, suggestion) {
59
+ super(message, 'SECURITY_ERROR', suggestion ?? 'Run `ctx-sync audit` to diagnose security issues.');
60
+ this.name = 'SecurityError';
61
+ }
62
+ }
63
+ /** Project not found or invalid project state. */
64
+ export class ProjectError extends CtxSyncError {
65
+ constructor(message, suggestion) {
66
+ super(message, 'PROJECT_ERROR', suggestion ?? 'Run `ctx-sync list` to see tracked projects.');
67
+ this.name = 'ProjectError';
68
+ }
69
+ }
70
+ /** Edge-case errors (disk full, permission denied, corrupted data). */
71
+ export class EdgeCaseError extends CtxSyncError {
72
+ constructor(message, suggestion) {
73
+ super(message, 'EDGE_CASE_ERROR', suggestion ?? 'Check system resources and file permissions.');
74
+ this.name = 'EdgeCaseError';
75
+ }
76
+ }
77
+ /**
78
+ * Determine whether verbose/debug output should be shown.
79
+ *
80
+ * Returns `true` if `--verbose` was passed or `DEBUG` env is set.
81
+ */
82
+ export function isVerbose() {
83
+ const args = process.argv;
84
+ return (args.includes('--verbose') ||
85
+ args.includes('-v') ||
86
+ !!process.env['DEBUG']);
87
+ }
88
+ /**
89
+ * Map common raw errors to ctx-sync error classes.
90
+ *
91
+ * Takes an unknown thrown value and wraps it in the most appropriate
92
+ * CtxSyncError subclass when possible.
93
+ *
94
+ * @param err - The raw thrown value.
95
+ * @returns A CtxSyncError (or the original if already one).
96
+ */
97
+ export function classifyError(err) {
98
+ if (err instanceof CtxSyncError) {
99
+ return err;
100
+ }
101
+ const message = err instanceof Error ? err.message : String(err);
102
+ const lowerMsg = message.toLowerCase();
103
+ // Encryption / decryption problems
104
+ // Note: avoid matching "age" alone — it also appears in "Invalid Age public key format".
105
+ // Only match "age:" (library prefix) or "age ciphertext" patterns.
106
+ if (lowerMsg.includes('decrypt') ||
107
+ lowerMsg.includes('age:') ||
108
+ lowerMsg.includes('age ciphertext') ||
109
+ lowerMsg.includes('ciphertext') ||
110
+ lowerMsg.includes('encrypted')) {
111
+ return new EncryptionError('Failed to decrypt state file.', 'Your encryption key may be wrong or the file may be corrupted.\n' +
112
+ ' Try: ctx-sync key verify');
113
+ }
114
+ // Missing key
115
+ if (lowerMsg.includes('key.txt') ||
116
+ lowerMsg.includes('key file') ||
117
+ lowerMsg.includes('no such file') && lowerMsg.includes('key')) {
118
+ return new ConfigError('Encryption key not found.', 'Run `ctx-sync init` to generate a new key, or `ctx-sync init --restore` to restore an existing one.');
119
+ }
120
+ // Permissions
121
+ if (lowerMsg.includes('permission') ||
122
+ lowerMsg.includes('eacces') ||
123
+ lowerMsg.includes('eperm')) {
124
+ return new SecurityError('Permission denied.', 'Check file permissions. Key file should be 600, config dir should be 700.\n' +
125
+ ' Try: chmod 600 ~/.config/ctx-sync/key.txt');
126
+ }
127
+ // Disk space
128
+ if (lowerMsg.includes('enospc') || lowerMsg.includes('no space')) {
129
+ return new EdgeCaseError('Disk is full — cannot write state files.', 'Free up disk space and try again.');
130
+ }
131
+ // Transport security (check before generic git errors)
132
+ if (lowerMsg.includes('insecure') || lowerMsg.includes('http://')) {
133
+ return new SecurityError(message, 'Use SSH (git@...) or HTTPS (https://...) for your remote URL.\n' +
134
+ ' Try: git remote set-url origin <secure-url>');
135
+ }
136
+ // Git errors
137
+ if (lowerMsg.includes('git') ||
138
+ lowerMsg.includes('remote') ||
139
+ lowerMsg.includes('repository')) {
140
+ return new SyncError(message, 'Ensure Git is installed and the sync repo is initialized.\n' +
141
+ ' Try: ctx-sync init');
142
+ }
143
+ // Path validation
144
+ if (lowerMsg.includes('path') &&
145
+ (lowerMsg.includes('outside') || lowerMsg.includes('traversal'))) {
146
+ return new SecurityError(message, 'Project paths must be within your home directory.');
147
+ }
148
+ // Fallback: wrap as a generic CtxSyncError
149
+ return new CtxSyncError(message, 'UNKNOWN_ERROR', 'If this persists, run with --verbose for more details or file an issue.');
150
+ }
151
+ /**
152
+ * Format an error for user-facing output.
153
+ *
154
+ * In normal mode: shows only the friendly message + suggestion.
155
+ * In verbose mode: also shows the full stack trace.
156
+ *
157
+ * @param err - The error to format.
158
+ * @returns Formatted string for console output.
159
+ */
160
+ export function formatError(err) {
161
+ const ctxErr = classifyError(err);
162
+ const lines = [];
163
+ lines.push(ctxErr.toFriendlyString());
164
+ if (isVerbose() && ctxErr.stack) {
165
+ lines.push('');
166
+ lines.push('Stack trace:');
167
+ lines.push(ctxErr.stack);
168
+ }
169
+ return lines.join('\n');
170
+ }
171
+ /**
172
+ * Wrap a command handler with user-friendly error handling.
173
+ *
174
+ * Catches any thrown error, classifies it, and prints a friendly message.
175
+ * Sets `process.exitCode = 1` on failure.
176
+ *
177
+ * @param fn - The async command handler function.
178
+ * @returns A wrapped function safe for use as a Commander action.
179
+ */
180
+ export function withErrorHandler(fn) {
181
+ return async (...args) => {
182
+ try {
183
+ await fn(...args);
184
+ }
185
+ catch (err) {
186
+ console.error(formatError(err));
187
+ process.exitCode = 1;
188
+ }
189
+ };
190
+ }
191
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Secure memory handling utilities.
3
+ *
4
+ * Provides best-effort memory cleanup for sensitive data.
5
+ * Buffers are zeroed after use; string clearing is best-effort
6
+ * due to JavaScript string immutability.
7
+ *
8
+ * **Limitations (documented trade-offs):**
9
+ * - JavaScript strings are immutable and interned by the V8 engine.
10
+ * Once a string is created, we cannot reliably zero it from memory.
11
+ * The `clearString` function is a best-effort signal; true clearing
12
+ * requires using Buffer/Uint8Array for sensitive data throughout.
13
+ * - The garbage collector may copy data before we can zero it.
14
+ * - V8 may keep optimised copies in JIT-compiled code.
15
+ *
16
+ * For maximum security, prefer using Buffers for sensitive data and
17
+ * pass them through `withSecret()` to ensure cleanup.
18
+ *
19
+ * @module utils/secure-memory
20
+ */
21
+ /**
22
+ * Execute a function with a secret buffer, ensuring the buffer is
23
+ * zeroed in the `finally` block regardless of success or failure.
24
+ *
25
+ * @param buffer - The buffer containing sensitive data.
26
+ * @param fn - The function to execute with the buffer.
27
+ * @returns The return value of `fn`.
28
+ */
29
+ export declare function withSecret<T>(buffer: Buffer, fn: (buf: Buffer) => T | Promise<T>): Promise<T>;
30
+ /**
31
+ * Synchronous version of `withSecret`.
32
+ *
33
+ * @param buffer - The buffer containing sensitive data.
34
+ * @param fn - The synchronous function to execute with the buffer.
35
+ * @returns The return value of `fn`.
36
+ */
37
+ export declare function withSecretSync<T>(buffer: Buffer, fn: (buf: Buffer) => T): T;
38
+ /**
39
+ * Best-effort clearing of a string variable.
40
+ *
41
+ * **Important:** Due to JavaScript string immutability, this function
42
+ * cannot guarantee the original string is removed from memory. It returns
43
+ * an empty string that the caller should assign back to the variable.
44
+ * The original string will be eligible for garbage collection, but may
45
+ * persist in memory until the GC runs.
46
+ *
47
+ * Usage:
48
+ * ```ts
49
+ * let secret = 'my-secret';
50
+ * // ... use secret ...
51
+ * secret = clearString(secret);
52
+ * // secret is now '', original may still be in memory until GC
53
+ * ```
54
+ *
55
+ * @param _variable - The string to "clear" (unused, but required for intent).
56
+ * @returns An empty string to assign back to the variable.
57
+ */
58
+ export declare function clearString(_variable: string): string;
59
+ /**
60
+ * Zero out a Uint8Array (for use with raw crypto buffers).
61
+ *
62
+ * @param array - The array to zero.
63
+ */
64
+ export declare function zeroOut(array: Uint8Array): void;
65
+ //# sourceMappingURL=secure-memory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secure-memory.d.ts","sourceRoot":"","sources":["../../src/utils/secure-memory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAMnG;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,CAAC,GAAG,CAAC,CAM3E;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAKrD;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAE/C"}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Secure memory handling utilities.
3
+ *
4
+ * Provides best-effort memory cleanup for sensitive data.
5
+ * Buffers are zeroed after use; string clearing is best-effort
6
+ * due to JavaScript string immutability.
7
+ *
8
+ * **Limitations (documented trade-offs):**
9
+ * - JavaScript strings are immutable and interned by the V8 engine.
10
+ * Once a string is created, we cannot reliably zero it from memory.
11
+ * The `clearString` function is a best-effort signal; true clearing
12
+ * requires using Buffer/Uint8Array for sensitive data throughout.
13
+ * - The garbage collector may copy data before we can zero it.
14
+ * - V8 may keep optimised copies in JIT-compiled code.
15
+ *
16
+ * For maximum security, prefer using Buffers for sensitive data and
17
+ * pass them through `withSecret()` to ensure cleanup.
18
+ *
19
+ * @module utils/secure-memory
20
+ */
21
+ /**
22
+ * Execute a function with a secret buffer, ensuring the buffer is
23
+ * zeroed in the `finally` block regardless of success or failure.
24
+ *
25
+ * @param buffer - The buffer containing sensitive data.
26
+ * @param fn - The function to execute with the buffer.
27
+ * @returns The return value of `fn`.
28
+ */
29
+ export async function withSecret(buffer, fn) {
30
+ try {
31
+ return await fn(buffer);
32
+ }
33
+ finally {
34
+ buffer.fill(0);
35
+ }
36
+ }
37
+ /**
38
+ * Synchronous version of `withSecret`.
39
+ *
40
+ * @param buffer - The buffer containing sensitive data.
41
+ * @param fn - The synchronous function to execute with the buffer.
42
+ * @returns The return value of `fn`.
43
+ */
44
+ export function withSecretSync(buffer, fn) {
45
+ try {
46
+ return fn(buffer);
47
+ }
48
+ finally {
49
+ buffer.fill(0);
50
+ }
51
+ }
52
+ /**
53
+ * Best-effort clearing of a string variable.
54
+ *
55
+ * **Important:** Due to JavaScript string immutability, this function
56
+ * cannot guarantee the original string is removed from memory. It returns
57
+ * an empty string that the caller should assign back to the variable.
58
+ * The original string will be eligible for garbage collection, but may
59
+ * persist in memory until the GC runs.
60
+ *
61
+ * Usage:
62
+ * ```ts
63
+ * let secret = 'my-secret';
64
+ * // ... use secret ...
65
+ * secret = clearString(secret);
66
+ * // secret is now '', original may still be in memory until GC
67
+ * ```
68
+ *
69
+ * @param _variable - The string to "clear" (unused, but required for intent).
70
+ * @returns An empty string to assign back to the variable.
71
+ */
72
+ export function clearString(_variable) {
73
+ // We cannot mutate the original string in JavaScript.
74
+ // Return empty string for the caller to overwrite their reference.
75
+ // The original string becomes eligible for garbage collection.
76
+ return '';
77
+ }
78
+ /**
79
+ * Zero out a Uint8Array (for use with raw crypto buffers).
80
+ *
81
+ * @param array - The array to zero.
82
+ */
83
+ export function zeroOut(array) {
84
+ array.fill(0);
85
+ }
86
+ //# sourceMappingURL=secure-memory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secure-memory.js","sourceRoot":"","sources":["../../src/utils/secure-memory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAI,MAAc,EAAE,EAAmC;IACrF,IAAI,CAAC;QACH,OAAO,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC;IAC1B,CAAC;YAAS,CAAC;QACT,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjB,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAI,MAAc,EAAE,EAAsB;IACtE,IAAI,CAAC;QACH,OAAO,EAAE,CAAC,MAAM,CAAC,CAAC;IACpB,CAAC;YAAS,CAAC;QACT,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjB,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,WAAW,CAAC,SAAiB;IAC3C,sDAAsD;IACtD,mEAAmE;IACnE,+DAA+D;IAC/D,OAAO,EAAE,CAAC;AACZ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,OAAO,CAAC,KAAiB;IACvC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAChB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "ctx-sync",
3
+ "version": "1.0.0",
4
+ "description": "Sync your complete development context across machines using Git",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "bin": {
9
+ "ctx-sync": "dist/index.js"
10
+ },
11
+ "files": [
12
+ "dist",
13
+ "README.md",
14
+ "LICENSE"
15
+ ],
16
+ "scripts": {
17
+ "build": "tsc",
18
+ "typecheck": "tsc --noEmit",
19
+ "dev": "tsx src/index.ts",
20
+ "test": "NODE_OPTIONS='--experimental-vm-modules' jest",
21
+ "test:unit": "NODE_OPTIONS='--experimental-vm-modules' jest test/unit",
22
+ "test:integration": "NODE_OPTIONS='--experimental-vm-modules' jest test/integration",
23
+ "test:e2e": "NODE_OPTIONS='--experimental-vm-modules' jest test/e2e",
24
+ "test:security": "NODE_OPTIONS='--experimental-vm-modules' jest test/security",
25
+ "test:pentest": "NODE_OPTIONS='--experimental-vm-modules' jest test/security/pentest.test.ts",
26
+ "test:coverage": "NODE_OPTIONS='--experimental-vm-modules' jest --coverage",
27
+ "test:watch": "NODE_OPTIONS='--experimental-vm-modules' jest --watch",
28
+ "test:performance": "NODE_OPTIONS='--experimental-vm-modules' jest test/performance --no-coverage",
29
+ "test:all": "npm run typecheck && npm run lint && NODE_OPTIONS='--experimental-vm-modules' jest --coverage"
30
+ },
31
+ "keywords": [
32
+ "cli",
33
+ "context",
34
+ "sync",
35
+ "development",
36
+ "git",
37
+ "encryption",
38
+ "developer-tools"
39
+ ],
40
+ "license": "MIT",
41
+ "engines": {
42
+ "node": ">=18.0.0"
43
+ },
44
+ "devDependencies": {
45
+ "@types/jest": "30.0.0",
46
+ "@types/mock-fs": "4.13.4",
47
+ "jest": "30.2.0",
48
+ "ts-jest": "29.4.6"
49
+ },
50
+ "dependencies": {
51
+ "age-encryption": "0.3.0",
52
+ "chalk": "5.6.2",
53
+ "commander": "14.0.3",
54
+ "enquirer": "2.4.1",
55
+ "ora": "9.3.0",
56
+ "simple-git": "3.30.0"
57
+ }
58
+ }