Skip to content

Commit e60bd95

Browse files
authored
feat: Stackables Webhooks initial release (#1)
* feat: Configuration helper * feat: Initial version of the plugin, without a loader * feat: Initial loader interface
1 parent 7267e1c commit e60bd95

22 files changed

+18012
-5
lines changed

.github/SECURITY.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
## Security
2+
3+
Stackables team takes the security of our software products and services extremely seriously.
4+
5+
If you believe you have found a security vulnerability in any of our repositories, please report it to us as described below.
6+
7+
## Reporting Security Issues
8+
9+
**Please do not report security vulnerabilities through public GitHub issues.**
10+
11+
Instead, please use the following email alias security@stackables.io
12+
13+
You should receive a response within 48 hours.
14+
15+
Please try to include as much information as possible to help us better understand the nature and scope of the possible issue. Information that will help us includes:
16+
17+
* Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
18+
* Full paths of source file(s) related to the manifestation of the issue
19+
* The location of the affected source code (tag/branch/commit or direct URL)
20+
* Any special configuration required to reproduce the issue
21+
* Step-by-step instructions to reproduce the issue
22+
* Proof-of-concept or exploit code (if possible)
23+
* Impact of the issue, including how an attacker might exploit the issue
24+
25+
## Preferred Languages
26+
27+
We prefer all communications to be in English, but for security we will try to do our best to understand you.

.github/dependabot.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# To get started with Dependabot version updates, you'll need to specify which
2+
# package ecosystems to update and where the package manifests are located.
3+
# Please see the documentation for all configuration options:
4+
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5+
6+
version: 2
7+
updates:
8+
- package-ecosystem: "npm" # See documentation for possible values
9+
directory: "/" # Location of package manifests
10+
schedule:
11+
interval: "daily"

.github/workflows/coverage.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
name: Code Coverage
2+
3+
on: [push, pull_request]
4+
5+
jobs:
6+
release:
7+
name: Coverage
8+
runs-on: ubuntu-latest
9+
steps:
10+
- name: Checkout
11+
uses: actions/checkout@v2
12+
with:
13+
fetch-depth: 0
14+
- name: Setup Node.js
15+
uses: actions/setup-node@v1
16+
with:
17+
node-version: '16'
18+
- name: Install dependencies
19+
run: npm install
20+
- name: Run the tests
21+
run: npm test -- --coverage
22+
- name: Upload coverage to Codecov
23+
uses: codecov/codecov-action@v1

.github/workflows/release.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
name: Release
2+
on:
3+
push:
4+
branches:
5+
- main
6+
jobs:
7+
release:
8+
name: Release
9+
runs-on: ubuntu-latest
10+
steps:
11+
- name: Checkout
12+
uses: actions/checkout@v2
13+
with:
14+
fetch-depth: 0
15+
- name: Setup Node.js
16+
uses: actions/setup-node@v1
17+
with:
18+
node-version: "16"
19+
- name: Install dependencies
20+
run: npm install
21+
- name: Release
22+
env:
23+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
24+
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
25+
run: npm run semantic-release

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
node_modules
2+
build
3+
coverage
4+
.DS_Store
5+
tmp

README.md

Lines changed: 82 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,90 @@
11
# Stackables Webhooks
22

3-
GraphQL Code Generator plugin for Stackables webhooks
3+
GraphQL Code Generator plugin for Stackables webhooks.
4+
5+
## Install
6+
7+
This is a plugin for GraphQL Code Generator. [See official installation docs for more info](https://www.graphql-code-generator.com/docs/getting-started/installation).
8+
9+
All packages should be installed as dev dependencies and are used only during development.
410

511
```bash
6-
npm add codegen-stackables-webhooks@beta
12+
# install generator cli
13+
npm install --save-dev @graphql-codegen/cli
14+
15+
# required typescript plugins
16+
npm install --save-dev @graphql-codegen/typescript
17+
npm install --save-dev @graphql-codegen/typescript-operations
18+
19+
# webhooks plugin
20+
npm install --save-dev codegen-stackables-webhooks@beta
21+
```
22+
23+
## Configuration
24+
25+
While GraphQL Code Generator configuration is simple we still recommend to use the [graphql configuration](https://graphql-config.com/introduction) for more universal configuration.
26+
27+
We also provide a simple utility to help with the verbosity. But you can always take full control when you need to.
28+
29+
`graphql.config.js` in repository root
30+
31+
```js
32+
const { getConfiguration } = require('stackables-webhooks');
33+
34+
// Returned configuration is just a plain object
35+
// So if needed you can add or modify the returned setting as needed
36+
37+
module.exports = getConfiguration({
38+
generatedFile: "<string>",
39+
accountSlug: "<string>",
40+
introspectionToken: "<string>"
41+
})
42+
```
43+
44+
[See full configuration options here](https://github.com/stackables/codegen-stackables-webhooks/blob/beta/docs/config.md)
45+
46+
## Usage
47+
48+
Generated types are easy to use with [cloudevents-router](https://github.com/stackables/cloudevents-router) package.
49+
50+
```typescript
51+
import { CloudEventsRouter } from 'cloudevents-router'
52+
import { FragmentRegistry } from './src/generated/webhooks'
53+
54+
const router = new CloudEventsRouter<FragmentRegistry>()
55+
56+
router.on('stackables.webhook.v1.YourHookName', async (event) => {
57+
console.log('Received typed webhook', event.data)
58+
})
759
```
860

9-
---
61+
See more options on how to use the router with different web servers [here](https://github.com/stackables/cloudevents-router). But simplest is to just use nodejs built in web server like this:
62+
63+
```typescript
64+
import http from "http"
65+
import { getMiddleware } from "cloudevents-router"
66+
67+
// const router = ...
68+
69+
const middleware = getMiddleware(router, { path: '/' })
70+
const server = http.createServer(middleware)
71+
72+
server.listen(5000);
73+
```
74+
75+
## Advanced Usage
76+
77+
- [Payload structure](https://github.com/stackables/codegen-stackables-webhooks/blob/beta/docs/advanced.md)
78+
- [Provided configuration](https://github.com/stackables/codegen-stackables-webhooks/blob/beta/docs/advanced.md)
79+
- [Callback tokens](https://github.com/stackables/codegen-stackables-webhooks/blob/beta/docs/advanced.md)
80+
- [Branches](https://github.com/stackables/codegen-stackables-webhooks/blob/beta/docs/advanced.md)
81+
82+
## Deployment options
83+
84+
You can deploy the created web service anywhere as long as its publicly accessible. **But,** You need to ensure that you validate the Stackables JWT token. [Instructions here](https://github.com/stackables/codegen-stackables-webhooks/blob/beta/docs/deploy.md)
85+
86+
You can also use Stackables cloud to host your webhooks, in this case authentication and scaling is taken care of by us. [Instructions here](https://github.com/stackables/codegen-stackables-webhooks/blob/beta/docs/deploy.md)
1087

11-
_Stackables service is still in closed beta, but we plan to open up for more users before the end of the year_
88+
## Thats it ...
1289

13-
_For more info you can reach us at info@stackables.io_
90+
... happy coding :)

docs/advanced.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Webhooks usage
2+
3+
## Payload structure
4+
## Provided configuration
5+
## Callback tokens
6+
## Branches

docs/config.md

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
## Recommended setup
2+
3+
While GraphQL Code Generator configuration is simple we still recommend to use the [graphql configuration](https://graphql-config.com/introduction) for more universal configuration.
4+
5+
We also provide a simple utility to help with the verbosity. But you can always take full control when you need to.
6+
7+
`graphql.config.js` in repository root
8+
9+
```js
10+
const { getConfiguration } = require('stackables-webhooks');
11+
12+
// Returned configuration is just a plain object
13+
// So if needed you can add or modify the returned setting as needed
14+
15+
module.exports = getConfiguration({
16+
generatedFile: "<string>",
17+
accountSlug: "<string>",
18+
introspectionToken: "<string>"
19+
})
20+
```
21+
22+
## Manual setup
23+
24+
See full configuration reference at https://www.graphql-code-generator.com/docs/getting-started/codegen-config
25+
26+
Plugin requires 3 configuration settings:
27+
- **Graphql schema** - Your graphql schema reference
28+
- **Fragment loader** - Fragments in filesystem (marked with special decorator) or load fragments from stackables cloud directly
29+
- **Webhooks type generator** - Register plugin to generate type map for [cloudevents-router](https://github.com/stackables/cloudevents-router) package
30+
31+
### With Fragment loader
32+
33+
`codegen.yml` in repository root
34+
35+
```yml
36+
schema: https://data.stackables.io/stackables/cloud?introspection=<token>
37+
documents:
38+
- "https://data.stackables.io/stackables/cloud?introspection=<token>":
39+
loader: "stackables-webhooks/loader"
40+
generates:
41+
./src/cloudevents.ts:
42+
plugins:
43+
- typescript
44+
- typescript-operations
45+
- stackables-webhooks
46+
config:
47+
preResolveTypes: true
48+
onlyOperationTypes: true
49+
fragmentRegistryName: StackablesEvents
50+
fragmentRegistryDirective: register
51+
```
52+
53+
### Without Fragment loader
54+
55+
`codegen.yml` in repository root
56+
57+
```yml
58+
schema: https://data.stackables.io/stackables/cloud?introspection=<token>
59+
documents: **/*.gql
60+
generates:
61+
./src/cloudevents.ts:
62+
plugins:
63+
- typescript
64+
- typescript-operations
65+
- stackables-webhooks
66+
config:
67+
preResolveTypes: true
68+
onlyOperationTypes: true
69+
fragmentRegistryName: StackablesEvents
70+
fragmentRegistryDirective: register
71+
```
72+
73+
**If you decide to NOT load the fragments dynamically you need to define the fragments for your webhooks manually (and keep them up to date with the service). [See instructions here](https://github.com/stackables/codegen-stackables-webhooks/blob/beta/docs/fragments.md)**
74+
75+
### Configuration options
76+
77+
- **fragmentRegistryName:** StackablesEvents
78+
- **fragmentRegistryDirective:** register

docs/deploy.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Deployment options
2+
3+
## Public (JWT auth)
4+
## Managed

docs/fragments.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Manual fragments configuration
2+
3+
Stackables stores webhook data requirements as fragment definitions against the base entity. While in most cases the plugin will just load the fragments dynamically from the service, it is possible to define fragments manually.
4+
5+
Fragments can be stored in any graphql document as long as the codegen configuration is set correctly to find them.
6+
7+
`src/webhooks.gql` for example might look like this
8+
9+
```graphql
10+
fragment YourWebhookName on EntityToMonitor {
11+
fields
12+
you
13+
want {
14+
to
15+
receive
16+
}
17+
}
18+
```
19+
20+
For the generator plugin to consider this fragment as webhook definition we need to mark it with a special decorator (if you change the name of the decorator you need to change generator configuration to match the new name).
21+
22+
```graphql
23+
fragment YourWebhookName on EntityToMonitor @register {
24+
# by default generator uses @register decorator
25+
}
26+
```

0 commit comments

Comments
 (0)