lobstercage-cli 0.1.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 (58) hide show
  1. package/README.md +64 -0
  2. package/dist/commands/auth.d.ts +39 -0
  3. package/dist/commands/auth.d.ts.map +1 -0
  4. package/dist/commands/auth.js +393 -0
  5. package/dist/commands/auth.js.map +1 -0
  6. package/dist/commands/billing.d.ts +11 -0
  7. package/dist/commands/billing.d.ts.map +1 -0
  8. package/dist/commands/billing.js +181 -0
  9. package/dist/commands/billing.js.map +1 -0
  10. package/dist/commands/cages.d.ts +87 -0
  11. package/dist/commands/cages.d.ts.map +1 -0
  12. package/dist/commands/cages.js +603 -0
  13. package/dist/commands/cages.js.map +1 -0
  14. package/dist/commands/env.d.ts +42 -0
  15. package/dist/commands/env.d.ts.map +1 -0
  16. package/dist/commands/env.js +287 -0
  17. package/dist/commands/env.js.map +1 -0
  18. package/dist/commands/exec.d.ts +12 -0
  19. package/dist/commands/exec.d.ts.map +1 -0
  20. package/dist/commands/exec.js +127 -0
  21. package/dist/commands/exec.js.map +1 -0
  22. package/dist/commands/tunnel.d.ts +29 -0
  23. package/dist/commands/tunnel.d.ts.map +1 -0
  24. package/dist/commands/tunnel.js +232 -0
  25. package/dist/commands/tunnel.js.map +1 -0
  26. package/dist/index.d.ts +31 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +138 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/lib/api.d.ts +96 -0
  31. package/dist/lib/api.d.ts.map +1 -0
  32. package/dist/lib/api.js +348 -0
  33. package/dist/lib/api.js.map +1 -0
  34. package/dist/lib/config.d.ts +63 -0
  35. package/dist/lib/config.d.ts.map +1 -0
  36. package/dist/lib/config.js +193 -0
  37. package/dist/lib/config.js.map +1 -0
  38. package/dist/lib/docker.d.ts +52 -0
  39. package/dist/lib/docker.d.ts.map +1 -0
  40. package/dist/lib/docker.js +210 -0
  41. package/dist/lib/docker.js.map +1 -0
  42. package/dist/lib/error-handler.d.ts +30 -0
  43. package/dist/lib/error-handler.d.ts.map +1 -0
  44. package/dist/lib/error-handler.js +113 -0
  45. package/dist/lib/error-handler.js.map +1 -0
  46. package/dist/lib/output.d.ts +71 -0
  47. package/dist/lib/output.d.ts.map +1 -0
  48. package/dist/lib/output.js +237 -0
  49. package/dist/lib/output.js.map +1 -0
  50. package/dist/lib/utils.d.ts +17 -0
  51. package/dist/lib/utils.d.ts.map +1 -0
  52. package/dist/lib/utils.js +71 -0
  53. package/dist/lib/utils.js.map +1 -0
  54. package/dist/types/index.d.ts +158 -0
  55. package/dist/types/index.d.ts.map +1 -0
  56. package/dist/types/index.js +8 -0
  57. package/dist/types/index.js.map +1 -0
  58. package/package.json +63 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docker.d.ts","sourceRoot":"","sources":["../../src/lib/docker.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,IAAI,EAAc,QAAQ,EAAE,MAAM,UAAU,CAAC;AAS3D,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AA4CD;;GAEG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAyDzF;AAED;;GAEG;AACH,wBAAsB,SAAS,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,CAMjD;AAED;;GAEG;AACH,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAazD;AAED;;GAEG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAI3D;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAQzE;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAG7D;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,UAAe,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAyB7F;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAErD"}
