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.
- package/dist/commands/audit.d.ts +76 -0
- package/dist/commands/audit.d.ts.map +1 -0
- package/dist/commands/audit.js +367 -0
- package/dist/commands/audit.js.map +1 -0
- package/dist/commands/config.d.ts +58 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +114 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/dir.d.ts +56 -0
- package/dist/commands/dir.d.ts.map +1 -0
- package/dist/commands/dir.js +172 -0
- package/dist/commands/dir.js.map +1 -0
- package/dist/commands/docker.d.ts +140 -0
- package/dist/commands/docker.d.ts.map +1 -0
- package/dist/commands/docker.js +380 -0
- package/dist/commands/docker.js.map +1 -0
- package/dist/commands/env.d.ts +96 -0
- package/dist/commands/env.d.ts.map +1 -0
- package/dist/commands/env.js +352 -0
- package/dist/commands/env.js.map +1 -0
- package/dist/commands/init.d.ts +89 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +272 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/key.d.ts +92 -0
- package/dist/commands/key.d.ts.map +1 -0
- package/dist/commands/key.js +274 -0
- package/dist/commands/key.js.map +1 -0
- package/dist/commands/list.d.ts +38 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +84 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/note.d.ts +151 -0
- package/dist/commands/note.d.ts.map +1 -0
- package/dist/commands/note.js +411 -0
- package/dist/commands/note.js.map +1 -0
- package/dist/commands/pull.d.ts +47 -0
- package/dist/commands/pull.d.ts.map +1 -0
- package/dist/commands/pull.js +94 -0
- package/dist/commands/pull.js.map +1 -0
- package/dist/commands/push.d.ts +40 -0
- package/dist/commands/push.d.ts.map +1 -0
- package/dist/commands/push.js +94 -0
- package/dist/commands/push.js.map +1 -0
- package/dist/commands/restore.d.ts +116 -0
- package/dist/commands/restore.d.ts.map +1 -0
- package/dist/commands/restore.js +336 -0
- package/dist/commands/restore.js.map +1 -0
- package/dist/commands/service.d.ts +83 -0
- package/dist/commands/service.d.ts.map +1 -0
- package/dist/commands/service.js +259 -0
- package/dist/commands/service.js.map +1 -0
- package/dist/commands/show.d.ts +63 -0
- package/dist/commands/show.d.ts.map +1 -0
- package/dist/commands/show.js +243 -0
- package/dist/commands/show.js.map +1 -0
- package/dist/commands/status.d.ts +53 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +150 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/sync.d.ts +105 -0
- package/dist/commands/sync.d.ts.map +1 -0
- package/dist/commands/sync.js +243 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/commands/team.d.ts +79 -0
- package/dist/commands/team.d.ts.map +1 -0
- package/dist/commands/team.js +233 -0
- package/dist/commands/team.js.map +1 -0
- package/dist/commands/track.d.ts +109 -0
- package/dist/commands/track.d.ts.map +1 -0
- package/dist/commands/track.js +406 -0
- package/dist/commands/track.js.map +1 -0
- package/dist/core/command-validator.d.ts +100 -0
- package/dist/core/command-validator.d.ts.map +1 -0
- package/dist/core/command-validator.js +299 -0
- package/dist/core/command-validator.js.map +1 -0
- package/dist/core/config-store.d.ts +76 -0
- package/dist/core/config-store.d.ts.map +1 -0
- package/dist/core/config-store.js +148 -0
- package/dist/core/config-store.js.map +1 -0
- package/dist/core/directories-handler.d.ts +116 -0
- package/dist/core/directories-handler.d.ts.map +1 -0
- package/dist/core/directories-handler.js +199 -0
- package/dist/core/directories-handler.js.map +1 -0
- package/dist/core/docker-handler.d.ts +183 -0
- package/dist/core/docker-handler.d.ts.map +1 -0
- package/dist/core/docker-handler.js +515 -0
- package/dist/core/docker-handler.js.map +1 -0
- package/dist/core/encryption.d.ts +79 -0
- package/dist/core/encryption.d.ts.map +1 -0
- package/dist/core/encryption.js +111 -0
- package/dist/core/encryption.js.map +1 -0
- package/dist/core/env-handler.d.ts +128 -0
- package/dist/core/env-handler.d.ts.map +1 -0
- package/dist/core/env-handler.js +272 -0
- package/dist/core/env-handler.js.map +1 -0
- package/dist/core/git-sync.d.ts +88 -0
- package/dist/core/git-sync.d.ts.map +1 -0
- package/dist/core/git-sync.js +143 -0
- package/dist/core/git-sync.js.map +1 -0
- package/dist/core/key-store.d.ts +51 -0
- package/dist/core/key-store.d.ts.map +1 -0
- package/dist/core/key-store.js +108 -0
- package/dist/core/key-store.js.map +1 -0
- package/dist/core/log-sanitizer.d.ts +72 -0
- package/dist/core/log-sanitizer.d.ts.map +1 -0
- package/dist/core/log-sanitizer.js +202 -0
- package/dist/core/log-sanitizer.js.map +1 -0
- package/dist/core/path-validator.d.ts +37 -0
- package/dist/core/path-validator.d.ts.map +1 -0
- package/dist/core/path-validator.js +127 -0
- package/dist/core/path-validator.js.map +1 -0
- package/dist/core/recipients.d.ts +99 -0
- package/dist/core/recipients.d.ts.map +1 -0
- package/dist/core/recipients.js +206 -0
- package/dist/core/recipients.js.map +1 -0
- package/dist/core/services-handler.d.ts +113 -0
- package/dist/core/services-handler.d.ts.map +1 -0
- package/dist/core/services-handler.js +176 -0
- package/dist/core/services-handler.js.map +1 -0
- package/dist/core/state-manager.d.ts +96 -0
- package/dist/core/state-manager.d.ts.map +1 -0
- package/dist/core/state-manager.js +165 -0
- package/dist/core/state-manager.js.map +1 -0
- package/dist/core/transport.d.ts +28 -0
- package/dist/core/transport.d.ts.map +1 -0
- package/dist/core/transport.js +79 -0
- package/dist/core/transport.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +80 -0
- package/dist/index.js.map +1 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/errors.d.ts +81 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +191 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/secure-memory.d.ts +65 -0
- package/dist/utils/secure-memory.d.ts.map +1 -0
- package/dist/utils/secure-memory.js +86 -0
- package/dist/utils/secure-memory.js.map +1 -0
- package/package.json +58 -0
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Directories handler module.
|
|
3
|
+
*
|
|
4
|
+
* Tracks recent working directories and pinned directories associated
|
|
5
|
+
* with a user's development workflow. State is persisted in
|
|
6
|
+
* `directories.age` (encrypted).
|
|
7
|
+
*
|
|
8
|
+
* **Path validation:** All directory paths are validated through the
|
|
9
|
+
* path-validator module to prevent path traversal attacks.
|
|
10
|
+
*
|
|
11
|
+
* @module core/directories-handler
|
|
12
|
+
*/
|
|
13
|
+
import { readState, writeState } from './state-manager.js';
|
|
14
|
+
import { validateProjectPath } from './path-validator.js';
|
|
15
|
+
// ─── Constants ────────────────────────────────────────────────────────────
|
|
16
|
+
/**
|
|
17
|
+
* Maximum number of recent directories to retain.
|
|
18
|
+
* Older, less-frequent entries are pruned when this limit is exceeded.
|
|
19
|
+
*/
|
|
20
|
+
export const MAX_RECENT_DIRS = 50;
|
|
21
|
+
// ─── Helpers ──────────────────────────────────────────────────────────────
|
|
22
|
+
/**
|
|
23
|
+
* Build an empty `DirectoryState`.
|
|
24
|
+
*/
|
|
25
|
+
function emptyState() {
|
|
26
|
+
return { recentDirs: [], pinnedDirs: [] };
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Sort recent directories by frequency (descending), then by lastVisit
|
|
30
|
+
* (most recent first).
|
|
31
|
+
*/
|
|
32
|
+
function sortRecent(dirs) {
|
|
33
|
+
return [...dirs].sort((a, b) => {
|
|
34
|
+
if (b.frequency !== a.frequency)
|
|
35
|
+
return b.frequency - a.frequency;
|
|
36
|
+
return b.lastVisit.localeCompare(a.lastVisit);
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
// ─── Public API ───────────────────────────────────────────────────────────
|
|
40
|
+
/**
|
|
41
|
+
* Load directory state from encrypted storage.
|
|
42
|
+
*
|
|
43
|
+
* @param syncDir - The sync directory (e.g. ~/.context-sync).
|
|
44
|
+
* @param privateKey - Age private key for decryption.
|
|
45
|
+
* @returns The decrypted `DirectoryState`, or an empty state if the
|
|
46
|
+
* file does not exist.
|
|
47
|
+
*/
|
|
48
|
+
export async function loadDirectories(syncDir, privateKey) {
|
|
49
|
+
const state = await readState(syncDir, privateKey, 'directories');
|
|
50
|
+
return state ?? emptyState();
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Save (overwrite) the entire directory state.
|
|
54
|
+
*
|
|
55
|
+
* @param syncDir - The sync directory.
|
|
56
|
+
* @param state - The complete `DirectoryState` to persist.
|
|
57
|
+
* @param publicKey - Age public key for encryption.
|
|
58
|
+
*/
|
|
59
|
+
export async function saveDirectories(syncDir, state, publicKey) {
|
|
60
|
+
await writeState(syncDir, state, publicKey, 'directories');
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Record a directory visit.
|
|
64
|
+
*
|
|
65
|
+
* - If the directory already exists in the recent list, its frequency is
|
|
66
|
+
* incremented and its lastVisit timestamp updated.
|
|
67
|
+
* - If new, it is added with frequency 1.
|
|
68
|
+
* - The list is pruned to `MAX_RECENT_DIRS` after insertion.
|
|
69
|
+
* - The path is validated against the path-validator to reject traversal
|
|
70
|
+
* attacks.
|
|
71
|
+
*
|
|
72
|
+
* @param syncDir - The sync directory.
|
|
73
|
+
* @param dirPath - The directory path to record (will be validated).
|
|
74
|
+
* @param publicKey - Age public key for encryption.
|
|
75
|
+
* @param privateKey - Age private key for decryption.
|
|
76
|
+
* @throws If the path fails validation.
|
|
77
|
+
*/
|
|
78
|
+
export async function visitDirectory(syncDir, dirPath, publicKey, privateKey) {
|
|
79
|
+
// Validate the path — throws on traversal / blocked paths
|
|
80
|
+
const validatedPath = validateProjectPath(dirPath);
|
|
81
|
+
const state = await loadDirectories(syncDir, privateKey);
|
|
82
|
+
const now = new Date().toISOString();
|
|
83
|
+
const existing = state.recentDirs.find((d) => d.path === validatedPath);
|
|
84
|
+
if (existing) {
|
|
85
|
+
existing.frequency += 1;
|
|
86
|
+
existing.lastVisit = now;
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
state.recentDirs.push({
|
|
90
|
+
path: validatedPath,
|
|
91
|
+
frequency: 1,
|
|
92
|
+
lastVisit: now,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
// Sort and prune
|
|
96
|
+
state.recentDirs = sortRecent(state.recentDirs).slice(0, MAX_RECENT_DIRS);
|
|
97
|
+
await saveDirectories(syncDir, state, publicKey);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Pin a directory.
|
|
101
|
+
*
|
|
102
|
+
* Pinned directories are always shown at the top of directory listings
|
|
103
|
+
* and are not subject to the recent-directory pruning limit.
|
|
104
|
+
*
|
|
105
|
+
* @param syncDir - The sync directory.
|
|
106
|
+
* @param dirPath - The directory path to pin (will be validated).
|
|
107
|
+
* @param publicKey - Age public key for encryption.
|
|
108
|
+
* @param privateKey - Age private key for decryption.
|
|
109
|
+
* @returns `true` if the directory was newly pinned, `false` if already pinned.
|
|
110
|
+
* @throws If the path fails validation.
|
|
111
|
+
*/
|
|
112
|
+
export async function pinDirectory(syncDir, dirPath, publicKey, privateKey) {
|
|
113
|
+
const validatedPath = validateProjectPath(dirPath);
|
|
114
|
+
const state = await loadDirectories(syncDir, privateKey);
|
|
115
|
+
if (state.pinnedDirs.includes(validatedPath)) {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
state.pinnedDirs.push(validatedPath);
|
|
119
|
+
await saveDirectories(syncDir, state, publicKey);
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Unpin a directory.
|
|
124
|
+
*
|
|
125
|
+
* @param syncDir - The sync directory.
|
|
126
|
+
* @param dirPath - The directory path to unpin (will be validated).
|
|
127
|
+
* @param publicKey - Age public key for encryption.
|
|
128
|
+
* @param privateKey - Age private key for decryption.
|
|
129
|
+
* @returns `true` if the directory was unpinned, `false` if it was not pinned.
|
|
130
|
+
* @throws If the path fails validation.
|
|
131
|
+
*/
|
|
132
|
+
export async function unpinDirectory(syncDir, dirPath, publicKey, privateKey) {
|
|
133
|
+
const validatedPath = validateProjectPath(dirPath);
|
|
134
|
+
const state = await loadDirectories(syncDir, privateKey);
|
|
135
|
+
const before = state.pinnedDirs.length;
|
|
136
|
+
state.pinnedDirs = state.pinnedDirs.filter((p) => p !== validatedPath);
|
|
137
|
+
if (state.pinnedDirs.length === before) {
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
await saveDirectories(syncDir, state, publicKey);
|
|
141
|
+
return true;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Remove a directory from the recent list (does not affect pinned).
|
|
145
|
+
*
|
|
146
|
+
* @param syncDir - The sync directory.
|
|
147
|
+
* @param dirPath - The directory path to remove.
|
|
148
|
+
* @param publicKey - Age public key for encryption.
|
|
149
|
+
* @param privateKey - Age private key for decryption.
|
|
150
|
+
* @returns `true` if the directory was removed, `false` if not found.
|
|
151
|
+
*/
|
|
152
|
+
export async function removeRecentDirectory(syncDir, dirPath, publicKey, privateKey) {
|
|
153
|
+
const validatedPath = validateProjectPath(dirPath);
|
|
154
|
+
const state = await loadDirectories(syncDir, privateKey);
|
|
155
|
+
const before = state.recentDirs.length;
|
|
156
|
+
state.recentDirs = state.recentDirs.filter((d) => d.path !== validatedPath);
|
|
157
|
+
if (state.recentDirs.length === before) {
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
await saveDirectories(syncDir, state, publicKey);
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Get the most-visited recent directories.
|
|
165
|
+
*
|
|
166
|
+
* @param syncDir - The sync directory.
|
|
167
|
+
* @param privateKey - Age private key.
|
|
168
|
+
* @param limit - Maximum number to return (default: 10).
|
|
169
|
+
* @returns Sorted recent directories (most-visited first).
|
|
170
|
+
*/
|
|
171
|
+
export async function getTopDirectories(syncDir, privateKey, limit = 10) {
|
|
172
|
+
const state = await loadDirectories(syncDir, privateKey);
|
|
173
|
+
return sortRecent(state.recentDirs).slice(0, limit);
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Get all pinned directories.
|
|
177
|
+
*
|
|
178
|
+
* @param syncDir - The sync directory.
|
|
179
|
+
* @param privateKey - Age private key.
|
|
180
|
+
* @returns Array of pinned directory paths.
|
|
181
|
+
*/
|
|
182
|
+
export async function getPinnedDirectories(syncDir, privateKey) {
|
|
183
|
+
const state = await loadDirectories(syncDir, privateKey);
|
|
184
|
+
return [...state.pinnedDirs];
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Validate a directory path for use in directory state.
|
|
188
|
+
*
|
|
189
|
+
* Thin wrapper around `validateProjectPath` exposed for external callers
|
|
190
|
+
* who want to validate before calling other functions.
|
|
191
|
+
*
|
|
192
|
+
* @param dirPath - The directory path to validate.
|
|
193
|
+
* @returns The canonicalised, validated path.
|
|
194
|
+
* @throws If the path is invalid.
|
|
195
|
+
*/
|
|
196
|
+
export function validateDirectoryPath(dirPath) {
|
|
197
|
+
return validateProjectPath(dirPath);
|
|
198
|
+
}
|
|
199
|
+
//# sourceMappingURL=directories-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"directories-handler.js","sourceRoot":"","sources":["../../src/core/directories-handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,183 @@
|
|
|
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 type { DockerState } from '@ctx-sync/shared';
|
|
14
|
+
/**
|
|
15
|
+
* Known Docker Compose file names (in priority order).
|
|
16
|
+
*/
|
|
17
|
+
export declare const COMPOSE_FILE_NAMES: readonly string[];
|
|
18
|
+
/**
|
|
19
|
+
* Result of Docker Compose file detection.
|
|
20
|
+
*/
|
|
21
|
+
export interface ComposeDetectResult {
|
|
22
|
+
/** Whether a compose file was found */
|
|
23
|
+
found: boolean;
|
|
24
|
+
/** Absolute path to the compose file (null if not found) */
|
|
25
|
+
filePath: string | null;
|
|
26
|
+
/** Which compose file name was found */
|
|
27
|
+
fileName: string | null;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* A parsed service entry from a Docker Compose file.
|
|
31
|
+
*/
|
|
32
|
+
export interface ParsedService {
|
|
33
|
+
/** Service name (key in the compose file) */
|
|
34
|
+
name: string;
|
|
35
|
+
/** Docker image */
|
|
36
|
+
image: string;
|
|
37
|
+
/** Container name (if specified) */
|
|
38
|
+
container: string;
|
|
39
|
+
/** Published host port (first mapping, or 0 if not specified) */
|
|
40
|
+
port: number;
|
|
41
|
+
/** Volume mounts */
|
|
42
|
+
volumes: string[];
|
|
43
|
+
/** Health check command (if specified) */
|
|
44
|
+
healthCheck: string | undefined;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Result of parsing a Docker Compose file.
|
|
48
|
+
*/
|
|
49
|
+
export interface ComposeParseResult {
|
|
50
|
+
/** Parsed services */
|
|
51
|
+
services: ParsedService[];
|
|
52
|
+
/** Networks defined in the compose file */
|
|
53
|
+
networks: string[];
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* A running container as reported by Docker.
|
|
57
|
+
*/
|
|
58
|
+
export interface RunningContainer {
|
|
59
|
+
/** Container ID */
|
|
60
|
+
id: string;
|
|
61
|
+
/** Container name */
|
|
62
|
+
name: string;
|
|
63
|
+
/** Docker image */
|
|
64
|
+
image: string;
|
|
65
|
+
/** Container status (e.g. "Up 2 hours") */
|
|
66
|
+
status: string;
|
|
67
|
+
/** Published ports (e.g. "0.0.0.0:5432->5432/tcp") */
|
|
68
|
+
ports: string;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Detect a Docker Compose file in the given project directory.
|
|
72
|
+
*
|
|
73
|
+
* Searches for known compose file names in priority order. Does not
|
|
74
|
+
* throw if none is found — returns `found: false`.
|
|
75
|
+
*
|
|
76
|
+
* @param projectDir - Absolute path to the project directory.
|
|
77
|
+
* @returns Detection result with file path if found.
|
|
78
|
+
*/
|
|
79
|
+
export declare function detectDockerCompose(projectDir: string): ComposeDetectResult;
|
|
80
|
+
/**
|
|
81
|
+
* Parse a Docker Compose file and extract service definitions.
|
|
82
|
+
*
|
|
83
|
+
* Uses a simple YAML parser (line-based) to extract services, ports,
|
|
84
|
+
* images, volumes, and networks without requiring a full YAML library.
|
|
85
|
+
* This handles common compose file patterns.
|
|
86
|
+
*
|
|
87
|
+
* @param filePath - Absolute path to the compose file.
|
|
88
|
+
* @returns Parsed services and networks.
|
|
89
|
+
* @throws If the file cannot be read.
|
|
90
|
+
*/
|
|
91
|
+
export declare function parseComposeFile(filePath: string): ComposeParseResult;
|
|
92
|
+
/**
|
|
93
|
+
* Parse Docker Compose YAML content.
|
|
94
|
+
*
|
|
95
|
+
* Simple line-based parser that handles common compose file patterns.
|
|
96
|
+
* Extracts service name, image, container_name, ports, volumes,
|
|
97
|
+
* healthcheck, and top-level networks.
|
|
98
|
+
*
|
|
99
|
+
* @param content - The raw YAML content.
|
|
100
|
+
* @returns Parsed services and networks.
|
|
101
|
+
*/
|
|
102
|
+
export declare function parseComposeContent(content: string): ComposeParseResult;
|
|
103
|
+
/**
|
|
104
|
+
* Parse a host port from a port mapping string.
|
|
105
|
+
*
|
|
106
|
+
* Handles formats like:
|
|
107
|
+
* - "5432:5432"
|
|
108
|
+
* - "5432:5432/tcp"
|
|
109
|
+
* - "0.0.0.0:5432:5432"
|
|
110
|
+
* - "8080:80"
|
|
111
|
+
*
|
|
112
|
+
* Returns the **host** port (left side).
|
|
113
|
+
*/
|
|
114
|
+
export declare function parseHostPort(mapping: string): number;
|
|
115
|
+
/**
|
|
116
|
+
* Check if Docker is available on this machine.
|
|
117
|
+
*
|
|
118
|
+
* @returns `true` if `docker` CLI is installed and responds to `docker info`.
|
|
119
|
+
*/
|
|
120
|
+
export declare function isDockerAvailable(): boolean;
|
|
121
|
+
/**
|
|
122
|
+
* Get running containers for a project directory.
|
|
123
|
+
*
|
|
124
|
+
* Uses `docker compose ps` to query running containers related to
|
|
125
|
+
* the compose file in the given directory.
|
|
126
|
+
*
|
|
127
|
+
* @param projectDir - Absolute path to the project directory.
|
|
128
|
+
* @returns List of running containers, or empty array if Docker is not available.
|
|
129
|
+
*/
|
|
130
|
+
export declare function getRunningContainers(projectDir: string): RunningContainer[];
|
|
131
|
+
/**
|
|
132
|
+
* Build a DockerState entry for a project from its compose file.
|
|
133
|
+
*
|
|
134
|
+
* Detects the compose file, parses it, and creates a DockerState entry
|
|
135
|
+
* suitable for encryption and storage.
|
|
136
|
+
*
|
|
137
|
+
* @param projectName - The project name (key in the DockerState map).
|
|
138
|
+
* @param projectDir - Absolute path to the project directory.
|
|
139
|
+
* @param autoStartDefault - Default value for autoStart on each service.
|
|
140
|
+
* @returns The project's Docker state entry, or `null` if no compose file found.
|
|
141
|
+
*/
|
|
142
|
+
export declare function buildDockerStateEntry(projectName: string, projectDir: string, autoStartDefault?: boolean): DockerState[string] | null;
|
|
143
|
+
/**
|
|
144
|
+
* Save Docker state for a project to encrypted storage.
|
|
145
|
+
*
|
|
146
|
+
* Reads existing Docker state, merges the new project entry, and
|
|
147
|
+
* writes the updated state to `docker-state.age`.
|
|
148
|
+
*
|
|
149
|
+
* @param syncDir - The sync directory path.
|
|
150
|
+
* @param projectName - The project name (key in DockerState).
|
|
151
|
+
* @param entry - The Docker state entry for the project.
|
|
152
|
+
* @param publicKey - The Age public key for encryption.
|
|
153
|
+
* @param privateKey - The Age private key for reading existing state.
|
|
154
|
+
*/
|
|
155
|
+
export declare function saveDockerState(syncDir: string, projectName: string, entry: DockerState[string], publicKey: string, privateKey: string): Promise<void>;
|
|
156
|
+
/**
|
|
157
|
+
* Load Docker state for a specific project from encrypted storage.
|
|
158
|
+
*
|
|
159
|
+
* @param syncDir - The sync directory path.
|
|
160
|
+
* @param projectName - The project name.
|
|
161
|
+
* @param privateKey - The Age private key for decryption.
|
|
162
|
+
* @returns The project's Docker state, or `null` if not found.
|
|
163
|
+
*/
|
|
164
|
+
export declare function loadDockerState(syncDir: string, projectName: string, privateKey: string): Promise<DockerState[string] | null>;
|
|
165
|
+
/**
|
|
166
|
+
* Load all Docker state from encrypted storage.
|
|
167
|
+
*
|
|
168
|
+
* @param syncDir - The sync directory path.
|
|
169
|
+
* @param privateKey - The Age private key for decryption.
|
|
170
|
+
* @returns Full Docker state, or `null` if no docker-state.age exists.
|
|
171
|
+
*/
|
|
172
|
+
export declare function loadAllDockerState(syncDir: string, privateKey: string): Promise<DockerState | null>;
|
|
173
|
+
/**
|
|
174
|
+
* Remove Docker state for a project from encrypted storage.
|
|
175
|
+
*
|
|
176
|
+
* @param syncDir - The sync directory path.
|
|
177
|
+
* @param projectName - The project name to remove.
|
|
178
|
+
* @param publicKey - The Age public key for re-encryption.
|
|
179
|
+
* @param privateKey - The Age private key for decryption.
|
|
180
|
+
* @returns `true` if the project was found and removed.
|
|
181
|
+
*/
|
|
182
|
+
export declare function removeDockerState(syncDir: string, projectName: string, publicKey: string, privateKey: string): Promise<boolean>;
|
|
183
|
+
//# sourceMappingURL=docker-handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docker-handler.d.ts","sourceRoot":"","sources":["../../src/core/docker-handler.ts"],"names":[],"mappings":"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"}
|