@griffin-app/griffin-plan-executor 0.1.13 → 0.1.14

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 (47) hide show
  1. package/README.md +14 -14
  2. package/dist/events/adapters/in-memory.test.js +22 -22
  3. package/dist/events/adapters/in-memory.test.js.map +1 -1
  4. package/dist/events/adapters/kinesis.test.js +13 -13
  5. package/dist/events/adapters/kinesis.test.js.map +1 -1
  6. package/dist/events/emitter.test.js +14 -14
  7. package/dist/events/emitter.test.js.map +1 -1
  8. package/dist/events/types.d.ts +9 -9
  9. package/dist/events/types.d.ts.map +1 -1
  10. package/dist/events/types.js +1 -1
  11. package/dist/executor.d.ts +2 -2
  12. package/dist/executor.d.ts.map +1 -1
  13. package/dist/executor.js +40 -40
  14. package/dist/executor.js.map +1 -1
  15. package/dist/executor.test.js +99 -99
  16. package/dist/executor.test.js.map +1 -1
  17. package/dist/index.d.ts +4 -4
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +2 -2
  20. package/dist/index.js.map +1 -1
  21. package/dist/secrets/index.d.ts +3 -3
  22. package/dist/secrets/index.d.ts.map +1 -1
  23. package/dist/secrets/index.js +3 -3
  24. package/dist/secrets/index.js.map +1 -1
  25. package/dist/secrets/resolver.d.ts +12 -12
  26. package/dist/secrets/resolver.d.ts.map +1 -1
  27. package/dist/secrets/resolver.js +19 -19
  28. package/dist/secrets/resolver.js.map +1 -1
  29. package/dist/secrets/secrets.test.js +54 -54
  30. package/dist/secrets/secrets.test.js.map +1 -1
  31. package/dist/secrets/types.d.ts +2 -2
  32. package/dist/types.d.ts +2 -2
  33. package/package.json +4 -4
  34. package/src/events/adapters/README.md +7 -7
  35. package/src/events/adapters/in-memory.test.ts +22 -22
  36. package/src/events/adapters/kinesis.test.ts +13 -13
  37. package/src/events/emitter.test.ts +14 -14
  38. package/src/events/types.ts +10 -10
  39. package/src/executor.test.ts +100 -100
  40. package/src/executor.ts +41 -41
  41. package/src/index.ts +7 -7
  42. package/src/secrets/index.ts +4 -4
  43. package/src/secrets/resolver.ts +24 -24
  44. package/src/secrets/secrets.test.ts +57 -57
  45. package/src/secrets/types.ts +2 -2
  46. package/src/{test-plan-types.ts → test-monitor-types.ts} +1 -1
  47. package/src/types.ts +2 -2
package/src/executor.ts CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  UnaryPredicate,
5
5
  Assertions,
6
6
  Node,
7
- PlanV1,
7
+ MonitorV1,
8
8
  Wait,
9
9
  HttpRequest,
10
10
  } from "@griffin-app/griffin-hub-sdk";
@@ -23,14 +23,14 @@ import { createStateGraph, graphStore, StateGraphRegistry } from "ts-edge";
23
23
  import type { ExecutionEvent, BaseEvent } from "./events/index.js";
24
24
  import { randomUUID } from "crypto";
25
25
  import {
26
- resolveSecretsInPlan,
26
+ resolveSecretsInMonitor,
27
27
  planHasSecrets,
28
28
  SecretResolutionError,
29
29
  } from "./secrets/index.js";
30
30
  import { utcNow } from "./utils/dates.js";
31
31
  import {
32
32
  migrateToLatest,
33
- CURRENT_PLAN_VERSION,
33
+ CURRENT_MONITOR_VERSION,
34
34
  isSupportedVersion,
35
35
  } from "@griffin-app/griffin-ts";
36
36
 
@@ -41,7 +41,7 @@ interface NodeExecuteContext {
41
41
  }
42
42
 
43
43
  /**
44
- * Execution context that tracks event emission state throughout a plan execution.
44
+ * Execution context that tracks event emission state throughout a monitor execution.
45
45
  * Maintains sequence counter and provides event creation helpers.
46
46
  */
