Skip to content

Commit

Permalink
feat: Add signal option so that requests can be aborted (#894)
Browse files Browse the repository at this point in the history
Signed-off-by: Andrew Haines <haines@cerbos.dev>
  • Loading branch information
haines authored Mar 25, 2024
1 parent 57ec74c commit 6833784
Show file tree
Hide file tree
Showing 32 changed files with 7,917 additions and 461 deletions.
1 change: 0 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/api/
/docs/
/packages/*/lib/
/releasing.md
/pnpm-lock.yaml
13 changes: 13 additions & 0 deletions docs/core.erroroptions.cause.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [@cerbos/core](./core.md) &gt; [ErrorOptions](./core.erroroptions.md) &gt; [cause](./core.erroroptions.cause.md)

## ErrorOptions.cause property

The original error that caused this one.

**Signature:**

```typescript
cause?: unknown;
```
57 changes: 57 additions & 0 deletions docs/core.erroroptions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [@cerbos/core](./core.md) &gt; [ErrorOptions](./core.erroroptions.md)

## ErrorOptions interface

Options for creating an error.

**Signature:**

```typescript
export interface ErrorOptions
```

## Properties

<table><thead><tr><th>

Property


</th><th>

Modifiers


</th><th>

Type


</th><th>

Description


</th></tr></thead>
<tbody><tr><td>

[cause?](./core.erroroptions.cause.md)


</td><td>


</td><td>

unknown


</td><td>

_(Optional)_ The original error that caused this one.


</td></tr>
</tbody></table>
11 changes: 11 additions & 0 deletions docs/core.md
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,17 @@ Input to [Client.enablePolicies()](./core.client.enablepolicies.md)<!-- -->.
The outcome of enabling policies.


</td></tr>
<tr><td>

[ErrorOptions](./core.erroroptions.md)


</td><td>

Options for creating an error.


</td></tr>
<tr><td>

Expand Down
18 changes: 17 additions & 1 deletion docs/core.notok._constructor_.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Constructs a new instance of the `NotOK` class
```typescript
constructor(
code: Status,
details: string);
details: string, options?: ErrorOptions);
```

## Parameters
Expand Down Expand Up @@ -59,5 +59,21 @@ string
</td><td>


</td></tr>
<tr><td>

options


</td><td>

[ErrorOptions](./core.erroroptions.md)


</td><td>

_(Optional)_


</td></tr>
</tbody></table>
2 changes: 1 addition & 1 deletion docs/core.notok.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ Description
</th></tr></thead>
<tbody><tr><td>
[(constructor)(code, details)](./core.notok._constructor_.md)
[(constructor)(code, details, options)](./core.notok._constructor_.md)
</td><td>
Expand Down
19 changes: 19 additions & 0 deletions docs/core.requestoptions.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,24 @@ Description
_(Optional)_ Headers to add to the request.


</td></tr>
<tr><td>

[signal?](./core.requestoptions.signal.md)


</td><td>


</td><td>

AbortSignal \| undefined


</td><td>

_(Optional)_ A [signal](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) to abort the request.


</td></tr>
</tbody></table>
13 changes: 13 additions & 0 deletions docs/core.requestoptions.signal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [@cerbos/core](./core.md) &gt; [RequestOptions](./core.requestoptions.md) &gt; [signal](./core.requestoptions.signal.md)

## RequestOptions.signal property

A [signal](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) to abort the request.

**Signature:**

```typescript
signal?: AbortSignal | undefined;
```
6 changes: 3 additions & 3 deletions docs/http.http._constructor_.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Create a client for interacting with the Cerbos policy decision point (PDP) serv
**Signature:**

```typescript
constructor(url: string, options?: Options);
constructor(baseUrl: string, options?: Options);
```

## Parameters
Expand All @@ -32,7 +32,7 @@ Description
</th></tr></thead>
<tbody><tr><td>

url
baseUrl


</td><td>
Expand All @@ -42,7 +42,7 @@ string

</td><td>

base Cerbos PDP server URL (the Cerbos REST API must be available at `${url}/api/`<!-- -->).
base Cerbos PDP server URL (the Cerbos REST API must be available at `${baseUrl}/api/`<!-- -->).


</td></tr>
Expand Down
2 changes: 1 addition & 1 deletion docs/http.http.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ Description
</th></tr></thead>
<tbody><tr><td>
[(constructor)(url, options)](./http.http._constructor_.md)
[(constructor)(baseUrl, options)](./http.http._constructor_.md)
</td><td>
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@
},
"scripts": {
"all:parallel": "concurrently --group --prefix=none",
"api:extract": "pnpm --filter='./packages/*' --parallel exec api-extractor run",
"api:fixup": "scripts/sed-all api 's/_2//'",
"build": "tsc --build",
"build:watch": "tsc --build --watch",
"clean": "rm -rf api packages/*/lib private/*/tsconfig.tsbuildinfo",
"docs": "pnpm run build && pnpm run docs:extract-api && pnpm run docs:generate && pnpm run docs:fixup",
"docs:extract-api": "pnpm --filter='./packages/*' --parallel exec api-extractor run",
"docs": "pnpm run build && pnpm run api:extract && pnpm run api:fixup && pnpm run docs:generate && pnpm run docs:fixup",
"docs:fixup": "scripts/sed-all docs 's/\\r$//'",
"docs:generate": "api-documenter markdown --input-folder api --output-folder docs",
"generate": "pnpm run generate:clean && pnpm run all:parallel 'pnpm:generate:*(!clean|format)' && pnpm run generate:format",
Expand Down
2 changes: 2 additions & 0 deletions packages/core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

- [`Client.withPrincipal`](../../docs/core.client.withprincipal.md) method to create a client instance with a pre-specified principal ([#868](https://github.com/cerbos/cerbos-sdk-javascript/pull/868), [#877](https://github.com/cerbos/cerbos-sdk-javascript/pull/877))

- [`signal`](../../docs/core.requestoptions.signal.md) option to all methods, so that requests can be aborted using an [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) ([#894](https://github.com/cerbos/cerbos-sdk-javascript/pull/894))

### Changed

- Publish package from GitHub Actions and [generate provenance statement](https://docs.npmjs.com/generating-provenance-statements) ([#852](https://github.com/cerbos/cerbos-sdk-javascript/pull/852))
Expand Down
3 changes: 3 additions & 0 deletions packages/core/changelog.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ unreleased:
- summary: "[`Client.withPrincipal`](../../docs/core.client.withprincipal.md) method to create a client instance with a pre-specified principal"
pulls: [868, 877]

- summary: "[`signal`](../../docs/core.requestoptions.signal.md) option to all methods, so that requests can be aborted using an [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal)"
pull: 894

changed:
- summary: Publish package from GitHub Actions and [generate provenance statement](https://docs.npmjs.com/generating-provenance-statements)
pull: 852
Expand Down
40 changes: 38 additions & 2 deletions packages/core/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
listPoliciesRequestToProtobuf,
planResourcesRequestToProtobuf,
} from "./convert/toProtobuf";
import { ValidationFailed } from "./errors";
import { NotOK, Status, ValidationFailed } from "./errors";
import type { _RPC, _Request, _Response, _Service } from "./rpcs";
import type {
AddOrUpdatePoliciesRequest,
Expand Down Expand Up @@ -56,12 +56,40 @@ import type {
ValidationFailedCallback,
} from "./types/external";

/** @internal */
export class _AbortHandler {
public constructor(public readonly signal: AbortSignal | undefined) {}

public throwIfAborted(): void {
if (this.signal?.aborted) {
throw this.error();
}
}

public onAbort(listener: (error: NotOK) => void): void {
this.signal?.addEventListener("abort", () => {
listener(this.error());
});
}

private error(): NotOK {
const reason = this.signal?.reason as unknown;

return new NotOK(
Status.CANCELLED,
reason instanceof Error ? `Aborted: ${reason.message}` : "Aborted",
{ cause: reason },
);
}
}

/** @internal */
export type _Transport = <Service extends _Service, RPC extends _RPC<Service>>(
service: Service,
rpc: RPC,
request: _Request<Service, RPC>,
headers: Headers,
abortHandler: _AbortHandler,
) => Promise<_Response<Service, RPC>>;

/** @internal */
Expand Down Expand Up @@ -181,6 +209,13 @@ export interface RequestOptions {
* @defaultValue `undefined`
*/
headers?: HeadersInit | undefined;

/**
* A {@link https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal | signal} to abort the request.
*
* @defaultValue `undefined`
*/
signal?: AbortSignal | undefined;
}

/**
Expand Down Expand Up @@ -912,13 +947,14 @@ export abstract class Client {
rpc: RPC,
request: _Request<Service, RPC>,
adminCredentials: AdminCredentials | undefined,
{ headers }: RequestOptions = {},
{ headers, signal }: RequestOptions = {},
): Promise<_Response<Service, RPC>> {
return await this.transport(
service,
rpc,
request,
await this.mergeHeaders(headers, adminCredentials),
new _AbortHandler(signal),
);
}

Expand Down
31 changes: 26 additions & 5 deletions packages/core/src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,18 @@ export enum Status {
UNKNOWN = 2,
}

/**
* Options for creating an error.
*
* @public
*/
export interface ErrorOptions {
/**
* The original error that caused this one.
*/
cause?: unknown;
}

/**
* Error thrown when the Cerbos policy decision point server returns an unsuccessful response.
*
Expand Down Expand Up @@ -80,10 +92,11 @@ export class NotOK extends Error {
* Additional error details.
*/
public readonly details: string,

options?: ErrorOptions,
) {
super(`gRPC error ${code} (${Status[code]}): ${details}`);
this.name = this.constructor.name;
Error.captureStackTrace(this, this.constructor);
super(`gRPC error ${code} (${Status[code]}): ${details}`, options);
setNameAndStack(this);
}
}

