@griffin-app/griffin-cli 1.0.29 → 1.0.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -92,18 +92,18 @@ griffin metrics --env production --period 7d --json
92
92
 
93
93
  Commands are **top-level** or under a **group**. The default environment is `default` unless overridden with `--env <name>` where supported.
94
94
 
95
- | Area | Commands | Purpose |
96
- |------|----------|--------|
97
- | **Project** | `init`, `validate`, `status` | Bootstrap, validate monitors, show status |
98
- | **Local run** | `test` | Run monitors locally |
99
- | **Hub sync** | `plan`, `apply`, `destroy` | Preview changes, push to hub, remove from hub |
100
- | **Hub runs** | `runs`, `run`, `metrics` | List runs, trigger run, view metrics |
101
- | **Auth** | `auth login`, `auth logout`, `auth connect`, `auth generate-key` | Cloud or self-hosted auth |
102
- | **Environments** | `env list`, `env add`, `env remove` | Manage environments |
103
- | **Variables** | `variables list`, `variables add`, `variables remove` | Per-environment variables (in state) |
104
- | **Secrets** | `secrets list`, `secrets set`, `secrets get`, `secrets delete` | Per-environment secrets (stored on hub) |
105
- | **Integrations** | `integrations list`, `integrations show`, `integrations connect`, `integrations update`, `integrations remove` | Slack, email, webhooks, etc. |
106
- | **Notifications** | `notifications list`, `notifications test` | Notification rules and test sends |
95
+ | Area | Commands | Purpose |
96
+ | ----------------- | -------------------------------------------------------------------------------------------------------------- | --------------------------------------------- |
97
+ | **Project** | `init`, `validate`, `status` | Bootstrap, validate monitors, show status |
98
+ | **Local run** | `test` | Run monitors locally |
99
+ | **Hub sync** | `plan`, `apply`, `destroy` | Preview changes, push to hub, remove from hub |
100
+ | **Hub runs** | `runs`, `run`, `metrics` | List runs, trigger run, view metrics |
101
+ | **Auth** | `auth login`, `auth logout`, `auth connect`, `auth generate-key` | Cloud or self-hosted auth |
102
+ | **Environments** | `env list`, `env add`, `env remove` | Manage environments |
103
+ | **Variables** | `variables list`, `variables add`, `variables remove` | Per-environment variables (in state) |
104
+ | **Secrets** | `secrets list`, `secrets set`, `secrets get`, `secrets delete` | Per-environment secrets (stored on hub) |
105
+ | **Integrations** | `integrations list`, `integrations show`, `integrations connect`, `integrations update`, `integrations remove` | Slack, email, webhooks, etc. |
106
+ | **Notifications** | `notifications list`, `notifications test` | Notification rules and test sends |
107
107
 
108
108
  ### Top-level commands
109
109
 
package/dist/cli.js CHANGED
@@ -20,7 +20,7 @@ import { executeIntegrationsConnect } from "./commands/hub/integrations.js";
20
20
  import { executeNotificationsList, executeNotificationsTest, } from "./commands/hub/notifications.js";
21
21
  import { executeSecretsList, executeSecretsSet, executeSecretsGet, executeSecretsDelete, } from "./commands/hub/secrets.js";
22
22
  import { executeIntegrationsList, executeIntegrationsShow, executeIntegrationsUpdate, executeIntegrationsRemove, } from "./commands/hub/integrations.js";
23
- import packageInfo from '../package.json' with { type: 'json' };
23
+ import packageInfo from "../package.json" with { type: "json" };
24
24
  const program = new Command();
25
25
  program
26
26
  .name("griffin")
@@ -60,7 +60,11 @@ program
60
60
  .option("--env <name>", "Environment name", "default")
61
61
  .option("--json", "Output in JSON format")
62
62
  .action(async (options) => {
63
- await executePlan({ ...options, env: options.env, json: program.opts().json ?? options.json });
63
+ await executePlan({
64
+ ...options,
65
+ env: options.env,
66
+ json: program.opts().json ?? options.json,
67
+ });
64
68
  });
