diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 7b51ca0..5e39b94 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.17.0" + ".": "0.18.0" } diff --git a/.stats.yml b/.stats.yml index 416f1d7..db5d940 100644 --- a/.stats.yml +++ b/.stats.yml @@ -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 diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f19957..68fca35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fcf63ff..c2a9271 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -60,7 +60,7 @@ $ yarn link steel-sdk # With pnpm $ pnpm link --global $ cd ../my-package -$ pnpm link -—global steel-sdk +$ pnpm link --global steel-sdk ``` ## Running tests @@ -68,7 +68,7 @@ $ pnpm link -—global steel-sdk 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 diff --git a/api.md b/api.md index 4e365d1..7060742 100644 --- a/api.md +++ b/api.md @@ -62,7 +62,7 @@ Methods: - client.sessions.list({ ...params }) -> SessionslistSessionsSessionsCursor - client.sessions.computer(sessionId, { ...params }) -> SessionComputerResponse - client.sessions.context(id) -> SessionContext -- client.sessions.events(id) -> SessionEventsResponse +- client.sessions.events(id, { ...params }) -> SessionEventsResponse - client.sessions.liveDetails(id) -> SessionLiveDetailsResponse - client.sessions.release(id) -> SessionReleaseResponse - client.sessions.releaseAll() -> SessionReleaseAllResponse diff --git a/package.json b/package.json index 1487d20..8d1b622 100644 --- a/package.json +++ b/package.json @@ -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 ", "types": "dist/index.d.ts", diff --git a/src/core.ts b/src/core.ts index c55a95a..65a6a9c 100644 --- a/src/core.ts +++ b/src/core.ts @@ -6,6 +6,7 @@ import { APIConnectionTimeoutError, APIUserAbortError, } from './error'; +import { stringifyQuery } from './internal/utils/query'; import { kind as shimsKind, type Readable, @@ -528,27 +529,14 @@ export abstract class APIClient { } if (typeof query === 'object' && query && !Array.isArray(query)) { - url.search = this.stringifyQuery(query as Record); + url.search = this.stringifyQuery(query); } return url.toString(); } - protected stringifyQuery(query: Record): 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 { + return stringifyQuery(query); } async fetchWithTimeout( diff --git a/src/index.ts b/src/index.ts index cbcabdc..5695168 100644 --- a/src/index.ts +++ b/src/index.ts @@ -54,6 +54,7 @@ import { SessionComputerResponse, SessionContext, SessionCreateParams, + SessionEventsParams, SessionEventsResponse, SessionListParams, SessionLiveDetailsResponse, @@ -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, }; diff --git a/src/internal/utils/query.ts b/src/internal/utils/query.ts new file mode 100644 index 0000000..b501944 --- /dev/null +++ b/src/internal/utils/query.ts @@ -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) { + 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('&'); +} diff --git a/src/resources/index.ts b/src/resources/index.ts index 62e9810..0b2fa24 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -46,6 +46,7 @@ export { type SessionCreateParams, type SessionListParams, type SessionComputerParams, + type SessionEventsParams, type SessionReleaseParams, type SessionReleaseAllParams, } from './sessions/sessions'; diff --git a/src/resources/sessions/index.ts b/src/resources/sessions/index.ts index e41c1e2..961a51a 100644 --- a/src/resources/sessions/index.ts +++ b/src/resources/sessions/index.ts @@ -23,6 +23,7 @@ export { type SessionCreateParams, type SessionListParams, type SessionComputerParams, + type SessionEventsParams, type SessionReleaseParams, type SessionReleaseAllParams, } from './sessions'; diff --git a/src/resources/sessions/sessions.ts b/src/resources/sessions/sessions.ts index 7bdf043..e5b66bc 100644 --- a/src/resources/sessions/sessions.ts +++ b/src/resources/sessions/sessions.ts @@ -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 { - return this._client.get(`/v1/sessions/${id}/events`, options); + events( + id: string, + query?: SessionEventsParams, + options?: Core.RequestOptions, + ): Core.APIPromise; + events(id: string, options?: Core.RequestOptions): Core.APIPromise; + events( + id: string, + query: SessionEventsParams | Core.RequestOptions = {}, + options?: Core.RequestOptions, + ): Core.APIPromise { + if (isRequestOptions(query)) { + return this.events(id, {}, query); + } + return this._client.get(`/v1/sessions/${id}/events`, { query, ...options }); } /** @@ -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 {} @@ -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, }; diff --git a/src/version.ts b/src/version.ts index 0251da7..74131f9 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.17.0'; // x-release-please-version +export const VERSION = '0.18.0'; // x-release-please-version diff --git a/tests/api-resources/files.test.ts b/tests/api-resources/files.test.ts index de7a347..6950457 100644 --- a/tests/api-resources/files.test.ts +++ b/tests/api-resources/files.test.ts @@ -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, diff --git a/tests/api-resources/sessions/files.test.ts b/tests/api-resources/sessions/files.test.ts index 587d41b..d0c99ad 100644 --- a/tests/api-resources/sessions/files.test.ts +++ b/tests/api-resources/sessions/files.test.ts @@ -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' }), diff --git a/tests/api-resources/sessions/sessions.test.ts b/tests/api-resources/sessions/sessions.test.ts index ee590b0..d45ef5a 100644 --- a/tests/api-resources/sessions/sessions.test.ts +++ b/tests/api-resources/sessions/sessions.test.ts @@ -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(); diff --git a/tests/stringifyQuery.test.ts b/tests/stringifyQuery.test.ts index 0ae97de..5622892 100644 --- a/tests/stringifyQuery.test.ts +++ b/tests/stringifyQuery.test.ts @@ -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 [ @@ -15,7 +13,7 @@ describe(stringifyQuery, () => { 'e=f', )}=${encodeURIComponent('g&h')}`, ], - ]) { + ] as const) { it(`${JSON.stringify(input)} -> ${expected}`, () => { expect(stringifyQuery(input)).toEqual(expected); });