@griffin-app/griffin-ts 0.1.0

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 (89) hide show
  1. package/ASSERTIONS_QUICK_REF.md +161 -0
  2. package/README.md +297 -0
  3. package/dist/assertions.d.ts +136 -0
  4. package/dist/assertions.d.ts.map +1 -0
  5. package/dist/assertions.js +230 -0
  6. package/dist/assertions.js.map +1 -0
  7. package/dist/builder.d.ts +168 -0
  8. package/dist/builder.d.ts.map +1 -0
  9. package/dist/builder.js +165 -0
  10. package/dist/builder.js.map +1 -0
  11. package/dist/constants.d.ts +5 -0
  12. package/dist/constants.d.ts.map +1 -0
  13. package/dist/constants.js +6 -0
  14. package/dist/constants.js.map +1 -0
  15. package/dist/example-sequential.d.ts +11 -0
  16. package/dist/example-sequential.d.ts.map +1 -0
  17. package/dist/example-sequential.js +160 -0
  18. package/dist/example-sequential.js.map +1 -0
  19. package/dist/example.d.ts +9 -0
  20. package/dist/example.d.ts.map +1 -0
  21. package/dist/example.js +36 -0
  22. package/dist/example.js.map +1 -0
  23. package/dist/frequency.d.ts +15 -0
  24. package/dist/frequency.d.ts.map +1 -0
  25. package/dist/frequency.js +34 -0
  26. package/dist/frequency.js.map +1 -0
  27. package/dist/http-methods.d.ts +6 -0
  28. package/dist/http-methods.d.ts.map +1 -0
  29. package/dist/http-methods.js +9 -0
  30. package/dist/http-methods.js.map +1 -0
  31. package/dist/index.d.ts +24 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +62 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/response-formats.d.ts +4 -0
  36. package/dist/response-formats.d.ts.map +1 -0
  37. package/dist/response-formats.js +7 -0
  38. package/dist/response-formats.js.map +1 -0
  39. package/dist/schema-exports.d.ts +6 -0
  40. package/dist/schema-exports.d.ts.map +1 -0
  41. package/dist/schema-exports.js +43 -0
  42. package/dist/schema-exports.js.map +1 -0
  43. package/dist/schema.d.ts +311 -0
  44. package/dist/schema.d.ts.map +1 -0
  45. package/dist/schema.js +214 -0
  46. package/dist/schema.js.map +1 -0
  47. package/dist/secrets.d.ts +56 -0
  48. package/dist/secrets.d.ts.map +1 -0
  49. package/dist/secrets.js +74 -0
  50. package/dist/secrets.js.map +1 -0
  51. package/dist/sequential-builder.d.ts +127 -0
  52. package/dist/sequential-builder.d.ts.map +1 -0
  53. package/dist/sequential-builder.js +128 -0
  54. package/dist/sequential-builder.js.map +1 -0
  55. package/dist/shared.d.ts +8 -0
  56. package/dist/shared.d.ts.map +1 -0
  57. package/dist/shared.js +36 -0
  58. package/dist/shared.js.map +1 -0
  59. package/dist/target.d.ts +33 -0
  60. package/dist/target.d.ts.map +1 -0
  61. package/dist/target.js +53 -0
  62. package/dist/target.js.map +1 -0
  63. package/dist/type-exports.d.ts +6 -0
  64. package/dist/type-exports.d.ts.map +1 -0
  65. package/dist/type-exports.js +7 -0
  66. package/dist/type-exports.js.map +1 -0
  67. package/dist/wait.d.ts +9 -0
  68. package/dist/wait.d.ts.map +1 -0
  69. package/dist/wait.js +8 -0
  70. package/dist/wait.js.map +1 -0
  71. package/package.json +43 -0
  72. package/src/assertions.ts +327 -0
  73. package/src/builder.ts +336 -0
  74. package/src/constants.ts +5 -0
  75. package/src/example-sequential.ts +191 -0
  76. package/src/example.ts +55 -0
  77. package/src/frequency.ts +38 -0
  78. package/src/http-methods.ts +5 -0
  79. package/src/index.ts +70 -0
  80. package/src/response-formats.ts +3 -0
  81. package/src/schema-exports.ts +43 -0
  82. package/src/schema.ts +289 -0
  83. package/src/secrets.ts +112 -0
  84. package/src/sequential-builder.ts +254 -0
  85. package/src/shared.ts +46 -0
  86. package/src/target.ts +55 -0
  87. package/src/type-exports.ts +20 -0
  88. package/src/wait.ts +4 -0
  89. package/tsconfig.json +20 -0
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ /**
3
+ * Secret reference types and utilities for griffin DSL.
4
+ *
5
+ * Secrets are referenced by provider and path, and resolved at runtime
6
+ * by the plan executor using configured secret providers.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.secret = secret;
10
+ exports.isSecretRef = isSecretRef;
11
+ /**
12
+ * Create a secret reference for use in endpoint headers or body.
13
+ *
14
+ * @param path - Provider-qualified path in format "provider:path"
15
+ * Examples:
16
+ * - "env:API_KEY" - Environment variable
17
+ * - "aws:prod/api-key" - AWS Secrets Manager
18
+ * - "vault:secret/data/api" - HashiCorp Vault
19
+ * - "doppler:backend/prod/API_KEY" - Doppler
20
+ *
21
+ * @param options - Optional version pinning or field extraction
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * builder.addEndpoint("call", {
26
+ * method: GET,
27
+ * path: "/api/data",
28
+ * headers: {
29
+ * "Authorization": secret("aws:prod/api-key"),
30
+ * "X-API-Key": secret("env:LOCAL_API_KEY"),
31
+ * },
32
+ * })
33
+ * ```
34
+ */
35
+ function secret(path, options) {
36
+ const colonIndex = path.indexOf(":");
37
+ if (colonIndex === -1) {
38
+ throw new Error(`Secret path must include provider: "provider:path" (e.g., "aws:my-secret", "env:API_KEY"). Got: "${path}"`);
39
+ }
40
+ if (colonIndex === 0) {
41
+ throw new Error(`Secret path must have a provider name before the colon. Got: "${path}"`);
42
+ }
43
+ if (colonIndex === path.length - 1) {
44
+ throw new Error(`Secret path must have a reference after the colon. Got: "${path}"`);
45
+ }
46
+ const provider = path.slice(0, colonIndex);
47
+ const ref = path.slice(colonIndex + 1);
48
+ return {
49
+ $secret: {
50
+ provider,
51
+ ref,
52
+ ...(options?.version !== undefined && { version: options.version }),
53
+ ...(options?.field !== undefined && { field: options.field }),
54
+ },
55
+ };
56
+ }
57
+ /**
58
+ * Type guard to check if a value is a secret reference.
59
+ */
60
+ function isSecretRef(value) {
61
+ if (typeof value !== "object" || value === null) {
62
+ return false;
63
+ }
64
+ const obj = value;
65
+ if (!("$secret" in obj) ||
66
+ typeof obj.$secret !== "object" ||
67
+ obj.$secret === null) {
68
+ return false;
69
+ }
70
+ const secretData = obj.$secret;
71
+ return (typeof secretData.provider === "string" &&
72
+ typeof secretData.ref === "string");
73
+ }
74
+ //# sourceMappingURL=secrets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secrets.js","sourceRoot":"","sources":["../src/secrets.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;AA4CH,wBAgCC;AAKD,kCAmBC;AAhFD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,SAAgB,MAAM,CAAC,IAAY,EAAE,OAAuB;IAC1D,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAErC,IAAI,UAAU,KAAK,CAAC,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CACb,oGAAoG,IAAI,GAAG,CAC5G,CAAC;IACJ,CAAC;IAED,IAAI,UAAU,KAAK,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CACb,iEAAiE,IAAI,GAAG,CACzE,CAAC;IACJ,CAAC;IAED,IAAI,UAAU,KAAK,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CACb,4DAA4D,IAAI,GAAG,CACpE,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;IAC3C,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC;IAEvC,OAAO;QACL,OAAO,EAAE;YACP,QAAQ;YACR,GAAG;YACH,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,SAAS,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;YACnE,GAAG,CAAC,OAAO,EAAE,KAAK,KAAK,SAAS,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC;SAC9D;KACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAgB,WAAW,CAAC,KAAc;IACxC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAChD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,GAAG,GAAG,KAAgC,CAAC;IAC7C,IACE,CAAC,CAAC,SAAS,IAAI,GAAG,CAAC;QACnB,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ;QAC/B,GAAG,CAAC,OAAO,KAAK,IAAI,EACpB,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,UAAU,GAAG,GAAG,CAAC,OAAkC,CAAC;IAC1D,OAAO,CACL,OAAO,UAAU,CAAC,QAAQ,KAAK,QAAQ;QACvC,OAAO,UAAU,CAAC,GAAG,KAAK,QAAQ,CACnC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,127 @@
1
+ import { type EndpointConfig, type WaitDuration } from "./builder";
2
+ import { Frequency, TestPlanV1 } from "./schema";
3
+ import { type SerializedAssertion, type StateProxy } from "./assertions";
4
+ type RawPlan = Omit<TestPlanV1, "id" | "environment">;
5
+ /**
6
+ * Callback type for building assertions with type-safe state access
7
+ */
8
+ export type AssertionCallback<NodeNames extends string> = (state: StateProxy<NodeNames>) => SerializedAssertion[];
9
+ /**
10
+ * SequentialTestBuilder provides a simplified DSL for creating linear test flows.
11
+ * Edges are automatically created based on the order nodes are added.
12
+ * No manual edge management required - just add steps in sequence.
13
+ *
14
+ * @template NodeNames - Union of all registered node names for type-safe state access
15
+ */
16
+ export interface SequentialTestBuilder<NodeNames extends string = never> {
17
+ /**
18
+ * Adds an endpoint request to the sequence.
19
+ *
20
+ * @param name - Unique name for this node
21
+ * @param config - Endpoint configuration
22
+ * @returns Updated builder with node name registered
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * builder.request("create_user", {
27
+ * method: POST,
28
+ * path: "/api/v1/users",
29
+ * response_format: Json,
30
+ * body: { name: "Test User" }
31
+ * })
32
+ * ```
33
+ */
34
+ request<Name extends string>(name: Name, config: EndpointConfig): SequentialTestBuilder<NodeNames | Name>;
35
+ /**
36
+ * Adds a wait/delay to the sequence.
37
+ *
38
+ * @param name - Unique name for this node
39
+ * @param duration - How long to wait
40
+ * @returns Updated builder with node name registered
41
+ *
42
+ * @example
43
+ * ```typescript
44
+ * builder.wait("pause", Wait.seconds(5))
45
+ * // or with raw milliseconds:
46
+ * builder.wait("pause", 5000)
47
+ * ```
48
+ */
49
+ wait<Name extends string>(name: Name, duration: WaitDuration): SequentialTestBuilder<NodeNames | Name>;
50
+ /**
51
+ * Adds assertions to the sequence using a callback with type-safe state access.
52
+ *
53
+ * The callback receives a state proxy that provides autocomplete for all registered
54
+ * node names and allows building rich JsonPath-based assertions.
55
+ *
56
+ * @param callback - Function that receives state proxy and returns assertions
57
+ * @returns Updated builder (no new node name registered - uses auto-generated name)
58
+ *
59
+ * @example
60
+ * ```typescript
61
+ * builder.assert((state) => [
62
+ * Assert(state["create_user"].status).equals(201),
63
+ * Assert(state["create_user"].body["data"]["id"]).not.isNull(),
64
+ * Assert(state["create_user"].headers["content-type"]).contains("application/json"),
65
+ * ])
66
+ * ```
67
+ */
68
+ assert(callback: AssertionCallback<NodeNames>): SequentialTestBuilder<NodeNames>;
69
+ /**
70
+ * Builds the final test plan.
71
+ * Automatically connects all nodes in sequence: START → node1 → node2 → ... → END
72
+ *
73
+ * @returns The completed TestPlan
74
+ */
75
+ build(): RawPlan;
76
+ }
77
+ /**
78
+ * Creates a sequential test builder for simple linear test flows.
79
+ *
80
+ * Unlike createGraphBuilder, this builder automatically manages edges
81
+ * based on the order in which nodes are added. Perfect for straightforward
82
+ * sequential tests where you don't need complex branching logic.
83
+ *
84
+ * @param config - Test configuration
85
+ * @param config.name - Name of the test
86
+ * @param config.frequency - Optional frequency for scheduled execution
87
+ * @param config.locations - Optional array of location identifiers where this test should run
88
+ * @returns A new SequentialTestBuilder instance
89
+ *
90
+ * @example
91
+ * ```typescript
92
+ * import { createTestBuilder, POST, GET, Json, Frequency, Assert } from "griffin-ts";
93
+ *
94
+ * const plan = createTestBuilder({
95
+ * name: "create-and-verify-user",
96
+ * frequency: Frequency.every(5).minute(),
97
+ * locations: ["us-east-1", "eu-west-1"]
98
+ * })
99
+ * .request("create_user", {
100
+ * method: POST,
101
+ * path: "/api/v1/users",
102
+ * response_format: Json,
103
+ * body: { name: "Test User", email: "test@example.com" }
104
+ * })
105
+ * .assert((state) => [
106
+ * Assert(state["create_user"].status).equals(201),
107
+ * Assert(state["create_user"].body["data"]["id"]).not.isNull(),
108
+ * ])
109
+ * .request("get_user", {
110
+ * method: GET,
111
+ * path: "/api/v1/users/123",
112
+ * response_format: Json
113
+ * })
114
+ * .assert((state) => [
115
+ * Assert(state["get_user"].status).equals(200),
116
+ * Assert(state["get_user"].body["data"]["name"]).equals("Test User"),
117
+ * ])
118
+ * .build();
119
+ * ```
120
+ */
121
+ export declare function createTestBuilder(config: {
122
+ name: string;
123
+ frequency?: Frequency;
124
+ locations?: string[];
125
+ }): SequentialTestBuilder;
126
+ export {};
127
+ //# sourceMappingURL=sequential-builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sequential-builder.d.ts","sourceRoot":"","sources":["../src/sequential-builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,cAAc,EACnB,KAAK,YAAY,EAClB,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAiC,SAAS,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAChF,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,UAAU,EAChB,MAAM,cAAc,CAAC;AAEtB,KAAK,OAAO,GAAG,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,aAAa,CAAC,CAAC;AAEtD;;GAEG;AACH,MAAM,MAAM,iBAAiB,CAAC,SAAS,SAAS,MAAM,IAAI,CACxD,KAAK,EAAE,UAAU,CAAC,SAAS,CAAC,KACzB,mBAAmB,EAAE,CAAC;AAE3B;;;;;;GAMG;AACH,MAAM,WAAW,qBAAqB,CAAC,SAAS,SAAS,MAAM,GAAG,KAAK;IACrE;;;;;;;;;;;;;;;;OAgBG;IACH,OAAO,CAAC,IAAI,SAAS,MAAM,EACzB,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,cAAc,GACrB,qBAAqB,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;IAE3C;;;;;;;;;;;;;OAaG;IACH,IAAI,CAAC,IAAI,SAAS,MAAM,EACtB,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,YAAY,GACrB,qBAAqB,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;IAE3C;;;;;;;;;;;;;;;;;OAiBG;IACH,MAAM,CACJ,QAAQ,EAAE,iBAAiB,CAAC,SAAS,CAAC,GACrC,qBAAqB,CAAC,SAAS,CAAC,CAAC;IAEpC;;;;;OAKG;IACH,KAAK,IAAI,OAAO,CAAC;CAClB;AAqGD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB,GAAG,qBAAqB,CAExB"}
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createTestBuilder = createTestBuilder;
4
+ const builder_1 = require("./builder");
5
+ const constants_1 = require("./constants");
6
+ const schema_1 = require("./schema");
7
+ const assertions_1 = require("./assertions");
8
+ /**
9
+ * Internal implementation class for SequentialTestBuilder.
10
+ */
11
+ class SequentialTestBuilderImpl {
12
+ config;
13
+ nodes = [];
14
+ nodeNames = [];
15
+ nodeCounter = 0;
16
+ constructor(config) {
17
+ this.config = config;
18
+ }
19
+ /**
20
+ * Generates a unique auto-generated node name
21
+ */
22
+ generateNodeName() {
23
+ return `step_${this.nodeCounter++}`;
24
+ }
25
+ request(name, config) {
26
+ const node = (0, builder_1.Endpoint)(config);
27
+ this.nodes.push({ ...node, id: name });
28
+ this.nodeNames.push(name);
29
+ return this;
30
+ }
31
+ wait(name, duration) {
32
+ const node = (0, builder_1.Wait)(duration);
33
+ this.nodes.push({ ...node, id: name });
34
+ this.nodeNames.push(name);
35
+ return this;
36
+ }
37
+ assert(callback) {
38
+ const stateProxy = (0, assertions_1.createStateProxy)(this.nodeNames);
39
+ const serializedAssertions = callback(stateProxy);
40
+ const nodeName = this.generateNodeName();
41
+ const node = (0, builder_1.Assertion)(serializedAssertions);
42
+ this.nodes.push({ ...node, id: nodeName });
43
+ this.nodeNames.push(nodeName);
44
+ return this;
45
+ }
46
+ build() {
47
+ const { name, frequency, locations } = this.config;
48
+ const edges = [];
49
+ // If no nodes, return empty plan with just START->END
50
+ if (this.nodes.length === 0) {
51
+ return {
52
+ name,
53
+ frequency,
54
+ locations,
55
+ version: schema_1.TEST_PLAN_VERSION,
56
+ nodes: [],
57
+ edges: [{ from: constants_1.START, to: constants_1.END }],
58
+ };
59
+ }
60
+ // Connect START to first node
61
+ edges.push({ from: constants_1.START, to: this.nodes[0].id });
62
+ // Connect consecutive nodes
63
+ for (let i = 0; i < this.nodes.length - 1; i++) {
64
+ edges.push({
65
+ from: this.nodes[i].id,
66
+ to: this.nodes[i + 1].id,
67
+ });
68
+ }
69
+ // Connect last node to END
70
+ edges.push({ from: this.nodes[this.nodes.length - 1].id, to: constants_1.END });
71
+ return {
72
+ name,
73
+ version: schema_1.TEST_PLAN_VERSION,
74
+ frequency,
75
+ locations,
76
+ nodes: this.nodes,
77
+ edges,
78
+ };
79
+ }
80
+ }
81
+ /**
82
+ * Creates a sequential test builder for simple linear test flows.
83
+ *
84
+ * Unlike createGraphBuilder, this builder automatically manages edges
85
+ * based on the order in which nodes are added. Perfect for straightforward
86
+ * sequential tests where you don't need complex branching logic.
87
+ *
88
+ * @param config - Test configuration
89
+ * @param config.name - Name of the test
90
+ * @param config.frequency - Optional frequency for scheduled execution
91
+ * @param config.locations - Optional array of location identifiers where this test should run
92
+ * @returns A new SequentialTestBuilder instance
93
+ *
94
+ * @example
95
+ * ```typescript
96
+ * import { createTestBuilder, POST, GET, Json, Frequency, Assert } from "griffin-ts";
97
+ *
98
+ * const plan = createTestBuilder({
99
+ * name: "create-and-verify-user",
100
+ * frequency: Frequency.every(5).minute(),
101
+ * locations: ["us-east-1", "eu-west-1"]
102
+ * })
103
+ * .request("create_user", {
104
+ * method: POST,
105
+ * path: "/api/v1/users",
106
+ * response_format: Json,
107
+ * body: { name: "Test User", email: "test@example.com" }
108
+ * })
109
+ * .assert((state) => [
110
+ * Assert(state["create_user"].status).equals(201),
111
+ * Assert(state["create_user"].body["data"]["id"]).not.isNull(),
112
+ * ])
113
+ * .request("get_user", {
114
+ * method: GET,
115
+ * path: "/api/v1/users/123",
116
+ * response_format: Json
117
+ * })
118
+ * .assert((state) => [
119
+ * Assert(state["get_user"].status).equals(200),
120
+ * Assert(state["get_user"].body["data"]["name"]).equals("Test User"),
121
+ * ])
122
+ * .build();
123
+ * ```
124
+ */
125
+ function createTestBuilder(config) {
126
+ return new SequentialTestBuilderImpl(config);
127
+ }
128
+ //# sourceMappingURL=sequential-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sequential-builder.js","sourceRoot":"","sources":["../src/sequential-builder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { TSchema, TSchemaOptions, TUnsafe, Static, Type } from "typebox";
2
+ export declare function Ref<T extends TSchema>(t: T, options?: TSchemaOptions): TUnsafe<Static<T>>;
3
+ export declare class TUnionOneOf<Types extends TSchema[] = TSchema[]> extends Type.Base<TSchema[]> {
4
+ oneOf: Types;
5
+ constructor(oneOf: Types);
6
+ }
7
+ export declare function UnionOneOf(oneOf: TSchema[]): TUnionOneOf;
8
+ //# sourceMappingURL=shared.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../src/shared.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EACP,cAAc,EACd,OAAO,EACP,MAAM,EAEN,IAAI,EACL,MAAM,SAAS,CAAC;AAIjB,wBAAgB,GAAG,CAAC,CAAC,SAAS,OAAO,EACnC,CAAC,EAAE,CAAC,EACJ,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAMpB;AAED,qBAAa,WAAW,CAAC,KAAK,SAAS,OAAO,EAAE,GAAG,OAAO,EAAE,CAAE,SAAQ,IAAI,CAAC,IAAI,CAC7E,OAAO,EAAE,CACV;IACQ,KAAK,EAAE,KAAK,CAAC;gBACR,KAAK,EAAE,KAAK;CAIzB;AACD,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,WAAW,CAExD"}
package/dist/shared.js ADDED
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TUnionOneOf = void 0;
4
+ exports.Ref = Ref;
5
+ exports.UnionOneOf = UnionOneOf;
6
+ const typebox_1 = require("typebox");
7
+ function Ref(t, options = {}) {
8
+ const id = t.$id;
9
+ if (!id) {
10
+ throw new Error("missing ID on schema");
11
+ }
12
+ return (0, typebox_1.Unsafe)({ ...t, $ref: id, $id: undefined, ...options });
13
+ }
14
+ class TUnionOneOf extends typebox_1.Type.Base {
15
+ oneOf;
16
+ constructor(oneOf) {
17
+ super();
18
+ this.oneOf = oneOf;
19
+ }
20
+ }
21
+ exports.TUnionOneOf = TUnionOneOf;
22
+ function UnionOneOf(oneOf) {
23
+ return new TUnionOneOf(oneOf);
24
+ }
25
+ //export interface TUnionOneOf<Types extends TSchema[] = TSchema[]> extends TSchema {
26
+ // '~kind': 'UnionOneOf'
27
+ // //static: { [K in keyof Types]: Static<Types[K]> }[number]
28
+ // oneOf: Types
29
+ //}
30
+ //
31
+ //export function UnionOneOf<Types extends TSchema[]>(oneOf: [...Types], options: TSchemaOptions = {}) {
32
+ // return { ...options, ["~kind"]: 'UnionOneOf', oneOf } as TUnionOneOf<Types>
33
+ //
34
+ // ///return Memory.Create({ '~kind': 'UnionOneOf' }, { oneOf }, options) as never
35
+ //}
36
+ //# sourceMappingURL=shared.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.js","sourceRoot":"","sources":["../src/shared.ts"],"names":[],"mappings":";;;AAWA,kBASC;AAWD,gCAEC;AAjCD,qCAOiB;AAIjB,SAAgB,GAAG,CACjB,CAAI,EACJ,UAA0B,EAAE;IAE5B,MAAM,EAAE,GAAI,CAAmD,CAAC,GAAG,CAAC;IACpE,IAAI,CAAC,EAAE,EAAE,CAAC;QACR,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;IAC1C,CAAC;IACD,OAAO,IAAA,gBAAM,EAAY,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;AAC3E,CAAC;AAED,MAAa,WAAiD,SAAQ,cAAI,CAAC,IAE1E;IACQ,KAAK,CAAQ;IACpB,YAAY,KAAY;QACtB,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;CACF;AARD,kCAQC;AACD,SAAgB,UAAU,CAAC,KAAgB;IACzC,OAAO,IAAI,WAAW,CAAC,KAAK,CAAC,CAAC;AAChC,CAAC;AAED,qFAAqF;AACrF,yBAAyB;AACzB,8DAA8D;AAC9D,gBAAgB;AAChB,GAAG;AACH,EAAE;AACF,wGAAwG;AACxG,+EAA+E;AAC/E,EAAE;AACF,mFAAmF;AACnF,GAAG"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Target reference utilities for griffin DSL.
3
+ *
4
+ * Targets are resolved at runtime by the runner based on the execution environment.
5
+ * This allows the same test to run against different environments (staging, production, etc.)
6
+ * without changing the test code.
7
+ */
8
+ import { TargetRef } from "./schema.js";
9
+ /**
10
+ * Create a target reference for endpoint base URLs.
11
+ *
12
+ * The runner will resolve this to the appropriate base URL based on the
13
+ * execution environment (passed as a per-run parameter).
14
+ *
15
+ * @param key - The target identifier (e.g., "billing-service", "api-gateway")
16
+ * @returns A target reference object
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * builder.addNode("billing", Endpoint({
21
+ * method: GET,
22
+ * path: "/invoices",
23
+ * base: target("billing-service"),
24
+ * response_format: JSON
25
+ * }));
26
+ * ```
27
+ */
28
+ export declare function target(key: string): TargetRef;
29
+ /**
30
+ * Type guard to check if a value is a target reference.
31
+ */
32
+ export declare function isTargetRef(value: unknown): value is TargetRef;
33
+ //# sourceMappingURL=target.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"target.d.ts","sourceRoot":"","sources":["../src/target.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAa7C;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,SAAS,CAO9D"}
package/dist/target.js ADDED
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ /**
3
+ * Target reference utilities for griffin DSL.
4
+ *
5
+ * Targets are resolved at runtime by the runner based on the execution environment.
6
+ * This allows the same test to run against different environments (staging, production, etc.)
7
+ * without changing the test code.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.target = target;
11
+ exports.isTargetRef = isTargetRef;
12
+ /**
13
+ * Create a target reference for endpoint base URLs.
14
+ *
15
+ * The runner will resolve this to the appropriate base URL based on the
16
+ * execution environment (passed as a per-run parameter).
17
+ *
18
+ * @param key - The target identifier (e.g., "billing-service", "api-gateway")
19
+ * @returns A target reference object
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * builder.addNode("billing", Endpoint({
24
+ * method: GET,
25
+ * path: "/invoices",
26
+ * base: target("billing-service"),
27
+ * response_format: JSON
28
+ * }));
29
+ * ```
30
+ */
31
+ function target(key) {
32
+ if (!key || typeof key !== "string") {
33
+ throw new Error(`Target key must be a non-empty string. Got: ${key}`);
34
+ }
35
+ if (key.trim() === "") {
36
+ throw new Error("Target key cannot be empty or whitespace only");
37
+ }
38
+ return {
39
+ type: "target",
40
+ key: key.trim(),
41
+ };
42
+ }
43
+ /**
44
+ * Type guard to check if a value is a target reference.
45
+ */
46
+ function isTargetRef(value) {
47
+ if (typeof value !== "object" || value === null) {
48
+ return false;
49
+ }
50
+ const obj = value;
51
+ return obj.type === "target" && typeof obj.key === "string";
52
+ }
53
+ //# sourceMappingURL=target.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"target.js","sourceRoot":"","sources":["../src/target.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;AAuBH,wBAaC;AAKD,kCAOC;AA5CD;;;;;;;;;;;;;;;;;;GAkBG;AACH,SAAgB,MAAM,CAAC,GAAW;IAChC,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QACpC,MAAM,IAAI,KAAK,CAAC,+CAA+C,GAAG,EAAE,CAAC,CAAC;IACxE,CAAC;IAED,IAAI,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;IACnE,CAAC;IAED,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE;KAChB,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAgB,WAAW,CAAC,KAAc;IACxC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAChD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,GAAG,GAAG,KAAgC,CAAC;IAC7C,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,IAAI,OAAO,GAAG,CAAC,GAAG,KAAK,QAAQ,CAAC;AAC9D,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Static types derived from TypeBox schemas.
3
+ * Import from "griffin/types" for TypeScript type checking.
4
+ */
5
+ export type { TargetRef, Endpoint, Frequency, Wait, BinaryPredicate, JSONAssertion, XMLAssertion, TextAssertion, Assertion, Assertions, Node, Edge, TestPlanV1, } from "./schema.js";
6
+ //# sourceMappingURL=type-exports.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"type-exports.d.ts","sourceRoot":"","sources":["../src/type-exports.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,YAAY,EACV,SAAS,EACT,QAAQ,EACR,SAAS,EACT,IAAI,EACJ,eAAe,EACf,aAAa,EACb,YAAY,EACZ,aAAa,EACb,SAAS,EACT,UAAU,EACV,IAAI,EACJ,IAAI,EACJ,UAAU,GACX,MAAM,aAAa,CAAC"}
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ /**
3
+ * Static types derived from TypeBox schemas.
4
+ * Import from "griffin/types" for TypeScript type checking.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ //# sourceMappingURL=type-exports.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"type-exports.js","sourceRoot":"","sources":["../src/type-exports.ts"],"names":[],"mappings":";AAAA;;;GAGG"}
package/dist/wait.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ export declare const WaitDuration: {
2
+ minutes: (value: number) => {
3
+ minutes: number;
4
+ };
5
+ seconds: (value: number) => {
6
+ seconds: number;
7
+ };
8
+ };
9
+ //# sourceMappingURL=wait.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wait.d.ts","sourceRoot":"","sources":["../src/wait.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,YAAY;qBACN,MAAM;;;qBACN,MAAM;;;CACxB,CAAC"}
package/dist/wait.js ADDED
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WaitDuration = void 0;
4
+ exports.WaitDuration = {
5
+ minutes: (value) => ({ minutes: value }),
6
+ seconds: (value) => ({ seconds: value }),
7
+ };
8
+ //# sourceMappingURL=wait.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wait.js","sourceRoot":"","sources":["../src/wait.ts"],"names":[],"mappings":";;;AAAa,QAAA,YAAY,GAAG;IAC1B,OAAO,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAChD,OAAO,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;CACjD,CAAC"}
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@griffin-app/griffin-ts",
3
+ "version": "0.1.0",
4
+ "description": "TypeScript DSL for defining griffin API tests",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "default": "./dist/index.js"
11
+ },
12
+ "./schema": {
13
+ "types": "./dist/schema-exports.d.ts",
14
+ "default": "./dist/schema-exports.js"
15
+ },
16
+ "./types": {
17
+ "types": "./dist/type-exports.d.ts",
18
+ "default": "./dist/type-exports.js"
19
+ }
20
+ },
21
+ "scripts": {
22
+ "build": "tsc",
23
+ "dev": "tsc --watch",
24
+ "test": "vitest run"
25
+ },
26
+ "keywords": [
27
+ "griffin",
28
+ "api",
29
+ "testing",
30
+ "dsl"
31
+ ],
32
+ "author": "",
33
+ "license": "MIT",
34
+ "devDependencies": {
35
+ "@types/node": "^20.10.0",
36
+ "typescript": "^5.3.3",
37
+ "vitest": "^4.0.17"
38
+ },
39
+ "dependencies": {
40
+ "ts-edge": "^1.0.4",
41
+ "typebox": "^1.0.78"
42
+ }
43
+ }