@griffin-app/griffin-cli 1.0.18 → 1.0.19

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 (48) hide show
  1. package/dist/cli.js +183 -196
  2. package/dist/commands/env.d.ts +3 -3
  3. package/dist/commands/env.js +28 -45
  4. package/dist/commands/hub/apply.d.ts +1 -1
  5. package/dist/commands/hub/apply.js +54 -95
  6. package/dist/commands/hub/connect.d.ts +1 -1
  7. package/dist/commands/hub/connect.js +2 -6
  8. package/dist/commands/hub/destroy.d.ts +10 -0
  9. package/dist/commands/hub/destroy.js +141 -0
  10. package/dist/commands/hub/integrations.d.ts +9 -9
  11. package/dist/commands/hub/integrations.js +104 -115
  12. package/dist/commands/hub/login.js +3 -0
  13. package/dist/commands/hub/metrics.d.ts +2 -2
  14. package/dist/commands/hub/metrics.js +41 -69
  15. package/dist/commands/hub/monitor.d.ts +1 -1
  16. package/dist/commands/hub/monitor.js +30 -70
  17. package/dist/commands/hub/notifications.d.ts +3 -3
  18. package/dist/commands/hub/notifications.js +61 -89
  19. package/dist/commands/hub/run.d.ts +1 -1
  20. package/dist/commands/hub/run.js +118 -144
  21. package/dist/commands/hub/runs.d.ts +1 -1
  22. package/dist/commands/hub/runs.js +60 -81
  23. package/dist/commands/hub/secrets.d.ts +8 -8
  24. package/dist/commands/hub/secrets.js +88 -148
  25. package/dist/commands/hub/status.d.ts +1 -1
  26. package/dist/commands/hub/status.js +13 -26
  27. package/dist/commands/init.js +3 -3
  28. package/dist/commands/local/run.d.ts +2 -2
  29. package/dist/commands/local/run.js +37 -42
  30. package/dist/commands/validate.d.ts +1 -1
  31. package/dist/commands/validate.js +19 -39
  32. package/dist/commands/variables.d.ts +3 -3
  33. package/dist/commands/variables.js +51 -69
  34. package/dist/core/discovery.js +0 -2
  35. package/dist/core/monitor-helpers.d.ts +19 -0
  36. package/dist/core/monitor-helpers.js +48 -0
  37. package/dist/core/sdk.d.ts +5 -0
  38. package/dist/core/sdk.js +11 -0
  39. package/dist/core/state.d.ts +1 -1
  40. package/dist/core/state.js +0 -3
  41. package/dist/index.d.ts +1 -0
  42. package/dist/index.js +1 -0
  43. package/dist/utils/command-wrapper.d.ts +10 -0
  44. package/dist/utils/command-wrapper.js +27 -0
  45. package/dist/utils/sdk-error.js +1 -1
  46. package/dist/utils/terminal.d.ts +4 -0
  47. package/dist/utils/terminal.js +17 -0
  48. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -5,15 +5,14 @@ import { executeValidate } from "./commands/validate.js";
5
5
  import { executeGenerateKey } from "./commands/generate-key.js";
6
6
  import { executeEnvList, executeEnvAdd, executeEnvRemove, } from "./commands/env.js";
7
7
  import { executeVariablesList, executeVariablesAdd, executeVariablesRemove, } from "./commands/variables.js";
8
- // Local commands
9
8
  import { executeRunLocal } from "./commands/local/run.js";
10
- // Hub commands
11
9
  import { executeConnect } from "./commands/hub/connect.js";
12
10
  import { executeStatus } from "./commands/hub/status.js";
13
11
  import { executeMetrics } from "./commands/hub/metrics.js";
14
12
  import { executeRuns } from "./commands/hub/runs.js";
15
13
  import { executePlan } from "./commands/hub/monitor.js";
16
14
  import { executeApply } from "./commands/hub/apply.js";
15
+ import { executeDestroy } from "./commands/hub/destroy.js";
17
16
  import { executeRun } from "./commands/hub/run.js";
18
17
  import { executeLogin } from "./commands/hub/login.js";
19
18
  import { executeLogout } from "./commands/hub/logout.js";
@@ -24,7 +23,7 @@ import { executeIntegrationsList, executeIntegrationsShow, executeIntegrationsUp
24
23
  const program = new Command();
25
24
  program
26
25
  .name("griffin")
27
- .description("Griffin CLI - Monitoring as Code")
26
+ .description("Griffin CLI - API Monitoring as Code")
28
27
  .version("1.0.0");
29
28
  // Top-level commands
30
29
  program
@@ -36,13 +35,112 @@ program
36
35
  });
