@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
@@ -1,107 +1,66 @@
1
- import { loadState, resolveEnvironment } from "../../core/state.js";
2
- import { discoverMonitors, formatDiscoveryErrors, } from "../../core/discovery.js";
1
+ import { resolveEnvironment } from "../../core/state.js";
3
2
  import { computeDiff, formatDiff } from "../../core/diff.js";
4
3
  import { applyDiff, formatApplyResult } from "../../core/apply.js";
5
- import { createSdkWithCredentials } from "../../core/sdk.js";
4
+ import { createSdkAndState } from "../../core/sdk.js";
6
5
  import { terminal } from "../../utils/terminal.js";
7
- import { withSDKErrorHandling } from "../../utils/sdk-error.js";
8
- import { loadVariables } from "../../core/variables.js";
9
- import { resolveMonitor } from "../../resolve.js";
6
+ import { withCommandErrorHandler } from "../../utils/command-wrapper.js";
7
+ import { discoverLocalMonitors, fetchRemoteMonitors, resolveLocalMonitors, } from "../../core/monitor-helpers.js";
10
8
  /**
11
9
  * Apply changes to the hub
12
10
  */
13
- export async function executeApply(options) {
14
- try {
15
- // Load state
16
- const state = await loadState();
17
- // Resolve environment
18
- const envName = await resolveEnvironment(options.env);
19
- // Check if runner is configured
20
- if (!state.hub?.baseUrl) {
21
- terminal.error("Hub connection not configured.");
22
- terminal.dim("Connect with:");
23
- terminal.dim(" griffin hub connect --url <url> --token <token>");
24
- terminal.exit(1);
25
- }
26
- terminal.info(`Applying to ${terminal.colors.cyan(envName)} environment`);
27
- terminal.blank();
28
- // Create SDK clients with credentials
29
- const sdk = await createSdkWithCredentials(state.hub.baseUrl);
30
- // Discover local monitors
31
- const discoveryPattern = state.discovery?.pattern || "**/__griffin__/*.{ts,js}";
32
- const discoveryIgnore = state.discovery?.ignore || [
33
- "node_modules/**",
34
- "dist/**",
35
- ];
36
- const spinner = terminal.spinner("Discovering local monitors...").start();
37
- const { monitors, errors } = await discoverMonitors(discoveryPattern, discoveryIgnore);
38
- if (errors.length > 0) {
39
- spinner.fail("Discovery failed");
40
- terminal.error(formatDiscoveryErrors(errors));
41
- terminal.exit(1);
42
- }
43
- spinner.succeed(`Found ${monitors.length} local monitor(s)`);
44
- // Fetch remote monitors for this project + environment
45
- const fetchSpinner = terminal
46
- .spinner("Fetching remote monitors...")
47
- .start();
48
- const response = await withSDKErrorHandling(() => sdk.getMonitor({
49
- query: {
50
- projectId: state.projectId,
51
- environment: envName,
52
- },
53
- }), "Failed to fetch remote monitors");
54
- const remoteMonitors = response?.data?.data;
55
- fetchSpinner.succeed(`Found ${remoteMonitors.length} remote monitor(s)`);
56
- // Load variables and resolve local monitors before computing diff
57
- const variables = await loadVariables(envName);
58
- const resolvedMonitors = monitors.map((p) => resolveMonitor(p.monitor, state.projectId, envName, variables));
59
- // Compute diff (include deletions if --prune)
60
- const diff = computeDiff(resolvedMonitors, remoteMonitors, {
61
- includeDeletions: options.prune || false,
62
- });
63
- // Show monitor
64
- terminal.blank();
65
- terminal.log(formatDiff(diff));
11
+ export const executeApply = withCommandErrorHandler(async (options) => {
12
+ const { sdk, state } = await createSdkAndState();
13
+ // Resolve environment
14
+ const envName = await resolveEnvironment(options.env);
15
+ terminal.info(`Applying to ${terminal.colors.cyan(envName)} environment`);
16
+ terminal.blank();
17
+ // Discover local monitors
18
+ const { monitors } = await discoverLocalMonitors(state);
19
+ // Fetch remote monitors for this project + environment
20
+ const remoteMonitors = await fetchRemoteMonitors(sdk, state.projectId, envName);
21
+ // Load variables and resolve local monitors before computing diff
22
+ const resolvedMonitors = await resolveLocalMonitors(monitors, state.projectId, envName);
23
+ // Compute diff (include deletions if --prune)
24
+ const diff = computeDiff(resolvedMonitors, remoteMonitors, {
25
+ includeDeletions: options.prune || false,
26
+ });
27
+ // Show monitor
28
+ terminal.blank();
29
+ terminal.log(formatDiff(diff));
30
+ terminal.blank();
31
+ // Check if there are changes
32
+ if (diff.summary.creates + diff.summary.updates + diff.summary.deletes ===
33
+ 0) {
34
+ terminal.success("No changes to apply.");
35
+ return;
36
+ }
37
+ // Show deletions warning if --prune
38
+ if (options.prune && diff.summary.deletes > 0) {
39
+ terminal.warn(`--prune will DELETE ${diff.summary.deletes} monitor(s) from the hub`);
66
40
  terminal.blank();
67
- // Check if there are changes
68
- if (diff.summary.creates + diff.summary.updates + diff.summary.deletes ===
69
- 0) {
70
- terminal.success("No changes to apply.");
41
+ }
42
+ // Ask for confirmation unless auto-approved
43
+ if (!options.autoApprove && !options.dryRun) {
44
+ const confirmed = await terminal.confirm("Do you want to perform these actions?");
45
+ if (!confirmed) {
46
+ terminal.warn("Apply cancelled.");
71
47
  return;
72
48
  }
73
- // Show deletions warning if --prune
74
- if (options.prune && diff.summary.deletes > 0) {
75
- terminal.warn(`--prune will DELETE ${diff.summary.deletes} monitor(s) from the hub`);
76
- terminal.blank();
77
- }
78
- // Ask for confirmation unless auto-approved
79
- if (!options.autoApprove && !options.dryRun) {
80
- const confirmed = await terminal.confirm("Do you want to perform these actions?");
81
- if (!confirmed) {
82
- terminal.warn("Apply cancelled.");
83
- return;
84
- }
85
- }
86
- // Apply changes with environment injection
87
- const applySpinner = terminal.spinner("Applying changes...").start();
88
- const result = await applyDiff(diff, sdk, {
89
- dryRun: options.dryRun,
90
- });
91
- if (result.success) {
92
- applySpinner.succeed("Changes applied successfully");
93
- }
94
- else {
95
- applySpinner.fail("Apply failed");
96
- }
97
- terminal.blank();
98
- terminal.log(formatApplyResult(result));
99
- if (!result.success) {
100
- terminal.exit(1);
101
- }
102
49
  }
103
- catch (error) {
104
- terminal.error(error.message);
50
+ // Apply changes with environment injection
51
+ const applySpinner = terminal.spinner("Applying changes...").start();
52
+ const result = await applyDiff(diff, sdk, {
53
+ dryRun: options.dryRun,
54
+ });
55
+ if (result.success) {
56
+ applySpinner.succeed("Changes applied successfully");
57
+ }
58
+ else {
59
+ applySpinner.fail("Apply failed");
60
+ }
61
+ terminal.blank();
62
+ terminal.log(formatApplyResult(result));
63
+ if (!result.success) {
105
64
  terminal.exit(1);
106
65
  }
107
- }
66
+ });
@@ -1,6 +1,6 @@
1
1
  export interface ConnectOptions {
2
2
  url: string;
3
- token?: string;
3
+ token: string;
4
4
  }
5
5
  /**
6
6
  * Configure hub connection settings
@@ -9,9 +9,7 @@ export async function executeConnect(options) {
9
9
  try {
10
10
  const state = await loadState();
11
11
  // Save token to user-level credentials file if provided
12
- if (options.token) {
13
- await saveHubCredentials(options.token);
14
- }
12
+ await saveHubCredentials(options.token);
15
13
  // Update hub config in project state (without token)
16
14
  state.hub = {
17
15
  baseUrl: options.url,
@@ -20,9 +18,7 @@ export async function executeConnect(options) {
20
18
  await saveState(state);
21
19
  terminal.success("Hub connection configured");
22
20
  terminal.log(` URL: ${terminal.colors.cyan(options.url)}`);
23
- if (options.token) {
24
- terminal.log(` API Token: ${terminal.colors.dim("***")} (saved to user credentials)`);
25
- }
21
+ terminal.log(` API Token: ${terminal.colors.dim("***")} (saved to user credentials)`);
26
22
  terminal.blank();
27
23
  }
28
24
  catch (error) {
@@ -0,0 +1,10 @@
1
+ export interface DestroyOptions {
2
+ autoApprove?: boolean;
3
+ dryRun?: boolean;
4
+ env: string;
5
+ monitor?: string;
6
+ }
7
+ /**
8
+ * Destroy monitors on the hub
9
+ */
10
+ export declare function executeDestroy(options: DestroyOptions): Promise<void>;
@@ -0,0 +1,141 @@
1
+ import { loadState, resolveEnvironment } from "../../core/state.js";
2
+ import { createSdkWithCredentials } from "../../core/sdk.js";
3
+ import { terminal } from "../../utils/terminal.js";
4
+ import { withSDKErrorHandling } from "../../utils/sdk-error.js";
5
+ /**
6
+ * Destroy monitors on the hub
7
+ */
8
+ export async function executeDestroy(options) {
9
+ try {
10
+ // Load state
11
+ const state = await loadState();
12
+ // Resolve environment
13
+ const envName = await resolveEnvironment(options.env);
14
+ // Check if hub is configured
15
+ if (!state.hub?.baseUrl) {
16
+ terminal.error("Hub connection not configured.");
17
+ terminal.dim("Connect with:");
18
+ terminal.dim(" griffin hub connect --url <url> --token <token>");
19
+ terminal.exit(1);
20
+ }
21
+ terminal.info(`Destroying monitors in ${terminal.colors.cyan(envName)} environment`);
22
+ terminal.blank();
23
+ // Create SDK client with credentials
24
+ const sdk = await createSdkWithCredentials(state.hub.baseUrl);
25
+ // Fetch remote monitors for this project + environment
26
+ const fetchSpinner = terminal
27
+ .spinner("Fetching remote monitors...")
28
+ .start();
29
+ const response = await withSDKErrorHandling(() => sdk.getMonitor({
30
+ query: {
31
+ projectId: state.projectId,
32
+ environment: envName,
33
+ },
34
+ }), "Failed to fetch remote monitors");
35
+ const remoteMonitors = response?.data?.data;
36
+ fetchSpinner.succeed(`Found ${remoteMonitors.length} remote monitor(s)`);
37
+ if (remoteMonitors.length === 0) {
38
+ terminal.success("No monitors to destroy.");
39
+ return;
40
+ }
41
+ // Filter monitors if --monitor option is provided
42
+ let monitorsToDestroy = remoteMonitors;
43
+ if (options.monitor) {
44
+ const targetMonitor = remoteMonitors.find((m) => m.name === options.monitor || m.id === options.monitor);
45
+ if (!targetMonitor) {
46
+ terminal.error(`Monitor "${options.monitor}" not found in ${envName} environment`);
47
+ terminal.blank();
48
+ terminal.dim("Available monitors:");
49
+ remoteMonitors.forEach((m) => {
50
+ terminal.dim(` - ${m.name} (${m.id})`);
51
+ });
52
+ terminal.exit(1);
53
+ return; // TypeScript doesn't know exit(1) terminates
54
+ }
55
+ monitorsToDestroy = [targetMonitor];
56
+ }
57
+ // Show what will be destroyed
58
+ terminal.blank();
59
+ terminal.warn(`The following ${monitorsToDestroy.length} monitor(s) will be DESTROYED:`);
60
+ terminal.blank();
61
+ monitorsToDestroy.forEach((monitor) => {
62
+ terminal.log(` ${terminal.colors.red("-")} ${monitor.name} (${monitor.id})`);
63
+ });
64
+ terminal.blank();
65
+ // Show dry run message if applicable
66
+ if (options.dryRun) {
67
+ terminal.info("[DRY RUN] No changes will be made");
68
+ terminal.blank();
69
+ terminal.log("Summary:");
70
+ terminal.log(` Would destroy: ${monitorsToDestroy.length} monitor(s)`);
71
+ return;
72
+ }
73
+ // Ask for confirmation unless auto-approved
74
+ if (!options.autoApprove) {
75
+ terminal.blank();
76
+ terminal.warn(terminal.colors.bold("This action is DESTRUCTIVE and cannot be undone!"));
77
+ terminal.blank();
78
+ const confirmed = await terminal.confirm("Do you really want to destroy these monitors?");
79
+ if (!confirmed) {
80
+ terminal.warn("Destroy cancelled.");
81
+ return;
82
+ }
83
+ // Double confirmation for destroying all monitors
84
+ if (!options.monitor && monitorsToDestroy.length > 1) {
85
+ terminal.blank();
86
+ const doubleConfirmed = await terminal.confirm(`Type 'yes' to confirm destroying ALL ${monitorsToDestroy.length} monitors`);
87
+ if (!doubleConfirmed) {
88
+ terminal.warn("Destroy cancelled.");
89
+ return;
90
+ }
91
+ }
92
+ }
93
+ // Destroy monitors
94
+ terminal.blank();
95
+ const destroySpinner = terminal.spinner("Destroying monitors...").start();
96
+ let successCount = 0;
97
+ let failureCount = 0;
98
+ const errors = [];
99
+ for (const monitor of monitorsToDestroy) {
100
+ try {
101
+ await withSDKErrorHandling(() => sdk.deleteMonitorById({
102
+ path: {
103
+ id: monitor.id,
104
+ },
105
+ }), `Failed to delete monitor "${monitor.name}"`);
106
+ successCount++;
107
+ terminal.success(`Destroyed: ${terminal.colors.cyan(monitor.name)}`);
108
+ }
109
+ catch (error) {
110
+ failureCount++;
111
+ const errorMessage = error.message;
112
+ errors.push({ monitor, error: errorMessage });
113
+ terminal.error(`Failed to destroy: ${monitor.name} - ${errorMessage}`);
114
+ }
115
+ }
116
+ if (failureCount === 0) {
117
+ destroySpinner.succeed("All monitors destroyed successfully");
118
+ }
119
+ else {
120
+ destroySpinner.fail("Some monitors failed to destroy");
121
+ }
122
+ // Show summary
123
+ terminal.blank();
124
+ terminal.log("Destroy complete:");
125
+ terminal.blank();
126
+ terminal.log(` ${terminal.colors.green("✓")} Destroyed: ${successCount}`);
127
+ if (failureCount > 0) {
128
+ terminal.log(` ${terminal.colors.red("✗")} Failed: ${failureCount}`);
129
+ terminal.blank();
130
+ terminal.error("Errors:");
131
+ errors.forEach(({ monitor, error }) => {
132
+ terminal.error(` - ${monitor.name}: ${error}`);
133
+ });
134
+ terminal.exit(1);
135
+ }
136
+ }
137
+ catch (error) {
138
+ terminal.error(error.message);
139
+ terminal.exit(1);
140
+ }
141
+ }
@@ -2,45 +2,45 @@ import type { IntegrationCategory, Provider } from "@griffin-app/griffin-ts/type
2
2
  export interface IntegrationsListOptions {
3
3
  category?: IntegrationCategory;
4
4
  provider?: Provider;
5
- environment?: string;
5
+ environment: string;
6
6
  enabled?: boolean;
7
7
  json?: boolean;
8
8
  }
9
- export declare function executeIntegrationsList(options: IntegrationsListOptions): Promise<void>;
9
+ export declare const executeIntegrationsList: (options: IntegrationsListOptions) => Promise<void>;
10
10
  export interface IntegrationsShowOptions {
11
11
  id: string;
12
12
  json?: boolean;
13
13
  }
14
- export declare function executeIntegrationsShow(options: IntegrationsShowOptions): Promise<void>;
14
+ export declare const executeIntegrationsShow: (options: IntegrationsShowOptions) => Promise<void>;
15
15
  export interface IntegrationsAddOptions {
16
16
  category: IntegrationCategory;
17
17
  provider: Provider;
18
18
  name: string;
19
19
  config?: Record<string, string>;
20
- environment?: string;
20
+ environment: string;
21
21
  enabled?: boolean;
22
22
  json?: boolean;
23
23
  }
24
- export declare function executeIntegrationsAdd(options: IntegrationsAddOptions): Promise<void>;
24
+ export declare const executeIntegrationsAdd: (options: IntegrationsAddOptions) => Promise<void>;
25
25
  export interface IntegrationsUpdateOptions {
26
26
  id: string;
27
27
  name?: string;
28
28
  config?: Record<string, string>;
29
- environment?: string;
29
+ environment: string;
30
30
  enabled?: boolean;
31
31
  json?: boolean;
32
32
  }
33
- export declare function executeIntegrationsUpdate(options: IntegrationsUpdateOptions): Promise<void>;
33
+ export declare const executeIntegrationsUpdate: (options: IntegrationsUpdateOptions) => Promise<void>;
34
34
  export interface IntegrationsRemoveOptions {
35
35
  id: string;
36
36
  force?: boolean;
37
37
  }
38
- export declare function executeIntegrationsRemove(options: IntegrationsRemoveOptions): Promise<void>;
38
+ export declare const executeIntegrationsRemove: (options: IntegrationsRemoveOptions) => Promise<void>;
39
39
  export interface IntegrationsConnectOptions {
40
40
  category: IntegrationCategory;
41
41
  provider: Provider;
42
42
  name?: string;
43
- environment?: string;
43
+ environment: string;
44
44
  json?: boolean;
45
45
  }
46
46
  export declare function printConnectHelp(): void;