@arnab-afk/zkm 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.
package/README.md ADDED
@@ -0,0 +1,101 @@
1
+ # zkm — ZkMultiCloud CLI
2
+
3
+ Deploy any app to the cloud without learning DevOps.
4
+
5
+ ```
6
+ npx zkm --help
7
+ ```
8
+
9
+ ---
10
+
11
+ ## Quick start
12
+
13
+ ### 1. Set your API key
14
+
15
+ Get your key from the ZkMultiCloud dashboard under **Settings → API Keys**, then:
16
+
17
+ ```bash
18
+ npx zkm config set-key zkm_your_key_here
19
+ # or export ZKM_API_KEY=zkm_your_key_here
20
+ ```
21
+
22
+ ### 2. Create a project
23
+
24
+ ```bash
25
+ npx zkm project create
26
+ ```
27
+
28
+ Follow the interactive prompts to name the project, pick a service type, and paste your GitHub repo URL.
29
+
30
+ ### 3. Deploy
31
+
32
+ ```bash
33
+ npx zkm deploy <projectId>
34
+
35
+ # Stream logs in real time:
36
+ npx zkm deploy <projectId> --tail
37
+ ```
38
+
39
+ ---
40
+
41
+ ## All commands
42
+
43
+ ```
44
+ zkm auth
45
+ login Log in with email & password (creates an API key automatically)
46
+ set-key <key> Store an existing API key locally
47
+ logout Remove locally stored credentials
48
+ whoami Show the currently configured API key
49
+
50
+ zkm config
51
+ show Show current config (API URL, key prefix, config file path)
52
+ set-key <key> Store an API key
53
+ set-url <url> Point the CLI at a self-hosted backend
54
+
55
+ zkm project (alias: proj)
56
+ list List all your projects
57
+ get <id> Show project details and config
58
+ create Interactively create a new project
59
+ delete <id> Delete a project
60
+
61
+ zkm deploy <projectId>
62
+ --tail Poll and stream deployment logs until done
63
+
64
+ zkm deployments (alias: deps)
65
+ list <projectId> List deployments
66
+ logs <projectId> <deployId> Print logs for a deployment
67
+ --tail Poll until the deployment finishes
68
+ get <projectId> <deployId> Get a single deployment
69
+
70
+ zkm apikeys (alias: keys)
71
+ list List all API keys
72
+ create Create a new API key
73
+ revoke <id> Revoke an API key
74
+ ```
75
+
76
+ ---
77
+
78
+ ## Environment variables
79
+
80
+ | Variable | Description |
81
+ |---|---|
82
+ | `ZKM_API_KEY` | API key (overrides the locally stored one) |
83
+ | `ZKM_API_URL` | Backend URL (default: `https://api.zkmulticloud.com`) |
84
+
85
+ ---
86
+
87
+ ## Self-hosted backend
88
+
89
+ ```bash
90
+ npx zkm config set-url http://localhost:3001
91
+ npx zkm config set-key zkm_your_key_here
92
+ ```
93
+
94
+ ---
95
+
96
+ ## Install globally (optional)
97
+
98
+ ```bash
99
+ npm install -g zkm
100
+ zkm deploy <projectId> --tail
101
+ ```
package/dist/api.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ export declare class ApiError extends Error {
2
+ readonly status: number;
3
+ constructor(status: number, message: string);
4
+ }
5
+ export declare const api: {
6
+ get: <T>(path: string) => Promise<T>;
7
+ post: <T>(path: string, body?: unknown) => Promise<T>;
8
+ put: <T>(path: string, body?: unknown) => Promise<T>;
9
+ delete: <T>(path: string) => Promise<T>;
10
+ authPost: <T>(path: string, body: unknown) => Promise<T>;
11
+ };
12
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAGA,qBAAa,QAAS,SAAQ,KAAK;aAEf,MAAM,EAAE,MAAM;gBAAd,MAAM,EAAE,MAAM,EAC9B,OAAO,EAAE,MAAM;CAKlB;AA8DD,eAAO,MAAM,GAAG;UACR,CAAC,QAAQ,MAAM;WACd,CAAC,QAAQ,MAAM,SAAS,OAAO;UAChC,CAAC,QAAQ,MAAM,SAAS,OAAO;aAC5B,CAAC,QAAQ,MAAM;eACb,CAAC,QAAQ,MAAM,QAAQ,OAAO;CAC1C,CAAC"}
package/dist/api.js ADDED
@@ -0,0 +1,62 @@
1
+ import { getApiKey, getApiUrl } from './config.js';
2
+ import chalk from 'chalk';
3
+ export class ApiError extends Error {
4
+ status;
5
+ constructor(status, message) {
6
+ super(message);
7
+ this.status = status;
8
+ this.name = 'ApiError';
9
+ }
10
+ }
11
+ async function request(method, path, body, authOverride) {
12
+ const baseUrl = getApiUrl();
13
+ const url = `${baseUrl}/api${path}`;
14
+ const apiKey = authOverride ?? getApiKey();
15
+ if (!apiKey) {
16
+ console.error(chalk.red('No API key configured.') +
17
+ '\n Run ' +
18
+ chalk.cyan('zkm config set-key <YOUR_API_KEY>') +
19
+ ' or set the ' +
20
+ chalk.cyan('ZKM_API_KEY') +
21
+ ' environment variable.');
22
+ process.exit(1);
23
+ }
24
+ const headers = {
25
+ 'Content-Type': 'application/json',
26
+ 'X-API-Key': apiKey,
27
+ };
28
+ const res = await fetch(url, {
29
+ method,
30
+ headers,
31
+ body: body !== undefined ? JSON.stringify(body) : undefined,
32
+ });
33
+ if (res.status === 204)
34
+ return undefined;
35
+ const data = await res.json().catch(() => ({ error: res.statusText }));
36
+ if (!res.ok) {
37
+ throw new ApiError(res.status, data.error ?? res.statusText);
38
+ }
39
+ return data;
40
+ }
41
+ /** Auth endpoint — uses email/password, no API key needed */
42
+ async function authRequest(path, body) {
43
+ const baseUrl = getApiUrl();
44
+ const url = `${baseUrl}/api${path}`;
45
+ const res = await fetch(url, {
46
+ method: 'POST',
47
+ headers: { 'Content-Type': 'application/json' },
48
+ body: JSON.stringify(body),
49
+ });
50
+ const data = await res.json().catch(() => ({ error: res.statusText }));
51
+ if (!res.ok)
52
+ throw new ApiError(res.status, data.error ?? res.statusText);
53
+ return data;
54
+ }
55
+ export const api = {
56
+ get: (path) => request('GET', path),
57
+ post: (path, body) => request('POST', path, body),
58
+ put: (path, body) => request('PUT', path, body),
59
+ delete: (path) => request('DELETE', path),
60
+ authPost: (path, body) => authRequest(path, body),
61
+ };
62
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from 'commander';
2
+ export declare function registerApiKeyCommands(program: Command): void;
3
+ //# sourceMappingURL=apikeys.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apikeys.d.ts","sourceRoot":"","sources":["../../src/commands/apikeys.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgBzC,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA2G7D"}
@@ -0,0 +1,109 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ import inquirer from 'inquirer';
4
+ import { table } from 'table';
5
+ import { api } from '../api.js';
6
+ import { handleError, formatDate } from '../utils.js';
7
+ export function registerApiKeyCommands(program) {
8
+ const keys = program.command('apikeys').description('Manage API keys').alias('keys');
9
+ // ── zkm apikeys list ───────────────────────────────────────────────────────
10
+ keys
11
+ .command('list')
12
+ .description('List all API keys')
13
+ .alias('ls')
14
+ .action(async () => {
15
+ const spinner = ora('Fetching API keys…').start();
16
+ try {
17
+ const apiKeys = await api.get('/apikeys');
18
+ spinner.stop();
19
+ if (apiKeys.length === 0) {
20
+ console.log(chalk.yellow('No API keys found.'));
21
+ return;
22
+ }
23
+ const rows = [
24
+ [
25
+ chalk.bold('ID'),
26
+ chalk.bold('Name'),
27
+ chalk.bold('Prefix'),
28
+ chalk.bold('Created'),
29
+ chalk.bold('Last used'),
30
+ ],
31
+ ...apiKeys.map((k) => [
32
+ chalk.dim(k.id.slice(0, 8)),
33
+ chalk.cyan(k.name),
34
+ chalk.bold(k.prefix),
35
+ formatDate(k.createdAt),
36
+ k.lastUsedAt ? formatDate(k.lastUsedAt) : chalk.dim('never'),
37
+ ]),
38
+ ];
39
+ console.log(table(rows));
40
+ }
41
+ catch (err) {
42
+ spinner.fail();
43
+ handleError(err);
44
+ }
45
+ });
46
+ // ── zkm apikeys create ─────────────────────────────────────────────────────
47
+ keys
48
+ .command('create')
49
+ .description('Create a new API key')
50
+ .option('-n, --name <name>', 'Key name')
51
+ .action(async (opts) => {
52
+ let name = opts.name;
53
+ if (!name) {
54
+ const ans = await inquirer.prompt([
55
+ {
56
+ type: 'input',
57
+ name: 'name',
58
+ message: 'Key name:',
59
+ validate: (v) => (v.trim().length > 0 ? true : 'Name is required'),
60
+ },
61
+ ]);
62
+ name = ans.name;
63
+ }
64
+ const spinner = ora('Creating API key…').start();
65
+ try {
66
+ const result = await api.post('/apikeys', { name });
67
+ spinner.succeed(chalk.green('API key created!'));
68
+ console.log(chalk.dim('Name: ') + chalk.cyan(result.name));
69
+ console.log(chalk.dim('Prefix: ') + chalk.bold(result.prefix));
70
+ console.log(chalk.yellow('\nCopy your key now — it will not be shown again:\n') +
71
+ chalk.bold(result.key));
72
+ }
73
+ catch (err) {
74
+ spinner.fail();
75
+ handleError(err);
76
+ }
77
+ });
78
+ // ── zkm apikeys revoke <id> ────────────────────────────────────────────────
79
+ keys
80
+ .command('revoke <id>')
81
+ .description('Revoke an API key')
82
+ .option('-y, --yes', 'Skip confirmation')
83
+ .action(async (id, opts) => {
84
+ if (!opts.yes) {
85
+ const { confirm } = await inquirer.prompt([
86
+ {
87
+ type: 'confirm',
88
+ name: 'confirm',
89
+ message: chalk.red(`Revoke API key ${id}?`),
90
+ default: false,
91
+ },
92
+ ]);
93
+ if (!confirm) {
94
+ console.log('Aborted.');
95
+ return;
96
+ }
97
+ }
98
+ const spinner = ora('Revoking key…').start();
99
+ try {
100
+ await api.delete(`/apikeys/${id}`);
101
+ spinner.succeed(chalk.green('API key revoked.'));
102
+ }
103
+ catch (err) {
104
+ spinner.fail();
105
+ handleError(err);
106
+ }
107
+ });
108
+ }
109
+ //# sourceMappingURL=apikeys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apikeys.js","sourceRoot":"","sources":["../../src/commands/apikeys.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from 'commander';
2
+ export declare function registerAuthCommands(program: Command): void;
3
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQzC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAuF3D"}
@@ -0,0 +1,86 @@
1
+ import inquirer from 'inquirer';
2
+ import chalk from 'chalk';
3
+ import ora from 'ora';
4
+ import { api } from '../api.js';
5
+ import { setApiKey, clearCredentials, getApiKey } from '../config.js';
6
+ import { handleError } from '../utils.js';
7
+ export function registerAuthCommands(program) {
8
+ const auth = program.command('auth').description('Authenticate with ZkMultiCloud');
9
+ // zkm auth login — get an API key via email/password
10
+ auth
11
+ .command('login')
12
+ .description('Log in with email & password to get an API key')
13
+ .action(async () => {
14
+ const { email, password } = await inquirer.prompt([
15
+ { type: 'input', name: 'email', message: 'Email:' },
16
+ { type: 'password', name: 'password', message: 'Password:', mask: '*' },
17
+ ]);
18
+ const spinner = ora('Logging in…').start();
19
+ try {
20
+ const { token } = await api.authPost('/auth/login', { email, password });
21
+ // Exchange the JWT for an API key
22
+ const { key, name: keyName } = await (async () => {
23
+ // Temporarily use the JWT to create an API key named "CLI"
24
+ const baseUrl = (await import('../config.js')).getApiUrl();
25
+ const res = await fetch(`${baseUrl}/api/apikeys`, {
26
+ method: 'POST',
27
+ headers: {
28
+ 'Content-Type': 'application/json',
29
+ Authorization: `Bearer ${token}`,
30
+ },
31
+ body: JSON.stringify({ name: 'CLI' }),
32
+ });
33
+ if (!res.ok) {
34
+ const d = await res.json().catch(() => ({}));
35
+ throw new Error(d.error ?? 'Failed to create API key');
36
+ }
37
+ return res.json();
38
+ })();
39
+ setApiKey(key);
40
+ spinner.succeed(chalk.green('Logged in!'));
41
+ console.log(chalk.dim('API key created: ') +
42
+ chalk.cyan(keyName) +
43
+ '\n' +
44
+ chalk.yellow('Save this key — it will not be shown again:\n') +
45
+ chalk.bold(key));
46
+ }
47
+ catch (err) {
48
+ spinner.fail();
49
+ handleError(err);
50
+ }
51
+ });
52
+ // zkm auth set-key <key> — store an existing API key
53
+ auth
54
+ .command('set-key <key>')
55
+ .description('Store an existing API key locally')
56
+ .action((key) => {
57
+ if (!key.startsWith('zkm_')) {
58
+ console.error(chalk.red('API keys must start with "zkm_".'));
59
+ process.exit(1);
60
+ }
61
+ setApiKey(key);
62
+ console.log(chalk.green('API key saved.'));
63
+ });
64
+ // zkm auth logout
65
+ auth
66
+ .command('logout')
67
+ .description('Remove locally stored credentials')
68
+ .action(() => {
69
+ clearCredentials();
70
+ console.log(chalk.green('Logged out. Credentials removed.'));
71
+ });
72
+ // zkm auth whoami
73
+ auth
74
+ .command('whoami')
75
+ .description('Show the currently configured API key')
76
+ .action(() => {
77
+ const key = getApiKey();
78
+ if (!key) {
79
+ console.log(chalk.yellow('No API key configured.'));
80
+ }
81
+ else {
82
+ console.log(chalk.dim('API key: ') + chalk.cyan(key.slice(0, 8) + '…' + key.slice(-4)));
83
+ }
84
+ });
85
+ }
86
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from 'commander';
2
+ export declare function registerConfigCommands(program: Command): void;
3
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIzC,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA8C7D"}
@@ -0,0 +1,46 @@
1
+ import chalk from 'chalk';
2
+ import { getApiKey, getApiUrl, setApiUrl, setApiKey, configPath } from '../config.js';
3
+ export function registerConfigCommands(program) {
4
+ const config = program.command('config').description('View and edit CLI configuration');
5
+ // zkm config show
6
+ config
7
+ .command('show')
8
+ .description('Show current configuration')
9
+ .action(() => {
10
+ const key = getApiKey();
11
+ console.log(chalk.bold('API URL: ') + chalk.cyan(getApiUrl()));
12
+ console.log(chalk.bold('API Key: ') +
13
+ (key
14
+ ? chalk.cyan(key.slice(0, 8) + '…' + key.slice(-4))
15
+ : chalk.dim('not set')));
16
+ console.log(chalk.dim('\nConfig file: ') + configPath());
17
+ });
18
+ // zkm config set-key <key>
19
+ config
20
+ .command('set-key <key>')
21
+ .description('Store an API key')
22
+ .action((key) => {
23
+ if (!key.startsWith('zkm_')) {
24
+ console.error(chalk.red('API keys must start with "zkm_".'));
25
+ process.exit(1);
26
+ }
27
+ setApiKey(key);
28
+ console.log(chalk.green('API key saved.'));
29
+ });
30
+ // zkm config set-url <url>
31
+ config
32
+ .command('set-url <url>')
33
+ .description('Set the backend API URL (default: https://api.zkmulticloud.com)')
34
+ .action((url) => {
35
+ try {
36
+ new URL(url); // validate
37
+ }
38
+ catch {
39
+ console.error(chalk.red('Invalid URL.'));
40
+ process.exit(1);
41
+ }
42
+ setApiUrl(url);
43
+ console.log(chalk.green('API URL saved: ') + chalk.cyan(url));
44
+ });
45
+ }
46
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAEtF,MAAM,UAAU,sBAAsB,CAAC,OAAgB;IACrD,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,CAAC,iCAAiC,CAAC,CAAC;IAExF,kBAAkB;IAClB,MAAM;SACH,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,4BAA4B,CAAC;SACzC,MAAM,CAAC,GAAG,EAAE;QACX,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC;QACxB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;QAC/D,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC;YACrB,CAAC,GAAG;gBACF,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;gBACnD,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAC5B,CAAC;QACF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,GAAG,UAAU,EAAE,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEL,2BAA2B;IAC3B,MAAM;SACH,OAAO,CAAC,eAAe,CAAC;SACxB,WAAW,CAAC,kBAAkB,CAAC;SAC/B,MAAM,CAAC,CAAC,GAAW,EAAE,EAAE;QACtB,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YAC5B,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC,CAAC;YAC7D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,SAAS,CAAC,GAAG,CAAC,CAAC;QACf,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEL,2BAA2B;IAC3B,MAAM;SACH,OAAO,CAAC,eAAe,CAAC;SACxB,WAAW,CAAC,iEAAiE,CAAC;SAC9E,MAAM,CAAC,CAAC,GAAW,EAAE,EAAE;QACtB,IAAI,CAAC;YACH,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW;QAC3B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC;YACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,SAAS,CAAC,GAAG,CAAC,CAAC;QACf,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,iBAAiB,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from 'commander';
2
+ export declare function registerDeployCommands(program: Command): void;
3
+ //# sourceMappingURL=deploy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAiBzC,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA8G7D"}
@@ -0,0 +1,160 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ import { table } from 'table';
4
+ import { api } from '../api.js';
5
+ import { handleError, formatDate, statusColor } from '../utils.js';
6
+ export function registerDeployCommands(program) {
7
+ // ── zkm deploy <projectId> ─────────────────────────────────────────────────
8
+ program
9
+ .command('deploy <projectId>')
10
+ .description('Trigger a deployment for a project')
11
+ .option('--tail', 'Stream logs after triggering (polls every 2 s)')
12
+ .action(async (projectId, opts) => {
13
+ const spinner = ora('Triggering deployment…').start();
14
+ try {
15
+ const { deploymentId } = await api.post(`/projects/${projectId}/deploy`);
16
+ spinner.succeed(chalk.green('Deployment started!'));
17
+ console.log(chalk.dim('Deployment ID: ') + chalk.cyan(deploymentId));
18
+ console.log(chalk.dim('Logs: ') + chalk.bold(`zkm deployments logs ${projectId} ${deploymentId}`));
19
+ if (opts.tail) {
20
+ await tailLogs(projectId, deploymentId);
21
+ }
22
+ }
23
+ catch (err) {
24
+ spinner.fail();
25
+ handleError(err);
26
+ }
27
+ });
28
+ // ── zkm deployments ────────────────────────────────────────────────────────
29
+ const dep = program.command('deployments').description('Manage deployments').alias('deps');
30
+ dep
31
+ .command('list <projectId>')
32
+ .description('List deployments for a project')
33
+ .alias('ls')
34
+ .action(async (projectId) => {
35
+ const spinner = ora('Fetching deployments…').start();
36
+ try {
37
+ const deployments = await api.get(`/projects/${projectId}/deployments`);
38
+ spinner.stop();
39
+ if (deployments.length === 0) {
40
+ console.log(chalk.yellow('No deployments found.'));
41
+ return;
42
+ }
43
+ const rows = [
44
+ [
45
+ chalk.bold('ID'),
46
+ chalk.bold('Status'),
47
+ chalk.bold('Created'),
48
+ chalk.bold('Deployed'),
49
+ ],
50
+ ...deployments.map((d) => [
51
+ chalk.dim(d.id.slice(0, 8)),
52
+ statusColor(d.status),
53
+ formatDate(d.createdAt),
54
+ d.deployedAt ? formatDate(d.deployedAt) : chalk.dim('—'),
55
+ ]),
56
+ ];
57
+ console.log(table(rows));
58
+ }
59
+ catch (err) {
60
+ spinner.fail();
61
+ handleError(err);
62
+ }
63
+ });
64
+ dep
65
+ .command('logs <projectId> <deploymentId>')
66
+ .description('Show logs for a deployment')
67
+ .option('--tail', 'Poll until the deployment finishes')
68
+ .action(async (projectId, deploymentId, opts) => {
69
+ if (opts.tail) {
70
+ await tailLogs(projectId, deploymentId);
71
+ }
72
+ else {
73
+ const spinner = ora('Fetching logs…').start();
74
+ try {
75
+ const deployment = await api.get(`/projects/${projectId}/deployments/${deploymentId}`);
76
+ spinner.stop();
77
+ printLogs(deployment);
78
+ }
79
+ catch (err) {
80
+ spinner.fail();
81
+ handleError(err);
82
+ }
83
+ }
84
+ });
85
+ dep
86
+ .command('get <projectId> <deploymentId>')
87
+ .description('Get a single deployment')
88
+ .action(async (projectId, deploymentId) => {
89
+ const spinner = ora('Fetching deployment…').start();
90
+ try {
91
+ const deployment = await api.get(`/projects/${projectId}/deployments/${deploymentId}`);
92
+ spinner.stop();
93
+ console.log(chalk.bold('Status: ') + statusColor(deployment.status));
94
+ console.log(chalk.dim('ID: ') + deployment.id);
95
+ console.log(chalk.dim('Created: ') + formatDate(deployment.createdAt));
96
+ if (deployment.deployedAt) {
97
+ console.log(chalk.dim('Deployed:') + ' ' + formatDate(deployment.deployedAt));
98
+ }
99
+ printLogs(deployment);
100
+ }
101
+ catch (err) {
102
+ spinner.fail();
103
+ handleError(err);
104
+ }
105
+ });
106
+ }
107
+ function printLogs(deployment) {
108
+ const logs = deployment.logs ?? [];
109
+ if (logs.length === 0) {
110
+ console.log(chalk.dim('No logs yet.'));
111
+ return;
112
+ }
113
+ for (const log of logs) {
114
+ const time = chalk.dim(new Date(log.timestamp).toLocaleTimeString());
115
+ const level = log.level === 'error'
116
+ ? chalk.red(log.level.padEnd(7))
117
+ : log.level === 'success'
118
+ ? chalk.green(log.level.padEnd(7))
119
+ : log.level === 'warning'
120
+ ? chalk.yellow(log.level.padEnd(7))
121
+ : chalk.dim(log.level.padEnd(7));
122
+ console.log(`${time} ${level} ${log.message}`);
123
+ }
124
+ }
125
+ async function tailLogs(projectId, deploymentId) {
126
+ const POLL_INTERVAL = 2000;
127
+ let lastLogCount = 0;
128
+ console.log(chalk.dim('Tailing logs (Ctrl+C to stop)…\n'));
129
+ while (true) {
130
+ try {
131
+ const deployment = await api.get(`/projects/${projectId}/deployments/${deploymentId}`);
132
+ const logs = deployment.logs ?? [];
133
+ const newLogs = logs.slice(lastLogCount);
134
+ lastLogCount = logs.length;
135
+ for (const log of newLogs) {
136
+ const time = chalk.dim(new Date(log.timestamp).toLocaleTimeString());
137
+ const level = log.level === 'error'
138
+ ? chalk.red(log.level.padEnd(7))
139
+ : log.level === 'success'
140
+ ? chalk.green(log.level.padEnd(7))
141
+ : log.level === 'warning'
142
+ ? chalk.yellow(log.level.padEnd(7))
143
+ : chalk.dim(log.level.padEnd(7));
144
+ console.log(`${time} ${level} ${log.message}`);
145
+ }
146
+ if (deployment.status === 'success' || deployment.status === 'failed') {
147
+ console.log('\n' +
148
+ (deployment.status === 'success'
149
+ ? chalk.green('Deployment succeeded.')
150
+ : chalk.red('Deployment failed.')));
151
+ break;
152
+ }
153
+ }
154
+ catch {
155
+ // network hiccup — keep polling
156
+ }
157
+ await new Promise((r) => setTimeout(r, POLL_INTERVAL));
158
+ }
159
+ }
160
+ //# sourceMappingURL=deploy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deploy.js","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from 'commander';
2
+ export declare function registerProjectCommands(program: Command): void;
3
+ //# sourceMappingURL=projects.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projects.d.ts","sourceRoot":"","sources":["../../src/commands/projects.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgBzC,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAyN9D"}
@@ -0,0 +1,281 @@
1
+ import inquirer from 'inquirer';
2
+ import chalk from 'chalk';
3
+ import ora from 'ora';
4
+ import { table } from 'table';
5
+ import { api } from '../api.js';
6
+ import { handleError, formatDate } from '../utils.js';
7
+ export function registerProjectCommands(program) {
8
+ const proj = program.command('project').description('Manage projects').alias('proj');
9
+ // ── zkm project list ───────────────────────────────────────────────────────
10
+ proj
11
+ .command('list')
12
+ .description('List all projects')
13
+ .alias('ls')
14
+ .action(async () => {
15
+ const spinner = ora('Fetching projects…').start();
16
+ try {
17
+ const projects = await api.get('/projects');
18
+ spinner.stop();
19
+ if (projects.length === 0) {
20
+ console.log(chalk.yellow('No projects found. Create one with: zkm project create'));
21
+ return;
22
+ }
23
+ const rows = [
24
+ [chalk.bold('ID'), chalk.bold('Name'), chalk.bold('Environment'), chalk.bold('Created')],
25
+ ...projects.map((p) => [
26
+ chalk.dim(p.id.slice(0, 8)),
27
+ chalk.cyan(p.name),
28
+ p.environment,
29
+ formatDate(p.createdAt),
30
+ ]),
31
+ ];
32
+ console.log(table(rows));
33
+ }
34
+ catch (err) {
35
+ spinner.fail();
36
+ handleError(err);
37
+ }
38
+ });
39
+ // ── zkm project get <id> ───────────────────────────────────────────────────
40
+ proj
41
+ .command('get <id>')
42
+ .description('Show details of a project')
43
+ .action(async (id) => {
44
+ const spinner = ora('Fetching project…').start();
45
+ try {
46
+ const project = await api.get(`/projects/${id}`);
47
+ spinner.stop();
48
+ console.log(chalk.bold('Project: ') + chalk.cyan(project.name));
49
+ console.log(chalk.dim('ID: ') + project.id);
50
+ console.log(chalk.dim('Environment: ') + project.environment);
51
+ console.log(chalk.dim('Created: ') + formatDate(project.createdAt));
52
+ console.log(chalk.dim('Updated: ') + formatDate(project.updatedAt));
53
+ console.log(chalk.dim('\nConfig:'));
54
+ console.log(JSON.stringify(project.config, null, 2));
55
+ }
56
+ catch (err) {
57
+ spinner.fail();
58
+ handleError(err);
59
+ }
60
+ });
61
+ // ── zkm project create ─────────────────────────────────────────────────────
62
+ proj
63
+ .command('create')
64
+ .description('Interactively create a new project')
65
+ .option('-n, --name <name>', 'Project name')
66
+ .option('-e, --environment <env>', 'Environment (development|staging|production)')
67
+ .action(async (opts) => {
68
+ const answers = await inquirer.prompt([
69
+ {
70
+ type: 'input',
71
+ name: 'name',
72
+ message: 'Project name:',
73
+ when: !opts.name,
74
+ validate: (v) => (v.trim().length > 0 ? true : 'Name is required'),
75
+ },
76
+ {
77
+ type: 'list',
78
+ name: 'environment',
79
+ message: 'Environment:',
80
+ choices: ['production', 'staging', 'development'],
81
+ default: 'production',
82
+ when: !opts.environment,
83
+ },
84
+ {
85
+ type: 'list',
86
+ name: 'serviceType',
87
+ message: 'Service type:',
88
+ choices: [
89
+ 'react', 'vue', 'angular', 'static', 'nextjs',
90
+ 'nodejs', 'python', 'java', 'dotnet', 'go',
91
+ ],
92
+ },
93
+ {
94
+ type: 'input',
95
+ name: 'serviceName',
96
+ message: 'Service name:',
97
+ default: 'app',
98
+ },
99
+ {
100
+ type: 'input',
101
+ name: 'repoUrl',
102
+ message: 'GitHub repository URL:',
103
+ validate: (v) => (v.startsWith('https://') ? true : 'Must be a full HTTPS URL'),
104
+ },
105
+ {
106
+ type: 'input',
107
+ name: 'branch',
108
+ message: 'Branch:',
109
+ default: 'main',
110
+ },
111
+ {
112
+ type: 'input',
113
+ name: 'buildCommand',
114
+ message: 'Build command (optional):',
115
+ },
116
+ {
117
+ type: 'input',
118
+ name: 'outputDir',
119
+ message: 'Output directory (optional, e.g. dist/build):',
120
+ },
121
+ {
122
+ type: 'input',
123
+ name: 'startCommand',
124
+ message: 'Start command (optional, for backend services):',
125
+ },
126
+ {
127
+ type: 'confirm',
128
+ name: 'addEnvVars',
129
+ message: 'Add environment variables?',
130
+ default: false,
131
+ },
132
+ ]);
133
+ // ── Env var provisioning ───────────────────────────────────────────────
134
+ let envVars = {};
135
+ if (answers.addEnvVars) {
136
+ console.log('\n' +
137
+ chalk.bold('Paste your .env content below.') +
138
+ chalk.dim(' (KEY=VALUE lines, # comments ignored)\n') +
139
+ chalk.dim('Press ') +
140
+ chalk.cyan('Enter') +
141
+ chalk.dim(' twice on an empty line when done:\n'));
142
+ const rawEnv = await collectMultilineInput();
143
+ envVars = parseEnvBlock(rawEnv);
144
+ if (Object.keys(envVars).length === 0) {
145
+ console.log(chalk.yellow(' No valid KEY=VALUE pairs found — skipping env vars.'));
146
+ }
147
+ else {
148
+ console.log(chalk.green(`\n Parsed ${Object.keys(envVars).length} variable(s):`));
149
+ for (const [k, v] of Object.entries(envVars)) {
150
+ console.log(` ${chalk.cyan(k)} = ${chalk.dim(v.length > 40 ? v.slice(0, 40) + '…' : v)}`);
151
+ }
152
+ console.log();
153
+ }
154
+ }
155
+ const name = opts.name ?? answers.name;
156
+ const environment = opts.environment ?? answers.environment;
157
+ const service = {
158
+ name: answers.serviceName,
159
+ type: answers.serviceType,
160
+ repo_url: answers.repoUrl,
161
+ branch: answers.branch,
162
+ };
163
+ if (answers.buildCommand)
164
+ service['build_command'] = answers.buildCommand;
165
+ if (answers.outputDir)
166
+ service['output_dir'] = answers.outputDir;
167
+ if (answers.startCommand)
168
+ service['start_command'] = answers.startCommand;
169
+ if (Object.keys(envVars).length > 0)
170
+ service['env_vars'] = envVars;
171
+ const spinner = ora('Creating project…').start();
172
+ try {
173
+ const project = await api.post('/projects', {
174
+ name,
175
+ environment,
176
+ services: [service],
177
+ databases: [],
178
+ });
179
+ spinner.succeed(chalk.green('Project created!'));
180
+ console.log(chalk.dim('ID: ') + chalk.cyan(project.id));
181
+ console.log(chalk.dim('Run: ') + chalk.bold(`zkm deploy ${project.id}`));
182
+ }
183
+ catch (err) {
184
+ spinner.fail();
185
+ handleError(err);
186
+ }
187
+ });
188
+ // ── zkm project delete <id> ────────────────────────────────────────────────
189
+ proj
190
+ .command('delete <id>')
191
+ .description('Delete a project')
192
+ .option('-y, --yes', 'Skip confirmation')
193
+ .action(async (id, opts) => {
194
+ if (!opts.yes) {
195
+ const { confirm } = await inquirer.prompt([
196
+ {
197
+ type: 'confirm',
198
+ name: 'confirm',
199
+ message: chalk.red(`Delete project ${id}? This cannot be undone.`),
200
+ default: false,
201
+ },
202
+ ]);
203
+ if (!confirm) {
204
+ console.log('Aborted.');
205
+ return;
206
+ }
207
+ }
208
+ const spinner = ora('Deleting project…').start();
209
+ try {
210
+ await api.delete(`/projects/${id}`);
211
+ spinner.succeed(chalk.green('Project deleted.'));
212
+ }
213
+ catch (err) {
214
+ spinner.fail();
215
+ handleError(err);
216
+ }
217
+ });
218
+ }
219
+ // ── Helpers ──────────────────────────────────────────────────────────────────
220
+ /**
221
+ * Read stdin lines until the user submits two consecutive blank lines
222
+ * (mimics the "double-Enter to finish" convention for multi-line paste).
223
+ */
224
+ async function collectMultilineInput() {
225
+ const { createInterface } = await import('readline');
226
+ const rl = createInterface({ input: process.stdin, terminal: false });
227
+ return new Promise((resolve) => {
228
+ const lines = [];
229
+ let blankCount = 0;
230
+ // Re-attach raw stdin so readline can read while inquirer has paused it
231
+ process.stdin.resume();
232
+ rl.on('line', (line) => {
233
+ if (line.trim() === '') {
234
+ blankCount++;
235
+ if (blankCount >= 2) {
236
+ rl.close();
237
+ return;
238
+ }
239
+ }
240
+ else {
241
+ blankCount = 0;
242
+ }
243
+ lines.push(line);
244
+ });
245
+ rl.on('close', () => resolve(lines.join('\n')));
246
+ });
247
+ }
248
+ /**
249
+ * Parse a .env-style block into a key→value map.
250
+ * Supports:
251
+ * KEY=value
252
+ * KEY="quoted value"
253
+ * KEY='single quoted'
254
+ * # comment lines (ignored)
255
+ * export KEY=value
256
+ */
257
+ function parseEnvBlock(raw) {
258
+ const result = {};
259
+ for (const line of raw.split('\n')) {
260
+ const trimmed = line.trim();
261
+ if (!trimmed || trimmed.startsWith('#'))
262
+ continue;
263
+ // Strip optional leading "export "
264
+ const stripped = trimmed.replace(/^export\s+/, '');
265
+ const eqIdx = stripped.indexOf('=');
266
+ if (eqIdx === -1)
267
+ continue;
268
+ const key = stripped.slice(0, eqIdx).trim();
269
+ if (!key || !/^[A-Za-z_][A-Za-z0-9_]*$/.test(key))
270
+ continue;
271
+ let value = stripped.slice(eqIdx + 1).trim();
272
+ // Strip surrounding quotes
273
+ if ((value.startsWith('"') && value.endsWith('"')) ||
274
+ (value.startsWith("'") && value.endsWith("'"))) {
275
+ value = value.slice(1, -1);
276
+ }
277
+ result[key] = value;
278
+ }
279
+ return result;
280
+ }
281
+ //# sourceMappingURL=projects.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projects.js","sourceRoot":"","sources":["../../src/commands/projects.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export declare function getApiKey(): string;
2
+ export declare function setApiKey(key: string): void;
3
+ export declare function getApiUrl(): string;
4
+ export declare function setApiUrl(url: string): void;
5
+ export declare function clearCredentials(): void;
6
+ export declare function configPath(): string;
7
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAeA,wBAAgB,SAAS,IAAI,MAAM,CAGlC;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAE3C;AAED,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAE3C;AAED,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC;AAED,wBAAgB,UAAU,IAAI,MAAM,CAEnC"}
package/dist/config.js ADDED
@@ -0,0 +1,28 @@
1
+ import Conf from 'conf';
2
+ const store = new Conf({
3
+ projectName: 'zkm-cli',
4
+ defaults: {
5
+ apiKey: '',
6
+ apiUrl: 'https://api.zkmulticloud.com',
7
+ },
8
+ });
9
+ export function getApiKey() {
10
+ // Env var takes precedence over stored value
11
+ return process.env.ZKM_API_KEY ?? store.get('apiKey') ?? '';
12
+ }
13
+ export function setApiKey(key) {
14
+ store.set('apiKey', key);
15
+ }
16
+ export function getApiUrl() {
17
+ return process.env.ZKM_API_URL ?? store.get('apiUrl') ?? 'https://api.zkmulticloud.com';
18
+ }
19
+ export function setApiUrl(url) {
20
+ store.set('apiUrl', url);
21
+ }
22
+ export function clearCredentials() {
23
+ store.delete('apiKey');
24
+ }
25
+ export function configPath() {
26
+ return store.path;
27
+ }
28
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAOxB,MAAM,KAAK,GAAG,IAAI,IAAI,CAAc;IAClC,WAAW,EAAE,SAAS;IACtB,QAAQ,EAAE;QACR,MAAM,EAAE,EAAE;QACV,MAAM,EAAE,8BAA8B;KACvC;CACF,CAAC,CAAC;AAEH,MAAM,UAAU,SAAS;IACvB,6CAA6C;IAC7C,OAAO,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;AAC9D,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,GAAW;IACnC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,OAAO,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,8BAA8B,CAAC;AAC1F,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,GAAW;IACnC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,OAAO,KAAK,CAAC,IAAI,CAAC;AACpB,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env node
2
+ import { program } from 'commander';
3
+ import { registerAuthCommands } from './commands/auth.js';
4
+ import { registerProjectCommands } from './commands/projects.js';
5
+ import { registerDeployCommands } from './commands/deploy.js';
6
+ import { registerApiKeyCommands } from './commands/apikeys.js';
7
+ import { registerConfigCommands } from './commands/config.js';
8
+ program
9
+ .name('zkm')
10
+ .description('ZkMultiCloud CLI — deploy any app to the cloud')
11
+ .version('0.1.0');
12
+ registerAuthCommands(program);
13
+ registerProjectCommands(program);
14
+ registerDeployCommands(program);
15
+ registerApiKeyCommands(program);
16
+ registerConfigCommands(program);
17
+ program.parse();
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAE9D,OAAO;KACJ,IAAI,CAAC,KAAK,CAAC;KACX,WAAW,CAAC,gDAAgD,CAAC;KAC7D,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC9B,uBAAuB,CAAC,OAAO,CAAC,CAAC;AACjC,sBAAsB,CAAC,OAAO,CAAC,CAAC;AAChC,sBAAsB,CAAC,OAAO,CAAC,CAAC;AAChC,sBAAsB,CAAC,OAAO,CAAC,CAAC;AAEhC,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function handleError(err: unknown): never;
2
+ export declare function formatDate(iso: string): string;
3
+ export declare function statusColor(status: string): string;
4
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAGA,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,KAAK,CAS/C;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAalD"}
package/dist/utils.js ADDED
@@ -0,0 +1,32 @@
1
+ import chalk from 'chalk';
2
+ import { ApiError } from './api.js';
3
+ export function handleError(err) {
4
+ if (err instanceof ApiError) {
5
+ console.error(chalk.red(`Error ${err.status}:`) + ' ' + err.message);
6
+ }
7
+ else if (err instanceof Error) {
8
+ console.error(chalk.red('Error:') + ' ' + err.message);
9
+ }
10
+ else {
11
+ console.error(chalk.red('An unexpected error occurred.'));
12
+ }
13
+ process.exit(1);
14
+ }
15
+ export function formatDate(iso) {
16
+ return new Date(iso).toLocaleString();
17
+ }
18
+ export function statusColor(status) {
19
+ switch (status) {
20
+ case 'success':
21
+ return chalk.green(status);
22
+ case 'failed':
23
+ return chalk.red(status);
24
+ case 'running':
25
+ return chalk.yellow(status);
26
+ case 'pending':
27
+ return chalk.gray(status);
28
+ default:
29
+ return status;
30
+ }
31
+ }
32
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEpC,MAAM,UAAU,WAAW,CAAC,GAAY;IACtC,IAAI,GAAG,YAAY,QAAQ,EAAE,CAAC;QAC5B,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,GAAG,CAAC,MAAM,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC;IACvE,CAAC;SAAM,IAAI,GAAG,YAAY,KAAK,EAAE,CAAC;QAChC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC;IACzD,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,OAAO,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,cAAc,EAAE,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAc;IACxC,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,SAAS;YACZ,OAAO,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC7B,KAAK,QAAQ;YACX,OAAO,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC3B,KAAK,SAAS;YACZ,OAAO,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC9B,KAAK,SAAS;YACZ,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC5B;YACE,OAAO,MAAM,CAAC;IAClB,CAAC;AACH,CAAC"}
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "@arnab-afk/zkm",
3
+ "version": "0.1.0",
4
+ "description": "ZkMultiCloud CLI — deploy any app to the cloud with a single command",
5
+ "keywords": ["zkmulticloud", "deploy", "cloud", "cli"],
6
+ "homepage": "https://github.com/zkmulticloud/zkmulticloud",
7
+ "license": "MIT",
8
+ "type": "module",
9
+ "bin": {
10
+ "zkm": "./dist/index.js"
11
+ },
12
+ "files": [
13
+ "dist"
14
+ ],
15
+ "scripts": {
16
+ "build": "tsc",
17
+ "dev": "tsc --watch",
18
+ "start": "node dist/index.js"
19
+ },
20
+ "dependencies": {
21
+ "chalk": "^5.3.0",
22
+ "commander": "^12.1.0",
23
+ "conf": "^13.0.1",
24
+ "inquirer": "^10.1.8",
25
+ "ora": "^8.1.0",
26
+ "table": "^6.8.1"
27
+ },
28
+ "devDependencies": {
29
+ "@types/node": "^20.12.0",
30
+ "typescript": "^5.4.0"
31
+ },
32
+ "engines": {
33
+ "node": ">=18.0.0"
34
+ }
35
+ }