@agentuity/cli 0.0.53 → 0.0.55
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/cli.d.ts.map +1 -1
- package/dist/cli.js +66 -8
- package/dist/cli.js.map +1 -1
- package/dist/cmd/auth/ssh/add.d.ts.map +1 -1
- package/dist/cmd/auth/ssh/add.js +28 -13
- package/dist/cmd/auth/ssh/add.js.map +1 -1
- package/dist/cmd/auth/ssh/delete.d.ts.map +1 -1
- package/dist/cmd/auth/ssh/delete.js +28 -18
- package/dist/cmd/auth/ssh/delete.js.map +1 -1
- package/dist/cmd/auth/ssh/list.d.ts.map +1 -1
- package/dist/cmd/auth/ssh/list.js +5 -6
- package/dist/cmd/auth/ssh/list.js.map +1 -1
- package/dist/cmd/build/ast.d.ts +34 -0
- package/dist/cmd/build/ast.d.ts.map +1 -1
- package/dist/cmd/build/ast.js +165 -5
- package/dist/cmd/build/ast.js.map +1 -1
- package/dist/cmd/build/bundler.d.ts +2 -1
- package/dist/cmd/build/bundler.d.ts.map +1 -1
- package/dist/cmd/build/bundler.js +78 -17
- package/dist/cmd/build/bundler.js.map +1 -1
- package/dist/cmd/build/index.d.ts.map +1 -1
- package/dist/cmd/build/index.js +2 -0
- package/dist/cmd/build/index.js.map +1 -1
- package/dist/cmd/build/plugin.d.ts.map +1 -1
- package/dist/cmd/build/plugin.js +75 -7
- package/dist/cmd/build/plugin.js.map +1 -1
- package/dist/cmd/cloud/deployment/list.d.ts.map +1 -1
- package/dist/cmd/cloud/deployment/list.js +28 -23
- package/dist/cmd/cloud/deployment/list.js.map +1 -1
- package/dist/cmd/cloud/deployment/show.d.ts.map +1 -1
- package/dist/cmd/cloud/deployment/show.js +50 -47
- package/dist/cmd/cloud/deployment/show.js.map +1 -1
- package/dist/cmd/cloud/env/get.d.ts.map +1 -1
- package/dist/cmd/cloud/env/get.js +16 -14
- package/dist/cmd/cloud/env/get.js.map +1 -1
- package/dist/cmd/cloud/env/list.d.ts.map +1 -1
- package/dist/cmd/cloud/env/list.js +24 -20
- package/dist/cmd/cloud/env/list.js.map +1 -1
- package/dist/cmd/cloud/keyvalue/get.d.ts.map +1 -1
- package/dist/cmd/cloud/keyvalue/get.js +18 -16
- package/dist/cmd/cloud/keyvalue/get.js.map +1 -1
- package/dist/cmd/cloud/keyvalue/keys.d.ts.map +1 -1
- package/dist/cmd/cloud/keyvalue/keys.js +11 -11
- package/dist/cmd/cloud/keyvalue/keys.js.map +1 -1
- package/dist/cmd/cloud/keyvalue/list-namespaces.d.ts.map +1 -1
- package/dist/cmd/cloud/keyvalue/list-namespaces.js +11 -7
- package/dist/cmd/cloud/keyvalue/list-namespaces.js.map +1 -1
- package/dist/cmd/cloud/keyvalue/search.d.ts.map +1 -1
- package/dist/cmd/cloud/keyvalue/search.js +16 -17
- package/dist/cmd/cloud/keyvalue/search.js.map +1 -1
- package/dist/cmd/cloud/keyvalue/stats.d.ts.map +1 -1
- package/dist/cmd/cloud/keyvalue/stats.js +38 -23
- package/dist/cmd/cloud/keyvalue/stats.js.map +1 -1
- package/dist/cmd/cloud/objectstore/get.d.ts.map +1 -1
- package/dist/cmd/cloud/objectstore/get.js +17 -15
- package/dist/cmd/cloud/objectstore/get.js.map +1 -1
- package/dist/cmd/cloud/objectstore/list-buckets.d.ts.map +1 -1
- package/dist/cmd/cloud/objectstore/list-buckets.js +12 -8
- package/dist/cmd/cloud/objectstore/list-buckets.js.map +1 -1
- package/dist/cmd/cloud/objectstore/list-keys.d.ts.map +1 -1
- package/dist/cmd/cloud/objectstore/list-keys.js +13 -10
- package/dist/cmd/cloud/objectstore/list-keys.js.map +1 -1
- package/dist/cmd/cloud/resource/list.d.ts.map +1 -1
- package/dist/cmd/cloud/resource/list.js +38 -27
- package/dist/cmd/cloud/resource/list.js.map +1 -1
- package/dist/cmd/cloud/secret/get.d.ts.map +1 -1
- package/dist/cmd/cloud/secret/get.js +17 -15
- package/dist/cmd/cloud/secret/get.js.map +1 -1
- package/dist/cmd/cloud/secret/list.d.ts.map +1 -1
- package/dist/cmd/cloud/secret/list.js +24 -20
- package/dist/cmd/cloud/secret/list.js.map +1 -1
- package/dist/cmd/cloud/session/logs.d.ts.map +1 -1
- package/dist/cmd/cloud/session/logs.js +18 -15
- package/dist/cmd/cloud/session/logs.js.map +1 -1
- package/dist/cmd/dev/agents.d.ts.map +1 -1
- package/dist/cmd/dev/agents.js +55 -41
- package/dist/cmd/dev/agents.js.map +1 -1
- package/dist/cmd/dev/index.d.ts.map +1 -1
- package/dist/cmd/dev/index.js +34 -14
- package/dist/cmd/dev/index.js.map +1 -1
- package/dist/cmd/profile/create.js +1 -1
- package/dist/cmd/profile/create.js.map +1 -1
- package/dist/cmd/profile/delete.d.ts.map +1 -1
- package/dist/cmd/profile/delete.js +1 -1
- package/dist/cmd/profile/delete.js.map +1 -1
- package/dist/cmd/profile/list.d.ts.map +1 -1
- package/dist/cmd/profile/list.js +29 -11
- package/dist/cmd/profile/list.js.map +1 -1
- package/dist/cmd/profile/show.d.ts.map +1 -1
- package/dist/cmd/profile/show.js +7 -10
- package/dist/cmd/profile/show.js.map +1 -1
- package/dist/cmd/project/delete.js +1 -1
- package/dist/cmd/project/delete.js.map +1 -1
- package/dist/cmd/version/index.d.ts.map +1 -1
- package/dist/cmd/version/index.js +1 -1
- package/dist/cmd/version/index.js.map +1 -1
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +3 -1
- package/dist/tui.js.map +1 -1
- package/dist/types.d.ts +32 -8
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +3 -3
- package/src/cli.ts +109 -8
- package/src/cmd/auth/ssh/add.ts +37 -17
- package/src/cmd/auth/ssh/delete.ts +36 -23
- package/src/cmd/auth/ssh/list.ts +8 -6
- package/src/cmd/build/ast.ts +209 -5
- package/src/cmd/build/bundler.ts +82 -16
- package/src/cmd/build/index.ts +2 -0
- package/src/cmd/build/plugin.ts +93 -7
- package/src/cmd/cloud/deployment/list.ts +30 -26
- package/src/cmd/cloud/deployment/show.ts +47 -42
- package/src/cmd/cloud/env/get.ts +14 -12
- package/src/cmd/cloud/env/list.ts +24 -22
- package/src/cmd/cloud/keyvalue/get.ts +19 -14
- package/src/cmd/cloud/keyvalue/keys.ts +10 -12
- package/src/cmd/cloud/keyvalue/list-namespaces.ts +10 -8
- package/src/cmd/cloud/keyvalue/search.ts +14 -17
- package/src/cmd/cloud/keyvalue/stats.ts +52 -28
- package/src/cmd/cloud/objectstore/get.ts +18 -13
- package/src/cmd/cloud/objectstore/list-buckets.ts +11 -9
- package/src/cmd/cloud/objectstore/list-keys.ts +12 -11
- package/src/cmd/cloud/resource/list.ts +33 -23
- package/src/cmd/cloud/secret/get.ts +15 -13
- package/src/cmd/cloud/secret/list.ts +24 -22
- package/src/cmd/cloud/session/logs.ts +18 -17
- package/src/cmd/dev/agents.ts +70 -50
- package/src/cmd/dev/index.ts +41 -14
- package/src/cmd/profile/create.ts +3 -3
- package/src/cmd/profile/delete.ts +5 -2
- package/src/cmd/profile/list.ts +31 -11
- package/src/cmd/profile/show.ts +15 -12
- package/src/cmd/project/delete.ts +1 -1
- package/src/cmd/version/index.ts +5 -1
- package/src/tui.ts +3 -1
- package/src/types.ts +32 -10
|
@@ -42,63 +42,68 @@ export const showSubcommand = createSubcommand({
|
|
|
42
42
|
idempotent: true,
|
|
43
43
|
async handler(ctx) {
|
|
44
44
|
const projectId = resolveProjectId(ctx, { projectId: ctx.opts['project-id'] });
|
|
45
|
-
const { apiClient, args } = ctx;
|
|
45
|
+
const { apiClient, args, options } = ctx;
|
|
46
46
|
|
|
47
47
|
try {
|
|
48
48
|
const deployment = await projectDeploymentGet(apiClient, projectId, args.deployment_id);
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
// Skip TUI output in JSON mode
|
|
51
|
+
if (!options.json) {
|
|
52
|
+
tui.banner(`Deployment ${deployment.id}`, `State: ${deployment.state || 'unknown'}`);
|
|
51
53
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
54
|
+
console.log(tui.bold('ID: ') + deployment.id);
|
|
55
|
+
console.log(tui.bold('Project: ') + projectId);
|
|
56
|
+
console.log(tui.bold('State: ') + (deployment.state || 'unknown'));
|
|
57
|
+
console.log(tui.bold('Active: ') + (deployment.active ? 'Yes' : 'No'));
|
|
58
|
+
console.log(tui.bold('Created: ') + new Date(deployment.createdAt).toLocaleString());
|
|
59
|
+
if (deployment.updatedAt) {
|
|
60
|
+
console.log(
|
|
61
|
+
tui.bold('Updated: ') + new Date(deployment.updatedAt).toLocaleString()
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
if (deployment.message) {
|
|
65
|
+
console.log(tui.bold('Message: ') + deployment.message);
|
|
66
|
+
}
|
|
67
|
+
if (deployment.tags.length > 0) {
|
|
68
|
+
console.log(tui.bold('Tags: ') + deployment.tags.join(', '));
|
|
69
|
+
}
|
|
70
|
+
if (deployment.customDomains && deployment.customDomains.length > 0) {
|
|
71
|
+
console.log(tui.bold('Domains: ') + deployment.customDomains.join(', '));
|
|
72
|
+
}
|
|
73
|
+
if (deployment.cloudRegion) {
|
|
74
|
+
console.log(tui.bold('Region: ') + deployment.cloudRegion);
|
|
75
|
+
}
|
|
72
76
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
77
|
+
// Metadata
|
|
78
|
+
const origin = deployment.metadata?.origin;
|
|
79
|
+
if (origin?.commit) {
|
|
80
|
+
tui.newline();
|
|
81
|
+
tui.info('Origin Information');
|
|
82
|
+
if (origin.trigger) console.log(` Trigger: ${origin.trigger}`);
|
|
83
|
+
if (origin.provider) console.log(` Provider: ${origin.provider}`);
|
|
84
|
+
if (origin.event) console.log(` Event: ${origin.event}`);
|
|
85
|
+
if (origin.branch) console.log(` Branch: ${origin.branch}`);
|
|
82
86
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
87
|
+
if (origin.commit) {
|
|
88
|
+
console.log(` Commit: ${origin.commit.hash}`);
|
|
89
|
+
if (origin.commit.message) console.log(` Message: ${origin.commit.message}`);
|
|
90
|
+
if (origin.commit.author?.name)
|
|
91
|
+
console.log(` Author: ${origin.commit.author.name}`);
|
|
92
|
+
}
|
|
88
93
|
}
|
|
89
94
|
}
|
|
90
95
|
|
|
91
96
|
return {
|
|
92
97
|
id: deployment.id,
|
|
93
|
-
state: deployment.state,
|
|
98
|
+
state: deployment.state ?? undefined,
|
|
94
99
|
active: deployment.active,
|
|
95
100
|
createdAt: deployment.createdAt,
|
|
96
|
-
updatedAt: deployment.updatedAt,
|
|
97
|
-
message: deployment.message,
|
|
101
|
+
updatedAt: deployment.updatedAt ?? undefined,
|
|
102
|
+
message: deployment.message ?? undefined,
|
|
98
103
|
tags: deployment.tags,
|
|
99
|
-
customDomains: deployment.customDomains,
|
|
100
|
-
cloudRegion: deployment.cloudRegion,
|
|
101
|
-
metadata: deployment.metadata,
|
|
104
|
+
customDomains: deployment.customDomains ?? undefined,
|
|
105
|
+
cloudRegion: deployment.cloudRegion ?? undefined,
|
|
106
|
+
metadata: deployment.metadata ?? undefined,
|
|
102
107
|
};
|
|
103
108
|
} catch (ex) {
|
|
104
109
|
tui.fatal(`Failed to show deployment: ${ex instanceof Error ? ex.message : String(ex)}`);
|
package/src/cmd/cloud/env/get.ts
CHANGED
|
@@ -32,7 +32,7 @@ export const getSubcommand = createSubcommand({
|
|
|
32
32
|
idempotent: true,
|
|
33
33
|
|
|
34
34
|
async handler(ctx) {
|
|
35
|
-
const { args, opts, apiClient, project } = ctx;
|
|
35
|
+
const { args, opts, apiClient, project, options } = ctx;
|
|
36
36
|
|
|
37
37
|
// Fetch project with unmasked secrets
|
|
38
38
|
const projectData = await tui.spinner('Fetching environment variables', () => {
|
|
@@ -46,18 +46,20 @@ export const getSubcommand = createSubcommand({
|
|
|
46
46
|
tui.fatal(`Environment variable '${args.key}' not found`, ErrorCode.RESOURCE_NOT_FOUND);
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
if (
|
|
52
|
-
|
|
49
|
+
if (!options.json) {
|
|
50
|
+
// Display the value, masked if requested
|
|
51
|
+
if (process.stdout.isTTY) {
|
|
52
|
+
if (opts?.mask) {
|
|
53
|
+
tui.success(`${args.key}=${maskSecret(value)}`);
|
|
54
|
+
} else {
|
|
55
|
+
tui.success(`${args.key}=${value}`);
|
|
56
|
+
}
|
|
53
57
|
} else {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
} else {
|
|
60
|
-
console.log(`${args.key}=${value}`);
|
|
58
|
+
if (opts?.mask) {
|
|
59
|
+
console.log(`${args.key}=${maskSecret(value)}`);
|
|
60
|
+
} else {
|
|
61
|
+
console.log(`${args.key}=${value}`);
|
|
62
|
+
}
|
|
61
63
|
}
|
|
62
64
|
}
|
|
63
65
|
|
|
@@ -29,7 +29,7 @@ export const listSubcommand = createSubcommand({
|
|
|
29
29
|
},
|
|
30
30
|
|
|
31
31
|
async handler(ctx) {
|
|
32
|
-
const { opts, apiClient, project } = ctx;
|
|
32
|
+
const { opts, apiClient, project, options } = ctx;
|
|
33
33
|
|
|
34
34
|
// Fetch project with unmasked secrets
|
|
35
35
|
const projectData = await tui.spinner('Fetching environment variables', () => {
|
|
@@ -38,28 +38,30 @@ export const listSubcommand = createSubcommand({
|
|
|
38
38
|
|
|
39
39
|
const env = projectData.env || {};
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
// Display the variables
|
|
47
|
-
if (process.stdout.isTTY) {
|
|
48
|
-
tui.newline();
|
|
49
|
-
tui.info(`Environment Variables (${Object.keys(env).length}):`);
|
|
50
|
-
tui.newline();
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const sortedKeys = Object.keys(env).sort();
|
|
54
|
-
// For env vars, masking should be explicitly opted-in (default false)
|
|
55
|
-
const shouldMask = opts?.mask === true;
|
|
56
|
-
for (const key of sortedKeys) {
|
|
57
|
-
const value = env[key];
|
|
58
|
-
const displayValue = shouldMask ? maskSecret(value) : value;
|
|
59
|
-
if (process.stdout.isTTY) {
|
|
60
|
-
console.log(`${tui.bold(key)}=${displayValue}`);
|
|
41
|
+
// Skip TUI output in JSON mode
|
|
42
|
+
if (!options.json) {
|
|
43
|
+
if (Object.keys(env).length === 0) {
|
|
44
|
+
tui.info('No environment variables found');
|
|
61
45
|
} else {
|
|
62
|
-
|
|
46
|
+
// Display the variables
|
|
47
|
+
if (process.stdout.isTTY) {
|
|
48
|
+
tui.newline();
|
|
49
|
+
tui.info(`Environment Variables (${Object.keys(env).length}):`);
|
|
50
|
+
tui.newline();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const sortedKeys = Object.keys(env).sort();
|
|
54
|
+
// For env vars, masking should be explicitly opted-in (default false)
|
|
55
|
+
const shouldMask = opts?.mask === true;
|
|
56
|
+
for (const key of sortedKeys) {
|
|
57
|
+
const value = env[key];
|
|
58
|
+
const displayValue = shouldMask ? maskSecret(value) : value;
|
|
59
|
+
if (process.stdout.isTTY) {
|
|
60
|
+
console.log(`${tui.bold(key)}=${displayValue}`);
|
|
61
|
+
} else {
|
|
62
|
+
console.log(`${key}=${displayValue}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
63
65
|
}
|
|
64
66
|
}
|
|
65
67
|
|
|
@@ -31,27 +31,32 @@ export const getSubcommand = createCommand({
|
|
|
31
31
|
idempotent: true,
|
|
32
32
|
|
|
33
33
|
async handler(ctx) {
|
|
34
|
-
const { args } = ctx;
|
|
34
|
+
const { args, options } = ctx;
|
|
35
35
|
const storage = await createStorageAdapter(ctx);
|
|
36
36
|
const started = Date.now();
|
|
37
37
|
const res = await storage.get(args.namespace, args.key);
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
38
|
+
|
|
39
|
+
if (!options.json) {
|
|
40
|
+
if (res.exists) {
|
|
41
|
+
if (res.data) {
|
|
42
|
+
if (res.contentType?.includes('json')) {
|
|
43
|
+
const val = tryParseJSON(res.data as unknown as string);
|
|
44
|
+
tui.json(val);
|
|
45
|
+
} else if (res.contentType?.includes('text')) {
|
|
46
|
+
console.log(String(res.data));
|
|
47
|
+
} else {
|
|
48
|
+
const b = res.data as ArrayBuffer;
|
|
49
|
+
tui.info(`Read ${b.byteLength} bytes (${res.contentType})`);
|
|
50
|
+
}
|
|
51
|
+
tui.success(
|
|
52
|
+
`retrieved in ${(Date.now() - started).toFixed(1)}ms (${res.contentType})`
|
|
53
|
+
);
|
|
45
54
|
} else {
|
|
46
|
-
|
|
47
|
-
tui.info(`Read ${b.byteLength} bytes (${res.contentType})`);
|
|
55
|
+
tui.warning(`${args.key} returned empty data for ${args.namespace}`);
|
|
48
56
|
}
|
|
49
|
-
tui.success(`retrieved in ${(Date.now() - started).toFixed(1)}ms (${res.contentType})`);
|
|
50
57
|
} else {
|
|
51
|
-
tui.warning(`${args.key}
|
|
58
|
+
tui.warning(`${args.key} does not exist in ${args.namespace}`);
|
|
52
59
|
}
|
|
53
|
-
} else {
|
|
54
|
-
tui.warning(`${args.key} does not exist in ${args.namespace}`);
|
|
55
60
|
}
|
|
56
61
|
|
|
57
62
|
return {
|
|
@@ -29,22 +29,20 @@ export const keysSubcommand = createCommand({
|
|
|
29
29
|
},
|
|
30
30
|
|
|
31
31
|
async handler(ctx) {
|
|
32
|
-
const { args } = ctx;
|
|
32
|
+
const { args, options } = ctx;
|
|
33
33
|
const kv = await createStorageAdapter(ctx);
|
|
34
34
|
|
|
35
35
|
const keys = await kv.getKeys(args.name);
|
|
36
36
|
|
|
37
|
-
if (
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
keys
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
for (const key of keys) {
|
|
47
|
-
tui.info(` ${key}`);
|
|
37
|
+
if (!options.json) {
|
|
38
|
+
if (keys.length === 0) {
|
|
39
|
+
tui.info(`No keys found in namespace ${tui.bold(args.name)}`);
|
|
40
|
+
} else {
|
|
41
|
+
tui.info(`Found ${keys.length} key(s) in ${tui.bold(args.name)}:`);
|
|
42
|
+
for (const key of keys) {
|
|
43
|
+
tui.info(` ${key}`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
48
46
|
}
|
|
49
47
|
|
|
50
48
|
return {
|
|
@@ -23,17 +23,19 @@ export const listNamespacesSubcommand = createCommand({
|
|
|
23
23
|
idempotent: true,
|
|
24
24
|
|
|
25
25
|
async handler(ctx) {
|
|
26
|
+
const { options } = ctx;
|
|
26
27
|
const storage = await createStorageAdapter(ctx);
|
|
27
28
|
const namespaces = await storage.getNamespaces();
|
|
28
29
|
|
|
29
|
-
if (
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
30
|
+
if (!options.json) {
|
|
31
|
+
if (namespaces.length === 0) {
|
|
32
|
+
tui.info('No namespaces found');
|
|
33
|
+
} else {
|
|
34
|
+
tui.info(`Found ${namespaces.length} namespace(s):`);
|
|
35
|
+
for (const name of namespaces) {
|
|
36
|
+
tui.arrow(name);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
37
39
|
}
|
|
38
40
|
|
|
39
41
|
return namespaces;
|
|
@@ -37,28 +37,25 @@ export const searchSubcommand = createCommand({
|
|
|
37
37
|
},
|
|
38
38
|
|
|
39
39
|
async handler(ctx) {
|
|
40
|
-
const { args } = ctx;
|
|
40
|
+
const { args, options } = ctx;
|
|
41
41
|
const kv = await createStorageAdapter(ctx);
|
|
42
42
|
|
|
43
43
|
const results = await kv.search(args.name, args.keyword);
|
|
44
44
|
const keys = Object.keys(results);
|
|
45
45
|
|
|
46
|
-
if (
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
const sizeMB = (item.size / (1024 * 1024)).toFixed(2);
|
|
60
|
-
const date = new Date(item.updated_at).toLocaleString();
|
|
61
|
-
tui.info(` ${tui.bold(key)}: ${sizeMB} MB, ${item.contentType}, updated ${date}`);
|
|
46
|
+
if (!options.json) {
|
|
47
|
+
if (keys.length === 0) {
|
|
48
|
+
tui.info(`No keys found matching ${tui.bold(args.keyword)} in ${tui.bold(args.name)}`);
|
|
49
|
+
} else {
|
|
50
|
+
tui.info(`Found ${keys.length} key(s) matching ${tui.bold(args.keyword)}:`);
|
|
51
|
+
for (const key of keys) {
|
|
52
|
+
const item = results[key];
|
|
53
|
+
if (!item) continue;
|
|
54
|
+
const sizeMB = (item.size / (1024 * 1024)).toFixed(2);
|
|
55
|
+
const date = new Date(item.updated_at).toLocaleString();
|
|
56
|
+
tui.info(` ${tui.bold(key)}: ${sizeMB} MB, ${item.contentType}, updated ${date}`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
62
59
|
}
|
|
63
60
|
|
|
64
61
|
return {
|
|
@@ -42,53 +42,77 @@ export const statsSubcommand = createCommand({
|
|
|
42
42
|
},
|
|
43
43
|
|
|
44
44
|
async handler(ctx) {
|
|
45
|
-
const { args } = ctx;
|
|
45
|
+
const { args, options } = ctx;
|
|
46
46
|
const kv = await createStorageAdapter(ctx);
|
|
47
47
|
|
|
48
48
|
if (args.name) {
|
|
49
49
|
const stats = await kv.getStats(args.name);
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
stats.
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
tui.info(`
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
50
|
+
|
|
51
|
+
if (!options.json) {
|
|
52
|
+
tui.info(`Statistics for ${tui.bold(args.name)}:`);
|
|
53
|
+
tui.info(` Keys: ${stats.count}`);
|
|
54
|
+
const sizeDisplay =
|
|
55
|
+
stats.sum < 1024 * 1024
|
|
56
|
+
? `${stats.sum.toLocaleString()} bytes`
|
|
57
|
+
: `${(stats.sum / (1024 * 1024)).toFixed(2)} MB`;
|
|
58
|
+
tui.info(` Total size: ${sizeDisplay} (raw: ${stats.sum})`);
|
|
59
|
+
if (stats.createdAt) {
|
|
60
|
+
tui.info(` Created: ${new Date(stats.createdAt).toLocaleString()}`);
|
|
61
|
+
}
|
|
62
|
+
if (stats.lastUsedAt) {
|
|
63
|
+
tui.info(` Last used: ${new Date(stats.lastUsedAt).toLocaleString()}`);
|
|
64
|
+
}
|
|
62
65
|
}
|
|
63
66
|
|
|
64
67
|
return {
|
|
65
68
|
namespace: args.name,
|
|
66
69
|
count: stats.count,
|
|
67
70
|
sum: stats.sum,
|
|
68
|
-
createdAt: stats.createdAt,
|
|
69
|
-
lastUsedAt: stats.lastUsedAt,
|
|
71
|
+
createdAt: stats.createdAt ? String(stats.createdAt) : undefined,
|
|
72
|
+
lastUsedAt: stats.lastUsedAt ? String(stats.lastUsedAt) : undefined,
|
|
70
73
|
};
|
|
71
74
|
} else {
|
|
72
75
|
const allStats = await kv.getAllStats();
|
|
73
76
|
const entries = Object.entries(allStats);
|
|
74
77
|
|
|
75
|
-
if (
|
|
76
|
-
|
|
77
|
-
|
|
78
|
+
if (!options.json) {
|
|
79
|
+
if (entries.length === 0) {
|
|
80
|
+
tui.info('No namespaces found');
|
|
81
|
+
} else {
|
|
82
|
+
tui.info(
|
|
83
|
+
`Found ${entries.length} ${tui.plural(entries.length, 'namespace', 'namespaces')}:`
|
|
84
|
+
);
|
|
85
|
+
for (const [name, stats] of entries) {
|
|
86
|
+
const sizeDisplay =
|
|
87
|
+
stats.sum < 1024 * 1024
|
|
88
|
+
? `${stats.sum.toLocaleString()} bytes`
|
|
89
|
+
: `${(stats.sum / (1024 * 1024)).toFixed(2)} MB`;
|
|
90
|
+
tui.arrow(
|
|
91
|
+
`${tui.bold(name.padEnd(15, ' '))}: ${stats.count} keys, ${sizeDisplay}`
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
78
95
|
}
|
|
79
96
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
97
|
+
// Convert timestamp fields to strings
|
|
98
|
+
const result: Record<
|
|
99
|
+
string,
|
|
100
|
+
{
|
|
101
|
+
count: number;
|
|
102
|
+
sum: number;
|
|
103
|
+
createdAt?: string;
|
|
104
|
+
lastUsedAt?: string;
|
|
105
|
+
}
|
|
106
|
+
> = {};
|
|
83
107
|
for (const [name, stats] of entries) {
|
|
84
|
-
|
|
85
|
-
stats.
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
108
|
+
result[name] = {
|
|
109
|
+
count: stats.count,
|
|
110
|
+
sum: stats.sum,
|
|
111
|
+
createdAt: stats.createdAt ? String(stats.createdAt) : undefined,
|
|
112
|
+
lastUsedAt: stats.lastUsedAt ? String(stats.lastUsedAt) : undefined,
|
|
113
|
+
};
|
|
89
114
|
}
|
|
90
|
-
|
|
91
|
-
return allStats;
|
|
115
|
+
return result;
|
|
92
116
|
}
|
|
93
117
|
},
|
|
94
118
|
});
|
|
@@ -31,26 +31,31 @@ export const getSubcommand = createCommand({
|
|
|
31
31
|
idempotent: true,
|
|
32
32
|
|
|
33
33
|
async handler(ctx) {
|
|
34
|
-
const { args } = ctx;
|
|
34
|
+
const { args, options } = ctx;
|
|
35
35
|
const storage = await createStorageAdapter(ctx);
|
|
36
36
|
const started = Date.now();
|
|
37
37
|
const res = await storage.get(args.bucket, args.key);
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
38
|
+
|
|
39
|
+
if (!options.json) {
|
|
40
|
+
if (res.exists) {
|
|
41
|
+
if (res.data) {
|
|
42
|
+
if (res.contentType?.includes('json')) {
|
|
43
|
+
const val = tryParseJSON(new TextDecoder().decode(res.data));
|
|
44
|
+
tui.json(val);
|
|
45
|
+
} else if (res.contentType?.includes('text')) {
|
|
46
|
+
console.log(new TextDecoder().decode(res.data));
|
|
47
|
+
} else {
|
|
48
|
+
tui.info(`Read ${res.data.byteLength} bytes (${res.contentType})`);
|
|
49
|
+
}
|
|
50
|
+
tui.success(
|
|
51
|
+
`retrieved in ${(Date.now() - started).toFixed(1)}ms (${res.contentType})`
|
|
52
|
+
);
|
|
45
53
|
} else {
|
|
46
|
-
tui.
|
|
54
|
+
tui.warning(`${args.key} returned empty data for bucket ${args.bucket}`);
|
|
47
55
|
}
|
|
48
|
-
tui.success(`retrieved in ${(Date.now() - started).toFixed(1)}ms (${res.contentType})`);
|
|
49
56
|
} else {
|
|
50
|
-
tui.warning(`${args.key}
|
|
57
|
+
tui.warning(`${args.key} does not exist in bucket ${args.bucket}`);
|
|
51
58
|
}
|
|
52
|
-
} else {
|
|
53
|
-
tui.warning(`${args.key} does not exist in bucket ${args.bucket}`);
|
|
54
59
|
}
|
|
55
60
|
|
|
56
61
|
return {
|
|
@@ -24,18 +24,20 @@ export const listBucketsSubcommand = createCommand({
|
|
|
24
24
|
examples: [`${getCommand('objectstore list-buckets')} - List all buckets with stats`],
|
|
25
25
|
|
|
26
26
|
async handler(ctx) {
|
|
27
|
+
const { options } = ctx;
|
|
27
28
|
const storage = await createStorageAdapter(ctx);
|
|
28
29
|
const buckets = await storage.listBuckets();
|
|
29
30
|
|
|
30
|
-
if (
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
31
|
+
if (!options.json) {
|
|
32
|
+
if (buckets.length === 0) {
|
|
33
|
+
tui.info('No buckets found');
|
|
34
|
+
} else {
|
|
35
|
+
tui.info(`Found ${buckets.length} bucket(s):`);
|
|
36
|
+
for (const bucket of buckets) {
|
|
37
|
+
const sizeMB = (bucket.total_bytes / (1024 * 1024)).toFixed(2);
|
|
38
|
+
tui.info(` ${tui.bold(bucket.name)}: ${bucket.object_count} objects, ${sizeMB} MB`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
39
41
|
}
|
|
40
42
|
|
|
41
43
|
return buckets;
|
|
@@ -36,21 +36,22 @@ export const listKeysSubcommand = createCommand({
|
|
|
36
36
|
},
|
|
37
37
|
|
|
38
38
|
async handler(ctx) {
|
|
39
|
-
const { args } = ctx;
|
|
39
|
+
const { args, options } = ctx;
|
|
40
40
|
const objectStore = await createStorageAdapter(ctx);
|
|
41
41
|
|
|
42
42
|
const objects = await objectStore.listKeys(args.bucket);
|
|
43
43
|
|
|
44
|
-
if (
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
44
|
+
if (!options.json) {
|
|
45
|
+
if (objects.length === 0) {
|
|
46
|
+
tui.info(`No objects found in bucket ${tui.bold(args.bucket)}`);
|
|
47
|
+
} else {
|
|
48
|
+
tui.info(`Found ${objects.length} object(s) in ${tui.bold(args.bucket)}:`);
|
|
49
|
+
for (const obj of objects) {
|
|
50
|
+
const sizeMB = (obj.size / (1024 * 1024)).toFixed(2);
|
|
51
|
+
const date = new Date(obj.updated_at).toLocaleString();
|
|
52
|
+
tui.info(` ${tui.bold(obj.key)}: ${sizeMB} MB, updated ${date}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
54
55
|
}
|
|
55
56
|
|
|
56
57
|
return { bucket: args.bucket, objects, count: objects.length };
|
|
@@ -57,39 +57,49 @@ export const listSubcommand = createSubcommand({
|
|
|
57
57
|
});
|
|
58
58
|
|
|
59
59
|
// Output based on format
|
|
60
|
-
if (options.json) {
|
|
61
|
-
console.log(JSON.stringify(resources, null, 2));
|
|
62
|
-
} else {
|
|
60
|
+
if (!options.json) {
|
|
63
61
|
// Text table format
|
|
64
62
|
if (resources.db.length === 0 && resources.s3.length === 0) {
|
|
65
63
|
tui.info('No resources found');
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
if (resources.db.length > 0) {
|
|
70
|
-
tui.info(tui.bold('Databases'));
|
|
71
|
-
tui.newline();
|
|
72
|
-
for (const db of resources.db) {
|
|
73
|
-
console.log(tui.bold(db.name));
|
|
74
|
-
if (db.url) console.log(` URL: ${tui.muted(db.url)}`);
|
|
64
|
+
} else {
|
|
65
|
+
if (resources.db.length > 0) {
|
|
66
|
+
tui.info(tui.bold('Databases'));
|
|
75
67
|
tui.newline();
|
|
68
|
+
for (const db of resources.db) {
|
|
69
|
+
console.log(tui.bold(db.name));
|
|
70
|
+
if (db.url) console.log(` URL: ${tui.muted(db.url)}`);
|
|
71
|
+
tui.newline();
|
|
72
|
+
}
|
|
76
73
|
}
|
|
77
|
-
}
|
|
78
74
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
tui.newline();
|
|
82
|
-
for (const s3 of resources.s3) {
|
|
83
|
-
console.log(tui.bold(s3.bucket_name));
|
|
84
|
-
if (s3.access_key) console.log(` Access Key: ${tui.muted(s3.access_key)}`);
|
|
85
|
-
if (s3.secret_key) console.log(` Secret Key: ${tui.muted(s3.secret_key)}`);
|
|
86
|
-
if (s3.region) console.log(` Region: ${tui.muted(s3.region)}`);
|
|
87
|
-
if (s3.endpoint) console.log(` Endpoint: ${tui.muted(s3.endpoint)}`);
|
|
75
|
+
if (resources.s3.length > 0) {
|
|
76
|
+
tui.info(tui.bold('Storage'));
|
|
88
77
|
tui.newline();
|
|
78
|
+
for (const s3 of resources.s3) {
|
|
79
|
+
console.log(tui.bold(s3.bucket_name));
|
|
80
|
+
if (s3.access_key) console.log(` Access Key: ${tui.muted(s3.access_key)}`);
|
|
81
|
+
if (s3.secret_key) console.log(` Secret Key: ${tui.muted(s3.secret_key)}`);
|
|
82
|
+
if (s3.region) console.log(` Region: ${tui.muted(s3.region)}`);
|
|
83
|
+
if (s3.endpoint) console.log(` Endpoint: ${tui.muted(s3.endpoint)}`);
|
|
84
|
+
tui.newline();
|
|
85
|
+
}
|
|
89
86
|
}
|
|
90
87
|
}
|
|
91
88
|
}
|
|
92
89
|
|
|
93
|
-
|
|
90
|
+
// Convert null to undefined for schema compliance
|
|
91
|
+
return {
|
|
92
|
+
db: resources.db.map((db) => ({
|
|
93
|
+
name: db.name,
|
|
94
|
+
url: db.url ?? undefined,
|
|
95
|
+
})),
|
|
96
|
+
s3: resources.s3.map((s3) => ({
|
|
97
|
+
bucket_name: s3.bucket_name,
|
|
98
|
+
access_key: s3.access_key ?? undefined,
|
|
99
|
+
secret_key: s3.secret_key ?? undefined,
|
|
100
|
+
region: s3.region ?? undefined,
|
|
101
|
+
endpoint: s3.endpoint ?? undefined,
|
|
102
|
+
})),
|
|
103
|
+
};
|
|
94
104
|
},
|
|
95
105
|
});
|