@oussema_mili/test-pkg-123 1.1.32

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 (49) hide show
  1. package/LICENSE +29 -0
  2. package/README.md +220 -0
  3. package/auth-callback.html +97 -0
  4. package/auth.js +276 -0
  5. package/cli-commands.js +1921 -0
  6. package/containerManager.js +304 -0
  7. package/daemon/agentRunner.js +491 -0
  8. package/daemon/daemonEntry.js +64 -0
  9. package/daemon/daemonManager.js +266 -0
  10. package/daemon/logManager.js +227 -0
  11. package/dist/styles.css +504 -0
  12. package/docker-actions/apps.js +3913 -0
  13. package/docker-actions/config-transformer.js +380 -0
  14. package/docker-actions/containers.js +355 -0
  15. package/docker-actions/general.js +171 -0
  16. package/docker-actions/images.js +1128 -0
  17. package/docker-actions/logs.js +224 -0
  18. package/docker-actions/metrics.js +270 -0
  19. package/docker-actions/registry.js +1100 -0
  20. package/docker-actions/setup-tasks.js +859 -0
  21. package/docker-actions/terminal.js +247 -0
  22. package/docker-actions/volumes.js +713 -0
  23. package/helper-functions.js +193 -0
  24. package/index.html +83 -0
  25. package/index.js +341 -0
  26. package/package.json +82 -0
  27. package/postcss.config.mjs +5 -0
  28. package/scripts/release.sh +212 -0
  29. package/setup/setupWizard.js +403 -0
  30. package/store/agentSessionStore.js +51 -0
  31. package/store/agentStore.js +113 -0
  32. package/store/configStore.js +171 -0
  33. package/store/daemonStore.js +217 -0
  34. package/store/deviceCredentialStore.js +107 -0
  35. package/store/npmTokenStore.js +65 -0
  36. package/store/registryStore.js +329 -0
  37. package/store/setupState.js +147 -0
  38. package/styles.css +1 -0
  39. package/utils/appLogger.js +223 -0
  40. package/utils/deviceInfo.js +98 -0
  41. package/utils/ecrAuth.js +225 -0
  42. package/utils/encryption.js +112 -0
  43. package/utils/envSetup.js +41 -0
  44. package/utils/errorHandler.js +327 -0
  45. package/utils/portUtils.js +59 -0
  46. package/utils/prerequisites.js +323 -0
  47. package/utils/prompts.js +318 -0
  48. package/utils/ssl-certificates.js +256 -0
  49. package/websocket-server.js +415 -0
