@passport-agent/middleware 0.0.1

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.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=middleware.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/middleware.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,128 @@
1
+ import { describe, it, expect, beforeEach, vi } from 'vitest';
2
+ import { PassportIssuer } from '@passport-agent/core';
3
+ import { expressPassport } from '../express.js';
4
+ import { fastifyPassport } from '../fastify.js';
5
+ import { nextjsPassport } from '../nextjs.js';
6
+ import { createMiddlewareHandler } from '../core.js';
7
+ describe('Framework Middleware', () => {
8
+ let issuer;
9
+ let passportHeader;
10
+ beforeEach(() => {
11
+ issuer = new PassportIssuer();
12
+ const signed = issuer.issue({
13
+ principal: 'user:alice',
14
+ agent: 'agent:bot',
15
+ permissions: ['api:*'],
16
+ });
17
+ passportHeader = JSON.stringify(signed);
18
+ });
19
+ describe('core handler', () => {
20
+ it('allows valid passport with matching permission', () => {
21
+ const handle = createMiddlewareHandler({ issuer });
22
+ const result = handle('GET', '/api/data', { 'x-agent-passport': passportHeader });
23
+ expect(result.allowed).toBe(true);
24
+ });
25
+ it('returns 401 without passport header', () => {
26
+ const handle = createMiddlewareHandler({ issuer });
27
+ const result = handle('GET', '/api/data', {});
28
+ expect(result.allowed).toBe(false);
29
+ if (!result.allowed)
30
+ expect(result.status).toBe(401);
31
+ });
32
+ it('returns 403 for denied action', () => {
33
+ const denied = issuer.issue({
34
+ principal: 'user:alice',
35
+ agent: 'agent:bot',
36
+ permissions: ['other:action'],
37
+ });
38
+ const handle = createMiddlewareHandler({ issuer });
39
+ const result = handle('GET', '/api/data', {
40
+ 'x-agent-passport': JSON.stringify(denied),
41
+ });
42
+ expect(result.allowed).toBe(false);
43
+ if (!result.allowed)
44
+ expect(result.status).toBe(403);
45
+ });
46
+ it('uses custom header name', () => {
47
+ const handle = createMiddlewareHandler({ issuer, headerName: 'authorization' });
48
+ const result = handle('GET', '/api', { 'authorization': passportHeader });
49
+ expect(result.allowed).toBe(true);
50
+ });
51
+ it('calls onDenied callback', () => {
52
+ const onDenied = vi.fn();
53
+ const handle = createMiddlewareHandler({ issuer, onDenied });
54
+ handle('DELETE', '/admin/users', { 'x-agent-passport': passportHeader });
55
+ expect(onDenied).toHaveBeenCalled();
56
+ });
57
+ it('calls onAllowed callback', () => {
58
+ const onAllowed = vi.fn();
59
+ const handle = createMiddlewareHandler({ issuer, onAllowed });
60
+ handle('GET', '/api/data', { 'x-agent-passport': passportHeader });
61
+ expect(onAllowed).toHaveBeenCalled();
62
+ });
63
+ });
64
+ describe('Express middleware', () => {
65
+ it('calls next() on allowed request', () => {
66
+ const mw = expressPassport({ issuer });
67
+ const req = { method: 'GET', path: '/api/data', headers: { 'x-agent-passport': passportHeader } };
68
+ const res = { status: vi.fn().mockReturnThis(), json: vi.fn() };
69
+ const next = vi.fn();
70
+ mw(req, res, next);
71
+ expect(next).toHaveBeenCalled();
72
+ expect(req.passportContext).toBeDefined();
73
+ });
74
+ it('returns 401 without passport', () => {
75
+ const mw = expressPassport({ issuer });
76
+ const req = { method: 'GET', path: '/api', headers: {} };
77
+ const res = { status: vi.fn().mockReturnThis(), json: vi.fn() };
78
+ const next = vi.fn();
79
+ mw(req, res, next);
80
+ expect(next).not.toHaveBeenCalled();
81
+ expect(res.status).toHaveBeenCalledWith(401);
82
+ });
83
+ });
84
+ describe('Fastify hook', () => {
85
+ it('sets passport context on allowed request', async () => {
86
+ const hook = fastifyPassport({ issuer });
87
+ const req = { method: 'GET', url: '/api/data?q=1', headers: { 'x-agent-passport': passportHeader } };
88
+ const reply = { status: vi.fn().mockReturnThis(), send: vi.fn() };
89
+ await hook(req, reply);
90
+ expect(reply.send).not.toHaveBeenCalled();
91
+ expect(req.passportContext).toBeDefined();
92
+ });
93
+ it('sends 401 without passport', async () => {
94
+ const hook = fastifyPassport({ issuer });
95
+ const req = { method: 'GET', url: '/api', headers: {} };
96
+ const reply = { status: vi.fn().mockReturnThis(), send: vi.fn() };
97
+ await hook(req, reply);
98
+ expect(reply.status).toHaveBeenCalledWith(401);
99
+ expect(reply.send).toHaveBeenCalled();
100
+ });
101
+ });
102
+ describe('Next.js middleware', () => {
103
+ it('returns null on allowed request', () => {
104
+ const MockNextResponse = { json: vi.fn().mockReturnValue('response') };
105
+ const mw = nextjsPassport({ issuer }, MockNextResponse);
106
+ const req = {
107
+ method: 'GET',
108
+ nextUrl: { pathname: '/api/data' },
109
+ headers: { get: (name) => name === 'x-agent-passport' ? passportHeader : null },
110
+ };
111
+ const result = mw(req);
112
+ expect(result).toBeNull();
113
+ });
114
+ it('returns JSON response on denied request', () => {
115
+ const MockNextResponse = { json: vi.fn().mockReturnValue('response') };
116
+ const mw = nextjsPassport({ issuer }, MockNextResponse);
117
+ const req = {
118
+ method: 'GET',
119
+ nextUrl: { pathname: '/api/data' },
120
+ headers: { get: () => null },
121
+ };
122
+ const result = mw(req);
123
+ expect(result).toBe('response');
124
+ expect(MockNextResponse.json).toHaveBeenCalledWith(expect.objectContaining({ error: expect.any(String) }), expect.objectContaining({ status: 401 }));
125
+ });
126
+ });
127
+ });
128
+ //# sourceMappingURL=middleware.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.test.js","sourceRoot":"","sources":["../../src/__tests__/middleware.test.ts"],"names":[],"mappings":"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"}
package/dist/core.d.ts ADDED
@@ -0,0 +1,23 @@
1
+ import { PassportIssuer, type SignedPassport, type AuthorizeResult } from '@passport-agent/core';
2
+ export interface MiddlewareConfig {
3
+ issuer: PassportIssuer;
4
+ headerName?: string;
5
+ extractAction?: (method: string, path: string) => string;
6
+ onDenied?: (result: AuthorizeResult, action: string) => void;
7
+ onAllowed?: (result: AuthorizeResult, action: string) => void;
8
+ }
9
+ export interface PassportContext {
10
+ passport: SignedPassport;
11
+ result: AuthorizeResult;
12
+ }
13
+ export declare function parsePassportHeader(header: string | undefined | null, issuer: PassportIssuer): SignedPassport | null;
14
+ export declare function defaultActionExtractor(method: string, path: string): string;
15
+ export declare function createMiddlewareHandler(config: MiddlewareConfig): (method: string, path: string, headers: Record<string, string | string[] | undefined>) => {
16
+ allowed: true;
17
+ context: PassportContext;
18
+ } | {
19
+ allowed: false;
20
+ status: number;
21
+ body: object;
22
+ };
23
+ //# sourceMappingURL=core.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,KAAK,cAAc,EAAE,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEjG,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,cAAc,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACzD,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7D,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/D;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,cAAc,CAAC;IACzB,MAAM,EAAE,eAAe,CAAC;CACzB;AAID,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,EACjC,MAAM,EAAE,cAAc,GACrB,cAAc,GAAG,IAAI,CAavB;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAI3E;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,gBAAgB,IAK5D,QAAQ,MAAM,EACd,MAAM,MAAM,EACZ,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,KACrD;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,eAAe,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAoClG"}
package/dist/core.js ADDED
@@ -0,0 +1,59 @@
1
+ const DEFAULT_HEADER = 'x-agent-passport';
2
+ export function parsePassportHeader(header, issuer) {
3
+ if (!header)
4
+ return null;
5
+ try {
6
+ const parsed = JSON.parse(header);
7
+ if (parsed.payload && parsed.signature && parsed.publicKey) {
8
+ if (issuer.verifySignature(parsed)) {
9
+ return parsed;
10
+ }
11
+ }
12
+ }
13
+ catch {
14
+ // not valid JSON passport
15
+ }
16
+ return null;
17
+ }
18
+ export function defaultActionExtractor(method, path) {
19
+ const verb = method.toLowerCase();
20
+ const resource = path.split('/').filter(Boolean).slice(0, 2).join(':') || 'root';
21
+ return `${resource}:${verb}`;
22
+ }
23
+ export function createMiddlewareHandler(config) {
24
+ const headerName = config.headerName ?? DEFAULT_HEADER;
25
+ const extractAction = config.extractAction ?? defaultActionExtractor;
26
+ return function handle(method, path, headers) {
27
+ const raw = headers[headerName];
28
+ const headerValue = Array.isArray(raw) ? raw[0] : raw;
29
+ const passport = parsePassportHeader(headerValue, config.issuer);
30
+ if (!passport) {
31
+ return {
32
+ allowed: false,
33
+ status: 401,
34
+ body: {
35
+ error: 'Missing or invalid agent passport',
36
+ hint: `Provide a signed passport in the "${headerName}" header`,
37
+ },
38
+ };
39
+ }
40
+ const action = extractAction(method, path);
41
+ const result = config.issuer.authorize(passport, action);
42
+ if (!result.allowed) {
43
+ config.onDenied?.(result, action);
44
+ return {
45
+ allowed: false,
46
+ status: 403,
47
+ body: {
48
+ error: 'Agent passport denied',
49
+ action,
50
+ reason: result.reason,
51
+ passportId: result.passportId,
52
+ },
53
+ };
54
+ }
55
+ config.onAllowed?.(result, action);
56
+ return { allowed: true, context: { passport, result } };
57
+ };
58
+ }
59
+ //# sourceMappingURL=core.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"core.js","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAeA,MAAM,cAAc,GAAG,kBAAkB,CAAC;AAE1C,MAAM,UAAU,mBAAmB,CACjC,MAAiC,EACjC,MAAsB;IAEtB,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAClC,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;YAC3D,IAAI,MAAM,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC;gBACnC,OAAO,MAAM,CAAC;YAChB,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,0BAA0B;IAC5B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,MAAc,EAAE,IAAY;IACjE,MAAM,IAAI,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;IAClC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC;IACjF,OAAO,GAAG,QAAQ,IAAI,IAAI,EAAE,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,MAAwB;IAC9D,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,IAAI,cAAc,CAAC;IACvD,MAAM,aAAa,GAAG,MAAM,CAAC,aAAa,IAAI,sBAAsB,CAAC;IAErE,OAAO,SAAS,MAAM,CACpB,MAAc,EACd,IAAY,EACZ,OAAsD;QAEtD,MAAM,GAAG,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;QAChC,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;QACtD,MAAM,QAAQ,GAAG,mBAAmB,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QAEjE,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,GAAG;gBACX,IAAI,EAAE;oBACJ,KAAK,EAAE,mCAAmC;oBAC1C,IAAI,EAAE,qCAAqC,UAAU,UAAU;iBAChE;aACF,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAG,aAAa,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC3C,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAEzD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YAClC,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,GAAG;gBACX,IAAI,EAAE;oBACJ,KAAK,EAAE,uBAAuB;oBAC9B,MAAM;oBACN,MAAM,EAAE,MAAM,CAAC,MAAM;oBACrB,UAAU,EAAE,MAAM,CAAC,UAAU;iBAC9B;aACF,CAAC;QACJ,CAAC;QAED,MAAM,CAAC,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACnC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,CAAC;IAC1D,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { type MiddlewareConfig, type PassportContext } from './core.js';
2
+ export interface ExpressRequest {
3
+ method: string;
4
+ path: string;
5
+ headers: Record<string, string | string[] | undefined>;
6
+ passportContext?: PassportContext;
7
+ }
8
+ export interface ExpressResponse {
9
+ status(code: number): ExpressResponse;
10
+ json(body: unknown): void;
11
+ }
12
+ export type ExpressNextFunction = (err?: unknown) => void;
13
+ export declare function expressPassport(config: MiddlewareConfig): (req: ExpressRequest, res: ExpressResponse, next: ExpressNextFunction) => void;
14
+ //# sourceMappingURL=express.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"express.d.ts","sourceRoot":"","sources":["../src/express.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2B,KAAK,gBAAgB,EAAE,KAAK,eAAe,EAAE,MAAM,WAAW,CAAC;AAEjG,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;IACvD,eAAe,CAAC,EAAE,eAAe,CAAC;CACnC;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAAC;IACtC,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,MAAM,mBAAmB,GAAG,CAAC,GAAG,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;AAE1D,wBAAgB,eAAe,CAAC,MAAM,EAAE,gBAAgB,IAIpD,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,MAAM,mBAAmB,UAY5B"}
@@ -0,0 +1,14 @@
1
+ import { createMiddlewareHandler } from './core.js';
2
+ export function expressPassport(config) {
3
+ const handle = createMiddlewareHandler(config);
4
+ return function passportMiddleware(req, res, next) {
5
+ const result = handle(req.method, req.path, req.headers);
6
+ if (!result.allowed) {
7
+ res.status(result.status).json(result.body);
8
+ return;
9
+ }
10
+ req.passportContext = result.context;
11
+ next();
12
+ };
13
+ }
14
+ //# sourceMappingURL=express.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"express.js","sourceRoot":"","sources":["../src/express.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAA+C,MAAM,WAAW,CAAC;AAgBjG,MAAM,UAAU,eAAe,CAAC,MAAwB;IACtD,MAAM,MAAM,GAAG,uBAAuB,CAAC,MAAM,CAAC,CAAC;IAE/C,OAAO,SAAS,kBAAkB,CAChC,GAAmB,EACnB,GAAoB,EACpB,IAAyB;QAEzB,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;QAEzD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC5C,OAAO;QACT,CAAC;QAED,GAAG,CAAC,eAAe,GAAG,MAAM,CAAC,OAAO,CAAC;QACrC,IAAI,EAAE,CAAC;IACT,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { type MiddlewareConfig, type PassportContext } from './core.js';
2
+ export interface FastifyRequest {
3
+ method: string;
4
+ url: string;
5
+ headers: Record<string, string | string[] | undefined>;
6
+ passportContext?: PassportContext;
7
+ }
8
+ export interface FastifyReply {
9
+ status(code: number): FastifyReply;
10
+ send(body: unknown): void;
11
+ }
12
+ export declare function fastifyPassport(config: MiddlewareConfig): (req: FastifyRequest, reply: FastifyReply) => Promise<void>;
13
+ //# sourceMappingURL=fastify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fastify.d.ts","sourceRoot":"","sources":["../src/fastify.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2B,KAAK,gBAAgB,EAAE,KAAK,eAAe,EAAE,MAAM,WAAW,CAAC;AAEjG,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;IACvD,eAAe,CAAC,EAAE,eAAe,CAAC;CACnC;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,CAAC;IACnC,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;CAC3B;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,gBAAgB,IAGnB,KAAK,cAAc,EAAE,OAAO,YAAY,mBAW5E"}
@@ -0,0 +1,14 @@
1
+ import { createMiddlewareHandler } from './core.js';
2
+ export function fastifyPassport(config) {
3
+ const handle = createMiddlewareHandler(config);
4
+ return async function passportHook(req, reply) {
5
+ const path = req.url.split('?')[0] ?? req.url;
6
+ const result = handle(req.method, path, req.headers);
7
+ if (!result.allowed) {
8
+ reply.status(result.status).send(result.body);
9
+ return;
10
+ }
11
+ req.passportContext = result.context;
12
+ };
13
+ }
14
+ //# sourceMappingURL=fastify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fastify.js","sourceRoot":"","sources":["../src/fastify.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAA+C,MAAM,WAAW,CAAC;AAcjG,MAAM,UAAU,eAAe,CAAC,MAAwB;IACtD,MAAM,MAAM,GAAG,uBAAuB,CAAC,MAAM,CAAC,CAAC;IAE/C,OAAO,KAAK,UAAU,YAAY,CAAC,GAAmB,EAAE,KAAmB;QACzE,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC;QAC9C,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;QAErD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC9C,OAAO;QACT,CAAC;QAED,GAAG,CAAC,eAAe,GAAG,MAAM,CAAC,OAAO,CAAC;IACvC,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,5 @@
1
+ export { createMiddlewareHandler, parsePassportHeader, defaultActionExtractor, type MiddlewareConfig, type PassportContext, } from './core.js';
2
+ export { expressPassport } from './express.js';
3
+ export { fastifyPassport } from './fastify.js';
4
+ export { nextjsPassport } from './nextjs.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EACvB,mBAAmB,EACnB,sBAAsB,EACtB,KAAK,gBAAgB,EACrB,KAAK,eAAe,GACrB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export { createMiddlewareHandler, parsePassportHeader, defaultActionExtractor, } from './core.js';
2
+ export { expressPassport } from './express.js';
3
+ export { fastifyPassport } from './fastify.js';
4
+ export { nextjsPassport } from './nextjs.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EACvB,mBAAmB,EACnB,sBAAsB,GAGvB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,21 @@
1
+ import { type MiddlewareConfig } from './core.js';
2
+ export interface NextRequest {
3
+ method: string;
4
+ nextUrl: {
5
+ pathname: string;
6
+ };
7
+ headers: {
8
+ get(name: string): string | null;
9
+ };
10
+ }
11
+ export interface NextResponse {
12
+ json(body: unknown, init?: {
13
+ status?: number;
14
+ }): NextResponse;
15
+ }
16
+ export declare function nextjsPassport(config: MiddlewareConfig, NextResponseClass: {
17
+ json(body: unknown, init?: {
18
+ status?: number;
19
+ }): unknown;
20
+ }): (req: NextRequest) => unknown;
21
+ //# sourceMappingURL=nextjs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nextjs.d.ts","sourceRoot":"","sources":["../src/nextjs.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2B,KAAK,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE3E,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9B,OAAO,EAAE;QAAE,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;CAC/C;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,YAAY,CAAC;CAC/D;AAED,wBAAgB,cAAc,CAC5B,MAAM,EAAE,gBAAgB,EACxB,iBAAiB,EAAE;IAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAA;CAAE,IAK5C,KAAK,WAAW,aAiBpD"}
package/dist/nextjs.js ADDED
@@ -0,0 +1,17 @@
1
+ import { createMiddlewareHandler } from './core.js';
2
+ export function nextjsPassport(config, NextResponseClass) {
3
+ const handle = createMiddlewareHandler(config);
4
+ const headerName = config.headerName ?? 'x-agent-passport';
5
+ return function passportMiddleware(req) {
6
+ const headers = {};
7
+ const val = req.headers.get(headerName);
8
+ if (val)
9
+ headers[headerName] = val;
10
+ const result = handle(req.method, req.nextUrl.pathname, headers);
11
+ if (!result.allowed) {
12
+ return NextResponseClass.json(result.body, { status: result.status });
13
+ }
14
+ return null;
15
+ };
16
+ }
17
+ //# sourceMappingURL=nextjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nextjs.js","sourceRoot":"","sources":["../src/nextjs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAyB,MAAM,WAAW,CAAC;AAY3E,MAAM,UAAU,cAAc,CAC5B,MAAwB,EACxB,iBAA+E;IAE/E,MAAM,MAAM,GAAG,uBAAuB,CAAC,MAAM,CAAC,CAAC;IAC/C,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,IAAI,kBAAkB,CAAC;IAE3D,OAAO,SAAS,kBAAkB,CAAC,GAAgB;QACjD,MAAM,OAAO,GAAuC,EAAE,CAAC;QACvD,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACxC,IAAI,GAAG;YAAE,OAAO,CAAC,UAAU,CAAC,GAAG,GAAG,CAAC;QAEnC,MAAM,MAAM,GAAG,MAAM,CACnB,GAAG,CAAC,MAAM,EACV,GAAG,CAAC,OAAO,CAAC,QAAQ,EACpB,OAAO,CACR,CAAC;QAEF,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QACxE,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;AACJ,CAAC"}
package/package.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "@passport-agent/middleware",
3
+ "version": "0.0.1",
4
+ "description": "Express, Fastify, and Next.js middleware for passport-agent",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "scripts": {
9
+ "build": "tsc",
10
+ "test": "vitest run",
11
+ "lint": "tsc --noEmit"
12
+ },
13
+ "files": ["dist"],
14
+ "license": "MIT",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "https://github.com/priyansh-x/passport-agent",
18
+ "directory": "packages/middleware"
19
+ },
20
+ "dependencies": {
21
+ "@passport-agent/core": "workspace:*"
22
+ },
23
+ "devDependencies": {
24
+ "vitest": "^3.0.0"
25
+ }
26
+ }