Skip to content

Commit b06fc28

Browse files
authored
Merge branch 'main' into add-asyncapi-rule
2 parents 77b8435 + 3b557d9 commit b06fc28

23 files changed

Lines changed: 356 additions & 56 deletions

File tree

.changeset/young-eggs-beam.md

Lines changed: 0 additions & 5 deletions
This file was deleted.

docs/@v2/changelog.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,20 @@ toc:
77

88
<!-- do-not-remove -->
99

10+
## 2.30.5 (2026-05-12)
11+
12+
### Patch Changes
13+
14+
- Fixed a status code mismatch that occurred when using the `--har-output` option in the `respect` command.
15+
- Updated @redocly/openapi-core to v2.30.5.
16+
17+
## 2.30.4 (2026-05-06)
18+
19+
### Patch Changes
20+
21+
- Updated `styled-components` dependency to `6.4.1`.
22+
- Updated @redocly/openapi-core to v2.30.4.
23+
1024
## 2.30.3 (2026-04-29)
1125

1226
### Patch Changes

docs/@v2/rules/configurable-rules.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ A minimum of one assertion property is required to be defined.
4747
| --------------------------- | ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
4848
| casing | string | Asserts a casing style. Supported styles are: `camelCase`, `kebab-case`, `snake_case`, `PascalCase`, `MACRO_CASE`, `COBOL-CASE`, `flatcase`. See [casing example](#casing-example). |
4949
| const | string | Asserts equality of a value. The behavior is the same as the `enum` assertion with exactly one value. See [const example](#const-example). |
50+
| contains | [string] | Asserts that all listed strings are included in the value array. See [contains example](#contains-example). |
5051
| defined | boolean | Asserts a property is defined. See [defined example](#defined-example). |
5152
| disallowed | [string] | Asserts all listed values are not defined. See [disallowed example](#disallowed-example). |
5253
| enum | [string] | Asserts a value is within a predefined list of values. Providing a single value in a list is an equality check. See [enum example](#enum-example). |
@@ -315,6 +316,32 @@ rules:
315316
message: Only application/json can be used
316317
```
317318

319+
### `contains` example
320+
321+
Use `contains` to assert that every listed string appears as an element of a **string array** property (for example, the `required` field of a `Schema`).
322+
This differs from `required`, which checks for **object keys** rather than array values.
323+
324+
The following example asserts that the `required` array of every schema includes both `page` and `items`.
325+
326+
```yaml Response example
327+
rules:
328+
rule/list-schema-required-fields:
329+
subject:
330+
type: Schema
331+
property: required
332+
where:
333+
- subject:
334+
type: Schema
335+
property: properties
336+
assertions:
337+
defined: true
338+
message: 'List schemas must include "page" and "items" in the required array'
339+
assertions:
340+
contains:
341+
- page
342+
- items
343+
```
344+
318345
### `defined` example
319346

320347
The following example asserts that `x-codeSamples` is defined.

package-lock.json

Lines changed: 29 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/cli/CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11
# @redocly/cli
22

3+
## 2.30.5
4+
5+
### Patch Changes
6+
7+
- Fixed a status code mismatch that occurred when using the `--har-output` option in the `respect` command.
8+
- Updated @redocly/openapi-core to v2.30.5.
9+
10+
## 2.30.4
11+
12+
### Patch Changes
13+
14+
- Updated `styled-components` dependency to `6.4.1`.
15+
- Updated @redocly/openapi-core to v2.30.4.
16+
317
## 2.30.3
418

519
### Patch Changes

packages/cli/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@redocly/cli",
3-
"version": "2.30.3",
3+
"version": "2.30.5",
44
"description": "",
55
"license": "MIT",
66
"bin": {
@@ -43,8 +43,8 @@
4343
"@opentelemetry/sdk-trace-node": "2.6.1",
4444
"@opentelemetry/semantic-conventions": "1.40.0",
4545
"@redocly/cli-otel": "0.1.2",
46-
"@redocly/openapi-core": "2.30.3",
47-
"@redocly/respect-core": "2.30.3",
46+
"@redocly/openapi-core": "2.30.5",
47+
"@redocly/respect-core": "2.30.5",
4848
"ajv": "npm:@redocly/ajv@8.18.1",
4949
"ajv-formats": "^3.0.1",
5050
"colorette": "^1.2.0",
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { createHarLog } from '../../../../commands/respect/har-logs/har-logs.js';
2+
import { withHar } from '../../../../commands/respect/har-logs/with-har.js';
3+
4+
describe('withHar', () => {
5+
it('should preserve the original response status', async () => {
6+
const har = createHarLog({ version: '1.0.0' });
7+
const dispatcher = { on: vi.fn() };
8+
const originalResponse = new Response(JSON.stringify({ created: true }), {
9+
status: 201,
10+
statusText: 'Created',
11+
headers: { 'content-type': 'application/json' },
12+
});
13+
const baseFetch = vi.fn(async () => {
14+
return originalResponse;
15+
});
16+
17+
const fetch = withHar(baseFetch as any, { har });
18+
const response = await fetch('https://example.com/resources', {
19+
method: 'POST',
20+
dispatcher,
21+
});
22+
23+
expect(response).toBe(originalResponse);
24+
expect(response.status).toBe(201);
25+
expect(response.statusText).toBe('Created');
26+
expect(await response.json()).toEqual({ created: true });
27+
expect(har.log.entries[0].response.status).toBe(201);
28+
});
29+
30+
it('should return a bodyless response for no-content statuses', async () => {
31+
const har = createHarLog({ version: '1.0.0' });
32+
const dispatcher = { on: vi.fn() };
33+
const originalResponse = new Response(null, {
34+
status: 204,
35+
statusText: 'No Content',
36+
});
37+
const baseFetch = vi.fn(async () => {
38+
return originalResponse;
39+
});
40+
41+
const fetch = withHar(baseFetch as any, { har });
42+
const response = await fetch('https://example.com/resources', {
43+
method: 'POST',
44+
dispatcher,
45+
});
46+
47+
expect(response).toBe(originalResponse);
48+
expect(response.status).toBe(204);
49+
expect(response.statusText).toBe('No Content');
50+
expect(await response.text()).toBe('');
51+
expect(har.log.entries[0].response.status).toBe(204);
52+
});
53+
});

packages/cli/src/commands/respect/har-logs/with-har.ts

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -110,14 +110,15 @@ export const withHar: WithHar = function <T extends typeof fetch>(
110110
// Make the request
111111
const response = await baseFetch(input, options);
112112

113-
// Need to clone response to get both text and arrayBuffer
114-
const responseClone = response.clone();
113+
// Read from clones so HAR logging does not consume or reconstruct the real response.
114+
const responseTextClone = response.clone();
115+
const responseBufferClone = response.clone();
115116

116117
// Update firstByte time when we get the response
117118
entry._timestamps.firstByte = process.hrtime();
118119

119120
// Get the response body and update received time
120-
const text = await response.text();
121+
const text = response.body === null ? '' : await responseTextClone.text();
121122
entry._timestamps.received = process.hrtime();
122123

123124
const harEntry = harEntryMap.get(requestId);
@@ -149,7 +150,7 @@ export const withHar: WithHar = function <T extends typeof fetch>(
149150
}
150151

151152
if (harEntry._compressed) {
152-
const rawBody = await responseClone.arrayBuffer();
153+
const rawBody = await responseBufferClone.arrayBuffer();
153154
harEntry.response.content.size = rawBody.byteLength;
154155
} else {
155156
harEntry.response.content.size = text ? Buffer.byteLength(text) : -1;
@@ -211,15 +212,7 @@ export const withHar: WithHar = function <T extends typeof fetch>(
211212
parent.pageref = entry.pageref;
212213
});
213214

214-
const Response =
215-
defaults.Response || baseFetch.Response || global.Response || response.constructor;
216-
const responseCopy = new Response(text, {
217-
status: response.statusCode,
218-
statusText: response.statusText || '',
219-
headers: response.headers,
220-
url: response.url,
221-
});
222-
responseCopy.harEntry = entry;
215+
response.harEntry = entry;
223216

224217
if (Array.isArray(har?.log?.entries)) {
225218
har.log.entries.push(...parents, entry);
@@ -232,6 +225,6 @@ export const withHar: WithHar = function <T extends typeof fetch>(
232225
onHarEntry(entry);
233226
}
234227

235-
return responseCopy;
228+
return response;
236229
} as T;
237230
};

packages/core/CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
11
# @redocly/openapi-core
22

3+
## 2.30.5
4+
5+
### Patch Changes
6+
7+
- Fixed an issue where using environment variables in `redocly.yaml` caused a config validation error during the build.
8+
9+
## 2.30.4
10+
11+
### Patch Changes
12+
13+
- Added `contains` assertion to check that all listed strings are present in an array property.
14+
315
## 2.30.3
416

517
### Patch Changes

packages/core/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@redocly/openapi-core",
3-
"version": "2.30.3",
3+
"version": "2.30.5",
44
"description": "",
55
"type": "module",
66
"types": "lib/index.d.ts",

0 commit comments

Comments
 (0)