@oussema_mili/test-pkg-123 1.1.22

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.

Potentially problematic release.


This version of @oussema_mili/test-pkg-123 might be problematic. Click here for more details.

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 +1923 -0
  6. package/containerManager.js +304 -0
  7. package/daemon/agentRunner.js +429 -0
  8. package/daemon/daemonEntry.js +64 -0
  9. package/daemon/daemonManager.js +271 -0
  10. package/daemon/logManager.js +227 -0
  11. package/dist/styles.css +504 -0
  12. package/docker-actions/apps.js +3938 -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 +696 -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 +44 -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,193 @@
1
+ import os from 'os';
2
+
3
+ // Format container uptime in a human-readable format
4
+ const formatUptime = (ms) => {
5
+ const seconds = Math.floor(ms / 1000);
6
+ const minutes = Math.floor(seconds / 60);
7
+ const hours = Math.floor(minutes / 60);
8
+ const days = Math.floor(hours / 24);
9
+
10
+ if (days > 0) return `${days} day${days > 1 ? 's' : ''}`;
11
+ if (hours > 0) return `${hours} hour${hours > 1 ? 's' : ''}`;
12
+ if (minutes > 0) return `${minutes} minute${minutes > 1 ? 's' : ''}`;
13
+ return `${seconds} second${seconds !== 1 ? 's' : ''}`;
14
+ };
15
+
16
+ // Format image size to human-readable format
17
+ const formatSize = (size) => {
18
+ const kb = size / 1000;
19
+ if (kb < 1000) return `${Math.round(kb)} KB`;
20
+
21
+ const mb = size / 1_000_000;
22
+ if (mb < 1000) return `${Math.round(mb)} MB`;
23
+
24
+ const gb = size / 1_000_000_000;
25
+ return `${gb.toFixed(2)} GB`;
26
+ };
27
+
28
+ // Format image creation time to relative time
29
+ const formatCreatedTime = (created) => {
30
+ const now = Date.now() / 1000;
31
+ const diff = now - created;
32
+
33
+ const minutes = Math.floor(diff / 60);
34
+ const hours = Math.floor(minutes / 60);
35
+ const days = Math.floor(hours / 24);
36
+ const months = Math.floor(days / 30);
37
+ const years = Math.floor(months / 12);
38
+
39
+ if (years > 0) return `${years} year${years > 1 ? 's' : ''} ago`;
40
+ if (months > 0) return `${months} month${months > 1 ? 's' : ''} ago`;
41
+ if (days > 0) return `${days} day${days > 1 ? 's' : ''} ago`;
42
+ if (hours > 0) return `${hours} hour${hours > 1 ? 's' : ''} ago`;
43
+ if (minutes > 0) return `${minutes} minute${minutes > 1 ? 's' : ''} ago`;
44
+ return 'Just now';
45
+ };
46
+
47
+ // Parse log line to extract timestamp, level, and message
48
+ function parseLogLine(line, containerId) {
49
+ let rawLine = line.toString();
50
+
51
+ // Docker logs can contain binary headers (8 bytes) that need to be stripped
52
+ // The first byte indicates the stream type (1=stdout, 2=stderr)
53
+ // Bytes 1-3 are padding, bytes 4-7 contain the length
54
+ if (rawLine.length > 8) {
55
+ const firstByte = rawLine.charCodeAt(0);
56
+ // Check if this looks like a Docker log header
57
+ if (firstByte === 1 || firstByte === 2) {
58
+ // Skip the 8-byte header
59
+ rawLine = rawLine.substring(8);
60
+ }
61
+ }
62
+
63
+ let message = rawLine;
64
+ let timestamp = new Date().toISOString();
65
+ let level = 'INFO';
66
+ const service = 'container';
67
+ let isEmptyLine = false;
68
+
69
+ // Check if this is an empty line (only whitespace or completely empty)
70
+ if (rawLine.trim() === '') {
71
+ isEmptyLine = true;
72
+ message = ''; // Keep as empty for empty lines
73
+ } else {
74
+ // Extract Docker timestamp if present (format: 2025-09-12T14:44:10.598127086Z)
75
+ const timestampMatch = message.match(
76
+ /^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+Z)\s*(.*)$/
77
+ );
78
+ if (timestampMatch) {
79
+ timestamp = timestampMatch[1];
80
+ message = timestampMatch[2] || ''; // This is the actual log content after the Docker timestamp
81
+
82
+ // If after extracting timestamp, message is empty, mark as empty line
83
+ if (message.trim() === '') {
84
+ isEmptyLine = true;
85
+ message = '';
86
+ }
87
+ }
88
+
89
+ // Clean up any remaining malformed timestamp artifacts
90
+ message = message.replace(
91
+ /^-?\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+Z\s*/,
92
+ ''
93
+ );
94
+
95
+ // Try to detect log level from content (only for non-empty lines)
96
+ if (!isEmptyLine) {
97
+ const lowerMessage = message.toLowerCase();
98
+ if (
99
+ lowerMessage.includes('"s":"e"') ||
100
+ lowerMessage.includes('error') ||
101
+ lowerMessage.includes('err') ||
102
+ lowerMessage.includes('fatal')
103
+ ) {
104
+ level = 'ERROR';
105
+ } else if (
106
+ lowerMessage.includes('"s":"w"') ||
107
+ lowerMessage.includes('warn')
108
+ ) {
109
+ level = 'WARN';
110
+ } else if (
111
+ lowerMessage.includes('"s":"d"') ||
112
+ lowerMessage.includes('debug')
113
+ ) {
114
+ level = 'DEBUG';
115
+ } else if (
116
+ lowerMessage.includes('"s":"i"') ||
117
+ lowerMessage.includes('info') ||
118
+ lowerMessage.includes('log:')
119
+ ) {
120
+ level = 'INFO';
121
+ }
122
+ }
123
+ }
124
+
125
+ return {
126
+ id: `log-${containerId}-${Date.now()}-${Math.random()
127
+ .toString(36)
128
+ .substring(2, 9)}`,
129
+ timestamp,
130
+ level,
131
+ service,
132
+ message,
133
+ isEmptyLine, // Add flag to identify empty lines
134
+ };
135
+ }
136
+
137
+ // Parse size strings like "10 GB" to bytes
138
+ function parseSize(sizeStr) {
139
+ if (!sizeStr || typeof sizeStr !== 'string') return 0;
140
+
141
+ const match = sizeStr.match(/^(\d+(\.\d+)?)\s*([KMGT]?B)$/);
142
+ if (!match) return 0;
143
+
144
+ const size = Number.parseFloat(match[1]);
145
+ const unit = match[3];
146
+
147
+ switch (unit) {
148
+ case 'B':
149
+ return size;
150
+ case 'KB':
151
+ return size * 1024;
152
+ case 'MB':
153
+ return size * 1024 * 1024;
154
+ case 'GB':
155
+ return size * 1024 * 1024 * 1024;
156
+ case 'TB':
157
+ return size * 1024 * 1024 * 1024 * 1024;
158
+ default:
159
+ return size;
160
+ }
161
+ }
162
+
163
+ // Simple CPU usage estimation without native modules
164
+ function estimateCpuUsage() {
165
+ try {
166
+ const cpus = os.cpus();
167
+ let idle = 0;
168
+ let total = 0;
169
+
170
+ for (const cpu of cpus) {
171
+ for (const type in cpu.times) {
172
+ total += cpu.times[type];
173
+ }
174
+ idle += cpu.times.idle;
175
+ }
176
+
177
+ // Calculate CPU usage as percentage of non-idle time
178
+ const usage = 100 - (idle / total) * 100;
179
+ return Math.round(usage * 100) / 100;
180
+ } catch (error) {
181
+ console.error('Error estimating CPU usage:', error.message);
182
+ return 0;
183
+ }
184
+ }
185
+
186
+ export {
187
+ formatUptime,
188
+ formatSize,
189
+ formatCreatedTime,
190
+ parseLogLine,
191
+ parseSize,
192
+ estimateCpuUsage,
193
+ };
package/index.html ADDED
@@ -0,0 +1,83 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Authorization Successful</title>
7
+ <link
8
+ rel="icon"
9
+ href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><circle cx='50' cy='50' r='45' fill='%2322c55e'/><path d='M30 50l15 15 25-30' stroke='white' stroke-width='8' fill='none' stroke-linecap='round' stroke-linejoin='round'/></svg>"
10
+ />
11
+ <link href="/dist/styles.css" rel="stylesheet" />
12
+ <script>
13
+ // Store WebSocket token in localStorage for App Builder to use
14
+ // These values are injected by the agent server
15
+ const wsToken = new URLSearchParams(window.location.search).get(
16
+ "wsToken",
17
+ );
18
+ const wsPort = new URLSearchParams(window.location.search).get("wsPort");
19
+ const containerPort = new URLSearchParams(window.location.search).get(
20
+ "containerPort",
21
+ );
22
+
23
+ if (wsToken) {
24
+ localStorage.setItem("fenwave-ws-token", wsToken);
25
+ localStorage.setItem("fenwave-ws-port", wsPort || "3001");
26
+ localStorage.setItem("fenwave-container-port", containerPort || "3006");
27
+ }
28
+ </script>
29
+ <style>
30
+ @keyframes fadeIn {
31
+ from {
32
+ opacity: 0;
33
+ }
34
+ to {
35
+ opacity: 1;
36
+ }
37
+ }
38
+ .fade-in {
39
+ animation: fadeIn 0.5s ease-in-out;
40
+ }
41
+ </style>
42
+ </head>
43
+ <body class="bg-gray-50 min-h-screen">
44
+ <div class="flex justify-center items-center min-h-[80vh]">
45
+ <div
46
+ class="fade-in max-w-sm mx-auto mt-8 p-8 text-center bg-white rounded-lg shadow-lg"
47
+ >
48
+ <!-- Success Icon Circle -->
49
+ <div
50
+ class="w-16 h-16 mx-auto mb-6 flex items-center justify-center rounded-full bg-green-500 text-white"
51
+ >
52
+ <svg
53
+ class="w-8 h-8"
54
+ fill="currentColor"
55
+ viewBox="0 0 20 20"
56
+ xmlns="http://www.w3.org/2000/svg"
57
+ >
58
+ <path
59
+ fill-rule="evenodd"
60
+ d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
61
+ clip-rule="evenodd"
62
+ ></path>
63
+ </svg>
64
+ </div>
65
+
66
+ <!-- Main Heading -->
67
+ <h2 class="text-2xl font-medium text-gray-900 mb-4">
68
+ Authorization Successful
69
+ </h2>
70
+
71
+ <!-- Description Text -->
72
+ <p class="text-base text-gray-600 mb-8">
73
+ Your agent has been successfully authorized.
74
+ </p>
75
+
76
+ <!-- Footer Text -->
77
+ <p class="text-sm text-gray-500">
78
+ You may now close this window and return to your CLI.
79
+ </p>
80
+ </div>
81
+ </div>
82
+ </body>
83
+ </html>
package/index.js ADDED
@@ -0,0 +1,341 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from "fs";
4
+ import chalk from "chalk";
5
+ import { program } from "commander";
6
+ import { fileURLToPath } from "url";
7
+ import { dirname } from "path";
8
+ import dotenv from "dotenv";
9
+
10
+ // ES module helpers
11
+ const __filename = fileURLToPath(import.meta.url);
12
+ const __dirname = dirname(__filename);
13
+
14
+ // Ensure environment files exist
15
+ import { ensureEnvironmentFiles } from "./utils/envSetup.js";
16
+ const agentEnvPath = ensureEnvironmentFiles(__dirname);
17
+
18
+ // Load environment variables from .env.agent
19
+ dotenv.config({ path: agentEnvPath });
20
+
21
+ // Load environment variables
22
+ dotenv.config();
23
+
24
+ // Import ES modules
25
+ import { setupCLICommands } from "./cli-commands.js";
26
+
27
+ // Version from package.json
28
+ const packageJson = JSON.parse(
29
+ fs.readFileSync(new URL("./package.json", import.meta.url), "utf8")
30
+ );
31
+ const { version } = packageJson;
32
+
33
+ // Initialize the CLI
34
+ program
35
+ .name("fenwave")
36
+ .description("Fenwave - Developer Platform CLI")
37
+ .version(version)
38
+ .option('--debug', 'Enable debug mode for verbose logging')
39
+ .hook('preAction', (thisCommand) => {
40
+ const opts = thisCommand.opts();
41
+ if (opts.debug) {
42
+ process.env.DEBUG = 'true';
43
+ console.log(chalk.yellow('Debug mode enabled'));
44
+ }
45
+ });
46
+
47
+ // Setup CLI commands (startServer function is no longer needed - using agentRunner instead)
48
+ setupCLICommands(program, null);
49
+
50
+ // Custom unknown command handler
51
+ program.on("command:*", ([cmd]) => {
52
+ console.error(`error: unknown command '${cmd}'`);
53
+
54
+ const available = program.commands.map((c) => c.name());
55
+
56
+ // First, try prefix matches
57
+ let matches = available.filter((c) => c.startsWith(cmd));
58
+
59
+ // If no prefix matches, try bidirectional substring matches
60
+ if (matches.length === 0) {
61
+ matches = available.filter((c) => cmd.includes(c) || c.includes(cmd));
62
+ }
63
+
64
+ if (matches.length > 0) {
65
+ if (matches.length === 1) {
66
+ console.error(`(Did you mean '${matches[0]}'?)`);
67
+ } else {
68
+ console.error(`(Did you mean one of ${matches.join(", ")}?)`);
69
+ }
70
+ }
71
+
72
+ process.exit(1);
73
+ });
74
+
75
+ // Pre-process arguments to handle incomplete options before Commander.js
76
+ function preprocessArguments() {
77
+ const args = process.argv.slice(2);
78
+
79
+ if (args.length >= 2) {
80
+ const commandName = args[0];
81
+ const lastArg = args[args.length - 1];
82
+
83
+ // Check if user typed incomplete option (just - or --)
84
+ if (lastArg === "-" || lastArg === "--") {
85
+ // Find the command
86
+ const command = program.commands.find(
87
+ (cmd) =>
88
+ cmd.name() === commandName || cmd.aliases().includes(commandName)
89
+ );
90
+
91
+ if (command) {
92
+ console.error(`error: unknown option '${lastArg}'`);
93
+
94
+ // Get all options for this command
95
+ const options = command.options || [];
96
+ const availableOptions = [];
97
+
98
+ // Add command-specific options
99
+ options.forEach((option) => {
100
+ if (option.short) availableOptions.push(option.short);
101
+ if (option.long) availableOptions.push(option.long);
102
+ });
103
+
104
+ // Always add help option
105
+ if (!availableOptions.includes("-h")) availableOptions.push("-h");
106
+ if (!availableOptions.includes("--help"))
107
+ availableOptions.push("--help");
108
+
109
+ let suggestions = [];
110
+
111
+ if (lastArg === "--") {
112
+ // User typed just '--', suggest all long options
113
+ suggestions = availableOptions.filter((opt) => opt.startsWith("--"));
114
+ } else if (lastArg === "-") {
115
+ // User typed just '-', suggest all short options with their long equivalents
116
+ const shortOpts = availableOptions.filter(
117
+ (opt) => opt.startsWith("-") && !opt.startsWith("--")
118
+ );
119
+ const longOpts = availableOptions.filter((opt) =>
120
+ opt.startsWith("--")
121
+ );
122
+
123
+ // Pair short and long options
124
+ suggestions = shortOpts.map((shortOpt) => {
125
+ const longEquivalent = longOpts.find(
126
+ (longOpt) =>
127
+ longOpt.substring(2) === shortOpt.substring(1) ||
128
+ (shortOpt === "-h" && longOpt === "--help") ||
129
+ (shortOpt === "-a" && longOpt === "--all") ||
130
+ (shortOpt === "-f" &&
131
+ (longOpt === "--force" || longOpt === "--follow")) ||
132
+ (shortOpt === "-d" && longOpt === "--driver") ||
133
+ (shortOpt === "-p" && longOpt === "--port") ||
134
+ (shortOpt === "-t" && longOpt === "--tail")
135
+ );
136
+ return longEquivalent ? `${shortOpt}, ${longEquivalent}` : shortOpt;
137
+ });
138
+ }
139
+
140
+ if (suggestions.length > 0) {
141
+ const formattedSuggestions = suggestions.map((suggestion) => {
142
+ // Add argument placeholder for options that require arguments
143
+ let displaySuggestion = suggestion;
144
+
145
+ // Find the matching option object to check if it requires an argument
146
+ const option = options.find(
147
+ (opt) =>
148
+ opt.long === suggestion ||
149
+ opt.short === suggestion ||
150
+ (suggestion.includes(opt.long) && opt.long) ||
151
+ (suggestion.includes(opt.short) && opt.short)
152
+ );
153
+
154
+ if (option && option.required) {
155
+ // Use a more descriptive argument name based on the option's own description
156
+ let argName = "<value>";
157
+ if (option.argChoices) {
158
+ argName = `<${option.argChoices.join("|")}>`;
159
+ } else if (option.long) {
160
+ // Map common option names to better argument descriptions
161
+ const optName = option.long.replace("--", "");
162
+ const argNameMap = {
163
+ tail: "lines",
164
+ port: "port",
165
+ driver: "driver",
166
+ "backend-url": "url",
167
+ "frontend-url": "url",
168
+ token: "token",
169
+ "aws-region": "region",
170
+ "aws-account-id": "id",
171
+ };
172
+ argName = `<${argNameMap[optName] || optName}>`;
173
+ }
174
+ displaySuggestion = `${suggestion} ${argName}`;
175
+ }
176
+
177
+ return `'${displaySuggestion}'`;
178
+ });
179
+
180
+ console.error(`(Did you mean ${formattedSuggestions.join(", ")}?)`);
181
+ }
182
+
183
+ process.exit(1);
184
+ }
185
+ }
186
+ }
187
+ }
188
+
189
+ // Run preprocessing before parsing
190
+ preprocessArguments();
191
+
192
+ // Handle unknown options
193
+ program.exitOverride((err) => {
194
+ if (err.code === "commander.unknownOption") {
195
+ const args = process.argv.slice(2);
196
+ const commandName = args[0];
197
+ const invalidOption = err.message.match(/unknown option '([^']+)'/)?.[1];
198
+
199
+ if (invalidOption) {
200
+ // Find the command
201
+ const command = program.commands.find(
202
+ (cmd) =>
203
+ cmd.name() === commandName || cmd.aliases().includes(commandName)
204
+ );
205
+
206
+ if (command) {
207
+ console.error(`error: unknown option '${invalidOption}'`);
208
+
209
+ // Get all options for this command
210
+ const options = command.options || [];
211
+ const availableOptions = [];
212
+
213
+ // Add command-specific options
214
+ options.forEach((option) => {
215
+ if (option.short) availableOptions.push(option.short);
216
+ if (option.long) availableOptions.push(option.long);
217
+ });
218
+
219
+ // Always add help option
220
+ if (!availableOptions.includes("-h")) availableOptions.push("-h");
221
+ if (!availableOptions.includes("--help"))
222
+ availableOptions.push("--help");
223
+
224
+ // Find suggestions for partial/incorrect options
225
+ const suggestions = availableOptions.filter(
226
+ (opt) =>
227
+ opt.startsWith(invalidOption) ||
228
+ opt.includes(invalidOption.replace(/^-+/, "")) ||
229
+ invalidOption.includes(opt.replace(/^-+/, ""))
230
+ );
231
+
232
+ if (suggestions.length > 0) {
233
+ // Group short and long options together
234
+ const pairedSuggestions = [];
235
+ const processed = new Set();
236
+
237
+ suggestions.forEach((suggestion) => {
238
+ if (processed.has(suggestion)) return;
239
+
240
+ const option = options.find(
241
+ (opt) => opt.long === suggestion || opt.short === suggestion
242
+ );
243
+
244
+ if (option) {
245
+ let displaySuggestion = "";
246
+
247
+ // Check if both short and long forms are in suggestions
248
+ const hasShort =
249
+ option.short && suggestions.includes(option.short);
250
+ const hasLong = option.long && suggestions.includes(option.long);
251
+
252
+ if (hasShort && hasLong) {
253
+ displaySuggestion = `${option.short}, ${option.long}`;
254
+ processed.add(option.short);
255
+ processed.add(option.long);
256
+ } else if (hasShort) {
257
+ // If only short form matched, still pair it with long form if available
258
+ displaySuggestion = option.long
259
+ ? `${option.short}, ${option.long}`
260
+ : option.short;
261
+ processed.add(option.short);
262
+ if (option.long) processed.add(option.long);
263
+ } else if (hasLong) {
264
+ // If only long form matched, still pair it with short form if available
265
+ displaySuggestion = option.short
266
+ ? `${option.short}, ${option.long}`
267
+ : option.long;
268
+ if (option.short) processed.add(option.short);
269
+ processed.add(option.long);
270
+ }
271
+
272
+ // Add argument placeholder for options that require arguments
273
+ if (option.required) {
274
+ let argName = "<value>";
275
+ if (option.argChoices) {
276
+ argName = `<${option.argChoices.join("|")}>`;
277
+ } else if (option.long) {
278
+ const optName = option.long.replace("--", "");
279
+ const argNameMap = {
280
+ tail: "lines",
281
+ port: "port",
282
+ driver: "driver",
283
+ "backend-url": "url",
284
+ "frontend-url": "url",
285
+ token: "token",
286
+ "aws-region": "region",
287
+ "aws-account-id": "id",
288
+ };
289
+ argName = `<${argNameMap[optName] || optName}>`;
290
+ }
291
+ displaySuggestion = `${displaySuggestion} ${argName}`;
292
+ }
293
+
294
+ pairedSuggestions.push(`'${displaySuggestion}'`);
295
+ } else {
296
+ // Fallback for options without Option object (like help)
297
+ processed.add(suggestion);
298
+
299
+ // Pair -h with --help
300
+ if (suggestion === "-h" && suggestions.includes("--help")) {
301
+ pairedSuggestions.push(`'${suggestion}, --help'`);
302
+ processed.add("--help");
303
+ } else if (
304
+ suggestion === "--help" &&
305
+ suggestions.includes("-h")
306
+ ) {
307
+ // Skip, already handled
308
+ } else {
309
+ pairedSuggestions.push(`'${suggestion}'`);
310
+ }
311
+ }
312
+ });
313
+
314
+ console.error(`(Did you mean ${pairedSuggestions.join(", ")}?)`);
315
+ }
316
+ }
317
+ }
318
+
319
+ process.exit(1);
320
+ }
321
+
322
+ // For other errors (like help), exit normally with the error's exit code
323
+ process.exit(err.exitCode || 1);
324
+ });
325
+
326
+ // Parse command line arguments
327
+ program.parse(process.argv);
328
+
329
+ // If no arguments, show help
330
+ if (process.argv.length === 2) {
331
+ program.help();
332
+ }
333
+
334
+ // Process error handling
335
+ process.on("uncaughtException", (error) => {
336
+ console.error("Uncaught exception:", error);
337
+ });
338
+
339
+ process.on("unhandledRejection", (reason, promise) => {
340
+ console.error("Unhandled rejection at:", promise, "reason:", reason);
341
+ });
package/package.json ADDED
@@ -0,0 +1,82 @@
1
+ {
2
+ "name": "@oussema_mili/test-pkg-123",
3
+ "version": "1.1.22",
4
+ "description": "Fenwave Docker Agent and CLI",
5
+ "keywords": [
6
+ "fenwave",
7
+ "fenleap",
8
+ "fenwave-idp"
9
+ ],
10
+ "homepage": "https://github.com/fenleap/fenwave-agent#readme",
11
+ "bugs": {
12
+ "url": "https://github.com/fenleap/fenwave-agent/issues"
13
+ },
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/fenleap/fenwave-agent.git"
17
+ },
18
+ "license": "SEE LICENSE IN LICENSE",
19
+ "author": "Fenleap",
20
+ "type": "module",
21
+ "main": "index.js",
22
+ "bin": {
23
+ "fenwave": "index.js"
24
+ },
25
+ "files": [
26
+ "index.js",
27
+ "index.html",
28
+ "auth-callback.html",
29
+ "dist/",
30
+ "styles.css",
31
+ "postcss.config.mjs",
32
+ "cli-commands.js",
33
+ "auth.js",
34
+ "containerManager.js",
35
+ "helper-functions.js",
36
+ "websocket-server.js",
37
+ "daemon/",
38
+ "docker-actions/",
39
+ "scripts/",
40
+ "setup/",
41
+ "store/",
42
+ "utils/",
43
+ "completion/"
44
+ ],
45
+ "scripts": {
46
+ "start": "node index.js server",
47
+ "agent": "node index.js",
48
+ "build:css": "postcss styles.css -o dist/styles.css",
49
+ "watch:css": "postcss styles.css -o dist/styles.css --watch",
50
+ "prepare": "npm run build:css",
51
+ "release": "bash scripts/release.sh",
52
+ "release:patch": "bash scripts/release.sh patch",
53
+ "release:minor": "bash scripts/release.sh minor",
54
+ "release:major": "bash scripts/release.sh major"
55
+ },
56
+ "dependencies": {
57
+ "@aws-sdk/client-ecr": "^3.879.0",
58
+ "@aws-sdk/client-sts": "^3.879.0",
59
+ "@tailwindcss/postcss": "^4.1.18",
60
+ "axios": "^1.11.0",
61
+ "chalk": "^4.1.2",
62
+ "cli-table3": "^0.6.3",
63
+ "commander": "^11.0.0",
64
+ "dockerode": "^4.0.0",
65
+ "dotenv": "^16.0.3",
66
+ "google-auth-library": "^9.0.0",
67
+ "inquirer": "^8.2.5",
68
+ "js-yaml": "^4.1.0",
69
+ "open": "^11.0.0",
70
+ "ora": "^5.4.1",
71
+ "postcss": "^8.5.6",
72
+ "tailwindcss": "^4.1.18",
73
+ "uuid": "^9.0.1",
74
+ "ws": "^8.15.1"
75
+ },
76
+ "engines": {
77
+ "node": ">=14.0.0"
78
+ },
79
+ "devDependencies": {
80
+ "postcss-cli": "^11.0.1"
81
+ }
82
+ }