@agentuity/cli 0.0.52 → 0.0.54

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/dist/cli.d.ts.map +1 -1
  2. package/dist/cli.js +66 -8
  3. package/dist/cli.js.map +1 -1
  4. package/dist/cmd/auth/ssh/add.d.ts.map +1 -1
  5. package/dist/cmd/auth/ssh/add.js +28 -13
  6. package/dist/cmd/auth/ssh/add.js.map +1 -1
  7. package/dist/cmd/auth/ssh/delete.d.ts.map +1 -1
  8. package/dist/cmd/auth/ssh/delete.js +28 -18
  9. package/dist/cmd/auth/ssh/delete.js.map +1 -1
  10. package/dist/cmd/auth/ssh/list.d.ts.map +1 -1
  11. package/dist/cmd/auth/ssh/list.js +5 -6
  12. package/dist/cmd/auth/ssh/list.js.map +1 -1
  13. package/dist/cmd/build/ast.d.ts +34 -0
  14. package/dist/cmd/build/ast.d.ts.map +1 -1
  15. package/dist/cmd/build/ast.js +159 -0
  16. package/dist/cmd/build/ast.js.map +1 -1
  17. package/dist/cmd/build/bundler.d.ts +2 -1
  18. package/dist/cmd/build/bundler.d.ts.map +1 -1
  19. package/dist/cmd/build/bundler.js +77 -16
  20. package/dist/cmd/build/bundler.js.map +1 -1
  21. package/dist/cmd/build/index.d.ts.map +1 -1
  22. package/dist/cmd/build/index.js +3 -1
  23. package/dist/cmd/build/index.js.map +1 -1
  24. package/dist/cmd/build/plugin.d.ts.map +1 -1
  25. package/dist/cmd/build/plugin.js +158 -63
  26. package/dist/cmd/build/plugin.js.map +1 -1
  27. package/dist/cmd/cloud/deployment/list.d.ts.map +1 -1
  28. package/dist/cmd/cloud/deployment/list.js +28 -23
  29. package/dist/cmd/cloud/deployment/list.js.map +1 -1
  30. package/dist/cmd/cloud/deployment/show.d.ts.map +1 -1
  31. package/dist/cmd/cloud/deployment/show.js +50 -47
  32. package/dist/cmd/cloud/deployment/show.js.map +1 -1
  33. package/dist/cmd/cloud/env/get.d.ts.map +1 -1
  34. package/dist/cmd/cloud/env/get.js +16 -14
  35. package/dist/cmd/cloud/env/get.js.map +1 -1
  36. package/dist/cmd/cloud/env/list.d.ts.map +1 -1
  37. package/dist/cmd/cloud/env/list.js +24 -20
  38. package/dist/cmd/cloud/env/list.js.map +1 -1
  39. package/dist/cmd/cloud/keyvalue/get.d.ts.map +1 -1
  40. package/dist/cmd/cloud/keyvalue/get.js +18 -16
  41. package/dist/cmd/cloud/keyvalue/get.js.map +1 -1
  42. package/dist/cmd/cloud/keyvalue/keys.d.ts.map +1 -1
  43. package/dist/cmd/cloud/keyvalue/keys.js +11 -11
  44. package/dist/cmd/cloud/keyvalue/keys.js.map +1 -1
  45. package/dist/cmd/cloud/keyvalue/list-namespaces.d.ts.map +1 -1
  46. package/dist/cmd/cloud/keyvalue/list-namespaces.js +11 -7
  47. package/dist/cmd/cloud/keyvalue/list-namespaces.js.map +1 -1
  48. package/dist/cmd/cloud/keyvalue/search.d.ts.map +1 -1
  49. package/dist/cmd/cloud/keyvalue/search.js +16 -17
  50. package/dist/cmd/cloud/keyvalue/search.js.map +1 -1
  51. package/dist/cmd/cloud/keyvalue/stats.d.ts.map +1 -1
  52. package/dist/cmd/cloud/keyvalue/stats.js +38 -23
  53. package/dist/cmd/cloud/keyvalue/stats.js.map +1 -1
  54. package/dist/cmd/cloud/objectstore/get.d.ts.map +1 -1
  55. package/dist/cmd/cloud/objectstore/get.js +17 -15
  56. package/dist/cmd/cloud/objectstore/get.js.map +1 -1
  57. package/dist/cmd/cloud/objectstore/list-buckets.d.ts.map +1 -1
  58. package/dist/cmd/cloud/objectstore/list-buckets.js +12 -8
  59. package/dist/cmd/cloud/objectstore/list-buckets.js.map +1 -1
  60. package/dist/cmd/cloud/objectstore/list-keys.d.ts.map +1 -1
  61. package/dist/cmd/cloud/objectstore/list-keys.js +13 -10
  62. package/dist/cmd/cloud/objectstore/list-keys.js.map +1 -1
  63. package/dist/cmd/cloud/resource/list.d.ts.map +1 -1
  64. package/dist/cmd/cloud/resource/list.js +38 -27
  65. package/dist/cmd/cloud/resource/list.js.map +1 -1
  66. package/dist/cmd/cloud/secret/get.d.ts.map +1 -1
  67. package/dist/cmd/cloud/secret/get.js +17 -15
  68. package/dist/cmd/cloud/secret/get.js.map +1 -1
  69. package/dist/cmd/cloud/secret/list.d.ts.map +1 -1
  70. package/dist/cmd/cloud/secret/list.js +24 -20
  71. package/dist/cmd/cloud/secret/list.js.map +1 -1
  72. package/dist/cmd/cloud/session/logs.d.ts.map +1 -1
  73. package/dist/cmd/cloud/session/logs.js +18 -15
  74. package/dist/cmd/cloud/session/logs.js.map +1 -1
  75. package/dist/cmd/dev/agents.d.ts.map +1 -1
  76. package/dist/cmd/dev/agents.js +55 -41
  77. package/dist/cmd/dev/agents.js.map +1 -1
  78. package/dist/cmd/dev/index.d.ts.map +1 -1
  79. package/dist/cmd/dev/index.js +2 -0
  80. package/dist/cmd/dev/index.js.map +1 -1
  81. package/dist/cmd/profile/create.js +1 -1
  82. package/dist/cmd/profile/create.js.map +1 -1
  83. package/dist/cmd/profile/delete.d.ts.map +1 -1
  84. package/dist/cmd/profile/delete.js +1 -1
  85. package/dist/cmd/profile/delete.js.map +1 -1
  86. package/dist/cmd/profile/list.d.ts.map +1 -1
  87. package/dist/cmd/profile/list.js +29 -11
  88. package/dist/cmd/profile/list.js.map +1 -1
  89. package/dist/cmd/profile/show.d.ts.map +1 -1
  90. package/dist/cmd/profile/show.js +7 -10
  91. package/dist/cmd/profile/show.js.map +1 -1
  92. package/dist/cmd/project/delete.js +1 -1
  93. package/dist/cmd/project/delete.js.map +1 -1
  94. package/dist/cmd/version/index.d.ts.map +1 -1
  95. package/dist/cmd/version/index.js +1 -1
  96. package/dist/cmd/version/index.js.map +1 -1
  97. package/dist/tui.d.ts.map +1 -1
  98. package/dist/tui.js +3 -1
  99. package/dist/tui.js.map +1 -1
  100. package/dist/types.d.ts +32 -8
  101. package/dist/types.d.ts.map +1 -1
  102. package/dist/types.js.map +1 -1
  103. package/package.json +3 -3
  104. package/src/cli.ts +109 -8
  105. package/src/cmd/auth/ssh/add.ts +37 -17
  106. package/src/cmd/auth/ssh/delete.ts +36 -23
  107. package/src/cmd/auth/ssh/list.ts +8 -6
  108. package/src/cmd/build/ast.ts +203 -0
  109. package/src/cmd/build/bundler.ts +81 -15
  110. package/src/cmd/build/index.ts +3 -1
  111. package/src/cmd/build/plugin.ts +186 -68
  112. package/src/cmd/cloud/deployment/list.ts +30 -26
  113. package/src/cmd/cloud/deployment/show.ts +47 -42
  114. package/src/cmd/cloud/env/get.ts +14 -12
  115. package/src/cmd/cloud/env/list.ts +24 -22
  116. package/src/cmd/cloud/keyvalue/get.ts +19 -14
  117. package/src/cmd/cloud/keyvalue/keys.ts +10 -12
  118. package/src/cmd/cloud/keyvalue/list-namespaces.ts +10 -8
  119. package/src/cmd/cloud/keyvalue/search.ts +14 -17
  120. package/src/cmd/cloud/keyvalue/stats.ts +52 -28
  121. package/src/cmd/cloud/objectstore/get.ts +18 -13
  122. package/src/cmd/cloud/objectstore/list-buckets.ts +11 -9
  123. package/src/cmd/cloud/objectstore/list-keys.ts +12 -11
  124. package/src/cmd/cloud/resource/list.ts +33 -23
  125. package/src/cmd/cloud/secret/get.ts +15 -13
  126. package/src/cmd/cloud/secret/list.ts +24 -22
  127. package/src/cmd/cloud/session/logs.ts +18 -17
  128. package/src/cmd/dev/agents.ts +70 -50
  129. package/src/cmd/dev/index.ts +2 -0
  130. package/src/cmd/profile/create.ts +3 -3
  131. package/src/cmd/profile/delete.ts +5 -2
  132. package/src/cmd/profile/list.ts +31 -11
  133. package/src/cmd/profile/show.ts +15 -12
  134. package/src/cmd/project/delete.ts +1 -1
  135. package/src/cmd/version/index.ts +5 -1
  136. package/src/tui.ts +3 -1
  137. package/src/types.ts +32 -10