@@ -0,0 +1,355 @@
1
+ import Docker from "dockerode";
2
+ import { formatUptime } from "../helper-functions.js";
3
+ import os from "os";
4
+
5
+ // Create Docker client
6
+ let docker;
7
+ try {
8
+ docker = new Docker();
9
+ } catch (error) {
10
+ console.error(`Failed to connect to Docker daemon: ${error.message}`);
11
+ process.exit(1);
12
+ }
13
+
14
+ // Format container for response
15
+ const formatContainer = async (container) => {
16
+ try {
17
+ const containerInfo = await container.inspect();
18
+ const stats = await container.stats({ stream: false });
19
+
20
+ // Calculate CPU usage percentage using a simpler approach
21
+ let cpuPercent = 0;
22
+ try {
23
+ const cpuDelta =
24
+ stats.cpu_stats.cpu_usage.total_usage -
25
+ stats.precpu_stats.cpu_usage.total_usage;
26
+ const systemCpuDelta =
27
+ stats.cpu_stats.system_cpu_usage - stats.precpu_stats.system_cpu_usage;
28
+ const cpuCores = stats.cpu_stats.online_cpus || os.cpus().length;
29
+
30
+ if (systemCpuDelta > 0 && cpuDelta > 0) {
31
+ cpuPercent = (cpuDelta / systemCpuDelta) * cpuCores * 100;
32
+ }
33
+ } catch (err) {
34
+ console.error("Error calculating CPU percentage:", err.message);
35
+ }
36
+
37
+ // Calculate memory usage percentage
38
+ let memoryPercent = 0;
39
+ try {
40
+ const memoryUsage = stats.memory_stats.usage || 0;
41
+ const memoryLimit = stats.memory_stats.limit || 1;
42
+ memoryPercent = (memoryUsage / memoryLimit) * 100;
43
+ } catch (err) {
44
+ console.error("Error calculating memory percentage:", err.message);
45
+ }
46
+
47
+ // Format ports
48
+ const ports = [];
49
+ if (containerInfo.NetworkSettings && containerInfo.NetworkSettings.Ports) {
50
+ Object.entries(containerInfo.NetworkSettings.Ports).forEach(
51
+ ([containerPort, hostBindings]) => {
52
+ if (hostBindings) {
53
+ hostBindings.forEach((binding) => {
54
+ ports.push(`${binding.HostPort}:${containerPort}`);
55
+ });
56
+ } else {
57
+ ports.push(containerPort);
58
+ }
59
+ }
60
+ );
61
+ }
62
+
63
+ // Calculate uptime
64
+ const startTime = new Date(containerInfo.State.StartedAt).getTime();
65
+ const uptime = containerInfo.State.Running
66
+ ? formatUptime(Date.now() - startTime)
67
+ : "-";
68
+
69
+ // Extract app-related labels
70
+ const labels = containerInfo.Config.Labels || {};
71
+ const appName = labels["app.name"] || null;
72
+ const fwId = labels["app.fwId"] || labels["app.backstageId"] || null;
73
+
74
+ return {
75
+ id: container.id,
76
+ name: containerInfo.Name.replace(/^\//, ""), // Remove leading slash
77
+ image: containerInfo.Config.Image,
78
+ status: containerInfo.State.Running ? "running" : "stopped",
79
+ uptime,
80
+ ports,
81
+ cpu: isNaN(cpuPercent) ? 0 : Math.round(cpuPercent * 100) / 100,
82
+ memory: isNaN(memoryPercent) ? 0 : Math.round(memoryPercent * 100) / 100,
83
+ created: new Date(containerInfo.Created).toLocaleDateString(),
84
+ appName,
85
+ fwId,
86
+ };
87
+ } catch (error) {
88
+ console.error("Error formatting container:", error.message);
89
+ return {
90
+ id: container.id,
91
+ name: "Unknown",
92
+ image: "Unknown",
93
+ status: "error",
94
+ uptime: "-",
95
+ ports: [],
96
+ cpu: 0,
97
+ memory: 0,
98
+ created: "Unknown",
99
+ appName: null,
100
+ fwId: null,
101
+ };
102
+ }
103
+ };
104
+
105
+ async function handleContainerAction(ws, action, payload) {
106
+ switch (action) {
107
+ case "fetchContainers":
108
+ return await handleFetchContainers(ws, payload);
109
+ case "startContainer":
110
+ return await handleStartContainer(ws, payload);
111
+ case "stopContainer":
112
+ return await handleStopContainer(ws, payload);
113
+ case "restartContainer":
114
+ return await handleRestartContainer(ws, payload);
115
+ case "deleteContainer":
116
+ return await handleDeleteContainer(ws, payload);
117
+ case "createContainer":
118
+ return await handleCreateContainer(ws, payload);
119
+ case "inspectContainer":
120
+ return await handleInspectContainer(ws, payload);
121
+ default:
122
+ throw new Error(`Unknown container action: ${action}`);
123
+ }
124
+ }
125
+
126
+ async function handleFetchContainers(ws, payload = {}) {
127
+ try {
128
+ const containers = await docker.listContainers({ all: true });
129
+ const containerPromises = containers.map((container) =>
130
+ formatContainer(docker.getContainer(container.Id))
131
+ );
132
+ const formattedContainers = await Promise.all(containerPromises);
133
+
134
+ ws.send(
135
+ JSON.stringify({
136
+ type: "containers",
137
+ containers: formattedContainers,
138
+ requestId: payload.requestId,
139
+ })
140
+ );
141
+ } catch (error) {
142
+ console.error("Error fetching containers:", error);
143
+ ws.send(
144
+ JSON.stringify({
145
+ type: "error",
146
+ error: "Failed to fetch containers: " + error.message,
147
+ requestId: payload.requestId,
148
+ })
149
+ );
150
+ }
151
+ }
152
+
153
+ async function handleStartContainer(ws, payload) {
154
+ try {
155
+ const container = docker.getContainer(payload.id);
156
+ await container.start();
157
+ const formattedContainer = await formatContainer(container);
158
+
159
+ ws.send(
160
+ JSON.stringify({
161
+ type: "containerStarted",
162
+ container: formattedContainer,
163
+ requestId: payload.requestId,
164
+ })
165
+ );
166
+ } catch (error) {
167
+ console.error("Error starting container:", error);
168
+ ws.send(
169
+ JSON.stringify({
170
+ type: "error",
171
+ error: "Failed to start container: " + error.message,
172
+ requestId: payload.requestId,
173
+ })
174
+ );
175
+ }
176
+ }
177
+
178
+ async function handleStopContainer(ws, payload) {
179
+ try {
180
+ const container = docker.getContainer(payload.id);
181
+ await container.stop();
182
+ const formattedContainer = await formatContainer(container);
183
+
184
+ ws.send(
185
+ JSON.stringify({
186
+ type: "containerStopped",
187
+ container: formattedContainer,
188
+ requestId: payload.requestId,
189
+ })
190
+ );
191
+ } catch (error) {
192
+ console.error("Error stopping container:", error);
193
+ ws.send(
194
+ JSON.stringify({
195
+ type: "error",
196
+ error: "Failed to stop container: " + error.message,
197
+ requestId: payload.requestId,
198
+ })
199
+ );
200
+ }
201
+ }
202
+
203
+ async function handleRestartContainer(ws, payload) {
204
+ try {
205
+ const container = docker.getContainer(payload.id);
206
+ await container.restart();
207
+ const formattedContainer = await formatContainer(container);
208
+
209
+ ws.send(
210
+ JSON.stringify({
211
+ type: "containerRestarted",
212
+ container: formattedContainer,
213
+ requestId: payload.requestId,
214
+ })
215
+ );
216
+ } catch (error) {
217
+ console.error("Error restarting container:", error);
218
+ ws.send(
219
+ JSON.stringify({
220
+ type: "error",
221
+ error: "Failed to restart container: " + error.message,
222
+ requestId: payload.requestId,
223
+ })
224
+ );
225
+ }
226
+ }
227
+
228
+ async function handleDeleteContainer(ws, payload) {
229
+ try {
230
+ const container = docker.getContainer(payload.id);
231
+ await container.remove({ force: true });
232
+
233
+ ws.send(
234
+ JSON.stringify({
235
+ type: "containerDeleted",
236
+ id: payload.id,
237
+ success: true,
238
+ requestId: payload.requestId,
239
+ })
240
+ );
241
+ } catch (error) {
242
+ console.error("Error deleting container:", error);
243
+ ws.send(
244
+ JSON.stringify({
245
+ type: "error",
246
+ error: "Failed to delete container: " + error.message,
247
+ requestId: payload.requestId,
248
+ })
249
+ );
250
+ }
251
+ }
252
+
253
+ async function handleCreateContainer(ws, payload) {
254
+ try {
255
+ const options = payload.options;
256
+
257
+ // Format port bindings
258
+ const portBindings = {};
259
+ if (options.ports) {
260
+ const portMappings = options.ports.split(",").map((p) => p.trim());
261
+ portMappings.forEach((mapping) => {
262
+ const [hostPort, containerPort] = mapping.split(":");
263
+ portBindings[`${containerPort}/tcp`] = [{ HostPort: hostPort }];
264
+ });
265
+ }
266
+
267
+ // Format volumes
268
+ const volumes = {};
269
+ const binds = [];
270
+ if (options.volumes) {
271
+ const volumeMappings = options.volumes.split(",").map((v) => v.trim());
272
+ volumeMappings.forEach((mapping) => {
273
+ const [hostPath, containerPath] = mapping.split(":");
274
+ volumes[containerPath] = {};
275
+ binds.push(`${hostPath}:${containerPath}`);
276
+ });
277
+ }
278
+
279
+ // Format environment variables
280
+ const env = [];
281
+ if (options.environment) {
282
+ const envMappings = options.environment.split(",").map((e) => e.trim());
283
+ envMappings.forEach((mapping) => {
284
+ env.push(mapping);
285
+ });
286
+ }
287
+
288
+ // Create container
289
+ const container = await docker.createContainer({
290
+ name: options.name,
291
+ Image: options.image,
292
+ ExposedPorts: Object.keys(portBindings).reduce((acc, port) => {
293
+ acc[port] = {};
294
+ return acc;
295
+ }, {}),
296
+ HostConfig: {
297
+ PortBindings: portBindings,
298
+ Binds: binds,
299
+ RestartPolicy: {
300
+ Name: options.restart || "no",
301
+ },
302
+ },
303
+ Env: env,
304
+ Volumes: volumes,
305
+ });
306
+
307
+ const formattedContainer = await formatContainer(container);
308
+
309
+ ws.send(
310
+ JSON.stringify({
311
+ type: "containerCreated",
312
+ container: formattedContainer,
313
+ requestId: payload.requestId,
314
+ })
315
+ );
316
+ } catch (error) {
317
+ console.error("Error creating container:", error);
318
+ ws.send(
319
+ JSON.stringify({
320
+ type: "error",
321
+ error: "Failed to create container: " + error.message,
322
+ requestId: payload.requestId,
323
+ })
324
+ );
325
+ }
326
+ }
327
+
328
+ async function handleInspectContainer(ws, payload) {
329
+ try {
330
+ const { id, requestId } = payload;
331
+ const container = docker.getContainer(id);
332
+ const inspectionData = await container.inspect();
333
+
334
+ ws.send(
335
+ JSON.stringify({
336
+ type: "containerInspected",
337
+ data: inspectionData,
338
+ requestId,
339
+ })
340
+ );
341
+ } catch (error) {
342
+ console.error("Error inspecting container:", error);
343
+ ws.send(
344
+ JSON.stringify({
345
+ type: "error",
346
+ error: "Failed to inspect container: " + error.message,
347
+ requestId: payload.requestId,
348
+ })
349
+ );
350
+ }
351
+ }
352
+
353
+ export default { handleContainerAction, formatContainer, docker };
354
+
355
+ export { handleContainerAction, formatContainer, docker };
@@ -0,0 +1,171 @@
1
+ import os from 'os';
2
+ import { formatUptime } from '../helper-functions.js';
3
+ import { docker } from './containers.js';
4
+ import agentStore from '../store/agentStore.js';
5
+ import { loadSession } from '../auth.js';
6
+ import agentSessionStore from '../store/agentSessionStore.js';
7
+
8
+ // Version from package.json
9
+ import packageJson from '../package.json' with { type: 'json' };
10
+ const { version } = packageJson;
11
+
12
+ // Agent informations - startTime will be loaded from store or set when server starts
13
+ let agentStartTime = new Date();
14
+ const agentInfo = {
15
+ version,
16
+ hostname: os.hostname(),
17
+ startTime: agentStartTime,
18
+ cpus: os.cpus().length,
19
+ memory: {
20
+ total: Math.round(os.totalmem() / (1024 * 1024)), // MB
21
+ free: Math.round(os.freemem() / (1024 * 1024)), // MB
22
+ },
23
+ };
24
+
25
+ /**
26
+ * Initialize agent start time - called when server actually starts
27
+ * Always creates a fresh start time when the server starts
28
+ */
29
+ async function initializeAgentStartTime() {
30
+ try {
31
+ // Always create a fresh start time when the server starts
32
+ agentStartTime = new Date();
33
+ agentInfo.startTime = agentStartTime;
34
+ await agentStore.saveAgentStartTime(agentStartTime);
35
+ } catch (err) {
36
+ console.error('Failed to initialize agent start time:', err);
37
+ }
38
+ }
39
+
40
+ async function handleGeneralAction(ws, clientId, action, payload) {
41
+ switch (action) {
42
+ case 'getAgentInfo':
43
+ return await handleGetAgentInfo(ws, payload);
44
+ case 'getDockerInfo':
45
+ return await handleGetDockerInfo(ws, payload);
46
+ case 'execInContainer':
47
+ return await handleExecInContainer(ws, clientId, payload);
48
+ default:
49
+ throw new Error(`Unknown general action: ${action}`);
50
+ }
51
+ }
52
+
53
+ async function handleGetAgentInfo(ws, payload = {}) {
54
+ try {
55
+ const currentTime = Date.now();
56
+ const uptimeMs = currentTime - new Date(agentInfo.startTime).getTime();
57
+ const formattedUptime = formatUptime(uptimeMs);
58
+
59
+ // Get session info
60
+ const sessionInfo = agentSessionStore.getAgentSessionInfo();
61
+ const session = loadSession();
62
+
63
+ const info = {
64
+ ...agentInfo,
65
+ timestamp: Date.now(),
66
+ uptime: formattedUptime,
67
+ agentId: sessionInfo.agentId,
68
+ userEntityRef:
69
+ sessionInfo.userEntityRef || (session && session.userEntityRef),
70
+ sessionExpiresAt:
71
+ sessionInfo.sessionExpiresAt || (session && session.expiresAt),
72
+ status: 'connected', // Agent is connected if responding
73
+ };
74
+
75
+ ws.send(
76
+ JSON.stringify({
77
+ type: 'agentInfo',
78
+ info,
79
+ requestId: payload.requestId,
80
+ })
81
+ );
82
+ } catch (error) {
83
+ console.error('Error getting agent info:', error);
84
+ ws.send(
85
+ JSON.stringify({
86
+ type: 'error',
87
+ error: 'Failed to get agent info: ' + error.message,
88
+ requestId: payload.requestId,
89
+ })
90
+ );
91
+ }
92
+ }
93
+
94
+ async function handleExecInContainer(ws, clientId, payload) {
95
+ try {
96
+ const { containerId, command, requestId } = payload;
97
+
98
+ const container = docker.getContainer(containerId);
99
+ const exec = await container.exec({
100
+ AttachStdin: false,
101
+ AttachStdout: true,
102
+ AttachStderr: true,
103
+ Tty: false,
104
+ Cmd: ['/bin/sh', '-c', command],
105
+ });
106
+
107
+ const stream = await exec.start({ hijack: true, stdin: false });
108
+ let output = '';
109
+
110
+ stream.on('data', (chunk) => {
111
+ output += chunk.toString();
112
+ });
113
+
114
+ stream.on('end', () => {
115
+ ws.send(
116
+ JSON.stringify({
117
+ type: 'execResult',
118
+ containerId,
119
+ output,
120
+ requestId,
121
+ })
122
+ );
123
+ });
124
+
125
+ stream.on('error', (err) => {
126
+ ws.send(
127
+ JSON.stringify({
128
+ type: 'error',
129
+ error: `Error executing command: ${err.message}`,
130
+ requestId,
131
+ })
132
+ );
133
+ });
134
+ } catch (error) {
135
+ console.error('Error executing command in container:', error);
136
+ ws.send(
137
+ JSON.stringify({
138
+ type: 'error',
139
+ error: 'Failed to execute command in container: ' + error.message,
140
+ requestId: payload.requestId,
141
+ })
142
+ );
143
+ }
144
+ }
145
+
146
+ async function handleGetDockerInfo(ws, payload = {}) {
147
+ try {
148
+ const info = await docker.info();
149
+
150
+ ws.send(
151
+ JSON.stringify({
152
+ type: 'dockerInfo',
153
+ info,
154
+ requestId: payload.requestId,
155
+ })
156
+ );
157
+ } catch (error) {
158
+ console.error('Error getting Docker info:', error);
159
+ ws.send(
160
+ JSON.stringify({
161
+ type: 'error',
162
+ error: 'Failed to get Docker info: ' + error.message,
163
+ requestId: payload.requestId,
164
+ })
165
+ );
166
+ }
167
+ }
168
+
169
+ export default { handleGeneralAction, agentInfo, initializeAgentStartTime };
170
+
171
+ export { handleGeneralAction, agentInfo, initializeAgentStartTime };