@griffin-app/griffin-cli 1.0.37 → 1.0.39

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 (53) hide show
  1. package/dist/cli.js +0 -0
  2. package/dist/commands/hub/runs.js +3 -2
  3. package/dist/commands/validate.js +2 -2
  4. package/dist/monitor-runner.js +9 -1
  5. package/package.json +2 -2
  6. package/dist/commands/apply.d.ts +0 -9
  7. package/dist/commands/apply.js +0 -76
  8. package/dist/commands/config.d.ts +0 -36
  9. package/dist/commands/config.js +0 -144
  10. package/dist/commands/configure-runner-host.d.ts +0 -2
  11. package/dist/commands/configure-runner-host.js +0 -41
  12. package/dist/commands/deploy.d.ts +0 -1
  13. package/dist/commands/deploy.js +0 -36
  14. package/dist/commands/execute-remote.d.ts +0 -1
  15. package/dist/commands/execute-remote.js +0 -33
  16. package/dist/commands/hub/config.d.ts +0 -27
  17. package/dist/commands/hub/config.js +0 -102
  18. package/dist/commands/hub/plan.d.ts +0 -8
  19. package/dist/commands/hub/plan.js +0 -75
  20. package/dist/commands/local/config.d.ts +0 -28
  21. package/dist/commands/local/config.js +0 -82
  22. package/dist/commands/logs.d.ts +0 -1
  23. package/dist/commands/logs.js +0 -20
  24. package/dist/commands/plan.d.ts +0 -8
  25. package/dist/commands/plan.js +0 -58
  26. package/dist/commands/run-remote.d.ts +0 -11
  27. package/dist/commands/run-remote.js +0 -98
  28. package/dist/commands/run.d.ts +0 -4
  29. package/dist/commands/run.js +0 -86
  30. package/dist/commands/runner.d.ts +0 -12
  31. package/dist/commands/runner.js +0 -53
  32. package/dist/commands/status.d.ts +0 -8
  33. package/dist/commands/status.js +0 -75
  34. package/dist/core/plan-diff.d.ts +0 -41
  35. package/dist/core/plan-diff.js +0 -257
  36. package/dist/output/context.d.ts +0 -18
  37. package/dist/output/context.js +0 -22
  38. package/dist/output/index.d.ts +0 -3
  39. package/dist/output/index.js +0 -2
  40. package/dist/output/renderer.d.ts +0 -6
  41. package/dist/output/renderer.js +0 -348
  42. package/dist/output/types.d.ts +0 -153
  43. package/dist/output/types.js +0 -1
  44. package/dist/providers/registry.d.ts +0 -24
  45. package/dist/providers/registry.js +0 -109
  46. package/dist/schemas/payload.d.ts +0 -6
  47. package/dist/schemas/payload.js +0 -8
  48. package/dist/test-discovery.d.ts +0 -4
  49. package/dist/test-discovery.js +0 -25
  50. package/dist/test-runner.d.ts +0 -6
  51. package/dist/test-runner.js +0 -56
  52. package/dist/utils/console.d.ts +0 -5
  53. package/dist/utils/console.js +0 -5