37
36
  program
38
37
  .command("validate")
39
- .description("Validate test monitor files without syncing")
38
+ .description("Check monitor files for errors")
40
39
  .action(async () => {
41
40
  await executeValidate();
42
41
  });
43
42
  program
43
+ .command("status")
44
+ .description("Show project and connection status")
45
+ .action(async () => {
46
+ await executeStatus();
47
+ });
48
+ program
49
+ .command("test")
50
+ .description("Run monitors locally")
51
+ .option("--env <name>", "Environment name", "default")
52
+ .action(async (options) => {
53
+ await executeRunLocal({ env: options.env });
54
+ });
55
+ program
56
+ .command("plan")
57
+ .description("Preview pending monitor changes")
58
+ .option("--env <name>", "Environment name", "default")
59
+ .option("--json", "Output in JSON format")
60
+ .action(async (options) => {
61
+ await executePlan({ ...options, env: options.env });
62
+ });
63
+ program
64
+ .command("apply")
65
+ .description("Push monitor changes to the platform")
66
+ .option("--env <name>", "Environment name", "default")
67
+ .option("--auto-approve", "Skip confirmation prompt")
68
+ .option("--dry-run", "Show what would be done without making changes")
69
+ .option("--prune", "Delete monitors on hub that don't exist locally")
70
+ .action(async (options) => {
71
+ await executeApply({ ...options, env: options.env });
72
+ });
73
+ program
74
+ .command("runs")
75
+ .description("List recent monitor runs")
76
+ .option("--env <name>", "Environment name", "default")
77
+ .option("--monitor <name>", "Filter by monitor name")
78
+ .option("--limit <number>", "Number of runs to show", "10")
79
+ .action(async (options) => {
80
+ await executeRuns({
81
+ ...options,
82
+ env: options.env,
83
+ limit: parseInt(options.limit, 10),
84
+ });
85
+ });
86
+ program
87
+ .command("run")
88
+ .description("Trigger a monitor run")
89
+ .option("--env <name>", "Environment name", "default")
90
+ .requiredOption("--monitor <name>", "Monitor name to run")
91
+ .option("--wait", "Wait for run to complete")
92
+ .option("--force", "Run even if local monitor differs from hub")
93
+ .action(async (options) => {
94
+ await executeRun({ ...options, env: options.env });
95
+ });
96
+ program
97
+ .command("metrics")
98
+ .description("Show monitor metrics summary")
99
+ .option("--env <name>", "Environment name", "default")
100
+ .option("--period <period>", "Time window: 1h, 6h, 24h, 7d, 30d", "24h")
101
+ .option("--json", "Output as JSON")
102
+ .action(async (options) => {
103
+ await executeMetrics({
104
+ period: options.period,
105
+ environment: options.env,
106
+ json: options.json,
107
+ });
108
+ });
109
+ program
110
+ .command("destroy")
111
+ .description("Destroy monitors on the hub")
112
+ .option("--env <name>", "Environment name", "default")
113
+ .option("--monitor <nameOrId>", "Specific monitor name or ID to destroy")
114
+ .option("--auto-approve", "Skip confirmation prompt")
115
+ .option("--dry-run", "Show what would be destroyed without making changes")
116
+ .action(async (env, options) => {
117
+ await executeDestroy({ ...options, env });
118
+ });
119
+ // Auth command group
120
+ const auth = program.command("auth").description("Manage authentication");
121
+ auth
122
+ .command("login")
123
+ .description("Authenticate with Griffin Cloud")
124
+ .action(async () => {
125
+ await executeLogin();
126
+ });
127
+ auth
128
+ .command("logout")
129
+ .description("Clear stored credentials")
130
+ .action(async (options) => {
131
+ await executeLogout(options);
132
+ });
133
+ auth
134
+ .command("connect")
135
+ .description("Set hub URL and API key for self-hosted deployments")
136
+ .requiredOption("--url <url>", "Hub URL")
137
+ .requiredOption("--token <token>", "API authentication token")
138
+ .action(async (options) => {
139
+ await executeConnect(options);
140
+ });
141
+ auth
44
142
  .command("generate-key")
45
- .description("Generate a cryptographically secure API key for authentication")
143
+ .description("Generate an API key")
46
144
  .action(async () => {
47
145
  await executeGenerateKey();
48
146
  });
@@ -50,13 +148,13 @@ program
50
148
  const env = program.command("env").description("Manage environments");