@@ -0,0 +1,210 @@
1
+ "use strict";
2
+ /**
3
+ * Local Docker Engine for cage management
4
+ *
5
+ * Implements cage operations using Docker instead of the remote API.
6
+ * Used when --local flag is set or no API is configured.
7
+ */
8
+ var __importDefault = (this && this.__importDefault) || function (mod) {
9
+ return (mod && mod.__esModule) ? mod : { "default": mod };
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.deployCage = deployCage;
13
+ exports.listCages = listCages;
14
+ exports.getCage = getCage;
15
+ exports.startCage = startCage;
16
+ exports.stopCage = stopCage;
17
+ exports.destroyCage = destroyCage;
18
+ exports.getCageLogs = getCageLogs;
19
+ exports.getContainerName = getContainerName;
20
+ const dockerode_1 = __importDefault(require("dockerode"));
21
+ const crypto_1 = require("crypto");
22
+ const docker = new dockerode_1.default();
23
+ const LABEL_PREFIX = 'lobstercage';
24
+ const CONTAINER_PREFIX = 'lobster-';
25
+ const DEFAULT_IMAGE = 'lobstercage/sandbox:latest';
26
+ const WORKSPACE_MOUNT = '/home/agent/workspace';
27
+ function containerName(name) {
28
+ return `${CONTAINER_PREFIX}${name}`;
29
+ }
30
+ function generateCageId() {
31
+ return `cage_local_${(0, crypto_1.randomBytes)(8).toString('hex')}`;
32
+ }
33
+ function containerToCage(container) {
34
+ const labels = container.Labels;
35
+ const name = labels[`${LABEL_PREFIX}.cage-name`] || container.Names[0]?.replace(/^\/lobster-/, '') || 'unknown';
36
+ const cageId = labels[`${LABEL_PREFIX}.cage-id`] || 'unknown';
37
+ let status;
38
+ const state = container.State;
39
+ if (state === 'running') {
40
+ status = 'running';
41
+ }
42
+ else if (state === 'exited' || state === 'dead') {
43
+ status = 'stopped';
44
+ }
45
+ else if (state === 'created' || state === 'restarting') {
46
+ status = 'pending';
47
+ }
48
+ else {
49
+ status = 'stopped';
50
+ }
51
+ return {
52
+ id: cageId,
53
+ name,
54
+ status,
55
+ image: container.Image,
56
+ resources: {
57
+ cpu: 1024,
58
+ memory: 2048,
59
+ storage: 20,
60
+ },
61
+ network: {
62
+ egressPolicy: 'allow-all',
63
+ },
64
+ createdAt: new Date(container.Created * 1000).toISOString(),
65
+ };
66
+ }
67
+ /**
68
+ * Deploy a new cage as a local Docker container
69
+ */
70
+ async function deployCage(name, options = {}) {
71
+ const cageId = generateCageId();
72
+ const cName = containerName(name);
73
+ // Determine image
74
+ let image = DEFAULT_IMAGE;
75
+ if (options.template) {
76
+ image = `lobstercage/sandbox:${options.template}`;
77
+ }
78
+ else if (options.image) {
79
+ image = options.image;
80
+ }
81
+ const cpuLimit = (options.cpu || 1) * 1e9; // nanoCPUs
82
+ const memoryLimit = (options.memory || 2048) * 1024 * 1024; // bytes
83
+ const volumeName = `lobster-${name}-workspace`;
84
+ const env = [
85
+ `CAGE_ID=${cageId}`,
86
+ `CAGE_NAME=${name}`,
87
+ `USER_ID=local`,
88
+ ...Object.entries(options.env || {}).map(([k, v]) => `${k}=${v}`),
89
+ ];
90
+ const container = await docker.createContainer({
91
+ name: cName,
92
+ Image: image,
93
+ Env: env,
94
+ Labels: {
95
+ [LABEL_PREFIX]: 'true',
96
+ [`${LABEL_PREFIX}.cage-name`]: name,
97
+ [`${LABEL_PREFIX}.cage-id`]: cageId,
98
+ },
99
+ HostConfig: {
100
+ NanoCpus: cpuLimit,
101
+ Memory: memoryLimit,
102
+ Binds: [`${volumeName}:${WORKSPACE_MOUNT}`],
103
+ },
104
+ Tty: true,
105
+ OpenStdin: true,
106
+ });
107
+ await container.start();
108
+ return {
109
+ id: cageId,
110
+ name,
111
+ status: 'running',
112
+ image,
113
+ resources: {
114
+ cpu: ((options.cpu || 1) * 1024),
115
+ memory: (options.memory || 2048),
116
+ storage: 20,
117
+ },
118
+ network: { egressPolicy: 'allow-all' },
119
+ createdAt: new Date().toISOString(),
120
+ startedAt: new Date().toISOString(),
121
+ };
122
+ }
123
+ /**
124
+ * List all local cages
125
+ */
126
+ async function listCages() {
127
+ const containers = await docker.listContainers({
128
+ all: true,
129
+ filters: { label: [`${LABEL_PREFIX}=true`] },
130
+ });
131
+ return containers.map(containerToCage);
132
+ }
133
+ /**
134
+ * Get a single cage by name
135
+ */
136
+ async function getCage(name) {
137
+ const containers = await docker.listContainers({
138
+ all: true,
139
+ filters: {
140
+ label: [`${LABEL_PREFIX}=true`, `${LABEL_PREFIX}.cage-name=${name}`],
141
+ },
142
+ });
143
+ if (containers.length === 0) {
144
+ throw new Error(`Cage not found: ${name}`);
145
+ }
146
+ return containerToCage(containers[0]);
147
+ }
148
+ /**
149
+ * Start a stopped cage
150
+ */
151
+ async function startCage(name) {
152
+ const container = docker.getContainer(containerName(name));
153
+ await container.start();
154
+ return getCage(name);
155
+ }
156
+ /**
157
+ * Stop a running cage
158
+ */
159
+ async function stopCage(name, force = false) {
160
+ const container = docker.getContainer(containerName(name));
161
+ if (force) {
162
+ await container.kill();
163
+ }
164
+ else {
165
+ await container.stop();
166
+ }
167
+ return getCage(name);
168
+ }
169
+ /**
170
+ * Destroy a cage (remove container and optionally volume)
171
+ */
172
+ async function destroyCage(name) {
173
+ const container = docker.getContainer(containerName(name));
174
+ await container.remove({ force: true });
175
+ }
176
+ /**
177
+ * Get cage logs
178
+ */
179
+ async function getCageLogs(name, options = {}) {
180
+ const container = docker.getContainer(containerName(name));
181
+ const logStream = await container.logs({
182
+ stdout: true,
183
+ stderr: true,
184
+ tail: options.tail ?? 100,
185
+ since: options.since ? Math.floor(new Date(options.since).getTime() / 1000) : undefined,
186
+ timestamps: true,
187
+ });
188
+ const logStr = typeof logStream === 'string' ? logStream : logStream.toString('utf-8');
189
+ if (!logStr.trim())
190
+ return [];
191
+ return logStr.trim().split('\n').map(line => {
192
+ // Docker log lines may have 8-byte header prefix in multiplexed streams
193
+ const cleaned = line.replace(/^[\x00-\x08].{7}/, '');
194
+ const spaceIdx = cleaned.indexOf(' ');
195
+ const timestamp = spaceIdx > 0 ? cleaned.slice(0, spaceIdx) : new Date().toISOString();
196
+ const message = spaceIdx > 0 ? cleaned.slice(spaceIdx + 1) : cleaned;
197
+ return {
198
+ timestamp,
199
+ stream: 'stdout',
200
+ message,
201
+ };
202
+ });
203
+ }
204
+ /**
205
+ * Get the container name for exec (used by exec command with child_process)
206
+ */
207
+ function getContainerName(name) {
208
+ return containerName(name);
209
+ }
210
+ //# sourceMappingURL=docker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docker.js","sourceRoot":"","sources":["../../src/lib/docker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Centralized Error Handler
3
+ *
4
+ * Replaces repeated try/catch boilerplate across CLI commands with a single
5
+ * `handleError()` function that handles spinner cleanup, contextual suggestions,
6
+ * JSON output, debug stack traces, and process.exit.
7
+ */
8
+ import type { Ora } from 'ora';
9
+ export interface HandleErrorOptions {
10
+ spinner?: Ora;
11
+ exitCode?: number;
12
+ json?: boolean;
13
+ context?: string;
14
+ }
15
+ /**
16
+ * Check if debug mode is enabled via --debug flag or DEBUG env var.
17
+ */
18
+ export declare function isDebug(): boolean;
19
+ /**
20
+ * Centralized error handler. Call from catch blocks to replace boilerplate.
21
+ *
22
+ * - Stops the spinner if provided
23
+ * - For ApiClientError: prints message + contextual suggestion
24
+ * - For generic Error: prints context-aware message
25
+ * - In --json mode: outputs structured JSON error
26
+ * - In --debug mode: prints stack trace
27
+ * - Calls process.exit(exitCode)
28
+ */
29
+ export declare function handleError(err: unknown, options?: HandleErrorOptions): never;
30
+ //# sourceMappingURL=error-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-handler.d.ts","sourceRoot":"","sources":["../../src/lib/error-handler.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAkB/B,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,wBAAgB,OAAO,IAAI,OAAO,CAEjC;AAED;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,GAAE,kBAAuB,GAAG,KAAK,CAmCjF"}
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ /**
3
+ * Centralized Error Handler
4
+ *
5
+ * Replaces repeated try/catch boilerplate across CLI commands with a single
6
+ * `handleError()` function that handles spinner cleanup, contextual suggestions,
7
+ * JSON output, debug stack traces, and process.exit.
8
+ */
9
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ var desc = Object.getOwnPropertyDescriptor(m, k);
12
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
13
+ desc = { enumerable: true, get: function() { return m[k]; } };
14
+ }
15
+ Object.defineProperty(o, k2, desc);
16
+ }) : (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ o[k2] = m[k];
19
+ }));
20
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
21
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
22
+ }) : function(o, v) {
23
+ o["default"] = v;
24
+ });
25
+ var __importStar = (this && this.__importStar) || (function () {
26
+ var ownKeys = function(o) {
27
+ ownKeys = Object.getOwnPropertyNames || function (o) {
28
+ var ar = [];
29
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
30
+ return ar;
31
+ };
32
+ return ownKeys(o);
33
+ };
34
+ return function (mod) {
35
+ if (mod && mod.__esModule) return mod;
36
+ var result = {};
37
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
38
+ __setModuleDefault(result, mod);
39
+ return result;
40
+ };
41
+ })();
42
+ Object.defineProperty(exports, "__esModule", { value: true });
43
+ exports.isDebug = isDebug;
44
+ exports.handleError = handleError;
45
+ const api_1 = require("./api");
46
+ const output = __importStar(require("./output"));
47
+ /**
48
+ * Error code → actionable suggestion mapping
49
+ */
50
+ const SUGGESTIONS = {
51
+ CAGE_NOT_FOUND: 'Check cage name with `lobster list`',
52
+ CAGE_NOT_RUNNING: 'Start the cage first with `lobster start <name>`',
53
+ CAGE_RUNNING: 'Stop the cage first with `lobster stop <name>`',
54
+ NETWORK_ERROR: 'Check your internet connection and API URL',
55
+ AUTH_REQUIRED: 'Run `lobster login` first',
56
+ FORBIDDEN: "You don't have permission. Check your API key",
57
+ RATE_LIMITED: 'Too many requests. Wait a moment and try again',
58
+ INSUFFICIENT_CREDITS: 'Add credits with `lobster upgrade`',
59
+ };
60
+ /**
61
+ * Check if debug mode is enabled via --debug flag or DEBUG env var.
62
+ */
63
+ function isDebug() {
64
+ return !!(process.env.DEBUG || process.argv.includes('--debug'));
65
+ }
66
+ /**
67
+ * Centralized error handler. Call from catch blocks to replace boilerplate.
68
+ *
69
+ * - Stops the spinner if provided
70
+ * - For ApiClientError: prints message + contextual suggestion
71
+ * - For generic Error: prints context-aware message
72
+ * - In --json mode: outputs structured JSON error
73
+ * - In --debug mode: prints stack trace
74
+ * - Calls process.exit(exitCode)
75
+ */
76
+ function handleError(err, options = {}) {
77
+ const { spinner, exitCode = 1, json, context } = options;
78
+ if (spinner) {
79
+ spinner.stop();
80
+ }
81
+ if (err instanceof api_1.ApiClientError) {
82
+ if (json) {
83
+ output.json({ error: err.code, message: err.message });
84
+ }
85
+ else {
86
+ output.error(err.message);
87
+ const suggestion = SUGGESTIONS[err.code];
88
+ if (suggestion) {
89
+ output.info(suggestion);
90
+ }
91
+ }
92
+ }
93
+ else if (err instanceof Error) {
94
+ if (json) {
95
+ output.json({ error: 'UNKNOWN_ERROR', message: err.message });
96
+ }
97
+ else if (context) {
98
+ output.error(`Failed ${context}: ${err.message}`);
99
+ }
100
+ else {
101
+ output.error(err.message);
102
+ }
103
+ }
104
+ else {
105
+ output.error('An unexpected error occurred');
106
+ }
107
+ if (isDebug() && err instanceof Error && err.stack) {
108
+ console.error('\nStack trace:');
109
+ console.error(err.stack);
110
+ }
111
+ process.exit(exitCode);
112
+ }
113
+ //# sourceMappingURL=error-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-handler.js","sourceRoot":"","sources":["../../src/lib/error-handler.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BH,0BAEC;AAYD,kCAmCC;AA5ED,+BAAuC;AACvC,iDAAmC;AAEnC;;GAEG;AACH,MAAM,WAAW,GAA2B;IAC1C,cAAc,EAAE,qCAAqC;IACrD,gBAAgB,EAAE,kDAAkD;IACpE,YAAY,EAAE,gDAAgD;IAC9D,aAAa,EAAE,4CAA4C;IAC3D,aAAa,EAAE,2BAA2B;IAC1C,SAAS,EAAE,+CAA+C;IAC1D,YAAY,EAAE,gDAAgD;IAC9D,oBAAoB,EAAE,oCAAoC;CAC3D,CAAC;AASF;;GAEG;AACH,SAAgB,OAAO;IACrB,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;AACnE,CAAC;AAED;;;;;;;;;GASG;AACH,SAAgB,WAAW,CAAC,GAAY,EAAE,UAA8B,EAAE;IACxE,MAAM,EAAE,OAAO,EAAE,QAAQ,GAAG,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IAEzD,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,CAAC,IAAI,EAAE,CAAC;IACjB,CAAC;IAED,IAAI,GAAG,YAAY,oBAAc,EAAE,CAAC;QAClC,IAAI,IAAI,EAAE,CAAC;YACT,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QACzD,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAC1B,MAAM,UAAU,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACzC,IAAI,UAAU,EAAE,CAAC;gBACf,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC;IACH,CAAC;SAAM,IAAI,GAAG,YAAY,KAAK,EAAE,CAAC;QAChC,IAAI,IAAI,EAAE,CAAC;YACT,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QAChE,CAAC;aAAM,IAAI,OAAO,EAAE,CAAC;YACnB,MAAM,CAAC,KAAK,CAAC,UAAU,OAAO,KAAK,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QACpD,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC;IAC/C,CAAC;IAED,IAAI,OAAO,EAAE,IAAI,GAAG,YAAY,KAAK,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;QACnD,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;QAChC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC;IAED,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AACzB,CAAC"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Output Formatting Utilities
3
+ *
4
+ * Consistent output formatting for the CLI.
5
+ */
6
+ import type { Cage, CageStatus, EnvVar, SecurityWarning, LogEntry, ApiKey } from '../types';
7
+ /**
8
+ * Format cage status with color
9
+ */
10
+ export declare function formatStatus(status: CageStatus): string;
11
+ /**
12
+ * Format a cage for display
13
+ */
14
+ export declare function formatCage(cage: Cage, verbose?: boolean): string;
15
+ /**
16
+ * Format a list of cages as a table
17
+ */
18
+ export declare function formatCageTable(cages: Cage[]): string;
19
+ /**
20
+ * Format environment variables
21
+ */
22
+ export declare function formatEnvVars(vars: EnvVar[]): string;
23
+ /**
24
+ * Format security warnings
25
+ */
26
+ export declare function formatSecurityWarnings(warnings: SecurityWarning[]): string;
27
+ /**
28
+ * Format security severity
29
+ */
30
+ export declare function formatSeverity(severity: string): string;
31
+ /**
32
+ * Format log entries
33
+ */
34
+ export declare function formatLogs(logs: LogEntry[]): string;
35
+ /**
36
+ * Format API keys
37
+ */
38
+ export declare function formatApiKeys(keys: ApiKey[]): string;
39
+ /**
40
+ * Format a date string
41
+ */
42
+ export declare function formatDate(dateStr: string): string;
43
+ /**
44
+ * Format a relative date (e.g., "2 hours ago")
45
+ */
46
+ export declare function formatRelativeDate(dateStr: string): string;
47
+ /**
48
+ * Print success message
49
+ */
50
+ export declare function success(message: string): void;
51
+ /**
52
+ * Print error message
53
+ */
54
+ export declare function error(message: string): void;
55
+ /**
56
+ * Print warning message
57
+ */
58
+ export declare function warning(message: string): void;
59
+ /**
60
+ * Print info message
61
+ */
62
+ export declare function info(message: string): void;
63
+ /**
64
+ * Print a section header
65
+ */
66
+ export declare function header(title: string): void;
67
+ /**
68
+ * Print JSON output (for --json flag)
69
+ */
70
+ export declare function json(data: unknown): void;
71
+ //# sourceMappingURL=output.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../src/lib/output.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAE5F;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAevD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,UAAQ,GAAG,MAAM,CAyB9D;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,MAAM,CAerD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAUpD;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,eAAe,EAAE,GAAG,MAAM,CAY1E;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAavD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,MAAM,CAMnD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAoBpD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAGlD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAoB1D;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE7C;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE3C;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE7C;AAED;;GAEG;AACH,wBAAgB,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE1C;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAI1C;AAED;;GAEG;AACH,wBAAgB,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAExC"}