Expand Down Expand Up @@ -127,7 +140,15 @@ export class ValidationFailed extends Error {
public readonly validationErrors: ValidationError[],
) {
super("Input failed schema validation");
this.name = this.constructor.name;
Error.captureStackTrace(this, this.constructor);
setNameAndStack(this);
}
}

function setNameAndStack(error: Error): void {
error.name = error.constructor.name;

// `Error.captureStackTrace` is not available in all browsers
if ("captureStackTrace" in Error) {
Error.captureStackTrace(error, error.constructor);
}
}
2 changes: 2 additions & 0 deletions packages/grpc/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

- [`Client.withPrincipal`](../../docs/core.client.withprincipal.md) method to create a client instance with a pre-specified principal ([#868](https://github.com/cerbos/cerbos-sdk-javascript/pull/868), [#877](https://github.com/cerbos/cerbos-sdk-javascript/pull/877))

- [`signal`](../../docs/core.requestoptions.signal.md) option to all methods, so that requests can be aborted using an [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) ([#894](https://github.com/cerbos/cerbos-sdk-javascript/pull/894))

### Changed

- Publish package from GitHub Actions and [generate provenance statement](https://docs.npmjs.com/generating-provenance-statements) ([#852](https://github.com/cerbos/cerbos-sdk-javascript/pull/852))
Expand Down
3 changes: 3 additions & 0 deletions packages/grpc/changelog.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ unreleased:
- summary: "[`Client.withPrincipal`](../../docs/core.client.withprincipal.md) method to create a client instance with a pre-specified principal"
pulls: [868, 877]

- summary: "[`signal`](../../docs/core.requestoptions.signal.md) option to all methods, so that requests can be aborted using an [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal)"
pull: 894

changed:
- summary: Publish package from GitHub Actions and [generate provenance statement](https://docs.npmjs.com/generating-provenance-statements)
pull: 852
Expand Down
Loading

0 comments on commit 6833784

Please sign in to comment.