@daileyos/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.
- package/dist/api.d.ts +12 -0
- package/dist/api.js +98 -0
- package/dist/api.js.map +1 -0
- package/dist/auth.d.ts +10 -0
- package/dist/auth.js +40 -0
- package/dist/auth.js.map +1 -0
- package/dist/commands/auth.d.ts +2 -0
- package/dist/commands/auth.js +106 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/billing.d.ts +2 -0
- package/dist/commands/billing.js +58 -0
- package/dist/commands/billing.js.map +1 -0
- package/dist/commands/db.d.ts +2 -0
- package/dist/commands/db.js +191 -0
- package/dist/commands/db.js.map +1 -0
- package/dist/commands/deploy.d.ts +2 -0
- package/dist/commands/deploy.js +72 -0
- package/dist/commands/deploy.js.map +1 -0
- package/dist/commands/domains.d.ts +2 -0
- package/dist/commands/domains.js +48 -0
- package/dist/commands/domains.js.map +1 -0
- package/dist/commands/env.d.ts +2 -0
- package/dist/commands/env.js +54 -0
- package/dist/commands/env.js.map +1 -0
- package/dist/commands/jobs.d.ts +2 -0
- package/dist/commands/jobs.js +160 -0
- package/dist/commands/jobs.js.map +1 -0
- package/dist/commands/open.d.ts +2 -0
- package/dist/commands/open.js +19 -0
- package/dist/commands/open.js.map +1 -0
- package/dist/commands/platform.d.ts +2 -0
- package/dist/commands/platform.js +57 -0
- package/dist/commands/platform.js.map +1 -0
- package/dist/commands/projects.d.ts +2 -0
- package/dist/commands/projects.js +91 -0
- package/dist/commands/projects.js.map +1 -0
- package/dist/commands/scale.d.ts +2 -0
- package/dist/commands/scale.js +39 -0
- package/dist/commands/scale.js.map +1 -0
- package/dist/commands/storage.d.ts +2 -0
- package/dist/commands/storage.js +128 -0
- package/dist/commands/storage.js.map +1 -0
- package/dist/commands/usage.d.ts +2 -0
- package/dist/commands/usage.js +25 -0
- package/dist/commands/usage.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +35 -0
- package/dist/index.js.map +1 -0
- package/dist/util.d.ts +26 -0
- package/dist/util.js +72 -0
- package/dist/util.js.map +1 -0
- package/package.json +27 -0
- package/src/api.ts +124 -0
- package/src/auth.ts +53 -0
- package/src/commands/auth.ts +117 -0
- package/src/commands/billing.ts +75 -0
- package/src/commands/db.ts +237 -0
- package/src/commands/deploy.ts +91 -0
- package/src/commands/domains.ts +62 -0
- package/src/commands/env.ts +69 -0
- package/src/commands/jobs.ts +287 -0
- package/src/commands/open.ts +22 -0
- package/src/commands/platform.ts +88 -0
- package/src/commands/projects.ts +115 -0
- package/src/commands/scale.ts +48 -0
- package/src/commands/storage.ts +214 -0
- package/src/commands/usage.ts +30 -0
- package/src/index.ts +39 -0
- package/src/util.ts +92 -0
- package/tsconfig.json +18 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scale.js","sourceRoot":"","sources":["../../src/commands/scale.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE1E,MAAM,UAAU,qBAAqB,CAAC,OAAgB;IACpD,OAAO;SACJ,OAAO,CAAC,6BAA6B,CAAC;SACtC,WAAW,CAAC,8BAA8B,CAAC;SAC3C,MAAM,CACL,gBAAgB,CAAC,KAAK,EAAE,QAAiB,EAAE,QAAiB,EAAE,EAAE;QAC9D,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;QACvD,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC;QAC7C,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YAC9B,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC,CAAC;YACrE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,OAAO,GAAG,GAAG,CAAC,YAAY,OAAO,CAAC,IAAI,QAAQ,KAAK,cAAc,CAAC,CAAC,KAAK,EAAE,CAAC;QACjF,MAAM,GAAG,CAAC,aAAa,OAAO,CAAC,EAAE,QAAQ,EAAE;YACzC,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE;SAC1B,CAAC,CAAC;QACH,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,OAAO,CAAC,IAAI,QAAQ,KAAK,YAAY,CAAC,CAAC,CAAC;IACjF,CAAC,CAAC,CACH,CAAC;IAEJ,OAAO;SACJ,OAAO,CAAC,mBAAmB,CAAC;SAC5B,WAAW,CAAC,0CAA0C,CAAC;SACvD,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC;SAClC,MAAM,CACL,gBAAgB,CAAC,KAAK,EAAE,QAAiB,EAAE,IAAwB,EAAE,EAAE;QACrE,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;QAEvD,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAE/B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,OAAO,CAAC,MAAM,IAAI,SAAS,EAAE,CAAC,CAAC;QAC5E,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,OAAO,CAAC,QAAQ,IAAI,KAAK,EAAE,CAAC,CAAC;QAC1E,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,OAAO,CAAC,GAAG,IAAI,KAAK,EAAE,CAAC,CAAC;QACrE,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACnB,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QACjE,CAAC;IACH,CAAC,CAAC,CACH,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import ora from 'ora';
|
|
3
|
+
import { api } from '../api.js';
|
|
4
|
+
import { formatTable, handleJson, resolveProject, withErrorHandler } from '../util.js';
|
|
5
|
+
export function registerStorageCommands(program) {
|
|
6
|
+
const storage = program.command('storage').description('Project-scoped object storage');
|
|
7
|
+
storage
|
|
8
|
+
.command('info <idOrName>')
|
|
9
|
+
.description('Show the storage binding for a project')
|
|
10
|
+
.option('--json', 'Output as JSON')
|
|
11
|
+
.action(withErrorHandler(async (idOrName, opts) => {
|
|
12
|
+
const project = await resolveProject(String(idOrName));
|
|
13
|
+
const spinner = opts.json ? null : ora('Loading storage binding...').start();
|
|
14
|
+
const data = await api(`/projects/${project.id}/storage`);
|
|
15
|
+
spinner?.stop();
|
|
16
|
+
handleJson(opts.json, data);
|
|
17
|
+
console.log(chalk.bold(`Storage: ${data.project.name}`));
|
|
18
|
+
console.log(chalk.gray(`${data.project.slug} • ${data.binding.bucket}\n`));
|
|
19
|
+
console.log(` ${chalk.blue('Provider:')} ${data.binding.provider}`);
|
|
20
|
+
console.log(` ${chalk.blue('Endpoint:')} ${data.binding.endpoint}`);
|
|
21
|
+
console.log(` ${chalk.blue('Region:')} ${data.binding.region}`);
|
|
22
|
+
console.log(` ${chalk.blue('Mode:')} ${data.binding.binding_model}`);
|
|
23
|
+
console.log(` ${chalk.blue('Upload:')} ${data.binding.upload_strategy}`);
|
|
24
|
+
console.log(` ${chalk.blue('Download:')} ${data.binding.download_strategy}`);
|
|
25
|
+
console.log(` ${chalk.blue('Objects:')} ${data.binding.usage.total_objects}`);
|
|
26
|
+
console.log(` ${chalk.blue('Usage:')} ${data.binding.usage.total_size_mb} MB / ${data.binding.usage.storage_limit_mb} MB`);
|
|
27
|
+
console.log(` ${chalk.blue('Max File:')} ${data.binding.limits.max_single_upload_mb} MB`);
|
|
28
|
+
console.log(` ${chalk.blue('TTL:')} ${data.binding.limits.signed_url_ttl_seconds}s`);
|
|
29
|
+
if (data.next_step) {
|
|
30
|
+
console.log(`\n${chalk.gray(data.next_step)}`);
|
|
31
|
+
}
|
|
32
|
+
}));
|
|
33
|
+
storage
|
|
34
|
+
.command('ls <idOrName> [prefix]')
|
|
35
|
+
.description('List objects in a project bucket')
|
|
36
|
+
.option('--limit <n>', 'Maximum number of objects to return', '100')
|
|
37
|
+
.option('--json', 'Output as JSON')
|
|
38
|
+
.action(withErrorHandler(async (idOrName, prefix, opts) => {
|
|
39
|
+
const project = await resolveProject(String(idOrName));
|
|
40
|
+
const spinner = opts.json ? null : ora('Listing storage objects...').start();
|
|
41
|
+
const params = {
|
|
42
|
+
limit: String(opts.limit || '100'),
|
|
43
|
+
};
|
|
44
|
+
if (prefix)
|
|
45
|
+
params.prefix = String(prefix);
|
|
46
|
+
const data = await api(`/projects/${project.id}/storage/objects`, { params });
|
|
47
|
+
spinner?.stop();
|
|
48
|
+
handleJson(opts.json, data);
|
|
49
|
+
console.log(chalk.bold(`Objects: ${project.name}`));
|
|
50
|
+
console.log(chalk.gray(`${data.bucket}${data.prefix ? ` • prefix ${data.prefix}` : ''}\n`));
|
|
51
|
+
console.log(formatTable(data.objects.map((object) => ({
|
|
52
|
+
key: object.key,
|
|
53
|
+
size: `${object.size_mb} MB`,
|
|
54
|
+
updated: object.last_modified ? new Date(object.last_modified).toLocaleString() : '-',
|
|
55
|
+
})), [
|
|
56
|
+
{ key: 'key', label: 'Key' },
|
|
57
|
+
{ key: 'size', label: 'Size' },
|
|
58
|
+
{ key: 'updated', label: 'Updated' },
|
|
59
|
+
]));
|
|
60
|
+
if (data.continuation_token) {
|
|
61
|
+
console.log(chalk.gray(`\nContinuation token available. Re-run with --json to fetch the next page.`));
|
|
62
|
+
}
|
|
63
|
+
}));
|
|
64
|
+
storage
|
|
65
|
+
.command('presign-upload <idOrName> <key>')
|
|
66
|
+
.description('Create a presigned upload URL for a project object')
|
|
67
|
+
.option('--content-type <type>', 'Content-Type to bind into the signed request')
|
|
68
|
+
.option('--size <bytes>', 'Expected content length in bytes')
|
|
69
|
+
.option('--ttl <seconds>', 'Signed URL TTL in seconds')
|
|
70
|
+
.option('--json', 'Output as JSON')
|
|
71
|
+
.action(withErrorHandler(async (idOrName, key, opts) => {
|
|
72
|
+
const project = await resolveProject(String(idOrName));
|
|
73
|
+
const spinner = opts.json ? null : ora('Creating upload URL...').start();
|
|
74
|
+
const body = { key: String(key) };
|
|
75
|
+
if (opts.contentType)
|
|
76
|
+
body.content_type = opts.contentType;
|
|
77
|
+
if (opts.size)
|
|
78
|
+
body.content_length_bytes = Number(opts.size);
|
|
79
|
+
if (opts.ttl)
|
|
80
|
+
body.expires_in_seconds = Number(opts.ttl);
|
|
81
|
+
const data = await api(`/projects/${project.id}/storage/presign-upload`, {
|
|
82
|
+
method: 'POST',
|
|
83
|
+
body,
|
|
84
|
+
});
|
|
85
|
+
spinner?.stop();
|
|
86
|
+
handleJson(opts.json, data);
|
|
87
|
+
console.log(chalk.bold('Presigned Upload URL'));
|
|
88
|
+
console.log(chalk.gray(`${data.bucket}/${data.key}\n`));
|
|
89
|
+
console.log(` ${chalk.blue('Method:')} ${data.method}`);
|
|
90
|
+
console.log(` ${chalk.blue('Expires:')} ${new Date(data.expires_at).toLocaleString()}`);
|
|
91
|
+
for (const [header, value] of Object.entries(data.headers || {})) {
|
|
92
|
+
console.log(` ${chalk.blue(header + ':')} ${value}`);
|
|
93
|
+
}
|
|
94
|
+
console.log(`\n${data.upload_url}`);
|
|
95
|
+
}));
|
|
96
|
+
storage
|
|
97
|
+
.command('presign-download <idOrName> <key>')
|
|
98
|
+
.description('Create a presigned download URL for a project object')
|
|
99
|
+
.option('--download-name <name>', 'Suggested filename for the download')
|
|
100
|
+
.option('--ttl <seconds>', 'Signed URL TTL in seconds')
|
|
101
|
+
.option('--json', 'Output as JSON')
|
|
102
|
+
.action(withErrorHandler(async (idOrName, key, opts) => {
|
|
103
|
+
const project = await resolveProject(String(idOrName));
|
|
104
|
+
const spinner = opts.json ? null : ora('Creating download URL...').start();
|
|
105
|
+
const body = { key: String(key) };
|
|
106
|
+
if (opts.downloadName)
|
|
107
|
+
body.download_name = opts.downloadName;
|
|
108
|
+
if (opts.ttl)
|
|
109
|
+
body.expires_in_seconds = Number(opts.ttl);
|
|
110
|
+
const data = await api(`/projects/${project.id}/storage/presign-download`, {
|
|
111
|
+
method: 'POST',
|
|
112
|
+
body,
|
|
113
|
+
});
|
|
114
|
+
spinner?.stop();
|
|
115
|
+
handleJson(opts.json, data);
|
|
116
|
+
console.log(chalk.bold('Presigned Download URL'));
|
|
117
|
+
console.log(chalk.gray(`${data.bucket}/${data.key}\n`));
|
|
118
|
+
console.log(` ${chalk.blue('Expires:')} ${new Date(data.expires_at).toLocaleString()}`);
|
|
119
|
+
if (data.content_type) {
|
|
120
|
+
console.log(` ${chalk.blue('Type:')} ${data.content_type}`);
|
|
121
|
+
}
|
|
122
|
+
if (data.size_bytes !== null) {
|
|
123
|
+
console.log(` ${chalk.blue('Size:')} ${data.size_bytes} bytes`);
|
|
124
|
+
}
|
|
125
|
+
console.log(`\n${data.download_url}`);
|
|
126
|
+
}));
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/commands/storage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import ora from 'ora';
|
|
3
|
+
import { api } from '../api.js';
|
|
4
|
+
import { resolveProject, handleJson, withErrorHandler } from '../util.js';
|
|
5
|
+
export function registerUsageCommands(program) {
|
|
6
|
+
program
|
|
7
|
+
.command('usage <idOrName>')
|
|
8
|
+
.description('Show resource usage')
|
|
9
|
+
.option('--period <period>', 'Time period (e.g., 7d, 30d)', '7d')
|
|
10
|
+
.option('--json', 'Output as JSON')
|
|
11
|
+
.action(withErrorHandler(async (idOrName, opts) => {
|
|
12
|
+
const project = await resolveProject(String(idOrName));
|
|
13
|
+
const spinner = ora('Fetching usage...').start();
|
|
14
|
+
const data = await api(`/projects/${project.id}/usage`, {
|
|
15
|
+
params: { period: opts.period },
|
|
16
|
+
});
|
|
17
|
+
spinner.stop();
|
|
18
|
+
handleJson(opts.json, data);
|
|
19
|
+
console.log(chalk.bold(`Usage for ${project.name} (${opts.period}):`));
|
|
20
|
+
for (const [key, value] of Object.entries(data)) {
|
|
21
|
+
console.log(` ${chalk.blue(key + ':')} ${value}`);
|
|
22
|
+
}
|
|
23
|
+
}));
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=usage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage.js","sourceRoot":"","sources":["../../src/commands/usage.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE1E,MAAM,UAAU,qBAAqB,CAAC,OAAgB;IACpD,OAAO;SACJ,OAAO,CAAC,kBAAkB,CAAC;SAC3B,WAAW,CAAC,qBAAqB,CAAC;SAClC,MAAM,CAAC,mBAAmB,EAAE,6BAA6B,EAAE,IAAI,CAAC;SAChE,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC;SAClC,MAAM,CACL,gBAAgB,CAAC,KAAK,EAAE,QAAiB,EAAE,IAAwC,EAAE,EAAE;QACrF,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;QACvD,MAAM,OAAO,GAAG,GAAG,CAAC,mBAAmB,CAAC,CAAC,KAAK,EAAE,CAAC;QACjD,MAAM,IAAI,GAAG,MAAM,GAAG,CAA0B,aAAa,OAAO,CAAC,EAAE,QAAQ,EAAE;YAC/E,MAAM,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE;SAChC,CAAC,CAAC;QACH,OAAO,CAAC,IAAI,EAAE,CAAC;QAEf,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAE5B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,OAAO,CAAC,IAAI,KAAK,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC;QACvE,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YAChD,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC;QACtD,CAAC;IACH,CAAC,CAAC,CACH,CAAC;AACN,CAAC"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } 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 { registerScaleCommands } from './commands/scale.js';
|
|
7
|
+
import { registerEnvCommands } from './commands/env.js';
|
|
8
|
+
import { registerDomainCommands } from './commands/domains.js';
|
|
9
|
+
import { registerDbCommands } from './commands/db.js';
|
|
10
|
+
import { registerUsageCommands } from './commands/usage.js';
|
|
11
|
+
import { registerBillingCommands } from './commands/billing.js';
|
|
12
|
+
import { registerOpenCommand } from './commands/open.js';
|
|
13
|
+
import { registerPlatformCommands } from './commands/platform.js';
|
|
14
|
+
import { registerStorageCommands } from './commands/storage.js';
|
|
15
|
+
import { registerJobCommands } from './commands/jobs.js';
|
|
16
|
+
const program = new Command();
|
|
17
|
+
program
|
|
18
|
+
.name('dailey')
|
|
19
|
+
.description('Dailey OS CLI — manage your projects, deployments, and billing')
|
|
20
|
+
.version('0.1.0');
|
|
21
|
+
registerAuthCommands(program);
|
|
22
|
+
registerProjectCommands(program);
|
|
23
|
+
registerDeployCommands(program);
|
|
24
|
+
registerScaleCommands(program);
|
|
25
|
+
registerEnvCommands(program);
|
|
26
|
+
registerDomainCommands(program);
|
|
27
|
+
registerDbCommands(program);
|
|
28
|
+
registerUsageCommands(program);
|
|
29
|
+
registerBillingCommands(program);
|
|
30
|
+
registerOpenCommand(program);
|
|
31
|
+
registerPlatformCommands(program);
|
|
32
|
+
registerStorageCommands(program);
|
|
33
|
+
registerJobCommands(program);
|
|
34
|
+
program.parse();
|
|
35
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,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,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,QAAQ,CAAC;KACd,WAAW,CAAC,gEAAgE,CAAC;KAC7E,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC9B,uBAAuB,CAAC,OAAO,CAAC,CAAC;AACjC,sBAAsB,CAAC,OAAO,CAAC,CAAC;AAChC,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC/B,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAC7B,sBAAsB,CAAC,OAAO,CAAC,CAAC;AAChC,kBAAkB,CAAC,OAAO,CAAC,CAAC;AAC5B,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC/B,uBAAuB,CAAC,OAAO,CAAC,CAAC;AACjC,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAC7B,wBAAwB,CAAC,OAAO,CAAC,CAAC;AAClC,uBAAuB,CAAC,OAAO,CAAC,CAAC;AACjC,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAE7B,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
package/dist/util.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
interface Project {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
slug?: string;
|
|
5
|
+
[key: string]: unknown;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Resolve a project identifier (UUID or name/slug) to a project object.
|
|
9
|
+
*/
|
|
10
|
+
export declare function resolveProject(idOrName: string): Promise<Project>;
|
|
11
|
+
/**
|
|
12
|
+
* Format an array of objects as an aligned table.
|
|
13
|
+
*/
|
|
14
|
+
export declare function formatTable(rows: Record<string, string>[], columns: {
|
|
15
|
+
key: string;
|
|
16
|
+
label: string;
|
|
17
|
+
}[]): string;
|
|
18
|
+
/**
|
|
19
|
+
* Handle --json flag: if set, print raw JSON and exit.
|
|
20
|
+
*/
|
|
21
|
+
export declare function handleJson(flag: boolean | undefined, data: unknown): void;
|
|
22
|
+
/**
|
|
23
|
+
* Wrap an async command handler with standard error handling.
|
|
24
|
+
*/
|
|
25
|
+
export declare function withErrorHandler<T extends (...args: any[]) => Promise<void>>(fn: T): T;
|
|
26
|
+
export {};
|
package/dist/util.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { api } from './api.js';
|
|
3
|
+
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
4
|
+
/**
|
|
5
|
+
* Resolve a project identifier (UUID or name/slug) to a project object.
|
|
6
|
+
*/
|
|
7
|
+
export async function resolveProject(idOrName) {
|
|
8
|
+
if (UUID_RE.test(idOrName)) {
|
|
9
|
+
return api(`/projects/${idOrName}`);
|
|
10
|
+
}
|
|
11
|
+
const { projects } = await api('/projects');
|
|
12
|
+
const lower = idOrName.toLowerCase();
|
|
13
|
+
const match = projects.find((p) => p.name.toLowerCase() === lower ||
|
|
14
|
+
(p.slug && p.slug.toLowerCase() === lower));
|
|
15
|
+
if (!match) {
|
|
16
|
+
console.error(chalk.red(`Project "${idOrName}" not found.`));
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
return match;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Format an array of objects as an aligned table.
|
|
23
|
+
*/
|
|
24
|
+
export function formatTable(rows, columns) {
|
|
25
|
+
if (rows.length === 0)
|
|
26
|
+
return chalk.gray(' No results.');
|
|
27
|
+
// Calculate column widths
|
|
28
|
+
const widths = {};
|
|
29
|
+
for (const col of columns) {
|
|
30
|
+
widths[col.key] = col.label.length;
|
|
31
|
+
}
|
|
32
|
+
for (const row of rows) {
|
|
33
|
+
for (const col of columns) {
|
|
34
|
+
const val = String(row[col.key] ?? '');
|
|
35
|
+
if (val.length > widths[col.key]) {
|
|
36
|
+
widths[col.key] = val.length;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const header = columns.map((c) => c.label.padEnd(widths[c.key])).join(' ');
|
|
41
|
+
const sep = columns.map((c) => '-'.repeat(widths[c.key])).join(' ');
|
|
42
|
+
const body = rows.map((row) => columns.map((c) => String(row[c.key] ?? '').padEnd(widths[c.key])).join(' '));
|
|
43
|
+
return [chalk.bold(header), chalk.gray(sep), ...body].join('\n');
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Handle --json flag: if set, print raw JSON and exit.
|
|
47
|
+
*/
|
|
48
|
+
export function handleJson(flag, data) {
|
|
49
|
+
if (flag) {
|
|
50
|
+
console.log(JSON.stringify(data, null, 2));
|
|
51
|
+
process.exit(0);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Wrap an async command handler with standard error handling.
|
|
56
|
+
*/
|
|
57
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
58
|
+
export function withErrorHandler(fn) {
|
|
59
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
60
|
+
const wrapped = async (...args) => {
|
|
61
|
+
try {
|
|
62
|
+
await fn(...args);
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
66
|
+
console.error(chalk.red(`Error: ${message}`));
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
return wrapped;
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=util.js.map
|
package/dist/util.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@daileyos/cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Dailey OS CLI",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"dailey": "./dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc",
|
|
11
|
+
"dev": "tsc --watch"
|
|
12
|
+
},
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"chalk": "^5.3.0",
|
|
15
|
+
"commander": "^12.1.0",
|
|
16
|
+
"conf": "^13.0.1",
|
|
17
|
+
"open": "^10.1.0",
|
|
18
|
+
"ora": "^8.1.1"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@types/node": "^20.14.0",
|
|
22
|
+
"typescript": "^5.5.0"
|
|
23
|
+
},
|
|
24
|
+
"publishConfig": {
|
|
25
|
+
"access": "public"
|
|
26
|
+
}
|
|
27
|
+
}
|
package/src/api.ts
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { getCredentialAuth, getToken } from './auth.js';
|
|
3
|
+
|
|
4
|
+
const BASE_URL = process.env.DAILEY_API_URL || 'https://os.dailey.cloud/api';
|
|
5
|
+
const AUTH_HINT = 'Run `dailey login`, or set `DAILEY_EMAIL` + `DAILEY_PASSWORD`, or set `DAILEY_API_TOKEN`.';
|
|
6
|
+
|
|
7
|
+
let currentToken = getToken();
|
|
8
|
+
|
|
9
|
+
interface ApiOptions {
|
|
10
|
+
method?: string;
|
|
11
|
+
body?: Record<string, unknown>;
|
|
12
|
+
params?: Record<string, string>;
|
|
13
|
+
requireAuth?: boolean;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export class ApiError extends Error {
|
|
17
|
+
status: number;
|
|
18
|
+
constructor(message: string, status: number) {
|
|
19
|
+
super(message);
|
|
20
|
+
this.status = status;
|
|
21
|
+
this.name = 'ApiError';
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async function refreshToken(): Promise<string> {
|
|
26
|
+
const credentials = getCredentialAuth();
|
|
27
|
+
if (!credentials) {
|
|
28
|
+
throw new Error('Cannot refresh token: `DAILEY_EMAIL` and `DAILEY_PASSWORD` are not both set.');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const res = await fetch(`${BASE_URL}/customers/login`, {
|
|
32
|
+
method: 'POST',
|
|
33
|
+
headers: { 'Content-Type': 'application/json' },
|
|
34
|
+
body: JSON.stringify(credentials),
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
if (!res.ok) {
|
|
38
|
+
throw new Error(`Token refresh failed (${res.status}): ${await res.text()}`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const data = await res.json() as { access_token?: string; token?: string };
|
|
42
|
+
currentToken = data.access_token || data.token || '';
|
|
43
|
+
|
|
44
|
+
if (!currentToken) {
|
|
45
|
+
throw new Error('Token refresh succeeded but no access token was returned.');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return currentToken;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export async function api<T = unknown>(path: string, opts: ApiOptions = {}): Promise<T> {
|
|
52
|
+
const { method = 'GET', body, params, requireAuth = true } = opts;
|
|
53
|
+
|
|
54
|
+
let url = `${BASE_URL}${path}`;
|
|
55
|
+
if (params) {
|
|
56
|
+
const qs = new URLSearchParams(params).toString();
|
|
57
|
+
url += `?${qs}`;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const makeRequest = async (token?: string): Promise<Response> => {
|
|
61
|
+
const headers: Record<string, string> = {
|
|
62
|
+
'Content-Type': 'application/json',
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
if (requireAuth && token) {
|
|
66
|
+
headers.Authorization = `Bearer ${token}`;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return fetch(url, {
|
|
70
|
+
method,
|
|
71
|
+
headers,
|
|
72
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
73
|
+
});
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
if (requireAuth && !currentToken && getCredentialAuth()) {
|
|
77
|
+
try {
|
|
78
|
+
await refreshToken();
|
|
79
|
+
} catch (err) {
|
|
80
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
81
|
+
console.error(chalk.red(`${message} ${AUTH_HINT}`));
|
|
82
|
+
process.exit(1);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (requireAuth && !currentToken) {
|
|
87
|
+
console.error(chalk.red(`Not logged in. ${AUTH_HINT}`));
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
let res = await makeRequest(currentToken);
|
|
92
|
+
|
|
93
|
+
if (requireAuth && res.status === 401 && getCredentialAuth()) {
|
|
94
|
+
try {
|
|
95
|
+
await refreshToken();
|
|
96
|
+
res = await makeRequest(currentToken);
|
|
97
|
+
} catch {
|
|
98
|
+
// If refresh fails, fall through to the normal expired-session path below.
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (requireAuth && res.status === 401) {
|
|
103
|
+
console.error(chalk.red(`Session expired. ${AUTH_HINT}`));
|
|
104
|
+
process.exit(1);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const text = await res.text();
|
|
108
|
+
let data: unknown;
|
|
109
|
+
try {
|
|
110
|
+
data = text ? JSON.parse(text) : {};
|
|
111
|
+
} catch {
|
|
112
|
+
data = { message: text };
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (!res.ok) {
|
|
116
|
+
const msg =
|
|
117
|
+
(data as Record<string, unknown>)?.error ||
|
|
118
|
+
(data as Record<string, unknown>)?.message ||
|
|
119
|
+
`HTTP ${res.status}`;
|
|
120
|
+
throw new ApiError(String(msg), res.status);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return data as T;
|
|
124
|
+
}
|
package/src/auth.ts
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import Conf from 'conf';
|
|
2
|
+
|
|
3
|
+
interface AuthConfig {
|
|
4
|
+
token?: string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
const config = new Conf<AuthConfig>({
|
|
8
|
+
projectName: 'dailey',
|
|
9
|
+
schema: {
|
|
10
|
+
token: {
|
|
11
|
+
type: 'string',
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
const ENV_TOKEN = process.env.DAILEY_API_TOKEN?.trim() || undefined;
|
|
17
|
+
const ENV_EMAIL = process.env.DAILEY_EMAIL?.trim() || undefined;
|
|
18
|
+
const ENV_PASSWORD = process.env.DAILEY_PASSWORD || undefined;
|
|
19
|
+
|
|
20
|
+
export function getToken(): string | undefined {
|
|
21
|
+
return ENV_TOKEN || config.get('token');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function getStoredToken(): string | undefined {
|
|
25
|
+
return config.get('token');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function setToken(token: string): void {
|
|
29
|
+
config.set('token', token);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function clearToken(): void {
|
|
33
|
+
config.delete('token');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function isLoggedIn(): boolean {
|
|
37
|
+
return !!(getToken() || getCredentialAuth());
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function getCredentialAuth(): { email: string; password: string } | undefined {
|
|
41
|
+
if (!ENV_EMAIL || !ENV_PASSWORD) {
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
email: ENV_EMAIL,
|
|
47
|
+
password: ENV_PASSWORD,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function hasEnvironmentAuth(): boolean {
|
|
52
|
+
return !!(ENV_TOKEN || getCredentialAuth());
|
|
53
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import ora from 'ora';
|
|
4
|
+
import { createInterface } from 'node:readline';
|
|
5
|
+
import { api } from '../api.js';
|
|
6
|
+
import { clearToken, hasEnvironmentAuth, isLoggedIn, setToken } from '../auth.js';
|
|
7
|
+
import { handleJson, withErrorHandler } from '../util.js';
|
|
8
|
+
|
|
9
|
+
function prompt(question: string, hidden = false): Promise<string> {
|
|
10
|
+
return new Promise((resolve) => {
|
|
11
|
+
const rl = createInterface({
|
|
12
|
+
input: process.stdin,
|
|
13
|
+
output: process.stdout,
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
if (hidden) {
|
|
17
|
+
// For password input, write prompt manually and mute output
|
|
18
|
+
process.stdout.write(question);
|
|
19
|
+
const stdin = process.stdin;
|
|
20
|
+
const wasRaw = stdin.isRaw;
|
|
21
|
+
if (stdin.isTTY) {
|
|
22
|
+
stdin.setRawMode(true);
|
|
23
|
+
}
|
|
24
|
+
let input = '';
|
|
25
|
+
const onData = (ch: Buffer) => {
|
|
26
|
+
const c = ch.toString();
|
|
27
|
+
if (c === '\n' || c === '\r') {
|
|
28
|
+
stdin.removeListener('data', onData);
|
|
29
|
+
if (stdin.isTTY && wasRaw !== undefined) {
|
|
30
|
+
stdin.setRawMode(wasRaw);
|
|
31
|
+
}
|
|
32
|
+
process.stdout.write('\n');
|
|
33
|
+
rl.close();
|
|
34
|
+
resolve(input);
|
|
35
|
+
} else if (c === '\u0003') {
|
|
36
|
+
process.exit(0);
|
|
37
|
+
} else if (c === '\u007f' || c === '\b') {
|
|
38
|
+
input = input.slice(0, -1);
|
|
39
|
+
} else {
|
|
40
|
+
input += c;
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
stdin.on('data', onData);
|
|
44
|
+
} else {
|
|
45
|
+
rl.question(question, (answer) => {
|
|
46
|
+
rl.close();
|
|
47
|
+
resolve(answer);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function registerAuthCommands(program: Command): void {
|
|
54
|
+
program
|
|
55
|
+
.command('login')
|
|
56
|
+
.description('Authenticate with email and password')
|
|
57
|
+
.action(
|
|
58
|
+
withErrorHandler(async () => {
|
|
59
|
+
const email = await prompt('Email: ');
|
|
60
|
+
const password = await prompt('Password: ', true);
|
|
61
|
+
|
|
62
|
+
const spinner = ora('Logging in...').start();
|
|
63
|
+
try {
|
|
64
|
+
const data = await api<{ access_token: string; token?: string }>('/customers/login', {
|
|
65
|
+
method: 'POST',
|
|
66
|
+
body: { email, password },
|
|
67
|
+
requireAuth: false,
|
|
68
|
+
});
|
|
69
|
+
setToken(data.access_token || data.token || '');
|
|
70
|
+
spinner.succeed(chalk.green('Logged in successfully.'));
|
|
71
|
+
} catch (err) {
|
|
72
|
+
spinner.fail(chalk.red('Login failed.'));
|
|
73
|
+
throw err;
|
|
74
|
+
}
|
|
75
|
+
}),
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
program
|
|
79
|
+
.command('logout')
|
|
80
|
+
.description('Clear stored credentials')
|
|
81
|
+
.action(
|
|
82
|
+
withErrorHandler(async () => {
|
|
83
|
+
clearToken();
|
|
84
|
+
if (hasEnvironmentAuth()) {
|
|
85
|
+
console.log(chalk.yellow('Stored token cleared. Environment-based auth is still configured.'));
|
|
86
|
+
console.log(chalk.gray('Unset `DAILEY_API_TOKEN` or `DAILEY_EMAIL` + `DAILEY_PASSWORD` to fully disable CLI auth.'));
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
console.log(chalk.green('Logged out.'));
|
|
91
|
+
}),
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
program
|
|
95
|
+
.command('whoami')
|
|
96
|
+
.description('Show current user info')
|
|
97
|
+
.option('--json', 'Output as JSON')
|
|
98
|
+
.action(
|
|
99
|
+
withErrorHandler(async (opts: { json?: boolean }) => {
|
|
100
|
+
if (!isLoggedIn()) {
|
|
101
|
+
console.error(chalk.red('Not logged in. Run `dailey login`, or set `DAILEY_EMAIL` + `DAILEY_PASSWORD`, or set `DAILEY_API_TOKEN`.'));
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const spinner = ora('Fetching profile...').start();
|
|
106
|
+
const user = await api<{ id: string; name: string; email: string; plan: string }>('/customers/me');
|
|
107
|
+
spinner.stop();
|
|
108
|
+
|
|
109
|
+
handleJson(opts.json, user);
|
|
110
|
+
|
|
111
|
+
console.log(chalk.bold('Logged in as:'));
|
|
112
|
+
console.log(` ${chalk.blue('Name:')} ${user.name}`);
|
|
113
|
+
console.log(` ${chalk.blue('Email:')} ${user.email}`);
|
|
114
|
+
console.log(` ${chalk.blue('Plan:')} ${user.plan}`);
|
|
115
|
+
}),
|
|
116
|
+
);
|
|
117
|
+
}
|