@zapkey/express 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +85 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.cts +76 -0
- package/dist/index.d.ts +76 -0
- package/dist/index.js +1 -0
- package/package.json +52 -0
package/README.md
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# @zapkey/express
|
|
2
|
+
|
|
3
|
+
Express adapter for ZapKey.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @zapkey/core @zapkey/express express cookie-parser
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## What it exports
|
|
12
|
+
|
|
13
|
+
- `requireAuth`
|
|
14
|
+
- `requireGuard`
|
|
15
|
+
- `setAuthCookie`
|
|
16
|
+
- `clearAuthCookie`
|
|
17
|
+
- `handleLogin`
|
|
18
|
+
- `handleRefresh`
|
|
19
|
+
- `handleLogout`
|
|
20
|
+
- `getUser`
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
import cookieParser from 'cookie-parser';
|
|
26
|
+
import express from 'express';
|
|
27
|
+
import { initZapkey } from '@zapkey/core';
|
|
28
|
+
import { getUser, handleLogin, handleLogout, handleRefresh, requireAuth, requireGuard } from '@zapkey/express';
|
|
29
|
+
import { MemoryAuthorizationStore, MemoryTokenStore } from '@zapkey/stores-memory';
|
|
30
|
+
|
|
31
|
+
const authorization = new MemoryAuthorizationStore();
|
|
32
|
+
authorization.addRole('user_123', 'admin');
|
|
33
|
+
authorization.addRolePermission('admin', 'users:read');
|
|
34
|
+
|
|
35
|
+
const sdk = initZapkey({
|
|
36
|
+
mode: 'session',
|
|
37
|
+
accessTokenSecret: process.env.ACCESS_TOKEN_SECRET!,
|
|
38
|
+
stores: {
|
|
39
|
+
token: new MemoryTokenStore(),
|
|
40
|
+
authorization,
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const app = express();
|
|
45
|
+
app.use(express.json());
|
|
46
|
+
app.use(cookieParser());
|
|
47
|
+
|
|
48
|
+
app.post('/auth/login', async (req, res) => {
|
|
49
|
+
const user = await authenticateUser(req.body.email, req.body.password);
|
|
50
|
+
if (!user) {
|
|
51
|
+
return res.status(401).json({ error: 'Invalid credentials' });
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
await handleLogin(sdk, user.id, res, {
|
|
55
|
+
metadata: { role: user.role },
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
app.post('/auth/refresh', (req, res) => handleRefresh(sdk, req, res));
|
|
60
|
+
app.post('/auth/logout', (req, res) => handleLogout(sdk, req, res));
|
|
61
|
+
|
|
62
|
+
app.get('/me', requireAuth(sdk), (req, res) => {
|
|
63
|
+
res.json({ userId: getUser(req).userId });
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
app.get(
|
|
67
|
+
'/admin/users',
|
|
68
|
+
requireAuth(sdk),
|
|
69
|
+
requireGuard(sdk, { type: 'permission', permission: 'users:read' }),
|
|
70
|
+
(_req, res) => {
|
|
71
|
+
res.json({ ok: true });
|
|
72
|
+
},
|
|
73
|
+
);
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Notes
|
|
77
|
+
|
|
78
|
+
- Register `cookie-parser` before using the auth helpers.
|
|
79
|
+
- `requireAuth` checks the access-token cookie first and then falls back to the `Authorization` header.
|
|
80
|
+
- `handleLogout` clears the access cookie and revokes the refresh token with reason `'logout'` when refresh mode is enabled.
|
|
81
|
+
- Abuse protection is not automatic. Call `sdk.abuse.check(...)` from your routes when needed.
|
|
82
|
+
|
|
83
|
+
## Full documentation
|
|
84
|
+
|
|
85
|
+
See [`../../docs/SDK_USAGE_GUIDE.md`](../../docs/SDK_USAGE_GUIDE.md) for full configuration, enterprise profile, OTP, abuse, and store guidance.
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var f=Object.defineProperty;var T=Object.getOwnPropertyDescriptor;var m=Object.getOwnPropertyNames;var g=Object.prototype.hasOwnProperty;var d=(e,t)=>{for(var o in t)f(e,o,{get:t[o],enumerable:!0})},O=(e,t,o,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of m(t))!g.call(e,n)&&n!==o&&f(e,n,{get:()=>t[n],enumerable:!(s=T(t,n))||s.enumerable});return e};var x=e=>O(f({},"__esModule",{value:!0}),e);var I={};d(I,{clearAuthCookie:()=>h,getUser:()=>N,handleLogin:()=>C,handleLogout:()=>E,handleRefresh:()=>A,requireAuth:()=>y,requireGuard:()=>l,setAuthCookie:()=>u});module.exports=x(I);var a=require("@zapkey/core");function y(e){return async(t,o,s)=>{try{let n=e.cookie.getAccessTokenName(),i=t.cookies?.[n];if(!i){let c=t.headers.authorization;c?.startsWith("Bearer ")&&(i=c.substring(7))}if(!i){o.status(401).json({error:"Unauthorized",code:"NO_TOKEN"});return}let r=await e.token.verifyAccessToken(i);t.user=r,s()}catch(n){k(n,o)}}}function l(e,t){return async(o,s,n)=>{try{if(!e.authorization){s.status(500).json({error:"Authorization not configured",code:"AUTHORIZATION_NOT_CONFIGURED",hint:"Provide AuthorizationStore in SDK config to use requireGuard"});return}let i=o.user;if(!i){s.status(401).json({error:"Unauthorized",code:"NO_USER"});return}await e.authorization.guard.enforce(i.userId,t),n()}catch(i){k(i,s)}}}function u(e,t,o,s){let n={httpOnly:s.httpOnly,secure:s.secure,sameSite:s.sameSite,maxAge:s.maxAge*1e3,path:s.path,domain:s.domain};e.cookie(t,o,n)}function h(e,t,o){let s={httpOnly:o.httpOnly,secure:o.secure,sameSite:o.sameSite,maxAge:0,path:o.path,domain:o.domain};e.clearCookie(t,s)}async function C(e,t,o,s){let n=s?.withRefresh??e.hasRefreshTokens(),i=s?.metadata!==void 0?{userId:t,metadata:s.metadata}:{userId:t};if(n){let r=await e.token.issue(i),c=e.cookie.getAccessTokenCookieOptions(r.expiresIn),p=e.getConfig().token.refreshTokenExpiresIn,R=e.cookie.getRefreshTokenCookieOptions(p);u(o,e.cookie.getAccessTokenName(),r.accessToken,c),u(o,e.cookie.getRefreshTokenName(),r.refreshToken,R),o.json({success:!0,accessToken:r.accessToken,expiresIn:r.expiresIn,refreshEnabled:!0})}else{let r=await e.token.issueAccessToken(i),c=e.cookie.getAccessTokenCookieOptions(r.expiresIn);u(o,e.cookie.getAccessTokenName(),r.accessToken,c),o.json({success:!0,accessToken:r.accessToken,expiresIn:r.expiresIn,refreshEnabled:!1})}}async function A(e,t,o){try{if(!e.hasRefreshTokens()||!e.token.rotate){o.status(400).json({error:"Refresh tokens are not enabled",code:"REFRESH_DISABLED",hint:"Set refreshTokens: true in SDK config to enable token refresh"});return}let s=t.cookies?.[e.cookie.getRefreshTokenName()];if(!s){o.status(401).json({error:"No refresh token",code:"NO_REFRESH_TOKEN"});return}let n=await e.token.rotate(s),i=e.cookie.getAccessTokenCookieOptions(n.expiresIn),r=e.getConfig().token.refreshTokenExpiresIn,c=e.cookie.getRefreshTokenCookieOptions(r);u(o,e.cookie.getAccessTokenName(),n.accessToken,i),u(o,e.cookie.getRefreshTokenName(),n.refreshToken,c),o.json({success:!0,accessToken:n.accessToken,expiresIn:n.expiresIn})}catch(s){k(s,o)}}async function E(e,t,o){try{let s=e.cookie.getClearCookieOptions();if(h(o,e.cookie.getAccessTokenName(),s),e.hasRefreshTokens()&&e.token.revokeToken){let n=t.cookies?.[e.cookie.getRefreshTokenName()];n&&await e.token.revokeToken(n,"logout"),h(o,e.cookie.getRefreshTokenName(),s)}o.json({success:!0})}catch(s){k(s,o)}}function k(e,t){e instanceof a.RateLimitError?t.status(e.statusCode).json({error:e.message,code:e.code,retryAfter:e.retryAfter}):e instanceof a.TokenError?t.status(e.statusCode).json({error:e.message,code:e.code}):e instanceof a.OTPError?t.status(e.statusCode).json({error:e.message,code:e.code}):e instanceof a.AuthorizationError?t.status(e.statusCode).json({error:e.message,code:e.code}):e instanceof a.AuthError?t.status(e.statusCode).json({error:e.message,code:e.code}):t.status(500).json({error:"Internal server error",code:"INTERNAL_ERROR"})}function N(e){return e.user}0&&(module.exports={clearAuthCookie,getUser,handleLogin,handleLogout,handleRefresh,requireAuth,requireGuard,setAuthCookie});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { Response, Request, RequestHandler } from 'express';
|
|
2
|
+
import { CookieOptions, Zapkey, Guard } from '@zapkey/core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Express Adapter
|
|
6
|
+
*
|
|
7
|
+
* CRITICAL: This is a THIN adapter. NO business logic.
|
|
8
|
+
* Only request/response mapping.
|
|
9
|
+
*
|
|
10
|
+
* Supports both token modes:
|
|
11
|
+
* - Access-Only: Only access token in cookies, no refresh endpoint
|
|
12
|
+
* - Access + Refresh: Full token lifecycle with rotation
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Middleware to verify access token from cookie or Authorization header
|
|
17
|
+
*
|
|
18
|
+
* Works in BOTH modes (access-only and access+refresh)
|
|
19
|
+
*/
|
|
20
|
+
declare function requireAuth(sdk: Zapkey): RequestHandler;
|
|
21
|
+
/**
|
|
22
|
+
* Middleware to enforce authorization guards
|
|
23
|
+
*/
|
|
24
|
+
declare function requireGuard(sdk: Zapkey, guard: Guard): RequestHandler;
|
|
25
|
+
/**
|
|
26
|
+
* Cookie helper - set cookie with SDK options
|
|
27
|
+
*/
|
|
28
|
+
declare function setAuthCookie(res: Response, name: string, value: string, options: CookieOptions): void;
|
|
29
|
+
/**
|
|
30
|
+
* Cookie helper - clear auth cookie
|
|
31
|
+
*/
|
|
32
|
+
declare function clearAuthCookie(res: Response, name: string, options: CookieOptions): void;
|
|
33
|
+
/**
|
|
34
|
+
* Login handler helper
|
|
35
|
+
*
|
|
36
|
+
* Supports both modes:
|
|
37
|
+
* - Access-Only: Issues only access token, sets only access cookie
|
|
38
|
+
* - Access + Refresh: Issues token pair, sets both cookies
|
|
39
|
+
*
|
|
40
|
+
* Mode is determined by sdk.hasRefreshTokens()
|
|
41
|
+
*
|
|
42
|
+
* @param sdk - The Zapkey instance
|
|
43
|
+
* @param userId - User ID to issue tokens for
|
|
44
|
+
* @param res - Express response object
|
|
45
|
+
* @param options - Optional configuration
|
|
46
|
+
*/
|
|
47
|
+
declare function handleLogin(sdk: Zapkey, userId: string, res: Response, options?: {
|
|
48
|
+
metadata?: Record<string, unknown>;
|
|
49
|
+
/**
|
|
50
|
+
* Override refresh token behavior
|
|
51
|
+
* Default: sdk.hasRefreshTokens()
|
|
52
|
+
* Set to false to force access-only mode even if refresh is enabled
|
|
53
|
+
*/
|
|
54
|
+
withRefresh?: boolean;
|
|
55
|
+
}): Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* Refresh token handler
|
|
58
|
+
*
|
|
59
|
+
* NOTE: Only works when refreshTokens is enabled.
|
|
60
|
+
* Returns 400 error if called when refresh tokens are disabled.
|
|
61
|
+
*/
|
|
62
|
+
declare function handleRefresh(sdk: Zapkey, req: Request, res: Response): Promise<void>;
|
|
63
|
+
/**
|
|
64
|
+
* Logout handler
|
|
65
|
+
*
|
|
66
|
+
* Works in both modes:
|
|
67
|
+
* - Access-Only: Just clears access cookie
|
|
68
|
+
* - Access + Refresh: Revokes refresh token and clears both cookies
|
|
69
|
+
*/
|
|
70
|
+
declare function handleLogout(sdk: Zapkey, req: Request, res: Response): Promise<void>;
|
|
71
|
+
/**
|
|
72
|
+
* Get user from request (helper)
|
|
73
|
+
*/
|
|
74
|
+
declare function getUser(req: Request): any;
|
|
75
|
+
|
|
76
|
+
export { clearAuthCookie, getUser, handleLogin, handleLogout, handleRefresh, requireAuth, requireGuard, setAuthCookie };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { Response, Request, RequestHandler } from 'express';
|
|
2
|
+
import { CookieOptions, Zapkey, Guard } from '@zapkey/core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Express Adapter
|
|
6
|
+
*
|
|
7
|
+
* CRITICAL: This is a THIN adapter. NO business logic.
|
|
8
|
+
* Only request/response mapping.
|
|
9
|
+
*
|
|
10
|
+
* Supports both token modes:
|
|
11
|
+
* - Access-Only: Only access token in cookies, no refresh endpoint
|
|
12
|
+
* - Access + Refresh: Full token lifecycle with rotation
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Middleware to verify access token from cookie or Authorization header
|
|
17
|
+
*
|
|
18
|
+
* Works in BOTH modes (access-only and access+refresh)
|
|
19
|
+
*/
|
|
20
|
+
declare function requireAuth(sdk: Zapkey): RequestHandler;
|
|
21
|
+
/**
|
|
22
|
+
* Middleware to enforce authorization guards
|
|
23
|
+
*/
|
|
24
|
+
declare function requireGuard(sdk: Zapkey, guard: Guard): RequestHandler;
|
|
25
|
+
/**
|
|
26
|
+
* Cookie helper - set cookie with SDK options
|
|
27
|
+
*/
|
|
28
|
+
declare function setAuthCookie(res: Response, name: string, value: string, options: CookieOptions): void;
|
|
29
|
+
/**
|
|
30
|
+
* Cookie helper - clear auth cookie
|
|
31
|
+
*/
|
|
32
|
+
declare function clearAuthCookie(res: Response, name: string, options: CookieOptions): void;
|
|
33
|
+
/**
|
|
34
|
+
* Login handler helper
|
|
35
|
+
*
|
|
36
|
+
* Supports both modes:
|
|
37
|
+
* - Access-Only: Issues only access token, sets only access cookie
|
|
38
|
+
* - Access + Refresh: Issues token pair, sets both cookies
|
|
39
|
+
*
|
|
40
|
+
* Mode is determined by sdk.hasRefreshTokens()
|
|
41
|
+
*
|
|
42
|
+
* @param sdk - The Zapkey instance
|
|
43
|
+
* @param userId - User ID to issue tokens for
|
|
44
|
+
* @param res - Express response object
|
|
45
|
+
* @param options - Optional configuration
|
|
46
|
+
*/
|
|
47
|
+
declare function handleLogin(sdk: Zapkey, userId: string, res: Response, options?: {
|
|
48
|
+
metadata?: Record<string, unknown>;
|
|
49
|
+
/**
|
|
50
|
+
* Override refresh token behavior
|
|
51
|
+
* Default: sdk.hasRefreshTokens()
|
|
52
|
+
* Set to false to force access-only mode even if refresh is enabled
|
|
53
|
+
*/
|
|
54
|
+
withRefresh?: boolean;
|
|
55
|
+
}): Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* Refresh token handler
|
|
58
|
+
*
|
|
59
|
+
* NOTE: Only works when refreshTokens is enabled.
|
|
60
|
+
* Returns 400 error if called when refresh tokens are disabled.
|
|
61
|
+
*/
|
|
62
|
+
declare function handleRefresh(sdk: Zapkey, req: Request, res: Response): Promise<void>;
|
|
63
|
+
/**
|
|
64
|
+
* Logout handler
|
|
65
|
+
*
|
|
66
|
+
* Works in both modes:
|
|
67
|
+
* - Access-Only: Just clears access cookie
|
|
68
|
+
* - Access + Refresh: Revokes refresh token and clears both cookies
|
|
69
|
+
*/
|
|
70
|
+
declare function handleLogout(sdk: Zapkey, req: Request, res: Response): Promise<void>;
|
|
71
|
+
/**
|
|
72
|
+
* Get user from request (helper)
|
|
73
|
+
*/
|
|
74
|
+
declare function getUser(req: Request): any;
|
|
75
|
+
|
|
76
|
+
export { clearAuthCookie, getUser, handleLogin, handleLogout, handleRefresh, requireAuth, requireGuard, setAuthCookie };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{AuthError as p,TokenError as R,OTPError as T,AuthorizationError as m,RateLimitError as g}from"@zapkey/core";function O(e){return async(s,o,t)=>{try{let n=e.cookie.getAccessTokenName(),i=s.cookies?.[n];if(!i){let a=s.headers.authorization;a?.startsWith("Bearer ")&&(i=a.substring(7))}if(!i){o.status(401).json({error:"Unauthorized",code:"NO_TOKEN"});return}let r=await e.token.verifyAccessToken(i);s.user=r,t()}catch(n){u(n,o)}}}function x(e,s){return async(o,t,n)=>{try{if(!e.authorization){t.status(500).json({error:"Authorization not configured",code:"AUTHORIZATION_NOT_CONFIGURED",hint:"Provide AuthorizationStore in SDK config to use requireGuard"});return}let i=o.user;if(!i){t.status(401).json({error:"Unauthorized",code:"NO_USER"});return}await e.authorization.guard.enforce(i.userId,s),n()}catch(i){u(i,t)}}}function c(e,s,o,t){let n={httpOnly:t.httpOnly,secure:t.secure,sameSite:t.sameSite,maxAge:t.maxAge*1e3,path:t.path,domain:t.domain};e.cookie(s,o,n)}function k(e,s,o){let t={httpOnly:o.httpOnly,secure:o.secure,sameSite:o.sameSite,maxAge:0,path:o.path,domain:o.domain};e.clearCookie(s,t)}async function y(e,s,o,t){let n=t?.withRefresh??e.hasRefreshTokens(),i=t?.metadata!==void 0?{userId:s,metadata:t.metadata}:{userId:s};if(n){let r=await e.token.issue(i),a=e.cookie.getAccessTokenCookieOptions(r.expiresIn),f=e.getConfig().token.refreshTokenExpiresIn,h=e.cookie.getRefreshTokenCookieOptions(f);c(o,e.cookie.getAccessTokenName(),r.accessToken,a),c(o,e.cookie.getRefreshTokenName(),r.refreshToken,h),o.json({success:!0,accessToken:r.accessToken,expiresIn:r.expiresIn,refreshEnabled:!0})}else{let r=await e.token.issueAccessToken(i),a=e.cookie.getAccessTokenCookieOptions(r.expiresIn);c(o,e.cookie.getAccessTokenName(),r.accessToken,a),o.json({success:!0,accessToken:r.accessToken,expiresIn:r.expiresIn,refreshEnabled:!1})}}async function l(e,s,o){try{if(!e.hasRefreshTokens()||!e.token.rotate){o.status(400).json({error:"Refresh tokens are not enabled",code:"REFRESH_DISABLED",hint:"Set refreshTokens: true in SDK config to enable token refresh"});return}let t=s.cookies?.[e.cookie.getRefreshTokenName()];if(!t){o.status(401).json({error:"No refresh token",code:"NO_REFRESH_TOKEN"});return}let n=await e.token.rotate(t),i=e.cookie.getAccessTokenCookieOptions(n.expiresIn),r=e.getConfig().token.refreshTokenExpiresIn,a=e.cookie.getRefreshTokenCookieOptions(r);c(o,e.cookie.getAccessTokenName(),n.accessToken,i),c(o,e.cookie.getRefreshTokenName(),n.refreshToken,a),o.json({success:!0,accessToken:n.accessToken,expiresIn:n.expiresIn})}catch(t){u(t,o)}}async function C(e,s,o){try{let t=e.cookie.getClearCookieOptions();if(k(o,e.cookie.getAccessTokenName(),t),e.hasRefreshTokens()&&e.token.revokeToken){let n=s.cookies?.[e.cookie.getRefreshTokenName()];n&&await e.token.revokeToken(n,"logout"),k(o,e.cookie.getRefreshTokenName(),t)}o.json({success:!0})}catch(t){u(t,o)}}function u(e,s){e instanceof g?s.status(e.statusCode).json({error:e.message,code:e.code,retryAfter:e.retryAfter}):e instanceof R?s.status(e.statusCode).json({error:e.message,code:e.code}):e instanceof T?s.status(e.statusCode).json({error:e.message,code:e.code}):e instanceof m?s.status(e.statusCode).json({error:e.message,code:e.code}):e instanceof p?s.status(e.statusCode).json({error:e.message,code:e.code}):s.status(500).json({error:"Internal server error",code:"INTERNAL_ERROR"})}function A(e){return e.user}export{k as clearAuthCookie,A as getUser,y as handleLogin,C as handleLogout,l as handleRefresh,O as requireAuth,x as requireGuard,c as setAuthCookie};
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@zapkey/express",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Express adapter for ZapKey authentication SDK",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"require": "./dist/index.cjs"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist",
|
|
18
|
+
"README.md"
|
|
19
|
+
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "tsup",
|
|
22
|
+
"test": "vitest run",
|
|
23
|
+
"lint": "eslint src --ext .ts",
|
|
24
|
+
"typecheck": "tsc --noEmit",
|
|
25
|
+
"clean": "rimraf dist"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"zapkey",
|
|
29
|
+
"express",
|
|
30
|
+
"authentication",
|
|
31
|
+
"adapter"
|
|
32
|
+
],
|
|
33
|
+
"author": "",
|
|
34
|
+
"license": "MIT",
|
|
35
|
+
"peerDependencies": {
|
|
36
|
+
"@zapkey/core": "^1.0.0",
|
|
37
|
+
"express": "^4.18.0 || ^5.0.0"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@zapkey/core": "^1.0.0",
|
|
41
|
+
"@types/express": "^5.0.6",
|
|
42
|
+
"@types/node": "^20.11.5",
|
|
43
|
+
"express": "^5.0.0",
|
|
44
|
+
"rimraf": "^5.0.5",
|
|
45
|
+
"tsup": "^8.0.1",
|
|
46
|
+
"typescript": "^5.3.3",
|
|
47
|
+
"vitest": "^1.2.0"
|
|
48
|
+
},
|
|
49
|
+
"engines": {
|
|
50
|
+
"node": ">=18.0.0"
|
|
51
|
+
}
|
|
52
|
+
}
|