@@ -53,42 +53,46 @@ export const listSubcommand = createSubcommand({
53
53
  },
54
54
  async handler(ctx) {
55
55
  const projectId = resolveProjectId(ctx, { projectId: ctx.opts['project-id'] });
56
- const { apiClient, opts } = ctx;
56
+ const { apiClient, opts, options } = ctx;
57
57
 
58
58
  try {
59
59
  const deployments = await projectDeploymentList(apiClient, projectId, opts.count);
60
60
 
61
- if (deployments.length === 0) {
62
- tui.info('No deployments found.');
63
- return [];
64
- }
65
-
66
- const tableData = deployments.map((d) => ({
67
- ID: d.id,
68
- State: d.state || 'unknown',
69
- Active: d.active ? 'Yes' : '',
70
- Created: new Date(d.createdAt).toLocaleString(),
71
- Message: d.message || '',
72
- Tags: d.tags.join(', '),
73
- }));
74
-
75
- tui.table(tableData, [
76
- { name: 'ID', alignment: 'left' },
77
- { name: 'State', alignment: 'left' },
78
- { name: 'Active', alignment: 'center' },
79
- { name: 'Created', alignment: 'left' },
80
- { name: 'Message', alignment: 'left' },
81
- { name: 'Tags', alignment: 'left' },
82
- ]);
83
-
84
- return deployments.map((d) => ({
61
+ const result = deployments.map((d) => ({
85
62
  id: d.id,
86
63
  state: d.state,
87
64
  active: d.active,
88
65
  createdAt: d.createdAt,
89
- message: d.message,
66
+ message: d.message ?? undefined,
90
67
  tags: d.tags,
91
68
  }));
69
+
70
+ // Skip TUI output in JSON mode
71
+ if (!options.json) {
72
+ if (deployments.length === 0) {
73
+ tui.info('No deployments found.');
74
+ } else {
75
+ const tableData = deployments.map((d) => ({
76
+ ID: d.id,
77
+ State: d.state || 'unknown',
78
+ Active: d.active ? 'Yes' : '',
79
+ Created: new Date(d.createdAt).toLocaleString(),
80
+ Message: d.message || '',
81
+ Tags: d.tags.join(', '),
82
+ }));
83
+
84
+ tui.table(tableData, [
85
+ { name: 'ID', alignment: 'left' },
86
+ { name: 'State', alignment: 'left' },
87
+ { name: 'Active', alignment: 'center' },
88
+ { name: 'Created', alignment: 'left' },
89
+ { name: 'Message', alignment: 'left' },
90
+ { name: 'Tags', alignment: 'left' },
91
+ ]);
92
+ }
93
+ }
94
+
95
+ return result;
92
96
  } catch (ex) {
93
97
  tui.fatal(
94
98
  `Failed to list deployments: ${ex instanceof Error ? ex.message : String(ex)}`,
@@ -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
- tui.banner(`Deployment ${deployment.id}`, `State: ${deployment.state || 'unknown'}`);
50
+ // Skip TUI output in JSON mode
51
+ if (!options.json) {
52
+ tui.banner(`Deployment ${deployment.id}`, `State: ${deployment.state || 'unknown'}`);
51
53
 
52
- console.log(tui.bold('ID: ') + deployment.id);
53
- console.log(tui.bold('Project: ') + projectId);
54
- console.log(tui.bold('State: ') + (deployment.state || 'unknown'));
55
- console.log(tui.bold('Active: ') + (deployment.active ? 'Yes' : 'No'));
56
- console.log(tui.bold('Created: ') + new Date(deployment.createdAt).toLocaleString());
57
- if (deployment.updatedAt) {
58
- console.log(tui.bold('Updated: ') + new Date(deployment.updatedAt).toLocaleString());
59
- }
60
- if (deployment.message) {
61
- console.log(tui.bold('Message: ') + deployment.message);
62
- }
63
- if (deployment.tags.length > 0) {
64
- console.log(tui.bold('Tags: ') + deployment.tags.join(', '));
65
- }
66
- if (deployment.customDomains && deployment.customDomains.length > 0) {
67
- console.log(tui.bold('Domains: ') + deployment.customDomains.join(', '));
68
- }
69
- if (deployment.cloudRegion) {
70
- console.log(tui.bold('Region: ') + deployment.cloudRegion);
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
- // Metadata
74
- const origin = deployment.metadata?.origin;
75
- if (origin?.commit) {
76
- tui.newline();
77
- tui.info('Origin Information');
78
- if (origin.trigger) console.log(` Trigger: ${origin.trigger}`);
79
- if (origin.provider) console.log(` Provider: ${origin.provider}`);
80
- if (origin.event) console.log(` Event: ${origin.event}`);
81
- if (origin.branch) console.log(` Branch: ${origin.branch}`);
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
- if (origin.commit) {
84
- console.log(` Commit: ${origin.commit.hash}`);
85
- if (origin.commit.message) console.log(` Message: ${origin.commit.message}`);
86
- if (origin.commit.author?.name)
87
- console.log(` Author: ${origin.commit.author.name}`);
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)}`);
@@ -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
- // Display the value, masked if requested
50
- if (process.stdout.isTTY) {
51
- if (opts?.mask) {
52
- tui.success(`${args.key}=${maskSecret(value)}`);
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
- tui.success(`${args.key}=${value}`);
55
- }
56
- } else {
57
- if (opts?.mask) {
58
- console.log(`${args.key}=${maskSecret(value)}`);
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
- if (Object.keys(env).length === 0) {
42
- tui.info('No environment variables found');
43
- return {};
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
- console.log(`${key}=${displayValue}`);
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
- if (res.exists) {
39
- if (res.data) {
40
- if (res.contentType?.includes('json')) {
41
- const val = tryParseJSON(res.data as unknown as string);
42
- tui.json(val);
43
- } else if (res.contentType?.includes('text')) {
44
- console.log(String(res.data));
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
- const b = res.data as ArrayBuffer;
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} returned empty data for ${args.namespace}`);
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 (keys.length === 0) {
38
- tui.info(`No keys found in namespace ${tui.bold(args.name)}`);
39
- return {
40
- namespace: args.name,
41
- keys: [],
42
- };
43
- }
44
-
45
- tui.info(`Found ${keys.length} key(s) in ${tui.bold(args.name)}:`);
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 (namespaces.length === 0) {
30
- tui.info('No namespaces found');
31
- return [];
32
- }
33
-
34
- tui.info(`Found ${namespaces.length} namespace(s):`);
35
- for (const name of namespaces) {
36
- tui.arrow(name);
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 (keys.length === 0) {
47
- tui.info(`No keys found matching ${tui.bold(args.keyword)} in ${tui.bold(args.name)}`);
48
- return {
49
- namespace: args.name,
50
- keyword: args.keyword,
51
- results: [],
52
- };
53
- }
54
-
55
- tui.info(`Found ${keys.length} key(s) matching ${tui.bold(args.keyword)}:`);
56
- for (const key of keys) {
57
- const item = results[key];
58
- if (!item) continue;
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
- tui.info(`Statistics for ${tui.bold(args.name)}:`);
51
- tui.info(` Keys: ${stats.count}`);
52
- const sizeDisplay =
53
- stats.sum < 1024 * 1024
54
- ? `${stats.sum.toLocaleString()} bytes`
55
- : `${(stats.sum / (1024 * 1024)).toFixed(2)} MB`;
56
- tui.info(` Total size: ${sizeDisplay} (raw: ${stats.sum})`);
57
- if (stats.createdAt) {
58
- tui.info(` Created: ${new Date(stats.createdAt).toLocaleString()}`);
59
- }
60
- if (stats.lastUsedAt) {
61
- tui.info(` Last used: ${new Date(stats.lastUsedAt).toLocaleString()}`);
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 (entries.length === 0) {
76
- tui.info('No namespaces found');
77
- return {};
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
- tui.info(
81
- `Found ${entries.length} ${tui.plural(entries.length, 'namespace', 'namespaces')}:`
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
- const sizeDisplay =
85
- stats.sum < 1024 * 1024
86
- ? `${stats.sum.toLocaleString()} bytes`
87
- : `${(stats.sum / (1024 * 1024)).toFixed(2)} MB`;
88
- tui.arrow(`${tui.bold(name.padEnd(15, ' '))}: ${stats.count} keys, ${sizeDisplay}`);
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
- if (res.exists) {
39
- if (res.data) {
40
- if (res.contentType?.includes('json')) {
41
- const val = tryParseJSON(new TextDecoder().decode(res.data));
42
- tui.json(val);
43
- } else if (res.contentType?.includes('text')) {
44
- console.log(new TextDecoder().decode(res.data));
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.info(`Read ${res.data.byteLength} bytes (${res.contentType})`);
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} returned empty data for bucket ${args.bucket}`);
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 (buckets.length === 0) {
31
- tui.info('No buckets found');
32
- return [];
33
- }
34
-
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`);
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 (objects.length === 0) {
45
- tui.info(`No objects found in bucket ${tui.bold(args.bucket)}`);
46
- return { bucket: args.bucket, objects: [], count: 0 };
47
- }
48
-
49
- tui.info(`Found ${objects.length} object(s) in ${tui.bold(args.bucket)}:`);
50
- for (const obj of objects) {
51
- const sizeMB = (obj.size / (1024 * 1024)).toFixed(2);
52
- const date = new Date(obj.updated_at).toLocaleString();
53
- tui.info(` ${tui.bold(obj.key)}: ${sizeMB} MB, updated ${date}`);
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 };