@exreve/exk 1.0.54 → 1.0.56

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.
@@ -1,193 +0,0 @@
1
- /**
2
- * Container Handlers Module
3
- *
4
- * Handles container:check, container:list, container:start,
5
- * container:stop, container:remove, container:logs operations.
6
- */
7
- import path from 'path';
8
- import { execSync } from 'child_process';
9
- function getContainerRuntime() {
10
- try {
11
- execSync('which docker', { stdio: 'ignore' });
12
- return 'docker';
13
- }
14
- catch {
15
- try {
16
- execSync('which podman', { stdio: 'ignore' });
17
- return 'podman';
18
- }
19
- catch {
20
- return null;
21
- }
22
- }
23
- }
24
- export function registerContainerHandlers(socket, foreground, cliDir) {
25
- socket.on('container:check:request', async () => {
26
- try {
27
- let enabled = false;
28
- let runtime;
29
- let version = '';
30
- try {
31
- execSync('which docker', { stdio: 'ignore' });
32
- runtime = 'docker';
33
- version = execSync('docker --version', { encoding: 'utf-8' }).trim();
34
- enabled = true;
35
- }
36
- catch {
37
- try {
38
- execSync('which podman', { stdio: 'ignore' });
39
- runtime = 'podman';
40
- version = execSync('podman --version', { encoding: 'utf-8' }).trim();
41
- enabled = true;
42
- }
43
- catch {
44
- enabled = false;
45
- }
46
- }
47
- socket.emit('container:check:response', { enabled, runtime, version });
48
- if (foreground) {
49
- console.log(`Container runtime check: ${enabled ? `${runtime} (${version})` : 'Not found'}`);
50
- }
51
- }
52
- catch (error) {
53
- socket.emit('container:check:response', { enabled: false, runtime: undefined, version: '' });
54
- }
55
- });
56
- socket.on('container:list:request', async () => {
57
- try {
58
- const runtime = getContainerRuntime();
59
- if (!runtime) {
60
- socket.emit('container:list:response', { success: false, error: 'No container runtime found' });
61
- return;
62
- }
63
- const output = execSync(`${runtime} ps -a --format "{{json .}}"`, { encoding: 'utf-8', maxBuffer: 10 * 1024 * 1024 });
64
- const containers = output.trim().split('\n').filter(Boolean).map(line => {
65
- try {
66
- const c = JSON.parse(line);
67
- const ports = [];
68
- if (c.Ports) {
69
- const portMatches = c.Ports.match(/(\d+)->(\d+)/g);
70
- if (portMatches) {
71
- portMatches.forEach((p) => {
72
- const [host, container] = p.split('->').map(Number);
73
- ports.push({ host, container });
74
- });
75
- }
76
- }
77
- return {
78
- containerId: c.ID,
79
- name: c.Names.replace(/^\//, ''),
80
- image: c.Image,
81
- status: c.State === 'running' ? 'running' : c.State === 'paused' ? 'paused' : c.Status === 'exited' ? 'exited' : 'stopped',
82
- ports,
83
- createdAt: new Date(c.CreatedAt).toISOString()
84
- };
85
- }
86
- catch {
87
- return null;
88
- }
89
- }).filter(Boolean);
90
- socket.emit('container:list:response', { success: true, containers });
91
- }
92
- catch (error) {
93
- socket.emit('container:list:response', { success: false, error: error.message });
94
- }
95
- });
96
- socket.on('container:start:request', async (data) => {
97
- try {
98
- const runtime = getContainerRuntime();
99
- if (!runtime) {
100
- socket.emit('container:start:response', { success: false, error: 'No container runtime found' });
101
- return;
102
- }
103
- const { name, image, ports = [], env = {}, runAsRoot = false } = data;
104
- let cmd = `${runtime} run -d --name ${name}`;
105
- if (!runAsRoot) {
106
- cmd += ' --user 1000:1000';
107
- }
108
- cmd += ' --memory=8g';
109
- cmd += ` -v "${cliDir}:/opt/ttc:ro"`;
110
- const entrypointScript = path.join(cliDir, 'container-entrypoint.sh');
111
- cmd += ` -v "${entrypointScript}:/entrypoint.sh:ro"`;
112
- ports.forEach(p => {
113
- cmd += ` -p ${p.host}:${p.container}`;
114
- });
115
- Object.entries(env).forEach(([k, v]) => {
116
- const escapedValue = String(v).replace(/"/g, '\\"');
117
- cmd += ` -e ${k}="${escapedValue}"`;
118
- });
119
- cmd += ` -e CONTAINER_NAME="${name}"`;
120
- cmd += ` -e HOSTNAME="${name}"`;
121
- cmd += ` --entrypoint /bin/sh ${image} /entrypoint.sh`;
122
- if (foreground) {
123
- console.log(`Starting container: ${cmd}`);
124
- }
125
- try {
126
- execSync(`${runtime} pull ${image}`, { stdio: 'ignore' });
127
- }
128
- catch {
129
- // Pull failed, but might already exist locally
130
- }
131
- const output = execSync(cmd, { encoding: 'utf-8', stdio: 'pipe' });
132
- const containerId = output.trim();
133
- socket.emit('container:start:response', { success: true, containerId });
134
- if (foreground) {
135
- console.log(`✓ Container started: ${containerId}`);
136
- }
137
- }
138
- catch (error) {
139
- socket.emit('container:start:response', { success: false, error: error.message });
140
- }
141
- });
142
- socket.on('container:stop:request', async (data) => {
143
- try {
144
- const runtime = getContainerRuntime();
145
- if (!runtime) {
146
- socket.emit('container:stop:response', { success: false, error: 'No container runtime found' });
147
- return;
148
- }
149
- const { containerId } = data;
150
- execSync(`${runtime} stop ${containerId}`, { stdio: 'ignore' });
151
- socket.emit('container:stop:response', { success: true });
152
- if (foreground) {
153
- console.log(`✓ Container stopped: ${containerId}`);
154
- }
155
- }
156
- catch (error) {
157
- socket.emit('container:stop:response', { success: false, error: error.message });
158
- }
159
- });
160
- socket.on('container:remove:request', async (data) => {
161
- try {
162
- const runtime = getContainerRuntime();
163
- if (!runtime) {
164
- socket.emit('container:remove:response', { success: false, error: 'No container runtime found' });
165
- return;
166
- }
167
- const { containerId } = data;
168
- execSync(`${runtime} rm -f ${containerId}`, { stdio: 'ignore' });
169
- socket.emit('container:remove:response', { success: true });
170
- if (foreground) {
171
- console.log(`✓ Container removed: ${containerId}`);
172
- }
173
- }
174
- catch (error) {
175
- socket.emit('container:remove:response', { success: false, error: error.message });
176
- }
177
- });
178
- socket.on('container:logs:request', async (data) => {
179
- try {
180
- const runtime = getContainerRuntime();
181
- if (!runtime) {
182
- socket.emit('container:logs:response', { success: false, error: 'No container runtime found' });
183
- return;
184
- }
185
- const { containerId, lines = 100 } = data;
186
- const logs = execSync(`${runtime} logs --tail ${lines} ${containerId}`, { encoding: 'utf-8', maxBuffer: 10 * 1024 * 1024 });
187
- socket.emit('container:logs:response', { success: true, logs });
188
- }
189
- catch (error) {
190
- socket.emit('container:logs:response', { success: false, error: error.message });
191
- }
192
- });
193
- }
@@ -1,86 +0,0 @@
1
- /**
2
- * Filesystem Handlers Module
3
- *
4
- * Handles fs:list, fs:write, fs:read operations on the CLI device.
5
- */
6
- import fs from 'fs/promises';
7
- import path from 'path';
8
- export function registerFsHandlers(socket) {
9
- socket.on('fs:list', async (data) => {
10
- try {
11
- const { dirPath } = data;
12
- if (!dirPath) {
13
- socket.emit('fs:list:response', { success: false, error: 'dirPath is required' });
14
- return;
15
- }
16
- const entries = [];
17
- try {
18
- const dirents = await fs.readdir(dirPath, { withFileTypes: true });
19
- for (const dirent of dirents) {
20
- if (dirent.name.startsWith('.'))
21
- continue;
22
- const fullPath = path.join(dirPath, dirent.name);
23
- entries.push({
24
- name: dirent.name,
25
- path: fullPath,
26
- isDir: dirent.isDirectory()
27
- });
28
- }
29
- entries.sort((a, b) => {
30
- if (a.isDir && !b.isDir)
31
- return -1;
32
- if (!a.isDir && b.isDir)
33
- return 1;
34
- return a.name.localeCompare(b.name);
35
- });
36
- socket.emit('fs:list:response', { success: true, entries });
37
- }
38
- catch (err) {
39
- socket.emit('fs:list:response', { success: false, error: err.message });
40
- }
41
- }
42
- catch (error) {
43
- socket.emit('fs:list:response', { success: false, error: error.message });
44
- }
45
- });
46
- socket.on('fs:write', async (data) => {
47
- try {
48
- const { filePath, content, encoding = 'utf-8' } = data;
49
- if (!filePath) {
50
- socket.emit('fs:write:response', { success: false, error: 'filePath is required' });
51
- return;
52
- }
53
- try {
54
- const dir = path.dirname(filePath);
55
- await fs.mkdir(dir, { recursive: true });
56
- await fs.writeFile(filePath, content, encoding);
57
- socket.emit('fs:write:response', { success: true });
58
- }
59
- catch (err) {
60
- socket.emit('fs:write:response', { success: false, error: err.message });
61
- }
62
- }
63
- catch (error) {
64
- socket.emit('fs:write:response', { success: false, error: error.message });
65
- }
66
- });
67
- socket.on('fs:read', async (data) => {
68
- try {
69
- const { filePath, encoding = 'utf-8' } = data;
70
- if (!filePath) {
71
- socket.emit('fs:read:response', { success: false, error: 'filePath is required' });
72
- return;
73
- }
74
- try {
75
- const content = await fs.readFile(filePath, encoding);
76
- socket.emit('fs:read:response', { success: true, content });
77
- }
78
- catch (err) {
79
- socket.emit('fs:read:response', { success: false, error: err.message });
80
- }
81
- }
82
- catch (error) {
83
- socket.emit('fs:read:response', { success: false, error: error.message });
84
- }
85
- });
86
- }