@@ -1,75 +0,0 @@
1
- import { loadState, resolveEnvironment } from "../../core/state.js";
2
- import { discoverMonitors, formatDiscoveryErrors } from "../../core/discovery.js";
3
- import { createSdkWithCredentials } from "../../core/sdk.js";
4
- import { computeDiff, formatDiff, formatDiffJson } from "../../core/diff.js";
5
- import { terminal } from "../../utils/terminal.js";
6
- import { withSDKErrorHandling } from "../../utils/sdk-error.js";
7
- import { loadVariables } from "../../core/variables.js";
8
- import { resolveMonitor } from "../../resolve.js";
9
- /**
10
- * Show what changes would be applied
11
- */
12
- export async function executeMonitor(options) {
13
- try {
14
- // Load state
15
- const state = await loadState();
16
- // Resolve environment
17
- const envName = await resolveEnvironment(options.env);
18
- if (!state.hub?.baseUrl) {
19
- terminal.error("Hub connection not configured.");
20
- terminal.dim("Connect with:");
21
- terminal.dim(" griffin hub connect --url <url> --token <token>");
22
- terminal.exit(1);
23
- }
24
- // Discover local monitors
25
- const discoveryPattern = state.discovery?.pattern || "**/__griffin__/*.{ts,js}";
26
- const discoveryIgnore = state.discovery?.ignore || [
27
- "node_modules/**",
28
- "dist/**",
29
- ];
30
- const spinner = terminal.spinner("Discovering local monitors...").start();
31
- const { monitors, errors } = await discoverMonitors(discoveryPattern, discoveryIgnore);
32
- if (errors.length > 0) {
33
- spinner.fail("Discovery failed");
34
- terminal.error(formatDiscoveryErrors(errors));
35
- terminal.exit(1);
36
- }
37
- spinner.succeed(`Found ${monitors.length} local monitor(s)`);
38
- // Create SDK clients with credentials
39
- const sdk = await createSdkWithCredentials(state.hub.baseUrl);
40
- // Fetch remote monitors for this project + environment
41
- const fetchSpinner = terminal.spinner("Fetching remote monitors...").start();
42
- const response = await withSDKErrorHandling(() => sdk.getMonitor({
43
- query: {
44
- projectId: state.projectId,
45
- environment: envName,
46
- },
47
- }), "Failed to fetch remote monitors");
48
- const remoteMonitors = response?.data?.data;
49
- fetchSpinner.succeed(`Found ${remoteMonitors.length} remote monitor(s)`);
50
- // Load variables and resolve local monitors before computing diff
51
- const variables = await loadVariables(envName);
52
- const resolvedMonitors = monitors.map((p) => resolveMonitor(p.monitor, state.projectId, envName, variables));
53
- // Compute diff (no deletions shown by default)
54
- const diff = computeDiff(resolvedMonitors, remoteMonitors, {
55
- includeDeletions: false,
56
- });
57
- terminal.blank();
58
- // Output
59
- if (options.json) {
60
- terminal.log(formatDiffJson(diff));
61
- }
62
- else {
63
- terminal.log(formatDiff(diff));
64
- }
65
- // Exit with error code if there are changes
66
- if (diff.summary.creates + diff.summary.updates + diff.summary.deletes >
67
- 0) {
68
- terminal.exit(2); // Exit code 2 indicates changes pending
69
- }
70
- }
71
- catch (error) {
72
- terminal.error(error.message);
73
- terminal.exit(1);
74
- }
75
- }
@@ -1,28 +0,0 @@
1
- export interface ConfigAddTargetOptions {
2
- env: string;
3
- key: string;
4
- url: string;
5
- }
6
- export interface ConfigRemoveTargetOptions {
7
- env: string;
8
- key: string;
9
- }
10
- export interface ConfigSetDefaultEnvOptions {
11
- env: string;
12
- }
13
- /**
14
- * List all local environments and their targets
15
- */
16
- export declare function executeConfigList(): Promise<void>;
17
- /**
18
- * Add a target to a local environment
19
- */
20
- export declare function executeConfigAddTarget(options: ConfigAddTargetOptions): Promise<void>;
21
- /**
22
- * Remove a target from a local environment
23
- */
24
- export declare function executeConfigRemoveTarget(options: ConfigRemoveTargetOptions): Promise<void>;
25
- /**
26
- * Set the default environment
27
- */
28
- export declare function executeConfigSetDefaultEnv(options: ConfigSetDefaultEnvOptions): Promise<void>;
@@ -1,82 +0,0 @@
1
- import { addTarget, removeTarget, listEnvironments, setDefaultEnvironment, } from "../../core/state.js";
2
- /**
3
- * List all local environments and their targets
4
- */
5
- export async function executeConfigList() {
6
- try {
7
- const environments = await listEnvironments();
8
- const envNames = Object.keys(environments);
9
- if (envNames.length === 0) {
10
- console.log("No environments configured.");
11
- console.log("");
12
- console.log("Add a target to create an environment:");
13
- console.log(" griffin local config add-target --env <name> --key <key> --url <url>");
14
- return;
15
- }
16
- console.log("Local environments:");
17
- console.log("");
18
- for (const envName of envNames) {
19
- const env = environments[envName];
20
- const marker = env.isDefault ? " (default)" : "";
21
- console.log(` ${envName}${marker}`);
22
- const targetKeys = Object.keys(env.targets);
23
- if (targetKeys.length === 0) {
24
- console.log(" (no targets)");
25
- }
26
- else {
27
- for (const [key, url] of Object.entries(env.targets)) {
28
- console.log(` ${key}: ${url}`);
29
- }
30
- }
31
- console.log("");
32
- }
33
- }
34
- catch (error) {
35
- console.error(`Error: ${error.message}`);
36
- process.exit(1);
37
- }
38
- }
39
- /**
40
- * Add a target to a local environment
41
- */
42
- export async function executeConfigAddTarget(options) {
43
- try {
44
- await addTarget(options.env, options.key, options.url);
45
- console.log(`✓ Target added to '${options.env}' environment`);
46
- console.log(` ${options.key}: ${options.url}`);
47
- console.log("");
48
- }
49
- catch (error) {
50
- console.error(`Error: ${error.message}`);
51
- process.exit(1);
52
- }
53
- }
54
- /**
55
- * Remove a target from a local environment
56
- */
57
- export async function executeConfigRemoveTarget(options) {
58
- try {
59
- await removeTarget(options.env, options.key);
60
- console.log(`✓ Target removed from '${options.env}' environment`);
61
- console.log(` Key: ${options.key}`);
62
- console.log("");
63
- }
64
- catch (error) {
65
- console.error(`Error: ${error.message}`);
66
- process.exit(1);
67
- }
68
- }
69
- /**
70
- * Set the default environment
71
- */
72
- export async function executeConfigSetDefaultEnv(options) {
73
- try {
74
- await setDefaultEnvironment(options.env);
75
- console.log(`✓ Set '${options.env}' as default environment`);
76
- console.log("");
77
- }
78
- catch (error) {
79
- console.error(`Error: ${error.message}`);
80
- process.exit(1);
81
- }
82
- }
@@ -1 +0,0 @@
1
- export declare function executeLogs(checkName: string): Promise<void>;
@@ -1,20 +0,0 @@
1
- import { getRunnerHost } from "./configure-runner-host";
2
- const axios = require("axios");
3
- export async function executeLogs(checkName) {
4
- const runnerHost = getRunnerHost();
5
- if (!runnerHost) {
6
- console.error("ERROR: No runner host configured. Run: griffin configure-runner-host <host>");
7
- process.exit(1);
8
- }
9
- console.log(`Fetching logs for: ${checkName}`);
10
- try {
11
- // TODO: Implement log fetching from runner API
12
- const response = await axios.get(`${runnerHost}/api/tests/${checkName}/logs`);
13
- console.log(JSON.stringify(response.data, null, 2));
14
- }
15
- catch (error) {
16
- console.error("ERROR: Failed to fetch logs");
17
- console.error(error.message || String(error));
18
- process.exit(1);
19
- }
20
- }
@@ -1,8 +0,0 @@
1
- export interface MonitorOptions {
2
- json?: boolean;
3
- env?: string;
4
- }
5
- /**
6
- * Show what changes would be applied
7
- */
8
- export declare function executeMonitor(options: MonitorOptions): Promise<void>;
@@ -1,58 +0,0 @@
1
- import { loadState, resolveEnvironment } from "../core/state.js";
2
- import { discoverMonitors, formatDiscoveryErrors } from "../core/discovery.js";
3
- import { createSdkClients } from "../core/sdk.js";
4
- import { computeDiff, formatDiff, formatDiffJson } from "../core/diff.js";
5
- /**
6
- * Show what changes would be applied
7
- */
8
- export async function executeMonitor(options) {
9
- try {
10
- // Load state
11
- const state = await loadState();
12
- // Resolve environment
13
- const envName = await resolveEnvironment(options.env);
14
- if (!state.runner?.baseUrl) {
15
- console.error("Error: Runner URL not configured.");
16
- console.log("Configure with:");
17
- console.log(" griffin runner set --base-url <url> --api-token <token>");
18
- process.exit(1);
19
- }
20
- // Discover local monitors
21
- const discoveryPattern = state.discovery?.pattern || "**/__griffin__/*.{ts,js}";
22
- const discoveryIgnore = state.discovery?.ignore || [
23
- "node_modules/**",
24
- "dist/**",
25
- ];
26
- const { monitors, errors } = await discoverMonitors(discoveryPattern, discoveryIgnore);
27
- if (errors.length > 0) {
28
- console.error(formatDiscoveryErrors(errors));
29
- process.exit(1);
30
- }
31
- // Create SDK clients
32
- const { planApi } = createSdkClients({
33
- baseUrl: state.runner.baseUrl,
34
- apiToken: state.runner.apiToken || undefined,
35
- });
36
- // Fetch remote monitors for this project
37
- const response = await planApi.planGet(state.projectId);
38
- const remoteMonitors = response.data.data.map((p) => p);
39
- // Compute diff for this environment
40
- const diff = computeDiff(monitors.map((p) => p.monitor), state, remoteMonitors, envName);
41
- // Output
42
- if (options.json) {
43
- console.log(formatDiffJson(diff));
44
- }
45
- else {
46
- console.log(formatDiff(diff));
47
- }
48
- // Exit with error code if there are changes
49
- if (diff.summary.creates + diff.summary.updates + diff.summary.deletes >
50
- 0) {
51
- process.exit(2); // Exit code 2 indicates changes pending
52
- }
53
- }
54
- catch (error) {
55
- console.error(`Error: ${error.message}`);
56
- process.exit(1);
57
- }
58
- }
@@ -1,11 +0,0 @@
1
- export interface RunOptions {
2
- planId?: string;
3
- planName?: string;
4
- wait?: boolean;
5
- env?: string;
6
- targetEnv?: string;
7
- }
8
- /**
9
- * Trigger a monitor run on the runner
10
- */
11
- export declare function executeRun(options: RunOptions): Promise<void>;
@@ -1,98 +0,0 @@
1
- import { loadState, resolveEnvironment } from "../core/state.js";
2
- import { createSdkClients } from "../core/sdk.js";
3
- /**
4
- * Trigger a monitor run on the runner
5
- */
6
- export async function executeRun(options) {
7
- try {
8
- // TODO: remove this. Users shoud be able to execute all monitors if they want.
9
- if (!options.planId && !options.planName) {
10
- console.error("Error: Either --monitor-id or --monitor-name must be provided");
11
- process.exit(1);
12
- }
13
- if (!options.targetEnv) {
14
- console.error("Error: --target-env must be provided (e.g., staging, production)");
15
- process.exit(1);
16
- }
17
- // Load state
18
- const state = await loadState();
19
- if (!state.runner?.baseUrl) {
20
- console.error("Error: Runner URL not configured.");
21
- console.log("Configure with:");
22
- console.log(" griffin runner set --base-url <url> --api-token <token>");
23
- process.exit(1);
24
- }
25
- // Create SDK clients (for status polling)
26
- const { runsApi } = createSdkClients({
27
- baseUrl: state.runner.baseUrl,
28
- apiToken: state.runner.apiToken || undefined,
29
- });
30
- // Resolve monitor ID from name if needed
31
- let planId = options.planId;
32
- if (!planId && options.planName) {
33
- // Resolve environment to search in
34
- const envName = await resolveEnvironment(options.env);
35
- const envMonitors = state.monitors[envName] || [];
36
- const stateEntry = envMonitors.find((p) => p.planName === options.planName);
37
- if (!stateEntry) {
38
- console.error(`Error: Monitor "${options.planName}" not found in state`);
39
- console.error("Run 'griffin apply' to sync your monitors first");
40
- process.exit(1);
41
- }
42
- planId = stateEntry.planId;
43
- }
44
- // Trigger the run with environment
45
- console.log(`Triggering run for monitor: ${planId}`);
46
- console.log(`Target environment: ${options.targetEnv}`);
47
- const response = await runsApi.runsTriggerMonitorIdPost(planId, {
48
- environment: options.targetEnv,
49
- });
50
- console.log(`Run ID: ${response.data.data.id}`);
51
- console.log(`Status: ${response.data.data.status}`);
52
- console.log(`Started: ${new Date(response.data.data.startedAt).toLocaleString()}`);
53
- // Wait for completion if requested
54
- if (options.wait) {
55
- console.log("");
56
- console.log("Waiting for run to complete...");
57
- const runId = response.data.data.id;
58
- let completed = false;
59
- while (!completed) {
60
- await new Promise((resolve) => setTimeout(resolve, 2000)); // Poll every 2 seconds
61
- const { data: runResponse } = await runsApi.runsIdGet(runId);
62
- const run = runResponse.data;
63
- if (run.status === "completed" || run.status === "failed") {
64
- completed = true;
65
- console.log("");
66
- console.log(`✓ Run ${run.status}`);
67
- if (run.duration_ms) {
68
- console.log(`Duration: ${(run.duration_ms / 1000).toFixed(2)}s`);
69
- }
70
- if (run.success !== undefined) {
71
- console.log(`Success: ${run.success ? "Yes" : "No"}`);
72
- }
73
- if (run.errors && run.errors.length > 0) {
74
- console.log("");
75
- console.log("Errors:");
76
- for (const error of run.errors) {
77
- console.log(` - ${error}`);
78
- }
79
- }
80
- if (!run.success) {
81
- process.exit(1);
82
- }
83
- }
84
- else {
85
- process.stdout.write(".");
86
- }
87
- }
88
- }
89
- else {
90
- console.log("");
91
- console.log("Run started. Use 'griffin status' to check progress.");
92
- }
93
- }
94
- catch (error) {
95
- console.error(`Error: ${error.message}`);
96
- process.exit(1);
97
- }
98
- }
@@ -1,4 +0,0 @@
1
- export interface RunLocalOptions {
2
- env?: string;
3
- }
4
- export declare function executeRunLocal(options?: RunLocalOptions): Promise<void>;
@@ -1,86 +0,0 @@
1
- import { findTestFiles } from "../test-discovery.js";
2
- import { runTestFile } from "../test-runner.js";
3
- import { resolveEnvironment, getEnvironment } from "../core/state.js";
4
- import { basename } from "path";
5
- export async function executeRunLocal(options = {}) {
6
- try {
7
- // Resolve environment
8
- const envName = await resolveEnvironment(options.env);
9
- const envConfig = await getEnvironment(envName);
10
- console.log(`Running tests locally against '${envName}' environment`);
11
- console.log(`Target: ${envConfig.baseUrl}`);
12
- console.log("");
13
- const testFiles = findTestFiles();
14
- if (testFiles.length === 0) {
15
- console.error("No test files found. Looking for .ts files in __griffin__ directories.");
16
- process.exit(1);
17
- }
18
- console.log(`Found ${testFiles.length} test file(s):`);
19
- testFiles.forEach((file) => console.log(` - ${file}`));
20
- console.log("");
21
- const results = await Promise.all(testFiles.map(async (file) => {
22
- const fileName = basename(file);
23
- console.log(`Running ${fileName}`);
24
- const result = await runTest(file, envConfig.baseUrl);
25
- return result;
26
- }));
27
- // Print summary
28
- const successful = results.filter((r) => r.success).length;
29
- const failed = results.length - successful;
30
- console.log("");
31
- console.log(`Summary: ${successful} passed, ${failed} failed`);
32
- if (failed > 0) {
33
- process.exit(1);
34
- }
35
- }
36
- catch (error) {
37
- console.error(`Error: ${error.message}`);
38
- process.exit(1);
39
- }
40
- }
41
- async function runTest(file, baseUrl) {
42
- try {
43
- const result = await runTestFile(file, baseUrl);
44
- console.log("SUCCESS: result", result);
45
- return { success: result.success };
46
- }
47
- catch (error) {
48
- console.error("ERROR: Failed to run test");
49
- console.error(error.message || String(error));
50
- return { success: false };
51
- }
52
- }
53
- function displayResults(result) {
54
- if (!result)
55
- return false;
56
- const success = result.success || false;
57
- const nodeResults = result.results || [];
58
- const errors = result.errors || [];
59
- nodeResults.forEach((nodeResult) => {
60
- const nodeId = nodeResult.nodeId || "unknown";
61
- const nodeSuccess = nodeResult.success || false;
62
- const status = nodeSuccess ? "." : "E";
63
- process.stdout.write(status);
64
- if (!nodeSuccess) {
65
- const error = nodeResult.error || "Unknown error";
66
- console.log("");
67
- console.log(`ERROR in ${nodeId}: ${error}`);
68
- }
69
- });
70
- console.log("");
71
- if (errors.length > 0) {
72
- console.log("Errors:");
73
- errors.forEach((error) => console.log(` - ${error}`));
74
- }
75
- // Check if any node failed or if there are errors
76
- const anyFailed = nodeResults.some((nodeResult) => !nodeResult.success) ||
77
- errors.length > 0;
78
- const testPassed = success && !anyFailed;
79
- if (testPassed) {
80
- console.log("✓ Test passed");
81
- }
82
- else {
83
- console.log("✗ Test failed");
84
- }
85
- return testPassed;
86
- }
@@ -1,12 +0,0 @@
1
- export interface RunnerSetOptions {
2
- baseUrl: string;
3
- apiToken?: string;
4
- }
5
- /**
6
- * Configure runner connection settings
7
- */
8
- export declare function executeRunnerSet(options: RunnerSetOptions): Promise<void>;
9
- /**
10
- * Show current runner configuration
11
- */
12
- export declare function executeRunnerShow(): Promise<void>;
@@ -1,53 +0,0 @@
1
- import { loadState, saveState } from "../core/state.js";
2
- /**
3
- * Configure runner connection settings
4
- */
5
- export async function executeRunnerSet(options) {
6
- try {
7
- const state = await loadState();
8
- // Update runner config
9
- state.runner = {
10
- baseUrl: options.baseUrl,
11
- apiToken: options.apiToken,
12
- };
13
- await saveState(state);
14
- console.log("✓ Runner configuration updated");
15
- console.log(` Base URL: ${options.baseUrl}`);
16
- if (options.apiToken) {
17
- console.log(" API Token: ***");
18
- }
19
- console.log("");
20
- }
21
- catch (error) {
22
- console.error(`Error: ${error.message}`);
23
- process.exit(1);
24
- }
25
- }
26
- /**
27
- * Show current runner configuration
28
- */
29
- export async function executeRunnerShow() {
30
- try {
31
- const state = await loadState();
32
- if (!state.runner) {
33
- console.log("No runner configured.");
34
- console.log("");
35
- console.log("Configure with:");
36
- console.log(" griffin runner set --base-url <url> --api-token <token>");
37
- return;
38
- }
39
- console.log("Runner configuration:");
40
- console.log(` Base URL: ${state.runner.baseUrl}`);
41
- if (state.runner.apiToken) {
42
- console.log(` API Token: ${state.runner.apiToken.substring(0, 8)}...`);
43
- }
44
- else {
45
- console.log(" API Token: (not set)");
46
- }
47
- console.log("");
48
- }
49
- catch (error) {
50
- console.error(`Error: ${error.message}`);
51
- process.exit(1);
52
- }
53
- }
@@ -1,8 +0,0 @@
1
- export interface StatusOptions {
2
- planId?: string;
3
- limit?: number;
4
- }
5
- /**
6
- * Show runner status and recent runs
7
- */
8
- export declare function executeStatus(options: StatusOptions): Promise<void>;
@@ -1,75 +0,0 @@
1
- import { loadState } from "../core/state.js";
2
- import { createSdkClients } from "../core/sdk.js";
3
- /**
4
- * Show runner status and recent runs
5
- */
6
- export async function executeStatus(options) {
7
- try {
8
- // Load state
9
- const state = await loadState();
10
- if (!state.runner?.baseUrl) {
11
- console.error("Error: Runner URL not configured.");
12
- console.log("Configure with:");
13
- console.log(" griffin runner set --base-url <url> --api-token <token>");
14
- process.exit(1);
15
- }
16
- // Create SDK clients
17
- const { runsApi } = createSdkClients({
18
- baseUrl: state.runner.baseUrl,
19
- apiToken: state.runner.apiToken || undefined,
20
- });
21
- console.log(`Runner: ${state.runner.baseUrl}`);
22
- console.log("");
23
- // Get recent runs
24
- const limit = options.limit || 10;
25
- const response = await runsApi.runsGet(options.planId, undefined, limit, 0);
26
- const runs = response.data;
27
- if (runs.total === 0) {
28
- console.log("No runs found.");
29
- return;
30
- }
31
- console.log(`Recent runs (${runs.total} total):`);
32
- console.log("");
33
- for (const run of runs.runs) {
34
- const statusIcon = getStatusIcon(run.status, run.success);
35
- const duration = run.duration_ms
36
- ? ` (${(run.duration_ms / 1000).toFixed(2)}s)`
37
- : "";
38
- console.log(`${statusIcon} ${run.planName}`);
39
- console.log(` ID: ${run.id}`);
40
- console.log(` Status: ${run.status}${duration}`);
41
- console.log(` Started: ${new Date(run.startedAt).toLocaleString()}`);
42
- if (run.completedAt) {
43
- console.log(` Completed: ${new Date(run.completedAt).toLocaleString()}`);
44
- }
45
- if (run.errors && run.errors.length > 0) {
46
- console.log(` Errors:`);
47
- for (const error of run.errors.slice(0, 3)) {
48
- console.log(` - ${error}`);
49
- }
50
- if (run.errors.length > 3) {
51
- console.log(` ... and ${run.errors.length - 3} more`);
52
- }
53
- }
54
- console.log("");
55
- }
56
- }
57
- catch (error) {
58
- console.error(`Error: ${error.message}`);
59
- process.exit(1);
60
- }
61
- }
62
- function getStatusIcon(status, success) {
63
- switch (status) {
64
- case "pending":
65
- return "⏳";
66
- case "running":
67
- return "🏃";
68
- case "completed":
69
- return success ? "✓" : "✗";
70
- case "failed":
71
- return "✗";
72
- default:
73
- return "•";
74
- }
75
- }
@@ -1,41 +0,0 @@
1
- import { MonitorV1 } from "@griffin-app/griffin-hub-sdk";
2
- /**
3
- * Represents a change to a single field
4
- */
5
- export interface FieldChange {
6
- field: string;
7
- oldValue: unknown;
8
- newValue: unknown;
9
- }
10
- /**
11
- * Represents a change to a node (add/remove/modify)
12
- */
13
- export interface NodeChange {
14
- type: "add" | "remove" | "modify";
15
- nodeId: string;
16
- nodeType: "ASSERTION" | "HTTP_REQUEST" | "WAIT";
17
- summary: string;
18
- fieldChanges: FieldChange[];
19
- }
20
- /**
21
- * Represents a change to an edge (add/remove)
22
- */
23
- export interface EdgeChange {
24
- type: "add" | "remove";
25
- from: string;
26
- to: string;
27
- }
28
- /**
29
- * Complete set of changes between local and remote monitors
30
- */
31
- export interface MonitorChanges {
32
- hasChanges: boolean;
33
- nodes: NodeChange[];
34
- edges: EdgeChange[];
35
- topLevel: FieldChange[];
36
- }
37
- /**
38
- * Compare two test monitors and return granular changes.
39
- * Local monitor should be resolved (variables replaced with actual values).
40
- */
41
- export declare function compareMonitors(local: MonitorV1, remote: MonitorV1): MonitorChanges;