Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
2048a84
chore(internal): update `actions/checkout` version
stainless-app[bot] Jan 16, 2026
bf382c0
feat(api): api update
stainless-app[bot] Jan 16, 2026
8fecb72
feat(api): api update
stainless-app[bot] Jan 20, 2026
10316df
feat(api): api update
stainless-app[bot] Jan 20, 2026
026e846
feat(api): api update
stainless-app[bot] Jan 22, 2026
d3c6eed
chore(ci): upgrade `actions/github-script`
stainless-app[bot] Jan 23, 2026
35bdbf0
feat(api): api update
stainless-app[bot] Jan 23, 2026
9aa302a
feat(api): api update
stainless-app[bot] Jan 23, 2026
4ef0068
feat(api): api update
stainless-app[bot] Jan 26, 2026
510da52
feat(api): api update
stainless-app[bot] Jan 26, 2026
77ebc62
feat(api): api update
stainless-app[bot] Jan 27, 2026
5def577
chore(internal): codegen related update
stainless-app[bot] Jan 27, 2026
8ff53b4
feat(api): api update
stainless-app[bot] Jan 27, 2026
b612191
feat(api): api update
stainless-app[bot] Jan 29, 2026
c4707a2
feat(api): api update
stainless-app[bot] Jan 29, 2026
d8cb362
fix(client): avoid memory leak with abort signals
stainless-app[bot] Feb 2, 2026
5feca1e
chore(client): do not parse responses with empty content-length
stainless-app[bot] Feb 2, 2026
dfcbdc9
feat(api): api update
stainless-app[bot] Feb 3, 2026
79f1bfe
feat(api): api update
stainless-app[bot] Feb 3, 2026
dbc9d1a
chore(client): restructure abort controller binding
stainless-app[bot] Feb 4, 2026
dfe3e70
fix(client): avoid removing abort listener too early
stainless-app[bot] Feb 5, 2026
311a889
chore(internal): fix pagination internals not accepting option promises
stainless-app[bot] Feb 5, 2026
2b49b60
feat(api): api update
stainless-app[bot] Feb 5, 2026
4bbd1e1
feat(api): api update
stainless-app[bot] Feb 9, 2026
45054df
feat(api): api update
stainless-app[bot] Feb 10, 2026
666d1b4
chore(internal): avoid type checking errors with ts-reset
stainless-app[bot] Feb 11, 2026
d70cd83
chore(internal/client): fix form-urlencoded requests
stainless-app[bot] Feb 17, 2026
ed982d3
feat(api): api update
stainless-app[bot] Feb 17, 2026
8cf1cb9
feat(api): api update
stainless-app[bot] Feb 18, 2026
f8e68be
chore: update mock server docs
stainless-app[bot] Feb 19, 2026
f1a0849
feat(api): api update
stainless-app[bot] Feb 19, 2026
439d2eb
fix(docs/contributing): correct pnpm link command
stainless-app[bot] Feb 23, 2026
70aae96
release: 1.29.0
stainless-app[bot] Feb 23, 2026
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
8 changes: 4 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
runs-on: ${{ github.repository == 'stainless-sdks/knock-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
if: github.event_name == 'push' || github.event.pull_request.head.repo.fork
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6

- name: Set up Node
uses: actions/setup-node@v4
Expand All @@ -41,7 +41,7 @@ jobs:
contents: read
id-token: write
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6

- name: Set up Node
uses: actions/setup-node@v4
Expand All @@ -57,7 +57,7 @@ jobs:
- name: Get GitHub OIDC Token
if: github.repository == 'stainless-sdks/knock-typescript'
id: github-oidc
uses: actions/github-script@v6
uses: actions/github-script@v8
with:
script: core.setOutput('github_token', await core.getIDToken());

Expand All @@ -74,7 +74,7 @@ jobs:
runs-on: ${{ github.repository == 'stainless-sdks/knock-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
if: github.event_name == 'push' || github.event.pull_request.head.repo.fork
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6

- name: Set up Node
uses: actions/setup-node@v4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish-npm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6

- name: Set up Node
uses: actions/setup-node@v3
Expand Down
3 changes: 1 addition & 2 deletions .github/workflows/release-doctor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,10 @@ jobs:
if: github.repository == 'knocklabs/knock-node' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next')

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6

- name: Check release environment
run: |
bash ./bin/check-release-environment
env:
NPM_TOKEN: ${{ secrets.KNOCK_NPM_TOKEN || secrets.NPM_TOKEN }}

2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "1.28.0"
".": "1.29.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: 90
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/knock%2Fknock-138601849c510c1e1c96af745bc2a4c4099a6e69054b454ba69e61082fb60f31.yml
openapi_spec_hash: 4858bf3005cfe4a73eaa5cdc8a4ac939
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/knock%2Fknock-b0b2bad50557aa0fe95d42cd97c6b45e8c45f6f257950048545faafafc851a17.yml
openapi_spec_hash: 4e26fcff8efa06e31f3b2bfc191a7006
config_hash: 2b42d138d85c524e65fa7e205d36cc4a
47 changes: 47 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,52 @@
# Changelog

## 1.29.0 (2026-02-23)

Full Changelog: [v1.28.0...v1.29.0](https://github.com/knocklabs/knock-node/compare/v1.28.0...v1.29.0)

### Features

* **api:** api update ([f1a0849](https://github.com/knocklabs/knock-node/commit/f1a0849dfe21babc2c872e59f5f06a8a40bc77d6))
* **api:** api update ([8cf1cb9](https://github.com/knocklabs/knock-node/commit/8cf1cb904850e248e85fe6fcf0dc5716c49b43db))
* **api:** api update ([ed982d3](https://github.com/knocklabs/knock-node/commit/ed982d39a49d9e088e1e9d14e49f363ce7845e72))
* **api:** api update ([45054df](https://github.com/knocklabs/knock-node/commit/45054dfc1940893305dbf902f8d0b83ad4f57aa4))
* **api:** api update ([4bbd1e1](https://github.com/knocklabs/knock-node/commit/4bbd1e147c3c2c4a0003e255f365a7de6fd3670d))
* **api:** api update ([2b49b60](https://github.com/knocklabs/knock-node/commit/2b49b60b0aaabfcebdc6aae066f3b40c2af13809))
* **api:** api update ([79f1bfe](https://github.com/knocklabs/knock-node/commit/79f1bfe1cfdd25fda0ddc823c9dffa6f07fa08b9))
* **api:** api update ([dfcbdc9](https://github.com/knocklabs/knock-node/commit/dfcbdc952b7e7d2ad619cd1bbf1e0e8eb445c18a))
* **api:** api update ([c4707a2](https://github.com/knocklabs/knock-node/commit/c4707a23b196e3af7f6878f5ca0651d11999f73f))
* **api:** api update ([b612191](https://github.com/knocklabs/knock-node/commit/b6121912872235644a76d4f5df5c260c41fc2b74))
* **api:** api update ([8ff53b4](https://github.com/knocklabs/knock-node/commit/8ff53b4798307b7d4a3feb5febdb3bfb3c039c43))
* **api:** api update ([77ebc62](https://github.com/knocklabs/knock-node/commit/77ebc623dcba86c33fd0685bf622fb372be47b91))
* **api:** api update ([510da52](https://github.com/knocklabs/knock-node/commit/510da5211c4d52dc3ff9aedc0a95a1ce689bd1dd))
* **api:** api update ([4ef0068](https://github.com/knocklabs/knock-node/commit/4ef00687d3d26bd308a9e4f4540492c4f6bbe3c7))
* **api:** api update ([9aa302a](https://github.com/knocklabs/knock-node/commit/9aa302a18b8ce1b77a6d07c418e328640084bf04))
* **api:** api update ([35bdbf0](https://github.com/knocklabs/knock-node/commit/35bdbf0694f7f29d5b5e4ad38d18d9a5fcec2f94))
* **api:** api update ([026e846](https://github.com/knocklabs/knock-node/commit/026e8466fb87b4f879755f222ad526ba8db956e8))
* **api:** api update ([10316df](https://github.com/knocklabs/knock-node/commit/10316df12a84166f5b2933be7a5aa73f9e43cec6))
* **api:** api update ([8fecb72](https://github.com/knocklabs/knock-node/commit/8fecb721112dee9e4b106d42f297c174a4271361))
* **api:** api update ([bf382c0](https://github.com/knocklabs/knock-node/commit/bf382c0bf162077e7c28b65551085f461f8592c0))


### Bug Fixes

* **client:** avoid memory leak with abort signals ([d8cb362](https://github.com/knocklabs/knock-node/commit/d8cb36276de54fa1328b5b8bcae66ba5b3ce1aad))
* **client:** avoid removing abort listener too early ([dfe3e70](https://github.com/knocklabs/knock-node/commit/dfe3e705d5a5c9ab74c1885f6b7ed8f563b3662b))
* **docs/contributing:** correct pnpm link command ([439d2eb](https://github.com/knocklabs/knock-node/commit/439d2ebd0f3416446b496cb423ee1b12a1ddc5ff))


### Chores

* **ci:** upgrade `actions/github-script` ([d3c6eed](https://github.com/knocklabs/knock-node/commit/d3c6eed42a83abd3e529c299edf4fa61b67ed58a))
* **client:** do not parse responses with empty content-length ([5feca1e](https://github.com/knocklabs/knock-node/commit/5feca1ec81e627f3ffadcd5ae4a406bdb2e80a65))
* **client:** restructure abort controller binding ([dbc9d1a](https://github.com/knocklabs/knock-node/commit/dbc9d1a37f329b417592bcda6d5b79f5f9f705cc))
* **internal/client:** fix form-urlencoded requests ([d70cd83](https://github.com/knocklabs/knock-node/commit/d70cd83026b494bfce38bf9733c9dc30190ad7eb))
* **internal:** avoid type checking errors with ts-reset ([666d1b4](https://github.com/knocklabs/knock-node/commit/666d1b444d89c58b59e30dd59b53d9e38497dc42))
* **internal:** codegen related update ([5def577](https://github.com/knocklabs/knock-node/commit/5def577b5e605cdd62e2d8e98d98543fc936e0b9))
* **internal:** fix pagination internals not accepting option promises ([311a889](https://github.com/knocklabs/knock-node/commit/311a889981ab8f3531e41633039106ce421f0f7c))
* **internal:** update `actions/checkout` version ([2048a84](https://github.com/knocklabs/knock-node/commit/2048a84ada13831beeb378d9b938bedf2f78eba4))
* update mock server docs ([f8e68be](https://github.com/knocklabs/knock-node/commit/f8e68be9c029ad400225d6df05e33a26a78cb22e))

## 1.28.0 (2026-01-15)

Full Changelog: [v1.27.0...v1.28.0](https://github.com/knocklabs/knock-node/compare/v1.27.0...v1.28.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 @knocklabs/node
# With pnpm
$ pnpm link --global
$ cd ../my-package
$ pnpm link -global @knocklabs/node
$ pnpm link --global @knocklabs/node
```

## 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 package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@knocklabs/node",
"version": "1.28.0",
"version": "1.29.0",
"description": "The official TypeScript library for the Knock API",
"author": "Knock <support@knock.app>",
"types": "dist/index.d.ts",
Expand Down
32 changes: 26 additions & 6 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,7 @@ export class Knock {
loggerFor(this).info(`${responseInfo} - ${retryMessage}`);

const errText = await response.text().catch((err: any) => castToError(err).message);
const errJSON = safeJSON(errText);
const errJSON = safeJSON(errText) as any;
const errMessage = errJSON ? undefined : errText;

loggerFor(this).debug(
Expand Down Expand Up @@ -630,17 +630,22 @@ export class Knock {
getAPIList<Item, PageClass extends Pagination.AbstractPage<Item> = Pagination.AbstractPage<Item>>(
path: string,
Page: new (...args: any[]) => PageClass,
opts?: RequestOptions,
opts?: PromiseOrValue<RequestOptions>,
): Pagination.PagePromise<PageClass, Item> {
return this.requestAPIList(Page, { method: 'get', path, ...opts });
return this.requestAPIList(
Page,
opts && 'then' in opts ?
opts.then((opts) => ({ method: 'get', path, ...opts }))
: { method: 'get', path, ...opts },
);
}

requestAPIList<
Item = unknown,
PageClass extends Pagination.AbstractPage<Item> = Pagination.AbstractPage<Item>,
>(
Page: new (...args: ConstructorParameters<typeof Pagination.AbstractPage>) => PageClass,
options: FinalRequestOptions,
options: PromiseOrValue<FinalRequestOptions>,
): Pagination.PagePromise<PageClass, Item> {
const request = this.makeRequest(options, null, undefined);
return new Pagination.PagePromise<PageClass, Item>(this as any as Knock, request, Page);
Expand All @@ -653,9 +658,10 @@ export class Knock {
controller: AbortController,
): Promise<Response> {
const { signal, method, ...options } = init || {};
if (signal) signal.addEventListener('abort', () => controller.abort());
const abort = this._makeAbort(controller);
if (signal) signal.addEventListener('abort', abort, { once: true });

const timeout = setTimeout(() => controller.abort(), ms);
const timeout = setTimeout(abort, ms);

const isReadableBody =
((globalThis as any).ReadableStream && options.body instanceof (globalThis as any).ReadableStream) ||
Expand Down Expand Up @@ -823,6 +829,12 @@ export class Knock {
return headers.values;
}

private _makeAbort(controller: AbortController) {
// note: we can't just inline this method inside `fetchWithTimeout()` because then the closure
// would capture all request options, and cause a memory leak.
return () => controller.abort();
}

private buildBody({ options: { body, headers: rawHeaders } }: { options: FinalRequestOptions }): {
bodyHeaders: HeadersLike;
body: BodyInit | undefined;
Expand Down Expand Up @@ -855,6 +867,14 @@ export class Knock {
(Symbol.iterator in body && 'next' in body && typeof body.next === 'function'))
) {
return { bodyHeaders: undefined, body: Shims.ReadableStreamFrom(body as AsyncIterable<Uint8Array>) };
} else if (
typeof body === 'object' &&
headers.values.get('content-type') === 'application/x-www-form-urlencoded'
) {
return {
bodyHeaders: { 'content-type': 'application/x-www-form-urlencoded' },
body: this.stringifyQuery(body as Record<string, unknown>),
};
} else {
return this.#encoder({ body, headers });
}
Expand Down
6 changes: 6 additions & 0 deletions src/internal/parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ export async function defaultParseResponse<T>(client: Knock, props: APIResponseP
const mediaType = contentType?.split(';')[0]?.trim();
const isJSON = mediaType?.includes('application/json') || mediaType?.endsWith('+json');
if (isJSON) {
const contentLength = response.headers.get('content-length');
if (contentLength === '0') {
// if there is no content we can't do anything
return undefined as T;
}

const json = await response.json();
return json as T;
}
Expand Down
61 changes: 28 additions & 33 deletions src/resources/audiences.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,20 @@ export class Audiences extends APIResource {
* members: [
* {
* tenant: 'ingen_isla_nublar',
* user: { id: 'dr_sattler' },
* user: {
* email: 'ellie@ingen.net',
* id: 'dr_sattler',
* name: 'Dr. Ellie Sattler',
* },
* },
* ],
* });
* ```
*/
addMembers(key: string, body: AudienceAddMembersParams, options?: RequestOptions): APIPromise<void> {
addMembers(key: string, params: AudienceAddMembersParams, options?: RequestOptions): APIPromise<void> {
const { create_audience, ...body } = params;
return this._client.post(path`/v1/audiences/${key}/members`, {
query: { create_audience },
body,
...options,
headers: buildHeaders([{ Accept: '*/*' }, options?.headers]),
Expand All @@ -50,7 +56,7 @@ export class Audiences extends APIResource {
* @example
* ```ts
* await client.audiences.removeMembers('key', {
* members: [{ user: {} }],
* members: [{ user: { id: 'dr_sattler' } }],
* });
* ```
*/
Expand Down Expand Up @@ -112,9 +118,15 @@ export interface AudienceListMembersResponse {

export interface AudienceAddMembersParams {
/**
* A list of audience members to add. Limited to 1,000 members per request.
* Body param: A list of audience members to add. You can add up to 1,000 members
* per request.
*/
members: Array<AudienceAddMembersParams.Member>;

/**
* Query param: Create the audience if it does not exist.
*/
create_audience?: boolean;
}

export namespace AudienceAddMembersParams {
Expand All @@ -123,32 +135,24 @@ export namespace AudienceAddMembersParams {
*/
export interface Member {
/**
* An object containing the user's ID.
* A set of parameters to inline-identify a user with. Inline identifying the user
* will ensure that the user is available before the request is executed in Knock.
* It will perform an upsert for the user you're supplying, replacing any
* properties specified.
*/
user: Member.User;
user: UsersAPI.InlineIdentifyUserRequest;

/**
* The unique identifier for the tenant.
*/
tenant?: string | null;
}

export namespace Member {
/**
* An object containing the user's ID.
*/
export interface User {
/**
* The unique identifier of the user.
*/
id?: string;
}
}
}

export interface AudienceRemoveMembersParams {
/**
* A list of audience members to remove.
* A list of audience members to remove. You can remove up to 1,000 members per
* request.
*/
members: Array<AudienceRemoveMembersParams.Member>;
}
Expand All @@ -159,27 +163,18 @@ export namespace AudienceRemoveMembersParams {
*/
export interface Member {
/**
* An object containing the user's ID.
* A set of parameters to inline-identify a user with. Inline identifying the user
* will ensure that the user is available before the request is executed in Knock.
* It will perform an upsert for the user you're supplying, replacing any
* properties specified.
*/
user: Member.User;
user: UsersAPI.InlineIdentifyUserRequest;

/**
* The unique identifier for the tenant.
*/
tenant?: string | null;
}

export namespace Member {
/**
* An object containing the user's ID.
*/
export interface User {
/**
* The unique identifier of the user.
*/
id?: string;
}
}
}

export declare namespace Audiences {
Expand Down
8 changes: 4 additions & 4 deletions src/resources/messages/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1031,22 +1031,22 @@ export interface MessageListParams extends ItemsCursorParams {
export namespace MessageListParams {
export interface InsertedAt {
/**
* Limits the results to messages inserted after the given date.
* Limits the results to items inserted after the given date.
*/
gt?: string;

/**
* Limits the results to messages inserted after or on the given date.
* Limits the results to items inserted after or on the given date.
*/
gte?: string;

/**
* Limits the results to messages inserted before the given date.
* Limits the results to items inserted before the given date.
*/
lt?: string;

/**
* Limits the results to messages inserted before or on the given date.
* Limits the results to items inserted before or on the given date.
*/
lte?: string;
}
Expand Down
Loading