cursortoys-cli 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.
package/README.md ADDED
@@ -0,0 +1,233 @@
1
+ # cursortoys-cli
2
+
3
+ Command-line utilities for CursorToys: HTTP testing, skill management, automation, and productivity tools.
4
+
5
+ ## Features
6
+
7
+ - 🧪 **HTTP Testing**: Run `.req` / `.request` files as automated tests
8
+ - 🎯 **Skill Management**: Create and manage AI agent skills
9
+ - 🤖 **LLM Instructions**: Built-in usage guide for LLMs
10
+ - 🔧 **Productivity Tools**: Utilities for development workflow
11
+
12
+ ## Requirements
13
+
14
+ - Node.js 18+
15
+ - `curl` installed and on PATH (for HTTP testing)
16
+
17
+ ## Installation
18
+
19
+ ### Install Globally
20
+
21
+ ```bash
22
+ npm install -g cursortoys-cli
23
+ ```
24
+
25
+ ### Use with npx (no installation)
26
+
27
+ ```bash
28
+ npx cursortoys-cli http test
29
+ ```
30
+
31
+ ### Local Development
32
+
33
+ ```bash
34
+ cd cursorToys-cli
35
+ npm install
36
+ npm run build
37
+ npm link
38
+ ```
39
+
40
+ ## Commands
41
+
42
+ ### HTTP Testing
43
+
44
+ Run HTTP request files (`.req` / `.request`) from the project's `http` folder as automated tests. Uses the same format and behavior as the CursorToys VS Code extension (REST Client format, `# @var`, `# @env`, `{{VAR}}`, `.env` files), without depending on VS Code.
45
+
46
+ ### HTTP Testing
47
+
48
+ #### Run all HTTP tests
49
+
50
+ From the project root (where `.cursor/http/` or your configured base folder lives):
51
+
52
+ ```bash
53
+ cursortoys http test
54
+ ```
55
+
56
+ Discovers all `.req` and `.request` files under the `http` folder (excluding the environments subfolder), runs the first request in each file (before the first `###`), and reports pass/fail. A request is considered **passed** if the response status code is 2xx.
57
+
58
+ #### Run a single file
59
+
60
+ ```bash
61
+ cursortoys http test --file path/to/file.req
62
+ cursortoys http test -f .cursor/http/api.req
63
+ ```
64
+
65
+ #### HTTP Test Options
66
+
67
+ | Option | Description |
68
+ |-------|-------------|
69
+ | `-p, --project <dir>` | Project directory (default: current working directory) |
70
+ | `--base-folder <name>` | Base folder name (default: `cursor`; or set `CURSORTOYS_BASE_FOLDER`) |
71
+ | `--environments-folder <name>` | Environments subfolder under `http` (default: `.environments`; or `CURSORTOYS_ENVIRONMENTS_FOLDER`) |
72
+ | `-e, --env <name>` | Environment to use; overrides `# @env` in the file (default when not set: `dev`) |
73
+ | `-t, --timeout <seconds>` | Request timeout in seconds (default: `10`) |
74
+ | `-f, --file <path>` | Run a single `.req` or `.request` file |
75
+ | `-V, --verbose` | Show request and response for each test (method, URL, headers, body, status, response body) |
76
+ | `--var <key=value>` | Override a variable (e.g. `BASE_URL=https://api.example.com`); can be repeated |
77
+
78
+ #### HTTP Paths (no VS Code)
79
+
80
+ - **Workspace**: `process.cwd()` or `--project <dir>`.
81
+ - **Base folder**: `CURSORTOYS_BASE_FOLDER` or `--base-folder` (default: `cursor`).
82
+ - **HTTP folder**: `{workspace}/.{baseFolder}/http/` (e.g. `.cursor/http/`).
83
+ - **Environments**: `{workspace}/.{baseFolder}/http/{environmentsFolder}/` (e.g. `.cursor/http/.environments/`), with files like `.env.dev`, `.env`, etc.
84
+
85
+ #### HTTP Request File Format
86
+
87
+ Same as in the CursorToys extension:
88
+
89
+ - **REST Client**: `METHOD URL` then optional headers and body; multiple requests separated by `###` (only the first is run in this first version).
90
+ - **Variables**: `# @var VAR_NAME=value` (or `VAR_NAME value`); `# @env name` to select environment.
91
+ - **Substitution**: `{{VAR_NAME}}` in URL, headers, and body; resolved first from file `# @var`, then from `.env.{name}` (or `.env`) in the environments folder.
92
+
93
+ Example:
94
+
95
+ ```http
96
+ # @env dev
97
+ # @var BASE_URL=https://api.example.com
98
+
99
+ ### Get health
100
+ GET {{BASE_URL}}/health
101
+ Accept: application/json
102
+ ```
103
+
104
+ #### HTTP Verbose Mode and Overrides
105
+
106
+ - **Verbose** (`-V` / `--verbose`): prints for each test the request (method, URL, headers, body) and the response (status, body), so you can inspect what was sent and received.
107
+ - **Environment** (`-e` / `--env`): chooses which environment to use (e.g. `.env.qa`). If you pass `-e qa`, the file’s `# @env` (if any) is ignored and `qa` is used.
108
+ - **Variable overrides** (`--var KEY=value`): overrides variables for the run. You can pass multiple: `--var BASE_URL=https://api.example.com --var API_KEY=secret`. These override both `# @var` in the file and values from `.env.*`.
109
+
110
+ Examples:
111
+
112
+ ```bash
113
+ cursortoys http test -V
114
+ cursortoys http test -e qa --var BASE_URL=https://staging.example.com
115
+ cursortoys http test -f .cursor/http/api.req --verbose --var API_KEY=xxx
116
+ ```
117
+
118
+ ### Skill Management
119
+
120
+ Create and manage AI agent skills for Cursor AI.
121
+
122
+ #### Create a new skill
123
+
124
+ ```bash
125
+ cursortoys skill add my-skill
126
+ ```
127
+
128
+ #### Create with description
129
+
130
+ ```bash
131
+ cursortoys skill add http-testing -d "Skill for testing HTTP APIs"
132
+ ```
133
+
134
+ #### Create project-specific skill
135
+
136
+ ```bash
137
+ cursortoys skill add api-docs -t project -p /path/to/project
138
+ ```
139
+
140
+ #### Skill Options
141
+
142
+ | Option | Description |
143
+ |-------|-------------|
144
+ | `-d, --description <text>` | Skill description |
145
+ | `-t, --target <type>` | Target directory (`personal` or `project`, default: `personal`) |
146
+ | `-p, --project <dir>` | Project directory (required if target is `project`) |
147
+ | `--base-folder <name>` | Base folder name (default: `cursor`, or `CURSORTOYS_BASE_FOLDER`) |
148
+
149
+ #### Skill Paths
150
+
151
+ - **Personal skills**: `~/.cursor/skills/{skill-name}/SKILL.md`
152
+ - **Project skills**: `{project}/.cursor/skills/{skill-name}/SKILL.md`
153
+
154
+ The command creates a `SKILL.md` file with a template that you can customize.
155
+
156
+ ### LLM Instructions
157
+
158
+ Display instructions for LLMs on how to use the CLI:
159
+
160
+ ```bash
161
+ cursortoys --llm
162
+ ```
163
+
164
+ This shows comprehensive documentation about all commands, options, and usage patterns, formatted for LLMs to understand and use the CLI effectively.
165
+
166
+ ## HTTP Test Output (Jest/Vitest style)
167
+
168
+ The CLI uses a visual style similar to Jest/Vitest: checkmarks for pass, crosses for fail, and a short summary with duration.
169
+
170
+ **Example when all tests pass:**
171
+
172
+ ```
173
+ ✓ .cursor/http/health.req 200 OK
174
+ ✓ .cursor/http/users.req 201 Created
175
+
176
+ Tests: 2 passed, 2 total
177
+ Time: 1.23s
178
+ ```
179
+
180
+ **Example when some tests fail:**
181
+
182
+ ```
183
+ ✓ .cursor/http/health.req 200 OK
184
+ ✗ .cursor/http/users.req 404 Not Found
185
+ Failed to parse HTTP request (check METHOD URL and format)
186
+
187
+ Tests: 1 passed, 1 failed, 2 total
188
+ Time: 2.45s
189
+ ```
190
+
191
+ **Example when using `-f` and the file is not found:**
192
+
193
+ ```
194
+ FAIL No file found at: /path/to/missing.req
195
+
196
+ Tests: 0 total
197
+ Time: 0.01s
198
+ ```
199
+
200
+ **Example with `--verbose` (request and response shown):**
201
+
202
+ ```
203
+ ✓ .cursor/http/health.req 200 OK
204
+ Request: GET https://api.example.com/health
205
+ Response: 200 OK
206
+ Body: {"status":"ok"}
207
+
208
+ Tests: 1 passed, 1 total
209
+ Time: 0.45s
210
+ ```
211
+
212
+ Exit code is `0` if all tests passed, `1` if any failed or no files were run.
213
+
214
+ ## Environment Variables
215
+
216
+ - `CURSORTOYS_BASE_FOLDER`: Default base folder (default: `cursor`)
217
+ - `CURSORTOYS_ENVIRONMENTS_FOLDER`: Environments subfolder (default: `.environments`)
218
+
219
+ ## Integration with CursorToys Extension
220
+
221
+ The CLI uses the same format and conventions as the CursorToys VS Code extension:
222
+ - Same `.req` / `.request` file format
223
+ - Same environment variable resolution
224
+ - Same base folder configuration
225
+ - Skills are compatible with Cursor AI Agent Skills
226
+
227
+ ## Contributing
228
+
229
+ Contributions are welcome! Please feel free to submit a Pull Request.
230
+
231
+ ## License
232
+
233
+ MIT
@@ -0,0 +1,24 @@
1
+ import { Assertion } from './assertionTypes';
2
+ /**
3
+ * Extracts assertions from HTTP request file content.
4
+ * Looks for comment blocks containing @assert() annotations.
5
+ * @param content The file content
6
+ * @returns Array of assertions
7
+ */
8
+ export declare function extractAssertions(content: string): Assertion[];
9
+ /**
10
+ * Validates assertion syntax (for error reporting)
11
+ * @param content File content
12
+ * @returns Array of syntax errors with line numbers
13
+ */
14
+ export declare function validateAssertionSyntax(content: string): Array<{
15
+ line: number;
16
+ error: string;
17
+ }>;
18
+ /**
19
+ * Removes assertion comment blocks from content
20
+ * @param content The file content
21
+ * @returns Content with assertion blocks removed
22
+ */
23
+ export declare function removeAssertionBlocks(content: string): string;
24
+ //# sourceMappingURL=assertionParser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assertionParser.d.ts","sourceRoot":"","sources":["../src/assertionParser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAqB,MAAM,kBAAkB,CAAC;AAEhE;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,CAiB9D;AAuMD;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAgC/F;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAI7D"}
@@ -0,0 +1,234 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.extractAssertions = extractAssertions;
4
+ exports.validateAssertionSyntax = validateAssertionSyntax;
5
+ exports.removeAssertionBlocks = removeAssertionBlocks;
6
+ /**
7
+ * Extracts assertions from HTTP request file content.
8
+ * Looks for comment blocks containing @assert() annotations.
9
+ * @param content The file content
10
+ * @returns Array of assertions
11
+ */
12
+ function extractAssertions(content) {
13
+ const assertions = [];
14
+ // Find all /* ... */ blocks
15
+ const blockRegex = /\/\*[\s\S]*?\*\//g;
16
+ let match;
17
+ while ((match = blockRegex.exec(content)) !== null) {
18
+ const blockContent = match[0];
19
+ const blockStartIndex = match.index;
20
+ // Parse assertions from this block
21
+ const blockAssertions = parseAssertionBlock(blockContent, blockStartIndex, content);
22
+ assertions.push(...blockAssertions);
23
+ }
24
+ return assertions;
25
+ }
26
+ /**
27
+ * Parses assertions from a single comment block.
28
+ * @param blockContent The comment block content
29
+ * @param blockStartIndex Starting index of the block in original content
30
+ * @param fullContent Full file content (for line number calculation)
31
+ * @returns Array of assertions found in the block
32
+ */
33
+ function parseAssertionBlock(blockContent, blockStartIndex, fullContent) {
34
+ const assertions = [];
35
+ const lines = blockContent.split('\n');
36
+ for (let i = 0; i < lines.length; i++) {
37
+ const line = lines[i].trim();
38
+ // Skip lines that don't contain @assert
39
+ if (!line.includes('@assert')) {
40
+ continue;
41
+ }
42
+ // Remove leading * if present
43
+ const cleanLine = line.replace(/^\*\s*/, '');
44
+ // Try to parse the assertion
45
+ const assertion = parseAssertionLine(cleanLine);
46
+ if (assertion) {
47
+ // Calculate line number in original file
48
+ const lineNumber = calculateLineNumber(fullContent, blockStartIndex + blockContent.indexOf(lines[i]));
49
+ assertion.line = lineNumber;
50
+ assertion.raw = cleanLine;
51
+ assertions.push(assertion);
52
+ }
53
+ }
54
+ return assertions;
55
+ }
56
+ /**
57
+ * Parses a single @assert() line
58
+ * Supports multiple formats:
59
+ * - @assert("description", "expression", "operator", value) - 4 params with description
60
+ * - @assert("expression", "operator", value) - 3 params
61
+ * - @assert("expression", "operator") - 2 params (no value)
62
+ * @param line The line to parse
63
+ * @returns Parsed assertion or null if invalid
64
+ */
65
+ function parseAssertionLine(line) {
66
+ // Try 4-parameter format first: @assert("description", "expression", "operator", value)
67
+ // Use non-greedy matching for quoted strings to support quotes inside values
68
+ const assertRegex4Params = /@assert\s*\(\s*"([^"]*)"\s*,\s*"([^"]*)"\s*,\s*"([^"]*)"\s*,\s*(.+?)\s*\)\s*$/;
69
+ const match4 = line.match(assertRegex4Params);
70
+ if (match4) {
71
+ const description = match4[1].trim();
72
+ const expression = match4[2].trim();
73
+ const operator = match4[3].trim();
74
+ const expectedRaw = match4[4].trim();
75
+ const expected = parseExpectedValue(expectedRaw);
76
+ return {
77
+ description,
78
+ expression,
79
+ operator,
80
+ expected,
81
+ };
82
+ }
83
+ // Try 3-parameter format: @assert("expression", "operator", value)
84
+ // IMPORTANT: Test this BEFORE the 3-param with description to avoid false matches
85
+ // Use non-greedy matching for the value part
86
+ const assertRegexWithValue = /@assert\s*\(\s*"([^"]*)"\s*,\s*"([^"]*)"\s*,\s*(.+?)\s*\)\s*$/;
87
+ const matchWithValue = line.match(assertRegexWithValue);
88
+ if (matchWithValue) {
89
+ const expression = matchWithValue[1].trim();
90
+ const operator = matchWithValue[2].trim();
91
+ const expectedRaw = matchWithValue[3].trim();
92
+ const expected = parseExpectedValue(expectedRaw);
93
+ return {
94
+ expression,
95
+ operator,
96
+ expected,
97
+ };
98
+ }
99
+ // Try 3-parameter format with description: @assert("description", "expression", "operator")
100
+ // This will only match if the third param is NOT followed by a comma
101
+ const assertRegex3ParamsDesc = /@assert\s*\(\s*"([^"]*)"\s*,\s*"([^"]*)"\s*,\s*"([^"]*)"\s*\)\s*$/;
102
+ const match3Desc = line.match(assertRegex3ParamsDesc);
103
+ if (match3Desc) {
104
+ const description = match3Desc[1].trim();
105
+ const expression = match3Desc[2].trim();
106
+ const operator = match3Desc[3].trim();
107
+ return {
108
+ description,
109
+ expression,
110
+ operator,
111
+ expected: null,
112
+ };
113
+ }
114
+ // Try 2-parameter format: @assert("expression", "operator")
115
+ const assertRegexNoValue = /@assert\s*\(\s*"([^"]*)"\s*,\s*"([^"]*)"\s*\)\s*$/;
116
+ const matchNoValue = line.match(assertRegexNoValue);
117
+ if (matchNoValue) {
118
+ const expression = matchNoValue[1].trim();
119
+ const operator = matchNoValue[2].trim();
120
+ return {
121
+ expression,
122
+ operator,
123
+ expected: null,
124
+ };
125
+ }
126
+ return null;
127
+ }
128
+ /**
129
+ * Parses the expected value from assertion
130
+ * Supports: numbers (200), booleans (true/false), strings ("text"), null, regex (/pattern/), arrays ([1,2,3])
131
+ * @param value Raw value string
132
+ * @returns Parsed value
133
+ */
134
+ function parseExpectedValue(value) {
135
+ const trimmed = value.trim();
136
+ // null
137
+ if (trimmed === 'null') {
138
+ return null;
139
+ }
140
+ // boolean
141
+ if (trimmed === 'true') {
142
+ return true;
143
+ }
144
+ if (trimmed === 'false') {
145
+ return false;
146
+ }
147
+ // array: [1, 2, 3] or ["a", "b"]
148
+ if (trimmed.startsWith('[') && trimmed.endsWith(']')) {
149
+ try {
150
+ // Use JSON.parse to handle arrays properly
151
+ const parsed = JSON.parse(trimmed);
152
+ if (Array.isArray(parsed)) {
153
+ return parsed;
154
+ }
155
+ }
156
+ catch {
157
+ // Invalid array format, continue to fallback
158
+ }
159
+ }
160
+ // number (integer or float)
161
+ if (/^-?\d+(\.\d+)?$/.test(trimmed)) {
162
+ return parseFloat(trimmed);
163
+ }
164
+ // regex: /pattern/ or /pattern/flags
165
+ const regexMatch = trimmed.match(/^\/(.+)\/([gimsuvy]*)$/);
166
+ if (regexMatch) {
167
+ try {
168
+ return new RegExp(regexMatch[1], regexMatch[2]);
169
+ }
170
+ catch {
171
+ // Invalid regex, treat as string
172
+ }
173
+ }
174
+ // string: "text" or 'text' - remove quotes
175
+ if ((trimmed.startsWith('"') && trimmed.endsWith('"')) ||
176
+ (trimmed.startsWith("'") && trimmed.endsWith("'"))) {
177
+ return trimmed.slice(1, -1);
178
+ }
179
+ // fallback: treat as string
180
+ return trimmed;
181
+ }
182
+ /**
183
+ * Calculates the line number (1-based) for a given position in the content
184
+ * @param content Full content
185
+ * @param position Character position
186
+ * @returns Line number (1-based)
187
+ */
188
+ function calculateLineNumber(content, position) {
189
+ const upToPosition = content.substring(0, position);
190
+ const lines = upToPosition.split('\n');
191
+ return lines.length;
192
+ }
193
+ /**
194
+ * Validates assertion syntax (for error reporting)
195
+ * @param content File content
196
+ * @returns Array of syntax errors with line numbers
197
+ */
198
+ function validateAssertionSyntax(content) {
199
+ const errors = [];
200
+ const blockRegex = /\/\*[\s\S]*?\*\//g;
201
+ let match;
202
+ while ((match = blockRegex.exec(content)) !== null) {
203
+ const blockContent = match[0];
204
+ const blockStartIndex = match.index;
205
+ const lines = blockContent.split('\n');
206
+ for (let i = 0; i < lines.length; i++) {
207
+ const line = lines[i].trim();
208
+ if (!line.includes('@assert')) {
209
+ continue;
210
+ }
211
+ const cleanLine = line.replace(/^\*\s*/, '');
212
+ const assertion = parseAssertionLine(cleanLine);
213
+ if (!assertion && cleanLine.includes('@assert')) {
214
+ const lineNumber = calculateLineNumber(content, blockStartIndex + blockContent.indexOf(lines[i]));
215
+ errors.push({
216
+ line: lineNumber,
217
+ error: `Invalid @assert syntax: ${cleanLine}`,
218
+ });
219
+ }
220
+ }
221
+ }
222
+ return errors;
223
+ }
224
+ /**
225
+ * Removes assertion comment blocks from content
226
+ * @param content The file content
227
+ * @returns Content with assertion blocks removed
228
+ */
229
+ function removeAssertionBlocks(content) {
230
+ // Remove all /* ... */ blocks that contain @assert
231
+ const blockRegex = /\/\*[\s\S]*?@assert[\s\S]*?\*\//g;
232
+ return content.replace(blockRegex, '').trim();
233
+ }
234
+ //# sourceMappingURL=assertionParser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assertionParser.js","sourceRoot":"","sources":["../src/assertionParser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Types and interfaces for HTTP request assertions
3
+ */
4
+ /**
5
+ * Supported assertion operators
6
+ */
7
+ export type AssertionOperator = 'equals' | 'notEquals' | 'gt' | 'gte' | 'lt' | 'lte' | 'contains' | 'notContains' | 'startsWith' | 'endsWith' | 'matches' | 'notMatches' | 'isNull' | 'isNotNull' | 'isEmpty' | 'isNotEmpty' | 'isDefined' | 'isUndefined' | 'isTruthy' | 'isFalsy' | 'isNumber' | 'isString' | 'isBoolean' | 'isArray' | 'isJson' | 'in' | 'notIn' | 'between' | 'length';
8
+ /**
9
+ * Assertion definition extracted from @assert() annotation
10
+ */
11
+ export interface Assertion {
12
+ description?: string;
13
+ expression: string;
14
+ operator: AssertionOperator;
15
+ expected: string | number | boolean | null | RegExp | any[];
16
+ line?: number;
17
+ raw?: string;
18
+ }
19
+ /**
20
+ * Result of assertion validation
21
+ */
22
+ export interface AssertionResult {
23
+ assertion: Assertion;
24
+ passed: boolean;
25
+ actualValue?: any;
26
+ error?: string;
27
+ }
28
+ /**
29
+ * HTTP response data structure for assertion evaluation
30
+ */
31
+ export interface ResponseData {
32
+ status: number;
33
+ headers: Record<string, string>;
34
+ body: any;
35
+ }
36
+ //# sourceMappingURL=assertionTypes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assertionTypes.d.ts","sourceRoot":"","sources":["../src/assertionTypes.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAEzB,QAAQ,GACR,WAAW,GACX,IAAI,GACJ,KAAK,GACL,IAAI,GACJ,KAAK,GAEL,UAAU,GACV,aAAa,GACb,YAAY,GACZ,UAAU,GACV,SAAS,GACT,YAAY,GAEZ,QAAQ,GACR,WAAW,GACX,SAAS,GACT,YAAY,GACZ,WAAW,GACX,aAAa,GAEb,UAAU,GACV,SAAS,GACT,UAAU,GACV,UAAU,GACV,WAAW,GACX,SAAS,GACT,QAAQ,GAER,IAAI,GACJ,OAAO,GACP,SAAS,GACT,QAAQ,CAAC;AAEb;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,MAAM,GAAG,GAAG,EAAE,CAAC;IAC5D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,SAAS,CAAC;IACrB,MAAM,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,GAAG,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,EAAE,GAAG,CAAC;CACX"}
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ /**
3
+ * Types and interfaces for HTTP request assertions
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ //# sourceMappingURL=assertionTypes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assertionTypes.js","sourceRoot":"","sources":["../src/assertionTypes.ts"],"names":[],"mappings":";AAAA;;GAEG"}
@@ -0,0 +1,16 @@
1
+ import { Assertion, AssertionResult } from './assertionTypes';
2
+ import { HttpRequestResult } from './httpRunner';
3
+ /**
4
+ * Validates assertions against HTTP response
5
+ * @param assertions Array of assertions to validate
6
+ * @param response HTTP response result
7
+ * @returns Array of assertion results
8
+ */
9
+ export declare function validateAssertions(assertions: Assertion[], response: HttpRequestResult, headers?: Record<string, string>): AssertionResult[];
10
+ /**
11
+ * Formats assertion results as text for display
12
+ * @param results Assertion results
13
+ * @returns Formatted text
14
+ */
15
+ export declare function formatAssertionResults(results: AssertionResult[]): string;
16
+ //# sourceMappingURL=assertionValidator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assertionValidator.d.ts","sourceRoot":"","sources":["../src/assertionValidator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,eAAe,EAAgB,MAAM,kBAAkB,CAAC;AAC5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEjD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,SAAS,EAAE,EACvB,QAAQ,EAAE,iBAAiB,EAC3B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,eAAe,EAAE,CAwBnB;AAmOD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,MAAM,CAgCzE"}