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
@@ -0,0 +1,515 @@
1
+ /**
2
+ * Docker handler module.
3
+ *
4
+ * Detects Docker Compose files, parses their service definitions,
5
+ * queries Docker for running container state, and saves/loads
6
+ * encrypted Docker state.
7
+ *
8
+ * **Graceful degradation:** If Docker is not installed or compose files
9
+ * are missing, the module returns empty/null results rather than throwing.
10
+ *
11
+ * @module core/docker-handler
12
+ */
13
+ import * as fs from 'node:fs';
14
+ import * as path from 'node:path';
15
+ import { execSync } from 'node:child_process';
16
+ import { readState, writeState } from './state-manager.js';
17
+ /**
18
+ * Known Docker Compose file names (in priority order).
19
+ */
20
+ export const COMPOSE_FILE_NAMES = [
21
+ 'docker-compose.yml',
22
+ 'docker-compose.yaml',
23
+ 'compose.yml',
24
+ 'compose.yaml',
25
+ ];
26
+ /**
27
+ * Detect a Docker Compose file in the given project directory.
28
+ *
29
+ * Searches for known compose file names in priority order. Does not
30
+ * throw if none is found — returns `found: false`.
31
+ *
32
+ * @param projectDir - Absolute path to the project directory.
33
+ * @returns Detection result with file path if found.
34
+ */
35
+ export function detectDockerCompose(projectDir) {
36
+ for (const fileName of COMPOSE_FILE_NAMES) {
37
+ const filePath = path.join(projectDir, fileName);
38
+ if (fs.existsSync(filePath)) {
39
+ return {
40
+ found: true,
41
+ filePath,
42
+ fileName,
43
+ };
44
+ }
45
+ }
46
+ return {
47
+ found: false,
48
+ filePath: null,
49
+ fileName: null,
50
+ };
51
+ }
52
+ /**
53
+ * Parse a Docker Compose file and extract service definitions.
54
+ *
55
+ * Uses a simple YAML parser (line-based) to extract services, ports,
56
+ * images, volumes, and networks without requiring a full YAML library.
57
+ * This handles common compose file patterns.
58
+ *
59
+ * @param filePath - Absolute path to the compose file.
60
+ * @returns Parsed services and networks.
61
+ * @throws If the file cannot be read.
62
+ */
63
+ export function parseComposeFile(filePath) {
64
+ if (!fs.existsSync(filePath)) {
65
+ throw new Error(`Compose file not found: ${filePath}`);
66
+ }
67
+ const content = fs.readFileSync(filePath, 'utf-8');
68
+ return parseComposeContent(content);
69
+ }
70
+ /**
71
+ * Parse Docker Compose YAML content.
72
+ *
73
+ * Simple line-based parser that handles common compose file patterns.
74
+ * Extracts service name, image, container_name, ports, volumes,
75
+ * healthcheck, and top-level networks.
76
+ *
77
+ * @param content - The raw YAML content.
78
+ * @returns Parsed services and networks.
79
+ */
80
+ export function parseComposeContent(content) {
81
+ const lines = content.split('\n');
82
+ const services = [];
83
+ const networks = [];
84
+ let inServices = false;
85
+ let inNetworks = false;
86
+ let currentService = null;
87
+ let currentServiceName = null;
88
+ let inPorts = false;
89
+ let inVolumes = false;
90
+ let inHealthcheck = false;
91
+ let servicesIndent = -1;
92
+ let serviceIndent = -1;
93
+ for (const rawLine of lines) {
94
+ // Skip comments and empty lines
95
+ const commentIdx = rawLine.indexOf('#');
96
+ const line = commentIdx >= 0 ? rawLine.slice(0, commentIdx) : rawLine;
97
+ if (line.trim() === '')
98
+ continue;
99
+ const indent = line.length - line.trimStart().length;
100
+ const trimmed = line.trim();
101
+ // Top-level section detection
102
+ if (indent === 0) {
103
+ // Flush current service before switching sections
104
+ if (currentService && currentServiceName) {
105
+ services.push(finalizeService(currentServiceName, currentService));
106
+ currentService = null;
107
+ currentServiceName = null;
108
+ }
109
+ inPorts = false;
110
+ inVolumes = false;
111
+ inHealthcheck = false;
112
+ if (trimmed === 'services:' || trimmed.startsWith('services:')) {
113
+ inServices = true;
114
+ inNetworks = false;
115
+ servicesIndent = 0;
116
+ continue;
117
+ }
118
+ else if (trimmed === 'networks:' || trimmed.startsWith('networks:')) {
119
+ inServices = false;
120
+ inNetworks = true;
121
+ continue;
122
+ }
123
+ else {
124
+ inServices = false;
125
+ inNetworks = false;
126
+ continue;
127
+ }
128
+ }
129
+ // Parse networks section
130
+ if (inNetworks && indent > 0) {
131
+ // Network names are keys at the first indent level
132
+ if (trimmed.endsWith(':') && !trimmed.includes(' ')) {
133
+ networks.push(trimmed.slice(0, -1));
134
+ }
135
+ continue;
136
+ }
137
+ // Parse services section
138
+ if (inServices) {
139
+ // Detect a new service (one level deeper than 'services:')
140
+ if (indent > servicesIndent &&
141
+ (serviceIndent === -1 || indent <= serviceIndent) &&
142
+ trimmed.endsWith(':') &&
143
+ !trimmed.includes(' ')) {
144
+ // Flush previous service
145
+ if (currentService && currentServiceName) {
146
+ services.push(finalizeService(currentServiceName, currentService));
147
+ }
148
+ currentServiceName = trimmed.slice(0, -1);
149
+ currentService = {
150
+ volumes: [],
151
+ };
152
+ serviceIndent = indent;
153
+ inPorts = false;
154
+ inVolumes = false;
155
+ inHealthcheck = false;
156
+ continue;
157
+ }
158
+ if (!currentService)
159
+ continue;
160
+ // Within a service definition
161
+ if (indent > serviceIndent) {
162
+ // Check if we're ending a list context
163
+ if (!trimmed.startsWith('-') && !trimmed.startsWith('#')) {
164
+ if (inPorts && !trimmed.startsWith('-')) {
165
+ inPorts = false;
166
+ }
167
+ if (inVolumes && !trimmed.startsWith('-')) {
168
+ inVolumes = false;
169
+ }
170
+ }
171
+ // Parse ports list items
172
+ if (inPorts && trimmed.startsWith('-')) {
173
+ const portMapping = trimmed.slice(1).trim().replace(/['"]/g, '');
174
+ const hostPort = parseHostPort(portMapping);
175
+ if (hostPort > 0 && !currentService.port) {
176
+ currentService.port = hostPort;
177
+ }
178
+ continue;
179
+ }
180
+ // Parse volumes list items
181
+ if (inVolumes && trimmed.startsWith('-')) {
182
+ const volume = trimmed.slice(1).trim().replace(/['"]/g, '');
183
+ if (volume) {
184
+ currentService.volumes = currentService.volumes ?? [];
185
+ currentService.volumes.push(volume);
186
+ }
187
+ continue;
188
+ }
189
+ // Parse healthcheck test
190
+ if (inHealthcheck) {
191
+ if (trimmed.startsWith('test:')) {
192
+ const testValue = trimmed.slice(5).trim();
193
+ if (testValue) {
194
+ // Could be inline array: ["CMD", "pg_isready"] or a string
195
+ currentService.healthCheck = parseHealthcheckValue(testValue);
196
+ }
197
+ }
198
+ else if (trimmed.startsWith('-') && !currentService.healthCheck) {
199
+ // Array form (multi-line): take the command part (skip CMD or CMD-SHELL)
200
+ const item = trimmed.slice(1).trim().replace(/['"]/g, '');
201
+ if (item !== 'CMD' && item !== 'CMD-SHELL') {
202
+ currentService.healthCheck = item;
203
+ }
204
+ }
205
+ // Stay in healthcheck context until we get to a key at the service indent level
206
+ const nextKeyMatch = trimmed.match(/^[a-z_]+:/i);
207
+ if (nextKeyMatch &&
208
+ !trimmed.startsWith('test:') &&
209
+ !trimmed.startsWith('interval:') &&
210
+ !trimmed.startsWith('timeout:') &&
211
+ !trimmed.startsWith('retries:') &&
212
+ !trimmed.startsWith('start_period:')) {
213
+ inHealthcheck = false;
214
+ }
215
+ else {
216
+ continue;
217
+ }
218
+ }
219
+ // Parse key-value pairs
220
+ if (trimmed.startsWith('image:')) {
221
+ currentService.image = cleanYamlValue(trimmed.slice(6));
222
+ }
223
+ else if (trimmed.startsWith('container_name:')) {
224
+ currentService.container = cleanYamlValue(trimmed.slice(15));
225
+ }
226
+ else if (trimmed.startsWith('ports:')) {
227
+ inPorts = true;
228
+ // Handle inline ports: ["5432:5432"]
229
+ const inlineValue = trimmed.slice(6).trim();
230
+ if (inlineValue) {
231
+ const ports = parseInlineList(inlineValue);
232
+ for (const portMapping of ports) {
233
+ const hostPort = parseHostPort(portMapping);
234
+ if (hostPort > 0 && !currentService.port) {
235
+ currentService.port = hostPort;
236
+ }
237
+ }
238
+ inPorts = false;
239
+ }
240
+ }
241
+ else if (trimmed.startsWith('volumes:')) {
242
+ inVolumes = true;
243
+ // Handle inline volumes
244
+ const inlineValue = trimmed.slice(8).trim();
245
+ if (inlineValue) {
246
+ const vols = parseInlineList(inlineValue);
247
+ currentService.volumes = currentService.volumes ?? [];
248
+ currentService.volumes.push(...vols);
249
+ inVolumes = false;
250
+ }
251
+ }
252
+ else if (trimmed.startsWith('healthcheck:')) {
253
+ inHealthcheck = true;
254
+ }
255
+ }
256
+ }
257
+ }
258
+ // Flush the last service
259
+ if (currentService && currentServiceName) {
260
+ services.push(finalizeService(currentServiceName, currentService));
261
+ }
262
+ return { services, networks };
263
+ }
264
+ /**
265
+ * Clean a YAML value: strip quotes and whitespace.
266
+ */
267
+ function cleanYamlValue(raw) {
268
+ return raw.trim().replace(/^['"]|['"]$/g, '');
269
+ }
270
+ /**
271
+ * Parse a healthcheck test value.
272
+ *
273
+ * Handles:
274
+ * - Inline array: `["CMD", "pg_isready"]` → `pg_isready`
275
+ * - Inline array: `["CMD-SHELL", "curl -f http://localhost:3000/health || exit 1"]` → `curl ...`
276
+ * - Plain string: `curl -f http://localhost/health || exit 1` → as-is
277
+ */
278
+ function parseHealthcheckValue(raw) {
279
+ const trimmed = raw.trim();
280
+ // Inline array form: ["CMD", "pg_isready"] or ["CMD-SHELL", "..."]
281
+ if (trimmed.startsWith('[') && trimmed.endsWith(']')) {
282
+ const items = trimmed
283
+ .slice(1, -1)
284
+ .split(',')
285
+ .map((s) => s.trim().replace(/^['"]|['"]$/g, ''));
286
+ // Filter out CMD / CMD-SHELL and return the rest joined
287
+ const commandParts = items.filter((item) => item !== 'CMD' && item !== 'CMD-SHELL');
288
+ return commandParts.join(' ').trim() || trimmed;
289
+ }
290
+ return cleanYamlValue(trimmed);
291
+ }
292
+ /**
293
+ * Parse an inline YAML list like ["a", "b"] or [a, b].
294
+ */
295
+ function parseInlineList(raw) {
296
+ const trimmed = raw.trim();
297
+ if (trimmed.startsWith('[') && trimmed.endsWith(']')) {
298
+ return trimmed
299
+ .slice(1, -1)
300
+ .split(',')
301
+ .map((s) => s.trim().replace(/^['"]|['"]$/g, ''))
302
+ .filter(Boolean);
303
+ }
304
+ return [];
305
+ }
306
+ /**
307
+ * Parse a host port from a port mapping string.
308
+ *
309
+ * Handles formats like:
310
+ * - "5432:5432"
311
+ * - "5432:5432/tcp"
312
+ * - "0.0.0.0:5432:5432"
313
+ * - "8080:80"
314
+ *
315
+ * Returns the **host** port (left side).
316
+ */
317
+ export function parseHostPort(mapping) {
318
+ const clean = mapping.replace(/\/\w+$/, '').trim(); // Remove /tcp, /udp suffix
319
+ const parts = clean.split(':');
320
+ if (parts.length === 0)
321
+ return 0;
322
+ // "5432:5432" or "8080:80" → host port is parts[0]
323
+ // "0.0.0.0:5432:5432" → host port is parts[1]
324
+ if (parts.length === 3) {
325
+ return parseInt(parts[1] ?? '0', 10) || 0;
326
+ }
327
+ if (parts.length === 2) {
328
+ return parseInt(parts[0] ?? '0', 10) || 0;
329
+ }
330
+ if (parts.length === 1) {
331
+ return parseInt(parts[0] ?? '0', 10) || 0;
332
+ }
333
+ return 0;
334
+ }
335
+ /**
336
+ * Finalize a partially parsed service into a full ParsedService.
337
+ */
338
+ function finalizeService(name, partial) {
339
+ return {
340
+ name,
341
+ image: partial.image ?? '',
342
+ container: partial.container ?? `${name}`,
343
+ port: partial.port ?? 0,
344
+ volumes: partial.volumes ?? [],
345
+ healthCheck: partial.healthCheck,
346
+ };
347
+ }
348
+ /**
349
+ * Check if Docker is available on this machine.
350
+ *
351
+ * @returns `true` if `docker` CLI is installed and responds to `docker info`.
352
+ */
353
+ export function isDockerAvailable() {
354
+ try {
355
+ execSync('docker info', { stdio: 'pipe', timeout: 5000 });
356
+ return true;
357
+ }
358
+ catch {
359
+ return false;
360
+ }
361
+ }
362
+ /**
363
+ * Get running containers for a project directory.
364
+ *
365
+ * Uses `docker compose ps` to query running containers related to
366
+ * the compose file in the given directory.
367
+ *
368
+ * @param projectDir - Absolute path to the project directory.
369
+ * @returns List of running containers, or empty array if Docker is not available.
370
+ */
371
+ export function getRunningContainers(projectDir) {
372
+ if (!isDockerAvailable()) {
373
+ return [];
374
+ }
375
+ const compose = detectDockerCompose(projectDir);
376
+ if (!compose.found) {
377
+ return [];
378
+ }
379
+ try {
380
+ const output = execSync('docker compose ps --format json', {
381
+ cwd: projectDir,
382
+ stdio: ['pipe', 'pipe', 'pipe'],
383
+ timeout: 10000,
384
+ }).toString();
385
+ if (!output.trim()) {
386
+ return [];
387
+ }
388
+ // docker compose ps --format json outputs one JSON object per line
389
+ const containers = [];
390
+ for (const line of output.trim().split('\n')) {
391
+ const trimmedLine = line.trim();
392
+ if (!trimmedLine)
393
+ continue;
394
+ try {
395
+ const entry = JSON.parse(trimmedLine);
396
+ containers.push({
397
+ id: entry['ID'] ?? '',
398
+ name: entry['Name'] ?? '',
399
+ image: entry['Image'] ?? '',
400
+ status: entry['Status'] ?? '',
401
+ ports: entry['Ports'] ?? entry['Publishers'] ?? '',
402
+ });
403
+ }
404
+ catch {
405
+ // Skip malformed lines
406
+ }
407
+ }
408
+ return containers;
409
+ }
410
+ catch {
411
+ return [];
412
+ }
413
+ }
414
+ /**
415
+ * Build a DockerState entry for a project from its compose file.
416
+ *
417
+ * Detects the compose file, parses it, and creates a DockerState entry
418
+ * suitable for encryption and storage.
419
+ *
420
+ * @param projectName - The project name (key in the DockerState map).
421
+ * @param projectDir - Absolute path to the project directory.
422
+ * @param autoStartDefault - Default value for autoStart on each service.
423
+ * @returns The project's Docker state entry, or `null` if no compose file found.
424
+ */
425
+ export function buildDockerStateEntry(projectName, projectDir, autoStartDefault = true) {
426
+ const compose = detectDockerCompose(projectDir);
427
+ if (!compose.found || !compose.filePath) {
428
+ return null;
429
+ }
430
+ const parsed = parseComposeFile(compose.filePath);
431
+ const services = parsed.services.map((svc) => ({
432
+ name: svc.name,
433
+ container: svc.container,
434
+ image: svc.image,
435
+ port: svc.port,
436
+ volumes: svc.volumes.length > 0 ? svc.volumes : undefined,
437
+ autoStart: autoStartDefault,
438
+ healthCheck: svc.healthCheck,
439
+ }));
440
+ return {
441
+ composeFile: compose.filePath,
442
+ services,
443
+ networks: parsed.networks.length > 0 ? parsed.networks : undefined,
444
+ lastStarted: undefined,
445
+ };
446
+ }
447
+ /**
448
+ * Save Docker state for a project to encrypted storage.
449
+ *
450
+ * Reads existing Docker state, merges the new project entry, and
451
+ * writes the updated state to `docker-state.age`.
452
+ *
453
+ * @param syncDir - The sync directory path.
454
+ * @param projectName - The project name (key in DockerState).
455
+ * @param entry - The Docker state entry for the project.
456
+ * @param publicKey - The Age public key for encryption.
457
+ * @param privateKey - The Age private key for reading existing state.
458
+ */
459
+ export async function saveDockerState(syncDir, projectName, entry, publicKey, privateKey) {
460
+ // Read existing state
461
+ const existing = await readState(syncDir, privateKey, 'docker-state');
462
+ const dockerState = existing ?? {};
463
+ // Merge the new entry
464
+ dockerState[projectName] = entry;
465
+ // Write encrypted state
466
+ await writeState(syncDir, dockerState, publicKey, 'docker-state');
467
+ }
468
+ /**
469
+ * Load Docker state for a specific project from encrypted storage.
470
+ *
471
+ * @param syncDir - The sync directory path.
472
+ * @param projectName - The project name.
473
+ * @param privateKey - The Age private key for decryption.
474
+ * @returns The project's Docker state, or `null` if not found.
475
+ */
476
+ export async function loadDockerState(syncDir, projectName, privateKey) {
477
+ const dockerState = await readState(syncDir, privateKey, 'docker-state');
478
+ if (!dockerState)
479
+ return null;
480
+ return dockerState[projectName] ?? null;
481
+ }
482
+ /**
483
+ * Load all Docker state from encrypted storage.
484
+ *
485
+ * @param syncDir - The sync directory path.
486
+ * @param privateKey - The Age private key for decryption.
487
+ * @returns Full Docker state, or `null` if no docker-state.age exists.
488
+ */
489
+ export async function loadAllDockerState(syncDir, privateKey) {
490
+ return readState(syncDir, privateKey, 'docker-state');
491
+ }
492
+ /**
493
+ * Remove Docker state for a project from encrypted storage.
494
+ *
495
+ * @param syncDir - The sync directory path.
496
+ * @param projectName - The project name to remove.
497
+ * @param publicKey - The Age public key for re-encryption.
498
+ * @param privateKey - The Age private key for decryption.
499
+ * @returns `true` if the project was found and removed.
500
+ */
501
+ export async function removeDockerState(syncDir, projectName, publicKey, privateKey) {
502
+ const dockerState = await readState(syncDir, privateKey, 'docker-state');
503
+ if (!dockerState || !(projectName in dockerState)) {
504
+ return false;
505
+ }
506
+ const updated = {};
507
+ for (const [key, value] of Object.entries(dockerState)) {
508
+ if (key !== projectName) {
509
+ updated[key] = value;
510
+ }
511
+ }
512
+ await writeState(syncDir, updated, publicKey, 'docker-state');
513
+ return true;
514
+ }
515
+ //# sourceMappingURL=docker-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docker-handler.js","sourceRoot":"","sources":["../../src/core/docker-handler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Age encryption wrapper module.
3
+ *
4
+ * Provides key generation, encryption, and decryption operations
5
+ * using the Age encryption library. All operations are in-memory only —
6
+ * no temporary files are created during crypto operations.
7
+ *
8
+ * @module core/encryption
9
+ */
10
+ /**
11
+ * Generate a new Age key pair.
12
+ *
13
+ * @returns Object containing the public key (age1...) and private key (AGE-SECRET-KEY-...).
14
+ */
15
+ export declare function generateKey(): Promise<{
16
+ publicKey: string;
17
+ privateKey: string;
18
+ }>;
19
+ /**
20
+ * Encrypt a plaintext string with an Age public key.
21
+ *
22
+ * @param plaintext - The string to encrypt.
23
+ * @param publicKey - The Age public key (age1...) to encrypt for.
24
+ * @returns ASCII-armored Age ciphertext.
25
+ * @throws If the public key is invalid.
26
+ */
27
+ export declare function encrypt(plaintext: string, publicKey: string): Promise<string>;
28
+ /**
29
+ * Decrypt an ASCII-armored Age ciphertext with a private key.
30
+ *
31
+ * @param ciphertext - The ASCII-armored Age ciphertext.
32
+ * @param privateKey - The Age private key (AGE-SECRET-KEY-...).
33
+ * @returns The decrypted plaintext string.
34
+ * @throws If the private key cannot decrypt the ciphertext.
35
+ */
36
+ export declare function decrypt(ciphertext: string, privateKey: string): Promise<string>;
37
+ /**
38
+ * Encrypt a typed data object as JSON into an Age ciphertext blob.
39
+ * The data is serialised to JSON in memory, then encrypted.
40
+ * No plaintext JSON is ever written to disk.
41
+ *
42
+ * @param data - The data to encrypt.
43
+ * @param publicKey - The Age public key to encrypt for.
44
+ * @returns ASCII-armored Age ciphertext containing the serialised JSON.
45
+ */
46
+ export declare function encryptState<T>(data: T, publicKey: string): Promise<string>;
47
+ /**
48
+ * Decrypt an Age ciphertext blob and parse the JSON back into a typed object.
49
+ *
50
+ * @param ciphertext - The ASCII-armored Age ciphertext.
51
+ * @param privateKey - The Age private key.
52
+ * @returns The decrypted and parsed data.
53
+ * @throws If decryption fails or the JSON is invalid.
54
+ */
55
+ export declare function decryptState<T>(ciphertext: string, privateKey: string): Promise<T>;
56
+ /**
57
+ * Encrypt a plaintext string for multiple Age recipients.
58
+ *
59
+ * All recipients can independently decrypt the resulting ciphertext
60
+ * using their own private key. This enables team/multi-machine support.
61
+ *
62
+ * @param plaintext - The string to encrypt.
63
+ * @param publicKeys - Array of Age public keys (age1...) to encrypt for.
64
+ * @returns ASCII-armored Age ciphertext.
65
+ * @throws If any public key is invalid or the array is empty.
66
+ */
67
+ export declare function encryptForRecipients(plaintext: string, publicKeys: string[]): Promise<string>;
68
+ /**
69
+ * Encrypt a typed data object as JSON for multiple Age recipients.
70
+ *
71
+ * Serialises the data to JSON in memory, then encrypts for all recipients.
72
+ * No plaintext JSON is ever written to disk.
73
+ *
74
+ * @param data - The data to encrypt.
75
+ * @param publicKeys - Array of Age public keys to encrypt for.
76
+ * @returns ASCII-armored Age ciphertext containing the serialised JSON.
77
+ */
78
+ export declare function encryptStateForRecipients<T>(data: T, publicKeys: string[]): Promise<string>;
79
+ //# sourceMappingURL=encryption.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encryption.d.ts","sourceRoot":"","sources":["../../src/core/encryption.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH;;;;GAIG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAItF;AAED;;;;;;;GAOG;AACH,wBAAsB,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAKnF;AAED;;;;;;;GAOG;AACH,wBAAsB,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAKrF;AAED;;;;;;;;GAQG;AACH,wBAAsB,YAAY,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAGjF;AAED;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAGxF;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,oBAAoB,CACxC,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAAE,GACnB,OAAO,CAAC,MAAM,CAAC,CAWjB;AAED;;;;;;;;;GASG;AACH,wBAAsB,yBAAyB,CAAC,CAAC,EAC/C,IAAI,EAAE,CAAC,EACP,UAAU,EAAE,MAAM,EAAE,GACnB,OAAO,CAAC,MAAM,CAAC,CAGjB"}