Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "0.17.0"
".": "0.18.0"
}
4 changes: 2 additions & 2 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
configured_endpoints: 39
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nen-labs%2Fsteel-45efcdf3e5ccffb6e94a86be505b24b7b4ff05d8f1a2978c2a281729af68cb82.yml
openapi_spec_hash: 9a7724672b05d44888d67b6ed0ffc7ca
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nen-labs%2Fsteel-4b22ad455f8bb416a7cd29beefa7d45a3de48382232ba24503867bb6c56da90f.yml
openapi_spec_hash: 98fd3141a41b0270cb651858bc202e78
config_hash: dce4dea59023b0a00890fa654fbfffb4
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,28 @@
# Changelog

## 0.18.0 (2026-02-27)

Full Changelog: [v0.17.0...v0.18.0](https://github.com/steel-dev/steel-node/compare/v0.17.0...v0.18.0)

### Features

* **api:** api update ([34de369](https://github.com/steel-dev/steel-node/commit/34de3694682b68fe48f799cc116caa9de8df215c))
* **api:** api update ([95c42cd](https://github.com/steel-dev/steel-node/commit/95c42cd171f43b25f2b527608210f4c6a0ebdba8))


### Bug Fixes

* **docs/contributing:** correct pnpm link command ([e3dddca](https://github.com/steel-dev/steel-node/commit/e3dddca3f68711c46b554a84a37c5d9161c26394))
* **internal:** skip tests that depend on mock server ([d73bebe](https://github.com/steel-dev/steel-node/commit/d73bebeca00b88e47357778c9365b332c8cbd5c2))
* publish via npm registry in release script ([74f0eae](https://github.com/steel-dev/steel-node/commit/74f0eae3e6987b92dada862eb4ab2a2ba6a22465))
* publish via npm registry in release script ([700090e](https://github.com/steel-dev/steel-node/commit/700090e76c67b8f6ee44efc41da77997f1b4edce))


### Chores

* **internal:** move stringifyQuery implementation to internal function ([ff8f1d9](https://github.com/steel-dev/steel-node/commit/ff8f1d9e4b65ab114f171c93ddba59aeded03192))
* update mock server docs ([782421b](https://github.com/steel-dev/steel-node/commit/782421bbe1366c326ec5b0e61b6538701d15118f))

## 0.17.0 (2026-02-06)

Full Changelog: [v0.16.0...v0.17.0](https://github.com/steel-dev/steel-node/compare/v0.16.0...v0.17.0)
Expand Down
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,15 @@ $ yarn link steel-sdk
# With pnpm
$ pnpm link --global
$ cd ../my-package
$ pnpm link -global steel-sdk
$ pnpm link --global steel-sdk
```

## Running tests

Most tests require you to [set up a mock server](https://github.com/stoplightio/prism) against the OpenAPI spec to run the tests.

```sh
$ npx prism mock path/to/your/openapi.yml
$ ./scripts/mock
```

```sh
Expand Down
2 changes: 1 addition & 1 deletion api.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ Methods:
- <code title="get /v1/sessions">client.sessions.<a href="./src/resources/sessions/sessions.ts">list</a>({ ...params }) -> SessionslistSessionsSessionsCursor</code>
- <code title="post /v1/sessions/{sessionId}/computer">client.sessions.<a href="./src/resources/sessions/sessions.ts">computer</a>(sessionId, { ...params }) -> SessionComputerResponse</code>
- <code title="get /v1/sessions/{id}/context">client.sessions.<a href="./src/resources/sessions/sessions.ts">context</a>(id) -> SessionContext</code>
- <code title="get /v1/sessions/{id}/events">client.sessions.<a href="./src/resources/sessions/sessions.ts">events</a>(id) -> SessionEventsResponse</code>
- <code title="get /v1/sessions/{id}/events">client.sessions.<a href="./src/resources/sessions/sessions.ts">events</a>(id, { ...params }) -> SessionEventsResponse</code>
- <code title="get /v1/sessions/{id}/live-details">client.sessions.<a href="./src/resources/sessions/sessions.ts">liveDetails</a>(id) -> SessionLiveDetailsResponse</code>
- <code title="post /v1/sessions/{id}/release">client.sessions.<a href="./src/resources/sessions/sessions.ts">release</a>(id) -> SessionReleaseResponse</code>
- <code title="post /v1/sessions/release">client.sessions.<a href="./src/resources/sessions/sessions.ts">releaseAll</a>() -> SessionReleaseAllResponse</code>
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "steel-sdk",
"version": "0.17.0",
"version": "0.18.0",
"description": "The official TypeScript library for the Steel API",
"author": "Steel <team@steel.dev>",
"types": "dist/index.d.ts",
Expand Down
20 changes: 4 additions & 16 deletions src/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
APIConnectionTimeoutError,
APIUserAbortError,
} from './error';
import { stringifyQuery } from './internal/utils/query';
import {
kind as shimsKind,
type Readable,
Expand Down Expand Up @@ -528,27 +529,14 @@ export abstract class APIClient {
}

if (typeof query === 'object' && query && !Array.isArray(query)) {
url.search = this.stringifyQuery(query as Record<string, unknown>);
url.search = this.stringifyQuery(query);
}

return url.toString();
}

protected stringifyQuery(query: Record<string, unknown>): string {
return Object.entries(query)
.filter(([_, value]) => typeof value !== 'undefined')
.map(([key, value]) => {
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
}
if (value === null) {
return `${encodeURIComponent(key)}=`;
}
throw new SteelError(
`Cannot stringify type ${typeof value}; Expected string, number, boolean, or null. If you need to pass nested query parameters, you can manually encode them, e.g. { query: { 'foo[key1]': value1, 'foo[key2]': value2 } }, and please open a GitHub issue requesting better support for your use case.`,
);
})
.join('&');
protected stringifyQuery(query: object | Record<string, unknown>): string {
return stringifyQuery(query);
}

async fetchWithTimeout(
Expand Down
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import {
SessionComputerResponse,
SessionContext,
SessionCreateParams,
SessionEventsParams,
SessionEventsResponse,
SessionListParams,
SessionLiveDetailsResponse,
Expand Down Expand Up @@ -313,6 +314,7 @@ export declare namespace Steel {
type SessionCreateParams as SessionCreateParams,
type SessionListParams as SessionListParams,
type SessionComputerParams as SessionComputerParams,
type SessionEventsParams as SessionEventsParams,
type SessionReleaseParams as SessionReleaseParams,
type SessionReleaseAllParams as SessionReleaseAllParams,
};
Expand Down
23 changes: 23 additions & 0 deletions src/internal/utils/query.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.

import { SteelError } from '../../error';

/**
* Basic re-implementation of `qs.stringify` for primitive types.
*/
export function stringifyQuery(query: object | Record<string, unknown>) {
return Object.entries(query)
.filter(([_, value]) => typeof value !== 'undefined')
.map(([key, value]) => {
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
}
if (value === null) {
return `${encodeURIComponent(key)}=`;
}
throw new SteelError(
`Cannot stringify type ${typeof value}; Expected string, number, boolean, or null. If you need to pass nested query parameters, you can manually encode them, e.g. { query: { 'foo[key1]': value1, 'foo[key2]': value2 } }, and please open a GitHub issue requesting better support for your use case.`,
);
})
.join('&');
}
1 change: 1 addition & 0 deletions src/resources/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export {
type SessionCreateParams,
type SessionListParams,
type SessionComputerParams,
type SessionEventsParams,
type SessionReleaseParams,
type SessionReleaseAllParams,
} from './sessions/sessions';
Expand Down
1 change: 1 addition & 0 deletions src/resources/sessions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export {
type SessionCreateParams,
type SessionListParams,
type SessionComputerParams,
type SessionEventsParams,
type SessionReleaseParams,
type SessionReleaseAllParams,
} from './sessions';
35 changes: 33 additions & 2 deletions src/resources/sessions/sessions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,21 @@ export class Sessions extends APIResource {
/**
* This endpoint allows you to get the recorded session events in the RRWeb format
*/
events(id: string, options?: Core.RequestOptions): Core.APIPromise<SessionEventsResponse> {
return this._client.get(`/v1/sessions/${id}/events`, options);
events(
id: string,
query?: SessionEventsParams,
options?: Core.RequestOptions,
): Core.APIPromise<SessionEventsResponse>;
events(id: string, options?: Core.RequestOptions): Core.APIPromise<SessionEventsResponse>;
events(
id: string,
query: SessionEventsParams | Core.RequestOptions = {},
options?: Core.RequestOptions,
): Core.APIPromise<SessionEventsResponse> {
if (isRequestOptions(query)) {
return this.events(id, {}, query);
}
return this._client.get(`/v1/sessions/${id}/events`, { query, ...options });
}

/**
Expand Down Expand Up @@ -2727,6 +2740,23 @@ export declare namespace SessionComputerParams {
}
}

export interface SessionEventsParams {
/**
* Compress the events
*/
compressed?: boolean;

/**
* Optional pagination limit
*/
limit?: number;

/**
* Opaque pagination token. Pass the Next-Cursor header value to get the next page.
*/
pointer?: string;
}

export interface SessionReleaseParams {}

export interface SessionReleaseAllParams {}
Expand All @@ -2749,6 +2779,7 @@ export declare namespace Sessions {
type SessionCreateParams as SessionCreateParams,
type SessionListParams as SessionListParams,
type SessionComputerParams as SessionComputerParams,
type SessionEventsParams as SessionEventsParams,
type SessionReleaseParams as SessionReleaseParams,
type SessionReleaseAllParams as SessionReleaseAllParams,
};
Expand Down
2 changes: 1 addition & 1 deletion src/version.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export const VERSION = '0.17.0'; // x-release-please-version
export const VERSION = '0.18.0'; // x-release-please-version
3 changes: 2 additions & 1 deletion tests/api-resources/files.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ describe('resource files', () => {
);
});

test('download: request options instead of params are passed correctly', async () => {
// Mock server doesn't support application/octet-stream responses
test.skip('download: request options instead of params are passed correctly', async () => {
// ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error
await expect(client.files.download('path', { path: '/_stainless_unknown_path' })).rejects.toThrow(
Steel.NotFoundError,
Expand Down
6 changes: 4 additions & 2 deletions tests/api-resources/sessions/files.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,16 @@ describe('resource files', () => {
).rejects.toThrow(Steel.NotFoundError);
});

test('download: request options instead of params are passed correctly', async () => {
// Mock server doesn't support application/octet-stream responses
test.skip('download: request options instead of params are passed correctly', async () => {
// ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error
await expect(
client.sessions.files.download('sessionId', 'path', { path: '/_stainless_unknown_path' }),
).rejects.toThrow(Steel.NotFoundError);
});

test('downloadArchive: request options instead of params are passed correctly', async () => {
// Mock server doesn't support application/zip responses
test.skip('downloadArchive: request options instead of params are passed correctly', async () => {
// ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error
await expect(
client.sessions.files.downloadArchive('sessionId', { path: '/_stainless_unknown_path' }),
Expand Down
15 changes: 15 additions & 0 deletions tests/api-resources/sessions/sessions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,21 @@ describe('resource sessions', () => {
).rejects.toThrow(Steel.NotFoundError);
});

test('events: request options and params are passed correctly', async () => {
// ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error
await expect(
client.sessions.events(
'182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e',
{
compressed: true,
limit: 1,
pointer: 'pointer',
},
{ path: '/_stainless_unknown_path' },
),
).rejects.toThrow(Steel.NotFoundError);
});

test('liveDetails', async () => {
const responsePromise = client.sessions.liveDetails('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e');
const rawResponse = await responsePromise.asResponse();
Expand Down
6 changes: 2 additions & 4 deletions tests/stringifyQuery.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.

import { Steel } from 'steel-sdk';

const { stringifyQuery } = Steel.prototype as any;
import { stringifyQuery } from 'steel-sdk/internal/utils/query';

describe(stringifyQuery, () => {
for (const [input, expected] of [
Expand All @@ -15,7 +13,7 @@ describe(stringifyQuery, () => {
'e=f',
)}=${encodeURIComponent('g&h')}`,
],
]) {
] as const) {
it(`${JSON.stringify(input)} -> ${expected}`, () => {
expect(stringifyQuery(input)).toEqual(expected);
});
Expand Down