65
69
  program
66
70
  .command("apply")
@@ -70,7 +74,11 @@ program
70
74
  .option("--dry-run", "Show what would be done without making changes")
71
75
  .option("--prune", "Delete monitors on hub that don't exist locally")
72
76
  .action(async (options) => {
73
- await executeApply({ ...options, env: options.env, json: program.opts().json });
77
+ await executeApply({
78
+ ...options,
79
+ env: options.env,
80
+ json: program.opts().json,
81
+ });
74
82
  });
75
83
  program
76
84
  .command("runs")
@@ -94,7 +102,11 @@ program
94
102
  .option("--wait", "Wait for run to complete")
95
103
  .option("--force", "Run even if local monitor differs from hub")
96
104
  .action(async (options) => {
97
- await executeRun({ ...options, env: options.env, json: program.opts().json });
105
+ await executeRun({
106
+ ...options,
107
+ env: options.env,
108
+ json: program.opts().json,
109
+ });
98
110
  });
99
111
  program
100
112
  .command("metrics")
@@ -285,7 +297,10 @@ integrations
285
297
  .description("Show integration details")
286
298
  .option("--json", "Output as JSON")
287
299
  .action(async (id, options) => {
288
- await executeIntegrationsShow({ id, json: program.opts().json ?? options.json });
300
+ await executeIntegrationsShow({
301
+ id,
302
+ json: program.opts().json ?? options.json,
303
+ });
289
304
  });
290
305
  integrations
291
306
  .command("connect [type] [provider]")
@@ -323,7 +338,11 @@ integrations
323
338
  .description("Remove an integration")
324
339
  .option("--force", "Skip confirmation")
325
340
  .action(async (id, options) => {
326
- await executeIntegrationsRemove({ id, force: options.force, json: program.opts().json });
341
+ await executeIntegrationsRemove({
342
+ id,
343
+ force: options.force,
344
+ json: program.opts().json,
345
+ });
327
346
  });
328
347
  // Notifications command group
329
348
  const notifications = program