47
47
  class ExecutionContext {
@@ -49,7 +49,7 @@ class ExecutionContext {
49
49
 
50
50
  constructor(
51
51
  public readonly executionId: string,
52
- public readonly plan: PlanV1,
52
+ public readonly monitor: MonitorV1,
53
53
  public readonly organizationId: string,
54
54
  private readonly emitter?: ExecutionOptions["eventEmitter"],
55
55
  ) {}
@@ -62,7 +62,7 @@ class ExecutionContext {
62
62
  eventId: randomUUID(),
63
63
  seq: this.seq++,
64
64
  timestamp: Date.now(),
65
- planId: this.plan.id,
65
+ planId: this.monitor.id,
66
66
  executionId: this.executionId,
67
67
  organizationId: this.organizationId,
68
68
  };
@@ -121,7 +121,7 @@ interface ExecutionState {
121
121
  }
122
122
 
123
123
  function buildNode(
124
- plan: PlanV1,
124
+ monitor: MonitorV1,
125
125
  node: Node,
126
126
  options: ExecutionOptions,
127
127
  ): {
@@ -294,7 +294,7 @@ function buildNode(
294
294
  }
295
295
 
296
296
  function buildGraph(
297
- plan: PlanV1,
297
+ monitor: MonitorV1,
298
298
  options: ExecutionOptions,
299
299
  executionContext: ExecutionContext,
300
300
  ): DynamicStateGraph {
@@ -317,23 +317,23 @@ function buildGraph(
317
317
  }) as DynamicStateGraph;
318
318
 
319
319
  // Add all nodes - cast back to DynamicStateGraph to maintain our dynamic type
320
- const graphWithNodes = plan.nodes.reduce<DynamicStateGraph>(
321
- (g, node) => g.addNode(buildNode(plan, node, options)) as DynamicStateGraph,
320
+ const graphWithNodes = monitor.nodes.reduce<DynamicStateGraph>(
321
+ (g, node) => g.addNode(buildNode(monitor, node, options)) as DynamicStateGraph,
322
322
  graph,
323
323
  );
324
324
 
325
325
  // Add all edges
326
326
  // Cast the edge method to accept string arguments since ts-edge expects literal types
327
- // but we have runtime strings from the plan
328
- const graphWithEdges = plan.edges.reduce<DynamicStateGraph>((g, edge) => {
327
+ // but we have runtime strings from the monitor
328
+ const graphWithEdges = monitor.edges.reduce<DynamicStateGraph>((g, edge) => {
329
329
  const addEdge = g.edge as (from: string, to: string) => DynamicStateGraph;
330
330
  return addEdge(edge.from, edge.to);
331
331
  }, graphWithNodes);
332
332
 
333
333
  return graphWithEdges;
334
334
  }
335
- export async function executePlanV1(
336
- plan: PlanV1,
335
+ export async function executeMonitorV1(
336
+ monitor: MonitorV1,
337
337
  organizationId: string,
338
338
  options: ExecutionOptions,
339
339
  ): Promise<ExecutionResult> {
@@ -342,33 +342,33 @@ export async function executePlanV1(
342
342
  // Generate or use provided executionId
343
343
  const executionId = options.executionId || randomUUID();
344
344
 
345
- // Migrate plan to latest version if needed
346
- let migratedPlan = plan;
347
- if (plan.version !== CURRENT_PLAN_VERSION) {
348
- if (!isSupportedVersion(plan.version)) {
345
+ // Migrate monitor to latest version if needed
346
+ let migratedMonitor = monitor;
347
+ if (monitor.version !== CURRENT_MONITOR_VERSION) {
348
+ if (!isSupportedVersion(monitor.version)) {
349
349
  throw new Error(
350
- `Unsupported plan version: ${plan.version}. Supported versions: ${CURRENT_PLAN_VERSION}`,
350
+ `Unsupported monitor version: ${monitor.version}. Supported versions: ${CURRENT_MONITOR_VERSION}`,
351
351
  );
352
352
  }
353
353
  // Migrate to latest version
354
- migratedPlan = migrateToLatest(plan as any) as PlanV1;
354
+ migratedMonitor = migrateToLatest(monitor as any) as MonitorV1;
355
355
  }
356
356
 
357
357
  // Create execution context for event emission
358
358
  const executionContext = new ExecutionContext(
359
359
  executionId,
360
- migratedPlan,
360
+ migratedMonitor,
361
361
  organizationId,
362
362
  options.eventEmitter,
363
363
  );
364
364
 
365
365
  try {
366
- // Resolve secrets if the plan contains any
367
- let resolvedPlan = migratedPlan;
368
- if (planHasSecrets(plan)) {
366
+ // Resolve secrets if the monitor contains any
367
+ let resolvedMonitor = migratedMonitor;
368
+ if (planHasSecrets(monitor)) {
369
369
  if (!options.secretRegistry) {
370
370
  throw new SecretResolutionError(
371
- "Plan contains secret references but no secret registry was provided",
371
+ "Monitor contains secret references but no secret registry was provided",
372
372
  { provider: "unknown", ref: "unknown" },
373
373
  );
374
374
  }
@@ -380,7 +380,7 @@ export async function executePlanV1(
380
380
  });
381
381
 
382
382
  try {
383
- resolvedPlan = await resolveSecretsInPlan(plan, options.secretRegistry);
383
+ resolvedMonitor = await resolveSecretsInMonitor(monitor, options.secretRegistry);
384
384
 
385
385
  executionContext.emit({
386
386
  type: "NODE_END",
@@ -402,13 +402,13 @@ export async function executePlanV1(
402
402
  }
403
403
  }
404
404
 
405
- // Emit PLAN_START event
405
+ // Emit MONITOR_START event
406
406
  executionContext.emit({
407
- type: "PLAN_START",
408
- planName: resolvedPlan.name,
409
- planVersion: resolvedPlan.version,
410
- nodeCount: resolvedPlan.nodes.length,
411
- edgeCount: resolvedPlan.edges.length,
407
+ type: "MONITOR_START",
408
+ planName: resolvedMonitor.name,
409
+ planVersion: resolvedMonitor.version,
410
+ nodeCount: resolvedMonitor.nodes.length,
411
+ edgeCount: resolvedMonitor.edges.length,
412
412
  });
413
413
 
414
414
  // Call onStart callback if provided
@@ -422,7 +422,7 @@ export async function executePlanV1(
422
422
  }
423
423
 
424
424
  // Build execution graph (state-based)
425
- const graph = buildGraph(resolvedPlan, options, executionContext);
425
+ const graph = buildGraph(resolvedMonitor, options, executionContext);
426
426
 
427
427
  // Compile and run the state graph
428
428
  const app = graph.compile(START, END);
@@ -436,9 +436,9 @@ export async function executePlanV1(
436
436
  const finalResults = graphResult.output?.results || [];
437
437
  const finalErrors = graphResult.output?.errors || [errorMessage];
438
438
 
439
- // Emit PLAN_END event
439
+ // Emit MONITOR_END event
440
440
  executionContext.emit({
441
- type: "PLAN_END",
441
+ type: "MONITOR_END",
442
442
  success: false,
443
443
  totalDuration_ms: Date.now() - startTime,
444
444
  nodeResultCount: finalResults.length,
@@ -477,9 +477,9 @@ export async function executePlanV1(
477
477
  const success = finalState.errors.length === 0;
478
478
  const duration = Date.now() - startTime;
479
479
 
480
- // Emit PLAN_END event
480
+ // Emit MONITOR_END event
481
481
  executionContext.emit({
482
- type: "PLAN_END",
482
+ type: "MONITOR_END",
483
483
  success,
484
484
  totalDuration_ms: duration,
485
485
  nodeResultCount: finalState.results.length,
@@ -519,9 +519,9 @@ export async function executePlanV1(
519
519
  const errorMessage = error instanceof Error ? error.message : String(error);
520
520
  const duration = Date.now() - startTime;
521
521
 
522
- // Emit PLAN_END event
522
+ // Emit MONITOR_END event
523
523
  executionContext.emit({
524
- type: "PLAN_END",
524
+ type: "MONITOR_END",
525
525
  success: false,
526
526
  totalDuration_ms: duration,
527
527
  nodeResultCount: 0,
@@ -572,12 +572,12 @@ async function executeHttpRequest(
572
572
  const path = endpoint.path;
573
573
  const url = `${baseUrl}${path}`;
574
574
 
575
- // TODO: Add retry configuration from plan (node-level or plan-level)
575
+ // TODO: Add retry configuration from monitor (node-level or monitor-level)
576
576
  // For now, we always attempt once (attempt: 1)
577
577
  const attempt = 1;
578
578
 
579
579
  // After secret resolution, headers are guaranteed to be plain strings
580
- // Cast is safe because resolveSecretsInPlan substitutes all SecretRefs
580
+ // Cast is safe because resolveSecretsInMonitor substitutes all SecretRefs
581
581
  const resolvedHeaders = endpoint.headers as
582
582
  | Record<string, string>
583
583
  | undefined;
package/src/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { executePlanV1 } from "./executor.js";
1
+ export { executeMonitorV1 } from "./executor.js";
2
2
  export type {
3
3
  ExecutionOptions,
4
4
  ExecutionResult,
@@ -10,12 +10,12 @@ export type {
10
10
  StatusCallbacks,
11
11
  } from "./types.js";
12
12
  export type {
13
- TestPlan,
13
+ TestMonitor,
14
14
  HttpRequest as HttpRequestNode,
15
15
  WaitNode,
16
16
  AssertionNode,
17
17
  Edge,
18
- } from "./test-plan-types.js";
18
+ } from "./test-monitor-types.js";
19
19
  export {
20
20
  AxiosAdapter,
21
21
  StubAdapter,
@@ -31,8 +31,8 @@ export {
31
31
  export type {
32
32
  ExecutionEvent,
33
33
  BaseEvent,
34
- PlanStartEvent,
35
- PlanEndEvent,
34
+ MonitorStartEvent,
35
+ MonitorEndEvent,
36
36
  NodeStartEvent,
37
37
  NodeEndEvent,
38
38
  HttpRequestEvent,
@@ -62,8 +62,8 @@ export {
62
62
  // Registry
63
63
  SecretProviderRegistry,
64
64
  // Resolution utilities
65
- resolveSecretsInPlan,
66
- collectSecretsFromPlan,
65
+ resolveSecretsInMonitor,
66
+ collectSecretsFromMonitor,
67
67
  planHasSecrets,
68
68
  // Providers
69
69
  EnvSecretProvider,
@@ -1,10 +1,10 @@
1
1
  /**
2
- * Secret management for griffin plan executor.
2
+ * Secret management for griffin monitor executor.
3
3
  *
4
4
  * This module provides:
5
5
  * - SecretProvider interface for implementing custom providers
6
6
  * - SecretProviderRegistry for managing multiple providers
7
- * - Secret resolution utilities for test plans
7
+ * - Secret resolution utilities for test monitors
8
8
  * - Built-in providers: env, aws, vault
9
9
  */
10
10
 
@@ -24,8 +24,8 @@ export { SecretProviderRegistry } from "./registry.js";
24
24
 
25
25
  // Resolution utilities
26
26
  export {
27
- resolveSecretsInPlan,
28
- collectSecretsFromPlan,
27
+ resolveSecretsInMonitor,
28
+ collectSecretsFromMonitor,
29
29
  planHasSecrets,
30
30
  } from "./resolver.js";
31
31
 
@@ -1,13 +1,13 @@
1
1
  /**
2
- * Secret resolution utilities for test plans.
2
+ * Secret resolution utilities for test monitors.
3
3
  */
4
- import { type PlanV1 } from "@griffin-app/griffin-hub-sdk";
4
+ import { type MonitorV1 } from "@griffin-app/griffin-hub-sdk";
5
5
  import type { SecretProviderRegistry } from "./registry.js";
6
6
  import type { SecretRef, SecretRefData } from "./types.js";
7
7
  import { isSecretRef, isStringLiteral } from "./types.js";
8
8
 
9
9
  /**
10
- * Collected secret references and literals from a plan.
10
+ * Collected secret references and literals from a monitor.
11
11
  */
12
12
  interface CollectedSecrets {
13
13
  /** All unique secret references found */
@@ -71,18 +71,18 @@ function collectSecretsFromValue(
71
71
  }
72
72
 
73
73
  /**
74
- * Collect all secret references and string literals from a test plan.
74
+ * Collect all secret references and string literals from a test monitor.
75
75
  * Scans endpoint headers and bodies for $secret markers and $literal wrappers.
76
76
  */
77
- export function collectSecretsFromPlan(plan: PlanV1): CollectedSecrets {
77
+ export function collectSecretsFromMonitor(monitor: MonitorV1): CollectedSecrets {
78
78
  const collected: CollectedSecrets = {
79
79
  refs: [],
80
80
  paths: [],
81
81
  literalPaths: [],
82
82
  };
83
83
 
84
- for (let nodeIndex = 0; nodeIndex < plan.nodes.length; nodeIndex++) {
85
- const node = plan.nodes[nodeIndex];
84
+ for (let nodeIndex = 0; nodeIndex < monitor.nodes.length; nodeIndex++) {
85
+ const node = monitor.nodes[nodeIndex];
86
86
 
87
87
  // Only endpoints can have secrets (in headers and body)
88
88
  if (node.type !== "HTTP_REQUEST") {
@@ -165,24 +165,24 @@ function deepClone<T>(value: T): T {
165
165
  }
166
166
 
167
167
  /**
168
- * Resolve all secrets and unwrap string literals in a plan and return a new plan with substituted values.
169
- * The original plan is not modified.
168
+ * Resolve all secrets and unwrap string literals in a monitor and return a new monitor with substituted values.
169
+ * The original monitor is not modified.
170
170
  *
171
- * @param plan - The test plan containing secret references and string literals
171
+ * @param monitor - The test monitor containing secret references and string literals
172
172
  * @param registry - The secret provider registry
173
- * @returns A new plan with all secrets resolved to their values and literals unwrapped
173
+ * @returns A new monitor with all secrets resolved to their values and literals unwrapped
174
174
  * @throws SecretResolutionError if any secret cannot be resolved (fail-fast)
175
175
  */
176
- export async function resolveSecretsInPlan(
177
- plan: PlanV1,
176
+ export async function resolveSecretsInMonitor(
177
+ monitor: MonitorV1,
178
178
  registry: SecretProviderRegistry,
179
- ): Promise<PlanV1> {
179
+ ): Promise<MonitorV1> {
180
180
  // Collect all secret references and string literals
181
- const collected = collectSecretsFromPlan(plan);
181
+ const collected = collectSecretsFromMonitor(monitor);
182
182
 
183
183
  if (collected.refs.length === 0 && collected.literalPaths.length === 0) {
184
184
  // No secrets or literals to resolve
185
- return plan;
185
+ return monitor;
186
186
  }
187
187
 
188
188
  // Resolve all secrets (fail-fast on any error)
@@ -191,8 +191,8 @@ export async function resolveSecretsInPlan(
191
191
  ? await registry.resolveMany(collected.refs)
192
192
  : new Map();
193
193
 
194
- // Clone the plan for modification
195
- const resolvedPlan = deepClone(plan);
194
+ // Clone the monitor for modification
195
+ const resolvedMonitor = deepClone(monitor);
196
196
 
197
197
  // Substitute resolved secret values at each path
198
198
  for (const { path, secretRef } of collected.paths) {
@@ -206,23 +206,23 @@ export async function resolveSecretsInPlan(
206
206
  );
207
207
  }
208
208
 
209
- setAtPath(resolvedPlan, path, value);
209
+ setAtPath(resolvedMonitor, path, value);
210
210
  }
211
211
 
212
212
  // Unwrap string literals at each path
213
213
  for (const { path, value } of collected.literalPaths) {
214
- setAtPath(resolvedPlan, path, value);
214
+ setAtPath(resolvedMonitor, path, value);
215
215
  }
216
216
 
217
- return resolvedPlan;
217
+ return resolvedMonitor;
218
218
  }
219
219
 
220
220
  /**
221
- * Check if a plan contains any secret references or string literals that need resolution.
221
+ * Check if a monitor contains any secret references or string literals that need resolution.
222
222
  * Useful for short-circuiting resolution when no secrets or literals are present.
223
223
  */
224
- export function planHasSecrets(plan: PlanV1): boolean {
225
- for (const node of plan.nodes) {
224
+ export function planHasSecrets(monitor: MonitorV1): boolean {
225
+ for (const node of monitor.nodes) {
226
226
  if (node.type !== "HTTP_REQUEST") {
227
227
  continue;
228
228
  }