Skip to content

Commit 1f72aa6

Browse files
committed
feat: implement envelop plugin
1 parent 12acda7 commit 1f72aa6

File tree

11 files changed

+246
-0
lines changed

11 files changed

+246
-0
lines changed

.changeset/quick-carrots-wonder.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@labdigital/federated-token-envelop": patch
3+
---
4+
5+
Initial release of an Envelop plugin

packages/envelop/.eslintignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
dist/**

packages/envelop/.eslintrc.cjs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = {
2+
extends: ["../../.eslintrc.cjs"],
3+
};

packages/envelop/CHANGELOG.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# @labdigital/federated-token-apollo
2+
3+
## 0.13.1
4+
5+
### Patch Changes
6+
7+
- 8cb1d63: Export `PublicFederatedTokenContext`
8+
9+
## 0.13.0
10+
11+
### Minor Changes
12+
13+
- 5d091fd: Split the package in a `core` and a `apollo` specific package. This makes it
14+
possible to support other gateways/servers in the future
15+
16+
### Patch Changes
17+
18+
- Updated dependencies [5d091fd]
19+
- @labdigital/federated-token@0.13.0

packages/envelop/package.json

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
{
2+
"name": "@labdigital/federated-token-envelop",
3+
"version": "0.13.1",
4+
"description": "Federate JWT tokens between GraphQL servers",
5+
"module": "./dist/index.js",
6+
"main": "./dist/index.cjs",
7+
"types": "./dist/index.d.ts",
8+
"type": "module",
9+
"exports": {
10+
".": {
11+
"import": "./dist/index.js",
12+
"require": "./dist/index.cjs"
13+
}
14+
},
15+
"keywords": [
16+
"graphql",
17+
"authentication",
18+
"yoga",
19+
"envelope"
20+
],
21+
"author": "Lab Digital <[email protected]>",
22+
"license": "MIT",
23+
"repository": {
24+
"type": "git",
25+
"url": "https://github.com/labd/node-federated-token"
26+
},
27+
"publishConfig": {
28+
"access": "public"
29+
},
30+
"scripts": {
31+
"build": "tsup",
32+
"test": "vitest run",
33+
"test:ci": "vitest run --coverage",
34+
"tsc": "tsc --noEmit",
35+
"format": "eslint src --fix && prettier --write .",
36+
"lint": "eslint src && prettier --check ."
37+
},
38+
"files": [
39+
"dist",
40+
"src"
41+
],
42+
"dependencies": {
43+
"@envelop/core": "5.0.2",
44+
"@labdigital/federated-token": "workspace:*"
45+
},
46+
"devDependencies": {
47+
"@types/express": "^4.17.21",
48+
"@typescript-eslint/eslint-plugin": "^7.12.0",
49+
"@vitest/coverage-v8": "1.6.0",
50+
"eslint": "^8.57.0",
51+
"eslint-plugin-unused-imports": "^4.0.0",
52+
"node-mocks-http": "^1.14.1",
53+
"prettier": "^3.3.1",
54+
"tsup": "^8.1.0",
55+
"typescript": "^5.4.5",
56+
"vitest": "1.6.0"
57+
},
58+
"peerDependencies": {
59+
"graphql": ">= 16.6.0"
60+
}
61+
}

packages/envelop/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { federatedAuthPlugin } from "./plugin";

packages/envelop/src/plugin.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import type { Plugin } from "@envelop/core";
2+
import { FederatedToken } from "@labdigital/federated-token";
3+
4+
type FederatedTokenContext = {
5+
federatedToken: FederatedToken;
6+
request: Request;
7+
response: Response;
8+
};
9+
10+
export const federatedAuthPlugin = (): Plugin<FederatedTokenContext> => ({
11+
onContextBuilding: ({ context, extendContext }) => {
12+
const req = context["request"] || {};
13+
14+
// Initialize FederatedToken and add it to the context
15+
const federatedToken = new FederatedToken();
16+
17+
// Retrieve tokens from headers using the serverContext
18+
const accessToken = req.headers.get("x-access-token") as string;
19+
const refreshToken = req.headers.get("x-refresh-token") as string;
20+
21+
if (accessToken) {
22+
federatedToken.deserializeAccessToken(accessToken);
23+
}
24+
25+
if (refreshToken) {
26+
federatedToken.loadRefreshToken(refreshToken);
27+
}
28+
29+
// Extend the context with federatedToken
30+
extendContext({ federatedToken });
31+
},
32+
33+
onExecute: ({ args }) => ({
34+
onExecuteDone: async ({ result }) => {
35+
const { federatedToken } = args.contextValue;
36+
const { response } = args.contextValue;
37+
38+
if (!federatedToken) return;
39+
40+
// Check if the tokens were modified and set headers accordingly
41+
if (
42+
federatedToken.isAccessTokenModified() ||
43+
federatedToken.isValueModified()
44+
) {
45+
const serializedToken = federatedToken.serializeAccessToken();
46+
if (serializedToken) {
47+
response.headers.set("X-Access-Token", serializedToken);
48+
}
49+
}
50+
51+
if (federatedToken.isRefreshTokenModified()) {
52+
const serializedRefreshToken = federatedToken.dumpRefreshToken();
53+
if (serializedRefreshToken) {
54+
response.headers.set("X-Refresh-Token", serializedRefreshToken);
55+
}
56+
}
57+
},
58+
}),
59+
});

packages/envelop/tsconfig.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"extends": "../../tsconfig.json",
3+
"include": ["src/**/*"]
4+
}

packages/envelop/tsup.config.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { defineConfig } from "tsup";
2+
3+
export default defineConfig([
4+
{
5+
entry: ["src/index.ts"],
6+
clean: true,
7+
splitting: false,
8+
dts: true,
9+
sourcemap: true,
10+
format: ["esm", "cjs"],
11+
outDir: "dist",
12+
},
13+
]);

packages/envelop/vitest.config.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { defineConfig } from "vitest/config";
2+
import path from "path";
3+
4+
export default defineConfig({
5+
test: {
6+
coverage: {
7+
provider: "v8",
8+
all: true,
9+
include: ["src/**/*.ts"],
10+
reportsDirectory: "./test-reports/",
11+
},
12+
passWithNoTests: true,
13+
},
14+
15+
resolve: {
16+
alias: {
17+
"~src": path.join(__dirname, "src"),
18+
},
19+
},
20+
});

pnpm-lock.yaml

Lines changed: 60 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)