51
149
  env
52
150
  .command("list")
53
- .description("List all available environments")
151
+ .description("List configured environments")
54
152
  .action(async () => {
55
153
  await executeEnvList();
56
154
  });
57
155
  env
58
156
  .command("add <name>")
59
- .description("Add a new environment")
157
+ .description("Add an environment")
60
158
  .action(async (name) => {
61
159
  await executeEnvAdd(name);
62
160
  });
@@ -72,156 +170,93 @@ const variables = program
72
170
  .description("Manage environment variables");
73
171
  variables
74
172
  .command("list")
75
- .description("List all variables for an environment")
76
- .requiredOption("--env <name>", "Environment name")
173
+ .description("List variables for an environment")
174
+ .option("--env <name>", "Environment name", "default")
77
175
  .action(async (options) => {
78
176
  await executeVariablesList(options.env);
79
177
  });
80
178
  variables
81
179
  .command("add <keyValue>")
82
- .description("Add or update a variable (format: KEY=VALUE)")
83
- .requiredOption("--env <name>", "Environment name")
180
+ .description("Set a variable (KEY=VALUE)")
181
+ .option("--env <name>", "Environment name", "default")
84
182
  .action(async (keyValue, options) => {
85
183
  await executeVariablesAdd(keyValue, options.env);
86
184
  });
87
185
  variables
88
186
  .command("remove <key>")
89
187
  .description("Remove a variable")
90
- .requiredOption("--env <name>", "Environment name")
188
+ .option("--env <name>", "Environment name", "default")
91
189
  .action(async (key, options) => {
92
190
  await executeVariablesRemove(key, options.env);
93
191
  });
94
- // Local command group
95
- const local = program.command("local").description("Local test execution");
96
- local
97
- .command("run [env]")
98
- .description("Run tests locally against an environment")
99
- .action(async (env, options) => {
100
- await executeRunLocal({ env });
101
- });
102
- // Hub command group
103
- const hub = program.command("hub").description("Griffin Hub operations");
104
- hub
105
- .command("connect")
106
- .description("Configure hub connection")
107
- .requiredOption("--url <url>", "Hub URL")
108
- .option("--token <token>", "API authentication token")
109
- .action(async (options) => {
110
- await executeConnect(options);
111
- });
112
- hub
113
- .command("status")
114
- .description("Show hub connection status")
115
- .action(async () => {
116
- await executeStatus();
117
- });
118
- hub
119
- .command("metrics [env]")
120
- .description("Show metrics summary from the hub")
121
- .option("--period <period>", "Time window: 1h, 6h, 24h, 7d, 30d", "24h")
192
+ // Secrets command group
193
+ const secrets = program
194
+ .command("secrets")
195
+ .description("Manage encrypted secrets");
196
+ secrets
197
+ .command("list")
198
+ .description("List secrets for an environment")
199
+ .option("--env <name>", "Environment name", "default")
122
200
  .option("--json", "Output as JSON")
