Skip to content
Merged
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
11 changes: 11 additions & 0 deletions .changeset/light-starfishes-build.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
'@team-plain/typescript-sdk': major
---

Upgrade the SDK webhook parsing to support webhook version '2024-09-18'.

### Breaking Changes
If your Plain webhook target is on the legacy/unversioned version, the SDK will no longer be able to parse the webhook payload. You must update your webhook target to '2024-09-18'. Refer to [our docs](https://www.plain.com/docs/api-reference/webhooks/versions) for more information and instructions on how to safely upgrade your webhook target.

### Added
`verifyPlainWebhook` method to verify the webhook signature, with support for replay attack protection, and parse the webhook payload. Refer to the [README](./README.md) for usage instructions.
42 changes: 33 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# @team-plain/typescript-sdk

[Changelog]('./CHANGELOG.md')
[Changelog](./CHANGELOG.md)

## Plain Client

Expand Down Expand Up @@ -104,16 +104,40 @@ Fallback error type when something unexpected happens.

## Webhooks

This package also provides functionality to validate our [Webhook payloads](https://www.plain.com/docs/api-reference/webhooks).
Plain signs the [webhooks](https://www.plain.com/docs/api-reference/webhooks) it sends to your endpoint,
allowing you to validate that they were not sent by a third-party. You can read more about it [here](https://www.plain.com/docs/api-reference/request-signing).
The SDK provides a convenient helper function to verify the signature, prevent replay attacks, and parse the payload to a typed object.

```ts
import { parsePlainWebhook } from '@team-plain/typescript-sdk';

const payload = { ... };

if(parsePlainWebhook(payload)) {
// payload is now typed!
doYourThing(payload);
import {
PlainWebhookSignatureVerificationError,
PlainWebhookVersionMismatchError,
verifyPlainWebhook,
} from '@team-plain/typescript-sdk';

// You must pass the raw request body, exactly as received from Plain,
// this will not work with a parsed (i.e., JSON) request body.
const payload = '...';

// The value of the `Plain-Request-Signature` header from the webhook request.
const signature = '...';

// Plain Request Signature Secret. You can find this in Plain's settings.
const secret = '...';

const webhookResult = verifyPlainWebhook(payload, signature, secret);
if (webhookResult.error instanceof PlainWebhookSignatureVerificationError) {
// Signature verification failed.
} else if (webhookResult.error instanceof PlainWebhookVersionMismatchError) {
// The SDK is not compatible with the received webhook version.
// Consider updating the SDK and the webhook target to the latest version.
// Consult the changelog or https://plain.com/docs/api-reference/webhooks/versions for more information.
} else if (webhookResult.error) {
// Unexpected error. Most likely due to an error in Plain's webhook server or a bug in the SDK.
// Treat this as a 500 response from Plain.
// We also recommend logging the error and sharing it with Plain's support team.
} else {
// webhookResult.data is now a typed object.
}
```

Expand Down
9 changes: 7 additions & 2 deletions biome.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,12 @@
}
},
"files": {
"include": ["biome.json", "vitest.*.js", "src/**/*.ts", "src/**/*.gql"],
"include": [
"biome.json",
"vitest.*.js",
"src/**/*.ts",
"src/**/*.gql"
],
"ignore": [
"dist/**",
"node_modules/**",
Expand Down Expand Up @@ -59,4 +64,4 @@
"organizeImports": {
"enabled": true
}
}
}
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
"@graphql-codegen/typescript-document-nodes": "^3.0.4",
"@graphql-codegen/typescript-operations": "^3.0.4",
"@rollup/plugin-json": "^6.1.0",
"@types/lodash.get": "^4.4.9",
"@types/node": "^22.7.2",
"esbuild": "^0.17.18",
"json-schema-to-typescript": "^13.1.2",
"rollup": "^3.21.5",
Expand All @@ -46,6 +48,7 @@
"ajv": "^8.12.0",
"ajv-formats": "^2.1.1",
"graphql": "^16.6.0",
"lodash.get": "^4.4.2",
"zod": "3.22.4"
}
}
83 changes: 55 additions & 28 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading