Skip to content

Commit

Permalink
types: add FastifyJwtNamespace helper (#303)
Browse files Browse the repository at this point in the history
* move types to types folder

* add FastifyJwtNamespace

* Update README.md

Co-authored-by: Frazer Smith <[email protected]>

* better typings

---------

Co-authored-by: Frazer Smith <[email protected]>
  • Loading branch information
Uzlopak and Fdawgs authored Aug 24, 2023
1 parent a4d495c commit 5ba0403
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 29 deletions.
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,31 @@ fastify.post('/sign/:namespace', async function (request, reply) {
})
```

#### Typescript

To simplify the use of namespaces in TypeScript you can use the `FastifyJwtNamespace` helper type:

```typescript
declare module 'fastify' {
interface FastifyInstance extends
FastifyJwtNamespace<{namespace: 'security'}> {
}
}
```

Alternatively you can type each key explicitly:

```typescript
declare module 'fastify' {
interface FastifyInstance extends
FastifyJwtNamespace<{
jwtDecode: 'securityJwtDecode',
jwtSign: 'securityJwtSign',
jwtVerify: 'securityJwtVerify',
}> { }
}
```

### `messages`
For your convenience, you can override the default HTTP response messages sent when an unauthorized or bad request error occurs. You can choose the specific messages to override and the rest will fallback to the default messages. The object must be in the format specified in the example below.

Expand Down
5 changes: 1 addition & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "7.2.0",
"description": "JWT utils for Fastify",
"main": "jwt.js",
"types": "jwt.d.ts",
"types": "types/jwt.d.ts",
"scripts": {
"lint": "standard",
"lint:fix": "standard --fix",
Expand Down Expand Up @@ -46,9 +46,6 @@
"tap": "^16.0.0",
"tsd": "^0.28.0"
},
"tsd": {
"directory": "test/types"
},
"publishConfig": {
"access": "public"
},
Expand Down
13 changes: 0 additions & 13 deletions tsconfig.json

This file was deleted.

31 changes: 29 additions & 2 deletions jwt.d.ts → types/jwt.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,33 @@ type FastifyJwt = FastifyPluginCallback<fastifyJwt.FastifyJWTOptions>

declare namespace fastifyJwt {

export type FastifyJwtNamespace<C extends {
namespace?: string;
jwtDecode?: string;
jwtVerify?: string;
jwtSign?: string;
}> =
Record<C extends { jwtDecode: string}
? C['jwtDecode']
: C extends {namespace: string}
? `${C['namespace']}JwtDecode`
: never,
JWT['decode']>
&
Record<C extends { jwtSign: string}
? C['jwtSign']
: C extends {namespace: string}
? `${C['namespace']}JwtSign`
: never,
JWT['sign']>
&
Record<C extends { jwtVerify: string}
? C['jwtVerify']
: C extends {namespace: string}
? `${C['namespace']}JwtVerify`
: never,
JWT['verify']>

/**
* for declaration merging
* @example
Expand Down Expand Up @@ -102,7 +129,7 @@ declare namespace fastifyJwt {
}

export interface FastifyJWTOptions {
secret: Secret | {public: Secret; private?: Secret}
secret: Secret | { public: Secret; private?: Secret }
decode?: Partial<DecoderOptions>
sign?: Partial<SignOptions>
verify?: Partial<VerifyOptions> & {
Expand All @@ -124,7 +151,7 @@ declare namespace fastifyJwt {
}
trusted?: (
request: FastifyRequest,
decodedToken: {[k: string]: any}
decodedToken: { [k: string]: any }
) => boolean | Promise<boolean> | SignPayloadType | Promise<SignPayloadType>
formatUser?: (payload: SignPayloadType) => UserType
jwtDecode?: string
Expand Down
49 changes: 39 additions & 10 deletions test/types/jwt.test-d.ts → types/jwt.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import fastify from 'fastify';
import fastifyJwt, { FastifyJWTOptions } from '../../jwt'
import { expectAssignable } from 'tsd'
import fastifyJwt, { FastifyJWTOptions, FastifyJwtNamespace, JWT } from '..'
import { expectAssignable, expectType } from 'tsd'

const app = fastify();

Expand All @@ -10,19 +10,19 @@ const secretOptions = {
public: 'publicKey',
private: 'privateKey'
},
secretFnCallback: (_req, _token, cb) => { cb(null, 'supersecret') },
secretFnPromise: (_req, _token) => Promise.resolve('supersecret'),
secretFnAsync: async (_req, _token) => 'supersecret',
secretFnBufferCallback: (_req, _token, cb) => { cb(null, Buffer.from('some secret', 'base64')) },
secretFnBufferPromise: (_req, _token) => Promise.resolve(Buffer.from('some secret', 'base64')),
secretFnBufferAsync: async (_req, _token) => Buffer.from('some secret', 'base64'),
secretFnCallback: (_req: any, _token: any, cb: any) => { cb(null, 'supersecret') },
secretFnPromise: (_req: any, _token: any) => Promise.resolve('supersecret'),
secretFnAsync: async (_req: any, _token: any) => 'supersecret',
secretFnBufferCallback: (_req: any, _token: any, cb: any) => { cb(null, Buffer.from('some secret', 'base64')) },
secretFnBufferPromise: (_req: any, _token: any) => Promise.resolve(Buffer.from('some secret', 'base64')),
secretFnBufferAsync: async (_req: any, _token: any) => Buffer.from('some secret', 'base64'),
publicPrivateKeyFn: {
public: (_req, _rep, cb) => { cb(null, 'publicKey') },
public: (_req: any, _rep: any, cb: any) => { cb(null, 'publicKey') },
private: 'privateKey'
},
publicPrivateKeyFn2: {
public: 'publicKey',
private: (_req, _rep, cb) => { cb(null, 'privateKey') },
private: (_req: any, _rep: any, cb: any) => { cb(null, 'privateKey') },
}
}

Expand Down Expand Up @@ -137,3 +137,32 @@ app.post('/signup', async (req, reply) => {
// }
// }
// }

expectType<JWT['decode']>(({} as FastifyJwtNamespace<{namespace: 'security'}>).securityJwtDecode)
expectType<JWT['sign']>(({} as FastifyJwtNamespace<{namespace: 'security'}>).securityJwtSign)
expectType<JWT['verify']>(({} as FastifyJwtNamespace<{namespace: 'security'}>).securityJwtVerify)

declare module 'fastify' {
interface FastifyInstance extends FastifyJwtNamespace<{namespace: 'tsdTest'}> {
}
}

expectType<JWT['decode']>(app.tsdTestJwtDecode)
expectType<JWT['sign']>(app.tsdTestJwtSign)
expectType<JWT['verify']>(app.tsdTestJwtVerify)

expectType<JWT['decode']>(({} as FastifyJwtNamespace<{ namespace: 'security', jwtDecode: 'decode'}>).decode)
expectType<JWT['sign']>(({} as FastifyJwtNamespace<{ namespace: 'security', jwtDecode: 'decode'}>).securityJwtSign)
expectType<JWT['verify']>(({} as FastifyJwtNamespace<{ namespace: 'security', jwtDecode: 'decode'}>).securityJwtVerify)

expectType<JWT['decode']>(({} as FastifyJwtNamespace<{ namespace: 'security', jwtSign: 'decode'}>).securityJwtDecode)
expectType<JWT['sign']>(({} as FastifyJwtNamespace<{ namespace: 'security', jwtSign: 'sign'}>).sign)
expectType<JWT['verify']>(({} as FastifyJwtNamespace<{ namespace: 'security', jwtSign: 'decode'}>).securityJwtVerify)

expectType<JWT['decode']>(({} as FastifyJwtNamespace<{ namespace: 'security', jwtVerify: 'verify'}>).securityJwtDecode)
expectType<JWT['sign']>(({} as FastifyJwtNamespace<{ namespace: 'security', jwtVerify: 'verify'}>).securityJwtSign)
expectType<JWT['verify']>(({} as FastifyJwtNamespace<{ namespace: 'security', jwtVerify: 'verify'}>).verify)

expectType<JWT['decode']>(({} as FastifyJwtNamespace<{ jwtDecode: 'decode'}>).decode)
expectType<JWT['sign']>(({} as FastifyJwtNamespace<{ jwtSign: 'sign'}>).sign)
expectType<JWT['verify']>(({} as FastifyJwtNamespace<{ jwtVerify: 'verify'}>).verify)

0 comments on commit 5ba0403

Please sign in to comment.