123
- .action(async (env, options) => {
124
- await executeMetrics({
125
- period: options.period,
126
- environment: env,
201
+ .action(async (options) => {
202
+ await executeSecretsList({
203
+ environment: options.env,
127
204
  json: options.json,
128
205
  });
129
206
  });
130
- hub
131
- .command("runs")
132
- .description("Show recent runs from the hub")
133
- .option("--monitor <name>", "Filter by monitor name")
134
- .option("--limit <number>", "Number of runs to show", "10")
135
- .action(async (options) => {
136
- await executeRuns({
137
- ...options,
138
- limit: parseInt(options.limit, 10),
207
+ secrets
208
+ .command("set <name>")
209
+ .description("Create or update a secret")
210
+ .option("--env <name>", "Environment name", "default")
211
+ .option("--value <value>", "Secret value (avoid for sensitive data)")
212
+ .action(async (name, options) => {
213
+ await executeSecretsSet({
214
+ name,
215
+ environment: options.env,
216
+ value: options.value,
139
217
  });
140
218
  });
141
- hub
142
- .command("plan [env]")
143
- .description("Show what changes would be applied")
144
- .option("--json", "Output in JSON format")
145
- .action(async (env, options) => {
146
- await executePlan({ ...options, env });
147
- });
148
- hub
149
- .command("apply [env]")
150
- .description("Apply changes to the hub")
151
- .option("--auto-approve", "Skip confirmation prompt")
152
- .option("--dry-run", "Show what would be done without making changes")
153
- .option("--prune", "Delete monitors on hub that don't exist locally")
154
- .action(async (env, options) => {
155
- await executeApply({ ...options, env });
156
- });
157
- hub
158
- .command("run [env]")
159
- .description("Trigger a monitor run on the hub")
160
- .requiredOption("--monitor <name>", "Monitor name to run")
161
- .option("--wait", "Wait for run to complete")
162
- .option("--force", "Run even if local monitor differs from hub")
163
- .action(async (env, options) => {
164
- await executeRun({ ...options, env });
165
- });
166
- hub
167
- .command("login")
168
- .description("Login to the hub")
169
- .action(async () => {
170
- await executeLogin();
171
- });
172
- hub
173
- .command("logout")
174
- .description("Remove stored credentials")
175
- .action(async (options) => {
176
- await executeLogout(options);
177
- });
178
- // Notifications command group
179
- const notifications = hub
180
- .command("notifications")
181
- .description("View notification rules (rules are defined in monitor DSL and synced via griffin hub apply)");
182
- notifications
183
- .command("list")
184
- .description("List notification rules")
185
- .option("--monitor <id>", "Filter by monitor ID")
186
- .option("--enabled", "Filter by enabled status")
219
+ secrets
220
+ .command("get <name>")
221
+ .description("Show secret metadata")
222
+ .option("--env <name>", "Environment name", "default")
187
223
  .option("--json", "Output as JSON")
188
- .action(async (options) => {
189
- await executeNotificationsList({
190
- monitor: options.monitor,
191
- enabled: options.enabled ? true : undefined,
224
+ .action(async (name, options) => {
225
+ await executeSecretsGet({
226
+ name,
227
+ environment: options.env,
192
228
  json: options.json,
193
229
  });
194
230
  });
195
- notifications
196
- .command("test")
197
- .description("Send a test notification (interactive wizard, or use flags for scripts)")
198
- .option("--integration <id|name>", "Integration id or name; omit to choose from a list")
199
- .option("--channel <channel>", "Slack channel (e.g. #alerts); use with Slack integration")
200
- .option("--to-addresses <emails>", "Email recipients, comma-separated; use with email integration")
201
- .action(async (options) => {
202
- await executeNotificationsTest({
203
- integration: options.integration,
204
- channel: options.channel,
205
- toAddresses: options.toAddresses,
231
+ secrets
232
+ .command("delete <name>")
233
+ .description("Delete a secret")
234
+ .option("--env <name>", "Environment name", "default")
235
+ .option("--force", "Skip confirmation prompt")
236
+ .action(async (name, options) => {
237
+ await executeSecretsDelete({
238
+ name,
239
+ environment: options.env,
240
+ force: options.force,
206
241
  });
207
242
  });
208
243
  // Integrations command group
209
- const integrations = hub
244
+ const integrations = program
210
245
  .command("integrations")
211
- .description("Manage integrations (notifications, secrets, metrics)");
246
+ .description("Manage integrations");
212
247
  integrations
213
248
  .command("list")
214
- .description("List integrations")
249
+ .description("List connected integrations")
215
250
  .option("--category <cat>", "Filter by category: secrets, notifications, metrics")
216
251
  .option("--provider <provider>", "Filter by provider")
217
- .option("--environment <env>", "Filter by environment")
252
+ .option("--env <name>", "Filter by environment", "default")
218
253
  .option("--enabled", "Filter by enabled status")
219
254
  .option("--json", "Output as JSON")
220
255
  .action(async (options) => {
221
256
  await executeIntegrationsList({
222
257
  category: options.category,
223
258
  provider: options.provider,
224
- environment: options.environment,
259
+ environment: options.env,
225
260
  enabled: options.enabled ? true : undefined,
226
261
  json: options.json,
227
262
  });
@@ -235,58 +270,31 @@ integrations
235
270
  });
236
271
  integrations
237
272
  .command("connect [type] [provider]")
238
- .description("Connect an integration.")
273
+ .description("Connect a new integration")
239
274
  .option("--name <name>", "Display name for the integration")
240
- .option("--environment <env>", "Environment scope")
275
+ .option("--env <name>", "Environment scope", "default")
241
276
  .option("--json", "Output as JSON")
242
277
  .action(async (category, provider, options) => {
243
278
  await executeIntegrationsConnect({
244
279
  category: category ?? "",
245
280
  provider: provider ?? "",
246
281
  name: options.name,
247
- environment: options.environment,
282
+ environment: options.env,
248
283
  json: options.json,
249
284
  });
250
285
  });
251
- //integrations
252
- // .command("add")
253
- // .description(
254
- // "Add an integration (no credentials in Phase 1; use API for credentials)",
255
- // )
256
- // .requiredOption(
257
- // "--category <cat>",
258
- // "Category: secrets, notifications, metrics",
259
- // )
260
- // .requiredOption(
261
- // "--provider-type <type>",
262
- // "Provider type (e.g. slack_webhook, datadog)",
263
- // )
264
- // .requiredOption("--name <name>", "Display name")
265
- // .option("--environment <env>", "Environment scope (omit for org-wide)")
266
- // .option("--enabled", "Enabled")
267
- // .option("--json", "Output as JSON")
268
- // .action(async (options) => {
269
- // await executeIntegrationsAdd({
270
- // category: options.category,
271
- // providerType: options.providerType,
272
- // name: options.name,
273
- // environment: options.environment,
274
- // enabled: options.enabled,
275
- // json: options.json,
276
- // });
277
- // });
278
286
  integrations
279
287
  .command("update <id>")
280
288
  .description("Update an integration")
281
289
  .option("--name <name>", "Display name")
282
- .option("--environment <env>", "Environment scope")
290
+ .option("--env <name>", "Environment scope", "default")
283
291
  .option("--enabled", "Enabled")
284
292
  .option("--json", "Output as JSON")
285
293
  .action(async (id, options) => {
286
294
  await executeIntegrationsUpdate({
287
295
  id,
288
296
  name: options.name,
289
- environment: options.environment,
297
+ environment: options.env,
290
298
  enabled: options.enabled,
291
299
  json: options.json,
292
300
  });
@@ -295,58 +303,37 @@ integrations
295
303
  .command("remove <id>")
296
304
  .description("Remove an integration")
297
305
  .option("--force", "Skip confirmation")
298
- .action(async (id) => {
299
- await executeIntegrationsRemove({ id });
306
+ .action(async (id, options) => {
307
+ await executeIntegrationsRemove({ id, force: options.force });
300
308
  });
301
- // Secrets command group
302
- const secrets = hub
303
- .command("secrets")
304
- .description("Manage secrets (platform storage)");
305
- secrets
309
+ // Notifications command group
310
+ const notifications = program
311
+ .command("notifications")
312
+ .description("Manage notification rules");
313
+ notifications
306
314
  .command("list")
307
- .description("List secrets for an environment")
308
- .option("--environment <env>", "Environment name", "default")
315
+ .description("List notification rules")
316
+ .option("--monitor <id>", "Filter by monitor ID")
317
+ .option("--enabled", "Filter by enabled status")
309
318
  .option("--json", "Output as JSON")
310
319
  .action(async (options) => {
311
- await executeSecretsList({
312
- environment: options.environment,
313
- json: options.json,
314
- });
315
- });
316
- secrets
317
- .command("set <name>")
318
- .description("Create or update a secret (prompts for value)")
319
- .option("--environment <env>", "Environment name", "default")
320
- .option("--value <value>", "Secret value (avoid for sensitive data)")
321
- .action(async (name, options) => {
322
- await executeSecretsSet({
323
- name,
324
- environment: options.environment,
325
- value: options.value,
326
- });
327
- });
328
- secrets
329
- .command("get <name>")
330
- .description("Show secret metadata (not the value)")
331
- .option("--environment <env>", "Environment name", "default")
332
- .option("--json", "Output as JSON")
333
- .action(async (name, options) => {
334
- await executeSecretsGet({
335
- name,
336
- environment: options.environment,
320
+ await executeNotificationsList({
321
+ monitor: options.monitor,
322
+ enabled: options.enabled ? true : undefined,
337
323
  json: options.json,
338
324
  });
339
325
  });
340
- secrets
341
- .command("delete <name>")
342
- .description("Delete a secret")
343
- .option("--environment <env>", "Environment name", "default")
344
- .option("--force", "Skip confirmation prompt")
345
- .action(async (name, options) => {
346
- await executeSecretsDelete({
347
- name,
348
- environment: options.environment,
349
- force: options.force,
326
+ notifications
327
+ .command("test")
328
+ .description("Send a test notification")
329
+ .option("--integration <id|name>", "Integration id or name; omit to choose from a list")
330
+ .option("--channel <channel>", "Slack channel (e.g. #alerts); use with Slack integration")
331
+ .option("--to-addresses <emails>", "Email recipients, comma-separated; use with email integration")
332
+ .action(async (options) => {
333
+ await executeNotificationsTest({
334
+ integration: options.integration,
335
+ channel: options.channel,
336
+ toAddresses: options.toAddresses,
350
337
  });
351
338
  });
352
339
  // Parse arguments
@@ -1,12 +1,12 @@
1
1
  /**
2
2
  * List all available environments
3
3
  */
4
- export declare function executeEnvList(): Promise<void>;
4
+ export declare const executeEnvList: () => Promise<void>;
5
5
  /**
6
6
  * Add a new environment
7
7
  */
8
- export declare function executeEnvAdd(name: string): Promise<void>;
8
+ export declare const executeEnvAdd: (name: string) => Promise<void>;
9
9
  /**
10
10
  * Remove an environment
11
11
  */
12
- export declare function executeEnvRemove(name: string): Promise<void>;
12
+ export declare const executeEnvRemove: (name: string) => Promise<void>;
@@ -1,59 +1,42 @@
1
1
  import { loadState, addEnvironment, removeEnvironment } from "../core/state.js";
2
2
  import { terminal } from "../utils/terminal.js";
3
+ import { withCommandErrorHandler } from "../utils/command-wrapper.js";
3
4
  /**
4
5
  * List all available environments
5
6
  */
6
- export async function executeEnvList() {
7
- try {
8
- const state = await loadState();
9
- const environments = Object.keys(state.environments);
10
- if (environments.length === 0) {
11
- terminal.warn("No environments configured.");
12
- terminal.blank();
13
- terminal.dim("Run 'griffin init' to set up your project.");
14
- return;
15
- }
16
- terminal.info("Available environments:");
17
- terminal.blank();
18
- for (const envName of environments) {
19
- const marker = terminal.colors.green("●");
20
- const envDisplay = terminal.colors.cyan(envName);
21
- terminal.log(` ${marker} ${envDisplay}`);
22
- }
7
+ export const executeEnvList = withCommandErrorHandler(async () => {
8
+ const state = await loadState();
9
+ const environments = Object.keys(state.environments);
10
+ if (environments.length === 0) {
11
+ terminal.warn("No environments configured.");
23
12
  terminal.blank();
13
+ terminal.dim("Run 'griffin init' to set up your project.");
14
+ return;
24
15
  }
25
- catch (error) {
26
- terminal.error(error.message);
27
- terminal.exit(1);
16
+ terminal.info("Available environments:");
17
+ terminal.blank();
18
+ for (const envName of environments) {
19
+ const marker = terminal.colors.green("●");
20
+ const envDisplay = terminal.colors.cyan(envName);
21
+ terminal.log(` ${marker} ${envDisplay}`);
28
22
  }
29
- }
23
+ terminal.blank();
24
+ });
30
25
  /**
31
26
  * Add a new environment
32
27
  */
33
- export async function executeEnvAdd(name) {
34
- try {
35
- await addEnvironment(name, {});
36
- terminal.success(`Environment '${name}' added successfully.`);
37
- terminal.blank();
38
- terminal.dim(`Add variables with: griffin variables add KEY=VALUE --env ${name}`);
39
- terminal.blank();
40
- }
41
- catch (error) {
42
- terminal.error(error.message);
43
- terminal.exit(1);
44
- }
45
- }
28
+ export const executeEnvAdd = withCommandErrorHandler(async (name) => {
29
+ await addEnvironment(name, {});
30
+ terminal.success(`Environment '${name}' added successfully.`);
31
+ terminal.blank();
32
+ terminal.dim(`Add variables with: griffin variables add KEY=VALUE --env ${name}`);
33
+ terminal.blank();
34
+ });
46
35
  /**
47
36
  * Remove an environment
48
37
  */
49
- export async function executeEnvRemove(name) {
50
- try {
51
- await removeEnvironment(name);
52
- terminal.success(`Environment '${name}' removed successfully.`);
53
- terminal.blank();
54
- }
55
- catch (error) {
56
- terminal.error(error.message);
57
- terminal.exit(1);
58
- }
59
- }
38
+ export const executeEnvRemove = withCommandErrorHandler(async (name) => {
39
+ await removeEnvironment(name);
40
+ terminal.success(`Environment '${name}' removed successfully.`);
41
+ terminal.blank();
42
+ });
@@ -7,4 +7,4 @@ export interface ApplyOptions {
7
7
  /**
8
8
  * Apply changes to the hub
9
9
  */
10
- export declare function executeApply(options: ApplyOptions): Promise<void>;
10
+ export declare const executeApply: (options: ApplyOptions) => Promise<void>;