@@ -35,7 +35,11 @@ export const executeDestroy = createCommandHandler("destroy", async (options, ou
35
35
  const remoteMonitors = response.data?.data;
36
36
  fetchSpinner.succeed(`Found ${remoteMonitors.length} remote monitor(s)`);
37
37
  if (remoteMonitors.length === 0) {
38
- output.setData({ destroyed: [], total: 0, dryRun: options.dryRun ?? false });
38
+ output.setData({
39
+ destroyed: [],
40
+ total: 0,
41
+ dryRun: options.dryRun ?? false,
42
+ });
39
43
  output.success("No monitors to destroy.");
40
44
  return;
41
45
  }
@@ -67,7 +71,10 @@ export const executeDestroy = createCommandHandler("destroy", async (options, ou
67
71
  if (options.dryRun) {
68
72
  output.setData({
69
73
  dryRun: true,
70
- wouldDestroy: monitorsToDestroy.map((m) => ({ id: m.id, name: m.name })),
74
+ wouldDestroy: monitorsToDestroy.map((m) => ({
75
+ id: m.id,
76
+ name: m.name,
77
+ })),
71
78
  total: monitorsToDestroy.length,
72
79
  });
73
80
  output.info("[DRY RUN] No changes will be made");
@@ -56,7 +56,10 @@ export const executeIntegrationsShow = createCommandHandler("integrations show",
56
56
  }
57
57
  const raw = response.data?.data;
58
58
  if (!raw) {
59
- output.setData({ error: "NOT_FOUND", message: "Integration not found." });
59
+ output.setData({
60
+ error: "NOT_FOUND",
61
+ message: "Integration not found.",
62
+ });
60
63
  output.error("Integration not found.");
61
64
  output.exit(1);
62
65
  }
@@ -120,7 +123,10 @@ export const executeIntegrationsUpdate = createCommandHandler("integrations upda
120
123
  }
121
124
  const raw = response.data?.data;
122
125
  if (!raw) {
123
- output.setData({ error: "NOT_FOUND", message: "Integration not found." });
126
+ output.setData({
127
+ error: "NOT_FOUND",
128
+ message: "Integration not found.",
129
+ });
124
130
  output.error("Integration not found.");
125
131
  output.exit(1);
126
132
  }
@@ -141,7 +147,10 @@ export const executeIntegrationsRemove = createCommandHandler("integrations remo
141
147
  }
142
148
  const raw = response.data?.data;
143
149
  if (!raw) {
144
- output.setData({ error: "NOT_FOUND", message: "Integration not found." });
150
+ output.setData({
151
+ error: "NOT_FOUND",
152
+ message: "Integration not found.",
153
+ });
145
154
  output.error("Integration not found.");
146
155
  output.exit(1);
147
156
  }
@@ -342,7 +351,9 @@ export const executeIntegrationsConnect = createCommandHandler("integrations con
342
351
  }
343
352
  }
344
353
  else {
345
- const categories = [...new Set(providers.map((p) => p.category))].sort();
354
+ const categories = [
355
+ ...new Set(providers.map((p) => p.category)),
356
+ ].sort();
346
357
  output.info("Available categories: " + categories.join(", "));
347
358
  }
348
359
  output.exit(1);
@@ -1,7 +1,7 @@
1
1
  import { resolveEnvironment } from "../../core/state.js";
2
2
  import { createSdkFromState } from "../../core/sdk.js";
3
3
  import { handleSDKErrorWithOutput } from "../../utils/sdk-error.js";
4
- import { createCommandHandler, } from "../../utils/command-wrapper.js";
4
+ import { createCommandHandler } from "../../utils/command-wrapper.js";
5
5
  const METRICS_PERIODS = ["1h", "6h", "24h", "7d", "30d"];
6
6
  /**
7
7
  * Show metrics summary from the hub
@@ -119,7 +119,8 @@ export const executeRun = createCommandHandler("run", async (options, output) =>
119
119
  handleSDKErrorWithOutput(err, output, "Failed to fetch run status");
120
120
  }
121
121
  const currentRun = runStatusResponse.data?.data;
122
- if (currentRun.status === "completed" || currentRun.status === "failed") {
122
+ if (currentRun.status === "completed" ||
123
+ currentRun.status === "failed") {
123
124
  if (currentRun.success) {
124
125
  waitSpinner.succeed(`Run ${currentRun.status}`);
125
126
  }
@@ -29,10 +29,10 @@ export const executeSecretsList = createCommandHandler("secrets list", async (op
29
29
  output.info(`Secrets (environment: ${env})`);
30
30
  output.blank();
31
31
  const table = output.table({
32
- head: ["Name", "Created", "Updated"],
32
+ head: ["Name"],
33
33
  });
34
34
  for (const s of secrets) {
35
- table.push([s.name, s.createdAt ?? "-", s.updatedAt ?? "-"]);
35
+ table.push([s.name]);
36
36
  }
37
37
  output.log(table.toString());
38
38
  });
@@ -80,8 +80,6 @@ export const executeSecretsSet = createCommandHandler("secrets set", async (opti
80
80
  const result = response.data;
81
81
  output.setData({
82
82
  name: result.data?.name ?? options.name,
83
- createdAt: result.data?.createdAt,
84
- updatedAt: result.data?.updatedAt,
85
83
  });
86
84
  output.success(`Secret "${result.data?.name ?? options.name}" saved.`);
87
85
  });
@@ -104,8 +102,6 @@ export const executeSecretsGet = createCommandHandler("secrets get", async (opti
104
102
  const secret = response.data?.data;
105
103
  output.setData(secret);
106
104
  output.info(`Secret: ${secret.name}`);
107
- output.dim(`Created: ${secret.createdAt ?? "-"}`);
108
- output.dim(`Updated: ${secret.updatedAt ?? "-"}`);
109
105
  });
110
106
  /**
111
107
  * Delete a secret (with confirmation unless --force; in JSON mode --force is required to avoid prompt).
@@ -1,37 +1,24 @@
1
1
  /**
2
- * Secrets configuration for CLI local runs.
3
- * Reads configuration from environment variables to construct a secret provider.
2
+ * Secrets configuration for CLI runs.
3
+ *
4
+ * Two providers:
5
+ * - `env`: reads secrets from environment variables (local dev, no hub needed)
6
+ * - `hub`: resolves secrets via POST /secrets/resolve on the hub API
4
7
  */
5
- import { type SecretProvider, type SecretProviderConfig } from "@griffin-app/griffin-executor";
8
+ import { type SecretProvider } from "@griffin-app/griffin-executor";
9
+ import type { GriffinHubSdk } from "@griffin-app/griffin-hub-sdk";
6
10
  /**
7
- * Read secrets provider configuration from environment variables.
8
- *
9
- * Supported configurations:
10
- *
11
- * 1. Environment provider (default if no config):
12
- * GRIFFIN_SECRETS_PROVIDER=env
13
- * GRIFFIN_SECRETS_ENV_PREFIX=APP_
14
- *
15
- * 2. AWS Secrets Manager:
16
- * GRIFFIN_SECRETS_PROVIDER=aws
17
- * GRIFFIN_SECRETS_AWS_REGION=us-east-1
18
- * GRIFFIN_SECRETS_AWS_PREFIX=myapp/
19
- * GRIFFIN_SECRETS_AWS_ROLE_ARN=arn:aws:iam::123:role/griffin
20
- * GRIFFIN_SECRETS_AWS_EXTERNAL_ID=xyz
21
- * GRIFFIN_SECRETS_AWS_ACCESS_KEY_ID=...
22
- * GRIFFIN_SECRETS_AWS_SECRET_ACCESS_KEY=...
23
- *
24
- * 3. HashiCorp Vault:
25
- * GRIFFIN_SECRETS_PROVIDER=vault
26
- * GRIFFIN_SECRETS_VAULT_ADDRESS=https://vault.example.com
27
- * GRIFFIN_SECRETS_VAULT_TOKEN=...
28
- * GRIFFIN_SECRETS_VAULT_NAMESPACE=myapp
29
- * GRIFFIN_SECRETS_VAULT_KV_VERSION=2
30
- * GRIFFIN_SECRETS_VAULT_PREFIX=myapp/
11
+ * Create an env-based secret provider for fully-local CLI runs (no hub).
31
12
  */
32
- export declare function getSecretsConfigFromEnv(): SecretProviderConfig;
13
+ export declare function createEnvSecretsProvider(): SecretProvider;
33
14
  /**
34
- * Create a secret provider for CLI local runs.
35
- * Reads configuration from environment variables.
15
+ * SecretProvider that resolves secrets via the hub's POST /secrets/resolve endpoint.
16
+ * The hub is the sole gateway for AWS Secrets Manager — no credentials leave the hub.
36
17
  */
37
- export declare function createSecretsProviderForCLI(): Promise<SecretProvider>;
18
+ export declare class HubSecretProvider implements SecretProvider {
19
+ readonly name = "hub";
20
+ private readonly sdk;
21
+ private readonly environment;
22
+ constructor(sdk: GriffinHubSdk, environment: string);
23
+ resolve(ref: string): Promise<string>;
24
+ }
@@ -1,96 +1,45 @@
1
1
  /**
2
- * Secrets configuration for CLI local runs.
3
- * Reads configuration from environment variables to construct a secret provider.
2
+ * Secrets configuration for CLI runs.
3
+ *
4
+ * Two providers:
5
+ * - `env`: reads secrets from environment variables (local dev, no hub needed)
6
+ * - `hub`: resolves secrets via POST /secrets/resolve on the hub API
4
7
  */
5
- import { createSecretProvider, } from "@griffin-app/griffin-executor";
8
+ import { EnvSecretProvider, } from "@griffin-app/griffin-executor";
6
9
  /**
7
- * Environment variable prefixes for secrets configuration.
10
+ * Environment variable name for selecting the local secrets provider.
11
+ * Only "env" is supported for fully-local runs without a hub.
8
12
  */
9
13
  const ENV_PREFIX = "GRIFFIN_SECRETS_";
10
14
  /**
11
- * Read secrets provider configuration from environment variables.
12
- *
13
- * Supported configurations:
14
- *
15
- * 1. Environment provider (default if no config):
16
- * GRIFFIN_SECRETS_PROVIDER=env
17
- * GRIFFIN_SECRETS_ENV_PREFIX=APP_
18
- *
19
- * 2. AWS Secrets Manager:
20
- * GRIFFIN_SECRETS_PROVIDER=aws
21
- * GRIFFIN_SECRETS_AWS_REGION=us-east-1
22
- * GRIFFIN_SECRETS_AWS_PREFIX=myapp/
23
- * GRIFFIN_SECRETS_AWS_ROLE_ARN=arn:aws:iam::123:role/griffin
24
- * GRIFFIN_SECRETS_AWS_EXTERNAL_ID=xyz
25
- * GRIFFIN_SECRETS_AWS_ACCESS_KEY_ID=...
26
- * GRIFFIN_SECRETS_AWS_SECRET_ACCESS_KEY=...
27
- *
28
- * 3. HashiCorp Vault:
29
- * GRIFFIN_SECRETS_PROVIDER=vault
30
- * GRIFFIN_SECRETS_VAULT_ADDRESS=https://vault.example.com
31
- * GRIFFIN_SECRETS_VAULT_TOKEN=...
32
- * GRIFFIN_SECRETS_VAULT_NAMESPACE=myapp
33
- * GRIFFIN_SECRETS_VAULT_KV_VERSION=2
34
- * GRIFFIN_SECRETS_VAULT_PREFIX=myapp/
15
+ * Create an env-based secret provider for fully-local CLI runs (no hub).
35
16
  */
36
- export function getSecretsConfigFromEnv() {
37
- const provider = process.env[`${ENV_PREFIX}PROVIDER`] || "env";
38
- switch (provider) {
39
- case "env":
40
- return {
41
- provider: "env",
42
- prefix: process.env[`${ENV_PREFIX}ENV_PREFIX`] || "",
43
- env: process.env,
44
- };
45
- case "aws": {
46
- const region = process.env[`${ENV_PREFIX}AWS_REGION`];
47
- if (!region) {
48
- throw new Error(`${ENV_PREFIX}AWS_REGION is required when GRIFFIN_SECRETS_PROVIDER=aws`);
49
- }
50
- const accessKeyId = process.env[`${ENV_PREFIX}AWS_ACCESS_KEY_ID`];
51
- const secretAccessKey = process.env[`${ENV_PREFIX}AWS_SECRET_ACCESS_KEY`];
52
- return {
53
- provider: "aws",
54
- region,
55
- prefix: process.env[`${ENV_PREFIX}AWS_PREFIX`],
56
- roleArn: process.env[`${ENV_PREFIX}AWS_ROLE_ARN`],
57
- externalId: process.env[`${ENV_PREFIX}AWS_EXTERNAL_ID`],
58
- credentials: accessKeyId && secretAccessKey
59
- ? { accessKeyId, secretAccessKey }
60
- : undefined,
61
- };
62
- }
63
- case "vault": {
64
- const address = process.env[`${ENV_PREFIX}VAULT_ADDRESS`];
65
- const token = process.env[`${ENV_PREFIX}VAULT_TOKEN`];
66
- if (!address) {
67
- throw new Error(`${ENV_PREFIX}VAULT_ADDRESS is required when GRIFFIN_SECRETS_PROVIDER=vault`);
68
- }
69
- if (!token) {
70
- throw new Error(`${ENV_PREFIX}VAULT_TOKEN is required when GRIFFIN_SECRETS_PROVIDER=vault`);
71
- }
72
- const kvVersionStr = process.env[`${ENV_PREFIX}VAULT_KV_VERSION`];
73
- const kvVersion = kvVersionStr === "1" || kvVersionStr === "2"
74
- ? parseInt(kvVersionStr)
75
- : 2;
76
- return {
77
- provider: "vault",
78
- address,
79
- token,
80
- namespace: process.env[`${ENV_PREFIX}VAULT_NAMESPACE`],
81
- kvVersion,
82
- prefix: process.env[`${ENV_PREFIX}VAULT_PREFIX`],
83
- };
84
- }
85
- default:
86
- throw new Error(`Unknown secrets provider: ${provider}. Supported: env, aws, vault`);
87
- }
17
+ export function createEnvSecretsProvider() {
18
+ return new EnvSecretProvider({
19
+ prefix: process.env[`${ENV_PREFIX}ENV_PREFIX`] || "",
20
+ env: process.env,
21
+ });
88
22
  }
89
23
  /**
90
- * Create a secret provider for CLI local runs.
91
- * Reads configuration from environment variables.
24
+ * SecretProvider that resolves secrets via the hub's POST /secrets/resolve endpoint.
25
+ * The hub is the sole gateway for AWS Secrets Manager — no credentials leave the hub.
92
26
  */
93
- export async function createSecretsProviderForCLI() {
94
- const config = getSecretsConfigFromEnv();
95
- return createSecretProvider(config);
27
+ export class HubSecretProvider {
28
+ name = "hub";
29
+ sdk;
30
+ environment;
31
+ constructor(sdk, environment) {
32
+ this.sdk = sdk;
33
+ this.environment = environment;
34
+ }
35
+ async resolve(ref) {
36
+ const response = await this.sdk.postSecretsResolve({
37
+ body: { name: ref, environment: this.environment },
38
+ });
39
+ const value = response.data?.data?.value;
40
+ if (value === undefined) {
41
+ throw new Error(`Secret "${ref}" not found for environment "${this.environment}"`);
42
+ }
43
+ return value;
44
+ }
96
45
  }
@@ -1,13 +1,14 @@
1
1
  import "tsx";
2
2
  import { Value } from "typebox/value";
3
- import { executeMonitorV1, AxiosAdapter, } from "@griffin-app/griffin-executor";
3
+ import { executeMonitorV1, AxiosAdapter, planHasSecrets, } from "@griffin-app/griffin-executor";
4
4
  import { MonitorDSLSchema } from "@griffin-app/griffin-core/schema";
5
5
  import { randomUUID } from "crypto";
6
6
  import { loadVariables } from "./core/variables.js";
7
7
  import { getProjectId } from "./core/state.js";
8
8
  import { resolveMonitor } from "./resolve.js";
9
9
  import { terminal } from "./utils/terminal.js";
10
- import { createSecretsProviderForCLI } from "./core/secrets.js";
10
+ import { createEnvSecretsProvider, HubSecretProvider } from "./core/secrets.js";
11
+ import { createSdkFromState } from "./core/sdk.js";
11
12
  function validateDsl(monitor) {
12
13
  const errors = Value.Errors(MonitorDSLSchema, monitor);
13
14
  if (errors.length > 0) {
@@ -25,13 +26,25 @@ export async function runTestFile(filePath, envName) {
25
26
  const rawMonitor = validateDsl(defaultExport.default);
26
27
  terminal.dim(`Project ID: ${projectId}`);
27
28
  const resolvedMonitor = resolveMonitor(rawMonitor, projectId, envName, variables);
28
- // Create secret provider from environment configuration
29
- const secretProvider = await createSecretsProviderForCLI();
29
+ // Create secret provider: prefer hub (authenticated) for cloud secrets,
30
+ // fall back to env provider for fully-local runs.
31
+ let secretProvider;
32
+ const monitorV1 = { ...resolvedMonitor, id: randomUUID() };
33
+ if (planHasSecrets(monitorV1)) {
34
+ try {
35
+ const sdk = await createSdkFromState();
36
+ secretProvider = new HubSecretProvider(sdk, envName);
37
+ }
38
+ catch {
39
+ // Hub not available — fall back to env provider
40
+ secretProvider = createEnvSecretsProvider();
41
+ }
42
+ }
43
+ else {
44
+ secretProvider = createEnvSecretsProvider();
45
+ }
30
46
  try {
31
- const result = await executeMonitorV1({
32
- ...resolvedMonitor,
33
- id: randomUUID(),
34
- }, "default-org", {
47
+ const result = await executeMonitorV1(monitorV1, "default-org", {
35
48
  mode: "local",
36
49
  httpClient: new AxiosAdapter(),
37
50
  secretProvider,
@@ -178,7 +178,12 @@ export class OutputContext {
178
178
  const envelope = {
179
179
  ok: false,
180
180
  command: this.commandName,
181
- error: { code, message, ...(details !== undefined && { details }), ...(hint && { hint }) },
181
+ error: {
182
+ code,
183
+ message,
184
+ ...(details !== undefined && { details }),
185
+ ...(hint && { hint }),
186
+ },
182
187
  };
183
188
  process.stderr.write(JSON.stringify(envelope) + "\n");
184
189
  }
@@ -47,7 +47,9 @@ function getSDKErrorCodeAndMessage(sdkError, context) {
47
47
  return {
48
48
  code: "CONFLICT",
49
49
  message: `${contextMsg}Conflict`,
50
- details: sdkError.body?.message ? { message: sdkError.body.message } : undefined,
50
+ details: sdkError.body?.message
51
+ ? { message: sdkError.body.message }
52
+ : undefined,
51
53
  hint: "The operation conflicts with the current state.",
52
54
  };
53
55
  case 422:
@@ -77,7 +79,9 @@ function getSDKErrorCodeAndMessage(sdkError, context) {
77
79
  details: {
78
80
  status: sdkError.status,
79
81
  statusText: sdkError.statusText,
80
- ...(sdkError.body?.message && { bodyMessage: sdkError.body.message }),
82
+ ...(sdkError.body?.message && {
83
+ bodyMessage: sdkError.body.message,
84
+ }),
81
85
  },
82
86
  hint: "The hub encountered an internal error.",
83
87
  };
@@ -88,7 +92,9 @@ function getSDKErrorCodeAndMessage(sdkError, context) {
88
92
  details: {
89
93
  status: sdkError.status,
90
94
  statusText: sdkError.statusText,
91
- ...(sdkError.body?.message && { bodyMessage: sdkError.body.message }),
95
+ ...(sdkError.body?.message && {
96
+ bodyMessage: sdkError.body.message,
97
+ }),
92
98
  ...(sdkError.message && { message: sdkError.message }),
93
99
  },
94
100
  };
@@ -116,7 +122,8 @@ export function handleSDKError(error, context) {
116
122
  }
117
123
  else if (typeof details === "object" && "errors" in details) {
118
124
  terminal.dim("Validation failed:");
119
- for (const err of details.errors) {
125
+ for (const err of details
126
+ .errors) {
120
127
  terminal.dim(` - ${err.message || err}`);
121
128
  }
122
129
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@griffin-app/griffin-cli",
3
- "version": "1.0.29",
3
+ "version": "1.0.30",
4
4
  "description": "CLI tool for running and managing griffin API tests",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -24,8 +24,8 @@
24
24
  "author": "",
25
25
  "license": "MIT",
26
26
  "dependencies": {
27
- "@griffin-app/griffin-hub-sdk": "1.0.25",
28
- "@griffin-app/griffin-executor": "0.1.1",
27
+ "@griffin-app/griffin-hub-sdk": "1.0.27",
28
+ "@griffin-app/griffin-executor": "0.1.2",
29
29
  "@griffin-app/griffin-core": "0.2.2",
30
30
  "better-auth": "^1.4.17",
31
31
  "cli-table3": "^0.6.5",